From 2aba76f014a7b56ab4fe75845c5fd57b5590acc2 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 20 May 2011 10:26:06 -0400 Subject: audio: tlv320aic26: fix PLL register configuration The current PLL configuration code for the tlc320aic26 codec appears to assume a hardcoded system clock of 12 MHz. Use the clock value provided by the DAI_OPS API for the calculation. Tested using a MityDSP-L138 platform providing a 24.576 MHz clock. Signed-off-by: Michael Williamson Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/tlv320aic26.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index e2a7608d3944..7859bdcc93db 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -161,10 +161,18 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; } - /* Configure PLL */ + /** + * Configure PLL + * fsref = (mclk * PLLM) / 2048 + * where PLLM = J.DDDD (DDDD register ranges from 0 to 9999, decimal) + */ pval = 1; - jval = (fsref == 44100) ? 7 : 8; - dval = (fsref == 44100) ? 5264 : 1920; + /* compute J portion of multiplier */ + jval = fsref / (aic26->mclk / 2048); + /* compute fractional DDDD component of multiplier */ + dval = fsref - (jval * (aic26->mclk / 2048)); + dval = (10000 * dval) / (aic26->mclk / 2048); + dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval); qval = 0; reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); -- cgit v1.2.3 From 508b76864c18f34f8d6ba08d192f5817f8dc8ead Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 20 May 2011 16:52:37 +0300 Subject: ASoC: tlv320aic3x: Don't sync first two registers from register cache There is no need to sync first two registers from cache to hw after a reset. First one is used to select page for register access and this driver is normally accessing page 0 only. Second one does a software reset which is obviously unneeded after hardware or previous software reset command. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/tlv320aic3x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index c3d96fc8c267..9047bb173c6b 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1114,7 +1114,7 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) /* Sync reg_cache with the hardware */ codec->cache_only = 0; - for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++) + for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++) snd_soc_write(codec, i, cache[i]); if (aic3x->model == AIC3X_MODEL_3007) aic3x_init_3007(codec); -- cgit v1.2.3 From 9fb352b18b11124ed1ddebc0d74ebbd7ba8defd7 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 20 May 2011 16:52:38 +0300 Subject: ASoC: tlv320aic3x: Do soft reset to codec when going to bias off state TLV320AIC33, TLV320AIC34 and I believe others too in this family have some hw bugs that cause that analogue and digital VDD supplies remain leaking up to a few mA of current after certain use cases even the hw blocks inside codec are driven to off. Highest leakages occur after using the bypass paths inside codec but it is possible to get smaller leakages just by toggling mute switches in unused audio paths (i.e. no DAPM changes) while codec is on due another active audio path. While some cases are able to workaroud by making sure that e.g. output mixer switches are muted before powering down the output stage this doesn't help all the cases. Therefore use the software reset command to clear possible leakage currents since that works in every cases and affects only this codec instance. Only drawback is that now cache sync is required everytime when codec bias comes out from bias off state, not only when supply regulators were off. Signed-off-by: Jarkko Nikula Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- sound/soc/codecs/tlv320aic3x.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 9047bb173c6b..789453d44ec5 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1120,6 +1120,13 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) aic3x_init_3007(codec); codec->cache_sync = 0; } else { + /* + * Do soft reset to this codec instance in order to clear + * possible VDD leakage currents in case the supply regulators + * remain on + */ + snd_soc_write(codec, AIC3X_RESET, SOFT_RESET); + codec->cache_sync = 1; aic3x->power = 0; /* HW writes are needless when bias is off */ codec->cache_only = 1; -- cgit v1.2.3 From 7f77897ef2b6a5ee4eb8bc24fe8b1f3eab254328 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 24 May 2011 11:43:18 +0200 Subject: HID: hiddev: fix potential use-after-free Commit 6cb4b040795 ("HID: hiddev: fix race between hiddev_disconnect and hiddev_release") made it possible to access hiddev (for unlocking the existance mutex) once hiddev has been kfreed. Change the order so that this can not happen (always unlock the mutex first, it is needed only to protect access to ->exist and ->open). Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index ff3c644888b1..4985f485932f 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -923,10 +923,11 @@ void hiddev_disconnect(struct hid_device *hid) usb_deregister_dev(usbhid->intf, &hiddev_class); if (hiddev->open) { + mutex_unlock(&hiddev->existancelock); usbhid_close(hiddev->hid); wake_up_interruptible(&hiddev->wait); } else { + mutex_unlock(&hiddev->existancelock); kfree(hiddev); } - mutex_unlock(&hiddev->existancelock); } -- cgit v1.2.3 From e23be0a27dcc9297ff0495360d89bc5b0bf12383 Mon Sep 17 00:00:00 2001 From: Jimmy Hon Date: Fri, 20 May 2011 17:59:19 -0400 Subject: HID: add quirk for HyperPen 10000U Add 5543:0064 UC-Logic Technology Corp. Aiptek HyperPen 10000U to quirks with HID_QUIRK_MULTI_INPUT. Originally the device is reporting the x,y coordinates on Z and RX. By adding this quirk, there will be two kernel devices. The first one is muted and the second device will report coordinates on X and Y. Signed-off-by: Jimmy Hon Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0b374a6d6db0..2bbaad70d76d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -622,6 +622,7 @@ #define USB_VENDOR_ID_UCLOGIC 0x5543 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 +#define USB_DEVICE_ID_UCLOGIC_TABLET_TWA60 0x0064 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 0e30b140edca..621959d5cc42 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -74,6 +74,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, -- cgit v1.2.3 From 8c127f0717b438e6abc3d92d4ae248c4224b9dcb Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 25 May 2011 09:24:32 -0700 Subject: Input: properly assign return value of clamp() macro. [dtor@mail.ru: added mousedev changes] Signed-off-by: Hans Petter Selasky Cc: stable@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 2 +- drivers/input/mousedev.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index 75e11c7b70fd..da38d97a51b1 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1756,7 +1756,7 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) { mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum - dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1, - clamp(mt_slots, 2, 32); + mt_slots = clamp(mt_slots, 2, 32); } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { mt_slots = 2; } else { diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 257e033986e4..0110b5a3a167 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -187,7 +187,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, if (size == 0) size = xres ? : 1; - clamp(value, min, max); + value = clamp(value, min, max); mousedev->packet.x = ((value - min) * xres) / size; mousedev->packet.abs_event = 1; @@ -201,7 +201,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, if (size == 0) size = yres ? : 1; - clamp(value, min, max); + value = clamp(value, min, max); mousedev->packet.y = yres - ((value - min) * yres) / size; mousedev->packet.abs_event = 1; -- cgit v1.2.3 From 5c699d7d3f94ee1dd934edea889b32f8279a4e65 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 26 May 2011 11:49:16 +0300 Subject: HID: hiddev: fix use after free in hiddev_release There are a couple use after free bugs here. Signed-off-by: Dan Carpenter [jkosina@suse.cz: removed already fixed hunk] Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4985f485932f..7c1188b53c3e 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -248,12 +248,15 @@ static int hiddev_release(struct inode * inode, struct file * file) usbhid_close(list->hiddev->hid); usbhid_put_power(list->hiddev->hid); } else { + mutex_unlock(&list->hiddev->existancelock); kfree(list->hiddev); + kfree(list); + return 0; } } - kfree(list); mutex_unlock(&list->hiddev->existancelock); + kfree(list); return 0; } -- cgit v1.2.3 From 0f7e4c33eb2c40b1e9cc24d2eab6de5921bc619c Mon Sep 17 00:00:00 2001 From: Kohei Kaigai Date: Thu, 26 May 2011 14:59:25 -0400 Subject: selinux: fix case of names with whitespace/multibytes on /selinux/create I submit the patch again, according to patch submission convension. This patch enables to accept percent-encoded object names as forth argument of /selinux/create interface to avoid possible bugs when we give an object name including whitespace or multibutes. E.g) if and when a userspace object manager tries to create a new object named as "resolve.conf but fake", it shall give this name as the forth argument of the /selinux/create. But sscanf() logic in kernel space fetches only the part earlier than the first whitespace. In this case, selinux may unexpectedly answer a default security context configured to "resolve.conf", but it is bug. Although I could not test this patch on named TYPE_TRANSITION rules actually, But debug printk() message seems to me the logic works correctly. I assume the libselinux provides an interface to apply this logic transparently, so nothing shall not be changed from the viewpoint of application. Signed-off-by: KaiGai Kohei Signed-off-by: Eric Paris --- security/selinux/selinuxfs.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index fde4e9d64bfd..19489042fdf7 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -29,6 +29,7 @@ #include #include #include +#include /* selinuxfs pseudo filesystem for exporting the security policy API. Based on the proc code and the fs/nfsd/nfsctl.c code. */ @@ -751,6 +752,14 @@ out: return length; } +static inline int hexcode_to_int(int code) { + if (code == '\0' || !isxdigit(code)) + return -1; + if (isdigit(code)) + return code - '0'; + return tolower(code) - 'a' + 10; +} + static ssize_t sel_write_create(struct file *file, char *buf, size_t size) { char *scon = NULL, *tcon = NULL; @@ -785,8 +794,34 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf); if (nargs < 3 || nargs > 4) goto out; - if (nargs == 4) + if (nargs == 4) { + /* + * If and when the name of new object to be queried contains + * either whitespace or multibyte characters, they shall be + * encoded based on the percentage-encoding rule. + * If not encoded, the sscanf logic picks up only left-half + * of the supplied name; splitted by a whitespace unexpectedly. + */ + char *r, *w; + int c1, c2; + + r = w = namebuf; + do { + c1 = *r++; + if (c1 == '+') + c1 = ' '; + else if (c1 == '%') { + if ((c1 = hexcode_to_int(*r++)) < 0) + goto out; + if ((c2 = hexcode_to_int(*r++)) < 0) + goto out; + c1 = (c1 << 4) | c2; + } + *w++ = c1; + } while (c1 != '\0'); + objname = namebuf; + } length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length) -- cgit v1.2.3 From 4a8fcc2cc34b7546584bf9ebd8f0caf433e4736e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 19 May 2011 20:19:09 -0700 Subject: [SCSI] target: Fix multi task->task_sg[] chaining logic bug This patch fixes a bug in transport_do_task_sg_chain() used by HW target mode modules with sg_chain() to provide a single sg_next() walkable memory layout for use with pci_map_sg() and friends. This patch addresses an issue with mapping multiple small block max_sector tasks across multiple struct se_task->task_sg[] mappings for HW target mode operation. This was causing OOPs with (cmd->t_task->t_tasks_no > 1) I/O traffic for HW target drivers using transport_do_task_sg_chain(), and has been tested so far with tcm_fc(openfcoe), tcm_qla2xxx, and ib_srpt fabrics with t_tasks_no > 1 IBLOCK backends using a smaller max_sectors to trigger the original issue. Signed-off-by: Nicholas Bellinger Acked-by: Kiran Patil Cc: stable@kernel.org Signed-off-by: James Bottomley --- drivers/target/target_core_transport.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 9583b23c9c84..fefe10a2aa94 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -4776,18 +4776,20 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) sg_end_cur->page_link &= ~0x02; sg_chain(sg_head, task_sg_num, sg_head_cur); - sg_count += (task->task_sg_num + 1); - } else sg_count += task->task_sg_num; + task_sg_num = (task->task_sg_num + 1); + } else { + sg_chain(sg_head, task_sg_num, sg_head_cur); + sg_count += task->task_sg_num; + task_sg_num = task->task_sg_num; + } sg_head = sg_head_cur; sg_link = sg_link_cur; - task_sg_num = task->task_sg_num; continue; } sg_head = sg_first = &task->task_sg[0]; sg_link = &task->task_sg[task->task_sg_num]; - task_sg_num = task->task_sg_num; /* * Check for single task.. */ @@ -4798,9 +4800,12 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) */ sg_end = &task->task_sg[task->task_sg_num - 1]; sg_end->page_link &= ~0x02; - sg_count += (task->task_sg_num + 1); - } else sg_count += task->task_sg_num; + task_sg_num = (task->task_sg_num + 1); + } else { + sg_count += task->task_sg_num; + task_sg_num = task->task_sg_num; + } } /* * Setup the starting pointer and total t_tasks_sg_linked_no including @@ -4809,21 +4814,20 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) T_TASK(cmd)->t_tasks_sg_chained = sg_first; T_TASK(cmd)->t_tasks_sg_chained_no = sg_count; - DEBUG_CMD_M("Setup T_TASK(cmd)->t_tasks_sg_chained: %p and" - " t_tasks_sg_chained_no: %u\n", T_TASK(cmd)->t_tasks_sg_chained, + DEBUG_CMD_M("Setup cmd: %p T_TASK(cmd)->t_tasks_sg_chained: %p and" + " t_tasks_sg_chained_no: %u\n", cmd, T_TASK(cmd)->t_tasks_sg_chained, T_TASK(cmd)->t_tasks_sg_chained_no); for_each_sg(T_TASK(cmd)->t_tasks_sg_chained, sg, T_TASK(cmd)->t_tasks_sg_chained_no, i) { - DEBUG_CMD_M("SG: %p page: %p length: %d offset: %d\n", - sg, sg_page(sg), sg->length, sg->offset); + DEBUG_CMD_M("SG[%d]: %p page: %p length: %d offset: %d, magic: 0x%08x\n", + i, sg, sg_page(sg), sg->length, sg->offset, sg->sg_magic); if (sg_is_chain(sg)) DEBUG_CMD_M("SG: %p sg_is_chain=1\n", sg); if (sg_is_last(sg)) DEBUG_CMD_M("SG: %p sg_is_last=1\n", sg); } - } EXPORT_SYMBOL(transport_do_task_sg_chain); -- cgit v1.2.3 From 1e7de68c57daf75ec4b721f101f88cccf029e38c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 19 May 2011 20:19:10 -0700 Subject: [SCSI] target: Fix interrupt context bug with stats_lock and core_tmr_alloc_req This patch fixes two bugs wrt to the interrupt context usage of target core with HW target mode drivers. It first converts the usage of struct se_device->stats_lock in transport_get_lun_for_cmd() and core_tmr_lun_reset() to properly use spin_lock_irq() to address an BUG with CONFIG_LOCKDEP_SUPPORT=y enabled. This patch also adds a 'in_interrupt()' check to allow GFP_ATOMIC usage from core_tmr_alloc_req() to fix a 'sleeping in interrupt context' BUG with HW target fabrics that require this logic to function. Signed-off-by: Nicholas Bellinger Cc: stable@kernel.org Signed-off-by: James Bottomley --- drivers/target/target_core_device.c | 4 ++-- drivers/target/target_core_tmr.c | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index d25e20829012..fc10ed4ac493 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -150,13 +150,13 @@ out: { struct se_device *dev = se_lun->lun_se_dev; - spin_lock(&dev->stats_lock); + spin_lock_irq(&dev->stats_lock); dev->num_cmds++; if (se_cmd->data_direction == DMA_TO_DEVICE) dev->write_bytes += se_cmd->data_length; else if (se_cmd->data_direction == DMA_FROM_DEVICE) dev->read_bytes += se_cmd->data_length; - spin_unlock(&dev->stats_lock); + spin_unlock_irq(&dev->stats_lock); } /* diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 4a109835e420..59b8b9c5ad72 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -55,7 +55,8 @@ struct se_tmr_req *core_tmr_alloc_req( { struct se_tmr_req *tmr; - tmr = kmem_cache_zalloc(se_tmr_req_cache, GFP_KERNEL); + tmr = kmem_cache_zalloc(se_tmr_req_cache, (in_interrupt()) ? + GFP_ATOMIC : GFP_KERNEL); if (!(tmr)) { printk(KERN_ERR "Unable to allocate struct se_tmr_req\n"); return ERR_PTR(-ENOMEM); @@ -398,9 +399,9 @@ int core_tmr_lun_reset( printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n"); } - spin_lock(&dev->stats_lock); + spin_lock_irq(&dev->stats_lock); dev->num_resets++; - spin_unlock(&dev->stats_lock); + spin_unlock_irq(&dev->stats_lock); DEBUG_LR("LUN_RESET: %s for [%s] Complete\n", (preempt_and_abort_list) ? "Preempt" : "TMR", -- cgit v1.2.3 From 42c6951e2f7a665bcb57b92fe3f806ba48152c0e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 19 May 2011 20:19:11 -0700 Subject: [SCSI] target: Fix bug with task_sg chained transport_free_dev_tasks release This patch addresses a bug in the target core release path for HW operation where transport_free_dev_tasks() was incorrectly being called from transport_lun_remove_cmd() while releasing a se_cmd reference and calling struct target_core_fabric_ops->queue_data_in(). This would result in a OOPs with HW target mode when the release of se_task->task_sg[] would happen before pci_unmap_sg() can be called in HW target mode fabric module code. This patch addresses the issue by moving transport_free_dev_tasks() from transport_lun_remove_cmd() into transport_generic_free_cmd(), and adding TRANSPORT_FREE_CMD_INTR and transport_generic_free_cmd_intr() to allow se_cmd descriptor release to happen fromfrom within transport_processing_thread() process context when release of se_cmd is not possible from HW interrupt context. Signed-off-by: Nicholas Bellinger Cc: stable@kernel.org Signed-off-by: James Bottomley --- drivers/target/target_core_transport.c | 13 ++++++++++++- include/target/target_core_base.h | 1 + include/target/target_core_transport.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index fefe10a2aa94..3eeb3e2436f1 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -762,7 +762,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) transport_all_task_dev_remove_state(cmd); spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); - transport_free_dev_tasks(cmd); check_lun: spin_lock_irqsave(&lun->lun_cmd_lock, flags); @@ -2058,6 +2057,13 @@ int transport_generic_handle_tmr( } EXPORT_SYMBOL(transport_generic_handle_tmr); +void transport_generic_free_cmd_intr( + struct se_cmd *cmd) +{ + transport_add_cmd_to_queue(cmd, TRANSPORT_FREE_CMD_INTR); +} +EXPORT_SYMBOL(transport_generic_free_cmd_intr); + static int transport_stop_tasks_for_cmd(struct se_cmd *cmd) { struct se_task *task, *task_tmp; @@ -5301,6 +5307,8 @@ void transport_generic_free_cmd( if (wait_for_tasks && cmd->transport_wait_for_tasks) cmd->transport_wait_for_tasks(cmd, 0, 0); + transport_free_dev_tasks(cmd); + transport_generic_remove(cmd, release_to_pool, session_reinstatement); } @@ -6136,6 +6144,9 @@ get_cmd: case TRANSPORT_REMOVE: transport_generic_remove(cmd, 1, 0); break; + case TRANSPORT_FREE_CMD_INTR: + transport_generic_free_cmd(cmd, 0, 1, 0); + break; case TRANSPORT_PROCESS_TMR: transport_generic_do_tmr(cmd); break; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1d3b5b2f0dbc..561ac99def5a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -98,6 +98,7 @@ enum transport_state_table { TRANSPORT_REMOVE = 14, TRANSPORT_FREE = 15, TRANSPORT_NEW_CMD_MAP = 16, + TRANSPORT_FREE_CMD_INTR = 17, }; /* Used for struct se_cmd->se_cmd_flags */ diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index 59aa464f6ee2..24a1c6cb83c3 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h @@ -172,6 +172,7 @@ extern int transport_generic_handle_cdb_map(struct se_cmd *); extern int transport_generic_handle_data(struct se_cmd *); extern void transport_new_cmd_failure(struct se_cmd *); extern int transport_generic_handle_tmr(struct se_cmd *); +extern void transport_generic_free_cmd_intr(struct se_cmd *); extern void __transport_stop_task_timer(struct se_task *, unsigned long *); extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]); extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, -- cgit v1.2.3 From ccf4d680f80941f0073a9bc6a5e0ed41496b46e7 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 19 May 2011 20:19:12 -0700 Subject: [SCSI] target: Fix task->task_execute_queue=1 clear bug + LUN_RESET OOPs This patch fixes a bug where task->task_execute_queue=1 was not being cleared once se_task had been removed from se_device->execute_task_list, resulting in an OOPs in core_tmr_lun_reset() for the task->task_active=0 case where transport_remove_task_from_execute_queue() was incorrectly being called. This patch fixes two cases in transport_get_task_from_execute_queue() and transport_remove_task_from_execute_queue() to properly clear task->task_execute_queue=0 once list_del(&task->t_execute_list) has been called. It also adds an explict check in transport_remove_task_from_execute_queue() to dump_stack + return if called with task->task_execute_queue=0. Signed-off-by: Nicholas Bellinger Cc: stable@kernel.org Signed-off-by: James Bottomley --- drivers/target/target_core_transport.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 3eeb3e2436f1..beaf8fa89124 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1194,6 +1194,7 @@ transport_get_task_from_execute_queue(struct se_device *dev) break; list_del(&task->t_execute_list); + atomic_set(&task->task_execute_queue, 0); atomic_dec(&dev->execute_tasks); return task; @@ -1209,8 +1210,14 @@ void transport_remove_task_from_execute_queue( { unsigned long flags; + if (atomic_read(&task->task_execute_queue) == 0) { + dump_stack(); + return; + } + spin_lock_irqsave(&dev->execute_task_lock, flags); list_del(&task->t_execute_list); + atomic_set(&task->task_execute_queue, 0); atomic_dec(&dev->execute_tasks); spin_unlock_irqrestore(&dev->execute_task_lock, flags); } -- cgit v1.2.3 From 1078da163fd2c1d3cba76cd4018e897a4f98efc5 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 19 May 2011 20:19:13 -0700 Subject: [SCSI] target: Convert REPORT_LUNs to use int_to_scsilun This patch converts transport_core_report_lun_response() to use drivers/scsi/scsi_scan.c:int_to_scsilun instead of using the struct target_core_fabric_ops->pack_lun() fabric provided API vector. It also removes the tfo->pack_lun check from target_fabric_tf_ops_check() and removes from struct target_core_fabric_ops->pack_lun() from target_core_fabric_ops.h, and the following mainline scsi-misc fabric modules: *) tcm_loop: Drop tcm_loop_pack_lun() usage *) tcm_fc: Drop ft_pack_lun() usage Reported-by: Mike Christie Signed-off-by: Nicholas A. Bellinger Signed-off-by: James Bottomley --- drivers/target/loopback/tcm_loop.c | 13 ------------- drivers/target/target_core_configfs.c | 4 ---- drivers/target/target_core_device.c | 25 +++++-------------------- drivers/target/tcm_fc/tfc_conf.c | 8 -------- include/target/target_core_fabric_ops.h | 1 - 5 files changed, 5 insertions(+), 46 deletions(-) diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index aed4e464d31c..09681bafe10d 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -939,18 +939,6 @@ static u16 tcm_loop_get_fabric_sense_len(void) return 0; } -static u64 tcm_loop_pack_lun(unsigned int lun) -{ - u64 result; - - /* LSB of lun into byte 1 big-endian */ - result = ((lun & 0xff) << 8); - /* use flat space addressing method */ - result |= 0x40 | ((lun >> 8) & 0x3f); - - return cpu_to_le64(result); -} - static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba) { switch (tl_hba->tl_proto_id) { @@ -1481,7 +1469,6 @@ static int tcm_loop_register_configfs(void) fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len; fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len; fabric->tf_ops.is_state_remove = &tcm_loop_is_state_remove; - fabric->tf_ops.pack_lun = &tcm_loop_pack_lun; tf_cg = &fabric->tf_group; /* diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index a5f44a6e6e1d..ee6fad979b50 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -497,10 +497,6 @@ static int target_fabric_tf_ops_check( printk(KERN_ERR "Missing tfo->is_state_remove()\n"); return -EINVAL; } - if (!(tfo->pack_lun)) { - printk(KERN_ERR "Missing tfo->pack_lun()\n"); - return -EINVAL; - } /* * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn() * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index fc10ed4ac493..8407f9ca2b31 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -658,8 +659,7 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) struct se_session *se_sess = SE_SESS(se_cmd); struct se_task *se_task; unsigned char *buf = (unsigned char *)T_TASK(se_cmd)->t_task_buf; - u32 cdb_offset = 0, lun_count = 0, offset = 8; - u64 i, lun; + u32 cdb_offset = 0, lun_count = 0, offset = 8, i; list_for_each_entry(se_task, &T_TASK(se_cmd)->t_task_list, t_list) break; @@ -675,15 +675,7 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) * a $FABRIC_MOD. In that case, report LUN=0 only. */ if (!(se_sess)) { - lun = 0; - buf[offset++] = ((lun >> 56) & 0xff); - buf[offset++] = ((lun >> 48) & 0xff); - buf[offset++] = ((lun >> 40) & 0xff); - buf[offset++] = ((lun >> 32) & 0xff); - buf[offset++] = ((lun >> 24) & 0xff); - buf[offset++] = ((lun >> 16) & 0xff); - buf[offset++] = ((lun >> 8) & 0xff); - buf[offset++] = (lun & 0xff); + int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); lun_count = 1; goto done; } @@ -703,15 +695,8 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) if ((cdb_offset + 8) >= se_cmd->data_length) continue; - lun = cpu_to_be64(CMD_TFO(se_cmd)->pack_lun(deve->mapped_lun)); - buf[offset++] = ((lun >> 56) & 0xff); - buf[offset++] = ((lun >> 48) & 0xff); - buf[offset++] = ((lun >> 40) & 0xff); - buf[offset++] = ((lun >> 32) & 0xff); - buf[offset++] = ((lun >> 24) & 0xff); - buf[offset++] = ((lun >> 16) & 0xff); - buf[offset++] = ((lun >> 8) & 0xff); - buf[offset++] = (lun & 0xff); + int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); + offset += 8; cdb_offset += 8; } spin_unlock_irq(&SE_NODE_ACL(se_sess)->device_list_lock); diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index fcdbbffe88cc..84e868c255dd 100644 --- a/drivers/target/tcm_fc/tfc_conf.c +++ b/drivers/target/tcm_fc/tfc_conf.c @@ -519,13 +519,6 @@ static u32 ft_tpg_get_inst_index(struct se_portal_group *se_tpg) return tpg->index; } -static u64 ft_pack_lun(unsigned int index) -{ - WARN_ON(index >= 256); - /* Caller wants this byte-swapped */ - return cpu_to_le64((index & 0xff) << 8); -} - static struct target_core_fabric_ops ft_fabric_ops = { .get_fabric_name = ft_get_fabric_name, .get_fabric_proto_ident = fc_get_fabric_proto_ident, @@ -564,7 +557,6 @@ static struct target_core_fabric_ops ft_fabric_ops = { .get_fabric_sense_len = ft_get_fabric_sense_len, .set_fabric_sense_len = ft_set_fabric_sense_len, .is_state_remove = ft_is_state_remove, - .pack_lun = ft_pack_lun, /* * Setup function pointers for generic logic in * target_core_fabric_configfs.c diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h index dc78f77f9450..747e1404dca0 100644 --- a/include/target/target_core_fabric_ops.h +++ b/include/target/target_core_fabric_ops.h @@ -77,7 +77,6 @@ struct target_core_fabric_ops { u16 (*set_fabric_sense_len)(struct se_cmd *, u32); u16 (*get_fabric_sense_len)(void); int (*is_state_remove)(struct se_cmd *); - u64 (*pack_lun)(unsigned int); /* * fabric module calls for target_core_fabric_configfs.c */ -- cgit v1.2.3 From 61db1802bf33bf027cd97ba3f79566b2b2fce5c6 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 19 May 2011 20:19:14 -0700 Subject: [SCSI] target: Convert TASK_ATTR to scsi_tcq.h definitions This patch converts target core and follwing scsi-misc upstream fabric modules to use include/scsi/scsi_tcq.h includes for SIMPLE, HEAD_OF_QUEUE and ORDERED SCSI tasks instead of scsi/libsas.h with TASK_ATTR* *) tcm_loop: Convert tcm_loop_allocate_core_cmd() + tcm_loop_device_reset() to scsi_tcq.h *) tcm_fc: Convert ft_send_cmd() from FCP_PTA_* to scsi_tcq.h Reported-by: Christoph Hellwig Signed-off-by: Nicholas A. Bellinger Signed-off-by: James Bottomley --- drivers/target/loopback/tcm_loop.c | 12 ++++++------ drivers/target/target_core_pscsi.c | 4 ++-- drivers/target/target_core_transport.c | 22 +++++++++++----------- drivers/target/tcm_fc/tfc_cmd.c | 20 +++++++++++++++++++- include/scsi/scsi_tcq.h | 1 + 5 files changed, 39 insertions(+), 20 deletions(-) diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 09681bafe10d..dee2a2c909f5 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -31,7 +31,7 @@ #include #include #include -#include /* For TASK_ATTR_* */ +#include #include #include @@ -95,17 +95,17 @@ static struct se_cmd *tcm_loop_allocate_core_cmd( if (sc->device->tagged_supported) { switch (sc->tag) { case HEAD_OF_QUEUE_TAG: - sam_task_attr = TASK_ATTR_HOQ; + sam_task_attr = MSG_HEAD_TAG; break; case ORDERED_QUEUE_TAG: - sam_task_attr = TASK_ATTR_ORDERED; + sam_task_attr = MSG_ORDERED_TAG; break; default: - sam_task_attr = TASK_ATTR_SIMPLE; + sam_task_attr = MSG_SIMPLE_TAG; break; } } else - sam_task_attr = TASK_ATTR_SIMPLE; + sam_task_attr = MSG_SIMPLE_TAG; /* * Initialize struct se_cmd descriptor from target_core_mod infrastructure @@ -379,7 +379,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) * Initialize struct se_cmd descriptor from target_core_mod infrastructure */ transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0, - DMA_NONE, TASK_ATTR_SIMPLE, + DMA_NONE, MSG_SIMPLE_TAG, &tl_cmd->tl_sense_buf[0]); /* * Allocate the LUN_RESET TMR diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 7ff6a35f26ac..331d423fd0e0 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -41,7 +41,7 @@ #include #include #include -#include /* For TASK_ATTR_* */ +#include #include #include @@ -911,7 +911,7 @@ static int pscsi_do_task(struct se_task *task) * descriptor */ blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req, - (task->task_se_cmd->sam_task_attr == TASK_ATTR_HOQ), + (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG), pscsi_req_done); return PYX_TRANSPORT_SENT_TO_TRANSPORT; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index beaf8fa89124..5b1ce81e3aa7 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -42,7 +42,7 @@ #include #include #include -#include /* For TASK_ATTR_* */ +#include #include #include @@ -1074,7 +1074,7 @@ static inline int transport_add_task_check_sam_attr( * head of the struct se_device->execute_task_list, and task_prev * after that for each subsequent task */ - if (task->task_se_cmd->sam_task_attr == TASK_ATTR_HOQ) { + if (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG) { list_add(&task->t_execute_list, (task_prev != NULL) ? &task_prev->t_execute_list : @@ -1873,7 +1873,7 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) if (SE_DEV(cmd)->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) return 0; - if (cmd->sam_task_attr == TASK_ATTR_ACA) { + if (cmd->sam_task_attr == MSG_ACA_TAG) { DEBUG_STA("SAM Task Attribute ACA" " emulation is not supported\n"); return -1; @@ -2517,7 +2517,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) * Check for the existence of HEAD_OF_QUEUE, and if true return 1 * to allow the passed struct se_cmd list of tasks to the front of the list. */ - if (cmd->sam_task_attr == TASK_ATTR_HOQ) { + if (cmd->sam_task_attr == MSG_HEAD_TAG) { atomic_inc(&SE_DEV(cmd)->dev_hoq_count); smp_mb__after_atomic_inc(); DEBUG_STA("Added HEAD_OF_QUEUE for CDB:" @@ -2525,7 +2525,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) T_TASK(cmd)->t_task_cdb[0], cmd->se_ordered_id); return 1; - } else if (cmd->sam_task_attr == TASK_ATTR_ORDERED) { + } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) { spin_lock(&SE_DEV(cmd)->ordered_cmd_lock); list_add_tail(&cmd->se_ordered_list, &SE_DEV(cmd)->ordered_cmd_list); @@ -3424,7 +3424,7 @@ static int transport_generic_cmd_sequencer( * See spc4r17 section 5.3 */ if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - cmd->sam_task_attr = TASK_ATTR_HOQ; + cmd->sam_task_attr = MSG_HEAD_TAG; cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; break; case READ_BUFFER: @@ -3632,7 +3632,7 @@ static int transport_generic_cmd_sequencer( * See spc4r17 section 5.3 */ if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - cmd->sam_task_attr = TASK_ATTR_HOQ; + cmd->sam_task_attr = MSG_HEAD_TAG; cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; break; default: @@ -3790,21 +3790,21 @@ static void transport_complete_task_attr(struct se_cmd *cmd) struct se_cmd *cmd_p, *cmd_tmp; int new_active_tasks = 0; - if (cmd->sam_task_attr == TASK_ATTR_SIMPLE) { + if (cmd->sam_task_attr == MSG_SIMPLE_TAG) { atomic_dec(&dev->simple_cmds); smp_mb__after_atomic_dec(); dev->dev_cur_ordered_id++; DEBUG_STA("Incremented dev->dev_cur_ordered_id: %u for" " SIMPLE: %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id); - } else if (cmd->sam_task_attr == TASK_ATTR_HOQ) { + } else if (cmd->sam_task_attr == MSG_HEAD_TAG) { atomic_dec(&dev->dev_hoq_count); smp_mb__after_atomic_dec(); dev->dev_cur_ordered_id++; DEBUG_STA("Incremented dev_cur_ordered_id: %u for" " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id); - } else if (cmd->sam_task_attr == TASK_ATTR_ORDERED) { + } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) { spin_lock(&dev->ordered_cmd_lock); list_del(&cmd->se_ordered_list); atomic_dec(&dev->dev_ordered_sync); @@ -3837,7 +3837,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd) new_active_tasks++; spin_lock(&dev->delayed_cmd_lock); - if (cmd_p->sam_task_attr == TASK_ATTR_ORDERED) + if (cmd_p->sam_task_attr == MSG_ORDERED_TAG) break; } spin_unlock(&dev->delayed_cmd_lock); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 49e51778f733..c056a1132ae1 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -592,8 +593,25 @@ static void ft_send_cmd(struct ft_cmd *cmd) case FCP_CFL_WRDATA | FCP_CFL_RDDATA: goto err; /* TBD not supported by tcm_fc yet */ } + /* + * Locate the SAM Task Attr from fc_pri_ta + */ + switch (fcp->fc_pri_ta & FCP_PTA_MASK) { + case FCP_PTA_HEADQ: + task_attr = MSG_HEAD_TAG; + break; + case FCP_PTA_ORDERED: + task_attr = MSG_ORDERED_TAG; + break; + case FCP_PTA_ACA: + task_attr = MSG_ACA_TAG; + break; + case FCP_PTA_SIMPLE: /* Fallthrough */ + default: + task_attr = MSG_SIMPLE_TAG; + } + - /* FCP_PTA_ maps 1:1 to TASK_ATTR_ */ task_attr = fcp->fc_pri_ta & FCP_PTA_MASK; data_len = ntohl(fcp->fc_dl); cmd->cdb = fcp->fc_cdb; diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h index d6e7994aa634..81dd12edc38c 100644 --- a/include/scsi/scsi_tcq.h +++ b/include/scsi/scsi_tcq.h @@ -9,6 +9,7 @@ #define MSG_SIMPLE_TAG 0x20 #define MSG_HEAD_TAG 0x21 #define MSG_ORDERED_TAG 0x22 +#define MSG_ACA_TAG 0x24 /* unsupported */ #define SCSI_NO_TAG (-1) /* identify no tag in use */ -- cgit v1.2.3 From cbf74cea070fa1f705de4712e25d9e56ae6543c7 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 30 May 2011 16:31:11 +0200 Subject: oprofile, x86: Add comments to IBS LVT offset initialization Adding a comment in the code as IBS LVT setup is not obvious at all ... Signed-off-by: Robert Richter --- arch/x86/kernel/apic/apic.c | 3 ++- arch/x86/oprofile/op_model_amd.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index fabf01eff771..a0bf78a0918c 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -390,7 +390,8 @@ static unsigned int reserve_eilvt_offset(int offset, unsigned int new) /* * If mask=1, the LVT entry does not generate interrupts while mask=0 - * enables the vector. See also the BKDGs. + * enables the vector. See also the BKDGs. Must be called with + * preemption disabled. */ int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask) diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 9fd8a567fe1e..9cbb710dc94b 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -609,16 +609,21 @@ static int setup_ibs_ctl(int ibs_eilvt_off) return 0; } +/* + * This runs only on the current cpu. We try to find an LVT offset and + * setup the local APIC. For this we must disable preemption. On + * success we initialize all nodes with this offset. This updates then + * the offset in the IBS_CTL per-node msr. The per-core APIC setup of + * the IBS interrupt vector is called from op_amd_setup_ctrs()/op_- + * amd_cpu_shutdown() using the new offset. + */ static int force_ibs_eilvt_setup(void) { int offset; int ret; - /* - * find the next free available EILVT entry, skip offset 0, - * pin search to this cpu - */ preempt_disable(); + /* find the next free available EILVT entry, skip offset 0 */ for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) { if (get_eilvt(offset)) break; -- cgit v1.2.3 From 6ac6519b93065625119a347be1cbcc1b89edb773 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 26 May 2011 18:22:54 +0200 Subject: oprofile: Free potentially owned tasks in case of errors After registering the task free notifier we possibly have tasks in our dying_tasks list. Free them after unregistering the notifier in case of an error. Cc: # .36+ Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index a3984f4ef192..04250aa16f51 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -141,6 +141,13 @@ static struct notifier_block module_load_nb = { .notifier_call = module_load_notify, }; +static void free_all_tasks(void) +{ + /* make sure we don't leak task structs */ + process_task_mortuary(); + process_task_mortuary(); +} + int sync_start(void) { int err; @@ -174,6 +181,7 @@ out3: profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); out2: task_handoff_unregister(&task_free_nb); + free_all_tasks(); out1: free_cpumask_var(marked_cpus); goto out; @@ -192,10 +200,7 @@ void sync_stop(void) mutex_unlock(&buffer_mutex); flush_cpu_work(); - /* make sure we don't leak task structs */ - process_task_mortuary(); - process_task_mortuary(); - + free_all_tasks(); free_cpumask_var(marked_cpus); } -- cgit v1.2.3 From 130c5ce716c9bfd1c2a2ec840a746eb7ff9ce1e6 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 26 May 2011 18:39:35 +0200 Subject: oprofile: Fix locking dependency in sync_start() This fixes the A->B/B->A locking dependency, see the warning below. The function task_exit_notify() is called with (task_exit_notifier) .rwsem set and then calls sync_buffer() which locks buffer_mutex. In sync_start() the buffer_mutex was set to prevent notifier functions to be started before sync_start() is finished. But when registering the notifier, (task_exit_notifier).rwsem is locked too, but now in different order than in sync_buffer(). In theory this causes a locking dependency, what does not occur in practice since task_exit_notify() is always called after the notifier is registered which means the lock is already released. However, after checking the notifier functions it turned out the buffer_mutex in sync_start() is unnecessary. This is because sync_buffer() may be called from the notifiers even if sync_start() did not finish yet, the buffers are already allocated but empty. No need to protect this with the mutex. So we fix this theoretical locking dependency by removing buffer_mutex in sync_start(). This is similar to the implementation before commit: 750d857 oprofile: fix crash when accessing freed task structs which introduced the locking dependency. Lockdep warning: oprofiled/4447 is trying to acquire lock: (buffer_mutex){+.+...}, at: [] sync_buffer+0x31/0x3ec [oprofile] but task is already holding lock: ((task_exit_notifier).rwsem){++++..}, at: [] __blocking_notifier_call_chain+0x39/0x67 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 ((task_exit_notifier).rwsem){++++..}: [] lock_acquire+0xf8/0x11e [] down_write+0x44/0x67 [] blocking_notifier_chain_register+0x52/0x8b [] profile_event_register+0x2d/0x2f [] sync_start+0x47/0xc6 [oprofile] [] oprofile_setup+0x60/0xa5 [oprofile] [] event_buffer_open+0x59/0x8c [oprofile] [] __dentry_open+0x1eb/0x308 [] nameidata_to_filp+0x60/0x67 [] do_last+0x5be/0x6b2 [] path_openat+0xc7/0x360 [] do_filp_open+0x3d/0x8c [] do_sys_open+0x110/0x1a9 [] sys_open+0x20/0x22 [] system_call_fastpath+0x16/0x1b -> #0 (buffer_mutex){+.+...}: [] __lock_acquire+0x1085/0x1711 [] lock_acquire+0xf8/0x11e [] mutex_lock_nested+0x63/0x309 [] sync_buffer+0x31/0x3ec [oprofile] [] task_exit_notify+0x16/0x1a [oprofile] [] notifier_call_chain+0x37/0x63 [] __blocking_notifier_call_chain+0x50/0x67 [] blocking_notifier_call_chain+0x14/0x16 [] profile_task_exit+0x1a/0x1c [] do_exit+0x2a/0x6fc [] do_group_exit+0x83/0xae [] sys_exit_group+0x17/0x1b [] system_call_fastpath+0x16/0x1b other info that might help us debug this: 1 lock held by oprofiled/4447: #0: ((task_exit_notifier).rwsem){++++..}, at: [] __blocking_notifier_call_chain+0x39/0x67 stack backtrace: Pid: 4447, comm: oprofiled Not tainted 2.6.39-00007-gcf4d8d4 #10 Call Trace: [] print_circular_bug+0xae/0xbc [] __lock_acquire+0x1085/0x1711 [] ? sync_buffer+0x31/0x3ec [oprofile] [] lock_acquire+0xf8/0x11e [] ? sync_buffer+0x31/0x3ec [oprofile] [] ? mark_lock+0x42f/0x552 [] ? sync_buffer+0x31/0x3ec [oprofile] [] mutex_lock_nested+0x63/0x309 [] ? sync_buffer+0x31/0x3ec [oprofile] [] sync_buffer+0x31/0x3ec [oprofile] [] ? __blocking_notifier_call_chain+0x39/0x67 [] ? __blocking_notifier_call_chain+0x39/0x67 [] task_exit_notify+0x16/0x1a [oprofile] [] notifier_call_chain+0x37/0x63 [] __blocking_notifier_call_chain+0x50/0x67 [] blocking_notifier_call_chain+0x14/0x16 [] profile_task_exit+0x1a/0x1c [] do_exit+0x2a/0x6fc [] ? retint_swapgs+0xe/0x13 [] do_group_exit+0x83/0xae [] sys_exit_group+0x17/0x1b [] system_call_fastpath+0x16/0x1b Reported-by: Marcin Slusarz Cc: Carl Love Cc: # .36+ Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 04250aa16f51..f34b5b29fb95 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -155,8 +155,6 @@ int sync_start(void) if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL)) return -ENOMEM; - mutex_lock(&buffer_mutex); - err = task_handoff_register(&task_free_nb); if (err) goto out1; @@ -173,7 +171,6 @@ int sync_start(void) start_cpu_work(); out: - mutex_unlock(&buffer_mutex); return err; out4: profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); @@ -190,14 +187,13 @@ out1: void sync_stop(void) { - /* flush buffers */ - mutex_lock(&buffer_mutex); end_cpu_work(); unregister_module_notifier(&module_load_nb); profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); task_handoff_unregister(&task_free_nb); - mutex_unlock(&buffer_mutex); + barrier(); /* do all of the above first */ + flush_cpu_work(); free_all_tasks(); -- cgit v1.2.3 From fe47ae7f53e179d2ef6771024feb000cbb86640f Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 31 May 2011 12:35:41 +0200 Subject: oprofile, dcookies: Fix possible circular locking dependency The lockdep warning below detects a possible A->B/B->A locking dependency of mm->mmap_sem and dcookie_mutex. The order in sync_buffer() is mm->mmap_sem/dcookie_mutex, while in sys_lookup_dcookie() it is vice versa. Fixing it in sys_lookup_dcookie() by unlocking dcookie_mutex before copy_to_user(). oprofiled/4432 is trying to acquire lock: (&mm->mmap_sem){++++++}, at: [] might_fault+0x53/0xa3 but task is already holding lock: (dcookie_mutex){+.+.+.}, at: [] sys_lookup_dcookie+0x45/0x149 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (dcookie_mutex){+.+.+.}: [] lock_acquire+0xf8/0x11e [] mutex_lock_nested+0x63/0x309 [] get_dcookie+0x30/0x144 [] sync_buffer+0x196/0x3ec [oprofile] [] task_exit_notify+0x16/0x1a [oprofile] [] notifier_call_chain+0x37/0x63 [] __blocking_notifier_call_chain+0x50/0x67 [] blocking_notifier_call_chain+0x14/0x16 [] profile_task_exit+0x1a/0x1c [] do_exit+0x2a/0x6fc [] do_group_exit+0x83/0xae [] sys_exit_group+0x17/0x1b [] system_call_fastpath+0x16/0x1b -> #0 (&mm->mmap_sem){++++++}: [] __lock_acquire+0x1085/0x1711 [] lock_acquire+0xf8/0x11e [] might_fault+0x80/0xa3 [] sys_lookup_dcookie+0x104/0x149 [] system_call_fastpath+0x16/0x1b other info that might help us debug this: 1 lock held by oprofiled/4432: #0: (dcookie_mutex){+.+.+.}, at: [] sys_lookup_dcookie+0x45/0x149 stack backtrace: Pid: 4432, comm: oprofiled Not tainted 2.6.39-00008-ge5a450d #9 Call Trace: [] print_circular_bug+0xae/0xbc [] __lock_acquire+0x1085/0x1711 [] ? get_parent_ip+0x11/0x42 [] ? might_fault+0x53/0xa3 [] lock_acquire+0xf8/0x11e [] ? might_fault+0x53/0xa3 [] ? path_put+0x22/0x27 [] might_fault+0x80/0xa3 [] ? might_fault+0x53/0xa3 [] sys_lookup_dcookie+0x104/0x149 [] system_call_fastpath+0x16/0x1b References: https://bugzilla.kernel.org/show_bug.cgi?id=13809 Cc: # .27+ Signed-off-by: Robert Richter --- fs/dcookies.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/dcookies.c b/fs/dcookies.c index a21cabdbd87b..dda0dc702d1b 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c @@ -178,6 +178,8 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) /* FIXME: (deleted) ? */ path = d_path(&dcs->path, kbuf, PAGE_SIZE); + mutex_unlock(&dcookie_mutex); + if (IS_ERR(path)) { err = PTR_ERR(path); goto out_free; @@ -194,6 +196,7 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) out_free: kfree(kbuf); + return err; out: mutex_unlock(&dcookie_mutex); return err; -- cgit v1.2.3 From 5aceca9d3cbdacbd017712513387d930f9f944d9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 May 2011 17:12:22 -0700 Subject: PCI: Fix warning in drivers/pci/probe.c on sparc64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IO_SPACE_LIMIT is currently used in two ways: 1) As a way to mask I/O port values read out of PCI base address registers. This value should be 64-bit. 2) As a value which is the upper limit for all I/O "ports" in the system. On sparc64 we store the full 64-bit physical I/O address in the resources. For this reason we define IO_SPACE_LIMIT at a 64-bit "all 1's". This is the right value to use for ioport_resource.end and for the check made in drivers/pcmcia/rsrc_nonstatic.c:adjust_io(). But in driver/pci/probe.c:__pci_read_base() we mask this against a "u32" variable and thus get the following warning: drivers/pci/probe.c: In function ¡__pci_read_base¢: drivers/pci/probe.c:207: warning: large integer implicitly truncated to unsigned type Fix this by using an explicit "u32" cast. I considered changing sparc64 to define a 32-bit "all 1's" like most other systems do, but this wouldn't work because the checks in PCMCIA's rsrc_nonstatic.c would no longer be right since they are testing against fully formed 64-bit resources. As described above, on sparc64 such resources will hold full 64-bit physical I/O addresses, not bus-centric 32-bit ones. Signed-off-by: David S. Miller Signed-off-by: Jesse Barnes --- drivers/pci/probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 48849ffdd672..bafb3c3d4a89 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -168,7 +168,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; if (type == pci_bar_io) { l &= PCI_BASE_ADDRESS_IO_MASK; - mask = PCI_BASE_ADDRESS_IO_MASK & IO_SPACE_LIMIT; + mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; } else { l &= PCI_BASE_ADDRESS_MEM_MASK; mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; -- cgit v1.2.3 From ebf30dc91cc8592cd72b004219cfc276b3ad2854 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 31 May 2011 16:10:00 -0700 Subject: msm: timer: Fix SMP build error Fix build breakage on SMP=y builds due to 0f7b332 (ARM: consolidate SMP cross call implementation, 2011-04-03) arch/arm/mach-msm/timer.c: In function 'local_timer_setup': arch/arm/mach-msm/timer.c:295: error: implicit declaration of function 'gic_enable_ppi' Signed-off-by: Stephen Boyd Signed-off-by: David Brown --- arch/arm/mach-msm/timer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 38b95e949d13..9bfdd5ad2441 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -23,6 +23,8 @@ #include #include +#include + #include #include -- cgit v1.2.3 From 3f37d6229ca309f96b163b943ff982f4697630cd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 25 May 2011 19:21:25 -0700 Subject: PCI: fix new kernel-doc warning Fix pci.c kernel-doc warnings: Warning(drivers/pci/pci.c:3292): No description found for parameter 'flags' Warning(drivers/pci/pci.c:3292): Excess function parameter 'change_bridge_flags' description in 'pci_set_vga_state' Signed-off-by: Randy Dunlap Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 56098b3e17c0..e43a7bbeb28f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3284,7 +3284,7 @@ static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode, * @dev: the PCI device * @decode: true = enable decoding, false = disable decoding * @command_bits: PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY - * @change_bridge_flags: traverse ancestors and change bridges + * @flags: traverse ancestors and change bridges * CHANGE_BRIDGE_ONLY / CHANGE_BRIDGE */ int pci_set_vga_state(struct pci_dev *dev, bool decode, -- cgit v1.2.3 From 6e33a852a37dee02979ec9d82bea26c07cee5bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sat, 14 May 2011 19:27:33 +0200 Subject: x86/PCI/ACPI: fix type mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The flags field of struct resource from linux/ioport.h is "unsigned long". Change the "type" parameter of coalesce_windows() function to match that field. This fixes the following warning messages when compiling with "make C=1 W=1 bzImage modules": arch/x86/pci/acpi.c: In function ‘coalesce_windows’: arch/x86/pci/acpi.c:198: warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result arch/x86/pci/acpi.c:203: warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result Signed-off-by: Márton Németh Signed-off-by: Jesse Barnes --- arch/x86/pci/acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 0972315c3860..68c3c1395202 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -188,7 +188,7 @@ static bool resource_contains(struct resource *res, resource_size_t point) return false; } -static void coalesce_windows(struct pci_root_info *info, int type) +static void coalesce_windows(struct pci_root_info *info, unsigned long type) { int i, j; struct resource *res1, *res2; -- cgit v1.2.3 From d62fa31123d557bca9a1e3b5da9672e8cc9753db Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Thu, 12 May 2011 18:31:20 +0900 Subject: ARM: S5PV210: Fix possible null pointer dereference Signed-off-by: Jonghwan Choi Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pv210/cpufreq.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c index 22046e2f53c2..153af8b359ec 100644 --- a/arch/arm/mach-s5pv210/cpufreq.c +++ b/arch/arm/mach-s5pv210/cpufreq.c @@ -101,12 +101,14 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) unsigned long tmp, tmp1; void __iomem *reg = NULL; - if (ch == DMC0) + if (ch == DMC0) { reg = (S5P_VA_DMC0 + 0x30); - else if (ch == DMC1) + } else if (ch == DMC1) { reg = (S5P_VA_DMC1 + 0x30); - else + } else { printk(KERN_ERR "Cannot find DMC port\n"); + return; + } /* Find current DRAM frequency */ tmp = s5pv210_dram_conf[ch].freq; -- cgit v1.2.3 From 457d4fe85138c0d313c92ef34ea892c73b0fe2f5 Mon Sep 17 00:00:00 2001 From: Padmavathi Venna Date: Tue, 31 May 2011 14:10:51 -0700 Subject: ARM: S5P64X0: Fix SPI platform device name Changed the SPI platform device name from S5P6450 to S5P64x0 as it is defined common for both S5p6440 and S5P6450 in dev-spi.c of S5P64x0. Signed-off-by: Padmavathi Venna Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/devs.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index b61b8ee7cc52..4af108ff4112 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -75,10 +75,8 @@ extern struct platform_device s5pc100_device_spi1; extern struct platform_device s5pc100_device_spi2; extern struct platform_device s5pv210_device_spi0; extern struct platform_device s5pv210_device_spi1; -extern struct platform_device s5p6440_device_spi0; -extern struct platform_device s5p6440_device_spi1; -extern struct platform_device s5p6450_device_spi0; -extern struct platform_device s5p6450_device_spi1; +extern struct platform_device s5p64x0_device_spi0; +extern struct platform_device s5p64x0_device_spi1; extern struct platform_device s3c_device_hwmon; -- cgit v1.2.3 From 08115a139229ca84adfef4d5983c3c186b9d1c30 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Wed, 1 Jun 2011 15:09:05 -0700 Subject: ARM: S5P: Should be S3C_VA_USB_HSPHY instead of S5P_VA_XX Basically, other S3C SoCs and S5PC100 use 'S3C_VA_USB_HSPHY' commonly. It should be changed to 'S3C_VA_USB_HSPHY' for common usage and others. Now happens build error on S5PC100. Cc: Greg Kroah-Hartman Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/cpu.c | 2 +- arch/arm/mach-exynos4/include/mach/regs-usb-phy.h | 2 +- arch/arm/plat-s5p/include/plat/map-s5p.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 08813a6f66b1..9babe4473e88 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -98,7 +98,7 @@ static struct map_desc exynos4_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_USB_HSPHY, + .virtual = (unsigned long)S3C_VA_USB_HSPHY, .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY), .length = SZ_4K, .type = MT_DEVICE, diff --git a/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h index 703118d5173c..c337cf3a71bf 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h +++ b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h @@ -11,7 +11,7 @@ #ifndef __PLAT_S5P_REGS_USB_PHY_H #define __PLAT_S5P_REGS_USB_PHY_H -#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S5P_VA_USB_HSPHY) +#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S3C_VA_USB_HSPHY) #define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00) #define PHY1_HSIC_NORMAL_MASK (0xf << 9) diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h index a6c3d327ce72..d973d39666a3 100644 --- a/arch/arm/plat-s5p/include/plat/map-s5p.h +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h @@ -39,7 +39,7 @@ #define S5P_VA_TWD S5P_VA_COREPERI(0x600) #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) -#define S5P_VA_USB_HSPHY S3C_ADDR(0x02900000) +#define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000) #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) #define VA_VIC0 VA_VIC(0) -- cgit v1.2.3 From e23ef227d10878ff3f323a1dfed10205a1825b71 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 29 May 2011 22:53:12 +0300 Subject: ptp: Return -EFAULT on copy_to_user() errors copy_to_user() returns the number of bytes remaining, but we want a negative error code in ptp_ioctl. Signed-off-by: Dan Carpenter Acked-by: Richard Cochran Signed-off-by: John Stultz --- drivers/ptp/ptp_chardev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index a8d03aeb4051..93fa22de5977 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -46,7 +46,8 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) caps.n_ext_ts = ptp->info->n_ext_ts; caps.n_per_out = ptp->info->n_per_out; caps.pps = ptp->info->pps; - err = copy_to_user((void __user *)arg, &caps, sizeof(caps)); + if (copy_to_user((void __user *)arg, &caps, sizeof(caps))) + err = -EFAULT; break; case PTP_EXTTS_REQUEST: -- cgit v1.2.3 From fb5a18cf7c771a12c3f42a5eb4b476eed68b77cb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 29 May 2011 22:54:07 +0300 Subject: ptp: Fix some locking bugs in ptp_read() In ptp_read there is an unlock missing on an error path, and a double unlock on another error path. Signed-off-by: Dan Carpenter Acked-by: Richard Cochran Signed-off-by: John Stultz --- drivers/ptp/ptp_chardev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index 93fa22de5977..e7f301da2902 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -130,8 +130,10 @@ ssize_t ptp_read(struct posix_clock *pc, return -ERESTARTSYS; } - if (ptp->defunct) + if (ptp->defunct) { + mutex_unlock(&ptp->tsevq_mux); return -ENODEV; + } spin_lock_irqsave(&queue->lock, flags); @@ -151,10 +153,8 @@ ssize_t ptp_read(struct posix_clock *pc, mutex_unlock(&ptp->tsevq_mux); - if (copy_to_user(buf, event, cnt)) { - mutex_unlock(&ptp->tsevq_mux); + if (copy_to_user(buf, event, cnt)) return -EFAULT; - } return cnt; } -- cgit v1.2.3 From e17fd4ba2a81f1d29875b20464e4899185a3c946 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 31 May 2011 23:26:11 -0700 Subject: rtc: Fix ioctl error path return Bryan Henderson noticed that the "RTC: Fix rtc driver ioctl specific shortcutting" commit has a small bug: When an ioctl is called with an invalid command code and the clock driver does not have an "ioctl" method, the ioctl returns rc 0 instead of -ENOTTY. This patch fixes the issue. CC: Bryan Henderson CC: Gabor Z. Papp Reported-by: Bryan Henderson Signed-off-by: John Stultz --- drivers/rtc/rtc-dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index d0e06edb14c5..cace6d3aed9a 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -421,7 +421,8 @@ static long rtc_dev_ioctl(struct file *file, err = ops->ioctl(rtc->dev.parent, cmd, arg); if (err == -ENOIOCTLCMD) err = -ENOTTY; - } + } else + err = -ENOTTY; break; } -- cgit v1.2.3 From d576fe49ca5c238e99d2d010a410480cb2aa29a0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Jun 2011 11:13:16 +0100 Subject: rtc: Staticize non-exported __rtc_set_alarm() It's not referenced outside this file so there's no need for it to be in the global namespace and sparse warns about that. Signed-off-by: Mark Brown Signed-off-by: John Stultz --- drivers/rtc/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index ef6316acec43..df68618f6dbb 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -318,7 +318,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_read_alarm); -int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) +static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { struct rtc_time tm; long now, scheduled; -- cgit v1.2.3 From eb7073db1076777496495483854993165e14790f Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 2 Jun 2011 11:31:29 +0900 Subject: 8250_pci: add -ENODEV code for Intel EG20T PCH Intel EG20T PCH has UART device which is compatible with 8250. Currently, with general configuration, the PCH UART driver is not loaded but 8250 standard driver is loaded. Therefore, in case of using PCH UART driver, need to disable 8250 pci function. However, this procedure is not best solution. This patch, in 8250_pci, if the device is the PCH or the family IOH, '-ENODEV' is returned. As a result, disabling 8250-pci processing becomes unnecessary. Signed-off-by: Tomoya MORINAGA Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250_pci.c | 59 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 4b4968a294b2..d7dc513451a6 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -994,6 +994,15 @@ static int skip_tx_en_setup(struct serial_private *priv, return pci_default_setup(priv, board, port, idx); } +static int pci_eg20t_init(struct pci_dev *dev) +{ +#if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE) + return -ENODEV; +#else + return 0; +#endif +} + /* This should be in linux/pci_ids.h */ #define PCI_VENDOR_ID_SBSMODULARIO 0x124B #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B @@ -1446,6 +1455,56 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .init = pci_oxsemi_tornado_init, .setup = pci_default_setup, }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x8811, + .init = pci_eg20t_init, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x8812, + .init = pci_eg20t_init, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x8813, + .init = pci_eg20t_init, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x8814, + .init = pci_eg20t_init, + }, + { + .vendor = 0x10DB, + .device = 0x8027, + .init = pci_eg20t_init, + }, + { + .vendor = 0x10DB, + .device = 0x8028, + .init = pci_eg20t_init, + }, + { + .vendor = 0x10DB, + .device = 0x8029, + .init = pci_eg20t_init, + }, + { + .vendor = 0x10DB, + .device = 0x800C, + .init = pci_eg20t_init, + }, + { + .vendor = 0x10DB, + .device = 0x800D, + .init = pci_eg20t_init, + }, + { + .vendor = 0x10DB, + .device = 0x800D, + .init = pci_eg20t_init, + }, /* * Cronyx Omega PCI (PLX-chip based) */ -- cgit v1.2.3 From 840d8e5e964dc51673d0f26e119b27d2898e8417 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Wed, 1 Jun 2011 23:59:10 +0200 Subject: ASoC: atmel_ssc: Don't try to free ssc if request failed We should only call ssc_free() when ssc_request() succeeds or bad things will happen. Signed-off-by: Joachim Eastwood Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_ssc_dai.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 7fbfa051f6e1..eda955b15834 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -848,9 +848,10 @@ int atmel_ssc_set_audio(int ssc_id) if (IS_ERR(ssc)) pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n", PTR_ERR(ssc)); - else + else { ssc_pdev->dev.parent = &(ssc->pdev->dev); - ssc_free(ssc); + ssc_free(ssc); + } ret = platform_device_add(ssc_pdev); if (ret < 0) -- cgit v1.2.3 From d4d84fef6d0366b585b7de13527a0faeca84d9ce Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 2 Jun 2011 10:19:41 -0400 Subject: slub: always align cpu_slab to honor cmpxchg_double requirement On an architecture without CMPXCHG_LOCAL but with DEBUG_VM enabled, the VM_BUG_ON() in __pcpu_double_call_return_bool() will cause an early panic during boot unless we always align cpu_slab properly. In principle we could remove the alignment-testing VM_BUG_ON() for architectures that don't have CMPXCHG_LOCAL, but leaving it in means that new code will tend not to break x86 even if it is introduced on another platform, and it's low cost to require alignment. Acked-by: David Rientjes Acked-by: Christoph Lameter Signed-off-by: Chris Metcalf Signed-off-by: Pekka Enberg --- include/linux/percpu.h | 3 +++ mm/slub.c | 12 ++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 8b97308e65df..9ca008f0c542 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -259,6 +259,9 @@ extern void __bad_size_call_parameter(void); * Special handling for cmpxchg_double. cmpxchg_double is passed two * percpu variables. The first has to be aligned to a double word * boundary and the second has to follow directly thereafter. + * We enforce this on all architectures even if they don't support + * a double cmpxchg instruction, since it's a cheap requirement, and it + * avoids breaking the requirement for architectures with the instruction. */ #define __pcpu_double_call_return_bool(stem, pcp1, pcp2, ...) \ ({ \ diff --git a/mm/slub.c b/mm/slub.c index 7be0223531b0..35f351f26193 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2320,16 +2320,12 @@ static inline int alloc_kmem_cache_cpus(struct kmem_cache *s) BUILD_BUG_ON(PERCPU_DYNAMIC_EARLY_SIZE < SLUB_PAGE_SHIFT * sizeof(struct kmem_cache_cpu)); -#ifdef CONFIG_CMPXCHG_LOCAL /* - * Must align to double word boundary for the double cmpxchg instructions - * to work. + * Must align to double word boundary for the double cmpxchg + * instructions to work; see __pcpu_double_call_return_bool(). */ - s->cpu_slab = __alloc_percpu(sizeof(struct kmem_cache_cpu), 2 * sizeof(void *)); -#else - /* Regular alignment is sufficient */ - s->cpu_slab = alloc_percpu(struct kmem_cache_cpu); -#endif + s->cpu_slab = __alloc_percpu(sizeof(struct kmem_cache_cpu), + 2 * sizeof(void *)); if (!s->cpu_slab) return 0; -- cgit v1.2.3 From a947eb95ea03199da7408a64baa97fbb613e9b84 Mon Sep 17 00:00:00 2001 From: Suleiman Souhlal Date: Thu, 2 Jun 2011 00:16:42 -0700 Subject: SLAB: Record actual last user of freed objects. Currently, when using CONFIG_DEBUG_SLAB, we put in kfree() or kmem_cache_free() as the last user of free objects, which is not very useful, so change it to the caller of those functions instead. Acked-by: David Rientjes Acked-by: Christoph Lameter Signed-off-by: Suleiman Souhlal Signed-off-by: Pekka Enberg --- mm/slab.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index bcfa4987c8ae..d96e223de775 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3604,13 +3604,14 @@ free_done: * Release an obj back to its cache. If the obj has a constructed state, it must * be in this state _before_ it is released. Called with disabled ints. */ -static inline void __cache_free(struct kmem_cache *cachep, void *objp) +static inline void __cache_free(struct kmem_cache *cachep, void *objp, + void *caller) { struct array_cache *ac = cpu_cache_get(cachep); check_irq_off(); kmemleak_free_recursive(objp, cachep->flags); - objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0)); + objp = cache_free_debugcheck(cachep, objp, caller); kmemcheck_slab_free(cachep, objp, obj_size(cachep)); @@ -3801,7 +3802,7 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) debug_check_no_locks_freed(objp, obj_size(cachep)); if (!(cachep->flags & SLAB_DEBUG_OBJECTS)) debug_check_no_obj_freed(objp, obj_size(cachep)); - __cache_free(cachep, objp); + __cache_free(cachep, objp, __builtin_return_address(0)); local_irq_restore(flags); trace_kmem_cache_free(_RET_IP_, objp); @@ -3831,7 +3832,7 @@ void kfree(const void *objp) c = virt_to_cache(objp); debug_check_no_locks_freed(objp, obj_size(c)); debug_check_no_obj_freed(objp, obj_size(c)); - __cache_free(c, (void *)objp); + __cache_free(c, (void *)objp, __builtin_return_address(0)); local_irq_restore(flags); } EXPORT_SYMBOL(kfree); -- cgit v1.2.3 From bdf492f502ad4f646e9905db1b89e11822826edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 1 Jun 2011 11:01:11 +0200 Subject: ssb: fix PCI(e) driver regression causing oops on PCI cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were incorrectly executing PCIe specific workarounds on PCI cards. This resulted in: Machine check in kernel mode. Caused by (from SRR1=149030): Transfer error ack signal Oops: Machine check, sig: 7 [#1] Reported-by: Andreas Schwab Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 82feb348c8bb..2a20dabec76d 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -539,10 +539,12 @@ void ssb_pcicore_init(struct ssb_pcicore *pc) if (!pc->hostmode) ssb_pcicore_init_clientmode(pc); - /* Additional always once-executed workarounds */ - ssb_pcicore_serdes_workaround(pc); - /* TODO: ASPM */ - /* TODO: Clock Request Update */ + /* Additional PCIe always once-executed workarounds */ + if (dev->id.coreid == SSB_DEV_PCIE) { + ssb_pcicore_serdes_workaround(pc); + /* TODO: ASPM */ + /* TODO: Clock Request Update */ + } } static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) -- cgit v1.2.3 From a99168eece601d2a79ecfcb968ce226f2f30cf98 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 2 Jun 2011 03:09:48 +0300 Subject: ath5k: Disable fast channel switching by default Disable fast channel change by default on AR2413/AR5413 due to some bug reports (it still works for me but it's better to be safe). Add a module parameter "fastchanswitch" in case anyone wants to enable it and play with it. Signed-off-by: Nick Kossifidis Tested-by: Sedat Dilek Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 11 ++++++++++- drivers/net/wireless/ath/ath5k/reset.c | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 22047628ccfa..b6c5d3715b96 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -72,6 +72,11 @@ static int modparam_all_channels; module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); +static int modparam_fastchanswitch; +module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); +MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); + + /* Module info */ MODULE_AUTHOR("Jiri Slaby"); MODULE_AUTHOR("Nick Kossifidis"); @@ -2686,6 +2691,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); int ret, ani_mode; + bool fast; ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); @@ -2705,7 +2711,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, ath5k_drain_tx_buffs(sc); if (chan) sc->curchan = chan; - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, + + fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; + + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, skip_pcu); if (ret) { ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 3510de2cf622..126a4eab35f3 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -1124,8 +1124,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* Non fatal, can happen eg. * on mode change */ ret = 0; - } else + } else { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + "fast chan change successful\n"); return 0; + } } /* -- cgit v1.2.3 From 6f213ff1919fab6f8244ceae55631b5d6ef750a7 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 2 Jun 2011 18:17:15 +0200 Subject: iwlagn: fix channel switch locking We use priv->mutex to avoid race conditions between iwl_chswitch_done() and iwlagn_mac_channel_switch(), when marking channel switch in progress. But iwl_chswitch_done() can be called in atomic context from iwl_rx_csa() or with mutex already taken from iwlagn_commit_rxon(). These bugs were introduced by: commit 79d07325502e73508f917475bc1617b60979dd94 Author: Wey-Yi Guy Date: Thu May 6 08:54:11 2010 -0700 iwlwifi: support channel switch offload in driver To fix remove mutex from iwl_chswitch_done() and use atomic bitops for marking channel switch pending. Also remove iwl2030_hw_channel_switch() since 2000 series adapters are 2.4GHz only devices. Cc: stable@kernel.org # 2.6.36+ Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-2000.c | 74 ----------------------------- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 - drivers/net/wireless/iwlwifi/iwl-6000.c | 2 - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 6 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 19 ++++---- drivers/net/wireless/iwlwifi/iwl-core.c | 6 +-- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 13 +---- drivers/net/wireless/iwlwifi/iwl-rx.c | 24 +++++----- 9 files changed, 28 insertions(+), 119 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 86feec86d130..2282279cffc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -177,79 +177,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) return 0; } -static int iwl2030_hw_channel_switch(struct iwl_priv *priv, - struct ieee80211_channel_switch *ch_switch) -{ - /* - * MULTI-FIXME - * See iwl_mac_channel_switch. - */ - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl6000_channel_switch_cmd cmd; - const struct iwl_channel_info *ch_info; - u32 switch_time_in_usec, ucode_switch_time; - u16 ch; - u32 tsf_low; - u8 switch_count; - u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); - struct ieee80211_vif *vif = ctx->vif; - struct iwl_host_cmd hcmd = { - .id = REPLY_CHANNEL_SWITCH, - .len = { sizeof(cmd), }, - .flags = CMD_SYNC, - .data = { &cmd, }, - }; - - cmd.band = priv->band == IEEE80211_BAND_2GHZ; - ch = ch_switch->channel->hw_value; - IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", - ctx->active.channel, ch); - cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = ctx->staging.flags; - cmd.rxon_filter_flags = ctx->staging.filter_flags; - switch_count = ch_switch->count; - tsf_low = ch_switch->timestamp & 0x0ffffffff; - /* - * calculate the ucode channel switch time - * adding TSF as one of the factor for when to switch - */ - if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { - if (switch_count > ((priv->ucode_beacon_time - tsf_low) / - beacon_interval)) { - switch_count -= (priv->ucode_beacon_time - - tsf_low) / beacon_interval; - } else - switch_count = 0; - } - if (switch_count <= 1) - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); - else { - switch_time_in_usec = - vif->bss_conf.beacon_int * switch_count * TIME_UNIT; - ucode_switch_time = iwl_usecs_to_beacons(priv, - switch_time_in_usec, - beacon_interval); - cmd.switch_time = iwl_add_beacon_time(priv, - priv->ucode_beacon_time, - ucode_switch_time, - beacon_interval); - } - IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", - cmd.switch_time); - ch_info = iwl_get_channel_info(priv, priv->band, ch); - if (ch_info) - cmd.expect_beacon = is_channel_radar(ch_info); - else { - IWL_ERR(priv, "invalid channel switch from %u to %u\n", - ctx->active.channel, ch); - return -EFAULT; - } - priv->switch_rxon.channel = cmd.channel; - priv->switch_rxon.switch_in_progress = true; - - return iwl_send_cmd_sync(priv, &hcmd); -} - static struct iwl_lib_ops iwl2000_lib = { .set_hw_params = iwl2000_hw_set_hw_params, .rx_handler_setup = iwlagn_rx_handler_setup, @@ -258,7 +185,6 @@ static struct iwl_lib_ops iwl2000_lib = { .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, - .set_channel_switch = iwl2030_hw_channel_switch, .apm_ops = { .init = iwl_apm_init, .config = iwl2000_nic_config, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a70b8cfafda1..5b721c56aee9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -331,8 +331,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, ctx->active.channel, ch); return -EFAULT; } - priv->switch_rxon.channel = cmd.channel; - priv->switch_rxon.switch_in_progress = true; return iwl_send_cmd_sync(priv, &hcmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index fda6fe08cf91..fbe565c816e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -270,8 +270,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, ctx->active.channel, ch); return -EFAULT; } - priv->switch_rxon.channel = cmd.channel; - priv->switch_rxon.switch_in_progress = true; return iwl_send_cmd_sync(priv, &hcmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index a95ad84c5377..2532c7db3aff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -342,10 +342,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * receive commit_rxon request * abort any previous channel switch if still in process */ - if (priv->switch_rxon.switch_in_progress && - (priv->switch_rxon.channel != ctx->staging.channel)) { + if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && + (priv->switch_channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", - le16_to_cpu(priv->switch_rxon.channel)); + le16_to_cpu(priv->switch_channel)); iwl_chswitch_done(priv, false); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a662adcb2adb..8e1942ebd9a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2843,16 +2843,13 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, goto out; if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) + test_bit(STATUS_SCANNING, &priv->status) || + test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) goto out; if (!iwl_is_associated_ctx(ctx)) goto out; - /* channel switch in progress */ - if (priv->switch_rxon.switch_in_progress == true) - goto out; - if (priv->cfg->ops->lib->set_channel_switch) { ch = channel->hw_value; @@ -2901,15 +2898,19 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, * at this point, staging_rxon has the * configuration for channel switch */ + set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); + priv->switch_channel = cpu_to_le16(ch); if (priv->cfg->ops->lib->set_channel_switch(priv, - ch_switch)) - priv->switch_rxon.switch_in_progress = false; + ch_switch)) { + clear_bit(STATUS_CHANNEL_SWITCH_PENDING, + &priv->status); + priv->switch_channel = 0; + ieee80211_chswitch_done(ctx->vif, false); + } } } out: mutex_unlock(&priv->mutex); - if (!priv->switch_rxon.switch_in_progress) - ieee80211_chswitch_done(ctx->vif, false); IWL_DEBUG_MAC80211(priv, "leave\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4653deada05b..213c80c6a668 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -843,12 +843,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (priv->switch_rxon.switch_in_progress) { + if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ieee80211_chswitch_done(ctx->vif, is_success); - mutex_lock(&priv->mutex); - priv->switch_rxon.switch_in_progress = false; - mutex_unlock(&priv->mutex); - } } #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 3bb76f6ea410..a54d416ec345 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -560,6 +560,7 @@ void iwlcore_free_geos(struct iwl_priv *priv); #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 #define STATUS_DEVICE_ENABLED 18 +#define STATUS_CHANNEL_SWITCH_PENDING 19 static inline int iwl_is_ready(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 22a6e3ec7094..c8de236c141b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -981,17 +981,6 @@ struct traffic_stats { #endif }; -/* - * iwl_switch_rxon: "channel switch" structure - * - * @ switch_in_progress: channel switch in progress - * @ channel: new channel - */ -struct iwl_switch_rxon { - bool switch_in_progress; - __le16 channel; -}; - /* * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds * to perform continuous uCode event logging operation if enabled @@ -1287,7 +1276,7 @@ struct iwl_priv { struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX]; - struct iwl_switch_rxon switch_rxon; + __le16 switch_channel; struct { u32 error_event_table; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 0053e9ea9021..b774517aa9fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -250,19 +250,19 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_cmd *rxon = (void *)&ctx->active; - if (priv->switch_rxon.switch_in_progress) { - if (!le32_to_cpu(csa->status) && - (csa->channel == priv->switch_rxon.channel)) { - rxon->channel = csa->channel; - ctx->staging.channel = csa->channel; - IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", - le16_to_cpu(csa->channel)); - iwl_chswitch_done(priv, true); - } else { - IWL_ERR(priv, "CSA notif (fail) : channel %d\n", + if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + return; + + if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { + rxon->channel = csa->channel; + ctx->staging.channel = csa->channel; + IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", le16_to_cpu(csa->channel)); - iwl_chswitch_done(priv, false); - } + iwl_chswitch_done(priv, true); + } else { + IWL_ERR(priv, "CSA notif (fail) : channel %d\n", + le16_to_cpu(csa->channel)); + iwl_chswitch_done(priv, false); } } -- cgit v1.2.3 From 59e7e7078d6c2c6294caf454c6e3695f9d3e46a2 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 2 Jun 2011 17:28:37 -0300 Subject: mac80211: call dev_alloc_name before copying name to sdata This partially reverts 1c5cae815d19ffe02bdfda1260949ef2b1806171, because the netdev name is copied into sdata->name, which is used for debugging messages, for example. Otherwise, we get messages like this: wlan%d: authenticated Signed-off-by: Thadeu Lima de Souza Cascardo Cc: Jiri Pirko Cc: David S. Miller Cc: Johannes Berg Cc: "John W. Linville" Signed-off-by: John W. Linville --- net/mac80211/iface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 49d4f869e0bc..dee30aea9ab3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1145,6 +1145,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, + IEEE80211_ENCRYPT_HEADROOM; ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; + ret = dev_alloc_name(ndev, ndev->name); + if (ret < 0) + goto fail; + ieee80211_assign_perm_addr(local, ndev, type); memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); -- cgit v1.2.3 From d2ac49fe3c7c4730323c1042fb53a2e008643b6a Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 3 Jun 2011 00:13:26 +0100 Subject: libertas_sdio: handle spurious interrupts Commit 06e8935febe687e2a561707d4c7ca4245d261dbe adds an IRQ handling optimization for single-function SDIO cards like this one, but at the same time exposes a small hardware bug. During hardware init, an interrupt is generated with (apparently) no source. Previously, mmc threw this interrupt away, but now (due to the optimization), the mmc layer passes this onto libertas, before it is ready (and before it has enabled interrupts), causing a crash. Work around this hardware bug by registering the IRQ handler later and making it capable of handling interrupts with no cause. The change that makes the IRQ handler registration happen later actually eliminates the spurious interrupt as well. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index a7b5cb0c2753..224e9853c480 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -907,7 +907,7 @@ static void if_sdio_interrupt(struct sdio_func *func) card = sdio_get_drvdata(func); cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret); - if (ret) + if (ret || !cause) goto out; lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause); @@ -1008,10 +1008,6 @@ static int if_sdio_probe(struct sdio_func *func, if (ret) goto release; - ret = sdio_claim_irq(func, if_sdio_interrupt); - if (ret) - goto disable; - /* For 1-bit transfers to the 8686 model, we need to enable the * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 * bit to allow access to non-vendor registers. */ @@ -1082,6 +1078,21 @@ static int if_sdio_probe(struct sdio_func *func, else card->rx_unit = 0; + /* + * Set up the interrupt handler late. + * + * If we set it up earlier, the (buggy) hardware generates a spurious + * interrupt, even before the interrupt has been enabled, with + * CCCR_INTx = 0. + * + * We register the interrupt handler late so that we can handle any + * spurious interrupts, and also to avoid generation of that known + * spurious interrupt in the first place. + */ + ret = sdio_claim_irq(func, if_sdio_interrupt); + if (ret) + goto disable; + /* * Enable interrupts now that everything is set up */ -- cgit v1.2.3 From f8d8e12dd1e0e2559e2419b7acdaf9eee9865736 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Fri, 3 Jun 2011 12:34:14 +0530 Subject: ARM: S5P: Fix compilation error for exynos4_defconfig Added Kconfig entry for setup-usb-phy.c on which EHCI support is dependent on. Following the naming convention of other setup files, we have following renaming. usb-phy.c ==> setup-usb-phy.c Signed-off-by: Tushar Behera Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/Kconfig | 6 ++ arch/arm/mach-exynos4/Makefile | 2 +- arch/arm/mach-exynos4/setup-usb-phy.c | 136 ++++++++++++++++++++++++++++++++++ arch/arm/mach-exynos4/usb-phy.c | 136 ---------------------------------- 4 files changed, 143 insertions(+), 137 deletions(-) create mode 100644 arch/arm/mach-exynos4/setup-usb-phy.c delete mode 100644 arch/arm/mach-exynos4/usb-phy.c diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig index b92c1e557145..1435fc31c4b2 100644 --- a/arch/arm/mach-exynos4/Kconfig +++ b/arch/arm/mach-exynos4/Kconfig @@ -91,6 +91,11 @@ config EXYNOS4_SETUP_FIMC help Common setup code for the camera interfaces. +config EXYNOS4_SETUP_USB_PHY + bool + help + Common setup code for USB PHY controller + # machine support menu "EXYNOS4 Machines" @@ -176,6 +181,7 @@ config MACH_NURI select EXYNOS4_SETUP_I2C3 select EXYNOS4_SETUP_I2C5 select EXYNOS4_SETUP_SDHCI + select EXYNOS4_SETUP_USB_PHY select SAMSUNG_DEV_PWM help Machine support for Samsung Mobile NURI Board. diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index a9bb94fabaa7..60fe5ecf3599 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -56,4 +56,4 @@ obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o -obj-$(CONFIG_USB_SUPPORT) += usb-phy.o +obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY) += setup-usb-phy.o diff --git a/arch/arm/mach-exynos4/setup-usb-phy.c b/arch/arm/mach-exynos4/setup-usb-phy.c new file mode 100644 index 000000000000..0883c1b824b9 --- /dev/null +++ b/arch/arm/mach-exynos4/setup-usb-phy.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2011 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int exynos4_usb_phy1_init(struct platform_device *pdev) +{ + struct clk *otg_clk; + struct clk *xusbxti_clk; + u32 phyclk; + u32 rstcon; + int err; + + otg_clk = clk_get(&pdev->dev, "otg"); + if (IS_ERR(otg_clk)) { + dev_err(&pdev->dev, "Failed to get otg clock\n"); + return PTR_ERR(otg_clk); + } + + err = clk_enable(otg_clk); + if (err) { + clk_put(otg_clk); + return err; + } + + writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE, + S5P_USBHOST_PHY_CONTROL); + + /* set clock frequency for PLL */ + phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK; + + xusbxti_clk = clk_get(&pdev->dev, "xusbxti"); + if (xusbxti_clk && !IS_ERR(xusbxti_clk)) { + switch (clk_get_rate(xusbxti_clk)) { + case 12 * MHZ: + phyclk |= CLKSEL_12M; + break; + case 24 * MHZ: + phyclk |= CLKSEL_24M; + break; + default: + case 48 * MHZ: + /* default reference clock */ + break; + } + clk_put(xusbxti_clk); + } + + writel(phyclk, EXYNOS4_PHYCLK); + + /* floating prevention logic: disable */ + writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON); + + /* set to normal HSIC 0 and 1 of PHY1 */ + writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK), + EXYNOS4_PHYPWR); + + /* set to normal standard USB of PHY1 */ + writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR); + + /* reset all ports of both PHY and Link */ + rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK | + PHY1_SWRST_MASK; + writel(rstcon, EXYNOS4_RSTCON); + udelay(10); + + rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK); + writel(rstcon, EXYNOS4_RSTCON); + udelay(50); + + clk_disable(otg_clk); + clk_put(otg_clk); + + return 0; +} + +static int exynos4_usb_phy1_exit(struct platform_device *pdev) +{ + struct clk *otg_clk; + int err; + + otg_clk = clk_get(&pdev->dev, "otg"); + if (IS_ERR(otg_clk)) { + dev_err(&pdev->dev, "Failed to get otg clock\n"); + return PTR_ERR(otg_clk); + } + + err = clk_enable(otg_clk); + if (err) { + clk_put(otg_clk); + return err; + } + + writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN), + EXYNOS4_PHYPWR); + + writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE, + S5P_USBHOST_PHY_CONTROL); + + clk_disable(otg_clk); + clk_put(otg_clk); + + return 0; +} + +int s5p_usb_phy_init(struct platform_device *pdev, int type) +{ + if (type == S5P_USB_PHY_HOST) + return exynos4_usb_phy1_init(pdev); + + return -EINVAL; +} + +int s5p_usb_phy_exit(struct platform_device *pdev, int type) +{ + if (type == S5P_USB_PHY_HOST) + return exynos4_usb_phy1_exit(pdev); + + return -EINVAL; +} diff --git a/arch/arm/mach-exynos4/usb-phy.c b/arch/arm/mach-exynos4/usb-phy.c deleted file mode 100644 index 0883c1b824b9..000000000000 --- a/arch/arm/mach-exynos4/usb-phy.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int exynos4_usb_phy1_init(struct platform_device *pdev) -{ - struct clk *otg_clk; - struct clk *xusbxti_clk; - u32 phyclk; - u32 rstcon; - int err; - - otg_clk = clk_get(&pdev->dev, "otg"); - if (IS_ERR(otg_clk)) { - dev_err(&pdev->dev, "Failed to get otg clock\n"); - return PTR_ERR(otg_clk); - } - - err = clk_enable(otg_clk); - if (err) { - clk_put(otg_clk); - return err; - } - - writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE, - S5P_USBHOST_PHY_CONTROL); - - /* set clock frequency for PLL */ - phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK; - - xusbxti_clk = clk_get(&pdev->dev, "xusbxti"); - if (xusbxti_clk && !IS_ERR(xusbxti_clk)) { - switch (clk_get_rate(xusbxti_clk)) { - case 12 * MHZ: - phyclk |= CLKSEL_12M; - break; - case 24 * MHZ: - phyclk |= CLKSEL_24M; - break; - default: - case 48 * MHZ: - /* default reference clock */ - break; - } - clk_put(xusbxti_clk); - } - - writel(phyclk, EXYNOS4_PHYCLK); - - /* floating prevention logic: disable */ - writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON); - - /* set to normal HSIC 0 and 1 of PHY1 */ - writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK), - EXYNOS4_PHYPWR); - - /* set to normal standard USB of PHY1 */ - writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR); - - /* reset all ports of both PHY and Link */ - rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK | - PHY1_SWRST_MASK; - writel(rstcon, EXYNOS4_RSTCON); - udelay(10); - - rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK); - writel(rstcon, EXYNOS4_RSTCON); - udelay(50); - - clk_disable(otg_clk); - clk_put(otg_clk); - - return 0; -} - -static int exynos4_usb_phy1_exit(struct platform_device *pdev) -{ - struct clk *otg_clk; - int err; - - otg_clk = clk_get(&pdev->dev, "otg"); - if (IS_ERR(otg_clk)) { - dev_err(&pdev->dev, "Failed to get otg clock\n"); - return PTR_ERR(otg_clk); - } - - err = clk_enable(otg_clk); - if (err) { - clk_put(otg_clk); - return err; - } - - writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN), - EXYNOS4_PHYPWR); - - writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE, - S5P_USBHOST_PHY_CONTROL); - - clk_disable(otg_clk); - clk_put(otg_clk); - - return 0; -} - -int s5p_usb_phy_init(struct platform_device *pdev, int type) -{ - if (type == S5P_USB_PHY_HOST) - return exynos4_usb_phy1_init(pdev); - - return -EINVAL; -} - -int s5p_usb_phy_exit(struct platform_device *pdev, int type) -{ - if (type == S5P_USB_PHY_HOST) - return exynos4_usb_phy1_exit(pdev); - - return -EINVAL; -} -- cgit v1.2.3 From 80839a19804702df2f24ebf24899579fd2ab6d9d Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 2 Jun 2011 18:30:52 +0900 Subject: ARM: EXYNOS4: Remove compiler warning on exynos4_pwm4_resume Remove compiler warning when no CONFIG_PM arch/arm/mach-exynos4/time.c:209: warning: 'exynos4_pwm4_resume' defined but not used Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/time.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c index 86b9fa0d3639..ebb8f38d5405 100644 --- a/arch/arm/mach-exynos4/time.c +++ b/arch/arm/mach-exynos4/time.c @@ -206,6 +206,7 @@ static cycle_t exynos4_pwm4_read(struct clocksource *cs) return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40)); } +#ifdef CONFIG_PM static void exynos4_pwm4_resume(struct clocksource *cs) { unsigned long pclk; @@ -218,6 +219,7 @@ static void exynos4_pwm4_resume(struct clocksource *cs) exynos4_pwm_init(4, ~0); exynos4_pwm_start(4, 1); } +#endif struct clocksource pwm_clocksource = { .name = "pwm_timer4", -- cgit v1.2.3 From 74cdfa538d433dde9720ae02ac48a7be8c0ec3fb Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 2 Jun 2011 18:27:27 +0900 Subject: ARM: SAMSUNG: Remove unused onenand plat functions There's no place to use these functions. and actually no need to set the platform data. Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/dev-onenand.c | 12 ------------ arch/arm/plat-samsung/dev-onenand.c | 12 ------------ 2 files changed, 24 deletions(-) diff --git a/arch/arm/plat-s5p/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c index 6db926202caa..20336c8f2479 100644 --- a/arch/arm/plat-s5p/dev-onenand.c +++ b/arch/arm/plat-s5p/dev-onenand.c @@ -15,8 +15,6 @@ #include #include -#include -#include #include #include @@ -45,13 +43,3 @@ struct platform_device s5p_device_onenand = { .num_resources = ARRAY_SIZE(s5p_onenand_resources), .resource = s5p_onenand_resources, }; - -void s5p_onenand_set_platdata(struct onenand_platform_data *pdata) -{ - struct onenand_platform_data *pd; - - pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL); - if (!pd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - s5p_device_onenand.dev.platform_data = pd; -} diff --git a/arch/arm/plat-samsung/dev-onenand.c b/arch/arm/plat-samsung/dev-onenand.c index 45ec73287d8c..f54ae71f0cd2 100644 --- a/arch/arm/plat-samsung/dev-onenand.c +++ b/arch/arm/plat-samsung/dev-onenand.c @@ -13,8 +13,6 @@ #include #include -#include -#include #include #include @@ -43,13 +41,3 @@ struct platform_device s3c_device_onenand = { .num_resources = ARRAY_SIZE(s3c_onenand_resources), .resource = s3c_onenand_resources, }; - -void s3c_onenand_set_platdata(struct onenand_platform_data *pdata) -{ - struct onenand_platform_data *pd; - - pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL); - if (!pd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - s3c_device_onenand.dev.platform_data = pd; -} -- cgit v1.2.3 From e4698188444a639ac9a3cfb3e06006dd1d4e7fcc Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 2 Jun 2011 12:56:39 +0200 Subject: ARM: S3C24xx: Fix missing struct for s3c2410_dma_chan s3c2410_dma_chan is not a type itself, so struct is required. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/plat-s3c24xx/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index c10d10c56e2e..2abf9660bc6c 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1199,7 +1199,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition); #ifdef CONFIG_PM -static void s3c2410_dma_suspend_chan(s3c2410_dma_chan *cp) +static void s3c2410_dma_suspend_chan(struct s3c2410_dma_chan *cp) { printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); -- cgit v1.2.3 From de11c5852811665e581ef0b915bb478f38b92fb1 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 2 Jun 2011 12:57:41 +0200 Subject: ARM: S3C24XX: Move s3c24xx_irq_syscore_ops to plat-s3c24xx/irq.c s3c24xx_irq_syscore_ops was only defined for s3c2410 cpus leading to compile errors on for example 2412 and 2416. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c2410/irq.c | 5 ----- arch/arm/plat-s3c24xx/irq.c | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index 2854129f8cc7..442869578fd0 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c @@ -27,8 +27,3 @@ #include #include - -struct syscore_ops s3c24xx_irq_syscore_ops = { - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, -}; diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 9aee7e1668b1..fc8c5f89954d 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -668,3 +669,8 @@ void __init s3c24xx_init_irq(void) irqdbf("s3c2410: registered interrupt handlers\n"); } + +struct syscore_ops s3c24xx_irq_syscore_ops = { + .suspend = s3c24xx_irq_suspend, + .resume = s3c24xx_irq_resume, +}; -- cgit v1.2.3 From 2aec0d697725bc4d402d7a9b51587af53a4cca76 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 2 Jun 2011 12:58:30 +0200 Subject: ARM: S3C2410: remove the now empty mach-s3c2410/irq.c Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c2410/Makefile | 1 - arch/arm/mach-s3c2410/irq.c | 29 ----------------------------- 2 files changed, 30 deletions(-) delete mode 100644 arch/arm/mach-s3c2410/irq.c diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 0d468e96e83e..81695353d8f4 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -10,7 +10,6 @@ obj-n := obj- := obj-$(CONFIG_CPU_S3C2410) += s3c2410.o -obj-$(CONFIG_CPU_S3C2410) += irq.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c deleted file mode 100644 index 442869578fd0..000000000000 --- a/arch/arm/mach-s3c2410/irq.c +++ /dev/null @@ -1,29 +0,0 @@ -/* linux/arch/arm/mach-s3c2410/irq.c - * - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ - -#include -#include -#include -#include -#include - -#include -#include -- cgit v1.2.3 From c316e6a3084cef1a5857cd66bb5429c969f06c93 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 5 Jun 2011 00:37:35 +0000 Subject: get_net_ns_by_fd() oopses if proc_ns_fget() returns an error BTW, looking through the code related to struct net lifetime rules has caught something else: struct net *get_net_ns_by_fd(int fd) { ... file = proc_ns_fget(fd); if (!file) goto out; ei = PROC_I(file->f_dentry->d_inode); while in proc_ns_fget() we have two return ERR_PTR(...) and not a single path that would return NULL. The other caller of proc_ns_fget() treats ERR_PTR() correctly... Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/core/net_namespace.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 6c6b86d0da15..e41e5110c65c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -310,19 +310,17 @@ struct net *get_net_ns_by_fd(int fd) struct file *file; struct net *net; - net = ERR_PTR(-EINVAL); file = proc_ns_fget(fd); - if (!file) - goto out; + if (IS_ERR(file)) + return ERR_CAST(file); ei = PROC_I(file->f_dentry->d_inode); - if (ei->ns_ops != &netns_operations) - goto out; + if (ei->ns_ops == &netns_operations) + net = get_net(ei->ns); + else + net = ERR_PTR(-EINVAL); - net = get_net(ei->ns); -out: - if (file) - fput(file); + fput(file); return net; } -- cgit v1.2.3 From b8f07a063163f8216cd891c5b007e839a56b6d93 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 5 Jun 2011 00:54:03 +0000 Subject: fix return values of l2tp_dfs_seq_open() More fallout from struct net lifetime rules review: PTR_ERR() is *already* negative and failing ->open() should return negatives on failure. Signed-off-by: Al Viro Signed-off-by: James Chapman Signed-off-by: David S. Miller --- net/l2tp/l2tp_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c index b8dbae82fab8..76130134bfa6 100644 --- a/net/l2tp/l2tp_debugfs.c +++ b/net/l2tp/l2tp_debugfs.c @@ -258,7 +258,7 @@ static int l2tp_dfs_seq_open(struct inode *inode, struct file *file) */ pd->net = get_net_ns_by_pid(current->pid); if (IS_ERR(pd->net)) { - rc = -PTR_ERR(pd->net); + rc = PTR_ERR(pd->net); goto err_free_pd; } -- cgit v1.2.3 From 54ff502c283b6cf77c95c05c99dbca40d910b17d Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 2 Jun 2011 12:42:21 +0000 Subject: qlcnic: Fix bug in FW queue dump Due to a change in FW template, a bug was introduced in dump queue entries. This is fixed by reinitializing queue address before looping for each que dump operation. Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index e9656616f2a2..a5d9fbf9d816 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -1406,6 +1406,7 @@ qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, for (loop = 0; loop < que->no_ops; loop++) { QLCNIC_WR_DUMP_REG(que->sel_addr, base, que_id); + addr = que->read_addr; for (i = 0; i < cnt; i++) { QLCNIC_RD_DUMP_REG(addr, base, &data); *buffer++ = cpu_to_le32(data); -- cgit v1.2.3 From 5b446c6a7179513edcb34706088c4ce901b9a039 Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Fri, 3 Jun 2011 05:52:18 +0000 Subject: qlcnic: Avoid double free of skb in tx path buffer->skb should be marked NULL to avoid double free of the skb. Signed-off-by: Sucheta Chakraborty Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 3ab7d2c7baf2..0f6af5c61a7c 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -2159,6 +2159,7 @@ qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb, nf = &pbuf->frag_array[0]; pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + pbuf->skb = NULL; } static inline void -- cgit v1.2.3 From 374eeb5a9d77ea719c5c46f4d70226623f4528ce Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 3 Jun 2011 10:35:52 +0000 Subject: bonding: reset queue mapping prior to transmission to physical device (v5) The bonding driver is multiqueue enabled, in which each queue represents a slave to enable optional steering of output frames to given slaves against the default output policy. However, it needs to reset the skb->queue_mapping prior to queuing to the physical device or the physical slave (if it is multiqueue) could wind up transmitting on an unintended tx queue Change Notes: v2) Based on first pass review, updated the patch to restore the origional queue mapping that was found in bond_select_queue, rather than simply resetting to zero. This preserves the value of queue_mapping when it was set on receive in the forwarding case which is desireable. v3) Fixed spelling an casting error in skb->cb v4) fixed to store raw queue_mapping to avoid double decrement v5) Eric D requested that ->cb access be wrapped in a macro. Signed-off-by: Neil Horman CC: Jay Vosburgh CC: Andy Gospodarek CC: "David S. Miller" Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 17b4dd94da90..652b30e525d0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -388,6 +388,8 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) return next; } +#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb)) + /** * bond_dev_queue_xmit - Prepare skb for xmit. * @@ -400,6 +402,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, { skb->dev = slave_dev; skb->priority = 1; + + skb->queue_mapping = bond_queue_mapping(skb); + if (unlikely(netpoll_tx_running(slave_dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); else @@ -4206,6 +4211,7 @@ static inline int bond_slave_override(struct bonding *bond, return res; } + static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) { /* @@ -4216,6 +4222,11 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) */ u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0; + /* + * Save the original txq to restore before passing to the driver + */ + bond_queue_mapping(skb) = skb->queue_mapping; + if (unlikely(txq >= dev->real_num_tx_queues)) { do { txq -= dev->real_num_tx_queues; -- cgit v1.2.3 From fb04883371f2cb7867d24783e7d590036dc9b548 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 May 2011 15:44:27 +0200 Subject: netfilter: add more values to enum ip_conntrack_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following error is raised (and other similar ones) : net/ipv4/netfilter/nf_nat_standalone.c: In function ‘nf_nat_fn’: net/ipv4/netfilter/nf_nat_standalone.c:119:2: warning: case value ‘4’ not in enumerated type ‘enum ip_conntrack_info’ gcc barfs on adding two enum values and getting a not enumerated result : case IP_CT_RELATED+IP_CT_IS_REPLY: Add missing enum values Signed-off-by: Eric Dumazet CC: David Miller Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nf_conntrack_common.h | 3 +++ net/ipv4/netfilter/ipt_CLUSTERIP.c | 6 +++--- net/ipv4/netfilter/ipt_MASQUERADE.c | 2 +- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 2 +- net/ipv4/netfilter/nf_nat_core.c | 2 +- net/ipv4/netfilter/nf_nat_rule.c | 2 +- net/ipv4/netfilter/nf_nat_standalone.c | 4 ++-- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 2 +- net/netfilter/nf_conntrack_core.c | 4 ++-- net/netfilter/nf_conntrack_ftp.c | 2 +- net/netfilter/nf_conntrack_h323_main.c | 10 ++++------ net/netfilter/nf_conntrack_irc.c | 3 +-- net/netfilter/nf_conntrack_pptp.c | 3 +-- net/netfilter/nf_conntrack_sane.c | 2 +- net/netfilter/nf_conntrack_sip.c | 2 +- net/netfilter/xt_socket.c | 4 ++-- 16 files changed, 26 insertions(+), 27 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 50cdc2559a5a..0d3dd66322ec 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -18,6 +18,9 @@ enum ip_conntrack_info { /* >= this indicates reply direction */ IP_CT_IS_REPLY, + IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY, + IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY, + IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY, /* Number of distinct IP_CT types (no NEW in reply dirn). */ IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 }; diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index d609ac3cb9a4..5c9e97c79017 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -307,7 +307,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) * error messages (RELATED) and information requests (see below) */ if (ip_hdr(skb)->protocol == IPPROTO_ICMP && (ctinfo == IP_CT_RELATED || - ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)) + ctinfo == IP_CT_RELATED_REPLY)) return XT_CONTINUE; /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, @@ -321,12 +321,12 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) ct->mark = hash; break; case IP_CT_RELATED: - case IP_CT_RELATED+IP_CT_IS_REPLY: + case IP_CT_RELATED_REPLY: /* FIXME: we don't handle expectations at the * moment. they can arrive on a different node than * the master connection (e.g. FTP passive mode) */ case IP_CT_ESTABLISHED: - case IP_CT_ESTABLISHED+IP_CT_IS_REPLY: + case IP_CT_ESTABLISHED_REPLY: break; default: break; diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index d2ed9dc74ebc..9931152a78b5 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -60,7 +60,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) nat = nfct_nat(ct); NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || - ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); + ctinfo == IP_CT_RELATED_REPLY)); /* Source address is 0.0.0.0 - locally generated packet that is * probably not supposed to be masqueraded. diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 5a03c02af999..db10075dd88e 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -101,7 +101,7 @@ static unsigned int ipv4_confirm(unsigned int hooknum, /* This is where we call the helper: as the packet goes out. */ ct = nf_ct_get(skb, &ctinfo); - if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) + if (!ct || ctinfo == IP_CT_RELATED_REPLY) goto out; help = nfct_help(ct); diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 9c71b2755ce3..3346de5d94d0 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -433,7 +433,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, /* Must be RELATED */ NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED || - skb->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY); + skb->nfctinfo == IP_CT_RELATED_REPLY); /* Redirects on non-null nats must be dropped, else they'll start talking to each other without our translation, and be diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 21c30426480b..733c9abc1cbd 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -53,7 +53,7 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par) /* Connection must be valid and new. */ NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || - ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); + ctinfo == IP_CT_RELATED_REPLY)); NF_CT_ASSERT(par->out != NULL); return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 7317bdf1d457..483b76d042da 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -116,7 +116,7 @@ nf_nat_fn(unsigned int hooknum, switch (ctinfo) { case IP_CT_RELATED: - case IP_CT_RELATED+IP_CT_IS_REPLY: + case IP_CT_RELATED_REPLY: if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { if (!nf_nat_icmp_reply_translation(ct, ctinfo, hooknum, skb)) @@ -144,7 +144,7 @@ nf_nat_fn(unsigned int hooknum, default: /* ESTABLISHED */ NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || - ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); + ctinfo == IP_CT_ESTABLISHED_REPLY); } return nf_nat_packet(ct, ctinfo, hooknum, skb); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c8af58b22562..4111050a9fc5 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -160,7 +160,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, /* This is where we call the helper: as the packet goes out. */ ct = nf_ct_get(skb, &ctinfo); - if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) + if (!ct || ctinfo == IP_CT_RELATED_REPLY) goto out; help = nfct_help(ct); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 2e1c11f78419..0bd568929403 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -850,7 +850,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, /* It exists; we have (non-exclusive) reference. */ if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) { - *ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY; + *ctinfo = IP_CT_ESTABLISHED_REPLY; /* Please set reply bit if this packet OK */ *set_reply = 1; } else { @@ -1143,7 +1143,7 @@ static void nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb) /* This ICMP is in reverse direction to the packet which caused it */ ct = nf_ct_get(skb, &ctinfo); if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) - ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY; + ctinfo = IP_CT_RELATED_REPLY; else ctinfo = IP_CT_RELATED; diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index e17cb7c7dd8f..6f5801eac999 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -368,7 +368,7 @@ static int help(struct sk_buff *skb, /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + ctinfo != IP_CT_ESTABLISHED_REPLY) { pr_debug("ftp: Conntrackinfo = %u\n", ctinfo); return NF_ACCEPT; } diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 18b2ce5c8ced..f03c2d4539f6 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -571,10 +571,9 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, int ret; /* Until there's been traffic both ways, don't look in packets. */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; - } + pr_debug("nf_ct_h245: skblen = %u\n", skb->len); spin_lock_bh(&nf_h323_lock); @@ -1125,10 +1124,9 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff, int ret; /* Until there's been traffic both ways, don't look in packets. */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; - } + pr_debug("nf_ct_q931: skblen = %u\n", skb->len); spin_lock_bh(&nf_h323_lock); diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index b394aa318776..4f9390b98697 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -125,8 +125,7 @@ static int help(struct sk_buff *skb, unsigned int protoff, return NF_ACCEPT; /* Until there's been traffic both ways, don't look in packets. */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; /* Not a full tcp header? */ diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 088944824e13..2fd4565144de 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -519,8 +519,7 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff, u_int16_t msg; /* don't do any tracking before tcp handshake complete */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; nexthdr_off = protoff; diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index d9e27734b2a2..8501823b3f9b 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -78,7 +78,7 @@ static int help(struct sk_buff *skb, ct_sane_info = &nfct_help(ct)->help.ct_sane_info; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) + ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; /* Not a full tcp header? */ diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index cb5a28581782..93faf6a3a637 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1423,7 +1423,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust; if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; /* No Data ? */ diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 9cc46356b577..fe39f7e913df 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -143,9 +143,9 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, ct = nf_ct_get(skb, &ctinfo); if (ct && !nf_ct_is_untracked(ct) && ((iph->protocol != IPPROTO_ICMP && - ctinfo == IP_CT_IS_REPLY + IP_CT_ESTABLISHED) || + ctinfo == IP_CT_ESTABLISHED_REPLY) || (iph->protocol == IPPROTO_ICMP && - ctinfo == IP_CT_IS_REPLY + IP_CT_RELATED)) && + ctinfo == IP_CT_RELATED_REPLY)) && (ct->status & IPS_SRC_NAT_DONE)) { daddr = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; -- cgit v1.2.3 From afb523c54718da57ff661950bd3287ec9eeb66bd Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Thu, 2 Jun 2011 09:09:54 +0900 Subject: ipvs: restore support for iptables SNAT Fix the IPVS priority in LOCAL_IN hook, so that SNAT target in POSTROUTING is supported for IPVS traffic as in 2.6.36 where it worked depending on module load order. Before 2.6.37 we used priority 100 in LOCAL_IN to process remote requests. We used the same priority as iptables SNAT and if IPVS handlers are installed before SNAT handlers we supported SNAT in POSTROUTING for the IPVS traffic. If SNAT is installed before IPVS, the netfilter handlers are before IPVS and netfilter checks the NAT table twice for the IPVS requests: once in LOCAL_IN where IPS_SRC_NAT_DONE is set and second time in POSTROUTING where the SNAT rules are ignored because IPS_SRC_NAT_DONE was already set in LOCAL_IN. But in 2.6.37 we changed the IPVS priority for LOCAL_IN with the goal to be unique (101) forgetting the fact that for IPVS traffic we should not walk both LOCAL_IN and POSTROUTING nat tables. So, change the priority for processing remote IPVS requests from 101 to 99, i.e. before NAT_SRC (100) because we prefer to support SNAT in POSTROUTING instead of LOCAL_IN. It also moves the priority for IPVS replies from 99 to 98. Use constants instead of magic numbers at these places. Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index bfa808f4da13..55af2242bccd 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1772,7 +1772,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_IN, - .priority = 99, + .priority = NF_IP_PRI_NAT_SRC - 2, }, /* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be @@ -1782,7 +1782,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_IN, - .priority = 101, + .priority = NF_IP_PRI_NAT_SRC - 1, }, /* Before ip_vs_in, change source only for VS/NAT */ { @@ -1790,7 +1790,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_OUT, - .priority = -99, + .priority = NF_IP_PRI_NAT_DST + 1, }, /* After mangle, schedule and forward local requests */ { @@ -1798,7 +1798,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_OUT, - .priority = -98, + .priority = NF_IP_PRI_NAT_DST + 2, }, /* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ @@ -1824,7 +1824,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_LOCAL_IN, - .priority = 99, + .priority = NF_IP6_PRI_NAT_SRC - 2, }, /* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be @@ -1834,7 +1834,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_LOCAL_IN, - .priority = 101, + .priority = NF_IP6_PRI_NAT_SRC - 1, }, /* Before ip_vs_in, change source only for VS/NAT */ { @@ -1842,7 +1842,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_OUT, - .priority = -99, + .priority = NF_IP6_PRI_NAT_DST + 1, }, /* After mangle, schedule and forward local requests */ { @@ -1850,7 +1850,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_LOCAL_OUT, - .priority = -98, + .priority = NF_IP6_PRI_NAT_DST + 2, }, /* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ -- cgit v1.2.3 From fcbf12817100d23890832801507107718a1fa448 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 1 Jun 2011 23:35:48 +0200 Subject: netfilter: ipset: Fix return code for destroy when sets are in use Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipset/ip_set_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 8041befc6555..42aa64b6b0b1 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -767,7 +767,7 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb, if (!attr[IPSET_ATTR_SETNAME]) { for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] != NULL && ip_set_list[i]->ref) { - ret = IPSET_ERR_BUSY; + ret = -IPSET_ERR_BUSY; goto out; } } -- cgit v1.2.3 From b48e3c5c323fea08c12a340cbb8dcc8ca2431d5b Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 1 Jun 2011 23:35:49 +0200 Subject: netfilter: ipset: Use the stored first cidr value instead of '1' The stored cidr values are tried one after anoter. The boolean condition evaluated to '1' instead of the first stored cidr or the default host cidr. Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipset/ip_set_hash_ipportnet.c | 10 ++++++---- net/netfilter/ipset/ip_set_hash_net.c | 8 ++++++-- net/netfilter/ipset/ip_set_hash_netport.c | 6 ++++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 4743e5402522..565a7c5b8818 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -146,8 +146,9 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_ipportnet4_elem data = - { .cidr = h->nets[0].cidr || HOST_MASK }; + struct hash_ipportnet4_elem data = { + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; @@ -394,8 +395,9 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_ipportnet6_elem data = - { .cidr = h->nets[0].cidr || HOST_MASK }; + struct hash_ipportnet6_elem data = { + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index c4db202b7da4..2aeeabcd5a21 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c @@ -131,7 +131,9 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_net4_elem data = { .cidr = h->nets[0].cidr || HOST_MASK }; + struct hash_net4_elem data = { + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; @@ -296,7 +298,9 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_net6_elem data = { .cidr = h->nets[0].cidr || HOST_MASK }; + struct hash_net6_elem data = { + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index d2a40362dd3a..e50d9bb8820b 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c @@ -144,7 +144,8 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport4_elem data = { - .cidr = h->nets[0].cidr || HOST_MASK }; + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; @@ -357,7 +358,8 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport6_elem data = { - .cidr = h->nets[0].cidr || HOST_MASK }; + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; -- cgit v1.2.3 From d9be76f38526dccf84062e3ac3ed3a6a97698565 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sun, 29 May 2011 23:42:29 +0300 Subject: netfilter: nf_nat: fix crash in nf_nat_csum Fix crash in nf_nat_csum when mangling packets in OUTPUT hook where skb->dev is not defined, it is set later before POSTROUTING. Problem happens for CHECKSUM_NONE. We can check device from rt but using CHECKSUM_PARTIAL should be safe (skb_checksum_help). Signed-off-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/nf_nat_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 99cfa28b6d38..ebc5f8894f99 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -160,7 +160,7 @@ static void nf_nat_csum(struct sk_buff *skb, const struct iphdr *iph, void *data if (skb->ip_summed != CHECKSUM_PARTIAL) { if (!(rt->rt_flags & RTCF_LOCAL) && - skb->dev->features & NETIF_F_V4_CSUM) { + (!skb->dev || skb->dev->features & NETIF_F_V4_CSUM)) { skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + -- cgit v1.2.3 From 88ed01d17b44bc2bed4ad4835d3b1099bff3dd71 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 2 Jun 2011 15:08:45 +0200 Subject: netfilter: nf_conntrack: fix ct refcount leak in l4proto->error() This patch fixes a refcount leak of ct objects that may occur if l4proto->error() assigns one conntrack object to one skbuff. In that case, we have to skip further processing in nf_conntrack_in(). With this patch, we can also fix wrong return values (-NF_ACCEPT) for special cases in ICMP[v6] that should not bump the invalid/error statistic counters. Reported-by: Zoltan Menyhart Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 2 +- net/netfilter/nf_conntrack_core.c | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 7404bde95994..ab5b27a2916f 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -160,7 +160,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, /* Update skb to refer to this connection */ skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; skb->nfctinfo = *ctinfo; - return -NF_ACCEPT; + return NF_ACCEPT; } /* Small and modified version of icmp_rcv */ diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 1df3c8b6bf47..7c05e7eacbc6 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -177,7 +177,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl, /* Update skb to refer to this connection */ skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; skb->nfctinfo = *ctinfo; - return -NF_ACCEPT; + return NF_ACCEPT; } static int diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0bd568929403..f7af8b866017 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -922,6 +922,9 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, ret = -ret; goto out; } + /* ICMP[v6] protocol trackers may assign one conntrack. */ + if (skb->nfct) + goto out; } ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, -- cgit v1.2.3 From d232b8dded624af3e346b13807a591c63b601c44 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 27 May 2011 20:36:51 -0400 Subject: netfilter: use unsigned variables for packet lengths in ip[6]_queue. Netlink message lengths can't be negative, so use unsigned variables. Signed-off-by: Dave Jones Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/ip_queue.c | 3 ++- net/ipv6/netfilter/ip6_queue.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index d2c1311cb28d..f7f9bd7ba12d 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -402,7 +402,8 @@ ipq_dev_drop(int ifindex) static inline void __ipq_rcv_skb(struct sk_buff *skb) { - int status, type, pid, flags, nlmsglen, skblen; + int status, type, pid, flags; + unsigned int nlmsglen, skblen; struct nlmsghdr *nlh; skblen = skb->len; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 413ab0754e1f..065fe405fb58 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -403,7 +403,8 @@ ipq_dev_drop(int ifindex) static inline void __ipq_rcv_skb(struct sk_buff *skb) { - int status, type, pid, flags, nlmsglen, skblen; + int status, type, pid, flags; + unsigned int nlmsglen, skblen; struct nlmsghdr *nlh; skblen = skb->len; -- cgit v1.2.3 From 5fb9fb132c5a83010cd8d4bf6d0ee34fb3b9d488 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 3 Jun 2011 21:31:27 +0000 Subject: net: fix smc91x.c device tree support Fix missing semicolon at end of smc91x.c match tabledevice driver. Also remove unnecessary #ifdef around of_match_table pointer. Signed-off-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/smc91x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index dc4805f473e3..f6285748bd3c 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -2400,8 +2400,10 @@ static const struct of_device_id smc91x_match[] = { { .compatible = "smsc,lan91c94", }, { .compatible = "smsc,lan91c111", }, {}, -} +}; MODULE_DEVICE_TABLE(of, smc91x_match); +#else +#define smc91x_match NULL #endif static struct dev_pm_ops smc_drv_pm_ops = { @@ -2416,9 +2418,7 @@ static struct platform_driver smc_driver = { .name = CARDNAME, .owner = THIS_MODULE, .pm = &smc_drv_pm_ops, -#ifdef CONFIG_OF .of_match_table = smc91x_match, -#endif }, }; -- cgit v1.2.3 From 5def1360252b974faeb438775c19c14338bc1903 Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Sun, 5 Jun 2011 23:26:40 -0400 Subject: ext4: correct comments for ext4_free_blocks() metadata is not parameter of ext4_free_blocks() any more. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 859f2ae8864e..eb71dd59f2e4 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4448,7 +4448,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, * @inode: inode * @block: start physical block to free * @count: number of blocks to count - * @metadata: Are these metadata blocks + * @flags: flags used by ext4_free_blocks */ void ext4_free_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh, ext4_fsblk_t block, -- cgit v1.2.3 From 298c48a811673ba5e292359545f3af6d1a6c9764 Mon Sep 17 00:00:00 2001 From: Srinivas KANDAGATLA Date: Thu, 2 Jun 2011 10:30:44 +0000 Subject: sh: fix wrong icache/dcache address-array start addr in cache-debugfs. This patch fixes a icache/dcache address-array start address while dumping its entires in debugfs. Perviously the code was attempting to remember the address in static variable, which is no more required for debugfs, as the function can be executed in one pass. Without this patch the start address ends up in wrong place and the /sys/kernel/debug/sh/icache or dcache debugfs contents may not be correct. Signed-off-by: Srinivas Kandagatla Cc: Stuart Menefy Signed-off-by: Paul Mundt --- arch/sh/mm/cache-debugfs.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c index 52411462c409..115725198038 100644 --- a/arch/sh/mm/cache-debugfs.c +++ b/arch/sh/mm/cache-debugfs.c @@ -26,9 +26,9 @@ static int cache_seq_show(struct seq_file *file, void *iter) { unsigned int cache_type = (unsigned int)file->private; struct cache_info *cache; - unsigned int waysize, way, cache_size; - unsigned long ccr, base; - static unsigned long addrstart = 0; + unsigned int waysize, way; + unsigned long ccr; + unsigned long addrstart = 0; /* * Go uncached immediately so we don't skew the results any @@ -45,28 +45,13 @@ static int cache_seq_show(struct seq_file *file, void *iter) } if (cache_type == CACHE_TYPE_DCACHE) { - base = CACHE_OC_ADDRESS_ARRAY; + addrstart = CACHE_OC_ADDRESS_ARRAY; cache = ¤t_cpu_data.dcache; } else { - base = CACHE_IC_ADDRESS_ARRAY; + addrstart = CACHE_IC_ADDRESS_ARRAY; cache = ¤t_cpu_data.icache; } - /* - * Due to the amount of data written out (depending on the cache size), - * we may be iterated over multiple times. In this case, keep track of - * the entry position in addrstart, and rewind it when we've hit the - * end of the cache. - * - * Likewise, the same code is used for multiple caches, so care must - * be taken for bouncing addrstart back and forth so the appropriate - * cache is hit. - */ - cache_size = cache->ways * cache->sets * cache->linesz; - if (((addrstart & 0xff000000) != base) || - (addrstart & 0x00ffffff) > cache_size) - addrstart = base; - waysize = cache->sets; /* -- cgit v1.2.3 From ab4bd22d3cce6977dc039664cc2d052e3147d662 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 5 Jun 2011 06:01:13 +0200 Subject: cfq-iosched: fix locking around ioc->ioc_data assignment Since we are modifying this RCU pointer, we need to hold the lock protecting it around it. This fixes a potential reuse and double free of a cfq io_context structure. The bug has been in CFQ for a long time, it hit very few people but those it did hit seemed to see it a lot. Tracked in RH bugzilla here: https://bugzilla.redhat.com/show_bug.cgi?id=577968 Credit goes to Paul Bolle for figuring out that the issue was around the one-hit ioc->ioc_data cache. Thanks to his hard work the issue is now fixed. Cc: stable@kernel.org Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3c7b537bf908..545b8d4c829d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2772,8 +2772,11 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, smp_wmb(); cic->key = cfqd_dead_key(cfqd); - if (ioc->ioc_data == cic) + if (rcu_dereference(ioc->ioc_data) == cic) { + spin_lock(&ioc->lock); rcu_assign_pointer(ioc->ioc_data, NULL); + spin_unlock(&ioc->lock); + } if (cic->cfqq[BLK_RW_ASYNC]) { cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); -- cgit v1.2.3 From f17722f917b2f21497deb6edc62fb1683daa08e6 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Mon, 6 Jun 2011 00:05:17 -0400 Subject: ext4: Fix max file size and logical block counting of extent format file Kazuya Mio reported that he was able to hit BUG_ON(next == lblock) in ext4_ext_put_gap_in_cache() while creating a sparse file in extent format and fill the tail of file up to its end. We will hit the BUG_ON when we write the last block (2^32-1) into the sparse file. The root cause of the problem lies in the fact that we specifically set s_maxbytes so that block at s_maxbytes fit into on-disk extent format, which is 32 bit long. However, we are not storing start and end block number, but rather start block number and length in blocks. It means that in order to cover extent from 0 to EXT_MAX_BLOCK we need EXT_MAX_BLOCK+1 to fit into len (because we counting block 0 as well) - and it does not. The only way to fix it without changing the meaning of the struct ext4_extent members is, as Kazuya Mio suggested, to lower s_maxbytes by one fs block so we can cover the whole extent we can get by the on-disk extent format. Also in many places EXT_MAX_BLOCK is used as length instead of maximum logical block number as the name suggests, it is all a bit messy. So this commit renames it to EXT_MAX_BLOCKS and change its usage in some places to actually be maximum number of blocks in the extent. The bug which this commit fixes can be reproduced as follows: dd if=/dev/zero of=/mnt/mp1/file bs= count=1 seek=$((2**32-2)) sync dd if=/dev/zero of=/mnt/mp1/file bs= count=1 seek=$((2**32-1)) Reported-by: Kazuya Mio Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/ext4_extents.h | 7 +++++-- fs/ext4/extents.c | 34 +++++++++++++++++----------------- fs/ext4/move_extent.c | 10 +++++----- fs/ext4/super.c | 15 ++++++++++++--- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 2e29abb30f76..476414644387 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h @@ -133,8 +133,11 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *, #define EXT_BREAK 1 #define EXT_REPEAT 2 -/* Maximum logical block in a file; ext4_extent's ee_block is __le32 */ -#define EXT_MAX_BLOCK 0xffffffff +/* + * Maximum number of logical blocks in a file; ext4_extent's ee_block is + * __le32. + */ +#define EXT_MAX_BLOCKS 0xffffffff /* * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 5199bac7fc62..41575704600a 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1408,7 +1408,7 @@ got_index: /* * ext4_ext_next_allocated_block: - * returns allocated block in subsequent extent or EXT_MAX_BLOCK. + * returns allocated block in subsequent extent or EXT_MAX_BLOCKS. * NOTE: it considers block number from index entry as * allocated block. Thus, index entries have to be consistent * with leaves. @@ -1422,7 +1422,7 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path) depth = path->p_depth; if (depth == 0 && path->p_ext == NULL) - return EXT_MAX_BLOCK; + return EXT_MAX_BLOCKS; while (depth >= 0) { if (depth == path->p_depth) { @@ -1439,12 +1439,12 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path) depth--; } - return EXT_MAX_BLOCK; + return EXT_MAX_BLOCKS; } /* * ext4_ext_next_leaf_block: - * returns first allocated block from next leaf or EXT_MAX_BLOCK + * returns first allocated block from next leaf or EXT_MAX_BLOCKS */ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, struct ext4_ext_path *path) @@ -1456,7 +1456,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, /* zero-tree has no leaf blocks at all */ if (depth == 0) - return EXT_MAX_BLOCK; + return EXT_MAX_BLOCKS; /* go to index block */ depth--; @@ -1469,7 +1469,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, depth--; } - return EXT_MAX_BLOCK; + return EXT_MAX_BLOCKS; } /* @@ -1677,13 +1677,13 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode, */ if (b2 < b1) { b2 = ext4_ext_next_allocated_block(path); - if (b2 == EXT_MAX_BLOCK) + if (b2 == EXT_MAX_BLOCKS) goto out; } /* check for wrap through zero on extent logical start block*/ if (b1 + len1 < b1) { - len1 = EXT_MAX_BLOCK - b1; + len1 = EXT_MAX_BLOCKS - b1; newext->ee_len = cpu_to_le16(len1); ret = 1; } @@ -1767,7 +1767,7 @@ repeat: fex = EXT_LAST_EXTENT(eh); next = ext4_ext_next_leaf_block(inode, path); if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block) - && next != EXT_MAX_BLOCK) { + && next != EXT_MAX_BLOCKS) { ext_debug("next leaf block - %d\n", next); BUG_ON(npath != NULL); npath = ext4_ext_find_extent(inode, next, NULL); @@ -1887,7 +1887,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, BUG_ON(func == NULL); BUG_ON(inode == NULL); - while (block < last && block != EXT_MAX_BLOCK) { + while (block < last && block != EXT_MAX_BLOCKS) { num = last - block; /* find extent for this block */ down_read(&EXT4_I(inode)->i_data_sem); @@ -2020,7 +2020,7 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, if (ex == NULL) { /* there is no extent yet, so gap is [0;-] */ lblock = 0; - len = EXT_MAX_BLOCK; + len = EXT_MAX_BLOCKS; ext_debug("cache gap(whole file):"); } else if (block < le32_to_cpu(ex->ee_block)) { lblock = block; @@ -2350,7 +2350,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, * never happen because at least one of the end points * needs to be on the edge of the extent. */ - if (end == EXT_MAX_BLOCK) { + if (end == EXT_MAX_BLOCKS - 1) { ext_debug(" bad truncate %u:%u\n", start, end); block = 0; @@ -2398,7 +2398,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, * If this is a truncate, this condition * should never happen */ - if (end == EXT_MAX_BLOCK) { + if (end == EXT_MAX_BLOCKS - 1) { ext_debug(" bad truncate %u:%u\n", start, end); err = -EIO; @@ -2478,7 +2478,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, * we need to remove it from the leaf */ if (num == 0) { - if (end != EXT_MAX_BLOCK) { + if (end != EXT_MAX_BLOCKS - 1) { /* * For hole punching, we need to scoot all the * extents up when an extent is removed so that @@ -3699,7 +3699,7 @@ void ext4_ext_truncate(struct inode *inode) last_block = (inode->i_size + sb->s_blocksize - 1) >> EXT4_BLOCK_SIZE_BITS(sb); - err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCK); + err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); /* In a multi-transaction truncate, we only make the final * transaction synchronous. @@ -4347,8 +4347,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, start_blk = start >> inode->i_sb->s_blocksize_bits; last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits; - if (last_blk >= EXT_MAX_BLOCK) - last_blk = EXT_MAX_BLOCK-1; + if (last_blk >= EXT_MAX_BLOCKS) + last_blk = EXT_MAX_BLOCKS-1; len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1; /* diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 2b8304bf3c50..f57455a1b1b2 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -1002,12 +1002,12 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } - if ((orig_start > EXT_MAX_BLOCK) || - (donor_start > EXT_MAX_BLOCK) || - (*len > EXT_MAX_BLOCK) || - (orig_start + *len > EXT_MAX_BLOCK)) { + if ((orig_start >= EXT_MAX_BLOCKS) || + (donor_start >= EXT_MAX_BLOCKS) || + (*len > EXT_MAX_BLOCKS) || + (orig_start + *len >= EXT_MAX_BLOCKS)) { ext4_debug("ext4 move extent: Can't handle over [%u] blocks " - "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCK, + "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCKS, orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cc5c157aa11d..9ea71aa864b3 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2243,6 +2243,12 @@ static void ext4_orphan_cleanup(struct super_block *sb, * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, * so that won't be a limiting factor. * + * However there is other limiting factor. We do store extents in the form + * of starting block and length, hence the resulting length of the extent + * covering maximum file size must fit into on-disk format containers as + * well. Given that length is always by 1 unit bigger than max unit (because + * we count 0 as well) we have to lower the s_maxbytes by one fs block. + * * Note, this does *not* consider any metadata overhead for vfs i_blocks. */ static loff_t ext4_max_size(int blkbits, int has_huge_files) @@ -2264,10 +2270,13 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files) upper_limit <<= blkbits; } - /* 32-bit extent-start container, ee_block */ - res = 1LL << 32; + /* + * 32-bit extent-start container, ee_block. We lower the maxbytes + * by one fs block, so ee_len can cover the extent of maximum file + * size + */ + res = (1LL << 32) - 1; res <<= blkbits; - res -= 1; /* Sanity check against vm- & vfs- imposed limits */ if (res > upper_limit) -- cgit v1.2.3 From c03f8aa9abdd517477c2021ea1251939b4da49e6 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Mon, 6 Jun 2011 00:06:52 -0400 Subject: ext4: use FIEMAP_EXTENT_LAST flag for last extent in fiemap Currently we are not marking the extent as the last one (FIEMAP_EXTENT_LAST) if there is a hole at the end of the file. This is because we just do not check for it right now and continue searching for next extent. But at the point we hit the hole at the end of the file, it is too late. This commit adds check for the allocated block in subsequent extent and if there is no more extents (block = EXT_MAX_BLOCKS) just flag the current one as the last one. This behaviour has been spotted unintentionally by 252 xfstest, when the test hangs out, because of wrong loop condition. However on other filesystems (like xfs) it will exit anyway, because we notice the last extent flag and exit. With this patch xfstest 252 does not hang anymore, ext4 fiemap implementation still reports bad extent type in some cases, however this seems to be different issue. Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/ext4_extents.h | 2 +- fs/ext4/extents.c | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 476414644387..095c36f3b612 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h @@ -125,7 +125,7 @@ struct ext4_ext_path { * positive retcode - signal for ext4_ext_walk_space(), see below * callback must return valid extent (passed or newly created) */ -typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *, +typedef int (*ext_prepare_callback)(struct inode *, ext4_lblk_t, struct ext4_ext_cache *, struct ext4_extent *, void *); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 41575704600a..f815cc81e7a2 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1958,7 +1958,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, err = -EIO; break; } - err = func(inode, path, &cbex, ex, cbdata); + err = func(inode, next, &cbex, ex, cbdata); ext4_ext_drop_refs(path); if (err < 0) @@ -3914,14 +3914,13 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, /* * Callback function called for each extent to gather FIEMAP information. */ -static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, +static int ext4_ext_fiemap_cb(struct inode *inode, ext4_lblk_t next, struct ext4_ext_cache *newex, struct ext4_extent *ex, void *data) { __u64 logical; __u64 physical; __u64 length; - loff_t size; __u32 flags = 0; int ret = 0; struct fiemap_extent_info *fieinfo = data; @@ -4103,8 +4102,7 @@ found_delayed_extent: if (ex && ext4_ext_is_uninitialized(ex)) flags |= FIEMAP_EXTENT_UNWRITTEN; - size = i_size_read(inode); - if (logical + length >= size) + if (next == EXT_MAX_BLOCKS) flags |= FIEMAP_EXTENT_LAST; ret = fiemap_fill_next_extent(fieinfo, logical, physical, -- cgit v1.2.3 From ad377c630864e2609c54385907493dbf68a34295 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 25 May 2011 11:34:57 +0200 Subject: arm: mxs: include asm/processor.h for cpu_relax() I get this build error as of today: arch/arm/mach-mxs/ocotp.c: In function 'mxs_get_ocotp': arch/arm/mach-mxs/ocotp.c:54: error: implicit declaration of function 'cpu_relax' make[2]: *** [arch/arm/mach-mxs/ocotp.o] Error 1 Looks like it has been indirectly included before which broke now. Include it directly. Signed-off-by: Wolfram Sang Cc: Shawn Guo Signed-off-by: Sascha Hauer --- arch/arm/mach-mxs/ocotp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c index 65157a35dbba..54add60f94c9 100644 --- a/arch/arm/mach-mxs/ocotp.c +++ b/arch/arm/mach-mxs/ocotp.c @@ -16,6 +16,8 @@ #include #include +#include /* for cpu_relax() */ + #include #define OCOTP_WORD_OFFSET 0x20 -- cgit v1.2.3 From 5f85e931278ff80aa3ea7861a73a6c6ce940f2e9 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 28 May 2011 16:05:08 -0300 Subject: ARM: mx51/sdma: Check the chip revision in run-time Check the MX51 chip revision in run-time so that the correct SDMA firmware can be loaded. While at it also remove the silicon revision from the sdma_script_start_addrs structure name for MX51. All the MX51 revisions share the same SDMA start addresses. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/devices/platform-imx-dma.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c index 3538b85ede91..b130f60ca6b7 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-dma.c +++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c @@ -139,7 +139,7 @@ static struct sdma_script_start_addrs addr_imx35_to2 = { #endif #ifdef CONFIG_SOC_IMX51 -static struct sdma_script_start_addrs addr_imx51_to1 = { +static struct sdma_script_start_addrs addr_imx51 = { .ap_2_ap_addr = 642, .uart_2_mcu_addr = 817, .mcu_2_app_addr = 747, @@ -196,7 +196,9 @@ static int __init imxXX_add_imx_dma(void) #if defined(CONFIG_SOC_IMX51) if (cpu_is_mx51()) { - imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51_to1; + int to_version = mx51_revision() >> 4; + imx51_imx_sdma_data.pdata.to_version = to_version; + imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51; ret = imx_add_imx_sdma(&imx51_imx_sdma_data); } else #endif -- cgit v1.2.3 From 363e9f05cbd105a900b7baf2cc55ec0cba546d08 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 6 Jun 2011 17:57:58 +0900 Subject: sh: Remove compressed kernel libgcc dependency. SH-2A is unable to combine the kernel and libgcc objects due to fundamental disagreements over FDPIC settings. As the kernel already contains all of the libgcc bits broken out, there's not much need to bother with the linking anymore, as everything can already be derived from the lib dir. This simply plugs in the necessary bits to ensure that everything is built uniformly, enabling us to wean the compressed build off of explicit libgcc linking. Reported-by: Phil Edworthy Signed-off-by: Paul Mundt --- arch/sh/boot/compressed/Makefile | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 780e083e4d17..23bc849d9c64 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -27,8 +27,6 @@ IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ $(CONFIG_BOOT_LINK_OFFSET)]') endif -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) - ifeq ($(CONFIG_MCOUNT),y) ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) @@ -37,7 +35,25 @@ endif LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(IMAGE_OFFSET) -e startup \ -T $(obj)/../../kernel/vmlinux.lds -$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE +# +# Pull in the necessary libgcc bits from the in-kernel implementation. +# +lib1funcs-$(CONFIG_SUPERH32) := ashiftrt.S ashldi3.c ashrsi3.S ashlsi3.S \ + lshrsi3.S +lib1funcs-obj := \ + $(addsuffix .o, $(basename $(addprefix $(obj)/, $(lib1funcs-y)))) + +lib1funcs-dir := $(srctree)/arch/$(SRCARCH)/lib +ifeq ($(BITS),64) + lib1funcs-dir := $(addsuffix $(BITS), $(lib1funcs-dir)) +endif + +KBUILD_CFLAGS += -I$(lib1funcs-dir) + +$(addprefix $(obj)/,$(lib1funcs-y)): $(obj)/%: $(lib1funcs-dir)/% FORCE + $(call cmd,shipped) + +$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(lib1funcs-obj) FORCE $(call if_changed,ld) @: -- cgit v1.2.3 From 2fdf99934c2c39848ad3633ce504a0262f21faf9 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 30 May 2011 19:44:22 +0100 Subject: ARM: 6946/1: vexpress: move v2m clock init to init_early Commit 7ff550de99141cbd3be0129d563cc4554fdde9f6 breaks vexpress booting. The v2m clock table needs to be setup in init_early before the timer initialization occurs. Signed-off-by: Rob Herring Signed-off-by: Russell King --- arch/arm/mach-vexpress/v2m.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 285edcd2da2a..9e6b93b1a043 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -46,12 +46,6 @@ static struct map_desc v2m_io_desc[] __initdata = { }, }; -static void __init v2m_init_early(void) -{ - ct_desc->init_early(); - versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); -} - static void __init v2m_timer_init(void) { u32 scctrl; @@ -365,6 +359,13 @@ static struct clk_lookup v2m_lookups[] = { }, }; +static void __init v2m_init_early(void) +{ + ct_desc->init_early(); + clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); + versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); +} + static void v2m_power_off(void) { if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0)) @@ -418,8 +419,6 @@ static void __init v2m_init(void) { int i; - clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); - platform_device_register(&v2m_pcie_i2c_device); platform_device_register(&v2m_ddc_i2c_device); platform_device_register(&v2m_flash_device); -- cgit v1.2.3 From 9425032b77c3a4f066a032bac7f7d08668b6cc3c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 31 May 2011 22:10:03 +0100 Subject: ARM: 6947/2: mach-u300: fix compilation error in timer The introduction of the mmio timer accidentally referenced the old clocksource struct which does not exist anymore. Fix this by using a simple string instead. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/timer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 891cf44591e0..18d7fa0603c2 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c @@ -411,8 +411,7 @@ static void __init u300_timer_init(void) /* Use general purpose timer 2 as clock source */ if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC, "GPT2", rate, 300, 32, clocksource_mmio_readl_up)) - printk(KERN_ERR "timer: failed to initialize clock " - "source %s\n", clocksource_u300_1mhz.name); + pr_err("timer: failed to initialize U300 clock source\n"); clockevents_calc_mult_shift(&clockevent_u300_1mhz, rate, APPTIMER_MIN_RANGE); -- cgit v1.2.3 From 9a819d8ac8197b44bbc2adad592b677fe749804d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 31 May 2011 08:09:39 +0100 Subject: ARM: 6948/1: Fix .size directives for __arm{7,9}tdmi_proc_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gas used to accept (and ignore?) .size directives which referred to undefined symbols, as these do. In binutils 2.21 these are treated as fatal errors. The issue in proc-arm7tdmi.S was also fixed independently by Peter Chubb. Signed-off-by: Ben Hutchings Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/mm/proc-arm7tdmi.S | 2 +- arch/arm/mm/proc-arm9tdmi.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S index e4c165ca6696..537ffcb0646d 100644 --- a/arch/arm/mm/proc-arm7tdmi.S +++ b/arch/arm/mm/proc-arm7tdmi.S @@ -146,7 +146,7 @@ __arm7tdmi_proc_info: .long 0 .long 0 .long v4_cache_fns - .size __arm7tdmi_proc_info, . - __arm7dmi_proc_info + .size __arm7tdmi_proc_info, . - __arm7tdmi_proc_info .type __triscenda7_proc_info, #object __triscenda7_proc_info: diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S index 7b7ebd4d096d..546b54da1005 100644 --- a/arch/arm/mm/proc-arm9tdmi.S +++ b/arch/arm/mm/proc-arm9tdmi.S @@ -116,7 +116,7 @@ __arm9tdmi_proc_info: .long 0 .long 0 .long v4_cache_fns - .size __arm9tdmi_proc_info, . - __arm9dmi_proc_info + .size __arm9tdmi_proc_info, . - __arm9tdmi_proc_info .type __p2001_proc_info, #object __p2001_proc_info: -- cgit v1.2.3 From 45f6d7e0e634d49744c1a590461ed1bb3d2201ac Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 2 Jun 2011 15:01:36 +0100 Subject: ARM: 6951/1: include .bss in memory layout information The "Virtual memory kernel layout" message at startup already prints .text and .data. Print .bss too. Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mm/init.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 2c2cce9cd8c8..b2cf9460ea60 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -635,7 +635,8 @@ void __init mem_init(void) " modules : 0x%08lx - 0x%08lx (%4ld MB)\n" " .init : 0x%p" " - 0x%p" " (%4d kB)\n" " .text : 0x%p" " - 0x%p" " (%4d kB)\n" - " .data : 0x%p" " - 0x%p" " (%4d kB)\n", + " .data : 0x%p" " - 0x%p" " (%4d kB)\n" + " .bss : 0x%p" " - 0x%p" " (%4d kB)\n", MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) + (PAGE_SIZE)), @@ -657,7 +658,8 @@ void __init mem_init(void) MLK_ROUNDUP(__init_begin, __init_end), MLK_ROUNDUP(_text, _etext), - MLK_ROUNDUP(_sdata, _edata)); + MLK_ROUNDUP(_sdata, _edata), + MLK_ROUNDUP(__bss_start, __bss_stop)); #undef MLK #undef MLM -- cgit v1.2.3 From 9fc2552a68eb28f95f367156cf46a3da7843ff37 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 5 Jun 2011 02:24:58 +0100 Subject: ARM: 6952/1: fix lockdep warning of "unannotated irqs-off" This patch fixes the lockdep warning of "unannotated irqs-off"[1]. After entering __irq_usr, arm core will disable interrupt automatically, but __irq_usr does not annotate the irq disable, so lockdep may complain the warning if it has chance to check this in irq handler. This patch adds trace_hardirqs_off in __irq_usr before entering irq_handler to handle the irq, also calls ret_to_user_from_irq to avoid calling disable_irq again. This is also a fix for irq off tracer. [1], lockdep warning log of "unannotated irqs-off" [ 13.804687] ------------[ cut here ]------------ [ 13.809570] WARNING: at kernel/lockdep.c:3335 check_flags+0x78/0x1d0() [ 13.816467] Modules linked in: [ 13.819732] Backtrace: [ 13.822357] [] (dump_backtrace+0x0/0x100) from [] (dump_stack+0x20/0x24) [ 13.831268] r6:c07d8c2c r5:00000d07 r4:00000000 r3:00000000 [ 13.837280] [] (dump_stack+0x0/0x24) from [] (warn_slowpath_common+0x5c/0x74) [ 13.846649] [] (warn_slowpath_common+0x0/0x74) from [] (warn_slowpath_null+0x2c/0x34) [ 13.856781] r8:00000000 r7:00000000 r6:c18b8194 r5:60000093 r4:ef182000 [ 13.863708] r3:00000009 [ 13.866485] [] (warn_slowpath_null+0x0/0x34) from [] (check_flags+0x78/0x1d0) [ 13.875823] [] (check_flags+0x0/0x1d0) from [] (lock_acquire+0x4c/0x150) [ 13.884704] [] (lock_acquire+0x0/0x150) from [] (_raw_spin_lock+0x4c/0x84) [ 13.893798] [] (_raw_spin_lock+0x0/0x84) from [] (sched_ttwu_pending+0x58/0x8c) [ 13.903320] r6:ef92d040 r5:00000003 r4:c18b8180 [ 13.908233] [] (sched_ttwu_pending+0x0/0x8c) from [] (scheduler_ipi+0x18/0x1c) [ 13.917663] r6:ef183fb0 r5:00000003 r4:00000000 r3:00000001 [ 13.923645] [] (scheduler_ipi+0x0/0x1c) from [] (do_IPI+0x9c/0xfc) [ 13.932006] [] (do_IPI+0x0/0xfc) from [] (__irq_usr+0x48/0xe0) [ 13.939971] Exception stack(0xef183fb0 to 0xef183ff8) [ 13.945281] 3fa0: ffffffc3 0001500c 00000001 0001500c [ 13.953948] 3fc0: 00000050 400b45f0 400d9000 00000000 00000001 400d9600 6474e552 bea05b3c [ 13.962585] 3fe0: 400d96c0 bea059c0 400b6574 400b65d8 20000010 ffffffff [ 13.969573] r6:00000403 r5:fa240100 r4:ffffffff r3:20000010 [ 13.975585] ---[ end trace efc4896ab0fb62cb ]--- [ 13.980468] possible reason: unannotated irqs-off. [ 13.985534] irq event stamp: 1610 [ 13.989044] hardirqs last enabled at (1610): [] no_work_pending+0x8/0x2c [ 13.997131] hardirqs last disabled at (1609): [] ret_slow_syscall+0xc/0x1c [ 14.005371] softirqs last enabled at (0): [] copy_process+0x2cc/0xa24 [ 14.013183] softirqs last disabled at (0): [< (null)>] (null) Signed-off-by: Ming Lei Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 6 +++++- arch/arm/kernel/entry-common.S | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index e8d885676807..90c62cd51ca9 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -435,6 +435,10 @@ __irq_usr: usr_entry kuser_cmpxchg_check +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + get_thread_info tsk #ifdef CONFIG_PREEMPT ldr r8, [tsk, #TI_PREEMPT] @ get preempt count @@ -453,7 +457,7 @@ __irq_usr: #endif mov why, #0 - b ret_to_user + b ret_to_user_from_irq UNWIND(.fnend ) ENDPROC(__irq_usr) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 1e7b04a40a31..b2a27b6b0046 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -64,6 +64,7 @@ work_resched: ENTRY(ret_to_user) ret_slow_syscall: disable_irq @ disable interrupts +ENTRY(ret_to_user_from_irq) ldr r1, [tsk, #TI_FLAGS] tst r1, #_TIF_WORK_MASK bne work_pending @@ -75,6 +76,7 @@ no_work_pending: arch_ret_to_user r1, lr restore_user_regs fast = 0, offset = 0 +ENDPROC(ret_to_user_from_irq) ENDPROC(ret_to_user) /* -- cgit v1.2.3 From 17ee083b7897ab27b4949c42de805889ebd2b4c5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 5 May 2011 17:23:10 +0100 Subject: ARM: 6894/1: mmci: trigger card detect IRQs on falling and rising edges Right now the card detect IRQ for MMCI is requested without any flags which will give some default machine-specified IRQ behaviour. However on the U300 rising+falling edges (such as can be expected from a simple GPIO to generate when inserting/removing a card) need to be requested explicitly. Cc: Rabin Vincent Cc: Ulf Hansson Cc: Sebastian Rasmussen Signed-off-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 5da5bea0f9f0..7721de942c69 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1144,9 +1144,17 @@ static int __devinit mmci_probe(struct amba_device *dev, else if (ret != -ENOSYS) goto err_gpio_cd; + /* + * A gpio pin that will detect cards when inserted and removed + * will most likely want to trigger on the edges if it is + * 0 when ejected and 1 when inserted (or mutatis mutandis + * for the inverted case) so we request triggers on both + * edges. + */ ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), - mmci_cd_irq, 0, - DRIVER_NAME " (cd)", host); + mmci_cd_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + DRIVER_NAME " (cd)", host); if (ret >= 0) host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); } -- cgit v1.2.3 From 1622ee1822e8adb391b55a09e3cd5144bd9fad47 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2011 17:13:57 +0100 Subject: ASoC: Only update SYSCLK_ENA when pausing WM8915 SYSCLK Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8915.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c index a0b1a7278284..28fbf072b9c0 100644 --- a/sound/soc/codecs/wm8915.c +++ b/sound/soc/codecs/wm8915.c @@ -1839,7 +1839,7 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, int old; /* Disable SYSCLK while we reconfigure */ - old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1); + old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA; snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, WM8915_SYSCLK_ENA, 0); -- cgit v1.2.3 From 6ac340623c5d2a945030814d900701439772ff57 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2011 18:20:50 +0100 Subject: ASoC: Add missing break in WM8915 FLL source selection Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8915.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c index 28fbf072b9c0..e2ab4fac2819 100644 --- a/sound/soc/codecs/wm8915.c +++ b/sound/soc/codecs/wm8915.c @@ -2038,6 +2038,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, break; case WM8915_FLL_MCLK2: reg = 1; + break; case WM8915_FLL_DACLRCLK1: reg = 2; break; -- cgit v1.2.3 From a9c667f8f0656631ee5438baaf21bf30d5f67375 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Mon, 6 Jun 2011 09:51:52 -0400 Subject: ext4: fixed tracepoints cleanup While creating fixed tracepoints for ext3, basically by porting them from ext4, I found a lot of useless retyping, wrong type usage, useless variable passing and other inconsistencies in the ext4 fixed tracepoint code. This patch cleans the fixed tracepoint code for ext4 and also simplify some of them. Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 2 +- fs/ext4/mballoc.c | 6 +- include/trace/events/ext4.h | 179 +++++++++++++++++++------------------------- 3 files changed, 80 insertions(+), 107 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a5763e3505ba..e3126c051006 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2634,7 +2634,7 @@ static int ext4_writepage(struct page *page, struct buffer_head *page_bufs = NULL; struct inode *inode = page->mapping->host; - trace_ext4_writepage(inode, page); + trace_ext4_writepage(page); size = i_size_read(inode); if (page->index == size >> PAGE_CACHE_SHIFT) len = size & ~PAGE_CACHE_MASK; diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index eb71dd59f2e4..6ed859d56850 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3578,8 +3578,8 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, free += next - bit; trace_ext4_mballoc_discard(sb, NULL, group, bit, next - bit); - trace_ext4_mb_release_inode_pa(sb, pa->pa_inode, pa, - grp_blk_start + bit, next - bit); + trace_ext4_mb_release_inode_pa(pa, grp_blk_start + bit, + next - bit); mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); bit = next + 1; } @@ -3608,7 +3608,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b, ext4_group_t group; ext4_grpblk_t bit; - trace_ext4_mb_release_group_pa(sb, pa); + trace_ext4_mb_release_group_pa(pa); BUG_ON(pa->pa_deleted == 0); ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); BUG_ON(group != e4b->bd_group && pa->pa_len != 0); diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index e09592d2f916..5ce2b2f5f524 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h @@ -26,7 +26,7 @@ TRACE_EVENT(ext4_free_inode, __field( umode_t, mode ) __field( uid_t, uid ) __field( gid_t, gid ) - __field( blkcnt_t, blocks ) + __field( __u64, blocks ) ), TP_fast_assign( @@ -40,9 +40,8 @@ TRACE_EVENT(ext4_free_inode, TP_printk("dev %d,%d ino %lu mode 0%o uid %u gid %u blocks %llu", MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->mode, __entry->uid, __entry->gid, - (unsigned long long) __entry->blocks) + (unsigned long) __entry->ino, __entry->mode, + __entry->uid, __entry->gid, __entry->blocks) ); TRACE_EVENT(ext4_request_inode, @@ -178,7 +177,7 @@ TRACE_EVENT(ext4_begin_ordered_truncate, TP_printk("dev %d,%d ino %lu new_size %lld", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - (long long) __entry->new_size) + __entry->new_size) ); DECLARE_EVENT_CLASS(ext4__write_begin, @@ -204,7 +203,7 @@ DECLARE_EVENT_CLASS(ext4__write_begin, __entry->flags = flags; ), - TP_printk("dev %d,%d ino %lu pos %llu len %u flags %u", + TP_printk("dev %d,%d ino %lu pos %lld len %u flags %u", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, __entry->pos, __entry->len, __entry->flags) @@ -248,7 +247,7 @@ DECLARE_EVENT_CLASS(ext4__write_end, __entry->copied = copied; ), - TP_printk("dev %d,%d ino %lu pos %llu len %u copied %u", + TP_printk("dev %d,%d ino %lu pos %lld len %u copied %u", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, __entry->pos, __entry->len, __entry->copied) @@ -286,29 +285,6 @@ DEFINE_EVENT(ext4__write_end, ext4_da_write_end, TP_ARGS(inode, pos, len, copied) ); -TRACE_EVENT(ext4_writepage, - TP_PROTO(struct inode *inode, struct page *page), - - TP_ARGS(inode, page), - - TP_STRUCT__entry( - __field( dev_t, dev ) - __field( ino_t, ino ) - __field( pgoff_t, index ) - - ), - - TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; - __entry->ino = inode->i_ino; - __entry->index = page->index; - ), - - TP_printk("dev %d,%d ino %lu page_index %lu", - MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, __entry->index) -); - TRACE_EVENT(ext4_da_writepages, TP_PROTO(struct inode *inode, struct writeback_control *wbc), @@ -341,7 +317,7 @@ TRACE_EVENT(ext4_da_writepages, ), TP_printk("dev %d,%d ino %lu nr_to_write %ld pages_skipped %ld " - "range_start %llu range_end %llu sync_mode %d" + "range_start %lld range_end %lld sync_mode %d" "for_kupdate %d range_cyclic %d writeback_index %lu", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, __entry->nr_to_write, @@ -449,7 +425,14 @@ DECLARE_EVENT_CLASS(ext4__page_op, TP_printk("dev %d,%d ino %lu page_index %lu", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - __entry->index) + (unsigned long) __entry->index) +); + +DEFINE_EVENT(ext4__page_op, ext4_writepage, + + TP_PROTO(struct page *page), + + TP_ARGS(page) ); DEFINE_EVENT(ext4__page_op, ext4_readpage, @@ -489,7 +472,7 @@ TRACE_EVENT(ext4_invalidatepage, TP_printk("dev %d,%d ino %lu page_index %lu offset %lu", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - __entry->index, __entry->offset) + (unsigned long) __entry->index, __entry->offset) ); TRACE_EVENT(ext4_discard_blocks, @@ -562,12 +545,10 @@ DEFINE_EVENT(ext4__mb_new_pa, ext4_mb_new_group_pa, ); TRACE_EVENT(ext4_mb_release_inode_pa, - TP_PROTO(struct super_block *sb, - struct inode *inode, - struct ext4_prealloc_space *pa, + TP_PROTO(struct ext4_prealloc_space *pa, unsigned long long block, unsigned int count), - TP_ARGS(sb, inode, pa, block, count), + TP_ARGS(pa, block, count), TP_STRUCT__entry( __field( dev_t, dev ) @@ -578,8 +559,8 @@ TRACE_EVENT(ext4_mb_release_inode_pa, ), TP_fast_assign( - __entry->dev = sb->s_dev; - __entry->ino = inode->i_ino; + __entry->dev = pa->pa_inode->i_sb->s_dev; + __entry->ino = pa->pa_inode->i_ino; __entry->block = block; __entry->count = count; ), @@ -591,10 +572,9 @@ TRACE_EVENT(ext4_mb_release_inode_pa, ); TRACE_EVENT(ext4_mb_release_group_pa, - TP_PROTO(struct super_block *sb, - struct ext4_prealloc_space *pa), + TP_PROTO(struct ext4_prealloc_space *pa), - TP_ARGS(sb, pa), + TP_ARGS(pa), TP_STRUCT__entry( __field( dev_t, dev ) @@ -604,7 +584,7 @@ TRACE_EVENT(ext4_mb_release_group_pa, ), TP_fast_assign( - __entry->dev = sb->s_dev; + __entry->dev = pa->pa_inode->i_sb->s_dev; __entry->pa_pstart = pa->pa_pstart; __entry->pa_len = pa->pa_len; ), @@ -666,10 +646,10 @@ TRACE_EVENT(ext4_request_blocks, __field( ino_t, ino ) __field( unsigned int, flags ) __field( unsigned int, len ) - __field( __u64, logical ) + __field( __u32, logical ) + __field( __u32, lleft ) + __field( __u32, lright ) __field( __u64, goal ) - __field( __u64, lleft ) - __field( __u64, lright ) __field( __u64, pleft ) __field( __u64, pright ) ), @@ -687,17 +667,13 @@ TRACE_EVENT(ext4_request_blocks, __entry->pright = ar->pright; ), - TP_printk("dev %d,%d ino %lu flags %u len %u lblk %llu goal %llu " - "lleft %llu lright %llu pleft %llu pright %llu ", + TP_printk("dev %d,%d ino %lu flags %u len %u lblk %u goal %llu " + "lleft %u lright %u pleft %llu pright %llu ", MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->flags, __entry->len, - (unsigned long long) __entry->logical, - (unsigned long long) __entry->goal, - (unsigned long long) __entry->lleft, - (unsigned long long) __entry->lright, - (unsigned long long) __entry->pleft, - (unsigned long long) __entry->pright) + (unsigned long) __entry->ino, __entry->flags, + __entry->len, __entry->logical, __entry->goal, + __entry->lleft, __entry->lright, __entry->pleft, + __entry->pright) ); TRACE_EVENT(ext4_allocate_blocks, @@ -711,10 +687,10 @@ TRACE_EVENT(ext4_allocate_blocks, __field( __u64, block ) __field( unsigned int, flags ) __field( unsigned int, len ) - __field( __u64, logical ) + __field( __u32, logical ) + __field( __u32, lleft ) + __field( __u32, lright ) __field( __u64, goal ) - __field( __u64, lleft ) - __field( __u64, lright ) __field( __u64, pleft ) __field( __u64, pright ) ), @@ -733,17 +709,13 @@ TRACE_EVENT(ext4_allocate_blocks, __entry->pright = ar->pright; ), - TP_printk("dev %d,%d ino %lu flags %u len %u block %llu lblk %llu " - "goal %llu lleft %llu lright %llu pleft %llu pright %llu", + TP_printk("dev %d,%d ino %lu flags %u len %u block %llu lblk %u " + "goal %llu lleft %u lright %u pleft %llu pright %llu", MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - __entry->flags, __entry->len, __entry->block, - (unsigned long long) __entry->logical, - (unsigned long long) __entry->goal, - (unsigned long long) __entry->lleft, - (unsigned long long) __entry->lright, - (unsigned long long) __entry->pleft, - (unsigned long long) __entry->pright) + (unsigned long) __entry->ino, __entry->flags, + __entry->len, __entry->block, __entry->logical, + __entry->goal, __entry->lleft, __entry->lright, + __entry->pleft, __entry->pright) ); TRACE_EVENT(ext4_free_blocks, @@ -755,10 +727,10 @@ TRACE_EVENT(ext4_free_blocks, TP_STRUCT__entry( __field( dev_t, dev ) __field( ino_t, ino ) - __field( umode_t, mode ) + __field( umode_t, mode ) __field( __u64, block ) __field( unsigned long, count ) - __field( int, flags ) + __field( int, flags ) ), TP_fast_assign( @@ -798,7 +770,7 @@ TRACE_EVENT(ext4_sync_file_enter, __entry->parent = dentry->d_parent->d_inode->i_ino; ), - TP_printk("dev %d,%d ino %ld parent %ld datasync %d ", + TP_printk("dev %d,%d ino %lu parent %lu datasync %d ", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, (unsigned long) __entry->parent, __entry->datasync) @@ -821,7 +793,7 @@ TRACE_EVENT(ext4_sync_file_exit, __entry->dev = inode->i_sb->s_dev; ), - TP_printk("dev %d,%d ino %ld ret %d", + TP_printk("dev %d,%d ino %lu ret %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, __entry->ret) @@ -1005,7 +977,7 @@ DECLARE_EVENT_CLASS(ext4__mballoc, __entry->result_len = len; ), - TP_printk("dev %d,%d inode %lu extent %u/%d/%u ", + TP_printk("dev %d,%d inode %lu extent %u/%d/%d ", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, __entry->result_group, __entry->result_start, @@ -1093,7 +1065,7 @@ TRACE_EVENT(ext4_da_update_reserve_space, "allocated_meta_blocks %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - __entry->mode, (unsigned long long) __entry->i_blocks, + __entry->mode, __entry->i_blocks, __entry->used_blocks, __entry->reserved_data_blocks, __entry->reserved_meta_blocks, __entry->allocated_meta_blocks) ); @@ -1127,7 +1099,7 @@ TRACE_EVENT(ext4_da_reserve_space, "reserved_data_blocks %d reserved_meta_blocks %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - __entry->mode, (unsigned long long) __entry->i_blocks, + __entry->mode, __entry->i_blocks, __entry->md_needed, __entry->reserved_data_blocks, __entry->reserved_meta_blocks) ); @@ -1164,7 +1136,7 @@ TRACE_EVENT(ext4_da_release_space, "allocated_meta_blocks %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - __entry->mode, (unsigned long long) __entry->i_blocks, + __entry->mode, __entry->i_blocks, __entry->freed_blocks, __entry->reserved_data_blocks, __entry->reserved_meta_blocks, __entry->allocated_meta_blocks) ); @@ -1239,14 +1211,15 @@ TRACE_EVENT(ext4_direct_IO_enter, __entry->rw = rw; ), - TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d", + TP_printk("dev %d,%d ino %lu pos %lld len %lu rw %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - (unsigned long long) __entry->pos, __entry->len, __entry->rw) + __entry->pos, __entry->len, __entry->rw) ); TRACE_EVENT(ext4_direct_IO_exit, - TP_PROTO(struct inode *inode, loff_t offset, unsigned long len, int rw, int ret), + TP_PROTO(struct inode *inode, loff_t offset, unsigned long len, + int rw, int ret), TP_ARGS(inode, offset, len, rw, ret), @@ -1268,10 +1241,10 @@ TRACE_EVENT(ext4_direct_IO_exit, __entry->ret = ret; ), - TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d ret %d", + TP_printk("dev %d,%d ino %lu pos %lld len %lu rw %d ret %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - (unsigned long long) __entry->pos, __entry->len, + __entry->pos, __entry->len, __entry->rw, __entry->ret) ); @@ -1296,15 +1269,15 @@ TRACE_EVENT(ext4_fallocate_enter, __entry->mode = mode; ), - TP_printk("dev %d,%d ino %ld pos %llu len %llu mode %d", + TP_printk("dev %d,%d ino %lu pos %lld len %lld mode %d", MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, - (unsigned long long) __entry->pos, - (unsigned long long) __entry->len, __entry->mode) + (unsigned long) __entry->ino, __entry->pos, + __entry->len, __entry->mode) ); TRACE_EVENT(ext4_fallocate_exit, - TP_PROTO(struct inode *inode, loff_t offset, unsigned int max_blocks, int ret), + TP_PROTO(struct inode *inode, loff_t offset, + unsigned int max_blocks, int ret), TP_ARGS(inode, offset, max_blocks, ret), @@ -1312,7 +1285,7 @@ TRACE_EVENT(ext4_fallocate_exit, __field( ino_t, ino ) __field( dev_t, dev ) __field( loff_t, pos ) - __field( unsigned, blocks ) + __field( unsigned int, blocks ) __field( int, ret ) ), @@ -1324,10 +1297,10 @@ TRACE_EVENT(ext4_fallocate_exit, __entry->ret = ret; ), - TP_printk("dev %d,%d ino %ld pos %llu blocks %d ret %d", + TP_printk("dev %d,%d ino %lu pos %lld blocks %u ret %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - (unsigned long long) __entry->pos, __entry->blocks, + __entry->pos, __entry->blocks, __entry->ret) ); @@ -1350,7 +1323,7 @@ TRACE_EVENT(ext4_unlink_enter, __entry->dev = dentry->d_inode->i_sb->s_dev; ), - TP_printk("dev %d,%d ino %ld size %lld parent %ld", + TP_printk("dev %d,%d ino %lu size %lld parent %lu", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, __entry->size, (unsigned long) __entry->parent) @@ -1373,7 +1346,7 @@ TRACE_EVENT(ext4_unlink_exit, __entry->ret = ret; ), - TP_printk("dev %d,%d ino %ld ret %d", + TP_printk("dev %d,%d ino %lu ret %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, __entry->ret) @@ -1387,7 +1360,7 @@ DECLARE_EVENT_CLASS(ext4__truncate, TP_STRUCT__entry( __field( ino_t, ino ) __field( dev_t, dev ) - __field( blkcnt_t, blocks ) + __field( __u64, blocks ) ), TP_fast_assign( @@ -1396,9 +1369,9 @@ DECLARE_EVENT_CLASS(ext4__truncate, __entry->blocks = inode->i_blocks; ), - TP_printk("dev %d,%d ino %lu blocks %lu", + TP_printk("dev %d,%d ino %lu blocks %llu", MAJOR(__entry->dev), MINOR(__entry->dev), - (unsigned long) __entry->ino, (unsigned long) __entry->blocks) + (unsigned long) __entry->ino, __entry->blocks) ); DEFINE_EVENT(ext4__truncate, ext4_truncate_enter, @@ -1417,7 +1390,7 @@ DEFINE_EVENT(ext4__truncate, ext4_truncate_exit, DECLARE_EVENT_CLASS(ext4__map_blocks_enter, TP_PROTO(struct inode *inode, ext4_lblk_t lblk, - unsigned len, unsigned flags), + unsigned int len, unsigned int flags), TP_ARGS(inode, lblk, len, flags), @@ -1425,8 +1398,8 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_enter, __field( ino_t, ino ) __field( dev_t, dev ) __field( ext4_lblk_t, lblk ) - __field( unsigned, len ) - __field( unsigned, flags ) + __field( unsigned int, len ) + __field( unsigned int, flags ) ), TP_fast_assign( @@ -1440,7 +1413,7 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_enter, TP_printk("dev %d,%d ino %lu lblk %u len %u flags %u", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - (unsigned) __entry->lblk, __entry->len, __entry->flags) + __entry->lblk, __entry->len, __entry->flags) ); DEFINE_EVENT(ext4__map_blocks_enter, ext4_ext_map_blocks_enter, @@ -1459,7 +1432,7 @@ DEFINE_EVENT(ext4__map_blocks_enter, ext4_ind_map_blocks_enter, DECLARE_EVENT_CLASS(ext4__map_blocks_exit, TP_PROTO(struct inode *inode, ext4_lblk_t lblk, - ext4_fsblk_t pblk, unsigned len, int ret), + ext4_fsblk_t pblk, unsigned int len, int ret), TP_ARGS(inode, lblk, pblk, len, ret), @@ -1468,7 +1441,7 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_exit, __field( dev_t, dev ) __field( ext4_lblk_t, lblk ) __field( ext4_fsblk_t, pblk ) - __field( unsigned, len ) + __field( unsigned int, len ) __field( int, ret ) ), @@ -1484,7 +1457,7 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_exit, TP_printk("dev %d,%d ino %lu lblk %u pblk %llu len %u ret %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - (unsigned) __entry->lblk, (unsigned long long) __entry->pblk, + __entry->lblk, __entry->pblk, __entry->len, __entry->ret) ); @@ -1524,7 +1497,7 @@ TRACE_EVENT(ext4_ext_load_extent, TP_printk("dev %d,%d ino %lu lblk %u pblk %llu", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, - (unsigned) __entry->lblk, (unsigned long long) __entry->pblk) + __entry->lblk, __entry->pblk) ); TRACE_EVENT(ext4_load_inode, -- cgit v1.2.3 From fd137e2bba53b7207cbae6a1312e89ef3ae55624 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 Jun 2011 11:26:15 +0100 Subject: ASoC: Check for NULL register bank in snd_soc_get_cache_val() Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-cache.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 06b7b81a1601..c005ceb70c9d 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -466,6 +466,9 @@ static bool snd_soc_set_cache_val(void *base, unsigned int idx, static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx, unsigned int word_size) { + if (!base) + return -1; + switch (word_size) { case 1: { const u8 *cache = base; -- cgit v1.2.3 From b084f598df36b62dfae83c10ed17f0b66b50f442 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 31 May 2011 12:24:58 -0400 Subject: nfsd: fix dependency of nfsd on auth_rpcgss Commit b0b0c0a26e84 "nfsd: add proc file listing kernel's gss_krb5 enctypes" added an nunnecessary dependency of nfsd on the auth_rpcgss module. It's a little ad hoc, but since the only piece of information nfsd needs from rpcsec_gss_krb5 is a single static string, one solution is just to share it with an include file. Cc: stable@kernel.org Reported-by: Michael Guntsche Cc: Kevin Coffman Signed-off-by: J. Bruce Fields --- fs/nfsd/nfsctl.c | 19 ++++++------------- include/linux/sunrpc/gss_krb5_enctypes.h | 4 ++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 3 ++- 3 files changed, 12 insertions(+), 14 deletions(-) create mode 100644 include/linux/sunrpc/gss_krb5_enctypes.h diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 1f5eae40f34e..2b1449dd2f49 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "idmap.h" #include "nfsd.h" @@ -189,18 +190,10 @@ static struct file_operations export_features_operations = { .release = single_release, }; -#ifdef CONFIG_SUNRPC_GSS +#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) static int supported_enctypes_show(struct seq_file *m, void *v) { - struct gss_api_mech *k5mech; - - k5mech = gss_mech_get_by_name("krb5"); - if (k5mech == NULL) - goto out; - if (k5mech->gm_upcall_enctypes != NULL) - seq_printf(m, k5mech->gm_upcall_enctypes); - gss_mech_put(k5mech); -out: + seq_printf(m, KRB5_SUPPORTED_ENCTYPES); return 0; } @@ -215,7 +208,7 @@ static struct file_operations supported_enctypes_ops = { .llseek = seq_lseek, .release = single_release, }; -#endif /* CONFIG_SUNRPC_GSS */ +#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); @@ -1427,9 +1420,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, -#ifdef CONFIG_SUNRPC_GSS +#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, -#endif /* CONFIG_SUNRPC_GSS */ +#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, diff --git a/include/linux/sunrpc/gss_krb5_enctypes.h b/include/linux/sunrpc/gss_krb5_enctypes.h new file mode 100644 index 000000000000..ec6234eee89c --- /dev/null +++ b/include/linux/sunrpc/gss_krb5_enctypes.h @@ -0,0 +1,4 @@ +/* + * Dumb way to share this static piece of information with nfsd + */ +#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2" diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 0a9a2ec2e469..c3b75333b821 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef RPC_DEBUG # define RPCDBG_FACILITY RPCDBG_AUTH @@ -750,7 +751,7 @@ static struct gss_api_mech gss_kerberos_mech = { .gm_ops = &gss_kerberos_ops, .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs), .gm_pfs = gss_kerberos_pfs, - .gm_upcall_enctypes = "18,17,16,23,3,1,2", + .gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES, }; static int __init init_kerberos_module(void) -- cgit v1.2.3 From ab6a44ce1da48d35fe7ec95fa068aa617bd7e8dd Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 6 Jun 2011 14:35:27 -0400 Subject: Revert "mac80211: Skip tailroom reservation for full HW-crypto devices" This reverts commit aac6af5534fade2b18682a0b9efad1a6c04c34c6. Conflicts: net/mac80211/key.c That commit has a race that causes a warning, as documented in the thread here: http://marc.info/?l=linux-wireless&m=130717684914101&w=2 Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 3 --- net/mac80211/key.c | 21 ++------------------- net/mac80211/tx.c | 7 ++++++- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 2025af52b195..090b0ec1e056 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -775,9 +775,6 @@ struct ieee80211_local { int tx_headroom; /* required headroom for hardware/radiotap */ - /* count for keys needing tailroom space allocation */ - int crypto_tx_tailroom_needed_cnt; - /* Tasklet and skb queue to process calls from IRQ mode. All frames * added to skb_queue will be processed, but frames in * skb_queue_unreliable may be dropped if the total length of these diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 31afd712930d..f825e2f0a57e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -101,11 +101,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (!ret) { key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; - - if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || - (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) - key->local->crypto_tx_tailroom_needed_cnt--; - return 0; } @@ -161,10 +156,6 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; - - if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || - (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) - key->local->crypto_tx_tailroom_needed_cnt++; } void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) @@ -403,10 +394,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) ieee80211_aes_key_free(key->u.ccmp.tfm); if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); - if (key->local) { + if (key->local) ieee80211_debugfs_key_remove(key); - key->local->crypto_tx_tailroom_needed_cnt--; - } kfree(key); } @@ -468,8 +457,6 @@ int ieee80211_key_link(struct ieee80211_key *key, ieee80211_debugfs_key_add(key); - key->local->crypto_tx_tailroom_needed_cnt++; - ret = ieee80211_key_enable_hw_accel(key); mutex_unlock(&sdata->local->key_mtx); @@ -511,12 +498,8 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->local->key_mtx); - sdata->local->crypto_tx_tailroom_needed_cnt = 0; - - list_for_each_entry(key, &sdata->key_list, list) { - sdata->local->crypto_tx_tailroom_needed_cnt++; + list_for_each_entry(key, &sdata->key_list, list) ieee80211_key_enable_hw_accel(key); - } mutex_unlock(&sdata->local->key_mtx); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 64e0f7587e6d..3104c844b544 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1480,7 +1480,12 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, { int tail_need = 0; - if (may_encrypt && local->crypto_tx_tailroom_needed_cnt) { + /* + * This could be optimised, devices that do full hardware + * crypto (including TKIP MMIC) need no tailroom... But we + * have no drivers for such devices currently. + */ + if (may_encrypt) { tail_need = IEEE80211_ENCRYPT_TAILROOM; tail_need -= skb_tailroom(skb); tail_need = max_t(int, tail_need, 0); -- cgit v1.2.3 From 42b70a5f6d18165a075d189d1bee82fad7cdbf29 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 26 May 2011 17:14:22 +0200 Subject: iwlagn: use cts-to-self protection on 5000 adapters series This patch fixes 802.11n stability and performance regression we have since 2.6.35. It boost performance on my 5GHz N-only network from about 5MB/s to 8MB/s. Similar percentage boost can be observed on 2.4 GHz. These are test results of 5x downloading of approximately 700MB iso image: vanilla: 5.27 5.22 4.94 4.47 5.31 ; avr 5.0420 std 0.35110 patched: 8.07 7.95 8.06 7.99 7.96 ; avr 8.0060 std 0.055946 This was achieved with NetworkManager configured to do not perform periodical scans, by configuring constant BSSID. With periodical scans, after some time, performance downgrade to unpatched driver level, like in example below: patched: 7.40 7.61 4.28 4.37 4.80 avr 5.6920 std 1.6683 However patch still make better here, since similar test on unpatched driver make link disconnects with below messages after some time: wlan1: authenticate with 00:23:69:35:d1:3f (try 1) wlan1: authenticate with 00:23:69:35:d1:3f (try 2) wlan1: authenticate with 00:23:69:35:d1:3f (try 3) wlan1: authentication with 00:23:69:35:d1:3f timed out On 2.6.35 kernel patch helps against connection hangs with messages: iwlagn 0000:20:00.0: queue 10 stuck 3 time. Fw reload. iwlagn 0000:20:00.0: On demand firmware reload iwlagn 0000:20:00.0: Stopping AGG while state not ON or starting Cc: stable@kernel.org # 2.6.35+ Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 12 ++---------- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 8 ++++++++ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5b721c56aee9..f99f9c193352 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -423,7 +423,6 @@ static struct iwl_base_params iwl5000_base_params = { }; static struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, - .use_rts_for_aggregation = true, /* use rts/cts protection */ }; #define IWL_DEVICE_5000 \ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index b12c72d63ccb..23fa93deae96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -163,17 +163,9 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, __le16 fc, __le32 *tx_flags) { if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || - info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || + info->flags & IEEE80211_TX_CTL_AMPDU) *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; - return; - } - - if (priv->cfg->ht_params && - priv->cfg->ht_params->use_rts_for_aggregation && - info->flags & IEEE80211_TX_CTL_AMPDU) { - *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; - return; - } } /* Calc max signal level (dBm) among 3 possible receivers */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 2532c7db3aff..018874964602 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -325,6 +325,14 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) return 0; } + /* + * force CTS-to-self frames protection if RTS-CTS is not preferred + * one aggregation protection method + */ + if (!(priv->cfg->ht_params && + priv->cfg->ht_params->use_rts_for_aggregation)) + ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; + if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; -- cgit v1.2.3 From 3bb42a64960253353278876ca8da6b0a7d3bea87 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 4 Jun 2011 16:48:54 +0200 Subject: rt2x00: fix rmmod crash Avoid queue and run autowakeup_work when device is not present anymore. That prevent rmmod and device remove crash introduced by: commit 1c0bcf89d85cc97a0d9ce4cd909351a81fa4fdde Author: Ivo van Doorn Date: Sat Apr 30 17:18:18 2011 +0200 rt2x00: Add autowake support for USB hardware Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00config.c | 3 ++- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 555180d8f4aa..b704e5b183d0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -250,7 +250,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) rt2x00link_reset_tuner(rt2x00dev, false); - if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) && (conf->flags & IEEE80211_CONF_PS)) { beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index c018d67aab8e..939821b4af2f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -146,6 +146,9 @@ static void rt2x00lib_autowakeup(struct work_struct *work) struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, autowakeup_work.work); + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return; + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) ERROR(rt2x00dev, "Device failed to wakeup.\n"); clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); @@ -1160,6 +1163,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) * Stop all work. */ cancel_work_sync(&rt2x00dev->intf_work); + cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); if (rt2x00_is_usb(rt2x00dev)) { del_timer_sync(&rt2x00dev->txstatus_timer); cancel_work_sync(&rt2x00dev->rxdone_work); -- cgit v1.2.3 From 51892dbbd511911c0f965a36b431fc3e8f1e4f8a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 6 Jun 2011 15:11:30 +0200 Subject: iwl4965: set tx power after rxon_assoc Setting tx power can be deferred during scan or changing channel. If after that correct tx power settings will not be sent to device, we can observe transmission problems and timeouts. Force to send tx power settings also after partial rxon change, to assure device always be configured with up-to-date settings. Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=36492 Cc: stable@kernel.org # 2.6.39+ Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-4965.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c index f9db25bb35c3..e1b89220c186 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965.c @@ -1237,7 +1237,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); iwl_legacy_print_rx_config_cmd(priv, ctx); - return 0; + goto set_tx_power; } /* If we are currently associated and the new config requires @@ -1317,6 +1317,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c iwl4965_init_sensitivity(priv); +set_tx_power: /* If we issue a new RXON command which required a tune then we must * send a new TXPOWER command or we won't be able to Tx any frames */ ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true); -- cgit v1.2.3 From 8ca695f273709a9d147826716a8dee3e0eb2407f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 6 Jun 2011 13:38:35 +0200 Subject: ASoC: AD1836: Fix setting the PCM format Signed-off-by: Lars-Peter Clausen Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/ad1836.c | 14 +++++++------- sound/soc/codecs/ad1836.h | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index ab63d52e36e1..754c496412bd 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -145,22 +145,22 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - word_len = 3; + word_len = AD1836_WORD_LEN_16; break; case SNDRV_PCM_FORMAT_S20_3LE: - word_len = 1; + word_len = AD1836_WORD_LEN_20; break; case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: - word_len = 0; + word_len = AD1836_WORD_LEN_24; break; } - snd_soc_update_bits(codec, AD1836_DAC_CTRL1, - AD1836_DAC_WORD_LEN_MASK, word_len); + snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, + word_len << AD1836_DAC_WORD_LEN_OFFSET); - snd_soc_update_bits(codec, AD1836_ADC_CTRL2, - AD1836_ADC_WORD_LEN_MASK, word_len); + snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, + word_len << AD1836_ADC_WORD_OFFSET); return 0; } diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 845596717fdf..9d6a3f8f8aaf 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -25,6 +25,7 @@ #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) #define AD1836_DAC_WORD_LEN_MASK 0x18 +#define AD1836_DAC_WORD_LEN_OFFSET 3 #define AD1836_DAC_CTRL2 1 #define AD1836_DACL1_MUTE 0 @@ -51,6 +52,7 @@ #define AD1836_ADCL2_MUTE 2 #define AD1836_ADCR2_MUTE 3 #define AD1836_ADC_WORD_LEN_MASK 0x30 +#define AD1836_ADC_WORD_OFFSET 5 #define AD1836_ADC_SERFMT_MASK (7 << 6) #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) @@ -60,4 +62,8 @@ #define AD1836_NUM_REGS 16 +#define AD1836_WORD_LEN_24 0x0 +#define AD1836_WORD_LEN_20 0x1 +#define AD1836_WORD_LEN_16 0x2 + #endif -- cgit v1.2.3 From 5a079c305ad4dda9708b7a29db4a8bd38e21c3a6 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Mon, 6 Jun 2011 06:00:07 +0000 Subject: net/ipv6: check for mistakenly passed in non-AF_INET6 sockaddrs Same check as for IPv4, also do for IPv6. (If you passed in a IPv4 sockaddr_in here, the sizeof check in the line before would have triggered already though.) Signed-off-by: Marcus Meissner Cc: Reinhard Max Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index b7919f901fbf..d450a2f9fc06 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -272,6 +272,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; + + if (addr->sin6_family != AF_INET6) + return -EINVAL; + addr_type = ipv6_addr_type(&addr->sin6_addr); if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM) return -EINVAL; -- cgit v1.2.3 From be1f4084b4824301e640e81d63b6275cd99ee6a1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 6 Jun 2011 11:22:17 -0700 Subject: nfsd: v4 support requires CRYPTO nfsd V4 support uses crypto interfaces, so select CRYPTO to fix build errors in 2.6.39: ERROR: "crypto_destroy_tfm" [fs/nfsd/nfsd.ko] undefined! ERROR: "crypto_alloc_base" [fs/nfsd/nfsd.ko] undefined! Reported-by: Wakko Warner Signed-off-by: Randy Dunlap Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 18b3e8975fe0..fbb2a5ef5817 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -82,6 +82,7 @@ config NFSD_V4 select NFSD_V3 select FS_POSIX_ACL select SUNRPC_GSS + select CRYPTO help This option enables support in your system's NFS server for version 4 of the NFS protocol (RFC 3530). -- cgit v1.2.3 From 7d751f6f8c679f51b73d01a1b5269347a929004c Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Fri, 3 Jun 2011 12:21:23 -0400 Subject: nfsd: link returns nfserr_delay when breaking lease fix for commit 4795bb37effb7b8fe77e2d2034545d062d3788a8, nfsd: break lease on unlink, link, and rename if the LINK operation breaks a delegation, it returns NFS4ERR_NOENT (which is not a valid error in rfc 5661) instead of NFS4ERR_DELAY. the return value of nfsd_break_lease() in nfsd_link() must be converted from host_err to err Signed-off-by: Casey Bodley Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/vfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index d5718273bb32..f3fb61b69a1e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1660,8 +1660,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, if (!dold->d_inode) goto out_drop_write; host_err = nfsd_break_lease(dold->d_inode); - if (host_err) + if (host_err) { + err = nfserrno(host_err); goto out_drop_write; + } host_err = vfs_link(dold, dirp, dnew); if (!host_err) { err = nfserrno(commit_metadata(ffhp)); -- cgit v1.2.3 From c8fb13d04ad0d08772f637bee873e620fcc064c2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 27 May 2011 13:56:12 -0700 Subject: OMAP: PM debug: fix section mismatch warnings WARNING: arch/arm/mach-omap2/built-in.o(.text+0x423c): Section mismatch in reference from the function pm_dbg_regset_init() to the function .init.text:pm_dbg_init() The function pm_dbg_regset_init() references the function __init pm_dbg_init(). This is often because pm_dbg_regset_init lacks a __init annotation or the annotation of pm_dbg_init is wrong. Signed-off-by: Russell King Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/pm-debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index a5a83b358ddd..e01da45c0537 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -189,7 +189,7 @@ static struct dentry *pm_dbg_dir; static int pm_dbg_init_done; -static int __init pm_dbg_init(void); +static int pm_dbg_init(void); enum { DEBUG_FILE_COUNTERS = 0, @@ -595,7 +595,7 @@ static int option_set(void *data, u64 val) DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n"); -static int __init pm_dbg_init(void) +static int pm_dbg_init(void) { int i; struct dentry *d; -- cgit v1.2.3 From 345f79b3de7f6d651e4dba794af7c7303bdfd649 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 31 May 2011 16:08:09 -0700 Subject: OMAP: PM: omap_device: fix device power domain callbacks After commit 4d27e9dcff00a6425d779b065ec8892e4f391661 (PM: Make power domain callbacks take precedence over subsystem ones), the power domain callbacks need to call the driver callbacks instead of relying on the default subsystem (in this case, platform_bus) to handle the driver callbacks. Validated on 3430/n900, 3530/Overo. Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/omap_device.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index a37b8eb65b76..49fc0df0c21f 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -84,6 +84,7 @@ #include #include #include +#include #include #include @@ -539,20 +540,34 @@ int omap_early_device_register(struct omap_device *od) static int _od_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); + int ret; + + ret = pm_generic_runtime_suspend(dev); + + if (!ret) + omap_device_idle(pdev); + + return ret; +} - return omap_device_idle(pdev); +static int _od_runtime_idle(struct device *dev) +{ + return pm_generic_runtime_idle(dev); } static int _od_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - return omap_device_enable(pdev); + omap_device_enable(pdev); + + return pm_generic_runtime_resume(dev); } static struct dev_power_domain omap_device_power_domain = { .ops = { .runtime_suspend = _od_runtime_suspend, + .runtime_idle = _od_runtime_idle, .runtime_resume = _od_runtime_resume, USE_PLATFORM_PM_SLEEP_OPS } -- cgit v1.2.3 From 3019de124b9f5b1526cb3668b74af14371e21795 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 6 Jun 2011 16:41:33 -0700 Subject: net: Rework netdev_drivername() to avoid warning. This interface uses a temporary buffer, but for no real reason. And now can generate warnings like: net/sched/sch_generic.c: In function dev_watchdog net/sched/sch_generic.c:254:10: warning: unused variable drivername Just return driver->name directly or "". Reported-by: Connor Hansen Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- net/core/dev.c | 16 +++++----------- net/sched/sch_generic.c | 3 +-- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ca333e79e10f..54b8b4d7b68f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2555,7 +2555,7 @@ extern void netdev_class_remove_file(struct class_attribute *class_attr); extern struct kobj_ns_type_operations net_ns_type_operations; -extern char *netdev_drivername(const struct net_device *dev, char *buffer, int len); +extern const char *netdev_drivername(const struct net_device *dev); extern void linkwatch_run_queue(void); diff --git a/net/core/dev.c b/net/core/dev.c index 939307891e71..1af6cb27f67a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6264,29 +6264,23 @@ err_name: /** * netdev_drivername - network driver for the device * @dev: network device - * @buffer: buffer for resulting name - * @len: size of buffer * * Determine network driver for device. */ -char *netdev_drivername(const struct net_device *dev, char *buffer, int len) +const char *netdev_drivername(const struct net_device *dev) { const struct device_driver *driver; const struct device *parent; - - if (len <= 0 || !buffer) - return buffer; - buffer[0] = 0; + const char *empty = ""; parent = dev->dev.parent; - if (!parent) - return buffer; + return empty; driver = parent->driver; if (driver && driver->name) - strlcpy(buffer, driver->name, len); - return buffer; + return driver->name; + return empty; } static int __netdev_printk(const char *level, const struct net_device *dev, diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index b1721d71c27c..b4c680900d7a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -251,9 +251,8 @@ static void dev_watchdog(unsigned long arg) } if (some_queue_timedout) { - char drivername[64]; WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n", - dev->name, netdev_drivername(dev, drivername, 64), i); + dev->name, netdev_drivername(dev), i); dev->netdev_ops->ndo_tx_timeout(dev); } if (!mod_timer(&dev->watchdog_timer, -- cgit v1.2.3 From 79b3891587741dfac72cdfead1f2764b56a567b0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 6 Jun 2011 17:00:35 -0700 Subject: irda: iriap: Use seperate lockdep class for irias_objects->hb_spinlock The SEQ output functions grab the obj->attrib->hb_spinlock lock of sub-objects found in the hash traversal. These locks are in a different realm than the one used for the irias_objects hash table itself. So put the latter into it's own lockdep class. Reported-by: Dave Jones Signed-off-by: David S. Miller --- net/irda/iriap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 36477538cea8..f876eed7d4aa 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -87,6 +87,8 @@ static inline void iriap_start_watchdog_timer(struct iriap_cb *self, iriap_watchdog_timer_expired); } +static struct lock_class_key irias_objects_key; + /* * Function iriap_init (void) * @@ -114,6 +116,9 @@ int __init iriap_init(void) return -ENOMEM; } + lockdep_set_class_and_name(&irias_objects->hb_spinlock, &irias_objects_key, + "irias_objects"); + /* * Register some default services for IrLMP */ -- cgit v1.2.3 From 0aff1c0cef13b34c17e81a502336fad738151c37 Mon Sep 17 00:00:00 2001 From: GuoWen Li Date: Wed, 1 Jun 2011 19:18:47 +0800 Subject: ftrace: Fix possible undefined return code kernel/trace/ftrace.c: In function 'ftrace_regex_write.clone.15': kernel/trace/ftrace.c:2743:6: warning: 'ret' may be used uninitialized in this function Signed-off-by: GuoWen Li Link: http://lkml.kernel.org/r/201106011918.47939.guowen.li.linux@gmail.com Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 1ee417fcbfa5..204b3eb4e690 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2740,7 +2740,7 @@ static int ftrace_process_regex(struct ftrace_hash *hash, { char *func, *command, *next = buff; struct ftrace_func_command *p; - int ret; + int ret = -EINVAL; func = strsep(&next, ":"); -- cgit v1.2.3 From 0a1896b27b030529ec770aefd790544a1bdb7d5a Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Mon, 6 Jun 2011 18:55:34 -0400 Subject: ALSA: hda: Fix quirk for Dell Inspiron 910 BugLink: https://launchpad.net/bugs/792712 The original reporter states that sound from the internal speakers is inaudible until using the model=auto quirk. This symptom is due to an existing quirk mask for 0x102802b* that uses the model=dell quirk. To limit the possible regressions, leave the existing quirk mask but add a higher priority specific mask for the reporter's PCI SSID. Reported-and-tested-by: rodni hipp Cc: [2.6.38+] Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7a4e10002f56..d7007896772b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13860,6 +13860,7 @@ static const struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One", ALC268_ACER_ASPIRE_ONE), SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL), + SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO), SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0, "Dell Inspiron Mini9/Vostro A90", ALC268_DELL), /* almost compatible with toshiba but with optional digital outs; -- cgit v1.2.3 From 13fcb7bd322164c67926ffe272846d4860196dc6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 6 Jun 2011 22:42:06 -0700 Subject: af_packet: prevent information leak In 2.6.27, commit 393e52e33c6c2 (packet: deliver VLAN TCI to userspace) added a small information leak. Add padding field and make sure its zeroed before copy to user. Signed-off-by: Eric Dumazet CC: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/if_packet.h | 2 ++ net/packet/af_packet.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index 6d66ce1791a9..7b318630139f 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h @@ -62,6 +62,7 @@ struct tpacket_auxdata { __u16 tp_mac; __u16 tp_net; __u16 tp_vlan_tci; + __u16 tp_padding; }; /* Rx ring - header status */ @@ -101,6 +102,7 @@ struct tpacket2_hdr { __u32 tp_sec; __u32 tp_nsec; __u16 tp_vlan_tci; + __u16 tp_padding; }; #define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll)) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ba248d93399a..c0c3cda19712 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -804,6 +804,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, } else { h.h2->tp_vlan_tci = 0; } + h.h2->tp_padding = 0; hdrlen = sizeof(*h.h2); break; default: @@ -1736,6 +1737,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, } else { aux.tp_vlan_tci = 0; } + aux.tp_padding = 0; put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux); } -- cgit v1.2.3 From 6407d74c5106bb362b4087693688afd34942b094 Mon Sep 17 00:00:00 2001 From: Alexander Holler Date: Tue, 7 Jun 2011 00:51:35 -0700 Subject: bridge: provide a cow_metrics method for fake_ops Like in commit 0972ddb237 (provide cow_metrics() methods to blackhole dst_ops), we must provide a cow_metrics for bridges fake_dst_ops as well. This fixes a regression coming from commits 62fa8a846d7d (net: Implement read-only protection and COW'ing of metrics.) and 33eb9873a28 (bridge: initialize fake_rtable metrics) ip link set mybridge mtu 1234 --> [ 136.546243] Pid: 8415, comm: ip Tainted: P 2.6.39.1-00006-g40545b7 #103 ASUSTeK Computer Inc. V1Sn /V1Sn [ 136.546256] EIP: 0060:[<00000000>] EFLAGS: 00010202 CPU: 0 [ 136.546268] EIP is at 0x0 [ 136.546273] EAX: f14a389c EBX: 000005d4 ECX: f80d32c0 EDX: f80d1da1 [ 136.546279] ESI: f14a3000 EDI: f255bf10 EBP: f15c3b54 ESP: f15c3b48 [ 136.546285] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 136.546293] Process ip (pid: 8415, ti=f15c2000 task=f4741f80 task.ti=f15c2000) [ 136.546297] Stack: [ 136.546301] f80c658f f14a3000 ffffffed f15c3b64 c12cb9c8 f80d1b80 ffffffa1 f15c3bbc [ 136.546315] c12da347 c12d9c7d 00000000 f7670b00 00000000 f80d1b80 ffffffa6 f15c3be4 [ 136.546329] 00000004 f14a3000 f255bf20 00000008 f15c3bbc c11d6cae 00000000 00000000 [ 136.546343] Call Trace: [ 136.546359] [] ? br_change_mtu+0x5f/0x80 [bridge] [ 136.546372] [] dev_set_mtu+0x38/0x80 [ 136.546381] [] do_setlink+0x1a7/0x860 [ 136.546390] [] ? rtnl_fill_ifinfo+0x9bd/0xc70 [ 136.546400] [] ? nla_parse+0x6e/0xb0 [ 136.546409] [] rtnl_newlink+0x361/0x510 [ 136.546420] [] ? vmalloc_sync_all+0x100/0x100 [ 136.546429] [] ? error_code+0x5a/0x60 [ 136.546438] [] ? rtnl_configure_link+0x80/0x80 [ 136.546446] [] rtnetlink_rcv_msg+0xfa/0x210 [ 136.546454] [] ? __rtnl_unlock+0x20/0x20 [ 136.546463] [] netlink_rcv_skb+0x8e/0xb0 [ 136.546471] [] rtnetlink_rcv+0x1c/0x30 [ 136.546479] [] netlink_unicast+0x23a/0x280 [ 136.546487] [] netlink_sendmsg+0x26b/0x2f0 [ 136.546497] [] sock_sendmsg+0xc8/0x100 [ 136.546508] [] ? __alloc_pages_nodemask+0xe1/0x750 [ 136.546517] [] ? _copy_from_user+0x42/0x60 [ 136.546525] [] ? verify_iovec+0x4c/0xc0 [ 136.546534] [] sys_sendmsg+0x1c5/0x200 [ 136.546542] [] ? __do_fault+0x310/0x410 [ 136.546549] [] ? do_wp_page+0x1d6/0x6b0 [ 136.546557] [] ? handle_pte_fault+0xe1/0x720 [ 136.546565] [] ? sys_getsockname+0x7f/0x90 [ 136.546574] [] ? handle_mm_fault+0xb1/0x180 [ 136.546582] [] ? vmalloc_sync_all+0x100/0x100 [ 136.546589] [] ? do_page_fault+0x173/0x3d0 [ 136.546596] [] ? sys_recvmsg+0x3b/0x60 [ 136.546605] [] sys_socketcall+0x293/0x2d0 [ 136.546614] [] sysenter_do_call+0x12/0x26 [ 136.546619] Code: Bad EIP value. [ 136.546627] EIP: [<00000000>] 0x0 SS:ESP 0068:f15c3b48 [ 136.546645] CR2: 0000000000000000 [ 136.546652] ---[ end trace 6909b560e78934fa ]--- Signed-off-by: Alexander Holler Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/bridge/br_netfilter.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 3fa123185e89..56149ec36d7f 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -104,10 +104,16 @@ static void fake_update_pmtu(struct dst_entry *dst, u32 mtu) { } +static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old) +{ + return NULL; +} + static struct dst_ops fake_dst_ops = { .family = AF_INET, .protocol = cpu_to_be16(ETH_P_IP), .update_pmtu = fake_update_pmtu, + .cow_metrics = fake_cow_metrics, }; /* -- cgit v1.2.3 From 264524d5e5195f6e0f099bee20253a22b651e272 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 6 Jun 2011 20:50:03 +0000 Subject: net: cpu offline cause napi stall Frank Blaschka reported : During heavy network load we turn off/on cpus. Sometimes this causes a stall on the network device. Digging into the dump I found out following: napi is scheduled but does not run. From the I/O buffers and the napi state I see napi/rx_softirq processing has stopped because the budget was reached. napi stays in the softnet_data poll_list and the rx_softirq was raised again. I assume at this time the cpu offline comes in, the rx softirq is raised/moved to another cpu but napi stays in the poll_list of the softnet_data of the now offline cpu. Reviewing dev_cpu_callback (net/core/dev.c) I did not find the poll_list is transfered to the new cpu. This patch is a straightforward implementation of Frank suggestion : Transfert poll_list and trigger NET_RX_SOFTIRQ on new cpu. Reported-by: Frank Blaschka Signed-off-by: Heiko Carstens Signed-off-by: Eric Dumazet Tested-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 1af6cb27f67a..a54c9f87ddbb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6178,6 +6178,11 @@ static int dev_cpu_callback(struct notifier_block *nfb, oldsd->output_queue = NULL; oldsd->output_queue_tailp = &oldsd->output_queue; } + /* Append NAPI poll list from offline CPU. */ + if (!list_empty(&oldsd->poll_list)) { + list_splice_init(&oldsd->poll_list, &sd->poll_list); + raise_softirq_irqoff(NET_RX_SOFTIRQ); + } raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); -- cgit v1.2.3 From 064d58ee3afb8a865a72d24e069c7258ec38640e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 7 Jun 2011 10:24:46 +0200 Subject: ASoC: Blackfin: bf5xx-ad1836: Fix codec device name Fix the codec_name field of the dai_link to match the actual device name of the codec. Otherwise the card won't be instantiated. Signed-off-by: Lars-Peter Clausen Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/blackfin/bf5xx-ad1836.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index ea4951cf5526..f79d1655e035 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c @@ -75,7 +75,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { .cpu_dai_name = "bfin-tdm.0", .codec_dai_name = "ad1836-hifi", .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "ad1836.0", + .codec_name = "spi0.4", .ops = &bf5xx_ad1836_ops, }, { @@ -84,7 +84,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { .cpu_dai_name = "bfin-tdm.1", .codec_dai_name = "ad1836-hifi", .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "ad1836.0", + .codec_name = "spi0.4", .ops = &bf5xx_ad1836_ops, }, }; -- cgit v1.2.3 From 942fd4225f72826b31d893582b6ae7e172bb3202 Mon Sep 17 00:00:00 2001 From: Austin Zhang Date: Sat, 28 May 2011 02:03:47 +0800 Subject: HID: hid-multitouch: add support for Chunghwa multi-touch panel Added Chunghwa hid multitouch panel support into hid-multitouch. Signed-off-by: Austin Zhang Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 5 +++++ 4 files changed, 10 insertions(+) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 67d2a7585934..36ca465c00ce 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -305,6 +305,7 @@ config HID_MULTITOUCH - 3M PCT touch screens - ActionStar dual touch panels - Cando dual touch panels + - Chunghwa panels - CVTouch panels - Cypress TrueTouch panels - Elo TouchSystems IntelliTouch Plus panels diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c957c4b4fe70..f7440e8ce3e7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1359,6 +1359,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2bbaad70d76d..aecb5a4b8d6d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -173,6 +173,9 @@ #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 +#define USB_VENDOR_ID_CHUNGHWAT 0x2247 +#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 + #define USB_VENDOR_ID_CIDC 0x1677 #define USB_VENDOR_ID_CMEDIA 0x0d8c diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index ecd4d2db9e80..8bc32a0fa00e 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -593,6 +593,11 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, + /* Chunghwa Telecom touch panels */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, + USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, + /* CVTouch panels */ { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, -- cgit v1.2.3 From c2f019713df67e09d32e1b3c12f147a83a579d25 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 1 Jun 2011 10:59:13 -0700 Subject: HID: MAINTAINERS: Update USB HID/HIDBP DRIVERS pattern It was moved by commit 1a978c50c6cf ("HID: Move hiddev.txt to the new Documentation/hid directory") so update the MAINTAINERS pattern too. cc: Jiri Kosina cc: Alan Ott Signed-off-by: Joe Perches Signed-off-by: Jiri Kosina --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0b415248ae25..8bd7caefd855 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6423,7 +6423,7 @@ M: Jiri Kosina L: linux-usb@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained -F: Documentation/usb/hiddev.txt +F: Documentation/hid/hiddev.txt F: drivers/hid/usbhid/ USB ISP116X DRIVER -- cgit v1.2.3 From af99d6f0037d970084b03d9690f50e34d6f70dae Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Wed, 1 Jun 2011 14:38:41 -0400 Subject: serial: ioremap warning fix for jsm driver. I saw a warning about ioremap from the jsm driver on a system which looked like this: resource map sanity check conflict: 0xe0200800 0xe02017ff 0xe0200800 0xe0200fff 0000:01:08.0 Turns out the warning is valid. The jsm driver has been asking to ioremap 0x1000 forever, but in fact only 8 port chips have 0x1000 bytes of memory. 4 port chips have 0x800 and 2 port chips have 0x400 according to the data sheet. It makes more sense to map the size of the region rather than a hard coded value. If you happen to have the region legitimately mapped to a base address that is not 4K aligned, ioremap complains otherwise. Signed-off-by: Len Sorensen Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/jsm/jsm_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index 18f548449c63..96da17868cf3 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c @@ -125,7 +125,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device brd->bd_uart_offset = 0x200; brd->bd_dividend = 921600; - brd->re_map_membase = ioremap(brd->membase, 0x1000); + brd->re_map_membase = ioremap(brd->membase, pci_resource_len(pdev, 0)); if (!brd->re_map_membase) { dev_err(&pdev->dev, "card has no PCI Memory resources, " -- cgit v1.2.3 From 470f22975448a65a1084a6f0721fa5df15323f02 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Fri, 27 May 2011 19:04:03 -0700 Subject: ARM: SAMSUNG: serial: Fix on handling of one clock source for UART This patch fixes the way of comparison for handling of two or more clock sources for UART. For example, if just only one clock source is defined even though there are two clock sources for UART, the serial driver does not set proper clock up. Of course, it is problem. So this patch changes the condition of comparison to avoid useless setup clock and adds a flag 'NO_NEED_CHECK_CLKSRC' which means selection of source clock is not required. In addition, since the Exynos4210 has only one clock source for UART this patch adds the flag into its common_init_uarts(). Signed-off-by: Boojin Kim Signed-off-by: Kukjin Kim Cc: stable Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-exynos4/init.c | 1 + arch/arm/plat-samsung/include/plat/regs-serial.h | 2 ++ drivers/tty/serial/s5pv210.c | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos4/init.c b/arch/arm/mach-exynos4/init.c index cf91f50e43ab..a8a83e3881a4 100644 --- a/arch/arm/mach-exynos4/init.c +++ b/arch/arm/mach-exynos4/init.c @@ -35,6 +35,7 @@ void __init exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) tcfg->clocks = exynos4_serial_clocks; tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks); } + tcfg->flags |= NO_NEED_CHECK_CLKSRC; } s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no); diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h index c151c5f94a87..116edfe120b9 100644 --- a/arch/arm/plat-samsung/include/plat/regs-serial.h +++ b/arch/arm/plat-samsung/include/plat/regs-serial.h @@ -224,6 +224,8 @@ #define S5PV210_UFSTAT_RXMASK (255<<0) #define S5PV210_UFSTAT_RXSHIFT (0) +#define NO_NEED_CHECK_CLKSRC 1 + #ifndef __ASSEMBLY__ /* struct s3c24xx_uart_clksrc diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c index fb2619f93d84..dd194dc80ee9 100644 --- a/drivers/tty/serial/s5pv210.c +++ b/drivers/tty/serial/s5pv210.c @@ -30,7 +30,7 @@ static int s5pv210_serial_setsource(struct uart_port *port, struct s3c2410_uartcfg *cfg = port->dev->platform_data; unsigned long ucon = rd_regl(port, S3C2410_UCON); - if ((cfg->clocks_size) == 1) + if (cfg->flags & NO_NEED_CHECK_CLKSRC) return 0; if (strcmp(clk->name, "pclk") == 0) @@ -55,7 +55,7 @@ static int s5pv210_serial_getsource(struct uart_port *port, clk->divisor = 1; - if ((cfg->clocks_size) == 1) + if (cfg->flags & NO_NEED_CHECK_CLKSRC) return 0; switch (ucon & S5PV210_UCON_CLKMASK) { -- cgit v1.2.3 From 1798ca13bfae8cc7c0ef82c034c3c4951ecaeb88 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 May 2011 12:35:48 +0100 Subject: 8250_pci: Fix missing const from merges Signed-off-by: Alan Cox Signed-off-by: Antony Pavlov Signed-off-by: Borislav Petkov Signed-off-by: Vasily Averin Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index d7dc513451a6..f41b4259ecdd 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -973,7 +973,7 @@ ce4100_serial_setup(struct serial_private *priv, static int pci_omegapci_setup(struct serial_private *priv, - struct pciserial_board *board, + const struct pciserial_board *board, struct uart_port *port, int idx) { return setup_port(priv, port, 2, idx * 8, 0); -- cgit v1.2.3 From cb01ece3ea5dec16ac7bab30069c7736b59f7dea Mon Sep 17 00:00:00 2001 From: "leitao@linux.vnet.ibm.com" Date: Thu, 26 May 2011 11:18:39 -0300 Subject: 8250: Fix capabilities when changing the port type When changing the port type, the capabilities flags should be changed also, otherwise the capabilities will not correspond to the port type, which make set_sleep() crash on rmmod. This patch just assign the correct capabilites when the port changes. Signed-off-by: Breno Leitao CC: Michael Reed Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index b40f7b90c81d..b4129f53fb1b 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -3318,6 +3318,7 @@ void serial8250_unregister_port(int line) uart->port.flags &= ~UPF_BOOT_AUTOCONF; uart->port.type = PORT_UNKNOWN; uart->port.dev = &serial8250_isa_devs->dev; + uart->capabilities = uart_config[uart->port.type].flags; uart_add_one_port(&serial8250_reg, &uart->port); } else { uart->port.dev = NULL; -- cgit v1.2.3 From 5daf538a0313509ecdeb5b7a61257f39881f9361 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 22 May 2011 17:38:02 -0700 Subject: firmware: fix GOOGLE_SMI kconfig dependency warning Is it meaningful/useful to enable EFI_VARS but not EFI? That's what GOOGLE_SMI does. Make it enable EFI also. Fixes this kconfig dependency warning: warning: (GOOGLE_SMI) selects EFI_VARS which has unmet direct dependencies (EFI) Signed-off-by: Randy Dunlap Acked-by: Mike Waychison Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig index 87096b6ca5c9..2f21b0bfe653 100644 --- a/drivers/firmware/google/Kconfig +++ b/drivers/firmware/google/Kconfig @@ -13,6 +13,7 @@ menu "Google Firmware Drivers" config GOOGLE_SMI tristate "SMI interface for Google platforms" depends on ACPI && DMI + select EFI select EFI_VARS help Say Y here if you want to enable SMI callbacks for Google -- cgit v1.2.3 From 7316a9f2a94c14e66e9421a777dffc509a2fe0e3 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 23 May 2011 16:45:32 -0400 Subject: st_kim: Handle case of no device found for ID 0 Running ktest.pl, I hit this bug: [ 19.780654] BUG: unable to handle kernel NULL pointer dereference at 0000000c [ 19.780660] IP: [] dev_get_drvdata+0xc/0x46 [ 19.780669] *pdpt = 0000000031daf001 *pde = 0000000000000000 [ 19.780673] Oops: 0000 [#1] SMP [ 19.780680] Dumping ftrace buffer:^M [ 19.780685] (ftrace buffer empty) [ 19.780687] Modules linked in: ide_pci_generic firewire_ohci firewire_core evbug crc_itu_t e1000 ide_core i2c_i801 iTCO_wdt [ 19.780697] [ 19.780700] Pid: 346, comm: v4l_id Not tainted 2.6.39-test-02740-gcaebc16-dirty #4 /DG965MQ [ 19.780706] EIP: 0060:[] EFLAGS: 00010202 CPU: 0 [ 19.780709] EIP is at dev_get_drvdata+0xc/0x46 [ 19.780712] EAX: 00000008 EBX: f1e37da4 ECX: 00000000 EDX: 00000000 [ 19.780715] ESI: f1c3f200 EDI: c33ec95c EBP: f1e37d80 ESP: f1e37d80 [ 19.780718] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 19.780721] Process v4l_id (pid: 346, ti=f1e36000 task=f2bc2a60 task.ti=f1e36000) [ 19.780723] Stack: [ 19.780725] f1e37d8c c117d395 c33ec93c f1e37db4 c117a0f9 00000002 00000000 c1725e54 [ 19.780732] 00000001 00000007 f2918c90 f1c3f200 c33ec95c f1e37dd4 c1789d3d 22222222 [ 19.780740] 22222222 22222222 f2918c90 f1c3f200 f29194f4 f1e37de8 c178d5c4 c1725e54 [ 19.780747] Call Trace: [ 19.780752] [] st_kim_ref+0x28/0x41 [ 19.780756] [] st_register+0x29/0x562 [ 19.780761] [] ? v4l2_open+0x111/0x1e3 [ 19.780766] [] fmc_prepare+0x97/0x424 [ 19.780770] [] fm_v4l2_fops_open+0x70/0x106 [ 19.780773] [] ? v4l2_open+0x111/0x1e3 [ 19.780777] [] v4l2_open+0x158/0x1e3 [ 19.780782] [] chrdev_open+0x22c/0x276 [ 19.780787] [] __dentry_open+0x35c/0x581 [ 19.780792] [] nameidata_to_filp+0x7c/0x96 [ 19.780795] [] ? cdev_put+0x57/0x57 [ 19.780800] [] do_last+0x743/0x9d4 [ 19.780804] [] ? path_init+0x1ee/0x596 [ 19.780808] [] path_openat+0x10c/0x597 [ 19.780813] [] ? trace_hardirqs_off+0x27/0x37 [ 19.780817] [] ? local_clock+0x78/0xc7 [ 19.780821] [] do_filp_open+0x39/0xc2 [ 19.780827] [] ? _raw_spin_unlock+0x4c/0x5d^M [ 19.780831] [] ? alloc_fd+0x19e/0x1b7 [ 19.780836] [] do_sys_open+0xb7/0x1bd [ 19.780840] [] ? sys_munmap+0x78/0x8d [ 19.780844] [] sys_open+0x36/0x58 [ 19.780849] [] sysenter_do_call+0x12/0x38 [ 19.780852] Code: d8 2f 20 c3 01 83 15 dc 2f 20 c3 00 f0 ff 00 83 05 e0 2f 20 c3 01 83 15 e4 2f 20 c3 00 5d c3 55 89 e5 3e 8d 74 26 00 85 c0 74 28 <8b> 40 04 83 05 e8 2f 20 c3 01 83 15 ec 2f 20 c3 00 85 c0 74 13 ^M [ 19.780889] EIP: [] dev_get_drvdata+0xc/0x46 SS:ESP 0068:f1e37d80 [ 19.780894] CR2: 000000000000000c [ 19.780898] ---[ end trace e7d1d0f6a2d1d390 ]--- The id of 0 passed to st_kim_ref() found no device, keeping pdev null, and causing pdev->dev cause a NULL pointer dereference. After having st_kim_ref() check for NULL, the st_unregister() function needed to be updated to handle the case that st_gdata was not set by the st_kim_ref(). Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_core.c | 2 +- drivers/misc/ti-st/st_kim.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index f91f82eabda7..54c91ffe4a91 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -605,7 +605,7 @@ long st_unregister(struct st_proto_s *proto) pr_debug("%s: %d ", __func__, proto->chnl_id); st_kim_ref(&st_gdata, 0); - if (proto->chnl_id >= ST_MAX_CHANNELS) { + if (!st_gdata || proto->chnl_id >= ST_MAX_CHANNELS) { pr_err(" chnl_id %d not supported", proto->chnl_id); return -EPROTONOSUPPORT; } diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 5da93ee6f6be..3613c3bc4da3 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -604,6 +604,10 @@ void st_kim_ref(struct st_data_s **core_data, int id) struct kim_data_s *kim_gdata; /* get kim_gdata reference from platform device */ pdev = st_get_plat_device(id); + if (!pdev) { + *core_data = NULL; + return; + } kim_gdata = dev_get_drvdata(&pdev->dev); *core_data = kim_gdata->core_data; } -- cgit v1.2.3 From bb2b43fefab723f4a0760146e7bed59d41a50e53 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 23 May 2011 14:44:19 -0700 Subject: drivers/base/platform.c: don't mark platform_device_register_resndata() as __init_or_module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts 737a3bb9416ce2a7c7a4 ("Driver core: move platform device creation helpers to .init.text (if MODULE=n)"). That patch assumed that platform_device_register_resndata() is only ever called from __init code but that isn't true in the case ioctl->drm_ioctl->radeon_cp_init(). Addresses https://bugzilla.kernel.org/show_bug.cgi?id=35192 Cc: Uwe Kleine-König Reported-by: Anthony Basile Cc: Greg KH Cc: David Airlie Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 1c291af637b3..6040717b62bb 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -367,7 +367,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); * * Returns &struct platform_device pointer on success, or ERR_PTR() on error. */ -struct platform_device *__init_or_module platform_device_register_resndata( +struct platform_device *platform_device_register_resndata( struct device *parent, const char *name, int id, const struct resource *res, unsigned int num, -- cgit v1.2.3 From 9d031d94da453077bbc6108b7822fc751ac85299 Mon Sep 17 00:00:00 2001 From: Shahar Lev Date: Mon, 23 May 2011 11:36:11 +0300 Subject: drivers:misc: ti-st: fix skipping of change remote baud Before the incrementing of ptr in skip_change_remote_baud, it points to cur_action, but the increment is done by the size of nxt_action instead. This could cause ptr to not point to a bts_action structure, which is harmful for the increment of ptr done in download_firmware. Therefore, the skipping is first done for cur_action. Signed-off-by: Shahar Lev Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_kim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 3613c3bc4da3..38fd2f04c07e 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -245,9 +245,9 @@ void skip_change_remote_baud(unsigned char **ptr, long *len) pr_err("invalid action after change remote baud command"); } else { *ptr = *ptr + sizeof(struct bts_action) + - ((struct bts_action *)nxt_action)->size; + ((struct bts_action *)cur_action)->size; *len = *len - (sizeof(struct bts_action) + - ((struct bts_action *)nxt_action)->size); + ((struct bts_action *)cur_action)->size); /* warn user on not commenting these in firmware */ pr_warn("skipping the wait event of change remote baud"); } -- cgit v1.2.3 From 29021bccea0dc42d7d101004058438a9a4e693b1 Mon Sep 17 00:00:00 2001 From: J Freyensee Date: Wed, 25 May 2011 14:38:18 -0700 Subject: pti: double-free security PTI fix This patch fixes a double-free error that will not always be seen unless /dev/pti char interface is stressed. Signed-off-by: J Freyensee Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pti.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index bb6f9255c17c..be4857358d91 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c @@ -317,7 +317,8 @@ EXPORT_SYMBOL_GPL(pti_request_masterchannel); * a master, channel ID address * used to write to PTI HW. * - * @mc: master, channel apeture ID address to be released. + * @mc: master, channel apeture ID address to be released. This + * will de-allocate the structure via kfree(). */ void pti_release_masterchannel(struct pti_masterchannel *mc) { @@ -581,7 +582,7 @@ static int pti_char_open(struct inode *inode, struct file *filp) static int pti_char_release(struct inode *inode, struct file *filp) { pti_release_masterchannel(filp->private_data); - kfree(filp->private_data); + filp->private_data = NULL; return 0; } -- cgit v1.2.3 From 1dae42bff57f7a61577ee881265985a660d35c07 Mon Sep 17 00:00:00 2001 From: J Freyensee Date: Wed, 25 May 2011 14:45:40 -0700 Subject: pti: ENXIO error case memory leak PTI fix. This patch fixes a memory leak that can occur in the error case ENXIO is returned in the pti_tty_install() routine. Signed-off-by: J Freyensee Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pti.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index be4857358d91..e74e7d266569 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c @@ -476,8 +476,10 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty) else pti_tty_data->mc = pti_request_masterchannel(2); - if (pti_tty_data->mc == NULL) + if (pti_tty_data->mc == NULL) { + kfree(pti_tty_data); return -ENXIO; + } tty->driver_data = pti_tty_data; } -- cgit v1.2.3 From 1312ba40c0d00f0a5cfcfe3afc222fcef2a90b56 Mon Sep 17 00:00:00 2001 From: J Freyensee Date: Wed, 25 May 2011 14:56:43 -0700 Subject: pti: PTI semantics fix in pti_tty_cleanup. This patch fixes a semantics issue in the pti_tty_cleanup() routine. Signed-off-by: J Freyensee Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index e74e7d266569..374dfcfccd07 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c @@ -498,7 +498,7 @@ static void pti_tty_cleanup(struct tty_struct *tty) if (pti_tty_data == NULL) return; pti_release_masterchannel(pti_tty_data->mc); - kfree(tty->driver_data); + kfree(pti_tty_data); tty->driver_data = NULL; } -- cgit v1.2.3 From 92f6fa09bd453ffe3351fa1f1377a1b7cfa911e6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 5 Jun 2011 14:16:16 +0200 Subject: TTY: ldisc, do not close until there are readers We restored tty_ldisc_wait_idle in 100eeae2c5c (TTY: restore tty_ldisc_wait_idle). We used it in the ldisc changing path to fix the case where there are tasks in n_tty_read waiting for data and somebody tries to change ldisc. Similar to the case above, there may be also tasks waiting in n_tty_read while hangup is performed. As 65b770468e98 (tty-ldisc: turn ldisc user count into a proper refcount) removed the wait-until-idle from all paths, hangup path won't wait for them to disappear either now. So add it back even to the hangup path. There is a difference, we need uninterruptible sleep as there is obviously HUP signal pending. So tty_ldisc_wait_idle now sleeps without possibility to be interrupted. This is what original tty_ldisc_wait_idle did. After the wait idle reintroduction (100eeae2c5c), we have had interruptible sleeps for the ldisc changing path. But as there is a 5s timeout anyway, we don't allow it to be interrupted from now on. It's not worth the added complexity of deciding what kind of sleep we want. Before 65b770468e98 tty_ldisc_release was called also from tty_ldisc_release. It is called from tty_release, so I don't think we need to restore that one. This is nicely reproducible after constifying the timing when drivers/tty/n_tty.c is patched as follows ("TTY: ntty, add one more sanity check" patch is needed to actually see it explode): %% -1548,6 +1549,7 @@ static int n_tty_open(struct tty_struct *tty) /* These are ugly. Currently a malloc failure here can panic */ if (!tty->read_buf) { + msleep(100); tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); if (!tty->read_buf) return -ENOMEM; %% -1785,6 +1788,7 @@ do_it_again: break; } timeout = schedule_timeout(timeout); + msleep(20); continue; } __set_current_state(TASK_RUNNING); ===== With a process: ===== while (1) { int fd = open(argv[1], O_RDWR); read(fd, buf, sizeof(buf)); close(fd); } ===== and its child: ===== setsid(); while (1) { int fd = open(tty, O_RDWR|O_NOCTTY); ioctl(fd, TIOCSCTTY, 1); vhangup(); close(fd); usleep(100 * (10 + random() % 1000)); } ===== EOF ===== References: https://bugzilla.novell.com/show_bug.cgi?id=693374 References: https://bugzilla.novell.com/show_bug.cgi?id=694509 Signed-off-by: Jiri Slaby Cc: Alan Cox Cc: Linus Torvalds Cc: stable [32, 33, 34, 39] Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 5d01d32e2cf0..ef925d581713 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -555,7 +555,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) static int tty_ldisc_wait_idle(struct tty_struct *tty) { int ret; - ret = wait_event_interruptible_timeout(tty_ldisc_idle, + ret = wait_event_timeout(tty_ldisc_idle, atomic_read(&tty->ldisc->users) == 1, 5 * HZ); if (ret < 0) return ret; @@ -763,6 +763,8 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) if (IS_ERR(ld)) return -1; + WARN_ON_ONCE(tty_ldisc_wait_idle(tty)); + tty_ldisc_close(tty, tty->ldisc); tty_ldisc_put(tty->ldisc); tty->ldisc = NULL; -- cgit v1.2.3 From 2872628680bad71a6734e7d379168f990a91cc09 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 5 Jun 2011 14:16:17 +0200 Subject: TTY: ntty, add one more sanity check With the previous patch, we fixed another bug where read_buf was freed while we still was in n_tty_read. We currently check whether read_buf is NULL at the start of the function. Add one more check after we wake up from waiting for input. Signed-off-by: Jiri Slaby Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0ad32888091c..c3954fbf6ac4 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1815,6 +1815,7 @@ do_it_again: /* FIXME: does n_tty_set_room need locking ? */ n_tty_set_room(tty); timeout = schedule_timeout(timeout); + BUG_ON(!tty->read_buf); continue; } __set_current_state(TASK_RUNNING); -- cgit v1.2.3 From bb77f6341728624314f488ebd8b4c69f2caa33ea Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 7 Jun 2011 14:03:08 -0400 Subject: Revert "mac80211: stop queues before rate control updation" This reverts commit 1d38c16ce4156f63b45abbd09dd28ca2ef5172b4. The mac80211 maintainer raised complaints about abuse of the CSA stop reason, and about whether this patch actually serves its intended purpose at all. Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 456cccf26b51..d595265d6c22 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -232,9 +232,6 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); } - ieee80211_stop_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CSA); - /* channel_type change automatically detected */ ieee80211_hw_config(local, 0); @@ -248,9 +245,6 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); } - ieee80211_wake_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CSA); - ht_opmode = le16_to_cpu(hti->operation_mode); /* if bss configuration changed store the new one */ -- cgit v1.2.3 From 4fea2e0e59dab863a63fa1638b86d850896cd861 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Tue, 31 May 2011 08:50:24 +0900 Subject: rtlwifi: Fix logic in rx_interrupt Should pass along packet if there's no CRC and no hardware error. Signed-off-by: Mike McCormack Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 89100e7c553b..3e055c6bad36 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -700,7 +700,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - if (!stats.crc || !stats.hwerror) { + if (!stats.crc && !stats.hwerror) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); -- cgit v1.2.3 From 6633d649788e72400b02098bd389585e2c56a557 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Tue, 7 Jun 2011 08:58:31 +0900 Subject: rtlwifi: Avoid modifying skbs that are resubmitted In the case we fail to allocate a new skb, the old skb should be resubmitted unmodified. Fixes bug introduced in a9e12869758430424804. Signed-off-by: Mike McCormack Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 3e055c6bad36..9f8ccae93317 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -669,6 +669,19 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) &rx_status, (u8 *) pdesc, skb); + new_skb = dev_alloc_skb(rtlpci->rxbuffersize); + if (unlikely(!new_skb)) { + RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), + DBG_DMESG, + ("can't alloc skb for rx\n")); + goto done; + } + + pci_unmap_single(rtlpci->pdev, + *((dma_addr_t *) skb->cb), + rtlpci->rxbuffersize, + PCI_DMA_FROMDEVICE); + skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false, HW_DESC_RXPKT_LEN)); @@ -685,21 +698,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) hdr = rtl_get_hdr(skb); fc = rtl_get_fc(skb); - /* try for new buffer - if allocation fails, drop - * frame and reuse old buffer - */ - new_skb = dev_alloc_skb(rtlpci->rxbuffersize); - if (unlikely(!new_skb)) { - RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), - DBG_DMESG, - ("can't alloc skb for rx\n")); - goto done; - } - pci_unmap_single(rtlpci->pdev, - *((dma_addr_t *) skb->cb), - rtlpci->rxbuffersize, - PCI_DMA_FROMDEVICE); - if (!stats.crc && !stats.hwerror) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); -- cgit v1.2.3 From 57a27e1d6a3bb9ad4efeebd3a8c71156d6207536 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 7 Jun 2011 20:42:26 +0300 Subject: nl80211: fix overflow in ssid_len When one of the SSID's length passed in a scan or sched_scan request is larger than 255, there will be an overflow in the u8 that is used to store the length before checking. This causes the check to fail and we overrun the buffer when copying the SSID. Fix this by checking the nl80211 attribute length before copying it to the struct. This is a follow up for the previous commit 208c72f4fe44fe09577e7975ba0e7fa0278f3d03, which didn't fix the problem entirely. Reported-by: Ido Yariv Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 88a565f130a5..98fa8eb6cc4b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3406,11 +3406,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) i = 0; if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { - request->ssids[i].ssid_len = nla_len(attr); - if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) { + if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) { err = -EINVAL; goto out_free; } + request->ssids[i].ssid_len = nla_len(attr); memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); i++; } @@ -3572,12 +3572,11 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { - request->ssids[i].ssid_len = nla_len(attr); - if (request->ssids[i].ssid_len > - IEEE80211_MAX_SSID_LEN) { + if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) { err = -EINVAL; goto out_free; } + request->ssids[i].ssid_len = nla_len(attr); memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); i++; -- cgit v1.2.3 From 265a5b7ee3eb21a4d0e53e17d59ba6eada91af39 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 6 Jun 2011 22:35:13 -0400 Subject: kprobes/trace: Fix kprobe selftest for gcc 4.6 With gcc 4.6, the self test kprobe function: kprobe_trace_selftest_target() is optimized such that kallsyms does not list it. The kprobes test uses this function to insert a probe and test it. But it will fail the test if the function is not listed in kallsyms. Adding a __used annotation keeps the symbol in the kallsyms table. Suggested-by: David Daney Cc: Masami Hiramatsu Signed-off-by: Steven Rostedt --- kernel/trace/trace_kprobe.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index f925c45f0afa..27d13b36b8be 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1870,8 +1870,12 @@ fs_initcall(init_kprobe_trace); #ifdef CONFIG_FTRACE_STARTUP_TEST -static int kprobe_trace_selftest_target(int a1, int a2, int a3, - int a4, int a5, int a6) +/* + * The "__used" keeps gcc from removing the function symbol + * from the kallsyms table. + */ +static __used int kprobe_trace_selftest_target(int a1, int a2, int a3, + int a4, int a5, int a6) { return a1 + a2 + a3 + a4 + a5 + a6; } -- cgit v1.2.3 From a4f18ed11a4ddf327dd91cd19e237278600ad327 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 7 Jun 2011 09:26:46 -0400 Subject: ftrace: Revert 8ab2b7efd ftrace: Remove unnecessary disabling of irqs Revert the commit that removed the disabling of interrupts around the initial modifying of mcount callers to nops, and update the comment. The original comment was outdated and stated that the interrupts were being disabled to prevent kstop machine, which was required with the old ftrace daemon, but was no longer the case. What the comment failed to mention was that interrupts needed to be disabled to keep interrupts from preempting the modifying of the code and then executing the code that was partially modified. Revert the commit and update the comment. Reported-by: Richard W.M. Jones Tested-by: Richard W.M. Jones Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 204b3eb4e690..908038f57440 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3330,6 +3330,7 @@ static int ftrace_process_locs(struct module *mod, { unsigned long *p; unsigned long addr; + unsigned long flags; mutex_lock(&ftrace_lock); p = start; @@ -3346,7 +3347,13 @@ static int ftrace_process_locs(struct module *mod, ftrace_record_ip(addr); } + /* + * Disable interrupts to prevent interrupts from executing + * code that is being modified. + */ + local_irq_save(flags); ftrace_update_code(mod); + local_irq_restore(flags); mutex_unlock(&ftrace_lock); return 0; -- cgit v1.2.3 From ea2c00095c022846dd8dfd211de05154d3e4e1b8 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 17 May 2011 15:25:37 -0700 Subject: Connector: Set the CN_NETLINK_USERS correctly The CN_NETLINK_USERS must be set to the highest valid index +1. Thanks to Evgeniy for pointing this out. Signed-off-by: K. Y. Srinivasan Acked-by: Evgeniy Polyakov Cc: stable [.39] Signed-off-by: Greg Kroah-Hartman --- include/linux/connector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/connector.h b/include/linux/connector.h index 7c60d0942adb..f696bccd48cb 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -44,7 +44,7 @@ #define CN_VAL_DRBD 0x1 #define CN_KVP_IDX 0x9 /* HyperV KVP */ -#define CN_NETLINK_USERS 9 +#define CN_NETLINK_USERS 10 /* Highest index + 1 */ /* * Maximum connector's message size. -- cgit v1.2.3 From 663dd6dcaf7e95526e469e91f41972a9c0cca30c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 17 May 2011 15:25:38 -0700 Subject: Connector: Correctly set the error code in case of success when dispatching receive callbacks The recent changes to the connector code introduced this bug where even when a callback was invoked, we would return an error resulting in double freeing of the skb. This patch fixes this bug. Signed-off-by: K. Y. Srinivasan Acked-by: Evgeniy Polyakov Cc: stable [.39] Signed-off-by: Greg Kroah-Hartman --- drivers/connector/connector.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 219d88a0eeae..dde6a0fad408 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -139,6 +139,7 @@ static int cn_call_callback(struct sk_buff *skb) spin_unlock_bh(&dev->cbdev->queue_lock); if (cbq != NULL) { + err = 0; cbq->callback(msg, nsp); kfree_skb(skb); cn_queue_release_callback(cbq); -- cgit v1.2.3 From 8c56cacc724c7650b893d43068fa66044aa29a61 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 25 May 2011 13:19:39 +0200 Subject: libata: fix unexpectedly frozen port after ata_eh_reset() To work around controllers which can't properly plug events while reset, ata_eh_reset() clears error states and ATA_PFLAG_EH_PENDING after reset but before RESET is marked done. As reset is the final recovery action and full verification of devices including onlineness and classfication match is done afterwards, this shouldn't lead to lost devices or missed hotplug events. Unfortunately, it forgot to thaw the port when clearing EH_PENDING, so if the condition happens after resetting an empty port, the port could be left frozen and EH will end without thawing it, making the port unresponsive to further hotplug events. Thaw if the port is frozen after clearing EH_PENDING. This problem is reported by Bruce Stenning in the following thread. http://thread.gmane.org/gmane.linux.kernel/1123265 stable: I think we should weather this patch a bit longer in -rcX before sending it to -stable. Please wait at least a month after this patch makes upstream. Thanks. -v2: Fixed spelling in the comment per Dave Howorth. Signed-off-by: Tejun Heo Reported-by: Bruce Stenning Cc: stable@kernel.org Cc: Dave Howorth Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index dfb6e9d3d759..7f099d6e4e0b 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2802,10 +2802,11 @@ int ata_eh_reset(struct ata_link *link, int classify, } /* - * Some controllers can't be frozen very well and may set - * spuruious error conditions during reset. Clear accumulated - * error information. As reset is the final recovery action, - * nothing is lost by doing this. + * Some controllers can't be frozen very well and may set spurious + * error conditions during reset. Clear accumulated error + * information and re-thaw the port if frozen. As reset is the + * final recovery action and we cross check link onlineness against + * device classification later, no hotplug event is lost by this. */ spin_lock_irqsave(link->ap->lock, flags); memset(&link->eh_info, 0, sizeof(link->eh_info)); @@ -2814,6 +2815,9 @@ int ata_eh_reset(struct ata_link *link, int classify, ap->pflags &= ~ATA_PFLAG_EH_PENDING; spin_unlock_irqrestore(link->ap->lock, flags); + if (ap->pflags & ATA_PFLAG_FROZEN) + ata_eh_thaw_port(ap); + /* * Make sure onlineness and classification result correspond. * Hotplug could have happened during reset and some -- cgit v1.2.3 From 665c8c8ee405738375b679246b49342ce38ba056 Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Tue, 7 Jun 2011 14:22:57 -0700 Subject: igb: fix i350 SR-IOV failture When SR-IOV is enabled, i350 devices fail to pass traffic. This is due to the driver attempting to enable RSS on the PF device, which is not supported by the i350. When max_vfs is specified on an i350 adapter, set the number of RSS queues to 1. This issue affects 2.6.39 as well. CC: stable@kernel.org Signed-off-by: Mitch Williams Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 18fccf913635..2c28621eb30b 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2373,6 +2373,9 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) } #endif /* CONFIG_PCI_IOV */ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); + /* i350 cannot do RSS and SR-IOV at the same time */ + if (hw->mac.type == e1000_i350 && adapter->vfs_allocated_count) + adapter->rss_queues = 1; /* * if rss_queues > 4 or vfs are going to be allocated with rss_queues -- cgit v1.2.3 From e756682c8baa47da1648c0c016e9f48ed66bc32d Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 5 Jun 2011 20:46:03 +0000 Subject: xfrm: Fix off by one in the replay advance functions We may write 4 byte too much when we reinitialize the anti replay window in the replay advance functions. This patch fixes this by adjusting the last index of the initialization loop. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/xfrm/xfrm_replay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 47f1b8638df9..b11ea692bd7d 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -265,7 +265,7 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq) bitnr = bitnr & 0x1F; replay_esn->bmp[nr] |= (1U << bitnr); } else { - nr = replay_esn->replay_window >> 5; + nr = (replay_esn->replay_window - 1) >> 5; for (i = 0; i <= nr; i++) replay_esn->bmp[i] = 0; @@ -471,7 +471,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) bitnr = bitnr & 0x1F; replay_esn->bmp[nr] |= (1U << bitnr); } else { - nr = replay_esn->replay_window >> 5; + nr = (replay_esn->replay_window - 1) >> 5; for (i = 0; i <= nr; i++) replay_esn->bmp[i] = 0; -- cgit v1.2.3 From 70b666c3b4cb2b96098d80e6f515e4bc6d37db5a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 27 May 2011 09:24:26 -0700 Subject: ceph: use ihold when we already have an inode ref We should use ihold whenever we already have a stable inode ref, even when we aren't holding i_lock. This avoids adding new and unnecessary locking dependencies. Signed-off-by: Sage Weil --- fs/ceph/addr.c | 2 +- fs/ceph/caps.c | 10 ++++------ fs/ceph/dir.c | 11 +++++++---- fs/ceph/export.c | 4 ++-- fs/ceph/file.c | 3 ++- fs/ceph/inode.c | 18 ++++++++++-------- fs/ceph/ioctl.c | 6 ++++-- fs/ceph/locks.c | 3 ++- fs/ceph/snap.c | 2 +- fs/ceph/xattr.c | 6 ++++-- 10 files changed, 37 insertions(+), 28 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 33da49dc3cc6..5a3953db8118 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -453,7 +453,7 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc) int err; struct inode *inode = page->mapping->host; BUG_ON(!inode); - igrab(inode); + ihold(inode); err = writepage_nounlock(page, wbc); unlock_page(page); iput(inode); diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 1f72b00447c4..f605753c8fe9 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2940,14 +2940,12 @@ void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) while (!list_empty(&mdsc->cap_dirty)) { ci = list_first_entry(&mdsc->cap_dirty, struct ceph_inode_info, i_dirty_item); - inode = igrab(&ci->vfs_inode); + inode = &ci->vfs_inode; + ihold(inode); dout("flush_dirty_caps %p\n", inode); spin_unlock(&mdsc->cap_dirty_lock); - if (inode) { - ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, - NULL); - iput(inode); - } + ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, NULL); + iput(inode); spin_lock(&mdsc->cap_dirty_lock); } spin_unlock(&mdsc->cap_dirty_lock); diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 33729e822bb9..ef8f08c343e8 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -308,7 +308,8 @@ more: req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_dentry = dget(filp->f_dentry); /* hints to request -> mds selection code */ req->r_direct_mode = USE_AUTH_MDS; @@ -787,10 +788,12 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir, req->r_dentry_drop = CEPH_CAP_FILE_SHARED; req->r_dentry_unless = CEPH_CAP_FILE_EXCL; err = ceph_mdsc_do_request(mdsc, dir, req); - if (err) + if (err) { d_drop(dentry); - else if (!req->r_reply_info.head->is_dentry) - d_instantiate(dentry, igrab(old_dentry->d_inode)); + } else if (!req->r_reply_info.head->is_dentry) { + ihold(old_dentry->d_inode); + d_instantiate(dentry, old_dentry->d_inode); + } ceph_mdsc_put_request(req); return err; } diff --git a/fs/ceph/export.c b/fs/ceph/export.c index a610d3d67488..f67b687550de 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -109,7 +109,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, err = ceph_mdsc_do_request(mdsc, NULL, req); inode = req->r_target_inode; if (inode) - igrab(inode); + ihold(inode); ceph_mdsc_put_request(req); if (!inode) return ERR_PTR(-ESTALE); @@ -167,7 +167,7 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb, err = ceph_mdsc_do_request(mdsc, NULL, req); inode = req->r_target_inode; if (inode) - igrab(inode); + ihold(inode); ceph_mdsc_put_request(req); if (!inode) return ERR_PTR(err ? err : -ESTALE); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 203252d88d9f..8c5ac4e72832 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -191,7 +191,8 @@ int ceph_open(struct inode *inode, struct file *file) err = PTR_ERR(req); goto out; } - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_num_caps = 1; err = ceph_mdsc_do_request(mdsc, parent_inode, req); if (!err) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 70b6a4839c38..d8858e96ab18 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1101,10 +1101,10 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, goto done; } req->r_dentry = dn; /* may have spliced */ - igrab(in); + ihold(in); } else if (ceph_ino(in) == vino.ino && ceph_snap(in) == vino.snap) { - igrab(in); + ihold(in); } else { dout(" %p links to %p %llx.%llx, not %llx.%llx\n", dn, in, ceph_ino(in), ceph_snap(in), @@ -1144,7 +1144,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, goto done; } req->r_dentry = dn; /* may have spliced */ - igrab(in); + ihold(in); rinfo->head->is_dentry = 1; /* fool notrace handlers */ } @@ -1328,7 +1328,7 @@ void ceph_queue_writeback(struct inode *inode) if (queue_work(ceph_inode_to_client(inode)->wb_wq, &ceph_inode(inode)->i_wb_work)) { dout("ceph_queue_writeback %p\n", inode); - igrab(inode); + ihold(inode); } else { dout("ceph_queue_writeback %p failed\n", inode); } @@ -1353,7 +1353,7 @@ void ceph_queue_invalidate(struct inode *inode) if (queue_work(ceph_inode_to_client(inode)->pg_inv_wq, &ceph_inode(inode)->i_pg_inv_work)) { dout("ceph_queue_invalidate %p\n", inode); - igrab(inode); + ihold(inode); } else { dout("ceph_queue_invalidate %p failed\n", inode); } @@ -1477,7 +1477,7 @@ void ceph_queue_vmtruncate(struct inode *inode) if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq, &ci->i_vmtruncate_work)) { dout("ceph_queue_vmtruncate %p\n", inode); - igrab(inode); + ihold(inode); } else { dout("ceph_queue_vmtruncate %p failed, pending=%d\n", inode, ci->i_truncate_pending); @@ -1738,7 +1738,8 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) __mark_inode_dirty(inode, inode_dirty_flags); if (mask) { - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_inode_drop = release; req->r_args.setattr.mask = cpu_to_le32(mask); req->r_num_caps = 1; @@ -1779,7 +1780,8 @@ int ceph_do_getattr(struct inode *inode, int mask) req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_num_caps = 1; req->r_args.getattr.mask = cpu_to_le32(mask); err = ceph_mdsc_do_request(mdsc, NULL, req); diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index 8888c9ba68db..ef0b5f48e13a 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c @@ -73,7 +73,8 @@ static long ceph_ioctl_set_layout(struct file *file, void __user *arg) USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_inode_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL; req->r_args.setlayout.layout.fl_stripe_unit = @@ -135,7 +136,8 @@ static long ceph_ioctl_set_layout_policy (struct file *file, void __user *arg) if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_args.setlayout.layout.fl_stripe_unit = cpu_to_le32(l.stripe_unit); diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index 476b329867d4..7f0f72c53f7e 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c @@ -23,7 +23,8 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); /* mds requires start and length rather than start and end */ if (LLONG_MAX == fl->fl_end) diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 24067d68a554..54b14de2e729 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -722,7 +722,7 @@ static void flush_snaps(struct ceph_mds_client *mdsc) ci = list_first_entry(&mdsc->snap_flush_list, struct ceph_inode_info, i_snap_flush_item); inode = &ci->vfs_inode; - igrab(inode); + ihold(inode); spin_unlock(&mdsc->snap_flush_lock); spin_lock(&inode->i_lock); __ceph_flush_snaps(ci, &session, 0); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index f2b628696180..f42d730f1b66 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -665,7 +665,8 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name, err = PTR_ERR(req); goto out; } - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_inode_drop = CEPH_CAP_XATTR_SHARED; req->r_num_caps = 1; req->r_args.setxattr.flags = cpu_to_le32(flags); @@ -795,7 +796,8 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name) USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_inode_drop = CEPH_CAP_XATTR_SHARED; req->r_num_caps = 1; req->r_path2 = kstrdup(name, GFP_NOFS); -- cgit v1.2.3 From 2584547230ae49b8de91ab3bb5e0a81898905b45 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 3 Jun 2011 09:37:09 -0700 Subject: ceph: fix sync vs canceled write If we cancel a write, trigger the safe completions to prevent a sync from blocking indefinitely in ceph_osdc_sync(). Signed-off-by: Sage Weil --- net/ceph/osd_client.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 6ea2b892f44b..9cb627a4073a 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1144,6 +1144,13 @@ static void handle_osds_timeout(struct work_struct *work) round_jiffies_relative(delay)); } +static void complete_request(struct ceph_osd_request *req) +{ + if (req->r_safe_callback) + req->r_safe_callback(req, NULL); + complete_all(&req->r_safe_completion); /* fsync waiter */ +} + /* * handle osd op reply. either call the callback if it is specified, * or do the completion to wake up the waiting thread. @@ -1226,11 +1233,8 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, else complete_all(&req->r_completion); - if (flags & CEPH_OSD_FLAG_ONDISK) { - if (req->r_safe_callback) - req->r_safe_callback(req, msg); - complete_all(&req->r_safe_completion); /* fsync waiter */ - } + if (flags & CEPH_OSD_FLAG_ONDISK) + complete_request(req); done: dout("req=%p req->r_linger=%d\n", req, req->r_linger); @@ -1732,6 +1736,7 @@ int ceph_osdc_wait_request(struct ceph_osd_client *osdc, __cancel_request(req); __unregister_request(osdc, req); mutex_unlock(&osdc->request_mutex); + complete_request(req); dout("wait_request tid %llu canceled/timed out\n", req->r_tid); return rc; } -- cgit v1.2.3 From c3cd62839aaa2cdb2b99687c9e44f1b300a4aece Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 1 Jun 2011 16:08:44 -0700 Subject: ceph: fix short sync reads from the OSD If we get a short read from the OSD because the object is small, we need to zero the remainder of the buffer. For O_DIRECT reads, the attempted range is not trimmed to i_size by the VFS, so we were actually looping indefinitely. Fix by trimming by i_size, and the unconditionally zeroing the trailing range. Reported-by: Jeff Wu Signed-off-by: Sage Weil --- fs/ceph/file.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 8c5ac4e72832..b654f403139e 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -283,7 +283,7 @@ int ceph_release(struct inode *inode, struct file *file) static int striped_read(struct inode *inode, u64 off, u64 len, struct page **pages, int num_pages, - int *checkeof, bool align_to_pages, + int *checkeof, bool o_direct, unsigned long buf_align) { struct ceph_fs_client *fsc = ceph_inode_to_client(inode); @@ -308,7 +308,7 @@ static int striped_read(struct inode *inode, io_align = off & ~PAGE_MASK; more: - if (align_to_pages) + if (o_direct) page_align = (pos - io_align + buf_align) & ~PAGE_MASK; else page_align = pos & ~PAGE_MASK; @@ -346,20 +346,22 @@ more: } if (was_short) { - /* was original extent fully inside i_size? */ - if (pos + left <= inode->i_size) { - dout("zero tail\n"); - ceph_zero_page_vector_range(page_off + read, len - read, + /* did we bounce off eof? */ + if (pos + left > inode->i_size) + *checkeof = 1; + + /* zero trailing bytes (inside i_size) */ + if (left > 0 && pos < inode->i_size) { + if (pos + left > inode->i_size) + left = inode->i_size - pos; + + dout("zero tail %d\n", left); + ceph_zero_page_vector_range(page_off + read, left, pages); - read = len; - goto out; + read += left; } - - /* check i_size */ - *checkeof = 1; } -out: if (ret >= 0) ret = read; dout("striped_read returns %d\n", ret); @@ -659,7 +661,7 @@ out: /* hit EOF or hole? */ if (statret == 0 && *ppos < inode->i_size) { - dout("aio_read sync_read hit hole, reading more\n"); + dout("aio_read sync_read hit hole, ppos %lld < size %lld, reading more\n", *ppos, inode->i_size); read += ret; base += ret; len -= ret; -- cgit v1.2.3 From 0e98728fa32d338907631349a8cc2afa07c0cb9a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 7 Jun 2011 20:40:35 -0700 Subject: ceph: fix ENOENT logic in striped_read Getting ENOENT is equivalent to reading 0 bytes. Make that correction before setting up the hit_stripe and was_short flags. Fixes the following case: dd if=/dev/zero of=/mnt/fs_depot/dd3 bs=1 seek=1048576 count=0 dd if=/mnt/fs_depot/dd3 of=/root/ddout1 skip=8 bs=500 count=2 iflag=direct Reported-by: Henry C Chang Signed-off-by: Sage Weil --- fs/ceph/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index b654f403139e..9542f07d0b93 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -318,10 +318,10 @@ more: ci->i_truncate_seq, ci->i_truncate_size, page_pos, pages_left, page_align); - hit_stripe = this_len < left; - was_short = ret >= 0 && ret < this_len; if (ret == -ENOENT) ret = 0; + hit_stripe = this_len < left; + was_short = ret >= 0 && ret < this_len; dout("striped_read %llu~%u (read %u) got %d%s%s\n", pos, left, read, ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : ""); -- cgit v1.2.3 From 0c1f91f27140cf3b6e38dc4e892adac241c73a20 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 25 May 2011 14:56:12 -0700 Subject: ceph: unwind canceled flock state If we request a lock and then abort (e.g., ^C), we need to send a matching unlock request to the MDS to unwind our lock attempt to avoid indefinitely blocking other clients. Reported-by: Brian Chrisman Signed-off-by: Sage Weil --- fs/ceph/locks.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index 7f0f72c53f7e..80576d05d687 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c @@ -33,11 +33,10 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, length = fl->fl_end - fl->fl_start + 1; dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " - "length: %llu, wait: %d, type`: %d", (int)lock_type, + "length: %llu, wait: %d, type: %d", (int)lock_type, (int)operation, (u64)fl->fl_pid, fl->fl_start, length, wait, fl->fl_type); - req->r_args.filelock_change.rule = lock_type; req->r_args.filelock_change.type = cmd; req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid); @@ -71,7 +70,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, } ceph_mdsc_put_request(req); dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " - "length: %llu, wait: %d, type`: %d, err code %d", (int)lock_type, + "length: %llu, wait: %d, type: %d, err code %d", (int)lock_type, (int)operation, (u64)fl->fl_pid, fl->fl_start, length, wait, fl->fl_type, err); return err; @@ -110,16 +109,20 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl) dout("mds locked, locking locally"); err = posix_lock_file(file, fl, NULL); if (err && (CEPH_MDS_OP_SETFILELOCK == op)) { - /* undo! This should only happen if the kernel detects - * local deadlock. */ + /* undo! This should only happen if + * the kernel detects local + * deadlock. */ ceph_lock_message(CEPH_LOCK_FCNTL, op, file, CEPH_LOCK_UNLOCK, 0, fl); - dout("got %d on posix_lock_file, undid lock", err); + dout("got %d on posix_lock_file, undid lock", + err); } } - } else { - dout("mds returned error code %d", err); + } else if (err == -ERESTARTSYS) { + dout("undoing lock\n"); + ceph_lock_message(CEPH_LOCK_FCNTL, op, file, + CEPH_LOCK_UNLOCK, 0, fl); } return err; } @@ -156,8 +159,11 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl) file, CEPH_LOCK_UNLOCK, 0, fl); dout("got %d on flock_lock_file_wait, undid lock", err); } - } else { - dout("mds error code %d", err); + } else if (err == -ERESTARTSYS) { + dout("undoing lock\n"); + ceph_lock_message(CEPH_LOCK_FLOCK, + CEPH_MDS_OP_SETFILELOCK, + file, CEPH_LOCK_UNLOCK, 0, fl); } return err; } -- cgit v1.2.3 From 629acb6abac0ef217ee579e14084af2ce7381dbc Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 15:10:08 +1000 Subject: MD: no integrity register if no gendisk Don't attempt md_integrity_register if there is no gendisk struct available. When MD arrays are built via device-mapper, the gendisk structure is not available via mddev. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/md.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index aa640a85bb21..4ea02c634d33 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1781,8 +1781,8 @@ int md_integrity_register(mddev_t *mddev) if (list_empty(&mddev->disks)) return 0; /* nothing to do */ - if (blk_get_integrity(mddev->gendisk)) - return 0; /* already registered */ + if (!mddev->gendisk || blk_get_integrity(mddev->gendisk)) + return 0; /* shouldn't register, or already is */ list_for_each_entry(rdev, &mddev->disks, same_set) { /* skip spares and non-functional disks */ if (test_bit(Faulty, &rdev->flags)) -- cgit v1.2.3 From 68866e425be2ef2664aa5c691bb3ab789736acf5 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 15:10:08 +1000 Subject: MD: no sync IO while suspended Disallow resync I/O while the RAID array is suspended. Recovery, resync, and metadata I/O should not be allowed while a device is suspended. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/md.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 4ea02c634d33..4fa915a21d0d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7045,7 +7045,6 @@ void md_do_sync(mddev_t *mddev) } EXPORT_SYMBOL_GPL(md_do_sync); - static int remove_and_add_spares(mddev_t *mddev) { mdk_rdev_t *rdev; @@ -7157,6 +7156,9 @@ static void reap_sync_thread(mddev_t *mddev) */ void md_check_recovery(mddev_t *mddev) { + if (mddev->suspended) + return; + if (mddev->bitmap) bitmap_daemon_work(mddev); -- cgit v1.2.3 From ac42450c7c814769bee963ae4b897c149bb0ab53 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 7 Jun 2011 17:48:35 -0500 Subject: MD: possible typo Make message a bit clearer by s/blocks/k/ I chose 'k' vs 'kiB' or 'kB' because it is what is used earlier in the message. 'k' may be a bit ambigous, but I think it's better than "blocks" which normally means 512, but means 1024 in MD. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/md.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 4fa915a21d0d..3715e89dcaae 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6866,8 +6866,8 @@ void md_do_sync(mddev_t *mddev) * Tune reconstruction: */ window = 32*(PAGE_SIZE/512); - printk(KERN_INFO "md: using %dk window, over a total of %llu blocks.\n", - window/2,(unsigned long long) max_sectors/2); + printk(KERN_INFO "md: using %dk window, over a total of %lluk.\n", + window/2, (unsigned long long)max_sectors/2); atomic_set(&mddev->recovery_active, 0); last_check = 0; -- cgit v1.2.3 From 0fd018af37dadbb7826850883ad8abfecdb1a00b Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 7 Jun 2011 17:49:36 -0500 Subject: MD: move thread wakeups into resume Move personality and sync/recovery thread starting outside md_run. Moving the wakeup's of the personality and sync/recovery threads out of md_run and into do_md_run and mddev_resume solves two issues: 1) It allows bitmap_load to be called before the sync_thread is run and 2) when MD personalities are used by device-mapper (dm-raid.c), the start-up of the array is better alligned with device-mapper primatives (CTR/resume/suspend/DTR). I/O - in this case, recovery operations - should not happen until after a resume has taken place. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/md.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 3715e89dcaae..d5385188c445 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -351,6 +351,9 @@ void mddev_resume(mddev_t *mddev) mddev->suspended = 0; wake_up(&mddev->sb_wait); mddev->pers->quiesce(mddev, 0); + + md_wakeup_thread(mddev->thread); + md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ } EXPORT_SYMBOL_GPL(mddev_resume); @@ -4619,9 +4622,6 @@ int md_run(mddev_t *mddev) if (mddev->flags) md_update_sb(mddev, 0); - md_wakeup_thread(mddev->thread); - md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ - md_new_event(mddev); sysfs_notify_dirent_safe(mddev->sysfs_state); sysfs_notify_dirent_safe(mddev->sysfs_action); @@ -4642,6 +4642,10 @@ static int do_md_run(mddev_t *mddev) bitmap_destroy(mddev); goto out; } + + md_wakeup_thread(mddev->thread); + md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ + set_capacity(mddev->gendisk, mddev->array_sectors); revalidate_disk(mddev->gendisk); mddev->changed = 1; -- cgit v1.2.3 From 1ed7242e591af7e233234d483f12d33818b189d9 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 7 Jun 2011 17:50:35 -0500 Subject: MD: raid1 changes to allow use by device mapper MD RAID1: Changes to allow RAID1 to be used by device-mapper (dm-raid.c) Added the necessary congestion function and conditionalize calls requiring an array 'queue' or 'gendisk'. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid1.c | 24 +++++++++++++++++------- drivers/md/raid1.h | 2 ++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 5d096096f958..f7431b6d8447 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -497,21 +497,19 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) return best_disk; } -static int raid1_congested(void *data, int bits) +int md_raid1_congested(mddev_t *mddev, int bits) { - mddev_t *mddev = data; conf_t *conf = mddev->private; int i, ret = 0; - if (mddev_congested(mddev, bits)) - return 1; - rcu_read_lock(); for (i = 0; i < mddev->raid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct request_queue *q = bdev_get_queue(rdev->bdev); + BUG_ON(!q); + /* Note the '|| 1' - when read_balance prefers * non-congested targets, it can be removed */ @@ -524,7 +522,15 @@ static int raid1_congested(void *data, int bits) rcu_read_unlock(); return ret; } +EXPORT_SYMBOL_GPL(md_raid1_congested); +static int raid1_congested(void *data, int bits) +{ + mddev_t *mddev = data; + + return mddev_congested(mddev, bits) || + md_raid1_congested(mddev, bits); +} static void flush_pending_writes(conf_t *conf) { @@ -1972,6 +1978,8 @@ static int run(mddev_t *mddev) return PTR_ERR(conf); list_for_each_entry(rdev, &mddev->disks, same_set) { + if (!mddev->gendisk) + continue; disk_stack_limits(mddev->gendisk, rdev->bdev, rdev->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk @@ -2013,8 +2021,10 @@ static int run(mddev_t *mddev) md_set_array_sectors(mddev, raid1_size(mddev, 0, 0)); - mddev->queue->backing_dev_info.congested_fn = raid1_congested; - mddev->queue->backing_dev_info.congested_data = mddev; + if (mddev->queue) { + mddev->queue->backing_dev_info.congested_fn = raid1_congested; + mddev->queue->backing_dev_info.congested_data = mddev; + } return md_integrity_register(mddev); } diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index 5fc4ca1af863..e743a64fac4f 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -126,4 +126,6 @@ struct r1bio_s { */ #define R1BIO_Returned 6 +extern int md_raid1_congested(mddev_t *mddev, int bits); + #endif -- cgit v1.2.3 From 076f968b37f0232d883749da8f5031df5dea7ade Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 7 Jun 2011 17:51:30 -0500 Subject: MD: add sync_super to mddev_t struct Add the 'sync_super' function pointer to MD array structure (struct mddev_s) If device-mapper (dm-raid.c) is to define its own on-disk superblock and be able to load it, there must still be a way for MD to initiate superblock updates. The simplest way to make this happen is to provide a pointer in the MD array structure that can be set by device-mapper (or other module) with a function to do this. If the function has been set, it will be used; otherwise, the method with be looked up via 'super_types' as usual. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/md.c | 15 +++++++++++++-- drivers/md/md.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index d5385188c445..9160463b5f68 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1753,6 +1753,18 @@ static struct super_type super_types[] = { }, }; +static void sync_super(mddev_t *mddev, mdk_rdev_t *rdev) +{ + if (mddev->sync_super) { + mddev->sync_super(mddev, rdev); + return; + } + + BUG_ON(mddev->major_version >= ARRAY_SIZE(super_types)); + + super_types[mddev->major_version].sync_super(mddev, rdev); +} + static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) { mdk_rdev_t *rdev, *rdev2; @@ -2171,8 +2183,7 @@ static void sync_sbs(mddev_t * mddev, int nospares) /* Don't update this superblock */ rdev->sb_loaded = 2; } else { - super_types[mddev->major_version]. - sync_super(mddev, rdev); + sync_super(mddev, rdev); rdev->sb_loaded = 1; } } diff --git a/drivers/md/md.h b/drivers/md/md.h index 0b1fd3f1d85b..5e35535ab7c3 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -330,6 +330,7 @@ struct mddev_s atomic_t flush_pending; struct work_struct flush_work; struct work_struct event_work; /* used by dm to report failure event */ + void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev); }; -- cgit v1.2.3 From 5bdbd4fa4df6891a6644d588c9a30d30e7c0af8e Mon Sep 17 00:00:00 2001 From: Srinivas KANDAGATLA Date: Wed, 8 Jun 2011 15:22:39 +0900 Subject: sh: Fix up xchg/cmpxchg corruption with gUSA RB. gUSA special cases r15 for part of its login/out sequence, meaning that any parameters need to be explicitly prohibited from accidentally being assigned that particular register, and the compiler ultimately needs to use a temporary instead. Certain configurations have begun generating code paths that do indeed get allocated r15, resulting in immediate corruption of the exchanged value. This was observed in (amongst others) exit_mm() code generation where the xchg_u32 call was immediately corrupting a structure address. As this is a general gUSA restriction, the rest of the users likewise need to be updated to ensure sensible constraints. References: https://bugzilla.stlinux.com/show_bug.cgi?id=11229 Signed-off-by: Srinivas Kandagatla Reviewed-by: Stuart Menefy Signed-off-by: Paul Mundt --- arch/sh/include/asm/cmpxchg-grb.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/arch/sh/include/asm/cmpxchg-grb.h b/arch/sh/include/asm/cmpxchg-grb.h index 4676bf57693a..f848dec9e483 100644 --- a/arch/sh/include/asm/cmpxchg-grb.h +++ b/arch/sh/include/asm/cmpxchg-grb.h @@ -15,8 +15,9 @@ static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val) " mov.l %2, @%1 \n\t" /* store new value */ "1: mov r1, r15 \n\t" /* LOGOUT */ : "=&r" (retval), - "+r" (m) - : "r" (val) + "+r" (m), + "+r" (val) /* inhibit r15 overloading */ + : : "memory", "r0", "r1"); return retval; @@ -36,8 +37,9 @@ static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val) " mov.b %2, @%1 \n\t" /* store new value */ "1: mov r1, r15 \n\t" /* LOGOUT */ : "=&r" (retval), - "+r" (m) - : "r" (val) + "+r" (m), + "+r" (val) /* inhibit r15 overloading */ + : : "memory" , "r0", "r1"); return retval; @@ -54,13 +56,14 @@ static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old, " nop \n\t" " mov r15, r1 \n\t" /* r1 = saved sp */ " mov #-8, r15 \n\t" /* LOGIN */ - " mov.l @%1, %0 \n\t" /* load old value */ - " cmp/eq %0, %2 \n\t" + " mov.l @%3, %0 \n\t" /* load old value */ + " cmp/eq %0, %1 \n\t" " bf 1f \n\t" /* if not equal */ - " mov.l %3, @%1 \n\t" /* store new value */ + " mov.l %2, @%3 \n\t" /* store new value */ "1: mov r1, r15 \n\t" /* LOGOUT */ - : "=&r" (retval) - : "r" (m), "r" (old), "r" (new) + : "=&r" (retval), + "+r" (old), "+r" (new) /* old or new can be r15 */ + : "r" (m) : "memory" , "r0", "r1", "t"); return retval; -- cgit v1.2.3 From 7416401661fad5c7ee9edb17cb54e7bff7a74dfe Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 6 Jun 2011 11:51:43 +0200 Subject: arm: davinci: Fix fallout from generic irq chip conversion The code which does the chained handler setup was overwriting chip_data. Signed-off-by: Thomas Gleixner Tested-by: Holger Hans Peter Freyther Signed-off-by: Kevin Hilman Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/gpio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index a0b838894ac9..e7221398e5af 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -252,9 +252,11 @@ static struct irq_chip gpio_irqchip = { static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct davinci_gpio_regs __iomem *g = irq2regs(irq); + struct davinci_gpio_regs __iomem *g; u32 mask = 0xffff; + g = (__force struct davinci_gpio_regs __iomem *) irq_desc_get_handler_data(desc); + /* we only care about one bank */ if (irq & 1) mask <<= 16; @@ -422,8 +424,7 @@ static int __init davinci_gpio_irq_setup(void) /* set up all irqs in this bank */ irq_set_chained_handler(bank_irq, gpio_irq_handler); - irq_set_chip_data(bank_irq, (__force void *)g); - irq_set_handler_data(bank_irq, (void *)irq); + irq_set_handler_data(bank_irq, (__force void *)g); for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { irq_set_chip(irq, &gpio_irqchip); -- cgit v1.2.3 From 7e9f1945213cdd7cd11f29346ded07a81854b5af Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Sun, 5 Jun 2011 17:33:33 +0530 Subject: davinci: make PCM platform devices static Make the PCM device structures used in devices.c and devices-da8xx.c static as they are used only in the respective files. This was found when trying to build a single image for DaVinci and DA8x devices using runtime P2V support. Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/devices-da8xx.c | 2 +- arch/arm/mach-davinci/devices.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 4e66881c7aee..fc4e98ea7543 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -494,7 +494,7 @@ static struct platform_device da850_mcasp_device = { .resource = da850_mcasp_resources, }; -struct platform_device davinci_pcm_device = { +static struct platform_device davinci_pcm_device = { .name = "davinci-pcm-audio", .id = -1, }; diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 8f4f736aa267..806a2f02b980 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -298,7 +298,7 @@ static void davinci_init_wdt(void) /*-------------------------------------------------------------------------*/ -struct platform_device davinci_pcm_device = { +static struct platform_device davinci_pcm_device = { .name = "davinci-pcm-audio", .id = -1, }; -- cgit v1.2.3 From fd8a7de177b6f56a0fc59ad211c197a7df06b1ad Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 20 Jul 2010 14:34:50 +0200 Subject: x86: cpu-hotplug: Prevent softirq wakeup on wrong CPU After a newly plugged CPU sets the cpu_online bit it enables interrupts and goes idle. The cpu which brought up the new cpu waits for the cpu_online bit and when it observes it, it sets the cpu_active bit for this cpu. The cpu_active bit is the relevant one for the scheduler to consider the cpu as a viable target. With forced threaded interrupt handlers which imply forced threaded softirqs we observed the following race: cpu 0 cpu 1 bringup(cpu1); set_cpu_online(smp_processor_id(), true); local_irq_enable(); while (!cpu_online(cpu1)); timer_interrupt() -> wake_up(softirq_thread_cpu1); -> enqueue_on(softirq_thread_cpu1, cpu0); ^^^^ cpu_notify(CPU_ONLINE, cpu1); -> sched_cpu_active(cpu1) -> set_cpu_active((cpu1, true); When an interrupt happens before the cpu_active bit is set by the cpu which brought up the newly onlined cpu, then the scheduler refuses to enqueue the woken thread which is bound to that newly onlined cpu on that newly onlined cpu due to the not yet set cpu_active bit and selects a fallback runqueue. Not really an expected and desirable behaviour. So far this has only been observed with forced hard/softirq threading, but in theory this could happen without forced threaded hard/softirqs as well. It's probably unobservable as it would take a massive interrupt storm on the newly onlined cpu which causes the softirq loop to wake up the softirq thread and an even longer delay of the cpu which waits for the cpu_online bit. Signed-off-by: Thomas Gleixner Reviewed-by: Peter Zijlstra Cc: stable@kernel.org # 2.6.39 --- arch/x86/kernel/smpboot.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 33a0c11797de..9fd3137230d4 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -285,6 +285,19 @@ notrace static void __cpuinit start_secondary(void *unused) per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; x86_platform.nmi_init(); + /* + * Wait until the cpu which brought this one up marked it + * online before enabling interrupts. If we don't do that then + * we can end up waking up the softirq thread before this cpu + * reached the active state, which makes the scheduler unhappy + * and schedule the softirq thread on the wrong cpu. This is + * only observable with forced threaded interrupts, but in + * theory it could also happen w/o them. It's just way harder + * to achieve. + */ + while (!cpumask_test_cpu(smp_processor_id(), cpu_active_mask)) + cpu_relax(); + /* enable local interrupts */ local_irq_enable(); -- cgit v1.2.3 From 0f82bdf572fc6e42147151aa4d52542f7fc6d793 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Jun 2011 23:42:04 +0100 Subject: ASoC: Fix WM8962 headphone volume update for use of advanced caches Signed-off-by: Mark Brown Acked-by: Liam Girdwood Cc: stable@kernel.org --- sound/soc/codecs/wm8962.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index f90ae427242b..5e05eed96c38 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1999,12 +1999,12 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA) + if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA) return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, reg_cache[WM8962_HPOUTL_VOLUME]); /* ...otherwise the right. The VU is stereo. */ - if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA) + if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA) return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, reg_cache[WM8962_HPOUTR_VOLUME]); -- cgit v1.2.3 From 43e4e0b94984b45d52048e3ac027cac15c718b65 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 27 May 2011 08:40:24 -0700 Subject: iwlagn: send tx power command if defer cause by RXON not match During channge channel, tx power will not send to uCode, the tx power command should send after scan complete. but should also can send after RXON command. Stable fix identified by Stanislaw Gruszka . Signed-off-by: Wey-Yi Guy Cc: stable@kernel.org [2.6.38+] Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 018874964602..09f679d6046f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -370,6 +370,11 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } memcpy(active, &ctx->staging, sizeof(*active)); + /* + * We do not commit tx power settings while channel changing, + * do it now if after settings changed. + */ + iwl_set_tx_power(priv, priv->tx_power_next, false); return 0; } -- cgit v1.2.3 From f3209bea110cade12e2b133da8b8499689cb0e2e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 Jun 2011 13:27:29 +0200 Subject: mac80211: fix IBSS teardown race Ignacy reports that sometimes after leaving an IBSS joining a new one didn't work because there still were stations on the list. He fixed it by flushing stations when attempting to join a new IBSS, but this shouldn't be happening in the first case. When I looked into it I saw a race condition in teardown that could cause stations to be added after flush, and thus cause this situation. Ignacy confirms that after applying my patch he hasn't seen this happen again. Reported-by: Ignacy Gawedzki Debugged-by: Ignacy Gawedzki Tested-by: Ignacy Gawedzki Cc: stable@kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 421eaa6b0c2b..56c24cabf26d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -965,6 +965,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->u.ibss.mtx); + sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; + memset(sdata->u.ibss.bssid, 0, ETH_ALEN); + sdata->u.ibss.ssid_len = 0; + active_ibss = ieee80211_sta_active_ibss(sdata); if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { @@ -999,8 +1003,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) kfree_skb(skb); skb_queue_purge(&sdata->skb_queue); - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); - sdata->u.ibss.ssid_len = 0; del_timer_sync(&sdata->u.ibss.timer); -- cgit v1.2.3 From 51e65257142a87fe46a1ce5c35c86c5baf012614 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 8 Jun 2011 15:26:31 +0200 Subject: iwlegacy: fix channel switch locking We use priv->mutex to avoid race conditions between chswitch_done() and mac_channel_switch(), when marking channel switch in progress. But chswitch_done() can be called in atomic context from rx_csa() or with mutex already taken from commit_rxon(). To fix remove mutex from chswitch_done() and use atomic bitops for marking channel switch pending. Cc: stable@kernel.org # 2.6.39+ Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-4965.c | 9 +++------ drivers/net/wireless/iwlegacy/iwl-core.c | 30 ++++++++++++---------------- drivers/net/wireless/iwlegacy/iwl-core.h | 2 +- drivers/net/wireless/iwlegacy/iwl-dev.h | 13 +----------- drivers/net/wireless/iwlegacy/iwl4965-base.c | 20 +++++++++---------- 5 files changed, 28 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c index e1b89220c186..facc94e74b07 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965.c @@ -1218,10 +1218,10 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c * receive commit_rxon request * abort any previous channel switch if still in process */ - if (priv->switch_rxon.switch_in_progress && - (priv->switch_rxon.channel != ctx->staging.channel)) { + if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && + (priv->switch_channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", - le16_to_cpu(priv->switch_rxon.channel)); + le16_to_cpu(priv->switch_channel)); iwl_legacy_chswitch_done(priv, false); } @@ -1404,9 +1404,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, return rc; } - priv->switch_rxon.channel = cmd.channel; - priv->switch_rxon.switch_in_progress = true; - return iwl_legacy_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); } diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 42df8321dae8..3be76bd5499a 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -859,12 +859,8 @@ void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (priv->switch_rxon.switch_in_progress) { + if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ieee80211_chswitch_done(ctx->vif, is_success); - mutex_lock(&priv->mutex); - priv->switch_rxon.switch_in_progress = false; - mutex_unlock(&priv->mutex); - } } EXPORT_SYMBOL(iwl_legacy_chswitch_done); @@ -876,19 +872,19 @@ void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_legacy_rxon_cmd *rxon = (void *)&ctx->active; - if (priv->switch_rxon.switch_in_progress) { - if (!le32_to_cpu(csa->status) && - (csa->channel == priv->switch_rxon.channel)) { - rxon->channel = csa->channel; - ctx->staging.channel = csa->channel; - IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", - le16_to_cpu(csa->channel)); - iwl_legacy_chswitch_done(priv, true); - } else { - IWL_ERR(priv, "CSA notif (fail) : channel %d\n", + if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + return; + + if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { + rxon->channel = csa->channel; + ctx->staging.channel = csa->channel; + IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", le16_to_cpu(csa->channel)); - iwl_legacy_chswitch_done(priv, false); - } + iwl_legacy_chswitch_done(priv, true); + } else { + IWL_ERR(priv, "CSA notif (fail) : channel %d\n", + le16_to_cpu(csa->channel)); + iwl_legacy_chswitch_done(priv, false); } } EXPORT_SYMBOL(iwl_legacy_rx_csa); diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h index bc66c604106c..c5fbda0760de 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.h +++ b/drivers/net/wireless/iwlegacy/iwl-core.h @@ -560,7 +560,7 @@ void iwl_legacy_free_geos(struct iwl_priv *priv); #define STATUS_SCAN_HW 15 #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 - +#define STATUS_CHANNEL_SWITCH_PENDING 18 static inline int iwl_legacy_is_ready(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h index be0106c6a2da..ea30122669ee 100644 --- a/drivers/net/wireless/iwlegacy/iwl-dev.h +++ b/drivers/net/wireless/iwlegacy/iwl-dev.h @@ -854,17 +854,6 @@ struct traffic_stats { #endif }; -/* - * iwl_switch_rxon: "channel switch" structure - * - * @ switch_in_progress: channel switch in progress - * @ channel: new channel - */ -struct iwl_switch_rxon { - bool switch_in_progress; - __le16 channel; -}; - /* * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds * to perform continuous uCode event logging operation if enabled @@ -1115,7 +1104,7 @@ struct iwl_priv { struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX]; - struct iwl_switch_rxon switch_rxon; + __le16 switch_channel; /* 1st responses from initialize and runtime uCode images. * _4965's initialize alive response contains some calibration data. */ diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index af2ae22fcfd3..7157ba529680 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -2861,16 +2861,13 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw, goto out; if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) + test_bit(STATUS_SCANNING, &priv->status) || + test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) goto out; if (!iwl_legacy_is_associated_ctx(ctx)) goto out; - /* channel switch in progress */ - if (priv->switch_rxon.switch_in_progress == true) - goto out; - if (priv->cfg->ops->lib->set_channel_switch) { ch = channel->hw_value; @@ -2919,15 +2916,18 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw, * at this point, staging_rxon has the * configuration for channel switch */ - if (priv->cfg->ops->lib->set_channel_switch(priv, - ch_switch)) - priv->switch_rxon.switch_in_progress = false; + set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); + priv->switch_channel = cpu_to_le16(ch); + if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) { + clear_bit(STATUS_CHANNEL_SWITCH_PENDING, + &priv->status); + priv->switch_channel = 0; + ieee80211_chswitch_done(ctx->vif, false); + } } } out: mutex_unlock(&priv->mutex); - if (!priv->switch_rxon.switch_in_progress) - ieee80211_chswitch_done(ctx->vif, false); IWL_DEBUG_MAC80211(priv, "leave\n"); } -- cgit v1.2.3 From 86d4a77ba3dc4ace238a0556541a41df2bd71d49 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 25 May 2011 13:03:16 -0400 Subject: Btrfs: cache bitmaps when searching for a cluster If we are looking for a cluster in a particularly sparse or fragmented block group, we will do a lot of looping through the free space tree looking for various things, and if we need to look at bitmaps we will endup doing the whole dance twice. So instead add the bitmap entries to a temporary list so if we have to do the bitmap search we can just look through the list of entries we've found quickly instead of having to loop through the entire tree again. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 54 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index ad144736a5fd..930c07f79b3d 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2144,6 +2144,7 @@ again: */ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, struct btrfs_free_cluster *cluster, + struct list_head *bitmaps, u64 offset, u64 bytes, u64 min_bytes) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; @@ -2166,6 +2167,8 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, * extent entry. */ while (entry->bitmap) { + if (list_empty(&entry->list)) + list_add_tail(&entry->list, bitmaps); node = rb_next(&entry->offset_index); if (!node) return -ENOSPC; @@ -2185,8 +2188,12 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, return -ENOSPC; entry = rb_entry(node, struct btrfs_free_space, offset_index); - if (entry->bitmap) + if (entry->bitmap) { + if (list_empty(&entry->list)) + list_add_tail(&entry->list, bitmaps); continue; + } + /* * we haven't filled the empty size and the window is * very large. reset and try again @@ -2240,6 +2247,7 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, */ static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, struct btrfs_free_cluster *cluster, + struct list_head *bitmaps, u64 offset, u64 bytes, u64 min_bytes) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; @@ -2250,10 +2258,39 @@ static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, if (ctl->total_bitmaps == 0) return -ENOSPC; + /* + * First check our cached list of bitmaps and see if there is an entry + * here that will work. + */ + list_for_each_entry(entry, bitmaps, list) { + if (entry->bytes < min_bytes) + continue; + ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset, + bytes, min_bytes); + if (!ret) + return 0; + } + + /* + * If we do have entries on our list and we are here then we didn't find + * anything, so go ahead and get the next entry after the last entry in + * this list and start the search from there. + */ + if (!list_empty(bitmaps)) { + entry = list_entry(bitmaps->prev, struct btrfs_free_space, + list); + node = rb_next(&entry->offset_index); + if (!node) + return -ENOSPC; + entry = rb_entry(node, struct btrfs_free_space, offset_index); + goto search; + } + entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1); if (!entry) return -ENOSPC; +search: node = &entry->offset_index; do { entry = rb_entry(node, struct btrfs_free_space, offset_index); @@ -2284,6 +2321,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, u64 offset, u64 bytes, u64 empty_size) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; + struct list_head bitmaps; + struct btrfs_free_space *entry, *tmp; u64 min_bytes; int ret; @@ -2322,11 +2361,16 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, goto out; } - ret = setup_cluster_no_bitmap(block_group, cluster, offset, bytes, - min_bytes); + INIT_LIST_HEAD(&bitmaps); + ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset, + bytes, min_bytes); if (ret) - ret = setup_cluster_bitmap(block_group, cluster, offset, - bytes, min_bytes); + ret = setup_cluster_bitmap(block_group, cluster, &bitmaps, + offset, bytes, min_bytes); + + /* Clear our temporary list */ + list_for_each_entry_safe(entry, tmp, &bitmaps, list) + list_del_init(&entry->list); if (!ret) { atomic_inc(&block_group->count); -- cgit v1.2.3 From 3de85bb95cc50d0977cbb7a0c605e894be4c790d Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 25 May 2011 13:07:37 -0400 Subject: Btrfs: noinline the cluster searching functions When profiling the find cluster code it's hard to tell where we are spending our time because the bitmap and non-bitmap functions get inlined by the compiler, so make that not happen. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 930c07f79b3d..f56caacfd8ad 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2142,10 +2142,11 @@ again: /* * This searches the block group for just extents to fill the cluster with. */ -static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, - struct btrfs_free_cluster *cluster, - struct list_head *bitmaps, - u64 offset, u64 bytes, u64 min_bytes) +static noinline int +setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, + struct btrfs_free_cluster *cluster, + struct list_head *bitmaps, u64 offset, u64 bytes, + u64 min_bytes) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *first = NULL; @@ -2245,10 +2246,11 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, * This specifically looks for bitmaps that may work in the cluster, we assume * that we have already failed to find extents that will work. */ -static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, - struct btrfs_free_cluster *cluster, - struct list_head *bitmaps, - u64 offset, u64 bytes, u64 min_bytes) +static noinline int +setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, + struct btrfs_free_cluster *cluster, + struct list_head *bitmaps, u64 offset, u64 bytes, + u64 min_bytes) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *entry; -- cgit v1.2.3 From f2bb8f5cfb3bce595b2de251ed7638047fc4e530 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 25 May 2011 13:10:16 -0400 Subject: Btrfs: don't commit the transaction if we dont have enough pinned bytes I noticed when running an enospc test that we would get stuck committing the transaction in check_data_space even though we truly didn't have enough space. So check to see if bytes_pinned is bigger than num_bytes, if it's not don't commit the transaction. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 5b9b6b6df242..0d0a3fe77bb7 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3089,6 +3089,13 @@ alloc: } goto again; } + + /* + * If we have less pinned bytes than we want to allocate then + * don't bother committing the transaction, it won't help us. + */ + if (data_sinfo->bytes_pinned < bytes) + committed = 1; spin_unlock(&data_sinfo->lock); /* commit the current transaction and try again */ -- cgit v1.2.3 From 2cdc342c204dba69ca3b2ec43d8e6ff41ed920b8 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 27 May 2011 14:07:49 -0400 Subject: Btrfs: fix bitmap regression In cleaning up the clustering code I accidently introduced a regression by adding bitmap entries to the cluster rb tree. The problem is if we've maxed out the number of bitmaps we can have for the block group we can only add free space to the bitmaps, but since the bitmap is on the cluster we can't find it and we try to create another one. This would result in a panic because the total bitmaps was bigger than the max bitmaps that were allowed. This patch fixes this by checking to see if we have a cluster, and then looking at the cluster rb tree to see if it has a bitmap entry and if it does and that space belongs to that bitmap, go ahead and add it to that bitmap. I could hit this panic every time with an fs_mark test within a couple of minutes. With this patch I no longer hit the panic and fs_mark goes to completion. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 88 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index f56caacfd8ad..8258ccf85dbd 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1417,6 +1417,23 @@ again: return 0; } +static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl, + struct btrfs_free_space *info, u64 offset, + u64 bytes) +{ + u64 bytes_to_set = 0; + u64 end; + + end = info->offset + (u64)(BITS_PER_BITMAP * ctl->unit); + + bytes_to_set = min(end - offset, bytes); + + bitmap_set_bits(ctl, info, offset, bytes_to_set); + + return bytes_to_set; + +} + static bool use_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info) { @@ -1453,12 +1470,18 @@ static bool use_bitmap(struct btrfs_free_space_ctl *ctl, return true; } +static struct btrfs_free_space_op free_space_op = { + .recalc_thresholds = recalculate_thresholds, + .use_bitmap = use_bitmap, +}; + static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info) { struct btrfs_free_space *bitmap_info; + struct btrfs_block_group_cache *block_group = NULL; int added = 0; - u64 bytes, offset, end; + u64 bytes, offset, bytes_added; int ret; bytes = info->bytes; @@ -1467,6 +1490,47 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, if (!ctl->op->use_bitmap(ctl, info)) return 0; + if (ctl->op == &free_space_op) + block_group = ctl->private; + + /* + * Since we link bitmaps right into the cluster we need to see if we + * have a cluster here, and if so and it has our bitmap we need to add + * the free space to that bitmap. + */ + if (block_group && !list_empty(&block_group->cluster_list)) { + struct btrfs_free_cluster *cluster; + struct rb_node *node; + struct btrfs_free_space *entry; + + cluster = list_entry(block_group->cluster_list.next, + struct btrfs_free_cluster, + block_group_list); + spin_lock(&cluster->lock); + node = rb_first(&cluster->root); + if (!node) { + spin_unlock(&cluster->lock); + goto again; + } + + entry = rb_entry(node, struct btrfs_free_space, offset_index); + if (!entry->bitmap) { + spin_unlock(&cluster->lock); + goto again; + } + + if (entry->offset == offset_to_bitmap(ctl, offset)) { + bytes_added = add_bytes_to_bitmap(ctl, entry, + offset, bytes); + bytes -= bytes_added; + offset += bytes_added; + } + spin_unlock(&cluster->lock); + if (!bytes) { + ret = 1; + goto out; + } + } again: bitmap_info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 1, 0); @@ -1475,19 +1539,10 @@ again: goto new_bitmap; } - end = bitmap_info->offset + (u64)(BITS_PER_BITMAP * ctl->unit); - - if (offset >= bitmap_info->offset && offset + bytes > end) { - bitmap_set_bits(ctl, bitmap_info, offset, end - offset); - bytes -= end - offset; - offset = end; - added = 0; - } else if (offset >= bitmap_info->offset && offset + bytes <= end) { - bitmap_set_bits(ctl, bitmap_info, offset, bytes); - bytes = 0; - } else { - BUG(); - } + bytes_added = add_bytes_to_bitmap(ctl, bitmap_info, offset, bytes); + bytes -= bytes_added; + offset += bytes_added; + added = 0; if (!bytes) { ret = 1; @@ -1766,11 +1821,6 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, "\n", count); } -static struct btrfs_free_space_op free_space_op = { - .recalc_thresholds = recalculate_thresholds, - .use_bitmap = use_bitmap, -}; - void btrfs_init_free_space_ctl(struct btrfs_block_group_cache *block_group) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; -- cgit v1.2.3 From 723bda2083d44edbd6be0f0b09f902120dc07442 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 27 May 2011 16:11:38 -0400 Subject: Btrfs: fix the allocator loop logic I was testing with empty_cluster = 0 to try and reproduce a problem and kept hitting early enospc panics. This was because our loop logic was a little confused. So this is what I did 1) Make the loop variable the ultimate decider on wether we should loop again isntead of checking to see if we had an uncached bg, empty size or empty cluster. 2) Increment loop before checking to see what we are on to make the loop definitions make more sense. 3) If we are on the chunk alloc loop don't set empty_size/empty_cluster to 0 unless we didn't actually allocate a chunk. If we did allocate a chunk we should be able to easily setup a new cluster so clearing empty_size/empty_cluster makes us less efficient. This kept me from hitting panics while trying to reproduce the other problem. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0d0a3fe77bb7..b42efc2ded51 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5218,9 +5218,7 @@ loop: * LOOP_NO_EMPTY_SIZE, set empty_size and empty_cluster to 0 and try * again */ - if (!ins->objectid && loop < LOOP_NO_EMPTY_SIZE && - (found_uncached_bg || empty_size || empty_cluster || - allowed_chunk_alloc)) { + if (!ins->objectid && loop < LOOP_NO_EMPTY_SIZE) { index = 0; if (loop == LOOP_FIND_IDEAL && found_uncached_bg) { found_uncached_bg = false; @@ -5260,32 +5258,36 @@ loop: goto search; } - if (loop < LOOP_CACHING_WAIT) { - loop++; - goto search; - } + loop++; if (loop == LOOP_ALLOC_CHUNK) { - empty_size = 0; - empty_cluster = 0; - } + if (allowed_chunk_alloc) { + ret = do_chunk_alloc(trans, root, num_bytes + + 2 * 1024 * 1024, data, + CHUNK_ALLOC_LIMITED); + allowed_chunk_alloc = 0; + if (ret == 1) + done_chunk_alloc = 1; + } else if (!done_chunk_alloc && + space_info->force_alloc == + CHUNK_ALLOC_NO_FORCE) { + space_info->force_alloc = CHUNK_ALLOC_LIMITED; + } - if (allowed_chunk_alloc) { - ret = do_chunk_alloc(trans, root, num_bytes + - 2 * 1024 * 1024, data, - CHUNK_ALLOC_LIMITED); - allowed_chunk_alloc = 0; - done_chunk_alloc = 1; - } else if (!done_chunk_alloc && - space_info->force_alloc == CHUNK_ALLOC_NO_FORCE) { - space_info->force_alloc = CHUNK_ALLOC_LIMITED; + /* + * We didn't allocate a chunk, go ahead and drop the + * empty size and loop again. + */ + if (!done_chunk_alloc) + loop = LOOP_NO_EMPTY_SIZE; } - if (loop < LOOP_NO_EMPTY_SIZE) { - loop++; - goto search; + if (loop == LOOP_NO_EMPTY_SIZE) { + empty_size = 0; + empty_cluster = 0; } - ret = -ENOSPC; + + goto search; } else if (!ins->objectid) { ret = -ENOSPC; } else if (ins->objectid) { -- cgit v1.2.3 From f6a398298d34af66ec3a2d82a44a4dbc5277357d Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 6 Jun 2011 10:50:35 -0400 Subject: Btrfs: fix duplicate checking logic When merging my code into the integration test the second check for duplicate entries got screwed up. This patch fixes it by dropping ret2 and just using ret for the return value, and checking if we got an error before adding the bitmap to the local list. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 8258ccf85dbd..38f3fd923043 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -250,7 +250,7 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, pgoff_t index = 0; unsigned long first_page_offset; int num_checksums; - int ret = 0, ret2; + int ret = 0; INIT_LIST_HEAD(&bitmaps); @@ -421,11 +421,10 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, goto free_cache; } spin_lock(&ctl->tree_lock); - ret2 = link_free_space(ctl, e); + ret = link_free_space(ctl, e); ctl->total_bitmaps++; ctl->op->recalc_thresholds(ctl); spin_unlock(&ctl->tree_lock); - list_add_tail(&e->list, &bitmaps); if (ret) { printk(KERN_ERR "Duplicate entries in " "free space cache, dumping\n"); @@ -434,6 +433,7 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, page_cache_release(page); goto free_cache; } + list_add_tail(&e->list, &bitmaps); } num_entries--; -- cgit v1.2.3 From 9c81075f436f867f580c2edf2350c0898cffc9d0 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 17:59:30 -0500 Subject: MD: support initial bitmap creation in-kernel Add bitmap support to the device-mapper specific metadata area. This patch allows the creation of the bitmap metadata area upon initial array creation via device-mapper. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++--- drivers/md/md.h | 1 + 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 70bd738b8b99..f0769b34d656 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -534,6 +534,82 @@ void bitmap_print_sb(struct bitmap *bitmap) kunmap_atomic(sb, KM_USER0); } +/* + * bitmap_new_disk_sb + * @bitmap + * + * This function is somewhat the reverse of bitmap_read_sb. bitmap_read_sb + * reads and verifies the on-disk bitmap superblock and populates bitmap_info. + * This function verifies 'bitmap_info' and populates the on-disk bitmap + * structure, which is to be written to disk. + * + * Returns: 0 on success, -Exxx on error + */ +static int bitmap_new_disk_sb(struct bitmap *bitmap) +{ + bitmap_super_t *sb; + unsigned long chunksize, daemon_sleep, write_behind; + int err = -EINVAL; + + bitmap->sb_page = alloc_page(GFP_KERNEL); + if (IS_ERR(bitmap->sb_page)) { + err = PTR_ERR(bitmap->sb_page); + bitmap->sb_page = NULL; + return err; + } + bitmap->sb_page->index = 0; + + sb = kmap_atomic(bitmap->sb_page, KM_USER0); + + sb->magic = cpu_to_le32(BITMAP_MAGIC); + sb->version = cpu_to_le32(BITMAP_MAJOR_HI); + + chunksize = bitmap->mddev->bitmap_info.chunksize; + BUG_ON(!chunksize); + if (!is_power_of_2(chunksize)) { + kunmap_atomic(sb, KM_USER0); + printk(KERN_ERR "bitmap chunksize not a power of 2\n"); + return -EINVAL; + } + sb->chunksize = cpu_to_le32(chunksize); + + daemon_sleep = bitmap->mddev->bitmap_info.daemon_sleep; + if (!daemon_sleep || + (daemon_sleep < 1) || (daemon_sleep > MAX_SCHEDULE_TIMEOUT)) { + printk(KERN_INFO "Choosing daemon_sleep default (5 sec)\n"); + daemon_sleep = 5 * HZ; + } + sb->daemon_sleep = cpu_to_le32(daemon_sleep); + bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; + + /* + * FIXME: write_behind for RAID1. If not specified, what + * is a good choice? We choose COUNTER_MAX / 2 arbitrarily. + */ + write_behind = bitmap->mddev->bitmap_info.max_write_behind; + if (write_behind > COUNTER_MAX) + write_behind = COUNTER_MAX / 2; + sb->write_behind = cpu_to_le32(write_behind); + bitmap->mddev->bitmap_info.max_write_behind = write_behind; + + /* keep the array size field of the bitmap superblock up to date */ + sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); + + memcpy(sb->uuid, bitmap->mddev->uuid, 16); + + bitmap->flags |= BITMAP_STALE; + sb->state |= cpu_to_le32(BITMAP_STALE); + bitmap->events_cleared = bitmap->mddev->events; + sb->events_cleared = cpu_to_le64(bitmap->mddev->events); + + bitmap->flags |= BITMAP_HOSTENDIAN; + sb->version = cpu_to_le32(BITMAP_MAJOR_HOSTENDIAN); + + kunmap_atomic(sb, KM_USER0); + + return 0; +} + /* read the superblock from the bitmap file and initialize some bitmap fields */ static int bitmap_read_sb(struct bitmap *bitmap) { @@ -1076,8 +1152,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) } printk(KERN_INFO "%s: bitmap initialized from disk: " - "read %lu/%lu pages, set %lu bits\n", - bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt); + "read %lu/%lu pages, set %lu of %lu bits\n", + bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, chunks); return 0; @@ -1728,9 +1804,16 @@ int bitmap_create(mddev_t *mddev) vfs_fsync(file, 1); } /* read superblock from bitmap file (this sets mddev->bitmap_info.chunksize) */ - if (!mddev->bitmap_info.external) - err = bitmap_read_sb(bitmap); - else { + if (!mddev->bitmap_info.external) { + /* + * If 'MD_ARRAY_FIRST_USE' is set, then device-mapper is + * instructing us to create a new on-disk bitmap instance. + */ + if (test_and_clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags)) + err = bitmap_new_disk_sb(bitmap); + else + err = bitmap_read_sb(bitmap); + } else { err = 0; if (mddev->bitmap_info.chunksize == 0 || mddev->bitmap_info.daemon_sleep == 0) diff --git a/drivers/md/md.h b/drivers/md/md.h index 5e35535ab7c3..1c26c7a08ae6 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -124,6 +124,7 @@ struct mddev_s #define MD_CHANGE_DEVS 0 /* Some device status has changed */ #define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */ #define MD_CHANGE_PENDING 2 /* switch from 'clean' to 'active' in progress */ +#define MD_ARRAY_FIRST_USE 3 /* First use of array, needs initialization */ int suspended; atomic_t active_io; -- cgit v1.2.3 From d6b212f4b19da5301e6b6eca562e5c7a2a6e8c8d Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 18:00:28 -0500 Subject: MD: raid5 do not set fullsync Add check to determine if a device needs full resync or if partial resync will do RAID 5 was assuming that if a device was not In_sync, it must undergo a full resync. We add a check to see if 'saved_raid_disk' is the same as 'raid_disk'. If it is, we can safely skip the full resync and rely on the bitmap for partial recovery instead. This is the legitimate purpose of 'saved_raid_disk', from md.h: int saved_raid_disk; /* role that device used to have in the * array and could again if we did a partial * resync from the bitmap */ Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 346e69bfdab3..f9d2fbc64977 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4858,7 +4858,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) printk(KERN_INFO "md/raid:%s: device %s operational as raid" " disk %d\n", mdname(mddev), bdevname(rdev->bdev, b), raid_disk); - } else + } else if (rdev->saved_raid_disk != raid_disk) /* Cannot rely on bitmap to complete recovery */ conf->fullsync = 1; } -- cgit v1.2.3 From d744540cd39e93976c4c8401e140232444ef3b0b Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 18:01:10 -0500 Subject: MD: use is_power_of_2 macro Make use of is_power_of_2 macro. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index f0769b34d656..7fc028f9701e 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -651,7 +651,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) reason = "unrecognized superblock version"; else if (chunksize < 512) reason = "bitmap chunksize too small"; - else if ((1 << ffz(~chunksize)) != chunksize) + else if (!is_power_of_2(chunksize)) reason = "bitmap chunksize not a power of 2"; else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT) reason = "daemon sleep period out of range"; -- cgit v1.2.3 From 9864c0053d3da4c5731ac8a6c4835179310bd40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E5=BB=BA=E6=9C=8B?= Date: Thu, 9 Jun 2011 11:42:48 +1000 Subject: md: Using poll /proc/mdstat can monitor the events of adding a spare disks Signed-off-by: majianpeng Signed-off-by: NeilBrown --- drivers/md/md.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 9160463b5f68..734bc0996390 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5274,6 +5274,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) if (mddev->degraded) set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + if (!err) + md_new_event(mddev); md_wakeup_thread(mddev->thread); return err; } -- cgit v1.2.3 From 01393f3d5836b7d62e925e6f4658a7eb22b83a11 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 9 Jun 2011 11:42:54 +1000 Subject: md: check ->hot_remove_disk when removing disk Check pers->hot_remove_disk instead of pers->hot_add_disk in slot_store() during disk removal. The linear personality only has ->hot_add_disk and no ->hot_remove_disk, so that removing disk in the array resulted to following kernel bug: $ sudo mdadm --create /dev/md0 --level=linear --raid-devices=4 /dev/loop[0-3] $ echo none | sudo tee /sys/block/md0/md/dev-loop2/slot BUG: unable to handle kernel NULL pointer dereference at (null) IP: [< (null)>] (null) PGD c9f5d067 PUD 8575a067 PMD 0 Oops: 0010 [#1] SMP CPU 2 Modules linked in: linear loop bridge stp llc kvm_intel kvm asus_atk0110 sr_mod cdrom sg Pid: 10450, comm: tee Not tainted 3.0.0-rc1-leonard+ #173 System manufacturer System Product Name/P5G41TD-M PRO RIP: 0010:[<0000000000000000>] [< (null)>] (null) RSP: 0018:ffff880085757df0 EFLAGS: 00010282 RAX: ffffffffa00168e0 RBX: ffff8800d1431800 RCX: 000000000000006e RDX: 0000000000000001 RSI: 0000000000000002 RDI: ffff88008543c000 RBP: ffff880085757e48 R08: 0000000000000002 R09: 000000000000000a R10: 0000000000000000 R11: ffff88008543c2e0 R12: 00000000ffffffff R13: ffff8800b4641000 R14: 0000000000000005 R15: 0000000000000000 FS: 00007fe8c9e05700(0000) GS:ffff88011fa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000000 CR3: 00000000b4502000 CR4: 00000000000406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process tee (pid: 10450, threadinfo ffff880085756000, task ffff8800c9f08000) Stack: ffffffff8138496a ffff8800b4641000 ffff88008543c268 0000000000000000 ffff8800b4641000 ffff88008543c000 ffff8800d1431868 ffffffff81a78a90 ffff8800b4641000 ffff88008543c000 ffff8800d1431800 ffff880085757e98 Call Trace: [] ? slot_store+0xaa/0x265 [] rdev_attr_store+0x89/0xa8 [] sysfs_write_file+0x108/0x144 [] vfs_write+0xb1/0x10d [] ? trace_hardirqs_on_caller+0x111/0x135 [] sys_write+0x4d/0x77 [] system_call_fastpath+0x16/0x1b Code: Bad RIP value. RIP [< (null)>] (null) RSP CR2: 0000000000000000 ---[ end trace ba5fc64319a826fb ]--- Signed-off-by: Namhyung Kim Cc: stable@kernel.org Signed-off-by: NeilBrown --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 734bc0996390..4332fc2f25d4 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2476,7 +2476,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) if (rdev->raid_disk == -1) return -EEXIST; /* personality does all needed checks */ - if (rdev->mddev->pers->hot_add_disk == NULL) + if (rdev->mddev->pers->hot_remove_disk == NULL) return -EINVAL; err = rdev->mddev->pers-> hot_remove_disk(rdev->mddev, rdev->raid_disk); -- cgit v1.2.3 From 27d5ea04d08bea37bf651090e5f3c573d2390df8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 9 Jun 2011 11:42:57 +1000 Subject: md/bitmap: use proper accessor macro Use COUNTER()/NEEDED() macro instead of open-coding them. Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7fc028f9701e..663e6051bbad 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1408,7 +1408,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect return 0; } - if (unlikely((*bmc & COUNTER_MAX) == COUNTER_MAX)) { + if (unlikely(COUNTER(*bmc) == COUNTER_MAX)) { DEFINE_WAIT(__wait); /* note that it is safe to do the prepare_to_wait * after the test as long as we do it before dropping @@ -1480,10 +1480,10 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto sysfs_notify_dirent_safe(bitmap->sysfs_can_clear); } - if (!success && ! (*bmc & NEEDED_MASK)) + if (!success && !NEEDED(*bmc)) *bmc |= NEEDED_MASK; - if ((*bmc & COUNTER_MAX) == COUNTER_MAX) + if (COUNTER(*bmc) == COUNTER_MAX) wake_up(&bitmap->overflow_wait); (*bmc)--; -- cgit v1.2.3 From 97b3d4aacfbd7186faf34597fcf1f55b8579be17 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 9 Jun 2011 11:43:01 +1000 Subject: md/bitmap: remove unused fields from struct bitmap Get rid of ->syncchunk and ->counter_bits since they're never used. Also discard COUNTER_BYTE_RATIO which is unused. Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 3 --- drivers/md/bitmap.h | 10 ---------- 2 files changed, 13 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 663e6051bbad..574b09afedd3 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1837,9 +1837,6 @@ int bitmap_create(mddev_t *mddev) bitmap->chunks = chunks; bitmap->pages = pages; bitmap->missing_pages = pages; - bitmap->counter_bits = COUNTER_BITS; - - bitmap->syncchunk = ~0UL; #ifdef INJECT_FATAL_FAULT_1 bitmap->bp = NULL; diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h index d0aeaf46d932..b2a127e891ac 100644 --- a/drivers/md/bitmap.h +++ b/drivers/md/bitmap.h @@ -85,7 +85,6 @@ typedef __u16 bitmap_counter_t; #define COUNTER_BITS 16 #define COUNTER_BIT_SHIFT 4 -#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8) #define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3) #define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1))) @@ -196,19 +195,10 @@ struct bitmap { mddev_t *mddev; /* the md device that the bitmap is for */ - int counter_bits; /* how many bits per block counter */ - /* bitmap chunksize -- how much data does each bit represent? */ unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */ unsigned long chunks; /* total number of data chunks for the array */ - /* We hold a count on the chunk currently being synced, and drop - * it when the last block is started. If the resync is aborted - * midway, we need to be able to drop that count, so we remember - * the counted chunk.. - */ - unsigned long syncchunk; - __u64 events_cleared; int need_sync; -- cgit v1.2.3 From f699bf2328521cc3e20c412fcdb9ffe1255c360f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 9 Jun 2011 11:43:04 +1000 Subject: md:Documentation/md.txt - fix typo Reported-by: CoolCold Signed-off-by: NeilBrown --- Documentation/md.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/md.txt b/Documentation/md.txt index 2366b1c8cf19..f0eee83ff78a 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt @@ -555,7 +555,7 @@ also have sync_min sync_max The two values, given as numbers of sectors, indicate a range - withing the array where 'check'/'repair' will operate. Must be + within the array where 'check'/'repair' will operate. Must be a multiple of chunk_size. When it reaches "sync_max" it will pause, rather than complete. You can use 'select' or 'poll' on "sync_completed" to wait for -- cgit v1.2.3 From 1780f2d3839a0d3eb85ee014a708f9e2c8f8ba0e Mon Sep 17 00:00:00 2001 From: John Johansen Date: Wed, 8 Jun 2011 15:07:47 -0700 Subject: AppArmor: Fix sleep in invalid context from task_setrlimit Affected kernels 2.6.36 - 3.0 AppArmor may do a GFP_KERNEL memory allocation with task_lock(tsk->group_leader); held when called from security_task_setrlimit. This will only occur when the task's current policy has been replaced, and the task's creds have not been updated before entering the LSM security_task_setrlimit() hook. BUG: sleeping function called from invalid context at mm/slub.c:847 in_atomic(): 1, irqs_disabled(): 0, pid: 1583, name: cupsd 2 locks held by cupsd/1583: #0: (tasklist_lock){.+.+.+}, at: [] do_prlimit+0x61/0x189 #1: (&(&p->alloc_lock)->rlock){+.+.+.}, at: [] do_prlimit+0x94/0x189 Pid: 1583, comm: cupsd Not tainted 3.0.0-rc2-git1 #7 Call Trace: [] __might_sleep+0x10d/0x112 [] slab_pre_alloc_hook.isra.49+0x2d/0x33 [] kmem_cache_alloc+0x22/0x132 [] prepare_creds+0x35/0xe4 [] aa_replace_current_profile+0x35/0xb2 [] aa_current_profile+0x45/0x4c [] apparmor_task_setrlimit+0x19/0x3a [] security_task_setrlimit+0x11/0x13 [] do_prlimit+0xd2/0x189 [] sys_setrlimit+0x3b/0x48 [] system_call_fastpath+0x16/0x1b Signed-off-by: John Johansen Reported-by: Miles Lane Cc: stable@kernel.org Signed-off-by: James Morris --- security/apparmor/lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index ec1bcecf2cda..3d2fd141dff7 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -612,7 +612,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, static int apparmor_task_setrlimit(struct task_struct *task, unsigned int resource, struct rlimit *new_rlim) { - struct aa_profile *profile = aa_current_profile(); + struct aa_profile *profile = __aa_current_profile(); int error = 0; if (!unconfined(profile)) -- cgit v1.2.3 From 618c75e491a5a50cd3819eaf5f853fd87df3ae42 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 3 Jun 2011 12:54:14 +0200 Subject: drm: fix fbs in DRM_IOCTL_MODE_GETRESOURCES ioctl The DRM_IOCTL_MODE_GETRESOURCES ioctl just returns bogus framebuffers. That is because the framebuffers for each file are in the filp_head member of struct drm_framebuffer, not in the head member. Signed-off-by: Sascha Hauer Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 872747c5a544..21058e6ad2b8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1113,7 +1113,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data, if (card_res->count_fbs >= fb_count) { copied = 0; fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; - list_for_each_entry(fb, &file_priv->fbs, head) { + list_for_each_entry(fb, &file_priv->fbs, filp_head) { if (put_user(fb->base.id, fb_id + copied)) { ret = -EFAULT; goto out; -- cgit v1.2.3 From b20f9bef8d9ff54be266062eae365ebf4b12ca64 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Jun 2011 13:01:11 -0400 Subject: drm/radeon/kms: check modes against max pixel clock Filter out modes that are higher than the max pixel clock. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_atombios.c | 4 ++++ drivers/gpu/drm/radeon/radeon_clocks.c | 8 +++++--- drivers/gpu/drm/radeon/radeon_combios.c | 5 +++++ drivers/gpu/drm/radeon/radeon_connectors.c | 13 ++++++++++++- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ba643b576054..27f45579e64b 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -165,6 +165,7 @@ struct radeon_clock { uint32_t default_sclk; uint32_t default_dispclk; uint32_t dp_extclk; + uint32_t max_pixel_clock; }; /* diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 90dfb2b8cf03..fa62a503ae70 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1246,6 +1246,10 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) } *dcpll = *p1pll; + rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock); + if (rdev->clock.max_pixel_clock == 0) + rdev->clock.max_pixel_clock = 40000; + return true; } diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 5249af8931e6..2d48e7a1474b 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -117,7 +117,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; if (p1pll->reference_div < 2) p1pll->reference_div = 12; - p2pll->reference_div = p1pll->reference_div; + p2pll->reference_div = p1pll->reference_div; /* These aren't in the device-tree */ if (rdev->family >= CHIP_R420) { @@ -139,6 +139,8 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) p2pll->pll_out_min = 12500; p2pll->pll_out_max = 35000; } + /* not sure what the max should be in all cases */ + rdev->clock.max_pixel_clock = 35000; spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; spll->reference_div = mpll->reference_div = @@ -151,7 +153,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) else rdev->clock.default_sclk = radeon_legacy_get_engine_clock(rdev); - + val = of_get_property(dp, "ATY,MCLK", NULL); if (val && *val) rdev->clock.default_mclk = (*val) / 10; @@ -160,7 +162,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) radeon_legacy_get_memory_clock(rdev); DRM_INFO("Using device-tree clock info\n"); - + return true; } #else diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 5b991f7c6e2a..d1b95b70af61 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -866,6 +866,11 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) rdev->clock.default_sclk = sclk; rdev->clock.default_mclk = mclk; + if (RBIOS32(pll_info + 0x16)) + rdev->clock.max_pixel_clock = RBIOS32(pll_info + 0x16); + else + rdev->clock.max_pixel_clock = 35000; /* might need something asic specific */ + return true; } return false; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index ee1dccb3fec9..9c2929c7e79f 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -626,8 +626,14 @@ static int radeon_vga_get_modes(struct drm_connector *connector) static int radeon_vga_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + /* XXX check mode bandwidth */ - /* XXX verify against max DAC output frequency */ + + if ((mode->clock / 10) > rdev->clock.max_pixel_clock) + return MODE_CLOCK_HIGH; + return MODE_OK; } @@ -1015,6 +1021,11 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector, } else return MODE_CLOCK_HIGH; } + + /* check against the max pixel clock */ + if ((mode->clock / 10) > rdev->clock.max_pixel_clock) + return MODE_CLOCK_HIGH; + return MODE_OK; } -- cgit v1.2.3 From 303c805cb4dc1f5bc1d21f1c3757da0eae1e4f84 Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Tue, 7 Jun 2011 14:54:48 -0400 Subject: drm/radeon: fix GUI idle IH debug statements debug statement for GUI idle interrupt is wrong and incorrectly reports CP EOP interrupt; trivial issue, but confusing for someone trying to distinguish interrupt sources while debugging ... fixed Signed-off-by: Ilija Hadzic Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 2 +- drivers/gpu/drm/radeon/r600.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 98ea597bc76d..86157b172c88 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2944,7 +2944,7 @@ restart_ih: radeon_fence_process(rdev); break; case 233: /* GUI IDLE */ - DRM_DEBUG("IH: CP EOP\n"); + DRM_DEBUG("IH: GUI idle\n"); rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); break; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index d74d4d71437f..7dd45ca64e29 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3444,7 +3444,7 @@ restart_ih: radeon_fence_process(rdev); break; case 233: /* GUI IDLE */ - DRM_DEBUG("IH: CP EOP\n"); + DRM_DEBUG("IH: GUI idle\n"); rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); break; -- cgit v1.2.3 From 72ba4cb608e7937792f3d61349ef616bbffda832 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 9 Jun 2011 04:26:31 +0000 Subject: video: s3c-fb: fix misleading kfree in remove function This patch fixes misleading kfree in remove function. Signed-off-by: Jingoo Han Signed-off-by: Paul Mundt --- drivers/video/s3c-fb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 0352afa49a39..148e19dbdbc5 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -1487,11 +1487,10 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); - kfree(sfb); - pm_runtime_put_sync(sfb->dev); pm_runtime_disable(sfb->dev); + kfree(sfb); return 0; } -- cgit v1.2.3 From 13e6af8886f3225fb9141dc3b6915d84bd4ad4de Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 9 Jun 2011 04:26:38 +0000 Subject: video: s3c-fb: fix virtual resolution checking This patch fixes mishandling in virtual resolution checking. Previously, virtual resolution is changed to virtual_x and virtual_y which mean the size for buffer allocation, when s3c_fb_check_var is called by fb_check_var. However, it is meaningless, since virtual_x and virtual_y are fixed and user cannot change virtual resolution. Therefore, virtual resolution should be more than resolution such as xres and yres. Signed-off-by: Jingoo Han Signed-off-by: Paul Mundt --- drivers/video/s3c-fb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 148e19dbdbc5..dfc2b64dde25 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -235,13 +235,12 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct s3c_fb_win *win = info->par; - struct s3c_fb_pd_win *windata = win->windata; struct s3c_fb *sfb = win->parent; dev_dbg(sfb->dev, "checking parameters\n"); - var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); - var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); + var->xres_virtual = max(var->xres_virtual, var->xres); + var->yres_virtual = max(var->yres_virtual, var->yres); if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) { dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", -- cgit v1.2.3 From fab7c5b778b1e0ee89e75679b2d6a1405318bb11 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 9 Jun 2011 04:26:45 +0000 Subject: video: s3c-fb: move enabling channel for window This patch moves enabling channel for window, because there should be enabling channel before enabling window. If the sequence is reversed, it makes the problem in displaying images to lcd panel. Signed-off-by: Jingoo Han Signed-off-by: Paul Mundt --- drivers/video/s3c-fb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index dfc2b64dde25..4aecf213c9be 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -557,6 +557,13 @@ static int s3c_fb_set_par(struct fb_info *info) vidosd_set_alpha(win, alpha); vidosd_set_size(win, data); + /* Enable DMA channel for this window */ + if (sfb->variant.has_shadowcon) { + data = readl(sfb->regs + SHADOWCON); + data |= SHADOWCON_CHx_ENABLE(win_no); + writel(data, sfb->regs + SHADOWCON); + } + data = WINCONx_ENWIN; /* note, since we have to round up the bits-per-pixel, we end up @@ -636,13 +643,6 @@ static int s3c_fb_set_par(struct fb_info *info) writel(data, regs + sfb->variant.wincon + (win_no * 4)); writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); - /* Enable DMA channel for this window */ - if (sfb->variant.has_shadowcon) { - data = readl(sfb->regs + SHADOWCON); - data |= SHADOWCON_CHx_ENABLE(win_no); - writel(data, sfb->regs + SHADOWCON); - } - shadow_protect_win(win, 0); return 0; -- cgit v1.2.3 From 6c43e0465f56248d9da56f2c4665ce1696766814 Mon Sep 17 00:00:00 2001 From: Wu Jiajun-B06378 Date: Tue, 7 Jun 2011 21:46:51 +0000 Subject: gianfar:localized filer table Each eTSEC device should own localized filer table. Signed-off-by: Jiajun Wu Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 29 +++++++++----------- drivers/net/gianfar.h | 8 ++++-- drivers/net/gianfar_ethtool.c | 64 ++++++++++++++++++++++--------------------- 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ff60b23a5b74..2dfcc8047847 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -10,7 +10,7 @@ * Maintainer: Kumar Gala * Modifier: Sandeep Gopalpet * - * Copyright 2002-2009 Freescale Semiconductor, Inc. + * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. * Copyright 2007 MontaVista Software, Inc. * * This program is free software; you can redistribute it and/or modify it @@ -476,9 +476,6 @@ static const struct net_device_ops gfar_netdev_ops = { #endif }; -unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; -unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; - void lock_rx_qs(struct gfar_private *priv) { int i = 0x0; @@ -868,28 +865,28 @@ static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar, rqfar--; rqfcr = RQFCR_CLE | RQFCR_PID_MASK | RQFCR_CMP_EXACT; - ftp_rqfpr[rqfar] = rqfpr; - ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); rqfar--; rqfcr = RQFCR_CMP_NOMATCH; - ftp_rqfpr[rqfar] = rqfpr; - ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); rqfar--; rqfcr = RQFCR_CMP_EXACT | RQFCR_PID_PARSE | RQFCR_CLE | RQFCR_AND; rqfpr = class; - ftp_rqfcr[rqfar] = rqfcr; - ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); rqfar--; rqfcr = RQFCR_CMP_EXACT | RQFCR_PID_MASK | RQFCR_AND; rqfpr = class; - ftp_rqfcr[rqfar] = rqfcr; - ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); return rqfar; @@ -904,8 +901,8 @@ static void gfar_init_filer_table(struct gfar_private *priv) /* Default rule */ rqfcr = RQFCR_CMP_MATCH; - ftp_rqfcr[rqfar] = rqfcr; - ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); rqfar = cluster_entry_per_class(priv, rqfar, RQFPR_IPV6); @@ -921,8 +918,8 @@ static void gfar_init_filer_table(struct gfar_private *priv) /* Rest are masked rules */ rqfcr = RQFCR_CMP_NOMATCH; for (i = 0; i < rqfar; i++) { - ftp_rqfcr[i] = rqfcr; - ftp_rqfpr[i] = rqfpr; + priv->ftp_rqfcr[i] = rqfcr; + priv->ftp_rqfpr[i] = rqfpr; gfar_write_filer(priv, i, rqfcr, rqfpr); } } diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index fc86f5195445..ba36dc7a3435 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -9,7 +9,7 @@ * Maintainer: Kumar Gala * Modifier: Sandeep Gopalpet * - * Copyright 2002-2009 Freescale Semiconductor, Inc. + * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -1107,10 +1107,12 @@ struct gfar_private { /* HW time stamping enabled flag */ int hwts_rx_en; int hwts_tx_en; + + /*Filer table*/ + unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; + unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; }; -extern unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; -extern unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; static inline int gfar_has_errata(struct gfar_private *priv, enum gfar_errata err) diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 493d743839d9..239e3330495f 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -9,7 +9,7 @@ * Maintainer: Kumar Gala * Modifier: Sandeep Gopalpet * - * Copyright 2003-2006, 2008-2009 Freescale Semiconductor, Inc. + * Copyright 2003-2006, 2008-2009, 2011 Freescale Semiconductor, Inc. * * This software may be used and distributed according to * the terms of the GNU Public License, Version 2, incorporated herein @@ -609,15 +609,15 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & RXH_L2DA) { fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -626,16 +626,16 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) fcr = RQFCR_PID_VID | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; priv->cur_filer_idx = priv->cur_filer_idx - 1; } if (ethflow & RXH_IP_SRC) { fcr = RQFCR_PID_SIA | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -643,8 +643,8 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & (RXH_IP_DST)) { fcr = RQFCR_PID_DIA | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -652,8 +652,8 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & RXH_L3_PROTO) { fcr = RQFCR_PID_L4P | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -661,8 +661,8 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & RXH_L4_B_0_1) { fcr = RQFCR_PID_SPT | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -670,8 +670,8 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & RXH_L4_B_2_3) { fcr = RQFCR_PID_DPT | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -705,12 +705,12 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u } for (i = 0; i < MAX_FILER_IDX + 1; i++) { - local_rqfpr[j] = ftp_rqfpr[i]; - local_rqfcr[j] = ftp_rqfcr[i]; + local_rqfpr[j] = priv->ftp_rqfpr[i]; + local_rqfcr[j] = priv->ftp_rqfcr[i]; j--; - if ((ftp_rqfcr[i] == (RQFCR_PID_PARSE | + if ((priv->ftp_rqfcr[i] == (RQFCR_PID_PARSE | RQFCR_CLE |RQFCR_AND)) && - (ftp_rqfpr[i] == cmp_rqfpr)) + (priv->ftp_rqfpr[i] == cmp_rqfpr)) break; } @@ -724,20 +724,22 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u * if it was already programmed, we need to overwrite these rules */ for (l = i+1; l < MAX_FILER_IDX; l++) { - if ((ftp_rqfcr[l] & RQFCR_CLE) && - !(ftp_rqfcr[l] & RQFCR_AND)) { - ftp_rqfcr[l] = RQFCR_CLE | RQFCR_CMP_EXACT | + if ((priv->ftp_rqfcr[l] & RQFCR_CLE) && + !(priv->ftp_rqfcr[l] & RQFCR_AND)) { + priv->ftp_rqfcr[l] = RQFCR_CLE | RQFCR_CMP_EXACT | RQFCR_HASHTBL_0 | RQFCR_PID_MASK; - ftp_rqfpr[l] = FPR_FILER_MASK; - gfar_write_filer(priv, l, ftp_rqfcr[l], ftp_rqfpr[l]); + priv->ftp_rqfpr[l] = FPR_FILER_MASK; + gfar_write_filer(priv, l, priv->ftp_rqfcr[l], + priv->ftp_rqfpr[l]); break; } - if (!(ftp_rqfcr[l] & RQFCR_CLE) && (ftp_rqfcr[l] & RQFCR_AND)) + if (!(priv->ftp_rqfcr[l] & RQFCR_CLE) && + (priv->ftp_rqfcr[l] & RQFCR_AND)) continue; else { - local_rqfpr[j] = ftp_rqfpr[l]; - local_rqfcr[j] = ftp_rqfcr[l]; + local_rqfpr[j] = priv->ftp_rqfpr[l]; + local_rqfcr[j] = priv->ftp_rqfcr[l]; j--; } } @@ -750,8 +752,8 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u /* Write back the popped out rules again */ for (k = j+1; k < MAX_FILER_IDX; k++) { - ftp_rqfpr[priv->cur_filer_idx] = local_rqfpr[k]; - ftp_rqfcr[priv->cur_filer_idx] = local_rqfcr[k]; + priv->ftp_rqfpr[priv->cur_filer_idx] = local_rqfpr[k]; + priv->ftp_rqfcr[priv->cur_filer_idx] = local_rqfcr[k]; gfar_write_filer(priv, priv->cur_filer_idx, local_rqfcr[k], local_rqfpr[k]); if (!priv->cur_filer_idx) -- cgit v1.2.3 From fe6fe792faec3fc2d2db39b69651682b8c4e7fcb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 8 Jun 2011 06:07:07 +0000 Subject: net: pmtu_expires fixes commit 2c8cec5c10bc (ipv4: Cache learned PMTU information in inetpeer) added some racy peer->pmtu_expires accesses. As its value can be changed by another cpu/thread, we should be more careful, reading its value once. Add peer_pmtu_expired() and peer_pmtu_cleaned() helpers Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 78 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 52b0b956508b..045f0ec6a4a0 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1316,6 +1316,23 @@ reject_redirect: ; } +static bool peer_pmtu_expired(struct inet_peer *peer) +{ + unsigned long orig = ACCESS_ONCE(peer->pmtu_expires); + + return orig && + time_after_eq(jiffies, orig) && + cmpxchg(&peer->pmtu_expires, orig, 0) == orig; +} + +static bool peer_pmtu_cleaned(struct inet_peer *peer) +{ + unsigned long orig = ACCESS_ONCE(peer->pmtu_expires); + + return orig && + cmpxchg(&peer->pmtu_expires, orig, 0) == orig; +} + static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) { struct rtable *rt = (struct rtable *)dst; @@ -1331,14 +1348,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) rt_genid(dev_net(dst->dev))); rt_del(hash, rt); ret = NULL; - } else if (rt->peer && - rt->peer->pmtu_expires && - time_after_eq(jiffies, rt->peer->pmtu_expires)) { - unsigned long orig = rt->peer->pmtu_expires; - - if (cmpxchg(&rt->peer->pmtu_expires, orig, 0) == orig) - dst_metric_set(dst, RTAX_MTU, - rt->peer->pmtu_orig); + } else if (rt->peer && peer_pmtu_expired(rt->peer)) { + dst_metric_set(dst, RTAX_MTU, rt->peer->pmtu_orig); } } return ret; @@ -1531,8 +1542,10 @@ unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer) { - unsigned long expires = peer->pmtu_expires; + unsigned long expires = ACCESS_ONCE(peer->pmtu_expires); + if (!expires) + return; if (time_before(jiffies, expires)) { u32 orig_dst_mtu = dst_mtu(dst); if (peer->pmtu_learned < orig_dst_mtu) { @@ -1555,10 +1568,11 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) rt_bind_peer(rt, rt->rt_dst, 1); peer = rt->peer; if (peer) { + unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires); + if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; - if (!peer->pmtu_expires || mtu < peer->pmtu_learned) { - unsigned long pmtu_expires; + if (!pmtu_expires || mtu < peer->pmtu_learned) { pmtu_expires = jiffies + ip_rt_mtu_expires; if (!pmtu_expires) @@ -1612,13 +1626,14 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) rt_bind_peer(rt, rt->rt_dst, 0); peer = rt->peer; - if (peer && peer->pmtu_expires) + if (peer) { check_peer_pmtu(dst, peer); - if (peer && peer->redirect_learned.a4 && - peer->redirect_learned.a4 != rt->rt_gateway) { - if (check_peer_redir(dst, peer)) - return NULL; + if (peer->redirect_learned.a4 && + peer->redirect_learned.a4 != rt->rt_gateway) { + if (check_peer_redir(dst, peer)) + return NULL; + } } rt->rt_peer_genid = rt_peer_genid(); @@ -1649,14 +1664,8 @@ static void ipv4_link_failure(struct sk_buff *skb) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); rt = skb_rtable(skb); - if (rt && - rt->peer && - rt->peer->pmtu_expires) { - unsigned long orig = rt->peer->pmtu_expires; - - if (cmpxchg(&rt->peer->pmtu_expires, orig, 0) == orig) - dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig); - } + if (rt && rt->peer && peer_pmtu_cleaned(rt->peer)) + dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig); } static int ip_rt_bug(struct sk_buff *skb) @@ -1770,8 +1779,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, sizeof(u32) * RTAX_MAX); dst_init_metrics(&rt->dst, peer->metrics, false); - if (peer->pmtu_expires) - check_peer_pmtu(&rt->dst, peer); + check_peer_pmtu(&rt->dst, peer); if (peer->redirect_learned.a4 && peer->redirect_learned.a4 != rt->rt_gateway) { rt->rt_gateway = peer->redirect_learned.a4; @@ -2775,7 +2783,8 @@ static int rt_fill_info(struct net *net, struct rtable *rt = skb_rtable(skb); struct rtmsg *r; struct nlmsghdr *nlh; - long expires; + long expires = 0; + const struct inet_peer *peer = rt->peer; u32 id = 0, ts = 0, tsage = 0, error; nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); @@ -2823,15 +2832,16 @@ static int rt_fill_info(struct net *net, NLA_PUT_BE32(skb, RTA_MARK, rt->rt_mark); error = rt->dst.error; - expires = (rt->peer && rt->peer->pmtu_expires) ? - rt->peer->pmtu_expires - jiffies : 0; - if (rt->peer) { + if (peer) { inet_peer_refcheck(rt->peer); - id = atomic_read(&rt->peer->ip_id_count) & 0xffff; - if (rt->peer->tcp_ts_stamp) { - ts = rt->peer->tcp_ts; - tsage = get_seconds() - rt->peer->tcp_ts_stamp; + id = atomic_read(&peer->ip_id_count) & 0xffff; + if (peer->tcp_ts_stamp) { + ts = peer->tcp_ts; + tsage = get_seconds() - peer->tcp_ts_stamp; } + expires = ACCESS_ONCE(peer->pmtu_expires); + if (expires) + expires -= jiffies; } if (rt_is_input_route(rt)) { -- cgit v1.2.3 From 0c1ad04aecb975f2a2014e1bc5a2fa23923ecbd9 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Thu, 9 Jun 2011 00:28:13 -0700 Subject: netpoll: prevent netpoll setup on slave devices In commit 8d8fc29d02a33e4bd5f4fa47823c1fd386346093 (netpoll: disable netpoll when enslave a device), we automatically disable netpoll when the underlying device is being enslaved, we also need to prevent people from setuping netpoll on devices that are already enslaved. Signed-off-by: WANG Cong Signed-off-by: David S. Miller --- net/core/netpoll.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 2d7d6d473781..42ea4b0e59f1 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -792,6 +792,12 @@ int netpoll_setup(struct netpoll *np) return -ENODEV; } + if (ndev->master) { + printk(KERN_ERR "%s: %s is a slave device, aborting.\n", + np->name, np->dev_name); + return -EBUSY; + } + if (!netif_running(ndev)) { unsigned long atmost, atleast; -- cgit v1.2.3 From 72887c8644384c0cc43b9298ae0659de383f2e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Mon, 30 May 2011 20:45:42 +0200 Subject: usb: musb: host: compare status for negative error values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variable d is a struct usb_iso_packet_descriptor. The status filed is usually negative when an error happens. Signed-off-by: Márton Németh Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 7295e316bdfc..8b2473fa0f47 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1575,7 +1575,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) /* even if there was an error, we did the dma * for iso_frame_desc->length */ - if (d->status != EILSEQ && d->status != -EOVERFLOW) + if (d->status != -EILSEQ && d->status != -EOVERFLOW) d->status = 0; if (++qh->iso_idx >= urb->number_of_packets) -- cgit v1.2.3 From 4858f06e7d92ed2ebdb29ccbc079c127e675a89c Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Wed, 8 Jun 2011 17:12:02 +0300 Subject: usb: musb: gadget: clear TXPKTRDY flag when set FLUSHFIFO Fixes mis-use of MUSB's hardware feature where it won't flush FIFOs when TXPKTRDY flag was set before and we are flushing setting both FLUSHFIFO and TXPKTRDY. In other words, we need to ensure that when we try to flush FIFOs, we don't accidentaly set TXPKTRDY bit too due to a read-back of the register. The MUSB Programming Guide says "May be set simultaneously with TxPktRdy to abort the packet that is currently being loaded into the FIFO". This is a situation where TXPKTRDY hasn't been set yet, but some data already loaded into the fifo. It looks, that if TXPKTRDY has been set before, and there is no loading in progress, but we set FLUSHFIFO with the TXPKTRDY, controller tries to use the same logic to abort loading and as the result just does nothing (because there is no packet been loaded currently) Signed-off-by: Yauheni Kaliuta [ balbi@ti.com : fixed one whitespace git complained about improved the commit log slightly ] Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 0a50a35e1853..6aeb363e63e7 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1524,6 +1524,12 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep) csr = musb_readw(epio, MUSB_TXCSR); if (csr & MUSB_TXCSR_FIFONOTEMPTY) { csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_P_WZC_BITS; + /* + * Setting both TXPKTRDY and FLUSHFIFO makes controller + * to interrupt current FIFO loading, but not flushing + * the already loaded ones. + */ + csr &= ~MUSB_TXCSR_TXPKTRDY; musb_writew(epio, MUSB_TXCSR, csr); /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */ musb_writew(epio, MUSB_TXCSR, csr); -- cgit v1.2.3 From 07989b7ad63af424886ff922fd3bcca9e00ffa78 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Jun 2011 10:10:27 +0100 Subject: Revert "ARM: 6943/1: mm: use TTBR1 instead of reserved context ID" This reverts commit 52af9c6cd863fe37d1103035ec7ee22ac1296458. Will Deacon reports that: In 52af9c6c ("ARM: 6943/1: mm: use TTBR1 instead of reserved context ID") I updated the ASID rollover code to use only the kernel page tables whilst updating the ASID. Unfortunately, the code to restore the user page tables was part of a later patch which isn't yet in mainline, so this leaves the code quite broken. We're also in the process of eliminating __ARCH_WANT_INTERRUPTS_ON_CTXSW from ARM, so lets revert these until we can properly sort out what we're doing with the ARM context switching. Signed-off-by: Russell King --- arch/arm/mm/context.c | 11 +++++------ arch/arm/mm/proc-v7.S | 10 ++++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 8bfae964b133..b6c776ae4039 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -24,7 +24,9 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm); /* * We fork()ed a process, and we need a new context for the child - * to run in. + * to run in. We reserve version 0 for initial tasks so we will + * always allocate an ASID. The ASID 0 is reserved for the TTBR + * register changing sequence. */ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) { @@ -34,11 +36,8 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) static void flush_context(void) { - u32 ttb; - /* Copy TTBR1 into TTBR0 */ - asm volatile("mrc p15, 0, %0, c2, c0, 1\n" - "mcr p15, 0, %0, c2, c0, 0" - : "=r" (ttb)); + /* set the reserved ASID before flushing the TLB */ + asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (0)); isb(); local_flush_tlb_all(); if (icache_is_vivt_asid_tagged()) { diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index b3b566ec83d3..3c3867850a30 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -108,16 +108,18 @@ ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_ARM_ERRATA_430973 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB #endif - mrc p15, 0, r2, c2, c0, 1 @ load TTB 1 - mcr p15, 0, r2, c2, c0, 0 @ into TTB 0 +#ifdef CONFIG_ARM_ERRATA_754322 + dsb +#endif + mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID + isb +1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 isb #ifdef CONFIG_ARM_ERRATA_754322 dsb #endif mcr p15, 0, r1, c13, c0, 1 @ set context ID isb - mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 - isb #endif mov pc, lr ENDPROC(cpu_v7_switch_mm) -- cgit v1.2.3 From a0a54d37b4b1d1f55d1e81e8ffc223bb85472fa3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Jun 2011 10:12:41 +0100 Subject: Revert "ARM: 6944/1: mm: allow ASID 0 to be allocated to tasks" This reverts commit 45b95235b0ac86cef2ad4480b0618b8778847479. Will Deacon reports that: In 52af9c6c ("ARM: 6943/1: mm: use TTBR1 instead of reserved context ID") I updated the ASID rollover code to use only the kernel page tables whilst updating the ASID. Unfortunately, the code to restore the user page tables was part of a later patch which isn't yet in mainline, so this leaves the code quite broken. We're also in the process of eliminating __ARCH_WANT_INTERRUPTS_ON_CTXSW from ARM, so lets revert these until we can properly sort out what we're doing with the context switching. Signed-off-by: Russell King --- arch/arm/mm/context.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index b6c776ae4039..b0ee9ba3cfab 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -93,7 +93,7 @@ static void reset_context(void *info) return; smp_rmb(); - asid = cpu_last_asid + cpu; + asid = cpu_last_asid + cpu + 1; flush_context(); set_mm_context(mm, asid); @@ -143,13 +143,13 @@ void __new_context(struct mm_struct *mm) * to start a new version and flush the TLB. */ if (unlikely((asid & ~ASID_MASK) == 0)) { - asid = cpu_last_asid + smp_processor_id(); + asid = cpu_last_asid + smp_processor_id() + 1; flush_context(); #ifdef CONFIG_SMP smp_wmb(); smp_call_function(reset_context, NULL, 1); #endif - cpu_last_asid += NR_CPUS - 1; + cpu_last_asid += NR_CPUS; } set_mm_context(mm, asid); -- cgit v1.2.3 From 6075e9df471e35f2ebf4c73c95c304d0473bd4b2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 7 Jun 2011 09:40:51 +0100 Subject: ARM: 6949/2: mach-u300: fix compilaton warning in IO accessors The IO accessors for U300 were using u32 rather than the nominal void __iomem * type, rectify this by properly defining the virtual base for statically mapped peripherals to be void __iomem *. Requires fixing a field in struct clk as well. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/clock.h | 2 +- arch/arm/mach-u300/include/mach/u300-regs.h | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-u300/clock.h b/arch/arm/mach-u300/clock.h index c34f3ea3017c..4f50ca8f901e 100644 --- a/arch/arm/mach-u300/clock.h +++ b/arch/arm/mach-u300/clock.h @@ -31,7 +31,7 @@ struct clk { bool reset; __u16 clk_val; __s8 usecount; - __u32 res_reg; + void __iomem * res_reg; __u16 res_mask; bool hw_ctrld; diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h index 8b85df4c8d8f..035fdc9dbdb0 100644 --- a/arch/arm/mach-u300/include/mach/u300-regs.h +++ b/arch/arm/mach-u300/include/mach/u300-regs.h @@ -18,6 +18,12 @@ * the defines are used for setting up the I/O memory mapping. */ +#ifdef __ASSEMBLER__ +#define IOMEM(a) (a) +#else +#define IOMEM(a) (void __iomem *) a +#endif + /* NAND Flash CS0 */ #define U300_NAND_CS0_PHYS_BASE 0x80000000 @@ -47,13 +53,6 @@ #define U300_SEMI_CONFIG_BASE 0x30000000 #endif -/* - * All the following peripherals are specified at their PHYSICAL address, - * so if you need to access them (in the kernel), you MUST use the macros - * defined in to map to the IO_ADDRESS_AHB() IO_ADDRESS_FAST() - * etc. - */ - /* * AHB peripherals */ @@ -63,11 +62,11 @@ /* Vectored Interrupt Controller 0, servicing 32 interrupts */ #define U300_INTCON0_BASE (U300_AHB_PER_PHYS_BASE+0x1000) -#define U300_INTCON0_VBASE (U300_AHB_PER_VIRT_BASE+0x1000) +#define U300_INTCON0_VBASE IOMEM(U300_AHB_PER_VIRT_BASE+0x1000) /* Vectored Interrupt Controller 1, servicing 32 interrupts */ #define U300_INTCON1_BASE (U300_AHB_PER_PHYS_BASE+0x2000) -#define U300_INTCON1_VBASE (U300_AHB_PER_VIRT_BASE+0x2000) +#define U300_INTCON1_VBASE IOMEM(U300_AHB_PER_VIRT_BASE+0x2000) /* Memory Stick Pro (MSPRO) controller */ #define U300_MSPRO_BASE (U300_AHB_PER_PHYS_BASE+0x3000) @@ -115,7 +114,7 @@ /* SYSCON */ #define U300_SYSCON_BASE (U300_SLOW_PER_PHYS_BASE+0x1000) -#define U300_SYSCON_VBASE (U300_SLOW_PER_VIRT_BASE+0x1000) +#define U300_SYSCON_VBASE IOMEM(U300_SLOW_PER_VIRT_BASE+0x1000) /* Watchdog */ #define U300_WDOG_BASE (U300_SLOW_PER_PHYS_BASE+0x2000) @@ -125,7 +124,7 @@ /* APP side special timer */ #define U300_TIMER_APP_BASE (U300_SLOW_PER_PHYS_BASE+0x4000) -#define U300_TIMER_APP_VBASE (U300_SLOW_PER_VIRT_BASE+0x4000) +#define U300_TIMER_APP_VBASE IOMEM(U300_SLOW_PER_VIRT_BASE+0x4000) /* Keypad */ #define U300_KEYPAD_BASE (U300_SLOW_PER_PHYS_BASE+0x5000) @@ -181,5 +180,4 @@ * Virtual accessor macros for static devices */ - #endif -- cgit v1.2.3 From f506cd48a4236b7045d092c9b92709ae6b4bdaf0 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 9 Jun 2011 04:58:36 +0100 Subject: ARM: 6953/1: DT: don't try to access physical address zero If the DT physical address is zero, this is equivalent to no DT. Especially when the actual RAM physical address is not located at zero, the result of phys_to_virt() would point to la-la-land and crash the kernel, which crash is completely silent this early during boot. Signed-off-by: Nicolas Pitre Acked-by: Grant Likely Signed-off-by: Russell King --- arch/arm/kernel/devtree.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index a701e4226a6c..0cdd7b456cb2 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -76,6 +76,9 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) unsigned long dt_root; const char *model; + if (!dt_phys) + return NULL; + devtree = phys_to_virt(dt_phys); /* check device tree validity */ -- cgit v1.2.3 From 720c60e1943a06cfd9472ad5a9967dec304e4394 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 9 Jun 2011 05:05:27 +0100 Subject: ARM: 6954/1: zImage: fix Thumb2 breakage Commit af3e4fd37a "ARM: 6859/1: Add writethrough dcache support for ARM926EJS processor" broke Thumb2 compilation by omitting to maintain the wide encoding for the added branch instructions which made the ARM926EJ-S record smaller than expected, breaking the record walk code. Signed-off-by: Nicolas Pitre Cc: Mark A. Greer Signed-off-by: Russell King --- arch/arm/boot/compressed/head.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index f9da41921c52..942fad97e447 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -691,9 +691,9 @@ proc_types: .word 0x41069260 @ ARM926EJ-S (v5TEJ) .word 0xff0ffff0 - b __arm926ejs_mmu_cache_on - b __armv4_mmu_cache_off - b __armv5tej_mmu_cache_flush + W(b) __arm926ejs_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv5tej_mmu_cache_flush .word 0x00007000 @ ARM7 IDs .word 0x0000f000 -- cgit v1.2.3 From 373ce3020b03fb6199415ab866595c7d627bbc97 Mon Sep 17 00:00:00 2001 From: Po-Yu Chuang Date: Thu, 9 Jun 2011 08:42:17 +0100 Subject: ARM: 6955/1: cmpxchg syscall should data abort if page not write If the page to cmpxchg is user mode read only (not write), we should simulate a data abort first. Signed-off-by: Po-Yu Chuang Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index d52eec268b47..c5ead3c2c618 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -563,7 +563,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) if (!pmd_present(*pmd)) goto bad_access; pte = pte_offset_map_lock(mm, pmd, addr, &ptl); - if (!pte_present(*pte) || !pte_dirty(*pte)) { + if (!pte_present(*pte) || !pte_write(*pte) || !pte_dirty(*pte)) { pte_unmap_unlock(pte, ptl); goto bad_access; } -- cgit v1.2.3 From 3115ae174620eeab4b16f52c8d0a9a35d2717e3c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Jun 2011 18:07:49 +0100 Subject: ASoC: WM8804 does not support sample rates below 32kHz Reported-by: Kieran O'Leary Signed-off-by: Mark Brown Acked-by: Liam Girdwood Cc: stable@kernel.org --- sound/soc/codecs/wm8804.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 6785688f8806..9a5e67c5a6bd 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -680,20 +680,25 @@ static struct snd_soc_dai_ops wm8804_dai_ops = { #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE) +#define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) + static struct snd_soc_dai_driver wm8804_dai = { .name = "wm8804-spdif", .playback = { .stream_name = "Playback", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = WM8804_RATES, .formats = WM8804_FORMATS, }, .capture = { .stream_name = "Capture", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = WM8804_RATES, .formats = WM8804_FORMATS, }, .ops = &wm8804_dai_ops, -- cgit v1.2.3 From 0cd114fff9ace7014c0d3ef8ab385fc5d3cf2d2f Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 8 Jun 2011 15:02:56 -0500 Subject: ASoC: fsl: fix initialization of DMA buffers The DMA (PCM) driver used by some Freescale PowerPC supports separate DAIs for playback and capture, so DMA buffers should be allocated only for the initialized streams. Instead of checking for the number of active channels, which apparently is not reliable, check to see if the actual stream object exists. Also provide a better name for the DMA interrupt. Signed-off-by: Timur Tabi Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 15dac0f20cd8..6680c0b4d203 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -310,7 +310,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, * should allocate a DMA buffer only for the streams that are valid. */ - if (dai->driver->playback.channels_min) { + if (pcm->streams[0].substream) { ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, fsl_dma_hardware.buffer_bytes_max, &pcm->streams[0].substream->dma_buffer); @@ -320,13 +320,13 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, } } - if (dai->driver->capture.channels_min) { + if (pcm->streams[1].substream) { ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, fsl_dma_hardware.buffer_bytes_max, &pcm->streams[1].substream->dma_buffer); if (ret) { - snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); dev_err(card->dev, "can't alloc capture dma buffer\n"); + snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); return ret; } } @@ -449,7 +449,8 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) dma_private->ld_buf_phys = ld_buf_phys; dma_private->dma_buf_phys = substream->dma_buffer.addr; - ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private); + ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "fsldma-audio", + dma_private); if (ret) { dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", dma_private->irq, ret); -- cgit v1.2.3 From db5e7ecc4abc91b9f26f0c0d79ef88a51e987d90 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 9 Jun 2011 08:40:59 -0400 Subject: tracing: Fix regression in printk_formats file The fix to fix the printk_formats of modules broke the printk_formats of trace_printks in the kernel. The update of what to show via the seq_file was only updated if the passed in fmt was NULL, which happens only on the first iteration. The result was showing the first format every time instead of iterating through the available formats. Signed-off-by: Steven Rostedt --- kernel/trace/trace_printk.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index dff763b7baf1..1f06468a10d7 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -240,13 +240,10 @@ static const char **find_next(void *v, loff_t *pos) const char **fmt = v; int start_index; - if (!fmt) - fmt = __start___trace_bprintk_fmt + *pos; - start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt; if (*pos < start_index) - return fmt; + return __start___trace_bprintk_fmt + *pos; return find_next_mod_format(start_index, v, fmt, pos); } -- cgit v1.2.3 From a91d92875ee94e4703fd017ccaadb48cfb344994 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 3 Jun 2011 09:51:34 +0000 Subject: xen: partially revert "xen: set max_pfn_mapped to the last pfn mapped" We only need to set max_pfn_mapped to the last pfn mapped on x86_64 to make sure that cleanup_highmap doesn't remove important mappings at _end. We don't need to do this on x86_32 because cleanup_highmap is not called on x86_32. Besides lowering max_pfn_mapped on x86_32 has the unwanted side effect of limiting the amount of memory available for the 1:1 kernel pagetable allocation. This patch reverts the x86_32 part of the original patch. CC: stable@kernel.org Signed-off-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index dc708dcc62f1..afe1d54f980c 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1599,6 +1599,11 @@ static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { pte_t pte; +#ifdef CONFIG_X86_32 + if (pfn > max_pfn_mapped) + max_pfn_mapped = pfn; +#endif + if (!pte_none(pte_page[pteidx])) continue; @@ -1766,7 +1771,9 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, initial_kernel_pmd = extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE); - max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + + xen_start_info->nr_pt_frames * PAGE_SIZE + + 512*1024); kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); -- cgit v1.2.3 From 977cb76d52e7aa040e18a84b29fe6fd80d79319b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 6 Jun 2011 10:15:49 +0200 Subject: x86: devicetree: Add missing early_init_dt_setup_initrd_arch stub This patch fixes the following build failure: drivers/built-in.o: In function `early_init_dt_check_for_initrd': /home/florian/dev/kernel/x86/linux-2.6-x86/drivers/of/fdt.c:571: undefined reference to `early_init_dt_setup_initrd_arch' make: *** [.tmp_vmlinux1] Error 1 which happens as soon as we enable initrd support on a x86 devicetree platform such as Intel CE4100. Signed-off-by: Florian Fainelli Acked-by: Grant Likely Cc: Maxime Bizon Acked-by: Sebastian Andrzej Siewior Cc: stable@kernel.org # 2.6.39 Link: http://lkml.kernel.org/r/201106061015.50039.ffainelli@freebox.fr Signed-off-by: Thomas Gleixner --- arch/x86/kernel/devicetree.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 690bc8461835..9aeb78a23de4 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,16 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); } +#ifdef CONFIG_BLK_DEV_INITRD +void __init early_init_dt_setup_initrd_arch(unsigned long start, + unsigned long end) +{ + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(end); + initrd_below_start_ok = 1; +} +#endif + void __init add_dtb(u64 data) { initial_dtb = data + offsetof(struct setup_data, data); -- cgit v1.2.3 From 4b80b8c2eee5282dab57f094fd3893c0c09f750c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 9 Jun 2011 13:22:36 +0200 Subject: ASoC: snd_soc_new_{mixer,mux,pga} make sure to use right DAPM context Currently it is possible that snd_soc_new_{mixer,mux,pga} is called with a DAPM context not matching the widgets context. This can lead to a wrong prefix_len calculation, which will result in undefined behaviour. To avoid this always use the DAPM context from the widget itself. Signed-off-by: Lars-Peter Clausen Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/soc-dapm.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 776e6f418306..32ab7fc4579a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -350,9 +350,9 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, } /* create new dapm mixer control */ -static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_mixer(struct snd_soc_dapm_widget *w) { + struct snd_soc_dapm_context *dapm = w->dapm; int i, ret = 0; size_t name_len, prefix_len; struct snd_soc_dapm_path *path; @@ -450,9 +450,9 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, } /* create new dapm mux control */ -static int dapm_new_mux(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_mux(struct snd_soc_dapm_widget *w) { + struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_dapm_path *path = NULL; struct snd_kcontrol *kcontrol; struct snd_card *card = dapm->card->snd_card; @@ -535,8 +535,7 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, } /* create new dapm volume control */ -static int dapm_new_pga(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_pga(struct snd_soc_dapm_widget *w) { if (w->num_kcontrols) dev_err(w->dapm->dev, @@ -1826,13 +1825,13 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) case snd_soc_dapm_mixer: case snd_soc_dapm_mixer_named_ctl: w->power_check = dapm_generic_check_power; - dapm_new_mixer(dapm, w); + dapm_new_mixer(w); break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: case snd_soc_dapm_value_mux: w->power_check = dapm_generic_check_power; - dapm_new_mux(dapm, w); + dapm_new_mux(w); break; case snd_soc_dapm_adc: case snd_soc_dapm_aif_out: @@ -1845,7 +1844,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: w->power_check = dapm_generic_check_power; - dapm_new_pga(dapm, w); + dapm_new_pga(w); break; case snd_soc_dapm_input: case snd_soc_dapm_output: -- cgit v1.2.3 From 25b8b936ed44814a5ce6fc3b2a21401f33cd56f6 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 8 Jun 2011 14:36:54 -0400 Subject: Btrfs: don't map extent buffer if path->skip_locking is set Arne's scrub stuff exposed a problem with mapping the extent buffer in reada_for_search. He searches the commit root with multiple threads and with skip_locking set, so we can race and overwrite node->map_token since node isn't locked. So fix this so that we only map the extent buffer if we don't already have a map_token and skip_locking isn't set. Without this patch scrub would panic almost immediately, with the patch it doesn't panic anymore. Thanks, Reported-by: Arne Jansen Signed-off-by: Josef Bacik --- fs/btrfs/ctree.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index d84089349c82..2e667868e0d2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1228,6 +1228,7 @@ static void reada_for_search(struct btrfs_root *root, u32 nr; u32 blocksize; u32 nscan = 0; + bool map = true; if (level != 1) return; @@ -1249,8 +1250,11 @@ static void reada_for_search(struct btrfs_root *root, nritems = btrfs_header_nritems(node); nr = slot; + if (node->map_token || path->skip_locking) + map = false; + while (1) { - if (!node->map_token) { + if (map && !node->map_token) { unsigned long offset = btrfs_node_key_ptr_offset(nr); map_private_extent_buffer(node, offset, sizeof(struct btrfs_key_ptr), @@ -1277,7 +1281,7 @@ static void reada_for_search(struct btrfs_root *root, if ((search <= target && target - search <= 65536) || (search > target && search - target <= 65536)) { gen = btrfs_node_ptr_generation(node, nr); - if (node->map_token) { + if (map && node->map_token) { unmap_extent_buffer(node, node->map_token, KM_USER1); node->map_token = NULL; @@ -1289,7 +1293,7 @@ static void reada_for_search(struct btrfs_root *root, if ((nread > 65536 || nscan > 32)) break; } - if (node->map_token) { + if (map && node->map_token) { unmap_extent_buffer(node, node->map_token, KM_USER1); node->map_token = NULL; } -- cgit v1.2.3 From 3473f3c06a36865ae05993041fff35ee928342a7 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 9 Jun 2011 10:15:17 -0400 Subject: Btrfs: unlock the trans lock properly In btrfs_wait_for_commit if we came upon a transaction that had committed we just exited, but that's bad since we are holding the trans_lock. So break instead so that the lock is dropped. Thanks, Reported-by: David Sterba Signed-off-by: Josef Bacik --- fs/btrfs/transaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index dd719662340e..6b2e4786d189 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -349,7 +349,7 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) list) { if (t->in_commit) { if (t->commit_done) - goto out; + break; cur_trans = t; atomic_inc(&cur_trans->use_count); break; -- cgit v1.2.3 From 8d03e971cf403305217b8e62db3a2e5ad2d6263f Mon Sep 17 00:00:00 2001 From: Filip Palian Date: Thu, 12 May 2011 19:32:46 +0200 Subject: Bluetooth: l2cap and rfcomm: fix 1 byte infoleak to userspace. Structures "l2cap_conninfo" and "rfcomm_conninfo" have one padding byte each. This byte in "cinfo" is copied to userspace uninitialized. Signed-off-by: Filip Palian Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 1 + net/bluetooth/rfcomm/sock.c | 1 + 2 files changed, 2 insertions(+) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 18dc9888d8c2..8248303f44e8 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -413,6 +413,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; } + memset(&cinfo, 0, sizeof(cinfo)); cinfo.hci_handle = chan->conn->hcon->handle; memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 386cfaffd4b7..1b10727ce523 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -788,6 +788,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk; + memset(&cinfo, 0, sizeof(cinfo)); cinfo.hci_handle = conn->hcon->handle; memcpy(cinfo.dev_class, conn->hcon->dev_class, 3); -- cgit v1.2.3 From a9dce2a3b4f0686dd66cb44d4826a59508bce969 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 9 Jun 2011 20:43:54 +0200 Subject: block: don't use non-syncing event blocking in disk_check_events() This patch is part of fix for triggering of WARN_ON_ONCE() in disk_clear_events() reported in bug#34662. https://bugzilla.kernel.org/show_bug.cgi?id=34662 disk_clear_events() blocks events, schedules and flushes the event work. It expects the work to have started execution on schedule and finished on return from flush. WARN_ON_ONCE() triggers if the event work hasn't executed as expected. This problem happens because __disk_block_events() fails to guarantee that the event work item is not in flight on return from the function in race-free manner. The problem is two-fold and this patch addresses one of them. When __disk_block_events() is called with @sync == %false, it bumps event block count, calls cancel_delayed_work() and return. This makes it impossible to guarantee that event polling is not in flight on return from syncing __disk_block_events() - if the first blocker was non-syncing, polling could still be in progress and later syncing ones would assume that the first blocker already canceled it. Making __disk_block_events() cancel_sync regardless of block count isn't feasible either as it may race with forced event checking in disk_clear_events(). As disk_check_events() is the only user of non-syncing __disk_block_events(), updating it to directly cancel and schedule event work is the easiest way to solve the issue. Note that there's another bug in __disk_block_events() and this patch doesn't fix the issue completely. Later patch will fix the other bug. Signed-off-by: Tejun Heo Tested-by: Sitsofe Wheeler Reported-by: Sitsofe Wheeler Reported-by: Borislav Petkov Reported-by: Meelis Roos Reported-by: Linus Torvalds Cc: Andrew Morton Cc: Jens Axboe Cc: Kay Sievers Signed-off-by: Jens Axboe --- block/genhd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 95822ae25cfe..3f0933077642 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1508,10 +1508,18 @@ void disk_unblock_events(struct gendisk *disk) */ void disk_check_events(struct gendisk *disk) { - if (disk->ev) { - __disk_block_events(disk, false); - __disk_unblock_events(disk, true); + struct disk_events *ev = disk->ev; + unsigned long flags; + + if (!ev) + return; + + spin_lock_irqsave(&ev->lock, flags); + if (!ev->block) { + cancel_delayed_work(&ev->dwork); + queue_delayed_work(system_nrt_wq, &ev->dwork, 0); } + spin_unlock_irqrestore(&ev->lock, flags); } EXPORT_SYMBOL_GPL(disk_check_events); -- cgit v1.2.3 From c3af54afbac3675337cedf326b7b127ffa7f7327 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 9 Jun 2011 20:43:55 +0200 Subject: block: remove non-syncing __disk_block_events() and fold it into disk_block_events() After the previous update to disk_check_events(), nobody is using non-syncing __disk_block_events(). Remove @sync and, as this makes __disk_block_events() virtually identical to disk_block_events(), remove the underscore prefixed version. Signed-off-by: Tejun Heo Cc: Jens Axboe Signed-off-by: Jens Axboe --- block/genhd.c | 55 ++++++++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 3f0933077642..ab0731d8976d 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1414,22 +1414,36 @@ static unsigned long disk_events_poll_jiffies(struct gendisk *disk) return msecs_to_jiffies(intv_msecs); } -static void __disk_block_events(struct gendisk *disk, bool sync) +/** + * disk_block_events - block and flush disk event checking + * @disk: disk to block events for + * + * On return from this function, it is guaranteed that event checking + * isn't in progress and won't happen until unblocked by + * disk_unblock_events(). Events blocking is counted and the actual + * unblocking happens after the matching number of unblocks are done. + * + * Note that this intentionally does not block event checking from + * disk_clear_events(). + * + * CONTEXT: + * Might sleep. + */ +void disk_block_events(struct gendisk *disk) { struct disk_events *ev = disk->ev; unsigned long flags; bool cancel; + if (!ev) + return; + spin_lock_irqsave(&ev->lock, flags); cancel = !ev->block++; spin_unlock_irqrestore(&ev->lock, flags); - if (cancel) { - if (sync) - cancel_delayed_work_sync(&disk->ev->dwork); - else - cancel_delayed_work(&disk->ev->dwork); - } + if (cancel) + cancel_delayed_work_sync(&disk->ev->dwork); } static void __disk_unblock_events(struct gendisk *disk, bool check_now) @@ -1460,27 +1474,6 @@ out_unlock: spin_unlock_irqrestore(&ev->lock, flags); } -/** - * disk_block_events - block and flush disk event checking - * @disk: disk to block events for - * - * On return from this function, it is guaranteed that event checking - * isn't in progress and won't happen until unblocked by - * disk_unblock_events(). Events blocking is counted and the actual - * unblocking happens after the matching number of unblocks are done. - * - * Note that this intentionally does not block event checking from - * disk_clear_events(). - * - * CONTEXT: - * Might sleep. - */ -void disk_block_events(struct gendisk *disk) -{ - if (disk->ev) - __disk_block_events(disk, true); -} - /** * disk_unblock_events - unblock disk event checking * @disk: disk to unblock events for @@ -1554,7 +1547,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask) spin_unlock_irq(&ev->lock); /* uncondtionally schedule event check and wait for it to finish */ - __disk_block_events(disk, true); + disk_block_events(disk); queue_delayed_work(system_nrt_wq, &ev->dwork, 0); flush_delayed_work(&ev->dwork); __disk_unblock_events(disk, false); @@ -1672,7 +1665,7 @@ static ssize_t disk_events_poll_msecs_store(struct device *dev, if (intv < 0 && intv != -1) return -EINVAL; - __disk_block_events(disk, true); + disk_block_events(disk); disk->ev->poll_msecs = intv; __disk_unblock_events(disk, true); @@ -1778,7 +1771,7 @@ static void disk_del_events(struct gendisk *disk) if (!disk->ev) return; - __disk_block_events(disk, true); + disk_block_events(disk); mutex_lock(&disk_events_mutex); list_del_init(&disk->ev->node); -- cgit v1.2.3 From fdd514e16bb2531c0c61ae8a1f87740ce217f630 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 9 Jun 2011 20:43:59 +0200 Subject: block: make disk_block_events() properly wait for work cancellation disk_block_events() should guarantee that the event work is not in flight on return and once blocked it shouldn't issue further cancellations. Because there was no synchronization between the first blocker doing cancel_delayed_work_sync() and the following blockers, the following blockers could finish before cancellation was complete, which broke both guarantees - event work could be in flight and cancellation could happen after return. This bug triggered WARN_ON_ONCE() in disk_clear_events() reported in bug#34662. https://bugzilla.kernel.org/show_bug.cgi?id=34662 Fix it by adding an outer mutex which protects both block count manipulation and work cancellation. -v2: Use outer mutex instead of bit waitqueue per Linus. Signed-off-by: Tejun Heo Tested-by: Sitsofe Wheeler Reported-by: Sitsofe Wheeler Reported-by: Borislav Petkov Reported-by: Meelis Roos Reported-by: Linus Torvalds Cc: Andrew Morton Cc: Jens Axboe Cc: Kay Sievers Signed-off-by: Jens Axboe --- block/genhd.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/block/genhd.c b/block/genhd.c index ab0731d8976d..3608289c8ecd 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1371,6 +1371,7 @@ struct disk_events { struct gendisk *disk; /* the associated disk */ spinlock_t lock; + struct mutex block_mutex; /* protects blocking */ int block; /* event blocking depth */ unsigned int pending; /* events already sent out */ unsigned int clearing; /* events being cleared */ @@ -1438,12 +1439,20 @@ void disk_block_events(struct gendisk *disk) if (!ev) return; + /* + * Outer mutex ensures that the first blocker completes canceling + * the event work before further blockers are allowed to finish. + */ + mutex_lock(&ev->block_mutex); + spin_lock_irqsave(&ev->lock, flags); cancel = !ev->block++; spin_unlock_irqrestore(&ev->lock, flags); if (cancel) cancel_delayed_work_sync(&disk->ev->dwork); + + mutex_unlock(&ev->block_mutex); } static void __disk_unblock_events(struct gendisk *disk, bool check_now) @@ -1751,6 +1760,7 @@ static void disk_add_events(struct gendisk *disk) INIT_LIST_HEAD(&ev->node); ev->disk = disk; spin_lock_init(&ev->lock); + mutex_init(&ev->block_mutex); ev->block = 1; ev->poll_msecs = -1; INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn); -- cgit v1.2.3 From 33d78647dc409784c18aa71995346e6955802fe0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Jun 2011 11:08:47 +0200 Subject: gpio/nomadik: fix sleepmode for elder Nomadik The mach-nomadik machine did not compile properly due to bad ux500-specific functions being called. Introduce new state variables to fix this up. Reported-by: Axel Lin Cc: Alessandro Rubini Cc: Prafulla Wadaskar Signed-off-by: Linus Walleij Signed-off-by: Grant Likely --- arch/arm/mach-ux500/cpu-db8500.c | 3 +++ arch/arm/plat-nomadik/include/plat/gpio.h | 1 + drivers/gpio/gpio-nomadik.c | 40 ++++++++++++++++++++++--------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index c3c417656bd9..4598b06c8c55 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -159,6 +159,9 @@ static void __init db8500_add_gpios(void) /* No custom data yet */ }; + if (cpu_is_u8500v2()) + pdata.supports_sleepmode = true; + dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), IRQ_DB8500_GPIO0, &pdata); } diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index ea19a5b2f227..d5d7e651269c 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -90,6 +90,7 @@ struct nmk_gpio_platform_data { int num_gpio; u32 (*get_secondary_status)(unsigned int bank); void (*set_ioforce)(bool enable); + bool supports_sleepmode; }; #endif /* __ASM_PLAT_GPIO_H */ diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index 4961ef9bc153..2c212c732d76 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -4,6 +4,7 @@ * Copyright (C) 2008,2009 STMicroelectronics * Copyright (C) 2009 Alessandro Rubini * Rewritten based on work by Prafulla WADASKAR + * Copyright (C) 2011 Linus Walleij * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -49,6 +50,7 @@ struct nmk_gpio_chip { u32 (*get_secondary_status)(unsigned int bank); void (*set_ioforce)(bool enable); spinlock_t lock; + bool sleepmode; /* Keep track of configured edges */ u32 edge_rising; u32 edge_falling; @@ -393,14 +395,25 @@ EXPORT_SYMBOL(nmk_config_pins_sleep); * @gpio: pin number * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE, * - * Sets the sleep mode of a pin. If @mode is NMK_GPIO_SLPM_INPUT, the pin is - * changed to an input (with pullup/down enabled) in sleep and deep sleep. If - * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was - * configured even when in sleep and deep sleep. + * This register is actually in the pinmux layer, not the GPIO block itself. + * The GPIO1B_SLPM register defines the GPIO mode when SLEEP/DEEP-SLEEP + * mode is entered (i.e. when signal IOFORCE is HIGH by the platform code). + * Each GPIO can be configured to be forced into GPIO mode when IOFORCE is + * HIGH, overriding the normal setting defined by GPIO_AFSELx registers. + * When IOFORCE returns LOW (by software, after SLEEP/DEEP-SLEEP exit), + * the GPIOs return to the normal setting defined by GPIO_AFSELx registers. * - * On DB8500v2 onwards, this setting loses the previous meaning and instead - * indicates if wakeup detection is enabled on the pin. Note that - * enable_irq_wake() will automatically enable wakeup detection. + * If @mode is NMK_GPIO_SLPM_INPUT, the corresponding GPIO is switched to GPIO + * mode when signal IOFORCE is HIGH (i.e. when SLEEP/DEEP-SLEEP mode is + * entered) regardless of the altfunction selected. Also wake-up detection is + * ENABLED. + * + * If @mode is NMK_GPIO_SLPM_NOCHANGE, the corresponding GPIO remains + * controlled by NMK_GPIO_DATC, NMK_GPIO_DATS, NMK_GPIO_DIR, NMK_GPIO_PDIS + * (for altfunction GPIO) or respective on-chip peripherals (for other + * altfuncs) when IOFORCE is HIGH. Also wake-up detection DISABLED. + * + * Note that enable_irq_wake() will automatically enable wakeup detection. */ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) { @@ -551,6 +564,12 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, int gpio, bool on) { + if (nmk_chip->sleepmode) { + __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, + on ? NMK_GPIO_SLPM_WAKEUP_ENABLE + : NMK_GPIO_SLPM_WAKEUP_DISABLE); + } + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); } @@ -901,7 +920,7 @@ void nmk_gpio_wakeups_suspend(void) writel(chip->fwimsc & chip->real_wake, chip->addr + NMK_GPIO_FWIMSC); - if (cpu_is_u8500v2()) { + if (chip->sleepmode) { chip->slpm = readl(chip->addr + NMK_GPIO_SLPC); /* 0 -> wakeup enable */ @@ -923,7 +942,7 @@ void nmk_gpio_wakeups_resume(void) writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); - if (cpu_is_u8500v2()) + if (chip->sleepmode) writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); } } @@ -1010,6 +1029,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) nmk_chip->secondary_parent_irq = secondary_irq; nmk_chip->get_secondary_status = pdata->get_secondary_status; nmk_chip->set_ioforce = pdata->set_ioforce; + nmk_chip->sleepmode = pdata->supports_sleepmode; spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; @@ -1065,5 +1085,3 @@ core_initcall(nmk_gpio_init); MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); MODULE_DESCRIPTION("Nomadik GPIO Driver"); MODULE_LICENSE("GPL"); - - -- cgit v1.2.3 From 96d7303e9cfb6a9bc664174a4dfdb6fa689284fe Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 5 Jun 2011 20:48:47 +0000 Subject: ipv4: Fix packet size calculation for raw IPsec packets in __ip_append_data We assume that transhdrlen is positive on the first fragment which is wrong for raw packets. So we don't add exthdrlen to the packet size for raw packets. This leads to a reallocation on IPsec because we have not enough headroom on the skb to place the IPsec headers. This patch fixes this by adding exthdrlen to the packet size whenever the send queue of the socket is empty. This issue was introduced with git commit 1470ddf7 (inet: Remove explicit write references to sk/inet in ip_append_data) Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 98af3697c718..a8024eaa0e87 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -799,7 +799,9 @@ static int __ip_append_data(struct sock *sk, int csummode = CHECKSUM_NONE; struct rtable *rt = (struct rtable *)cork->dst; - exthdrlen = transhdrlen ? rt->dst.header_len : 0; + skb = skb_peek_tail(queue); + + exthdrlen = !skb ? rt->dst.header_len : 0; length += exthdrlen; transhdrlen += exthdrlen; mtu = cork->fragsize; @@ -825,8 +827,6 @@ static int __ip_append_data(struct sock *sk, !exthdrlen) csummode = CHECKSUM_PARTIAL; - skb = skb_peek_tail(queue); - cork->length += length; if (((length > mtu) || (skb && skb_is_gso(skb))) && (sk->sk_protocol == IPPROTO_UDP) && -- cgit v1.2.3 From 5587912fcff1da2ff8494fa33cf9d92dc6982c11 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 9 Jun 2011 15:00:21 -0700 Subject: ep93xx_eth: Update MAINTAINERS Lennert stated that he has been short on time lately. Since I'm maintaining the ep93xx core stuff, I'm willing to also take over maintaining the Ethernet driver. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Acked-by: Lennert Buytenhek Signed-off-by: David S. Miller --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 29801f760b6f..6a1c430d2821 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1739,7 +1739,7 @@ S: Supported F: drivers/net/enic/ CIRRUS LOGIC EP93XX ETHERNET DRIVER -M: Lennert Buytenhek +M: Hartley Sweeten L: netdev@vger.kernel.org S: Maintained F: drivers/net/arm/ep93xx_eth.c -- cgit v1.2.3 From b4c8cc88c18213688268d1d53a51d97ce2f19a64 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 9 Jun 2011 15:05:48 -0700 Subject: ethtool.h: fix typos Signed-off-by: Yegor Yefremov Signed-off-by: David S. Miller --- include/linux/ethtool.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c6a850ab2ec5..439b173c5882 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -268,7 +268,7 @@ struct ethtool_pauseparam { __u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autonet' here non-zero to have the + * being true) the user may set 'autoneg' here non-zero to have the * pause parameters be auto-negotiated too. In such a case, the * {rx,tx}_pause values below determine what capabilities are * advertised. @@ -811,7 +811,7 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * @get_tx_csum: Deprecated as redundant. Report whether transmit checksums * are turned on or off. * @set_tx_csum: Deprecated in favour of generic netdev features. Turn - * transmit checksums on or off. Returns a egative error code or zero. + * transmit checksums on or off. Returns a negative error code or zero. * @get_sg: Deprecated as redundant. Report whether scatter-gather is * enabled. * @set_sg: Deprecated in favour of generic netdev features. Turn @@ -1087,7 +1087,7 @@ struct ethtool_ops { /* The following are all involved in forcing a particular link * mode for the device for setting things. When getting the * devices settings, these indicate the current mode and whether - * it was foced up into this mode or autonegotiated. + * it was forced up into this mode or autonegotiated. */ /* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ -- cgit v1.2.3 From a9011580a99cd4f21546381782582bfaf9e40675 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Jun 2011 23:21:11 +0100 Subject: ARM: extend Code: line by one 16-bit quantity for Thumb instructions Dump out the following 16-bit instruction to the faulting instruction in the Code: line. This allows Thumb-2 instructions to be properly encoded. Tested-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index c5ead3c2c618..6807cb1e76dd 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -139,7 +139,7 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) fs = get_fs(); set_fs(KERNEL_DS); - for (i = -4; i < 1; i++) { + for (i = -4; i < 1 + !!thumb; i++) { unsigned int val, bad; if (thumb) -- cgit v1.2.3 From 13863a66c9c8a663665445cf05d68de96ff31830 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 9 Jun 2011 23:14:58 +0200 Subject: genirq: Prevent potential NULL dereference in irq_set_irq_wake() In kernel/irq/manage.c::irq_set_irq_wake() we call irq_get_desc_buslock() which may return NULL, but the code dereferences the result unconditionally. irq_set_irq_wake() has lots of callers - I checked a few and I couldn't find anything that guarantees that they won't call it with some input that will cause irq_get_desc_buslock() to return NULL, so I think it's a good thing to test and -EINVAL was the most sane error code in this situation that I could think of. Not all callers test the return value of irq_set_irq_wake(), but those that do take != 0 to mean error as far as I can see, so they should be fine. I guess those that don't test actually should, but that's a different issue. Signed-off-by: Jesper Juhl Link: http://lkml.kernel.org/r/alpine.LNX.2.00.1106092300360.17868@swampdragon.chaosbits.net Signed-off-by: Thomas Gleixner --- kernel/irq/manage.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index d64bafb1afd0..0a7840aeb0fb 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -491,6 +491,9 @@ int irq_set_irq_wake(unsigned int irq, unsigned int on) struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); int ret = 0; + if (!desc) + return -EINVAL; + /* wakeup-capable irqs can be shared between drivers that * don't need to have the same sleep mode behaviors. */ -- cgit v1.2.3 From 33195500edf260e8c8809ab9dfc67f50e0ce031f Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Fri, 10 Jun 2011 10:36:54 +0900 Subject: ASoC: SAMSUNG: Fix the incorrect referencing of I2SCON register If DMA active status should be checked, I2SCON register should be referenced. In this patch, Fix the incorrect referencing of I2SCON register. Reported-by : Lakkyung Jung Signed-off-by: Sangbeom Kim Acked-by: Jassi Brar Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/samsung/i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index ffa09b3b2caa..992a732b5211 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -191,7 +191,7 @@ static inline bool tx_active(struct i2s_dai *i2s) if (!i2s) return false; - active = readl(i2s->addr + I2SMOD); + active = readl(i2s->addr + I2SCON); if (is_secondary(i2s)) active &= CON_TXSDMA_ACTIVE; @@ -223,7 +223,7 @@ static inline bool rx_active(struct i2s_dai *i2s) if (!i2s) return false; - active = readl(i2s->addr + I2SMOD) & CON_RXDMA_ACTIVE; + active = readl(i2s->addr + I2SCON) & CON_RXDMA_ACTIVE; return active ? true : false; } -- cgit v1.2.3 From ad3e34bba4b64ab8e1f5ea1a17768e1a0d9648ea Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 8 Jun 2011 14:45:50 -0400 Subject: Btrfs: don't map extent buffer if path->skip_locking is set Arne's scrub stuff exposed a problem with mapping the extent buffer in reada_for_search. He searches the commit root with multiple threads and with skip_locking set, so we can race and overwrite node->map_token since node isn't locked. So fix this so that we only map the extent buffer if we don't already have a map_token and skip_locking isn't set. Without this patch scrub would panic almost immediately, with the patch it doesn't panic anymore. Thanks, Reported-by: Arne Jansen Signed-off-by: Josef Bacik --- fs/btrfs/ctree.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index d84089349c82..2e667868e0d2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1228,6 +1228,7 @@ static void reada_for_search(struct btrfs_root *root, u32 nr; u32 blocksize; u32 nscan = 0; + bool map = true; if (level != 1) return; @@ -1249,8 +1250,11 @@ static void reada_for_search(struct btrfs_root *root, nritems = btrfs_header_nritems(node); nr = slot; + if (node->map_token || path->skip_locking) + map = false; + while (1) { - if (!node->map_token) { + if (map && !node->map_token) { unsigned long offset = btrfs_node_key_ptr_offset(nr); map_private_extent_buffer(node, offset, sizeof(struct btrfs_key_ptr), @@ -1277,7 +1281,7 @@ static void reada_for_search(struct btrfs_root *root, if ((search <= target && target - search <= 65536) || (search > target && search - target <= 65536)) { gen = btrfs_node_ptr_generation(node, nr); - if (node->map_token) { + if (map && node->map_token) { unmap_extent_buffer(node, node->map_token, KM_USER1); node->map_token = NULL; @@ -1289,7 +1293,7 @@ static void reada_for_search(struct btrfs_root *root, if ((nread > 65536 || nscan > 32)) break; } - if (node->map_token) { + if (map && node->map_token) { unmap_extent_buffer(node, node->map_token, KM_USER1); node->map_token = NULL; } -- cgit v1.2.3 From 8c51032f978bac5bec5dae0c5de4f85db97c1cc9 Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Fri, 3 Jun 2011 10:09:26 +0200 Subject: btrfs: scrub: errors in tree enumeration due to the semantics of btrfs_search_slot the path can point to an invalid slot when ret > 0. This condition went unnoticed, which in turn could have led to an incomplete scrubbing. Signed-off-by: Arne Jansen --- fs/btrfs/scrub.c | 57 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index df50fd1eca8f..d5a4108cedaf 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -804,18 +804,12 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) - goto out; - - l = path->nodes[0]; - slot = path->slots[0]; - btrfs_item_key_to_cpu(l, &key, slot); - if (key.objectid != logical) { - ret = btrfs_previous_item(root, path, 0, - BTRFS_EXTENT_ITEM_KEY); - if (ret < 0) - goto out; - } + goto out_noplug; + /* + * we might miss half an extent here, but that doesn't matter, + * as it's only the prefetch + */ while (1) { l = path->nodes[0]; slot = path->slots[0]; @@ -824,7 +818,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, if (ret == 0) continue; if (ret < 0) - goto out; + goto out_noplug; break; } @@ -906,15 +900,20 @@ again: ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) goto out; - - l = path->nodes[0]; - slot = path->slots[0]; - btrfs_item_key_to_cpu(l, &key, slot); - if (key.objectid != logical) { + if (ret > 0) { ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY); if (ret < 0) goto out; + if (ret > 0) { + /* there's no smaller item, so stick with the + * larger one */ + btrfs_release_path(path); + ret = btrfs_search_slot(NULL, root, &key, + path, 0, 0); + if (ret < 0) + goto out; + } } while (1) { @@ -989,6 +988,7 @@ next: out: blk_finish_plug(&plug); +out_noplug: btrfs_free_path(path); return ret < 0 ? ret : 0; } @@ -1064,8 +1064,15 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) while (1) { ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) - goto out; - ret = 0; + break; + if (ret > 0) { + if (path->slots[0] >= + btrfs_header_nritems(path->nodes[0])) { + ret = btrfs_next_leaf(root, path); + if (ret) + break; + } + } l = path->nodes[0]; slot = path->slots[0]; @@ -1075,7 +1082,7 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) if (found_key.objectid != sdev->dev->devid) break; - if (btrfs_key_type(&key) != BTRFS_DEV_EXTENT_KEY) + if (btrfs_key_type(&found_key) != BTRFS_DEV_EXTENT_KEY) break; if (found_key.offset >= end) @@ -1104,7 +1111,7 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) cache = btrfs_lookup_block_group(fs_info, chunk_offset); if (!cache) { ret = -ENOENT; - goto out; + break; } ret = scrub_chunk(sdev, chunk_tree, chunk_objectid, chunk_offset, length); @@ -1116,9 +1123,13 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) btrfs_release_path(path); } -out: btrfs_free_path(path); - return ret; + + /* + * ret can still be 1 from search_slot or next_leaf, + * that's not an error + */ + return ret < 0 ? ret : 0; } static noinline_for_stack int scrub_supers(struct scrub_dev *sdev) -- cgit v1.2.3 From 632dd772fcbde2ba37c0e8983bd38ef4a1eac906 Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Fri, 10 Jun 2011 12:07:07 +0200 Subject: btrfs: reinitialize scrub workers Scrub starts the workers each time a scrub starts and stops them after it finished. This patch adds an initialization for the workers before each start, otherwise the workers behave strangely. Signed-off-by: Arne Jansen --- fs/btrfs/disk-io.c | 2 -- fs/btrfs/scrub.c | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a203d363184d..7bbbfebe47e4 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1668,8 +1668,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, init_waitqueue_head(&fs_info->scrub_pause_wait); init_rwsem(&fs_info->scrub_super_lock); fs_info->scrub_workers_refcnt = 0; - btrfs_init_workers(&fs_info->scrub_workers, "scrub", - fs_info->thread_pool_size, &fs_info->generic_worker); sb->s_blocksize = 4096; sb->s_blocksize_bits = blksize_bits(4096); diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index d5a4108cedaf..92cac19388ed 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1166,8 +1166,12 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_root *root) struct btrfs_fs_info *fs_info = root->fs_info; mutex_lock(&fs_info->scrub_lock); - if (fs_info->scrub_workers_refcnt == 0) + if (fs_info->scrub_workers_refcnt == 0) { + btrfs_init_workers(&fs_info->scrub_workers, "scrub", + fs_info->thread_pool_size, &fs_info->generic_worker); + fs_info->scrub_workers.idle_thresh = 4; btrfs_start_workers(&fs_info->scrub_workers, 1); + } ++fs_info->scrub_workers_refcnt; mutex_unlock(&fs_info->scrub_lock); -- cgit v1.2.3 From 6eef3125886df260ca0e8758d141308152226f6a Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Fri, 10 Jun 2011 13:04:58 +0200 Subject: btrfs: remove unneeded includes from scrub.c Signed-off-by: Arne Jansen --- fs/btrfs/scrub.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 92cac19388ed..a8d03d5efb5d 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -16,13 +16,7 @@ * Boston, MA 021110-1307, USA. */ -#include -#include -#include #include -#include -#include -#include #include "ctree.h" #include "volumes.h" #include "disk-io.h" -- cgit v1.2.3 From 20f5e0b36d968326fab3b720035f226113e34ae9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Jun 2011 09:31:54 +0200 Subject: ALSA: hda - Fix invalid unsol tag for some alc262 model quirks The tag number was forgotten to be fixed after cleaning up the model quirks for ALC262 fujitsu and lenovo-3000 models. Tested-by: Michal Hocko Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d7007896772b..ca211c1cba03 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -11924,7 +11924,7 @@ static const struct hda_verb alc262_nec_verbs[] = { * 0x1b = port replicator headphone out */ -#define ALC_HP_EVENT 0x37 +#define ALC_HP_EVENT ALC880_HP_EVENT static const struct hda_verb alc262_fujitsu_unsol_verbs[] = { {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, -- cgit v1.2.3 From c0a20263dbe1fc5f394913d71063c9cd8282c5db Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Jun 2011 15:28:15 +0200 Subject: ALSA: hda - Fix initialization of hp pins with master_mute in Realtek Some Reatlek model quirks use master_mute bool switch for controlling the master-mute of outputs. For these cases, the initialization of HP pins/amps were forgotten during the transition to the common automute helper function in 3.0 development time, and resulted in the muted HP output as default. This patch fixes the issue by adjusting the HP output explicitly with master_mute switch. Tested-by: Michal Hocko Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ca211c1cba03..43fcfbd32847 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1141,6 +1141,13 @@ static void update_speakers(struct hda_codec *codec) struct alc_spec *spec = codec->spec; int on; + /* Control HP pins/amps depending on master_mute state; + * in general, HP pins/amps control should be enabled in all cases, + * but currently set only for master_mute, just to be safe + */ + do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), + spec->autocfg.hp_pins, spec->master_mute, true); + if (!spec->automute) on = 0; else @@ -6201,11 +6208,6 @@ static const struct snd_kcontrol_new alc260_input_mixer[] = { /* update HP, line and mono out pins according to the master switch */ static void alc260_hp_master_update(struct hda_codec *codec) { - struct alc_spec *spec = codec->spec; - - /* change HP pins */ - do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), - spec->autocfg.hp_pins, spec->master_mute, true); update_speakers(codec); } -- cgit v1.2.3 From 890ee02ac12c02c4712b6d7dd062ff4d6d37691c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Jun 2011 15:32:31 +0200 Subject: ALSA: Use %pV for snd_printk() Clean up snd_printk() helper using the %pV prefix for recursive printks. This also automagically fixes an Oops with RO/NX-enabled modules. Tested-by: Maarten Lankhorst Signed-off-by: Takashi Iwai --- sound/core/misc.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/sound/core/misc.c b/sound/core/misc.c index 2c41825c836e..eb9fe2e1d291 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -58,26 +58,6 @@ static const char *sanity_file_name(const char *path) else return path; } - -/* print file and line with a certain printk prefix */ -static int print_snd_pfx(unsigned int level, const char *path, int line, - const char *format) -{ - const char *file = sanity_file_name(path); - char tmp[] = "<0>"; - const char *pfx = level ? KERN_DEBUG : KERN_DEFAULT; - int ret = 0; - - if (format[0] == '<' && format[2] == '>') { - tmp[1] = format[1]; - pfx = tmp; - ret = 1; - } - printk("%sALSA %s:%d: ", pfx, file, line); - return ret; -} -#else -#define print_snd_pfx(level, path, line, format) 0 #endif #if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) @@ -85,15 +65,29 @@ void __snd_printk(unsigned int level, const char *path, int line, const char *format, ...) { va_list args; - +#ifdef CONFIG_SND_VERBOSE_PRINTK + struct va_format vaf; + char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV"; +#endif + #ifdef CONFIG_SND_DEBUG if (debug < level) return; #endif + va_start(args, format); - if (print_snd_pfx(level, path, line, format)) - format += 3; /* skip the printk level-prefix */ +#ifdef CONFIG_SND_VERBOSE_PRINTK + vaf.fmt = format; + vaf.va = &args; + if (format[0] == '<' && format[2] == '>') { + memcpy(verbose_fmt, format, 3); + vaf.fmt = format + 3; + } else if (level) + memcpy(verbose_fmt, KERN_DEBUG, 3); + printk(verbose_fmt, sanity_file_name(path), line, &vaf); +#else vprintk(format, args); +#endif va_end(args); } EXPORT_SYMBOL_GPL(__snd_printk); -- cgit v1.2.3 From 7ab1fc0af3464d231e17eb729a03495d93d0cc5c Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Fri, 10 Jun 2011 10:14:01 -0400 Subject: ALSA: hda: Fix inaudible internal speakers on CyberpowerPC Gamer Xplorer N57001 laptop BugLink: https://launchpad.net/bugs/761171 The original reporter needs the model=auto quirk for his internal speakers to be audible in the latest daily snapshot, so add an entry in the quirk table for his PCI SSID. A trivially different version of this patch using the model=asus quirk should be applied to the 2.6.38 and 2.6.39 stable kernels. We don't use the asus quirk in 3.0-rc2, because 3.0-rc2's autoparser is much improved. Reported-and-tested-by: tomdeering7 Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 3e6b9a8539c2..694b9daf691f 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3102,6 +3102,7 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ + SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), {} }; -- cgit v1.2.3 From e5ea3f12d41d96edf4ad9374db2b1725e457acec Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Fri, 10 Jun 2011 13:44:49 +0100 Subject: gpio/basic_mmio: add missing include of spinlock_types.h include/linux/basic_mmio_gpio.h uses a spinlock_t without including any of the spinlock headers resulting in this compiler warning. include/linux/basic_mmio_gpio.h:51:2: error: expected specifier-qualifier-list before 'spinlock_t' Explicitly include linux/spinlock_types.h to fix it. Signed-off-by: Jamie Iles Signed-off-by: Grant Likely --- include/linux/basic_mmio_gpio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h index 1ae12710d732..98999cf107ce 100644 --- a/include/linux/basic_mmio_gpio.h +++ b/include/linux/basic_mmio_gpio.h @@ -16,6 +16,7 @@ #include #include #include +#include struct bgpio_pdata { int base; -- cgit v1.2.3 From 0da67bed835fdde68ca0e924d2a2d6ac82c70833 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 12 May 2011 11:13:15 +0300 Subject: Bluetooth: fix shutdown on SCO sockets shutdown should wait for SCO link to be properly disconnected before detroying the socket, otherwise an application using the socket may assume link is properly disconnected before it really happens which can be a problem when e.g synchronizing profile switch. Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Gustavo F. Padovan --- net/bluetooth/sco.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 42fdffd1d76c..cb4fb7837e5c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -369,6 +369,15 @@ static void __sco_sock_close(struct sock *sk) case BT_CONNECTED: case BT_CONFIG: + if (sco_pi(sk)->conn) { + sk->sk_state = BT_DISCONN; + sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT); + hci_conn_put(sco_pi(sk)->conn->hcon); + sco_pi(sk)->conn->hcon = NULL; + } else + sco_chan_del(sk, ECONNRESET); + break; + case BT_CONNECT: case BT_DISCONN: sco_chan_del(sk, ECONNRESET); @@ -819,7 +828,9 @@ static void sco_chan_del(struct sock *sk, int err) conn->sk = NULL; sco_pi(sk)->conn = NULL; sco_conn_unlock(conn); - hci_conn_put(conn->hcon); + + if (conn->hcon) + hci_conn_put(conn->hcon); } sk->sk_state = BT_CLOSED; -- cgit v1.2.3 From 26e7acf315ba5fc5ac4e7cbdb422a345e59898bd Mon Sep 17 00:00:00 2001 From: David Miller Date: Thu, 19 May 2011 17:37:45 -0400 Subject: Bluetooth: Do not ignore errors returned from strict_strtol() Signed-off-by: David S. Miller Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btmrvl_debugfs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index fd6305bf953e..8ecf4c6c2874 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -64,6 +64,8 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.hscfgcmd = result; @@ -108,6 +110,8 @@ static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.psmode = result; @@ -147,6 +151,8 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.pscmd = result; @@ -191,6 +197,8 @@ static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 16, &result); + if (ret) + return ret; priv->btmrvl_dev.gpio_gap = result; @@ -230,6 +238,8 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.hscmd = result; if (priv->btmrvl_dev.hscmd) { @@ -272,6 +282,8 @@ static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.hsmode = result; -- cgit v1.2.3 From 7f4f0572df6c8eaa6a587bc212b0806ff37380dd Mon Sep 17 00:00:00 2001 From: Ville Tervo Date: Fri, 27 May 2011 11:16:21 +0300 Subject: Bluetooth: Do not send SET_EVENT_MASK for 1.1 and earlier devices Some old hci controllers do not accept any mask so leave the default mask on for these devices. < HCI Command: Set Event Mask (0x03|0x0001) plen 8 Mask: 0xfffffbff00000000 > HCI Event: Command Complete (0x0e) plen 4 Set Event Mask (0x03|0x0001) ncmd 1 status 0x12 Error: Invalid HCI Command Parameters Signed-off-by: Ville Tervo Tested-by: Corey Boyle Tested-by: Ed Tomlinson Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index f13ddbf858ba..77930aa522e3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -477,14 +477,16 @@ static void hci_setup_event_mask(struct hci_dev *hdev) * command otherwise */ u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; - /* Events for 1.2 and newer controllers */ - if (hdev->lmp_ver > 1) { - events[4] |= 0x01; /* Flow Specification Complete */ - events[4] |= 0x02; /* Inquiry Result with RSSI */ - events[4] |= 0x04; /* Read Remote Extended Features Complete */ - events[5] |= 0x08; /* Synchronous Connection Complete */ - events[5] |= 0x10; /* Synchronous Connection Changed */ - } + /* CSR 1.1 dongles does not accept any bitfield so don't try to set + * any event mask for pre 1.2 devices */ + if (hdev->lmp_ver <= 1) + return; + + events[4] |= 0x01; /* Flow Specification Complete */ + events[4] |= 0x02; /* Inquiry Result with RSSI */ + events[4] |= 0x04; /* Read Remote Extended Features Complete */ + events[5] |= 0x08; /* Synchronous Connection Complete */ + events[5] |= 0x10; /* Synchronous Connection Changed */ if (hdev->features[3] & LMP_RSSI_INQ) events[4] |= 0x04; /* Inquiry Result with RSSI */ -- cgit v1.2.3 From 38e87880666091fe9c572a7a2ed2e771d97ca5aa Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 10 Jun 2011 16:36:57 -0400 Subject: Btrfs: make sure to recheck for bitmaps in clusters Josef recently changed the free extent cache to look in the block group cluster for any bitmaps before trying to add a new bitmap for the same offset. This avoids BUG_ON()s due covering duplicate ranges. But it didn't go quite far enough. A given free range might span between one or more bitmaps or free space entries. The code has looping to cover this, but it doesn't check for clustered bitmaps every time. This shuffles our gotos to check for a bitmap in the cluster for every new bitmap entry we try to add. Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 38f3fd923043..9f985a429877 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1492,7 +1492,7 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, if (ctl->op == &free_space_op) block_group = ctl->private; - +again: /* * Since we link bitmaps right into the cluster we need to see if we * have a cluster here, and if so and it has our bitmap we need to add @@ -1510,13 +1510,13 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, node = rb_first(&cluster->root); if (!node) { spin_unlock(&cluster->lock); - goto again; + goto no_cluster_bitmap; } entry = rb_entry(node, struct btrfs_free_space, offset_index); if (!entry->bitmap) { spin_unlock(&cluster->lock); - goto again; + goto no_cluster_bitmap; } if (entry->offset == offset_to_bitmap(ctl, offset)) { @@ -1531,7 +1531,8 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, goto out; } } -again: + +no_cluster_bitmap: bitmap_info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 1, 0); if (!bitmap_info) { -- cgit v1.2.3 From 38e880540f983045da7a00fbc50daad238207fc5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 10 Jun 2011 18:43:13 +0000 Subject: Btrfs: clear current->journal_info on async transaction commit Normally current->jouranl_info is cleared by commit_transaction. For an async snap or subvol creation, though, it runs in a work queue. Clear it in btrfs_commit_transaction_async() to avoid leaking a non-NULL journal_info when we return to userspace. When the actual commit runs in the other thread it won't care that it's current->journal_info is already NULL. Signed-off-by: Sage Weil Tested-by: Jim Schutt Signed-off-by: Chris Mason --- fs/btrfs/transaction.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 6b2e4786d189..2b3590b9fe98 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1118,8 +1118,11 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, wait_current_trans_commit_start_and_unblock(root, cur_trans); else wait_current_trans_commit_start(root, cur_trans); - put_transaction(cur_trans); + if (current->journal_info == trans) + current->journal_info = NULL; + + put_transaction(cur_trans); return 0; } -- cgit v1.2.3 From 9eb9104c665aae2401a1723c044669eb10240072 Mon Sep 17 00:00:00 2001 From: richard kennedy Date: Tue, 7 Jun 2011 10:46:32 +0000 Subject: btrfs: remove 64bit alignment padding to allow extent_buffer to fit into one fewer cacheline Reorder extent_buffer to remove 8 bytes of alignment padding on 64 bit builds. This shrinks its size to 128 bytes allowing it to fit into one fewer cache lines and allows more objects per slab in its kmem_cache. slabinfo extent_buffer reports :- before:- Sizes (bytes) Slabs ---------------------------------- Object : 136 Total : 123 SlabObj: 136 Full : 121 SlabSiz: 4096 Partial: 0 Loss : 0 CpuSlab: 2 Align : 8 Objects: 30 after :- Object : 128 Total : 4 SlabObj: 128 Full : 2 SlabSiz: 4096 Partial: 0 Loss : 0 CpuSlab: 2 Align : 8 Objects: 32 Signed-off-by: Richard Kennedy Signed-off-by: Chris Mason --- fs/btrfs/extent_io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 4e8445a4757c..a11a92ee2d30 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -126,9 +126,9 @@ struct extent_buffer { unsigned long map_len; struct page *first_page; unsigned long bflags; - atomic_t refs; struct list_head leak_list; struct rcu_head rcu_head; + atomic_t refs; /* the spinlock is used to protect most operations */ spinlock_t lock; -- cgit v1.2.3 From 027ed2f0044e95a97ed34db2d55a9ca95ba84385 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 8 Jun 2011 08:27:56 +0000 Subject: Btrfs: avoid stack bloat in btrfs_ioctl_fs_info() The size of struct btrfs_ioctl_fs_info_args is as big as 1KB, so don't declare the variable on stack. Signed-off-by: Li Zefan Reviewed-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ac37040e426a..b793d112d1f6 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2054,29 +2054,34 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) static long btrfs_ioctl_fs_info(struct btrfs_root *root, void __user *arg) { - struct btrfs_ioctl_fs_info_args fi_args; + struct btrfs_ioctl_fs_info_args *fi_args; struct btrfs_device *device; struct btrfs_device *next; struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; + int ret = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - fi_args.num_devices = fs_devices->num_devices; - fi_args.max_id = 0; - memcpy(&fi_args.fsid, root->fs_info->fsid, sizeof(fi_args.fsid)); + fi_args = kzalloc(sizeof(*fi_args), GFP_KERNEL); + if (!fi_args) + return -ENOMEM; + + fi_args->num_devices = fs_devices->num_devices; + memcpy(&fi_args->fsid, root->fs_info->fsid, sizeof(fi_args->fsid)); mutex_lock(&fs_devices->device_list_mutex); list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) { - if (device->devid > fi_args.max_id) - fi_args.max_id = device->devid; + if (device->devid > fi_args->max_id) + fi_args->max_id = device->devid; } mutex_unlock(&fs_devices->device_list_mutex); - if (copy_to_user(arg, &fi_args, sizeof(fi_args))) - return -EFAULT; + if (copy_to_user(arg, fi_args, sizeof(*fi_args))) + ret = -EFAULT; - return 0; + kfree(fi_args); + return ret; } static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg) -- cgit v1.2.3 From 5be76758f35ec6578e5b9b150aa513ac26bd9c54 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Thu, 9 Jun 2011 10:02:51 +0000 Subject: btrfs: fix unlocked access of delalloc_inodes list_splice_init will make delalloc_inodes empty, but without a spinlock around, this may produce corrupted list head, accessed in many placess, The race window is very tight and nobody seems to have hit it so far. Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a203d363184d..33b744a5ac03 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2911,9 +2911,8 @@ static int btrfs_destroy_delalloc_inodes(struct btrfs_root *root) INIT_LIST_HEAD(&splice); - list_splice_init(&root->fs_info->delalloc_inodes, &splice); - spin_lock(&root->fs_info->delalloc_lock); + list_splice_init(&root->fs_info->delalloc_inodes, &splice); while (!list_empty(&splice)) { btrfs_inode = list_entry(splice.next, struct btrfs_inode, -- cgit v1.2.3 From 08d2f347e877e489ca098c87a6fd2e872fef9767 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Wed, 4 May 2011 16:18:50 +0200 Subject: Btrfs: fix extent state leak on failed nodatasum reads When encountering an EIO while reading from a nodatasum extent, we insert an error record into the inode's failure tree. btrfs_readpage_end_io_hook returns early for nodatasum inodes. We'd better clear the failure tree in that case, otherwise the kernel complains about BUG extent_state: Objects remaining on kmem_cache_close() on rmmod. Signed-off-by: Jan Schmidt Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 02ff4a1b968b..113913ae36e0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1986,7 +1986,7 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, } if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) - return 0; + goto good; if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && test_range_bit(io_tree, start, end, EXTENT_NODATASUM, 1, NULL)) { -- cgit v1.2.3 From 22b63a2971c5657dfc1bf4514f9410fc90c8b2c2 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Wed, 9 Feb 2011 16:05:31 +0200 Subject: Btrfs - use %pU to print fsid Get rid of FIXME comment. Uuids from dmesg are now the same as uuids given by btrfs-progs. Signed-off-by: Ilya Dryomov Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index da541dfca2e3..1efa56e18f9b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -689,12 +689,8 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, transid = btrfs_super_generation(disk_super); if (disk_super->label[0]) printk(KERN_INFO "device label %s ", disk_super->label); - else { - /* FIXME, make a readl uuid parser */ - printk(KERN_INFO "device fsid %llx-%llx ", - *(unsigned long long *)disk_super->fsid, - *(unsigned long long *)(disk_super->fsid + 8)); - } + else + printk(KERN_INFO "device fsid %pU ", disk_super->fsid); printk(KERN_CONT "devid %llu transid %llu %s\n", (unsigned long long)devid, (unsigned long long)transid, path); ret = device_list_add(path, disk_super, devid, fs_devices_ret); -- cgit v1.2.3 From 8f4b8c7613928d5c6da43715fedc00a7b1ee53be Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Jun 2011 00:43:21 +0100 Subject: ARM: initrd: disable initrds outside of memory We can't cope with initrds outside of memory, so check that the initrd is within some declared memory to the kernel before using it. Otherwise we're likely to OOPS during boot. Signed-off-by: Russell King --- arch/arm/mm/init.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index b2cf9460ea60..c19571c40a21 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -330,6 +330,12 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) memblock_reserve(__pa(_stext), _end - _stext); #endif #ifdef CONFIG_BLK_DEV_INITRD + if (phys_initrd_size && + !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) { + pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n", + phys_initrd_start, phys_initrd_size); + phys_initrd_start = phys_initrd_size = 0; + } if (phys_initrd_size && memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) { pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n", -- cgit v1.2.3 From e172dedd89a342b30fddfafd820d2ef40c039cea Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Jun 2011 00:44:35 +0100 Subject: ARM: footbridge: fix debug macros More of the same of 5f2c1b30 (ARM: footbridge: fix debug macros), this time for the DC21285-based debugging code rather than the 8250- based debugging code. Signed-off-by: Russell King --- arch/arm/mach-footbridge/include/mach/debug-macro.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S index 30b971d65815..1be2eeb7a0a0 100644 --- a/arch/arm/mach-footbridge/include/mach/debug-macro.S +++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S @@ -26,6 +26,7 @@ #include #else +#include /* For EBSA285 debugging */ .equ dc21285_high, ARMCSR_BASE & 0xff000000 .equ dc21285_low, ARMCSR_BASE & 0x00ffffff @@ -36,8 +37,8 @@ .else mov \rp, #0 .endif - orr \rv, \rp, #0x42000000 - orr \rp, \rp, #dc21285_high + orr \rv, \rp, #dc21285_high + orr \rp, \rp, #0x42000000 .endm .macro senduart,rd,rx -- cgit v1.2.3 From 7d7975a0e1da7d6e558211b6296a96f1d6bf60ce Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Jun 2011 00:46:17 +0100 Subject: ARM: footbridge: fix clock event support 4e8d7637 (ARM: footbridge: convert to clockevents/clocksource) did not set the cpumask for the clock event device. This causes boot to fail. Add the necessary initialization. Signed-off-by: Russell King --- arch/arm/mach-footbridge/dc21285-timer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 5f1f9867fc70..121ad1d4fa39 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -103,6 +103,7 @@ static void __init footbridge_timer_init(void) clockevents_calc_mult_shift(ce, mem_fclk_21285, 5); ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce); ce->min_delta_ns = clockevent_delta2ns(0x000004, ce); + ce->cpumask = cpumask_of(smp_processor_id()); clockevents_register_device(ce); } -- cgit v1.2.3 From fe744fdb74f2417d8571faefa45f72b0ead25f89 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 25 May 2011 23:00:27 +0900 Subject: nilfs2: fix incorrect block address termination in node concatenation nilfs_btree_delete function wrongly terminates virtual block address of the btree node held by its parent at index 0. When concatenating the index-0 node with its right sibling node, nilfs_btree_delete terminates the block address of index-0 node instead of the right sibling node which should be deleted. This bug not only wears disk space in the long run, but also causes file system corruption. This will fix it. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/btree.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 7eafe468a29c..fd4f05b91942 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -1356,20 +1356,19 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, struct buffer_head *bh; struct nilfs_btree_node *node, *parent, *sib; __u64 sibptr; - int pindex, level, ncmin, ncmax, ncblk, ret; + int pindex, dindex, level, ncmin, ncmax, ncblk, ret; ret = 0; stats->bs_nblocks = 0; ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); ncblk = nilfs_btree_nchildren_per_block(btree); - for (level = NILFS_BTREE_LEVEL_NODE_MIN; + for (level = NILFS_BTREE_LEVEL_NODE_MIN, dindex = path[level].bp_index; level < nilfs_btree_height(btree) - 1; level++) { node = nilfs_btree_get_nonroot_node(path, level); path[level].bp_oldreq.bpr_ptr = - nilfs_btree_node_get_ptr(node, path[level].bp_index, - ncblk); + nilfs_btree_node_get_ptr(node, dindex, ncblk); ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat); if (ret < 0) @@ -1383,6 +1382,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); pindex = path[level + 1].bp_index; + dindex = pindex; if (pindex > 0) { /* left sibling */ @@ -1421,6 +1421,14 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, path[level].bp_sib_bh = bh; path[level].bp_op = nilfs_btree_concat_right; stats->bs_nblocks++; + /* + * When merging right sibling node + * into the current node, pointer to + * the right sibling node must be + * terminated instead. The adjustment + * below is required for that. + */ + dindex = pindex + 1; /* continue; */ } } else { @@ -1443,7 +1451,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, node = nilfs_btree_get_root(btree); path[level].bp_oldreq.bpr_ptr = - nilfs_btree_node_get_ptr(node, path[level].bp_index, + nilfs_btree_node_get_ptr(node, dindex, NILFS_BTREE_ROOT_NCHILDREN_MAX); ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat); -- cgit v1.2.3 From d40990537c9ea85dfe75dbe0ffba5e1002dfdf3f Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 25 May 2011 23:00:27 +0900 Subject: nilfs2: fix missing block address termination in btree node shrinking nilfs_btree_delete function does not terminate part of virtual block addresses when shrinking the last remaining child node into the root node. The missing address termination causes that dead btree node blocks persist and chip away free disk space. This fixes the leak bug on the btree node deletion. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/btree.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index fd4f05b91942..b2e3ff347620 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -1346,6 +1346,11 @@ static void nilfs_btree_shrink(struct nilfs_bmap *btree, path[level].bp_bh = NULL; } +static void nilfs_btree_nop(struct nilfs_bmap *btree, + struct nilfs_btree_path *path, + int level, __u64 *keyp, __u64 *ptrp) +{ +} static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, struct nilfs_btree_path *path, @@ -1439,16 +1444,22 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, NILFS_BTREE_ROOT_NCHILDREN_MAX) { path[level].bp_op = nilfs_btree_shrink; stats->bs_nblocks += 2; + level++; + path[level].bp_op = nilfs_btree_nop; + goto shrink_root_child; } else { path[level].bp_op = nilfs_btree_do_delete; stats->bs_nblocks++; + goto out; } - - goto out; - } } + /* child of the root node is deleted */ + path[level].bp_op = nilfs_btree_do_delete; + stats->bs_nblocks++; + +shrink_root_child: node = nilfs_btree_get_root(btree); path[level].bp_oldreq.bpr_ptr = nilfs_btree_node_get_ptr(node, dindex, @@ -1458,10 +1469,6 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, if (ret < 0) goto err_out_child_node; - /* child of the root node is deleted */ - path[level].bp_op = nilfs_btree_do_delete; - stats->bs_nblocks++; - /* success */ out: *levelp = level; -- cgit v1.2.3 From 071d73cfe5c38cf62338b952bd350ff3de541b75 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 10 Jun 2011 00:33:06 +0900 Subject: nilfs2: fix problem in setting checkpoint interval Checkpoint generation interval of nilfs goes wrong after user has changed the interval parameter with nilfs-tune tool. segctord starting. Construction interval = 5 seconds, CP frequency < 30 seconds segctord starting. Construction interval = 0 seconds, CP frequency < 30 seconds This turned out to be caused by a trivial bug in initialization code of log writer. This will fix it. Reported-by: Andrea Gelmini Signed-off-by: Ryusuke Konishi --- fs/nilfs2/segment.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 141646e88fb5..bb24ab6c282f 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2573,7 +2573,7 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK; if (nilfs->ns_interval) - sci->sc_interval = nilfs->ns_interval; + sci->sc_interval = HZ * nilfs->ns_interval; if (nilfs->ns_watermark) sci->sc_watermark = nilfs->ns_watermark; return sci; -- cgit v1.2.3 From 5ae8f9a3757e4010c7ea9c07c047088fb812335e Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 26 May 2011 15:51:11 -0300 Subject: [media] mceusb: add and use mce_dbg printk macro Using dev_dbg is more complexity than many users are able to deal with. Make it easier to get debug spew feedback from them by adding an mce_dbg printk macro that spews using dev_info when debug=1 is set for the mceusb module. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index ad927fcaa020..10ec54b93d26 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -108,6 +108,12 @@ static int debug = 1; static int debug; #endif +#define mce_dbg(dev, fmt, ...) \ + do { \ + if (debug) \ + dev_info(dev, fmt, ## __VA_ARGS__); \ + } while (0) + /* general constants */ #define SEND_FLAG_IN_PROGRESS 1 #define SEND_FLAG_COMPLETE 2 @@ -606,7 +612,7 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs) if (ir) { len = urb->actual_length; - dev_dbg(ir->dev, "callback called (status=%d len=%d)\n", + mce_dbg(ir->dev, "callback called (status=%d len=%d)\n", urb->status, len); mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true); @@ -655,17 +661,17 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, return; } - dev_dbg(dev, "receive request called (size=%#x)\n", size); + mce_dbg(dev, "receive request called (size=%#x)\n", size); async_urb->transfer_buffer_length = size; async_urb->dev = ir->usbdev; res = usb_submit_urb(async_urb, GFP_ATOMIC); if (res) { - dev_dbg(dev, "receive request FAILED! (res=%d)\n", res); + mce_dbg(dev, "receive request FAILED! (res=%d)\n", res); return; } - dev_dbg(dev, "receive request complete (res=%d)\n", res); + mce_dbg(dev, "receive request complete (res=%d)\n", res); } static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) @@ -794,7 +800,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier) ir->carrier = carrier; cmdbuf[2] = MCE_CMD_SIG_END; cmdbuf[3] = MCE_IRDATA_TRAILER; - dev_dbg(ir->dev, "%s: disabling carrier " + mce_dbg(ir->dev, "%s: disabling carrier " "modulation\n", __func__); mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); return carrier; @@ -806,7 +812,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier) ir->carrier = carrier; cmdbuf[2] = prescaler; cmdbuf[3] = divisor; - dev_dbg(ir->dev, "%s: requesting %u HZ " + mce_dbg(ir->dev, "%s: requesting %u HZ " "carrier\n", __func__, carrier); /* Transmit new carrier to mce device */ @@ -879,7 +885,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) * US_TO_NS(MCE_TIME_UNIT); - dev_dbg(ir->dev, "Storing %s with duration %d\n", + mce_dbg(ir->dev, "Storing %s with duration %d\n", rawir.pulse ? "pulse" : "space", rawir.duration); @@ -911,7 +917,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) if (ir->parser_state != CMD_HEADER && !ir->rem) ir->parser_state = CMD_HEADER; } - dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); + mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); ir_raw_event_handle(ir->rc); } @@ -933,7 +939,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { ir->send_flags = SEND_FLAG_COMPLETE; - dev_dbg(ir->dev, "setup answer received %d bytes\n", + mce_dbg(ir->dev, "setup answer received %d bytes\n", buf_len); } @@ -951,7 +957,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) case -EPIPE: default: - dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status); + mce_dbg(ir->dev, "Error: urb status = %d\n", urb->status); break; } @@ -978,8 +984,8 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, data, USB_CTRL_MSG_SZ, HZ * 3); - dev_dbg(dev, "%s - ret = %d\n", __func__, ret); - dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n", + mce_dbg(dev, "%s - ret = %d\n", __func__, ret); + mce_dbg(dev, "%s - data[0] = %d, data[1] = %d\n", __func__, data[0], data[1]); /* set feature: bit rate 38400 bps */ @@ -987,19 +993,19 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, 0xc04e, 0x0000, NULL, 0, HZ * 3); - dev_dbg(dev, "%s - ret = %d\n", __func__, ret); + mce_dbg(dev, "%s - ret = %d\n", __func__, ret); /* bRequest 4: set char length to 8 bits */ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 4, USB_TYPE_VENDOR, 0x0808, 0x0000, NULL, 0, HZ * 3); - dev_dbg(dev, "%s - retB = %d\n", __func__, ret); + mce_dbg(dev, "%s - retB = %d\n", __func__, ret); /* bRequest 2: set handshaking to use DTR/DSR */ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 2, USB_TYPE_VENDOR, 0x0000, 0x0100, NULL, 0, HZ * 3); - dev_dbg(dev, "%s - retC = %d\n", __func__, ret); + mce_dbg(dev, "%s - retC = %d\n", __func__, ret); /* device reset */ mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); @@ -1122,7 +1128,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, bool tx_mask_normal; int ir_intfnum; - dev_dbg(&intf->dev, "%s called\n", __func__); + mce_dbg(&intf->dev, "%s called\n", __func__); idesc = intf->cur_altsetting; @@ -1150,7 +1156,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, ep_in = ep; ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; ep_in->bInterval = 1; - dev_dbg(&intf->dev, "acceptable inbound endpoint " + mce_dbg(&intf->dev, "acceptable inbound endpoint " "found\n"); } @@ -1165,12 +1171,12 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, ep_out = ep; ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; ep_out->bInterval = 1; - dev_dbg(&intf->dev, "acceptable outbound endpoint " + mce_dbg(&intf->dev, "acceptable outbound endpoint " "found\n"); } } if (ep_in == NULL) { - dev_dbg(&intf->dev, "inbound and/or endpoint not found\n"); + mce_dbg(&intf->dev, "inbound and/or endpoint not found\n"); return -ENODEV; } -- cgit v1.2.3 From b825fe1b1bb5927402c3d3084641355946ef05f8 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 26 May 2011 16:03:17 -0300 Subject: [media] mceusb: support I-O Data GV-MC7/RCKIT There's an SMK-device-id remote kit from I-O Data avaiable primarily in Japan, which appears to have no tx hardware, but has rx functionality that works with the mceusb driver by simply adding its device ID. Reported-by: Jeremy Kwok Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 10ec54b93d26..650b2f479519 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -252,6 +252,9 @@ static struct usb_device_id mceusb_dev_table[] = { .driver_info = MCE_GEN2_TX_INV }, /* SMK eHome Infrared Transceiver */ { USB_DEVICE(VENDOR_SMK, 0x0338) }, + /* SMK/I-O Data GV-MC7/RCKIT Receiver */ + { USB_DEVICE(VENDOR_SMK, 0x0353), + .driver_info = MCE_GEN2_NO_TX }, /* Tatung eHome Infrared Transceiver */ { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, /* Shuttle eHome Infrared Transceiver */ -- cgit v1.2.3 From 3a918aa69daf001910640cc910ea4053ba840a6e Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 26 May 2011 14:23:18 -0300 Subject: [media] mceusb: mce_sync_in is brain-dead Aside from the initial "hey, lets make sure we've flushed any pre-existing data on the device" call to mce_sync_in, every other one of the calls was entirely superfluous. Ergo, remove them all, and rename the one and only (questionably) useful one to reflect what it really does. Verified on both gen2 and gen3 hardware to make zero difference. Well, except that you no longer get a bunch of urb submit failures from the unneeded mce_sync_in calls. Oh. And move that flush to a point *after* we've wired up the inbound urb, or it won't do squat. I have half a mind to just remove it entirely, but someone thought it was necessary at some point, and it doesn't seem to hurt, so lets leave it for the time being. This excercise took place due to insightful questions asked by Hans Petter Selasky, about the possible reuse of the inbound urb before it was actually availble by mce_sync_in, so thanks to him for motivating this cleanup. Reported-by: Hans Petter Selasky Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 650b2f479519..6cf22012079a 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -682,9 +682,9 @@ static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) mce_request_packet(ir, data, size, MCEUSB_TX); } -static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) +static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size) { - mce_request_packet(ir, data, size, MCEUSB_RX); + mce_request_packet(ir, NULL, size, MCEUSB_RX); } /* Send data out the IR blaster port(s) */ @@ -970,7 +970,6 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) static void mceusb_gen1_init(struct mceusb_dev *ir) { int ret; - int maxp = ir->len_in; struct device *dev = ir->dev; char *data; @@ -1012,55 +1011,40 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) /* device reset */ mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); - mce_sync_in(ir, NULL, maxp); /* get hw/sw revision? */ mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); - mce_sync_in(ir, NULL, maxp); kfree(data); }; static void mceusb_gen2_init(struct mceusb_dev *ir) { - int maxp = ir->len_in; - /* device reset */ mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); - mce_sync_in(ir, NULL, maxp); /* get hw/sw revision? */ mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); - mce_sync_in(ir, NULL, maxp); /* unknown what the next two actually return... */ mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN)); - mce_sync_in(ir, NULL, maxp); mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); - mce_sync_in(ir, NULL, maxp); } static void mceusb_get_parameters(struct mceusb_dev *ir) { - int maxp = ir->len_in; - /* get the carrier and frequency */ mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); - mce_sync_in(ir, NULL, maxp); - if (!ir->flags.no_tx) { + if (!ir->flags.no_tx) /* get the transmitter bitmask */ mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); - mce_sync_in(ir, NULL, maxp); - } /* get receiver timeout value */ mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); - mce_sync_in(ir, NULL, maxp); /* get receiver sensor setting */ mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); - mce_sync_in(ir, NULL, maxp); } static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) @@ -1224,16 +1208,16 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, if (!ir->rc) goto rc_dev_fail; - /* flush buffers on the device */ - mce_sync_in(ir, NULL, maxp); - mce_sync_in(ir, NULL, maxp); - /* wire up inbound data handler */ usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval); ir->urb_in->transfer_dma = ir->dma_in; ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + /* flush buffers on the device */ + mce_dbg(&intf->dev, "Flushing receive buffers\n"); + mce_flush_rx_buffer(ir, maxp); + /* initialize device */ if (ir->flags.microsoft_gen1) mceusb_gen1_init(ir); -- cgit v1.2.3 From e5fd0f7db3c3ba127dc1c51f0a0fe31d89db27cc Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 27 May 2011 15:37:23 -0300 Subject: [media] [staging] lirc_imon: fix unused-but-set warnings Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/lirc/lirc_imon.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c index 4039eda2a15b..4a9e563f40fa 100644 --- a/drivers/staging/lirc/lirc_imon.c +++ b/drivers/staging/lirc/lirc_imon.c @@ -672,8 +672,6 @@ static void imon_incoming_packet(struct imon_context *context, static void usb_rx_callback(struct urb *urb) { struct imon_context *context; - unsigned char *buf; - int len; int intfnum = 0; if (!urb) @@ -683,9 +681,6 @@ static void usb_rx_callback(struct urb *urb) if (!context) return; - buf = urb->transfer_buffer; - len = urb->actual_length; - switch (urb->status) { case -ENOENT: /* usbcore unlink successful! */ return; @@ -728,7 +723,6 @@ static int imon_probe(struct usb_interface *interface, int ir_ep_found = 0; int alloc_status = 0; int vfd_proto_6p = 0; - int code_length; struct imon_context *context = NULL; int i; u16 vendor, product; @@ -749,8 +743,6 @@ static int imon_probe(struct usb_interface *interface, else context->display = 1; - code_length = BUF_CHUNK_SIZE * 8; - usbdev = usb_get_dev(interface_to_usbdev(interface)); iface_desc = interface->cur_altsetting; num_endpts = iface_desc->desc.bNumEndpoints; @@ -856,7 +848,7 @@ static int imon_probe(struct usb_interface *interface, strcpy(driver->name, MOD_NAME); driver->minor = -1; - driver->code_length = sizeof(int) * 8; + driver->code_length = BUF_CHUNK_SIZE * 8; driver->sample_rate = 0; driver->features = LIRC_CAN_REC_MODE2; driver->data = context; -- cgit v1.2.3 From 04f561ff8714c89733dcf1d178b64d100d5a084a Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 27 May 2011 15:46:19 -0300 Subject: [media] [staging] lirc_sir: fix unused-but-set warnings Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/lirc/lirc_sir.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c index a7b46f24f24e..0d3864594b12 100644 --- a/drivers/staging/lirc/lirc_sir.c +++ b/drivers/staging/lirc/lirc_sir.c @@ -739,23 +739,16 @@ static void send_space(unsigned long len) static void send_pulse(unsigned long len) { long bytes_out = len / TIME_CONST; - long time_left; - time_left = (long)len - (long)bytes_out * (long)TIME_CONST; - if (bytes_out == 0) { + if (bytes_out == 0) bytes_out++; - time_left = 0; - } + while (bytes_out--) { outb(PULSE, io + UART_TX); /* FIXME treba seriozne cakanie z char/serial.c */ while (!(inb(io + UART_LSR) & UART_LSR_THRE)) ; } -#if 0 - if (time_left > 0) - safe_udelay(time_left); -#endif } #endif -- cgit v1.2.3 From 8de111e27688798623b9e9062235bb0cac29f599 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 27 May 2011 16:56:50 -0300 Subject: [media] lirc_dev: store cdev in irctl, up maxdevs Store the cdev pointer in struct irctl, allocated dynamically as needed, rather than having a static array. At the same time, recycle some of the saved memory to nudge the maximum number of lirc devices supported up a ways -- its not that uncommon these days, now that we have the rc-core lirc bridge driver, to see a system with at least 4 raw IR receivers. (consider a mythtv backend with several video capture devices and the possible need for IR transmit hardware). Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 37 +++++++++++++++++++++++++++---------- include/media/lirc_dev.h | 2 +- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index fd237ab120bb..27997a9ceb0d 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -55,6 +55,8 @@ struct irctl { struct lirc_buffer *buf; unsigned int chunk_size; + struct cdev *cdev; + struct task_struct *task; long jiffies_to_wait; }; @@ -62,7 +64,6 @@ struct irctl { static DEFINE_MUTEX(lirc_dev_lock); static struct irctl *irctls[MAX_IRCTL_DEVICES]; -static struct cdev cdevs[MAX_IRCTL_DEVICES]; /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; @@ -167,9 +168,13 @@ static struct file_operations lirc_dev_fops = { static int lirc_cdev_add(struct irctl *ir) { - int retval; + int retval = -ENOMEM; struct lirc_driver *d = &ir->d; - struct cdev *cdev = &cdevs[d->minor]; + struct cdev *cdev; + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) + goto err_out; if (d->fops) { cdev_init(cdev, d->fops); @@ -180,12 +185,20 @@ static int lirc_cdev_add(struct irctl *ir) } retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor); if (retval) - return retval; + goto err_out; retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); - if (retval) + if (retval) { kobject_put(&cdev->kobj); + goto err_out; + } + + ir->cdev = cdev; + + return 0; +err_out: + kfree(cdev); return retval; } @@ -214,7 +227,7 @@ int lirc_register_driver(struct lirc_driver *d) if (MAX_IRCTL_DEVICES <= d->minor) { dev_err(d->dev, "lirc_dev: lirc_register_driver: " "\"minor\" must be between 0 and %d (%d)!\n", - MAX_IRCTL_DEVICES-1, d->minor); + MAX_IRCTL_DEVICES - 1, d->minor); err = -EBADRQC; goto out; } @@ -369,7 +382,7 @@ int lirc_unregister_driver(int minor) if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " - "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); + "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES - 1); return -EBADRQC; } @@ -380,7 +393,7 @@ int lirc_unregister_driver(int minor) return -ENOENT; } - cdev = &cdevs[minor]; + cdev = ir->cdev; mutex_lock(&lirc_dev_lock); @@ -410,6 +423,7 @@ int lirc_unregister_driver(int minor) } else { lirc_irctl_cleanup(ir); cdev_del(cdev); + kfree(cdev); kfree(ir); irctls[minor] = NULL; } @@ -453,7 +467,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) goto error; } - cdev = &cdevs[iminor(inode)]; + cdev = ir->cdev; if (try_module_get(cdev->owner)) { ir->open++; retval = ir->d.set_use_inc(ir->d.data); @@ -484,13 +498,15 @@ EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { struct irctl *ir = irctls[iminor(inode)]; - struct cdev *cdev = &cdevs[iminor(inode)]; + struct cdev *cdev; if (!ir) { printk(KERN_ERR "%s: called with invalid irctl\n", __func__); return -EINVAL; } + cdev = ir->cdev; + dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); WARN_ON(mutex_lock_killable(&lirc_dev_lock)); @@ -503,6 +519,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file) lirc_irctl_cleanup(ir); cdev_del(cdev); irctls[ir->d.minor] = NULL; + kfree(cdev); kfree(ir); } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 630e702c9511..168dd0b1bae2 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -9,7 +9,7 @@ #ifndef _LINUX_LIRC_DEV_H #define _LINUX_LIRC_DEV_H -#define MAX_IRCTL_DEVICES 4 +#define MAX_IRCTL_DEVICES 8 #define BUFLEN 16 #define mod(n, div) ((n) % (div)) -- cgit v1.2.3 From 0ae90252d0b28265bc16cf272e72d62281f7baf1 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 27 May 2011 17:14:51 -0300 Subject: [media] fintek-cir: make suspend with active IR more reliable There was a missing lock in fintek_suspend. Without the lock, its possible the system will be in the middle of receiving IR (draining the RX buffer) when we try to disable CIR interrupts. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/fintek-cir.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index 8fa539dde1b4..7f7079b12f23 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c @@ -597,12 +597,17 @@ static void __devexit fintek_remove(struct pnp_dev *pdev) static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state) { struct fintek_dev *fintek = pnp_get_drvdata(pdev); + unsigned long flags; fit_dbg("%s called", __func__); + spin_lock_irqsave(&fintek->fintek_lock, flags); + /* disable all CIR interrupts */ fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); + spin_unlock_irqrestore(&fintek->fintek_lock, flags); + fintek_config_mode_enable(fintek); /* disable cir logical dev */ -- cgit v1.2.3 From 589e116062d8b5fd1809dfff4c9b7694ce6c2318 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 24 May 2011 14:19:23 -0300 Subject: [media] nuvoton-cir: in_use isn't actually in use, remove it Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 2 -- drivers/media/rc/nuvoton-cir.h | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index bf3060ea6107..565f24c20d77 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -991,7 +991,6 @@ static int nvt_open(struct rc_dev *dev) unsigned long flags; spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->in_use = true; nvt_enable_cir(nvt); spin_unlock_irqrestore(&nvt->nvt_lock, flags); @@ -1004,7 +1003,6 @@ static void nvt_close(struct rc_dev *dev) unsigned long flags; spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->in_use = false; nvt_disable_cir(nvt); spin_unlock_irqrestore(&nvt->nvt_lock, flags); } diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 379795d61ea7..1241fc89a36c 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -70,7 +70,6 @@ struct nvt_dev { struct ir_raw_event rawir; spinlock_t nvt_lock; - bool in_use; /* for rx */ u8 buf[RX_BUF_LEN]; -- cgit v1.2.3 From 0b43fcdff6495958c39e3575848edef4b685ddef Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 24 May 2011 16:44:54 -0300 Subject: [media] mceusb: plug memory leak on data transmit Hans Petter Selasky pointed out to me that we're leaking urbs when mce_async_out is called. Its used both for configuring the hardware and for transmitting IR data. In the tx case, mce_request_packet actually allocates both a urb and the transfer buffer, neither of which was being torn down. Do that in the tx callback. CC: Hans Petter Selasky Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 6cf22012079a..06dfe0957b5e 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -621,6 +621,9 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs) mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true); } + /* the transfer buffer and urb were allocated in mce_request_packet */ + kfree(urb->transfer_buffer); + usb_free_urb(urb); } /* request incoming or send outgoing usb packet - used to initialize remote */ -- cgit v1.2.3 From 443b391900469f2c5ec5a354ce305000096a94b7 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Sat, 4 Jun 2011 14:00:54 -0300 Subject: [media] imon: support for 0x46 0xffdc imon vfd Courtesy of information from Andreas Dick on the lirc list. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/imon.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 3f3c70716268..43344fd67130 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -307,6 +307,14 @@ static const struct { /* 0xffdc iMON MCE VFD */ { 0x00010000ffffffeell, KEY_VOLUMEUP }, { 0x01000000ffffffeell, KEY_VOLUMEDOWN }, + { 0x00000001ffffffeell, KEY_MUTE }, + { 0x0000000fffffffeell, KEY_MEDIA }, + { 0x00000012ffffffeell, KEY_UP }, + { 0x00000013ffffffeell, KEY_DOWN }, + { 0x00000014ffffffeell, KEY_LEFT }, + { 0x00000015ffffffeell, KEY_RIGHT }, + { 0x00000016ffffffeell, KEY_ENTER }, + { 0x00000017ffffffeell, KEY_ESC }, /* iMON Knob values */ { 0x000100ffffffffeell, KEY_VOLUMEUP }, { 0x010000ffffffffeell, KEY_VOLUMEDOWN }, @@ -1740,6 +1748,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx) detected_display_type = IMON_DISPLAY_TYPE_VFD; break; /* iMON VFD, MCE IR */ + case 0x46: case 0x9e: dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR"); detected_display_type = IMON_DISPLAY_TYPE_VFD; -- cgit v1.2.3 From 94215ccd99eb6e3c8a035c06984630bd7479d963 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Sat, 4 Jun 2011 14:14:41 -0300 Subject: [media] imon: fix initial panel key repeat suppression As pointed out on the lirc list by Andreas Dick, initial panel key repeat suppression wasn't working, as we had no timevals accumulated until after the first repeat. Also add a missing locking call. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/imon.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 43344fd67130..7136582a8573 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1590,16 +1590,16 @@ static void imon_incoming_packet(struct imon_context *ictx, /* Only panel type events left to process now */ spin_lock_irqsave(&ictx->kc_lock, flags); + do_gettimeofday(&t); /* KEY_MUTE repeats from knob need to be suppressed */ if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) { - do_gettimeofday(&t); msec = tv2int(&t, &prev_time); - prev_time = t; if (msec < ictx->idev->rep[REP_DELAY]) { spin_unlock_irqrestore(&ictx->kc_lock, flags); return; } } + prev_time = t; kc = ictx->kc; spin_unlock_irqrestore(&ictx->kc_lock, flags); @@ -1611,7 +1611,9 @@ static void imon_incoming_packet(struct imon_context *ictx, input_report_key(ictx->idev, kc, 0); input_sync(ictx->idev); + spin_lock_irqsave(&ictx->kc_lock, flags); ictx->last_keycode = kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); return; -- cgit v1.2.3 From 30b4caf5d73af5c99cf1b2b46496d8bc35330992 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 8 Jun 2011 03:56:44 +0000 Subject: Btrfs: use join_transaction in btrfs_evict_inode() The WARN_ON() in start_transaction() was triggered while balancing. The cause is btrfs_relocate_chunk() started a transaction and then called iput() on the inode that stores free space cache, and iput() called btrfs_start_transaction() again. Reported-by: Tsutomu Itoh Signed-off-by: Li Zefan Reviewed-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 113913ae36e0..c15636b17874 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3646,7 +3646,7 @@ void btrfs_evict_inode(struct inode *inode) btrfs_i_size_write(inode, 0); while (1) { - trans = btrfs_start_transaction(root, 0); + trans = btrfs_join_transaction(root); BUG_ON(IS_ERR(trans)); trans->block_rsv = root->orphan_block_rsv; -- cgit v1.2.3 From cfd77310a93aac6de7077335b2b73c19531043e4 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 2 Jun 2011 06:18:34 -0300 Subject: [media] s5p-fimc: Fix possible memory leak during capture devnode registration Add missing kfree on the error path. Reported-by: Tomasz Stanislawski Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index d142b40ea64e..7e66455be0da 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -903,6 +903,7 @@ err_vd_reg: err_v4l2_reg: v4l2_device_unregister(v4l2_dev); err_info: + kfree(ctx); dev_err(&fimc->pdev->dev, "failed to install\n"); return ret; } -- cgit v1.2.3 From 6ba8d13b0cff80ea6da18563fc2aa2cde2771be4 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 18 May 2011 14:14:56 -0300 Subject: [media] s5p-fimc: Fix V4L2_PIX_FMT_RGB565X description Remove V4L2_MBUS_FMT_RGB565_2X8_BE media code entry as camera interface supports only packed YUYV formats. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index dc91a8511af6..f1c7119c0977 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -42,7 +42,6 @@ static struct fimc_fmt fimc_formats[] = { .color = S5P_FIMC_RGB565, .memplanes = 1, .colplanes = 1, - .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_BE, .flags = FMT_FLAGS_M2M, }, { .name = "BGR666", -- cgit v1.2.3 From 3495dcefeb3b5ab825788206d5b696be14f4de19 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 20 May 2011 06:14:59 -0300 Subject: [media] s5p-fimc: Fix data structures documentation and cleanup debug trace Correct inconsistencies in data structures' documentation. Remove meaningless debug traces. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 9 --------- drivers/media/video/s5p-fimc/fimc-core.c | 6 ------ drivers/media/video/s5p-fimc/fimc-core.h | 25 ++++++++++++------------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 7e66455be0da..44fc26f5b05a 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -262,12 +262,7 @@ static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane) { if (!fr || plane >= fr->fmt->memplanes) return 0; - - dbg("%s: w: %d. h: %d. depth[%d]: %d", - __func__, fr->width, fr->height, plane, fr->fmt->depth[plane]); - return fr->f_width * fr->f_height * fr->fmt->depth[plane] / 8; - } static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, @@ -283,12 +278,8 @@ static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, *num_planes = fmt->memplanes; - dbg("%s, buffer count=%d, plane count=%d", - __func__, *num_buffers, *num_planes); - for (i = 0; i < fmt->memplanes; i++) { sizes[i] = get_plane_size(&ctx->d_frame, i); - dbg("plane: %u, plane_size: %lu", i, sizes[i]); allocators[i] = ctx->fimc_dev->alloc_ctx; } diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index f1c7119c0977..c427edd3cd5e 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -231,11 +231,7 @@ static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift) return 0; } } - *shift = 0, *ratio = 1; - - dbg("s: %d, t: %d, shift: %d, ratio: %d", - src, tar, *shift, *ratio); return 0; } @@ -267,10 +263,8 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx) err("invalid source size: %d x %d", sx, sy); return -EINVAL; } - sc->real_width = sx; sc->real_height = sy; - dbg("sx= %d, sy= %d, tx= %d, ty= %d", sx, sy, tx, ty); ret = fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor); if (ret) diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 3beb1e5320ce..8f0f168a9ac3 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -135,9 +135,10 @@ enum fimc_color_fmt { * @name: format description * @fourcc: the fourcc code for this format, 0 if not applicable * @color: the corresponding fimc_color_fmt - * @depth: per plane driver's private 'number of bits per pixel' * @memplanes: number of physically non-contiguous data planes * @colplanes: number of physically contiguous data planes + * @depth: per plane driver's private 'number of bits per pixel' + * @flags: flags indicating which operation mode format applies to */ struct fimc_fmt { enum v4l2_mbus_pixelcode mbus_code; @@ -171,7 +172,7 @@ struct fimc_dma_offset { }; /** - * struct fimc_effect - the configuration data for the "Arbitrary" image effect + * struct fimc_effect - color effect information * @type: effect type * @pat_cb: cr value when type is "arbitrary" * @pat_cr: cr value when type is "arbitrary" @@ -184,7 +185,6 @@ struct fimc_effect { /** * struct fimc_scaler - the configuration data for FIMC inetrnal scaler - * * @scaleup_h: flag indicating scaling up horizontally * @scaleup_v: flag indicating scaling up vertically * @copy_mode: flag indicating transparent DMA transfer (no scaling @@ -220,7 +220,6 @@ struct fimc_scaler { /** * struct fimc_addr - the FIMC physical address set for DMA - * * @y: luminance plane physical address * @cb: Cb plane physical address * @cr: Cr plane physical address @@ -234,6 +233,7 @@ struct fimc_addr { /** * struct fimc_vid_buffer - the driver's video buffer * @vb: v4l videobuf buffer + * @list: linked list structure for buffer queue * @paddr: precalculated physical address set * @index: buffer index for the output DMA engine */ @@ -254,11 +254,10 @@ struct fimc_vid_buffer { * @offs_v: image vertical pixel offset * @width: image pixel width * @height: image pixel weight - * @paddr: image frame buffer physical addresses - * @buf_cnt: number of buffers depending on a color format * @payload: image size in bytes (w x h x bpp) - * @color: color format + * @paddr: image frame buffer physical addresses * @dma_offset: DMA offset in bytes + * @fmt: fimc color format pointer */ struct fimc_frame { u32 f_width; @@ -390,21 +389,22 @@ struct fimc_ctx; /** * struct fimc_dev - abstraction for FIMC entity - * * @slock: the spinlock protecting this data structure * @lock: the mutex protecting this data structure * @pdev: pointer to the FIMC platform device * @pdata: pointer to the device platform data + * @variant: the IP variant information * @id: FIMC device index (0..FIMC_MAX_DEVS) * @num_clocks: the number of clocks managed by this device instance - * @clock[]: the clocks required for FIMC operation + * @clock: clocks required for FIMC operation * @regs: the mapped hardware registers * @regs_res: the resource claimed for IO registers - * @irq: interrupt number of the FIMC subdevice - * @irq_queue: + * @irq: FIMC interrupt number + * @irq_queue: interrupt handler waitqueue * @m2m: memory-to-memory V4L2 device information * @vid_cap: camera capture device information * @state: flags used to synchronize m2m and capture mode operation + * @alloc_ctx: videobuf2 memory allocator context */ struct fimc_dev { spinlock_t slock; @@ -427,8 +427,7 @@ struct fimc_dev { /** * fimc_ctx - the device context data - * - * @lock: mutex protecting this data structure + * @slock: spinlock protecting this data structure * @s_frame: source frame properties * @d_frame: destination frame properties * @out_order_1p: output 1-plane YCBCR order -- cgit v1.2.3 From a629f86b4aa1669ddf2afaa3ded66d5a59d60b77 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 23 May 2011 09:15:05 -0300 Subject: [media] s5p-fimc: Fix wrong buffer size in queue_setup Avoid dereferencing of NULL f->fmt. Correct size of the allocated buffer in case the crop rectangle is smaller than the bounds rectangle (configured with S_FMT). Also remove redundant check for *num_buffer == 0 as this case is handled in videobuf2. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-core.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index c427edd3cd5e..85b47a328a5d 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -704,22 +704,18 @@ static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, f = ctx_get_frame(ctx, vq->type); if (IS_ERR(f)) return PTR_ERR(f); - /* * Return number of non-contigous planes (plane buffers) * depending on the configured color format. */ - if (f->fmt) - *num_planes = f->fmt->memplanes; + if (!f->fmt) + return -EINVAL; + *num_planes = f->fmt->memplanes; for (i = 0; i < f->fmt->memplanes; i++) { - sizes[i] = (f->width * f->height * f->fmt->depth[i]) >> 3; + sizes[i] = (f->f_width * f->f_height * f->fmt->depth[i]) / 8; allocators[i] = ctx->fimc_dev->alloc_ctx; } - - if (*num_buffers == 0) - *num_buffers = 1; - return 0; } -- cgit v1.2.3 From dbdd0dfb89ca45895f2063db8b31085cf32aa81d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 23 May 2011 09:15:17 -0300 Subject: [media] s5p-fimc: Remove empty buf_init operation The buf_init buffer queue operation is optional and buffer_init() does nothing, remove it. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 44fc26f5b05a..69016436fffc 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -286,12 +286,6 @@ static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, return 0; } -static int buffer_init(struct vb2_buffer *vb) -{ - /* TODO: */ - return 0; -} - static int buffer_prepare(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; @@ -371,7 +365,6 @@ static struct vb2_ops fimc_capture_qops = { .queue_setup = queue_setup, .buf_prepare = buffer_prepare, .buf_queue = buffer_queue, - .buf_init = buffer_init, .wait_prepare = fimc_unlock, .wait_finish = fimc_lock, .start_streaming = start_streaming, -- cgit v1.2.3 From ba0545e328390b9e5589c14876b3940fbe647d0c Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 20 May 2011 14:02:11 -0300 Subject: [media] s5p-fimc: Use pix_mp for the color format lookup With multi-planar formats fmt.pix_mp member of struct v4l2_format should be used rather than fmt.pix. Fix find_fmt() function to do the right thing. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 85b47a328a5d..873a879dc770 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -841,7 +841,7 @@ struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask) for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) { fmt = &fimc_formats[i]; - if (fmt->fourcc == f->fmt.pix.pixelformat && + if (fmt->fourcc == f->fmt.pix_mp.pixelformat && (fmt->flags & mask)) break; } -- cgit v1.2.3 From 3a3f94497aa236d9a4f47f0f4f8dc84e531ffa22 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 28 Apr 2011 09:06:19 -0300 Subject: [media] s5p-fimc: Update copyright notices Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 4 ++-- drivers/media/video/s5p-fimc/fimc-core.c | 7 +++---- drivers/media/video/s5p-fimc/fimc-core.h | 4 +--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 69016436fffc..81b4a826ee5e 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -1,7 +1,7 @@ /* - * Samsung S5P SoC series camera interface (camera capture) driver + * Samsung S5P/EXYNOS4 SoC series camera interface (camera capture) driver * - * Copyright (c) 2010 Samsung Electronics Co., Ltd + * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd. * Author: Sylwester Nawrocki, * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 873a879dc770..bdf19ada9172 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -1,9 +1,8 @@ /* - * S5P camera interface (video postprocessor) driver + * Samsung S5P/EXYNOS4 SoC series camera interface (video postprocessor) driver * - * Copyright (c) 2010 Samsung Electronics Co., Ltd - * - * Sylwester Nawrocki, + * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd. + * Contact: Sylwester Nawrocki, * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 8f0f168a9ac3..1f70772daaf0 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -1,7 +1,5 @@ /* - * Copyright (c) 2010 Samsung Electronics - * - * Sylwester Nawrocki, + * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as -- cgit v1.2.3 From bbe66edc607425acc47d7ad69ba7ad7193ec05b4 Mon Sep 17 00:00:00 2001 From: "HeungJun, Kim" Date: Tue, 31 May 2011 02:27:53 -0300 Subject: [media] m5mols: Fix capture image size register definition The main capture and the thumbnail image size registers were erroneously defined to have 1 byte width, resulting in wrong reported image size. Fix this by changing the registers width to correct value. Reported-by: Sylwester Nawrocki Signed-off-by: HeungJun, Kim Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/m5mols/m5mols_reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h index b83e36fc6ac6..8260f5030c7e 100644 --- a/drivers/media/video/m5mols/m5mols_reg.h +++ b/drivers/media/video/m5mols/m5mols_reg.h @@ -382,8 +382,8 @@ #define REG_CAP_START_MAIN 0x01 #define REG_CAP_START_THUMB 0x03 -#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 1) -#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 1) +#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 4) +#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 4) /* * Category F - Flash -- cgit v1.2.3 From 57644f56234a154afffd0f4d53becf8ff4a55b41 Mon Sep 17 00:00:00 2001 From: "HeungJun, Kim" Date: Tue, 31 May 2011 03:44:19 -0300 Subject: [media] m5mols: add m5mols_read_u8/u16/u32() according to I2C byte width For now, the m5mols_read() share in case of I2C packet 1, 2, 4 byte(s) width. So, this commit adds 3 functions - m5mols_read_u8/u16/u32() according to byte width of I2C packet. And, the u32 variables in spite of u8 or u16 for fitting to m5mols_read() having no choice, is replaced to have original byte width like u8, u16, u32 as same reason. Signed-off-by: HeungJun, Kim Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/m5mols/m5mols.h | 52 +++++++-------- drivers/media/video/m5mols/m5mols_capture.c | 18 +++--- drivers/media/video/m5mols/m5mols_controls.c | 2 +- drivers/media/video/m5mols/m5mols_core.c | 96 +++++++++++++++++++--------- 4 files changed, 104 insertions(+), 64 deletions(-) diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h index 10b55c854487..dbe8928855de 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/video/m5mols/m5mols.h @@ -106,23 +106,23 @@ struct m5mols_capture { * The each value according to each scenemode is recommended in the documents. */ struct m5mols_scenemode { - u32 metering; - u32 ev_bias; - u32 wb_mode; - u32 wb_preset; - u32 chroma_en; - u32 chroma_lvl; - u32 edge_en; - u32 edge_lvl; - u32 af_range; - u32 fd_mode; - u32 mcc; - u32 light; - u32 flash; - u32 tone; - u32 iso; - u32 capt_mode; - u32 wdr; + u8 metering; + u8 ev_bias; + u8 wb_mode; + u8 wb_preset; + u8 chroma_en; + u8 chroma_lvl; + u8 edge_en; + u8 edge_lvl; + u8 af_range; + u8 fd_mode; + u8 mcc; + u8 light; + u8 flash; + u8 tone; + u8 iso; + u8 capt_mode; + u8 wdr; }; /** @@ -216,9 +216,9 @@ struct m5mols_info { bool lock_ae; bool lock_awb; u8 resolution; - u32 interrupt; - u32 mode; - u32 mode_save; + u8 interrupt; + u8 mode; + u8 mode_save; int (*set_power)(struct device *dev, int on); }; @@ -256,9 +256,11 @@ struct m5mols_info { * +-------+---+----------+-----+------+------+------+------+ * - d[0..3]: according to size1 */ -int m5mols_read(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); +int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val); +int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); +int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); -int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value); +int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value); /* * Mode operation of the M-5MOLS @@ -280,12 +282,12 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value); * The available executing order between each modes are as follows: * PARAMETER <---> MONITOR <---> CAPTURE */ -int m5mols_mode(struct m5mols_info *info, u32 mode); +int m5mols_mode(struct m5mols_info *info, u8 mode); -int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg); +int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg); int m5mols_sync_controls(struct m5mols_info *info); int m5mols_start_capture(struct m5mols_info *info); -int m5mols_do_scenemode(struct m5mols_info *info, u32 mode); +int m5mols_do_scenemode(struct m5mols_info *info, u8 mode); int m5mols_lock_3a(struct m5mols_info *info, bool lock); int m5mols_set_ctrl(struct v4l2_ctrl *ctrl); diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c index d71a3903b60f..751f4593da9b 100644 --- a/drivers/media/video/m5mols/m5mols_capture.c +++ b/drivers/media/video/m5mols/m5mols_capture.c @@ -58,9 +58,9 @@ static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num, { u32 num, den; - int ret = m5mols_read(sd, addr_num, &num); + int ret = m5mols_read_u32(sd, addr_num, &num); if (!ret) - ret = m5mols_read(sd, addr_den, &den); + ret = m5mols_read_u32(sd, addr_den, &den); if (ret) return ret; *val = den == 0 ? 0 : num / den; @@ -99,20 +99,20 @@ static int m5mols_capture_info(struct m5mols_info *info) if (ret) return ret; - ret = m5mols_read(sd, EXIF_INFO_ISO, (u32 *)&exif->iso_speed); + ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed); if (!ret) - ret = m5mols_read(sd, EXIF_INFO_FLASH, (u32 *)&exif->flash); + ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash); if (!ret) - ret = m5mols_read(sd, EXIF_INFO_SDR, (u32 *)&exif->sdr); + ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr); if (!ret) - ret = m5mols_read(sd, EXIF_INFO_QVAL, (u32 *)&exif->qval); + ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval); if (ret) return ret; if (!ret) - ret = m5mols_read(sd, CAPC_IMAGE_SIZE, &info->cap.main); + ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main); if (!ret) - ret = m5mols_read(sd, CAPC_THUMB_SIZE, &info->cap.thumb); + ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb); if (!ret) info->cap.total = info->cap.main + info->cap.thumb; @@ -122,7 +122,7 @@ static int m5mols_capture_info(struct m5mols_info *info) int m5mols_start_capture(struct m5mols_info *info) { struct v4l2_subdev *sd = &info->sd; - u32 resolution = info->resolution; + u8 resolution = info->resolution; int timeout; int ret; diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/video/m5mols/m5mols_controls.c index 817c16fec368..d392c83fbf05 100644 --- a/drivers/media/video/m5mols/m5mols_controls.c +++ b/drivers/media/video/m5mols/m5mols_controls.c @@ -130,7 +130,7 @@ static struct m5mols_scenemode m5mols_default_scenemode[] = { * * WARNING: The execution order is important. Do not change the order. */ -int m5mols_do_scenemode(struct m5mols_info *info, u32 mode) +int m5mols_do_scenemode(struct m5mols_info *info, u8 mode) { struct v4l2_subdev *sd = &info->sd; struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode]; diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index 76eac26e84ae..2b1f23f8d063 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c @@ -133,13 +133,13 @@ static u32 m5mols_swap_byte(u8 *data, u8 length) /** * m5mols_read - I2C read function * @reg: combination of size, category and command for the I2C packet + * @size: desired size of I2C packet * @val: read value */ -int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val) +static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val) { struct i2c_client *client = v4l2_get_subdevdata(sd); u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1]; - u8 size = I2C_SIZE(reg); u8 category = I2C_CATEGORY(reg); u8 cmd = I2C_COMMAND(reg); struct i2c_msg msg[2]; @@ -149,11 +149,6 @@ int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val) if (!client->adapter) return -ENODEV; - if (size != 1 && size != 2 && size != 4) { - v4l2_err(sd, "Wrong data size\n"); - return -EINVAL; - } - msg[0].addr = client->addr; msg[0].flags = 0; msg[0].len = 5; @@ -184,6 +179,52 @@ int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val) return 0; } +int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val) +{ + u32 val_32; + int ret; + + if (I2C_SIZE(reg) != 1) { + v4l2_err(sd, "Wrong data size\n"); + return -EINVAL; + } + + ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32); + if (ret) + return ret; + + *val = (u8)val_32; + return ret; +} + +int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val) +{ + u32 val_32; + int ret; + + if (I2C_SIZE(reg) != 2) { + v4l2_err(sd, "Wrong data size\n"); + return -EINVAL; + } + + ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32); + if (ret) + return ret; + + *val = (u16)val_32; + return ret; +} + +int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val) +{ + if (I2C_SIZE(reg) != 4) { + v4l2_err(sd, "Wrong data size\n"); + return -EINVAL; + } + + return m5mols_read(sd, I2C_SIZE(reg), reg, val); +} + /** * m5mols_write - I2C command write function * @reg: combination of size, category and command for the I2C packet @@ -231,13 +272,14 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) return 0; } -int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask) +int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask) { - u32 busy, i; + u8 busy; + int i; int ret; for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { - ret = m5mols_read(sd, I2C_REG(category, cmd, 1), &busy); + ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy); if (ret < 0) return ret; if ((busy & mask) == mask) @@ -252,14 +294,14 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask) * Before writing desired interrupt value the INT_FACTOR register should * be read to clear pending interrupts. */ -int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg) +int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg) { struct m5mols_info *info = to_m5mols(sd); - u32 mask = is_available_af(info) ? REG_INT_AF : 0; - u32 dummy; + u8 mask = is_available_af(info) ? REG_INT_AF : 0; + u8 dummy; int ret; - ret = m5mols_read(sd, SYSTEM_INT_FACTOR, &dummy); + ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy); if (!ret) ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask); return ret; @@ -271,7 +313,7 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg) * It always accompanies a little delay changing the M-5MOLS mode, so it is * needed checking current busy status to guarantee right mode. */ -static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode) +static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) { int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); @@ -286,16 +328,16 @@ static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode) * can be guaranteed only when the sensor is operating in mode which which * a command belongs to. */ -int m5mols_mode(struct m5mols_info *info, u32 mode) +int m5mols_mode(struct m5mols_info *info, u8 mode) { struct v4l2_subdev *sd = &info->sd; int ret = -EINVAL; - u32 reg; + u8 reg; if (mode < REG_PARAMETER && mode > REG_CAPTURE) return ret; - ret = m5mols_read(sd, SYSTEM_SYSMODE, ®); + ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®); if ((!ret && reg == mode) || ret) return ret; @@ -348,28 +390,24 @@ static int m5mols_get_version(struct v4l2_subdev *sd) struct m5mols_version ver; u8 bytes[VERSION_SIZE]; } version; - u32 *value; u8 cmd = CAT0_VER_CUSTOMER; int ret; do { - value = (u32 *)&version.bytes[cmd]; - ret = m5mols_read(sd, SYSTEM_CMD(cmd), value); + ret = m5mols_read_u8(sd, SYSTEM_CMD(cmd), &version.bytes[cmd]); if (ret) return ret; } while (cmd++ != CAT0_VER_AWB); do { - value = (u32 *)&version.bytes[cmd]; - ret = m5mols_read(sd, SYSTEM_VER_STRING, value); + ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &version.bytes[cmd]); if (ret) return ret; if (cmd >= VERSION_SIZE - 1) return -EINVAL; } while (version.bytes[cmd++]); - value = (u32 *)&version.bytes[cmd]; - ret = m5mols_read(sd, AF_VERSION, value); + ret = m5mols_read_u8(sd, AF_VERSION, &version.bytes[cmd]); if (ret) return ret; @@ -722,7 +760,7 @@ static int m5mols_init_controls(struct m5mols_info *info) int ret; /* Determine value's range & step of controls for various FW version */ - ret = m5mols_read(sd, AE_MAX_GAIN_MON, (u32 *)&max_exposure); + ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &max_exposure); if (!ret) step_zoom = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1; if (ret) @@ -842,18 +880,18 @@ static void m5mols_irq_work(struct work_struct *work) struct m5mols_info *info = container_of(work, struct m5mols_info, work_irq); struct v4l2_subdev *sd = &info->sd; - u32 reg; + u8 reg; int ret; if (!is_powered(info) || - m5mols_read(sd, SYSTEM_INT_FACTOR, &info->interrupt)) + m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt)) return; switch (info->interrupt & REG_INT_MASK) { case REG_INT_AF: if (!is_available_af(info)) break; - ret = m5mols_read(sd, AF_STATUS, ®); + ret = m5mols_read_u8(sd, AF_STATUS, ®); v4l2_dbg(2, m5mols_debug, sd, "AF %s\n", reg == REG_AF_FAIL ? "Failed" : reg == REG_AF_SUCCESS ? "Success" : -- cgit v1.2.3 From a6354d2e5da646926ce492b66b527a1efc39cd27 Mon Sep 17 00:00:00 2001 From: "HeungJun, Kim" Date: Tue, 7 Jun 2011 01:59:44 -0300 Subject: [media] m5mols: remove union in the m5mols_get_version(), and VERSION_SIZE Remove union version in the m5mols_get_version(), and read version information directly. Also remove VERSION_SIZE. Signed-off-by: HeungJun, Kim Signed-off-by: Kyungmin Park Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/m5mols/m5mols.h | 1 - drivers/media/video/m5mols/m5mols_core.c | 50 ++++++++++++++++---------------- drivers/media/video/m5mols/m5mols_reg.h | 13 ++++++++- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h index dbe8928855de..9ae170935871 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/video/m5mols/m5mols.h @@ -154,7 +154,6 @@ struct m5mols_version { u8 str[VERSION_STRING_SIZE]; u8 af; }; -#define VERSION_SIZE sizeof(struct m5mols_version) /** * struct m5mols_info - M-5MOLS driver data structure diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index 2b1f23f8d063..9815f2c75e83 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c @@ -386,37 +386,37 @@ int m5mols_mode(struct m5mols_info *info, u8 mode) static int m5mols_get_version(struct v4l2_subdev *sd) { struct m5mols_info *info = to_m5mols(sd); - union { - struct m5mols_version ver; - u8 bytes[VERSION_SIZE]; - } version; - u8 cmd = CAT0_VER_CUSTOMER; + struct m5mols_version *ver = &info->ver; + u8 *str = ver->str; + int i; int ret; - do { - ret = m5mols_read_u8(sd, SYSTEM_CMD(cmd), &version.bytes[cmd]); - if (ret) - return ret; - } while (cmd++ != CAT0_VER_AWB); + ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer); + if (!ret) + ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project); + if (!ret) + ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw); + if (!ret) + ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw); + if (!ret) + ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param); + if (!ret) + ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb); + if (!ret) + ret = m5mols_read_u8(sd, AF_VERSION, &ver->af); + if (ret) + return ret; - do { - ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &version.bytes[cmd]); + for (i = 0; i < VERSION_STRING_SIZE; i++) { + ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]); if (ret) return ret; - if (cmd >= VERSION_SIZE - 1) - return -EINVAL; - } while (version.bytes[cmd++]); - - ret = m5mols_read_u8(sd, AF_VERSION, &version.bytes[cmd]); - if (ret) - return ret; + } - /* store version information swapped for being readable */ - info->ver = version.ver; - info->ver.fw = be16_to_cpu(info->ver.fw); - info->ver.hw = be16_to_cpu(info->ver.hw); - info->ver.param = be16_to_cpu(info->ver.param); - info->ver.awb = be16_to_cpu(info->ver.awb); + ver->fw = be16_to_cpu(ver->fw); + ver->hw = be16_to_cpu(ver->hw); + ver->param = be16_to_cpu(ver->param); + ver->awb = be16_to_cpu(ver->awb); v4l2_info(sd, "Manufacturer\t[%s]\n", is_manufacturer(info, REG_SAMSUNG_ELECTRO) ? diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h index 8260f5030c7e..5f5bdcf608b6 100644 --- a/drivers/media/video/m5mols/m5mols_reg.h +++ b/drivers/media/video/m5mols/m5mols_reg.h @@ -56,13 +56,24 @@ * more specific contents, see definition if file m5mols.h. */ #define CAT0_VER_CUSTOMER 0x00 /* customer version */ -#define CAT0_VER_AWB 0x09 /* Auto WB version */ +#define CAT0_VER_PROJECT 0x01 /* project version */ +#define CAT0_VER_FIRMWARE 0x02 /* Firmware version */ +#define CAT0_VER_HARDWARE 0x04 /* Hardware version */ +#define CAT0_VER_PARAMETER 0x06 /* Parameter version */ +#define CAT0_VER_AWB 0x08 /* Auto WB version */ #define CAT0_VER_STRING 0x0a /* string including M-5MOLS */ #define CAT0_SYSMODE 0x0b /* SYSTEM mode register */ #define CAT0_STATUS 0x0c /* SYSTEM mode status register */ #define CAT0_INT_FACTOR 0x10 /* interrupt pending register */ #define CAT0_INT_ENABLE 0x11 /* interrupt enable register */ +#define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, CAT0_VER_CUSTOMER, 1) +#define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, CAT0_VER_PROJECT, 1) +#define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, CAT0_VER_FIRMWARE, 2) +#define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, CAT0_VER_HARDWARE, 2) +#define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, CAT0_VER_PARAMETER, 2) +#define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, CAT0_VER_AWB, 2) + #define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1) #define REG_SYSINIT 0x00 /* SYSTEM mode */ #define REG_PARAMETER 0x01 /* PARAMETER mode */ -- cgit v1.2.3 From c30701130cf7bff4f97a148b1bc96f878c046a40 Mon Sep 17 00:00:00 2001 From: "HeungJun, Kim" Date: Tue, 7 Jun 2011 02:00:58 -0300 Subject: [media] m5mols: Use proper email address format Signed-off-by: HeungJun, Kim Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/m5mols/m5mols.h | 4 ++-- drivers/media/video/m5mols/m5mols_capture.c | 4 ++-- drivers/media/video/m5mols/m5mols_controls.c | 4 ++-- drivers/media/video/m5mols/m5mols_core.c | 4 ++-- drivers/media/video/m5mols/m5mols_reg.h | 4 ++-- include/media/m5mols.h | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h index 9ae170935871..89d09a8914f8 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/video/m5mols/m5mols.h @@ -2,10 +2,10 @@ * Header for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c index 751f4593da9b..d9471928369d 100644 --- a/drivers/media/video/m5mols/m5mols_capture.c +++ b/drivers/media/video/m5mols/m5mols_capture.c @@ -2,10 +2,10 @@ * The Capture code for Fujitsu M-5MOLS ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/video/m5mols/m5mols_controls.c index d392c83fbf05..d135d20d09cf 100644 --- a/drivers/media/video/m5mols/m5mols_controls.c +++ b/drivers/media/video/m5mols/m5mols_controls.c @@ -2,10 +2,10 @@ * Controls for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index 9815f2c75e83..43c68f51c5ce 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c @@ -2,10 +2,10 @@ * Driver for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h index 5f5bdcf608b6..c755bd6edfe9 100644 --- a/drivers/media/video/m5mols/m5mols_reg.h +++ b/drivers/media/video/m5mols/m5mols_reg.h @@ -2,10 +2,10 @@ * Register map for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/include/media/m5mols.h b/include/media/m5mols.h index 2d7e7ca2313d..aac2c0e06d5e 100644 --- a/include/media/m5mols.h +++ b/include/media/m5mols.h @@ -2,10 +2,10 @@ * Driver header for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From e76e4706cf9051e4db12c3d4418fcfbb053fc463 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 2 Jun 2011 04:52:07 -0300 Subject: [media] MAINTAINERS: Add videobuf2 maintainers Add maintainers for the videobuf2 V4L2 driver framework. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 29801f760b6f..63be58b2891f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6720,6 +6720,15 @@ S: Maintained F: Documentation/filesystems/vfat.txt F: fs/fat/ +VIDEOBUF2 FRAMEWORK +M: Pawel Osciak +M: Marek Szyprowski +M: Kyungmin Park +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/video/videobuf2-* +F: include/media/videobuf2-* + VIRTIO CONSOLE DRIVER M: Amit Shah L: virtualization@lists.linux-foundation.org -- cgit v1.2.3 From 56a210526adb2854d5b7c398a40260720390ee05 Mon Sep 17 00:00:00 2001 From: David Howells Date: Sat, 11 Jun 2011 12:29:58 +0100 Subject: linux/seqlock.h should #include asm/processor.h for cpu_relax() It uses cpu_relax(), and so needs Without this patch, I see: CC arch/mn10300/kernel/asm-offsets.s In file included from include/linux/time.h:8, from include/linux/timex.h:56, from include/linux/sched.h:57, from arch/mn10300/kernel/asm-offsets.c:7: include/linux/seqlock.h: In function 'read_seqbegin': include/linux/seqlock.h:91: error: implicit declaration of function 'cpu_relax' whilst building asb2364_defconfig on MN10300. Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- include/linux/seqlock.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h index e9811892844f..c6db9fb33c44 100644 --- a/include/linux/seqlock.h +++ b/include/linux/seqlock.h @@ -28,6 +28,7 @@ #include #include +#include typedef struct { unsigned sequence; -- cgit v1.2.3 From 3307d0d83b7bf636dc6dd2aa4a584d0f52cc185b Mon Sep 17 00:00:00 2001 From: Connor Hansen Date: Sat, 11 Jun 2011 15:06:48 -0700 Subject: ide-cd: signedness warning fix again One of the legit warnings 'make W=3 drivers/ide/ide-cd.c' generates is: drivers/ide/ide-cd.c: In function ide_cd_do_request drivers/ide/ide-cd.c:828:2: warning: conversion to int from \ unsigned int may change the sign of the result drivers/ide/ide-cd.c:833:2: warning: conversion to int from \ unsigned int may change the sign of the result nsectors is declared int, should be unsigned int. blk_rq_sectors() returns unsigned int, and ide_complete_rq expects unsigned int as well. Fixes both warnings. Signed-off-by: Connor Hansen Signed-off-by: David S. Miller --- drivers/ide/ide-cd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 144d27261e43..04b09564bfa9 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -778,7 +778,8 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, sector_t block) { struct ide_cmd cmd; - int uptodate = 0, nsectors; + int uptodate = 0; + unsigned int nsectors; ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, block: %llu", rq->cmd[0], (unsigned long long)block); -- cgit v1.2.3 From d814dee0e1a5d9b2f858b91551a0dd0608f777a1 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Fri, 10 Jun 2011 00:51:54 +0000 Subject: NET: am79c961: ensure asm() statements are marked volatile Without this the compiler can (and does) optimize register reads away from within loops, and other such optimizations. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 0c9217f48b72..084b67fbe7aa 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -50,7 +50,7 @@ static const char version[] = #ifdef __arm__ static void write_rreg(u_long base, u_int reg, u_int val) { - __asm__( + asm volatile( "str%?h %1, [%2] @ NET_RAP\n\t" "str%?h %0, [%2, #-4] @ NET_RDP" : @@ -60,7 +60,7 @@ static void write_rreg(u_long base, u_int reg, u_int val) static inline unsigned short read_rreg(u_long base_addr, u_int reg) { unsigned short v; - __asm__( + asm volatile( "str%?h %1, [%2] @ NET_RAP\n\t" "ldr%?h %0, [%2, #-4] @ NET_RDP" : "=r" (v) @@ -70,7 +70,7 @@ static inline unsigned short read_rreg(u_long base_addr, u_int reg) static inline void write_ireg(u_long base, u_int reg, u_int val) { - __asm__( + asm volatile( "str%?h %1, [%2] @ NET_RAP\n\t" "str%?h %0, [%2, #8] @ NET_IDP" : @@ -80,7 +80,7 @@ static inline void write_ireg(u_long base, u_int reg, u_int val) static inline unsigned short read_ireg(u_long base_addr, u_int reg) { u_short v; - __asm__( + asm volatile( "str%?h %1, [%2] @ NAT_RAP\n\t" "ldr%?h %0, [%2, #8] @ NET_IDP\n\t" : "=r" (v) @@ -131,7 +131,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned length = (length + 1) & ~1; if ((int)buf & 2) { unsigned int tmp; - __asm__ __volatile__( + asm volatile( "ldr%?h %2, [%0], #4\n\t" "str%?b %2, [%1], #1\n\t" "mov%? %2, %2, lsr #8\n\t" @@ -141,7 +141,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned } while (length > 8) { unsigned int tmp, tmp2, tmp3; - __asm__ __volatile__( + asm volatile( "ldr%?h %2, [%0], #4\n\t" "ldr%?h %3, [%0], #4\n\t" "orr%? %2, %2, %3, lsl #16\n\t" @@ -155,7 +155,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned } while (length > 0) { unsigned int tmp; - __asm__ __volatile__( + asm volatile( "ldr%?h %2, [%0], #4\n\t" "str%?b %2, [%1], #1\n\t" "mov%? %2, %2, lsr #8\n\t" -- cgit v1.2.3 From bfc6501324427a97814de1587f89d73bf8677057 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Fri, 10 Jun 2011 00:52:14 +0000 Subject: NET: am79c961: ensure multicast filter is correctly set at open We were clearing out the multicast filter whenever the interface was upped, and not setting the mode bits correctly. This can cause problems if there are any multicast addresses already set at this point, or if ALLMULTI was set. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 77 +++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 084b67fbe7aa..79d88a0b00a3 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -196,6 +196,42 @@ am79c961_ramtest(struct net_device *dev, unsigned int val) return errorcount; } +static void am79c961_mc_hash(char *addr, u16 *hash) +{ + if (addr[0] & 0x01) { + int idx, bit; + u32 crc; + + crc = ether_crc_le(ETH_ALEN, addr); + + idx = crc >> 30; + bit = (crc >> 26) & 15; + + hash[idx] |= 1 << bit; + } +} + +static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash) +{ + unsigned int mode = MODE_PORT_10BT; + + if (dev->flags & IFF_PROMISC) { + mode |= MODE_PROMISC; + memset(hash, 0xff, 4 * sizeof(*hash)); + } else if (dev->flags & IFF_ALLMULTI) { + memset(hash, 0xff, 4 * sizeof(*hash)); + } else { + struct netdev_hw_addr *ha; + + memset(hash, 0, 4 * sizeof(*hash)); + + netdev_for_each_mc_addr(ha, dev) + am79c961_mc_hash(ha->addr, hash); + } + + return mode; +} + static void am79c961_init_for_open(struct net_device *dev) { @@ -203,6 +239,7 @@ am79c961_init_for_open(struct net_device *dev) unsigned long flags; unsigned char *p; u_int hdr_addr, first_free_addr; + u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash); int i; /* @@ -218,16 +255,12 @@ am79c961_init_for_open(struct net_device *dev) write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */ for (i = LADRL; i <= LADRH; i++) - write_rreg (dev->base_addr, i, 0); + write_rreg (dev->base_addr, i, multi_hash[i - LADRL]); for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2) write_rreg (dev->base_addr, i, p[0] | (p[1] << 8)); - i = MODE_PORT_10BT; - if (dev->flags & IFF_PROMISC) - i |= MODE_PROMISC; - - write_rreg (dev->base_addr, MODE, i); + write_rreg (dev->base_addr, MODE, mode); write_rreg (dev->base_addr, POLLINT, 0); write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS); write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS); @@ -340,21 +373,6 @@ am79c961_close(struct net_device *dev) return 0; } -static void am79c961_mc_hash(char *addr, unsigned short *hash) -{ - if (addr[0] & 0x01) { - int idx, bit; - u32 crc; - - crc = ether_crc_le(ETH_ALEN, addr); - - idx = crc >> 30; - bit = (crc >> 26) & 15; - - hash[idx] |= 1 << bit; - } -} - /* * Set or clear promiscuous/multicast mode filter for this adapter. */ @@ -362,24 +380,9 @@ static void am79c961_setmulticastlist (struct net_device *dev) { struct dev_priv *priv = netdev_priv(dev); unsigned long flags; - unsigned short multi_hash[4], mode; + u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash); int i, stopped; - mode = MODE_PORT_10BT; - - if (dev->flags & IFF_PROMISC) { - mode |= MODE_PROMISC; - } else if (dev->flags & IFF_ALLMULTI) { - memset(multi_hash, 0xff, sizeof(multi_hash)); - } else { - struct netdev_hw_addr *ha; - - memset(multi_hash, 0x00, sizeof(multi_hash)); - - netdev_for_each_mc_addr(ha, dev) - am79c961_mc_hash(ha->addr, multi_hash); - } - spin_lock_irqsave(&priv->chip_lock, flags); stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP; -- cgit v1.2.3 From f777737885a69d37132c956f1e8deab676693157 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Fri, 10 Jun 2011 00:52:35 +0000 Subject: NET: am79c961: fix assembler warnings Fix: /tmp/ccvoZ6h8.s: Assembler messages: /tmp/ccvoZ6h8.s:284: Warning: register range not in ascending order /tmp/ccvoZ6h8.s:881: Warning: register range not in ascending order /tmp/ccvoZ6h8.s:1087: Warning: register range not in ascending order by ensuring that we have temporary variables placed into specific registers. Reorder the code a bit to allow the resulting assembly to be slightly more optimal. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 79d88a0b00a3..7b3e23f38913 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -91,40 +91,41 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg) #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1)) #define am_readword(dev,off) __raw_readw(ISAMEM_BASE + ((off) << 1)) -static inline void +static void am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length) { offset = ISAMEM_BASE + (offset << 1); length = (length + 1) & ~1; if ((int)buf & 2) { - __asm__ __volatile__("str%?h %2, [%0], #4" + asm volatile("str%?h %2, [%0], #4" : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8))); buf += 2; length -= 2; } while (length > 8) { - unsigned int tmp, tmp2; - __asm__ __volatile__( - "ldm%?ia %1!, {%2, %3}\n\t" + register unsigned int tmp asm("r2"), tmp2 asm("r3"); + asm volatile( + "ldm%?ia %0!, {%1, %2}" + : "+r" (buf), "=&r" (tmp), "=&r" (tmp2)); + length -= 8; + asm volatile( + "str%?h %1, [%0], #4\n\t" + "mov%? %1, %1, lsr #16\n\t" + "str%?h %1, [%0], #4\n\t" "str%?h %2, [%0], #4\n\t" "mov%? %2, %2, lsr #16\n\t" - "str%?h %2, [%0], #4\n\t" - "str%?h %3, [%0], #4\n\t" - "mov%? %3, %3, lsr #16\n\t" - "str%?h %3, [%0], #4" - : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2) - : "0" (offset), "1" (buf)); - length -= 8; + "str%?h %2, [%0], #4" + : "+r" (offset), "=&r" (tmp), "=&r" (tmp2)); } while (length > 0) { - __asm__ __volatile__("str%?h %2, [%0], #4" + asm volatile("str%?h %2, [%0], #4" : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8))); buf += 2; length -= 2; } } -static inline void +static void am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length) { offset = ISAMEM_BASE + (offset << 1); @@ -140,12 +141,12 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned length -= 2; } while (length > 8) { - unsigned int tmp, tmp2, tmp3; + register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3; asm volatile( "ldr%?h %2, [%0], #4\n\t" + "ldr%?h %4, [%0], #4\n\t" "ldr%?h %3, [%0], #4\n\t" - "orr%? %2, %2, %3, lsl #16\n\t" - "ldr%?h %3, [%0], #4\n\t" + "orr%? %2, %2, %4, lsl #16\n\t" "ldr%?h %4, [%0], #4\n\t" "orr%? %3, %3, %4, lsl #16\n\t" "stm%?ia %1!, {%2, %3}" -- cgit v1.2.3 From 06866bf5c5ad8989119a145fdb54a9fbcafa702d Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 10 Jun 2011 04:55:16 +0000 Subject: dl2k: EEPROM CRC calculation wrong endianess on bigendian machine Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/dl2k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index c445457b66d5..23179dbcedd2 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -346,7 +346,7 @@ parse_eeprom (struct net_device *dev) if (np->pdev->vendor == PCI_VENDOR_ID_DLINK) { /* D-Link Only */ /* Check CRC */ crc = ~ether_crc_le (256 - 4, sromdata); - if (psrom->crc != crc) { + if (psrom->crc != cpu_to_le32(crc)) { printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name); return -1; -- cgit v1.2.3 From 0b5c9db1b11d3175bb42b80663a9f072f801edf5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 10 Jun 2011 06:56:58 +0000 Subject: vlan: Fix the ingress VLAN_FLAG_REORDER_HDR check Testing of VLAN_FLAG_REORDER_HDR does not belong in vlan_untag but rather in vlan_do_receive. Otherwise the vlan header will not be properly put on the packet in the case of vlan header accelleration. As we remove the check from vlan_check_reorder_header rename it vlan_reorder_header to keep the naming clean. Fix up the skb->pkt_type early so we don't look at the packet after adding the vlan tag, which guarantees we don't goof and look at the wrong field. Use a simple if statement instead of a complicated switch statement to decided that we need to increment rx_stats for a multicast packet. Hopefully at somepoint we will just declare the case where VLAN_FLAG_REORDER_HDR is cleared as unsupported and remove the code. Until then this keeps it working correctly. Signed-off-by: Eric W. Biederman Signed-off-by: Jiri Pirko Acked-by: Changli Gao Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 25 ++++++++++++++++++--- include/linux/skbuff.h | 5 +++++ net/8021q/vlan_core.c | 60 +++++++++++++++++++++++++++---------------------- net/core/dev.c | 2 +- 4 files changed, 61 insertions(+), 31 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index dc01681fbb42..affa27380b72 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -225,7 +225,7 @@ static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb, } /** - * __vlan_put_tag - regular VLAN tag inserting + * vlan_insert_tag - regular VLAN tag inserting * @skb: skbuff to tag * @vlan_tci: VLAN TCI to insert * @@ -234,8 +234,10 @@ static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb, * * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. + * + * Does not change skb->protocol so this function can be used during receive. */ -static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) +static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, u16 vlan_tci) { struct vlan_ethhdr *veth; @@ -255,8 +257,25 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) /* now, the TCI */ veth->h_vlan_TCI = htons(vlan_tci); - skb->protocol = htons(ETH_P_8021Q); + return skb; +} +/** + * __vlan_put_tag - regular VLAN tag inserting + * @skb: skbuff to tag + * @vlan_tci: VLAN TCI to insert + * + * Inserts the VLAN tag into @skb as part of the payload + * Returns a VLAN tagged skb. If a new skb is created, @skb is freed. + * + * Following the skb_unshare() example, in case of error, the calling function + * doesn't have to worry about freeing the original skb. + */ +static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) +{ + skb = vlan_insert_tag(skb, vlan_tci); + if (skb) + skb->protocol = htons(ETH_P_8021Q); return skb; } diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index e8b78ce14474..c0a4f3ab0cc0 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1256,6 +1256,11 @@ static inline void skb_reserve(struct sk_buff *skb, int len) skb->tail += len; } +static inline void skb_reset_mac_len(struct sk_buff *skb) +{ + skb->mac_len = skb->network_header - skb->mac_header; +} + #ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_transport_header(const struct sk_buff *skb) { diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 41495dc2a4c9..fcc684678af6 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -23,6 +23,31 @@ bool vlan_do_receive(struct sk_buff **skbp) return false; skb->dev = vlan_dev; + if (skb->pkt_type == PACKET_OTHERHOST) { + /* Our lower layer thinks this is not local, let's make sure. + * This allows the VLAN to have a different MAC than the + * underlying device, and still route correctly. */ + if (!compare_ether_addr(eth_hdr(skb)->h_dest, + vlan_dev->dev_addr)) + skb->pkt_type = PACKET_HOST; + } + + if (!(vlan_dev_info(vlan_dev)->flags & VLAN_FLAG_REORDER_HDR)) { + unsigned int offset = skb->data - skb_mac_header(skb); + + /* + * vlan_insert_tag expect skb->data pointing to mac header. + * So change skb->data before calling it and change back to + * original position later + */ + skb_push(skb, offset); + skb = *skbp = vlan_insert_tag(skb, skb->vlan_tci); + if (!skb) + return false; + skb_pull(skb, offset + VLAN_HLEN); + skb_reset_mac_len(skb); + } + skb->priority = vlan_get_ingress_priority(vlan_dev, skb->vlan_tci); skb->vlan_tci = 0; @@ -31,22 +56,8 @@ bool vlan_do_receive(struct sk_buff **skbp) u64_stats_update_begin(&rx_stats->syncp); rx_stats->rx_packets++; rx_stats->rx_bytes += skb->len; - - switch (skb->pkt_type) { - case PACKET_BROADCAST: - break; - case PACKET_MULTICAST: + if (skb->pkt_type == PACKET_MULTICAST) rx_stats->rx_multicast++; - break; - case PACKET_OTHERHOST: - /* Our lower layer thinks this is not local, let's make sure. - * This allows the VLAN to have a different MAC than the - * underlying device, and still route correctly. */ - if (!compare_ether_addr(eth_hdr(skb)->h_dest, - vlan_dev->dev_addr)) - skb->pkt_type = PACKET_HOST; - break; - } u64_stats_update_end(&rx_stats->syncp); return true; @@ -89,18 +100,13 @@ gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, } EXPORT_SYMBOL(vlan_gro_frags); -static struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) +static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) { - if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { - if (skb_cow(skb, skb_headroom(skb)) < 0) - skb = NULL; - if (skb) { - /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - ETH_HLEN, - skb->data - VLAN_ETH_HLEN, 12); - skb->mac_header += VLAN_HLEN; - } - } + if (skb_cow(skb, skb_headroom(skb)) < 0) + return NULL; + memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); + skb->mac_header += VLAN_HLEN; + skb_reset_mac_len(skb); return skb; } @@ -161,7 +167,7 @@ struct sk_buff *vlan_untag(struct sk_buff *skb) skb_pull_rcsum(skb, VLAN_HLEN); vlan_set_encap_proto(skb, vhdr); - skb = vlan_check_reorder_header(skb); + skb = vlan_reorder_header(skb); if (unlikely(!skb)) goto err_free; diff --git a/net/core/dev.c b/net/core/dev.c index a54c9f87ddbb..9c58c1ec41a9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3114,7 +3114,7 @@ static int __netif_receive_skb(struct sk_buff *skb) skb_reset_network_header(skb); skb_reset_transport_header(skb); - skb->mac_len = skb->network_header - skb->mac_header; + skb_reset_mac_len(skb); pt_prev = NULL; -- cgit v1.2.3 From fa70cf472c0bc3a0d7e613a418cfc1117b796c6c Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:54 +0000 Subject: ep93xx: set DMA masks for the ep93xx_eth Since the driver uses the DMA API, we should pass it valid DMA masks. Signed-off-by: Mika Westerberg Acked-by: Russell King Acked-by: H Hartley Sweeten Tested-by: Petr Stetiar Signed-off-by: David S. Miller --- arch/arm/mach-ep93xx/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 82079545adc4..1d4b65fd673e 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -402,11 +402,15 @@ static struct resource ep93xx_eth_resource[] = { } }; +static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32); + static struct platform_device ep93xx_eth_device = { .name = "ep93xx-eth", .id = -1, .dev = { - .platform_data = &ep93xx_eth_data, + .platform_data = &ep93xx_eth_data, + .coherent_dma_mask = DMA_BIT_MASK(32), + .dma_mask = &ep93xx_eth_dma_mask, }, .num_resources = ARRAY_SIZE(ep93xx_eth_resource), .resource = ep93xx_eth_resource, -- cgit v1.2.3 From fc9b4910b00039da054f221e2821be0519261101 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:55 +0000 Subject: net: ep93xx_eth: pass struct device to DMA API functions We shouldn't use NULL for any DMA API functions, unless we are dealing with ISA or EISA device. So pass correct struct dev pointer to these functions. Signed-off-by: Mika Westerberg Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 5a77001b6d10..f65dfb6e5705 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -284,7 +284,7 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) skb = dev_alloc_skb(length + 2); if (likely(skb != NULL)) { skb_reserve(skb, 2); - dma_sync_single_for_cpu(NULL, ep->descs->rdesc[entry].buf_addr, + dma_sync_single_for_cpu(dev->dev.parent, ep->descs->rdesc[entry].buf_addr, length, DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, ep->rx_buf[entry], length); skb_put(skb, length); @@ -362,7 +362,7 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) ep->descs->tdesc[entry].tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff); skb_copy_and_csum_dev(skb, ep->tx_buf[entry]); - dma_sync_single_for_cpu(NULL, ep->descs->tdesc[entry].buf_addr, + dma_sync_single_for_cpu(dev->dev.parent, ep->descs->tdesc[entry].buf_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb(skb); @@ -457,6 +457,7 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id) static void ep93xx_free_buffers(struct ep93xx_priv *ep) { + struct device *dev = ep->dev->dev.parent; int i; for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) { @@ -464,7 +465,7 @@ static void ep93xx_free_buffers(struct ep93xx_priv *ep) d = ep->descs->rdesc[i].buf_addr; if (d) - dma_unmap_single(NULL, d, PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(dev, d, PAGE_SIZE, DMA_FROM_DEVICE); if (ep->rx_buf[i] != NULL) free_page((unsigned long)ep->rx_buf[i]); @@ -475,13 +476,13 @@ static void ep93xx_free_buffers(struct ep93xx_priv *ep) d = ep->descs->tdesc[i].buf_addr; if (d) - dma_unmap_single(NULL, d, PAGE_SIZE, DMA_TO_DEVICE); + dma_unmap_single(dev, d, PAGE_SIZE, DMA_TO_DEVICE); if (ep->tx_buf[i] != NULL) free_page((unsigned long)ep->tx_buf[i]); } - dma_free_coherent(NULL, sizeof(struct ep93xx_descs), ep->descs, + dma_free_coherent(dev, sizeof(struct ep93xx_descs), ep->descs, ep->descs_dma_addr); } @@ -491,9 +492,10 @@ static void ep93xx_free_buffers(struct ep93xx_priv *ep) */ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) { + struct device *dev = ep->dev->dev.parent; int i; - ep->descs = dma_alloc_coherent(NULL, sizeof(struct ep93xx_descs), + ep->descs = dma_alloc_coherent(dev, sizeof(struct ep93xx_descs), &ep->descs_dma_addr, GFP_KERNEL | GFP_DMA); if (ep->descs == NULL) return 1; @@ -506,8 +508,8 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) if (page == NULL) goto err; - d = dma_map_single(NULL, page, PAGE_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(NULL, d)) { + d = dma_map_single(dev, page, PAGE_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(dev, d)) { free_page((unsigned long)page); goto err; } @@ -529,8 +531,8 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) if (page == NULL) goto err; - d = dma_map_single(NULL, page, PAGE_SIZE, DMA_TO_DEVICE); - if (dma_mapping_error(NULL, d)) { + d = dma_map_single(dev, page, PAGE_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(dev, d)) { free_page((unsigned long)page); goto err; } @@ -829,6 +831,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev) } ep = netdev_priv(dev); ep->dev = dev; + SET_NETDEV_DEV(dev, &pdev->dev); netif_napi_add(dev, &ep->napi, ep93xx_poll, 64); platform_set_drvdata(pdev, dev); -- cgit v1.2.3 From 3247a1fcee49b571b40c4bd723439ce5c64f56ad Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:56 +0000 Subject: net: ep93xx_eth: allocate buffers using kmalloc() We can use simply kmalloc() to allocate the buffers. This also simplifies the code and allows us to perform DMA sync operations more easily. Memory is allocated with only GFP_KERNEL since there are no DMA allocation restrictions on this platform. Signed-off-by: Mika Westerberg Acked-by: Russell King Acked-by: H Hartley Sweeten Tested-by: Petr Stetiar Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 51 +++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index f65dfb6e5705..97bf6b10ce61 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -460,36 +460,32 @@ static void ep93xx_free_buffers(struct ep93xx_priv *ep) struct device *dev = ep->dev->dev.parent; int i; - for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) { + for (i = 0; i < RX_QUEUE_ENTRIES; i++) { dma_addr_t d; d = ep->descs->rdesc[i].buf_addr; if (d) - dma_unmap_single(dev, d, PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_FROM_DEVICE); if (ep->rx_buf[i] != NULL) - free_page((unsigned long)ep->rx_buf[i]); + kfree(ep->rx_buf[i]); } - for (i = 0; i < TX_QUEUE_ENTRIES; i += 2) { + for (i = 0; i < TX_QUEUE_ENTRIES; i++) { dma_addr_t d; d = ep->descs->tdesc[i].buf_addr; if (d) - dma_unmap_single(dev, d, PAGE_SIZE, DMA_TO_DEVICE); + dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_TO_DEVICE); if (ep->tx_buf[i] != NULL) - free_page((unsigned long)ep->tx_buf[i]); + kfree(ep->tx_buf[i]); } dma_free_coherent(dev, sizeof(struct ep93xx_descs), ep->descs, ep->descs_dma_addr); } -/* - * The hardware enforces a sub-2K maximum packet size, so we put - * two buffers on every hardware page. - */ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) { struct device *dev = ep->dev->dev.parent; @@ -500,48 +496,41 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) if (ep->descs == NULL) return 1; - for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) { - void *page; + for (i = 0; i < RX_QUEUE_ENTRIES; i++) { + void *buf; dma_addr_t d; - page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (page == NULL) + buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL); + if (buf == NULL) goto err; - d = dma_map_single(dev, page, PAGE_SIZE, DMA_FROM_DEVICE); + d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_FROM_DEVICE); if (dma_mapping_error(dev, d)) { - free_page((unsigned long)page); + kfree(buf); goto err; } - ep->rx_buf[i] = page; + ep->rx_buf[i] = buf; ep->descs->rdesc[i].buf_addr = d; ep->descs->rdesc[i].rdesc1 = (i << 16) | PKT_BUF_SIZE; - - ep->rx_buf[i + 1] = page + PKT_BUF_SIZE; - ep->descs->rdesc[i + 1].buf_addr = d + PKT_BUF_SIZE; - ep->descs->rdesc[i + 1].rdesc1 = ((i + 1) << 16) | PKT_BUF_SIZE; } - for (i = 0; i < TX_QUEUE_ENTRIES; i += 2) { - void *page; + for (i = 0; i < TX_QUEUE_ENTRIES; i++) { + void *buf; dma_addr_t d; - page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (page == NULL) + buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL); + if (buf == NULL) goto err; - d = dma_map_single(dev, page, PAGE_SIZE, DMA_TO_DEVICE); + d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dev, d)) { - free_page((unsigned long)page); + kfree(buf); goto err; } - ep->tx_buf[i] = page; + ep->tx_buf[i] = buf; ep->descs->tdesc[i].buf_addr = d; - - ep->tx_buf[i + 1] = page + PKT_BUF_SIZE; - ep->descs->tdesc[i + 1].buf_addr = d + PKT_BUF_SIZE; } return 0; -- cgit v1.2.3 From 1f758a4341ac83289a549e6ba2d29a08cf639717 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:57 +0000 Subject: net: ep93xx_eth: drop GFP_DMA from call to dma_alloc_coherent() Commit a197b59ae6e8 (mm: fail GFP_DMA allocations when ZONE_DMA is not configured) made page allocator to return NULL if GFP_DMA is set but CONFIG_ZONE_DMA is disabled. This causes ep93xx_eth to fail: WARNING: at mm/page_alloc.c:2251 __alloc_pages_nodemask+0x11c/0x638() Modules linked in: [] (unwind_backtrace+0x0/0xf4) from [] (warn_slowpath_common+0x48/0x60) [] (warn_slowpath_common+0x48/0x60) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (__alloc_pages_nodemask+0x11c/0x638) [] (__alloc_pages_nodemask+0x11c/0x638) from [] (__dma_alloc+0x8c/0x3ec) [] (__dma_alloc+0x8c/0x3ec) from [] (dma_alloc_coherent+0x54/0x60) [] (dma_alloc_coherent+0x54/0x60) from [] (ep93xx_open+0x20/0x864) [] (ep93xx_open+0x20/0x864) from [] (__dev_open+0xb8/0x108) [] (__dev_open+0xb8/0x108) from [] (__dev_change_flags+0x70/0x128) [] (__dev_change_flags+0x70/0x128) from [] (dev_change_flags+0x10/0x48) [] (dev_change_flags+0x10/0x48) from [] (ip_auto_config+0x190/0xf68) [] (ip_auto_config+0x190/0xf68) from [] (do_one_initcall+0x34/0x18c) [] (do_one_initcall+0x34/0x18c) from [] (kernel_init+0x94/0x134) [] (kernel_init+0x94/0x134) from [] (kernel_thread_exit+0x0/0x8) Since there is no restrictions for DMA on ep93xx, we can fix this by just removing the GFP_DMA flag from the call. Signed-off-by: Mika Westerberg Acked-by: Russell King Acked-by: H Hartley Sweeten Tested-by: Petr Stetiar Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 97bf6b10ce61..bef38116abaf 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -492,7 +492,7 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) int i; ep->descs = dma_alloc_coherent(dev, sizeof(struct ep93xx_descs), - &ep->descs_dma_addr, GFP_KERNEL | GFP_DMA); + &ep->descs_dma_addr, GFP_KERNEL); if (ep->descs == NULL) return 1; -- cgit v1.2.3 From f1c089e3192f1afdfa76226dc38ef81b08ac810d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:58 +0000 Subject: net: ep93xx_eth: fix DMA API violations Russell King said: > > So, to summarize what its doing: > > 1. It allocates buffers for rx and tx. > 2. It maps them with dma_map_single(). > This transfers ownership of the buffer to the DMA device. > 3. In ep93xx_xmit, > 3a. It copies the data into the buffer with skb_copy_and_csum_dev() > This violates the DMA buffer ownership rules - the CPU should > not be writing to this buffer while it is (in principle) owned > by the DMA device. > 3b. It then calls dma_sync_single_for_cpu() for the buffer. > This transfers ownership of the buffer to the CPU, which surely > is the wrong direction. > 4. In ep93xx_rx, > 4a. It calls dma_sync_single_for_cpu() for the buffer. > This at least transfers the DMA buffer ownership to the CPU > before the CPU reads the buffer > 4b. It then uses skb_copy_to_linear_data() to copy the data out. > At no point does it transfer ownership back to the DMA device. > 5. When the driver is removed, it dma_unmap_single()'s the buffer. > This transfers ownership of the buffer to the CPU. > 6. It frees the buffer. > > While it may work on ep93xx, it's not respecting the DMA API rules, > and with DMA debugging enabled it will probably encounter quite a few > warnings. This patch fixes these violations. Signed-off-by: Mika Westerberg Acked-by: Russell King Acked-by: H Hartley Sweeten Tested-by: Petr Stetiar Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index bef38116abaf..0b46b8ea0e80 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -283,10 +283,14 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) skb = dev_alloc_skb(length + 2); if (likely(skb != NULL)) { + struct ep93xx_rdesc *rxd = &ep->descs->rdesc[entry]; skb_reserve(skb, 2); - dma_sync_single_for_cpu(dev->dev.parent, ep->descs->rdesc[entry].buf_addr, + dma_sync_single_for_cpu(dev->dev.parent, rxd->buf_addr, length, DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, ep->rx_buf[entry], length); + dma_sync_single_for_device(dev->dev.parent, + rxd->buf_addr, length, + DMA_FROM_DEVICE); skb_put(skb, length); skb->protocol = eth_type_trans(skb, dev); @@ -348,6 +352,7 @@ poll_some_more: static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) { struct ep93xx_priv *ep = netdev_priv(dev); + struct ep93xx_tdesc *txd; int entry; if (unlikely(skb->len > MAX_PKT_SIZE)) { @@ -359,11 +364,14 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) entry = ep->tx_pointer; ep->tx_pointer = (ep->tx_pointer + 1) & (TX_QUEUE_ENTRIES - 1); - ep->descs->tdesc[entry].tdesc1 = - TDESC1_EOF | (entry << 16) | (skb->len & 0xfff); + txd = &ep->descs->tdesc[entry]; + + txd->tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff); + dma_sync_single_for_cpu(dev->dev.parent, txd->buf_addr, skb->len, + DMA_TO_DEVICE); skb_copy_and_csum_dev(skb, ep->tx_buf[entry]); - dma_sync_single_for_cpu(dev->dev.parent, ep->descs->tdesc[entry].buf_addr, - skb->len, DMA_TO_DEVICE); + dma_sync_single_for_device(dev->dev.parent, txd->buf_addr, skb->len, + DMA_TO_DEVICE); dev_kfree_skb(skb); spin_lock_irq(&ep->tx_pending_lock); -- cgit v1.2.3 From 83fe32de63e60af34fa8dae83716cb13b8677abd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 11 Jun 2011 18:55:22 -0700 Subject: netpoll: call dev_put() on error in netpoll_setup() There is a dev_put(ndev) missing on an error path. This was introduced in 0c1ad04aecb "netpoll: prevent netpoll setup on slave devices". Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- net/core/netpoll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 42ea4b0e59f1..18d9cbda3a39 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -795,7 +795,8 @@ int netpoll_setup(struct netpoll *np) if (ndev->master) { printk(KERN_ERR "%s: %s is a slave device, aborting.\n", np->name, np->dev_name); - return -EBUSY; + err = -EBUSY; + goto put; } if (!netif_running(ndev)) { -- cgit v1.2.3 From 84860c725364372a331589a600ce6a00437a14f8 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 11 Jun 2011 06:36:42 +0000 Subject: ISDN, hfcsusb: Don't leak in hfcsusb_ph_info() We leak the memory allocated to 'phi' when the variable goes out of scope in hfcsusb_ph_info(). Signed-off-by: Jesper Juhl Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcsusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 3ccbff13eaf2..71a8eb6ef71e 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -283,6 +283,7 @@ hfcsusb_ph_info(struct hfcsusb *hw) _queue_data(&dch->dev.D, MPH_INFORMATION_IND, MISDN_ID_ANY, sizeof(struct ph_info_dch) + dch->dev.nrbchan * sizeof(struct ph_info_ch), phi, GFP_ATOMIC); + kfree(phi); } /* -- cgit v1.2.3 From c0da00145f9a32ef33b14508e6fd90fc130afbdc Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Sun, 12 Jun 2011 17:26:17 +0200 Subject: ALSA: hdspm - Fix locking in snd_hdspm_midi_input_read For the MIDI part, we need to acquire (and release) the hmidi->lock, access to the global hdspm structure is serialized through hmidi->hdspm->lock instead. Signed-off-by: Adrian Knoth Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 949691a876d3..32d80af012cc 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1639,12 +1639,14 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) } } hmidi->pending = 0; + spin_unlock_irqrestore(&hmidi->lock, flags); + spin_lock_irqsave(&hmidi->hdspm->lock, flags); hmidi->hdspm->control_register |= hmidi->ie; hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register); + spin_unlock_irqrestore(&hmidi->hdspm->lock, flags); - spin_unlock_irqrestore (&hmidi->lock, flags); return snd_hdspm_midi_output_write (hmidi); } -- cgit v1.2.3 From fedf1535ab5ee02acbbc235c2272d84bb9334758 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Sun, 12 Jun 2011 17:26:18 +0200 Subject: ALSA: hdspm - Fix jumping external wordclock frequency in AutoSync mode When using Word Clock on RME MADI cards, AutoSync mode was alternating betweeen MADI and WC due to a typo: AutoSync is indicated in the second status register (status2), not the first one (status). While the proc output was always correct, the reported WC frequency to ALSA was unstable as mentioned in http://mailman.alsa-project.org/pipermail/alsa-devel/2008-March/006723.html Signed-off-by: Adrian Knoth Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 32d80af012cc..d03ef94d570e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1143,7 +1143,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) /* if wordclock has synced freq and wordclock is valid */ if ((status2 & HDSPM_wcLock) != 0 && - (status & HDSPM_SelSyncRef0) == 0) { + (status2 & HDSPM_SelSyncRef0) == 0) { rate_bits = status2 & HDSPM_wcFreqMask; -- cgit v1.2.3 From efef054e8c4bc4fd48a0b4deb5491116d9f557c7 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Sun, 12 Jun 2011 17:26:19 +0200 Subject: ALSA: hdspm - Add firmware revision ID for RME MADI PCI version The PCI version of the RME HDSP MADI card uses 0xcf as revision ID. Just add this to the list of supported cards. Signed-off-by: Adrian Knoth Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index d03ef94d570e..3f08afc0f0d3 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -521,6 +521,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) /* revisions >= 230 indicate AES32 card */ +#define HDSPM_MADI_OLD_REV 207 #define HDSPM_MADI_REV 210 #define HDSPM_RAYDAT_REV 211 #define HDSPM_AIO_REV 212 @@ -6379,6 +6380,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, switch (hdspm->firmware_rev) { case HDSPM_MADI_REV: + case HDSPM_MADI_OLD_REV: hdspm->io_type = MADI; hdspm->card_name = "RME MADI"; hdspm->midiPorts = 3; -- cgit v1.2.3 From ac5d4b404e78bd7eb67fc70c2acb437a25497e98 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Sun, 12 Jun 2011 01:15:42 +0200 Subject: ALSA: emu10k1: Add details for E-mu 0404 PCIe version This patch adds the necessary details to support the PCIe version of E-MU's 0404 card. From comparing the PCBs it seems the PCIe version just added a PCIe chipset and left all other components pretty much in place. For anyone intrigued to take a look at the PCB there are pictures I took at . Signed-off-by: Florian Zeitz Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 5e619a84da06..15f0161ce4a2 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1440,6 +1440,14 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0102_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ + /* EMU0404 PCIe */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, + .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", + .id = "EMU0404", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ /* Note that all E-mu cards require kernel 2.6 or newer. */ {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", -- cgit v1.2.3 From 89b882a25e703b72c3e84c582357e3e864d8ccca Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 1 Jun 2011 10:59:10 -0700 Subject: MAINTAINERS: Update CPU FREQUENCY patterns Commit bb0a56ecc4ba ("[CPUFREQ] Move x86 drivers to drivers/cpufreq/") moved the files, remove the old pattern. Signed-off-by: Joe Perches Signed-off-by: Dave Jones --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 29801f760b6f..55d7b8062b30 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1889,7 +1889,6 @@ L: cpufreq@vger.kernel.org W: http://www.codemonkey.org.uk/projects/cpufreq/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git S: Maintained -F: arch/x86/kernel/cpu/cpufreq/ F: drivers/cpufreq/ F: include/linux/cpufreq.h -- cgit v1.2.3 From 13f067537f34456443f61c950cd6dc37d1d5f3ee Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 12 Jun 2011 16:35:28 -0400 Subject: [CPUFREQ] Remove cpufreq_stats sysfs entries on module unload. cpufreq_stats leaves behind its sysfs entries, which causes a panic when something stumbled across them. (Discovered by unloading cpufreq_stats while powertop was loaded). Signed-off-by: Dave Jones Cc: stable@kernel.org --- drivers/cpufreq/cpufreq_stats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index b60a4c263686..853f92d23ddb 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -387,6 +387,7 @@ static void __exit cpufreq_stats_exit(void) unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); for_each_online_cpu(cpu) { cpufreq_stats_free_table(cpu); + cpufreq_stats_free_sysfs(cpu); } } -- cgit v1.2.3 From ff78fca2a03c08436535d3f7152a30752d8131d1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jun 2011 09:42:17 -0400 Subject: fix leak in proc_set_super() set_anon_super() can fail... Signed-off-by: Al Viro --- fs/proc/root.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/proc/root.c b/fs/proc/root.c index a9000e9cfee5..d6c3b416529b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -28,11 +28,12 @@ static int proc_test_super(struct super_block *sb, void *data) static int proc_set_super(struct super_block *sb, void *data) { - struct pid_namespace *ns; - - ns = (struct pid_namespace *)data; - sb->s_fs_info = get_pid_ns(ns); - return set_anon_super(sb, NULL); + int err = set_anon_super(sb, NULL); + if (!err) { + struct pid_namespace *ns = (struct pid_namespace *)data; + sb->s_fs_info = get_pid_ns(ns); + } + return err; } static struct dentry *proc_mount(struct file_system_type *fs_type, -- cgit v1.2.3 From b1c27ab3f93daede979f804afc38b189c2f17c60 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jun 2011 10:07:03 -0400 Subject: ubifs: split allocation of ubifs_info into a separate function preparation to ubifs sget() race fixes Signed-off-by: Al Viro --- fs/ubifs/super.c | 87 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index b5aeb5a8ebed..ddc3b02e8cf0 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1971,6 +1971,53 @@ static struct ubi_volume_desc *open_ubi(const char *name, int mode) return ERR_PTR(-EINVAL); } +static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) +{ + struct ubifs_info *c; + + c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); + if (c) { + spin_lock_init(&c->cnt_lock); + spin_lock_init(&c->cs_lock); + spin_lock_init(&c->buds_lock); + spin_lock_init(&c->space_lock); + spin_lock_init(&c->orphan_lock); + init_rwsem(&c->commit_sem); + mutex_init(&c->lp_mutex); + mutex_init(&c->tnc_mutex); + mutex_init(&c->log_mutex); + mutex_init(&c->mst_mutex); + mutex_init(&c->umount_mutex); + mutex_init(&c->bu_mutex); + mutex_init(&c->write_reserve_mutex); + init_waitqueue_head(&c->cmt_wq); + c->buds = RB_ROOT; + c->old_idx = RB_ROOT; + c->size_tree = RB_ROOT; + c->orph_tree = RB_ROOT; + INIT_LIST_HEAD(&c->infos_list); + INIT_LIST_HEAD(&c->idx_gc); + INIT_LIST_HEAD(&c->replay_list); + INIT_LIST_HEAD(&c->replay_buds); + INIT_LIST_HEAD(&c->uncat_list); + INIT_LIST_HEAD(&c->empty_list); + INIT_LIST_HEAD(&c->freeable_list); + INIT_LIST_HEAD(&c->frdi_idx_list); + INIT_LIST_HEAD(&c->unclean_leb_list); + INIT_LIST_HEAD(&c->old_buds); + INIT_LIST_HEAD(&c->orph_list); + INIT_LIST_HEAD(&c->orph_new); + c->no_chk_data_crc = 1; + + c->highest_inum = UBIFS_FIRST_INO; + c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; + + ubi_get_volume_info(ubi, &c->vi); + ubi_get_device_info(c->vi.ubi_num, &c->di); + } + return c; +} + static int ubifs_fill_super(struct super_block *sb, void *data, int silent) { struct ubi_volume_desc *ubi = sb->s_fs_info; @@ -1978,49 +2025,11 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) struct inode *root; int err; - c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); + c = alloc_ubifs_info(ubi); if (!c) return -ENOMEM; - spin_lock_init(&c->cnt_lock); - spin_lock_init(&c->cs_lock); - spin_lock_init(&c->buds_lock); - spin_lock_init(&c->space_lock); - spin_lock_init(&c->orphan_lock); - init_rwsem(&c->commit_sem); - mutex_init(&c->lp_mutex); - mutex_init(&c->tnc_mutex); - mutex_init(&c->log_mutex); - mutex_init(&c->mst_mutex); - mutex_init(&c->umount_mutex); - mutex_init(&c->bu_mutex); - mutex_init(&c->write_reserve_mutex); - init_waitqueue_head(&c->cmt_wq); - c->buds = RB_ROOT; - c->old_idx = RB_ROOT; - c->size_tree = RB_ROOT; - c->orph_tree = RB_ROOT; - INIT_LIST_HEAD(&c->infos_list); - INIT_LIST_HEAD(&c->idx_gc); - INIT_LIST_HEAD(&c->replay_list); - INIT_LIST_HEAD(&c->replay_buds); - INIT_LIST_HEAD(&c->uncat_list); - INIT_LIST_HEAD(&c->empty_list); - INIT_LIST_HEAD(&c->freeable_list); - INIT_LIST_HEAD(&c->frdi_idx_list); - INIT_LIST_HEAD(&c->unclean_leb_list); - INIT_LIST_HEAD(&c->old_buds); - INIT_LIST_HEAD(&c->orph_list); - INIT_LIST_HEAD(&c->orph_new); - c->no_chk_data_crc = 1; - c->vfs_sb = sb; - c->highest_inum = UBIFS_FIRST_INO; - c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; - - ubi_get_volume_info(ubi, &c->vi); - ubi_get_device_info(c->vi.ubi_num, &c->di); - /* Re-open the UBI device in read-write mode */ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); if (IS_ERR(c->ubi)) { -- cgit v1.2.3 From d251ed271d528afb407cc2ede30923e34cb209a5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jun 2011 10:24:33 -0400 Subject: ubifs: fix sget races * allocate ubifs_info in ->mount(), fill it enough for sb_test() and set ->s_fs_info to it in set() callback passed to sget(). * do *not* free it in ->put_super(); do that in ->kill_sb() after we'd done kill_anon_super(). * don't free it in ubifs_fill_super() either - deactivate_locked_super() done by caller when ubifs_fill_super() returns an error will take care of that sucker. * get rid of kludge with passing ubi to ubifs_fill_super() in ->s_fs_info; we only need it in alloc_ubifs_info(), so ubifs_fill_super() will need only ubifs_info. Which it will find in ->s_fs_info just fine, no need to reassign anything... As the result, sb_test() becomes safe to apply to all superblocks that can be found by sget() (and a kludge with temporary use of ->s_fs_info to store a pointer to very different structure goes away). Signed-off-by: Al Viro --- fs/ubifs/super.c | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index ddc3b02e8cf0..8c892c2d5300 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1848,7 +1848,6 @@ static void ubifs_put_super(struct super_block *sb) bdi_destroy(&c->bdi); ubi_close_volume(c->ubi); mutex_unlock(&c->umount_mutex); - kfree(c); } static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) @@ -2020,21 +2019,16 @@ static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) static int ubifs_fill_super(struct super_block *sb, void *data, int silent) { - struct ubi_volume_desc *ubi = sb->s_fs_info; - struct ubifs_info *c; + struct ubifs_info *c = sb->s_fs_info; struct inode *root; int err; - c = alloc_ubifs_info(ubi); - if (!c) - return -ENOMEM; - c->vfs_sb = sb; /* Re-open the UBI device in read-write mode */ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); if (IS_ERR(c->ubi)) { err = PTR_ERR(c->ubi); - goto out_free; + goto out; } /* @@ -2100,24 +2094,29 @@ out_bdi: bdi_destroy(&c->bdi); out_close: ubi_close_volume(c->ubi); -out_free: - kfree(c); +out: return err; } static int sb_test(struct super_block *sb, void *data) { - dev_t *dev = data; + struct ubifs_info *c1 = data; struct ubifs_info *c = sb->s_fs_info; - return c->vi.cdev == *dev; + return c->vi.cdev == c1->vi.cdev; +} + +static int sb_set(struct super_block *sb, void *data) +{ + sb->s_fs_info = data; + return set_anon_super(sb, NULL); } static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, const char *name, void *data) { struct ubi_volume_desc *ubi; - struct ubi_volume_info vi; + struct ubifs_info *c; struct super_block *sb; int err; @@ -2134,19 +2133,24 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, name, (int)PTR_ERR(ubi)); return ERR_CAST(ubi); } - ubi_get_volume_info(ubi, &vi); - dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); + c = alloc_ubifs_info(ubi); + if (!c) { + err = -ENOMEM; + goto out_close; + } + + dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); - sb = sget(fs_type, &sb_test, &set_anon_super, &vi.cdev); + sb = sget(fs_type, sb_test, sb_set, c); if (IS_ERR(sb)) { err = PTR_ERR(sb); - goto out_close; + kfree(c); } if (sb->s_root) { struct ubifs_info *c1 = sb->s_fs_info; - + kfree(c); /* A new mount point for already mounted UBIFS */ dbg_gen("this ubi volume is already mounted"); if (!!(flags & MS_RDONLY) != c1->ro_mount) { @@ -2155,11 +2159,6 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, } } else { sb->s_flags = flags; - /* - * Pass 'ubi' to 'fill_super()' in sb->s_fs_info where it is - * replaced by 'c'. - */ - sb->s_fs_info = ubi; err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (err) goto out_deact; @@ -2179,11 +2178,18 @@ out_close: return ERR_PTR(err); } +static void kill_ubifs_super(struct super_block *s) +{ + struct ubifs_info *c = s->s_fs_info; + kill_anon_super(s); + kfree(c); +} + static struct file_system_type ubifs_fs_type = { .name = "ubifs", .owner = THIS_MODULE, .mount = ubifs_mount, - .kill_sb = kill_anon_super, + .kill_sb = kill_ubifs_super, }; /* -- cgit v1.2.3 From dde194a64bb5c3fd05d965775dc92e8a4920a53a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jun 2011 16:01:21 -0400 Subject: afs: fix sget() races, close leak on umount * set ->s_fs_info in set() callback passed to sget() * allocate the thing and set it up enough for afs_test_super() before making it visible * have it freed in ->kill_sb() (current tree simply leaks it) * have ->put_super() leave ->s_fs_info->volume alone; it's too early for dropping it; do that from ->kill_sb() after having called kill_anon_super(). Signed-off-by: Al Viro --- fs/afs/super.c | 73 +++++++++++++++++++++++++--------------------------------- 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/fs/afs/super.c b/fs/afs/super.c index fb240e8766d6..b7d48d7eaa1e 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -31,8 +31,8 @@ static void afs_i_init_once(void *foo); static struct dentry *afs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data); +static void afs_kill_super(struct super_block *sb); static struct inode *afs_alloc_inode(struct super_block *sb); -static void afs_put_super(struct super_block *sb); static void afs_destroy_inode(struct inode *inode); static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); @@ -40,7 +40,7 @@ struct file_system_type afs_fs_type = { .owner = THIS_MODULE, .name = "afs", .mount = afs_mount, - .kill_sb = kill_anon_super, + .kill_sb = afs_kill_super, .fs_flags = 0, }; @@ -50,7 +50,6 @@ static const struct super_operations afs_super_ops = { .drop_inode = afs_drop_inode, .destroy_inode = afs_destroy_inode, .evict_inode = afs_evict_inode, - .put_super = afs_put_super, .show_options = generic_show_options, }; @@ -282,19 +281,25 @@ static int afs_parse_device_name(struct afs_mount_params *params, */ static int afs_test_super(struct super_block *sb, void *data) { - struct afs_mount_params *params = data; + struct afs_super_info *as1 = data; struct afs_super_info *as = sb->s_fs_info; - return as->volume == params->volume; + return as->volume == as1->volume; +} + +static int afs_set_super(struct super_block *sb, void *data) +{ + sb->s_fs_info = data; + return set_anon_super(sb, NULL); } /* * fill in the superblock */ -static int afs_fill_super(struct super_block *sb, void *data) +static int afs_fill_super(struct super_block *sb, + struct afs_mount_params *params) { - struct afs_mount_params *params = data; - struct afs_super_info *as = NULL; + struct afs_super_info *as = sb->s_fs_info; struct afs_fid fid; struct dentry *root = NULL; struct inode *inode = NULL; @@ -302,22 +307,11 @@ static int afs_fill_super(struct super_block *sb, void *data) _enter(""); - /* allocate a superblock info record */ - as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); - if (!as) { - _leave(" = -ENOMEM"); - return -ENOMEM; - } - - afs_get_volume(params->volume); - as->volume = params->volume; - /* fill in the superblock */ sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = AFS_FS_MAGIC; sb->s_op = &afs_super_ops; - sb->s_fs_info = as; sb->s_bdi = &as->volume->bdi; /* allocate the root inode and dentry */ @@ -326,7 +320,7 @@ static int afs_fill_super(struct super_block *sb, void *data) fid.unique = 1; inode = afs_iget(sb, params->key, &fid, NULL, NULL); if (IS_ERR(inode)) - goto error_inode; + return PTR_ERR(inode); if (params->autocell) set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags); @@ -342,16 +336,8 @@ static int afs_fill_super(struct super_block *sb, void *data) _leave(" = 0"); return 0; -error_inode: - ret = PTR_ERR(inode); - inode = NULL; error: iput(inode); - afs_put_volume(as->volume); - kfree(as); - - sb->s_fs_info = NULL; - _leave(" = %d", ret); return ret; } @@ -367,6 +353,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, struct afs_volume *vol; struct key *key; char *new_opts = kstrdup(options, GFP_KERNEL); + struct afs_super_info *as; int ret; _enter(",,%s,%p", dev_name, options); @@ -399,12 +386,22 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, ret = PTR_ERR(vol); goto error; } - params.volume = vol; + + /* allocate a superblock info record */ + as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); + if (!as) { + ret = -ENOMEM; + afs_put_volume(vol); + goto error; + } + as->volume = vol; /* allocate a deviceless superblock */ - sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); + sb = sget(fs_type, afs_test_super, afs_set_super, as); if (IS_ERR(sb)) { ret = PTR_ERR(sb); + afs_put_volume(vol); + kfree(as); goto error; } @@ -422,16 +419,16 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, } else { _debug("reuse"); ASSERTCMP(sb->s_flags, &, MS_ACTIVE); + afs_put_volume(vol); + kfree(as); } - afs_put_volume(params.volume); afs_put_cell(params.cell); kfree(new_opts); _leave(" = 0 [%p]", sb); return dget(sb->s_root); error: - afs_put_volume(params.volume); afs_put_cell(params.cell); key_put(params.key); kfree(new_opts); @@ -439,18 +436,12 @@ error: return ERR_PTR(ret); } -/* - * finish the unmounting process on the superblock - */ -static void afs_put_super(struct super_block *sb) +static void afs_kill_super(struct super_block *sb) { struct afs_super_info *as = sb->s_fs_info; - - _enter(""); - + kill_anon_super(sb); afs_put_volume(as->volume); - - _leave(""); + kfree(as); } /* -- cgit v1.2.3 From a685e08987d1edf1995b76511d4c98ea0e905377 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Jun 2011 21:13:01 -0400 Subject: Delay struct net freeing while there's a sysfs instance refering to it * new refcount in struct net, controlling actual freeing of the memory * new method in kobj_ns_type_operations (->drop_ns()) * ->current_ns() semantics change - it's supposed to be followed by corresponding ->drop_ns(). For struct net in case of CONFIG_NET_NS it bumps the new refcount; net_drop_ns() decrements it and calls net_free() if the last reference has been dropped. Method renamed to ->grab_current_ns(). * old net_free() callers call net_drop_ns() instead. * sysfs_exit_ns() is gone, along with a large part of callchain leading to it; now that the references stored in ->ns[...] stay valid we do not need to hunt them down and replace them with NULL. That fixes problems in sysfs_lookup() and sysfs_readdir(), along with getting rid of sb->s_instances abuse. Note that struct net *shutdown* logics has not changed - net_cleanup() is called exactly when it used to be called. The only thing postponed by having a sysfs instance refering to that struct net is actual freeing of memory occupied by struct net. Signed-off-by: Al Viro --- fs/sysfs/mount.c | 37 +++++++++++-------------------------- fs/sysfs/sysfs.h | 2 +- include/linux/kobject_ns.h | 10 ++++++---- include/linux/sysfs.h | 7 ------- include/net/net_namespace.h | 10 +++++++++- lib/kobject.c | 26 +++++++++----------------- net/core/net-sysfs.c | 23 +++++++++-------------- net/core/net_namespace.c | 12 ++++++++++-- 8 files changed, 55 insertions(+), 72 deletions(-) diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 266895783b47..e34f0d99ea4e 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -95,6 +95,14 @@ static int sysfs_set_super(struct super_block *sb, void *data) return error; } +static void free_sysfs_super_info(struct sysfs_super_info *info) +{ + int type; + for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) + kobj_ns_drop(type, info->ns[type]); + kfree(info); +} + static struct dentry *sysfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { @@ -108,11 +116,11 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, return ERR_PTR(-ENOMEM); for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) - info->ns[type] = kobj_ns_current(type); + info->ns[type] = kobj_ns_grab_current(type); sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info); if (IS_ERR(sb) || sb->s_fs_info != info) - kfree(info); + free_sysfs_super_info(info); if (IS_ERR(sb)) return ERR_CAST(sb); if (!sb->s_root) { @@ -131,12 +139,11 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, static void sysfs_kill_sb(struct super_block *sb) { struct sysfs_super_info *info = sysfs_info(sb); - /* Remove the superblock from fs_supers/s_instances * so we can't find it, before freeing sysfs_super_info. */ kill_anon_super(sb); - kfree(info); + free_sysfs_super_info(info); } static struct file_system_type sysfs_fs_type = { @@ -145,28 +152,6 @@ static struct file_system_type sysfs_fs_type = { .kill_sb = sysfs_kill_sb, }; -void sysfs_exit_ns(enum kobj_ns_type type, const void *ns) -{ - struct super_block *sb; - - mutex_lock(&sysfs_mutex); - spin_lock(&sb_lock); - list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { - struct sysfs_super_info *info = sysfs_info(sb); - /* - * If we see a superblock on the fs_supers/s_instances - * list the unmount has not completed and sb->s_fs_info - * points to a valid struct sysfs_super_info. - */ - /* Ignore superblocks with the wrong ns */ - if (info->ns[type] != ns) - continue; - info->ns[type] = NULL; - } - spin_unlock(&sb_lock); - mutex_unlock(&sysfs_mutex); -} - int __init sysfs_init(void) { int err = -ENOMEM; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 3d28af31d863..2ed2404f3113 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -136,7 +136,7 @@ struct sysfs_addrm_cxt { * instance). */ struct sysfs_super_info { - const void *ns[KOBJ_NS_TYPES]; + void *ns[KOBJ_NS_TYPES]; }; #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) extern struct sysfs_dirent sysfs_root; diff --git a/include/linux/kobject_ns.h b/include/linux/kobject_ns.h index 82cb5bf461fb..f66b065a8b5f 100644 --- a/include/linux/kobject_ns.h +++ b/include/linux/kobject_ns.h @@ -32,15 +32,17 @@ enum kobj_ns_type { /* * Callbacks so sysfs can determine namespaces - * @current_ns: return calling task's namespace + * @grab_current_ns: return a new reference to calling task's namespace * @netlink_ns: return namespace to which a sock belongs (right?) * @initial_ns: return the initial namespace (i.e. init_net_ns) + * @drop_ns: drops a reference to namespace */ struct kobj_ns_type_operations { enum kobj_ns_type type; - const void *(*current_ns)(void); + void *(*grab_current_ns)(void); const void *(*netlink_ns)(struct sock *sk); const void *(*initial_ns)(void); + void (*drop_ns)(void *); }; int kobj_ns_type_register(const struct kobj_ns_type_operations *ops); @@ -48,9 +50,9 @@ int kobj_ns_type_registered(enum kobj_ns_type type); const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent); const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj); -const void *kobj_ns_current(enum kobj_ns_type type); +void *kobj_ns_grab_current(enum kobj_ns_type type); const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk); const void *kobj_ns_initial(enum kobj_ns_type type); -void kobj_ns_exit(enum kobj_ns_type type, const void *ns); +void kobj_ns_drop(enum kobj_ns_type type, void *ns); #endif /* _LINUX_KOBJECT_NS_H */ diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index c3acda60eee0..e2696d76a599 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -177,9 +177,6 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); void sysfs_put(struct sysfs_dirent *sd); -/* Called to clear a ns tag when it is no longer valid */ -void sysfs_exit_ns(enum kobj_ns_type type, const void *tag); - int __must_check sysfs_init(void); #else /* CONFIG_SYSFS */ @@ -338,10 +335,6 @@ static inline void sysfs_put(struct sysfs_dirent *sd) { } -static inline void sysfs_exit_ns(int type, const void *tag) -{ -} - static inline int __must_check sysfs_init(void) { return 0; diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 2bf9ed9ef26b..aef430d779bd 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -35,8 +35,11 @@ struct netns_ipvs; #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS) struct net { + atomic_t passive; /* To decided when the network + * namespace should be freed. + */ atomic_t count; /* To decided when the network - * namespace should be freed. + * namespace should be shut down. */ #ifdef NETNS_REFCNT_DEBUG atomic_t use_count; /* To track references we @@ -154,6 +157,9 @@ int net_eq(const struct net *net1, const struct net *net2) { return net1 == net2; } + +extern void net_drop_ns(void *); + #else static inline struct net *get_net(struct net *net) @@ -175,6 +181,8 @@ int net_eq(const struct net *net1, const struct net *net2) { return 1; } + +#define net_drop_ns NULL #endif diff --git a/lib/kobject.c b/lib/kobject.c index 82dc34c095c2..640bd98a4c8a 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -948,14 +948,14 @@ const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj) } -const void *kobj_ns_current(enum kobj_ns_type type) +void *kobj_ns_grab_current(enum kobj_ns_type type) { - const void *ns = NULL; + void *ns = NULL; spin_lock(&kobj_ns_type_lock); if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && kobj_ns_ops_tbl[type]) - ns = kobj_ns_ops_tbl[type]->current_ns(); + ns = kobj_ns_ops_tbl[type]->grab_current_ns(); spin_unlock(&kobj_ns_type_lock); return ns; @@ -987,23 +987,15 @@ const void *kobj_ns_initial(enum kobj_ns_type type) return ns; } -/* - * kobj_ns_exit - invalidate a namespace tag - * - * @type: the namespace type (i.e. KOBJ_NS_TYPE_NET) - * @ns: the actual namespace being invalidated - * - * This is called when a tag is no longer valid. For instance, - * when a network namespace exits, it uses this helper to - * make sure no sb's sysfs_info points to the now-invalidated - * netns. - */ -void kobj_ns_exit(enum kobj_ns_type type, const void *ns) +void kobj_ns_drop(enum kobj_ns_type type, void *ns) { - sysfs_exit_ns(type, ns); + spin_lock(&kobj_ns_type_lock); + if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && + kobj_ns_ops_tbl[type] && kobj_ns_ops_tbl[type]->drop_ns) + kobj_ns_ops_tbl[type]->drop_ns(ns); + spin_unlock(&kobj_ns_type_lock); } - EXPORT_SYMBOL(kobject_get); EXPORT_SYMBOL(kobject_put); EXPORT_SYMBOL(kobject_del); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 11b98bc2aa8f..33d2a1fba131 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1179,9 +1179,14 @@ static void remove_queue_kobjects(struct net_device *net) #endif } -static const void *net_current_ns(void) +static void *net_grab_current_ns(void) { - return current->nsproxy->net_ns; + struct net *ns = current->nsproxy->net_ns; +#ifdef CONFIG_NET_NS + if (ns) + atomic_inc(&ns->passive); +#endif + return ns; } static const void *net_initial_ns(void) @@ -1196,22 +1201,13 @@ static const void *net_netlink_ns(struct sock *sk) struct kobj_ns_type_operations net_ns_type_operations = { .type = KOBJ_NS_TYPE_NET, - .current_ns = net_current_ns, + .grab_current_ns = net_grab_current_ns, .netlink_ns = net_netlink_ns, .initial_ns = net_initial_ns, + .drop_ns = net_drop_ns, }; EXPORT_SYMBOL_GPL(net_ns_type_operations); -static void net_kobj_ns_exit(struct net *net) -{ - kobj_ns_exit(KOBJ_NS_TYPE_NET, net); -} - -static struct pernet_operations kobj_net_ops = { - .exit = net_kobj_ns_exit, -}; - - #ifdef CONFIG_HOTPLUG static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) { @@ -1339,6 +1335,5 @@ EXPORT_SYMBOL(netdev_class_remove_file); int netdev_kobject_init(void) { kobj_ns_type_register(&net_ns_type_operations); - register_pernet_subsys(&kobj_net_ops); return class_register(&net_class); } diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 6c6b86d0da15..cdcbc3cb00a9 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -128,6 +128,7 @@ static __net_init int setup_net(struct net *net) LIST_HEAD(net_exit_list); atomic_set(&net->count, 1); + atomic_set(&net->passive, 1); #ifdef NETNS_REFCNT_DEBUG atomic_set(&net->use_count, 0); @@ -210,6 +211,13 @@ static void net_free(struct net *net) kmem_cache_free(net_cachep, net); } +void net_drop_ns(void *p) +{ + struct net *ns = p; + if (ns && atomic_dec_and_test(&ns->passive)) + net_free(ns); +} + struct net *copy_net_ns(unsigned long flags, struct net *old_net) { struct net *net; @@ -230,7 +238,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) } mutex_unlock(&net_mutex); if (rv < 0) { - net_free(net); + net_drop_ns(net); return ERR_PTR(rv); } return net; @@ -286,7 +294,7 @@ static void cleanup_net(struct work_struct *work) /* Finally it is safe to free my network namespace structure */ list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { list_del_init(&net->exit_list); - net_free(net); + net_drop_ns(net); } } static DECLARE_WORK(net_cleanup_work, cleanup_net); -- cgit v1.2.3 From b84bd27fe70206f9253c395958134e4e4b7e55f0 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Sun, 12 Jun 2011 08:22:08 +0200 Subject: HID: hid-multitouch: fix broken eGalax Since the inclusion of eGalax devices in 2.6.39, I've got some bug reports for 480d and other devices. The problem lies in the reports descriptors: eGalax supports both pen and fingers, and so the reports descriptors contained both. But hid-multitouch relies on them to detect the last item in each field to send the multitouch events. In 480d, the last item is not Y as it should but Pressure. That means that the fields are not aligned and X,Y are at 0,0 (the other touch coordinates of the report). With this patch, the detection is made only when the field ContactID has been detected inside the collection. There is still a problem with the detections of the range as stylus and fingers may not have the same min/max, but it's a start. Signed-off-by: Benjamin Tissoires Reviewed-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 57 ++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 8bc32a0fa00e..0b2dcd0ee591 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -64,6 +64,7 @@ struct mt_device { struct mt_class *mtclass; /* our mt device class */ unsigned last_field_index; /* last field index of the report */ unsigned last_slot_field; /* the last field of a slot */ + int last_mt_collection; /* last known mt-related collection */ __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ __u8 num_received; /* how many contacts we received */ __u8 num_expected; /* expected last contact index */ @@ -225,8 +226,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_X, field, cls->sn_move); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_GD_Y: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) @@ -237,8 +240,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_Y, field, cls->sn_move); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; } return 0; @@ -246,31 +251,40 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_UP_DIGITIZER: switch (usage->hid) { case HID_DG_INRANGE: - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONFIDENCE: - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONTACTID: input_mt_init_slots(hi->input, td->maxcontacts); td->last_slot_field = usage->hid; td->last_field_index = field->index; + td->last_mt_collection = usage->collection_index; return 1; case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, @@ -279,8 +293,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_height); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_TIPPRESSURE: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) @@ -292,16 +308,20 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, /* touchscreen emulation */ set_abs(hi->input, ABS_PRESSURE, field, cls->sn_pressure); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONTACTCOUNT: - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) + td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) + td->last_field_index = field->index; return -1; } /* let hid-input decide for the others */ @@ -516,6 +536,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) } td->mtclass = mtclass; td->inputmode = -1; + td->last_mt_collection = -1; hid_set_drvdata(hdev, td); ret = hid_parse(hdev); -- cgit v1.2.3 From 1fb74cda1b5e9c6207225fda5ef7504e815ce0e0 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Sun, 12 Jun 2011 22:44:10 -0400 Subject: jbd2: Remove obsolete parameters in the comments for some jbd2 functions credits isn't a parameter for jbd2_journal_get_write_access and jbd2_journal_get_undo_access. So remove the corresponding comments. Acked-by: Jan Kara Cc: Randy Dunlap Signed-off-by: Tao Ma Signed-off-by: "Theodore Ts'o" --- fs/jbd2/transaction.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 3eec82d32fd4..547b101049e5 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -814,7 +814,6 @@ out: * int jbd2_journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update. * @handle: transaction to add buffer modifications to * @bh: bh to be used for metadata writes - * @credits: variable that will receive credits for the buffer * * Returns an error code or 0 on success. * @@ -932,7 +931,6 @@ out: * non-rewindable consequences * @handle: transaction * @bh: buffer to undo - * @credits: store the number of taken credits here (if not NULL) * * Sometimes there is a need to distinguish between metadata which has * been committed to disk and that which has not. The ext3fs code uses -- cgit v1.2.3 From 54463a66b91cf491a7c9af612b0e310babc5fa24 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Jun 2011 08:32:06 +0200 Subject: ALSA: hda - Fix wrong auto-mute type for Acer Aspire-one The auto-mute setup for Acer Aspire-one with ALC268 was set wrongly during the clean-up of auto-mute function. Fixed now. Tested-by: Borislav Petkov Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 43fcfbd32847..61a774b3d3cb 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13316,9 +13316,8 @@ static void alc268_acer_lc_setup(struct hda_codec *codec) struct alc_spec *spec = codec->spec; spec->autocfg.hp_pins[0] = 0x15; spec->autocfg.speaker_pins[0] = 0x14; - spec->automute_mixer_nid[0] = 0x0f; spec->automute = 1; - spec->automute_mode = ALC_AUTOMUTE_MIXER; + spec->automute_mode = ALC_AUTOMUTE_AMP; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; -- cgit v1.2.3 From 2308f4add3de9f6c9c9f02e49461e94d84bb200a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 12 Jun 2011 13:02:43 -0700 Subject: ALSA: hda - Fix beep_device compilation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using static inline functions can reduce compilation messages and macro misuse. sound/pci/hda/patch_conexant.c: In function ‘patch_cxt5045’: sound/pci/hda/patch_conexant.c:1232:3: warning: statement with no effect Signed-off-by: Joe Perches Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index f1de1bac042c..4967eabe774e 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -50,7 +50,12 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); void snd_hda_detach_beep_device(struct hda_codec *codec); #else -#define snd_hda_attach_beep_device(...) 0 -#define snd_hda_detach_beep_device(...) +static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) +{ + return 0; +} +void snd_hda_detach_beep_device(struct hda_codec *codec) +{ +} #endif #endif -- cgit v1.2.3 From 8f4e0a18682d91abfad72ede3d3cb5f3ebdf54b4 Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Mon, 13 Jun 2011 09:06:57 +0200 Subject: IPVS netns exit causes crash in conntrack Quote from Patric Mc Hardy "This looks like nfnetlink.c excited and destroyed the nfnl socket, but ip_vs was still holding a reference to a conntrack. When the conntrack got destroyed it created a ctnetlink event, causing an oops in netlink_has_listeners when trying to use the destroyed nfnetlink socket." If nf_conntrack_netlink is loaded before ip_vs this is not a problem. This patch simply avoids calling ip_vs_conn_drop_conntrack() when netns is dying as suggested by Julian. Signed-off-by: Hans Schillstrom Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_conn.c | 10 +++++++++- net/netfilter/ipvs/ip_vs_core.c | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index bf28ac2fc99b..782db275ac53 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -776,8 +776,16 @@ static void ip_vs_conn_expire(unsigned long data) if (cp->control) ip_vs_control_del(cp); - if (cp->flags & IP_VS_CONN_F_NFCT) + if (cp->flags & IP_VS_CONN_F_NFCT) { ip_vs_conn_drop_conntrack(cp); + /* Do not access conntracks during subsys cleanup + * because nf_conntrack_find_get can not be used after + * conntrack cleanup for the net. + */ + smp_rmb(); + if (ipvs->enable) + ip_vs_conn_drop_conntrack(cp); + } ip_vs_pe_put(cp->pe); kfree(cp->pe_data); diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 55af2242bccd..24c28d238dcb 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1945,6 +1945,7 @@ static void __net_exit __ip_vs_dev_cleanup(struct net *net) { EnterFunction(2); net_ipvs(net)->enable = 0; /* Disable packet reception */ + smp_wmb(); __ip_vs_sync_cleanup(net); LeaveFunction(2); } -- cgit v1.2.3 From 08e8138adebdd511e0955e8d6c051904bb4082af Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 13 Jun 2011 10:42:49 +0200 Subject: block: Add __attribute__((format(printf...) and fix fallout Use the compiler to verify format strings and arguments. Fix fallout. Signed-off-by: Joe Perches Signed-off-by: Jens Axboe --- block/blk-throttle.c | 4 ++-- block/cfq-iosched.c | 11 ++++++----- include/linux/blktrace_api.h | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index a62be8d0dc1b..3689f833afdc 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -927,7 +927,7 @@ static int throtl_dispatch(struct request_queue *q) bio_list_init(&bio_list_on_stack); - throtl_log(td, "dispatch nr_queued=%lu read=%u write=%u", + throtl_log(td, "dispatch nr_queued=%d read=%u write=%u", total_nr_queued(td), td->nr_queued[READ], td->nr_queued[WRITE]); @@ -1204,7 +1204,7 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop) } queue_bio: - throtl_log_tg(td, tg, "[%c] bio. bdisp=%u sz=%u bps=%llu" + throtl_log_tg(td, tg, "[%c] bio. bdisp=%llu sz=%u bps=%llu" " iodisp=%u iops=%u queued=%d/%d", rw == READ ? 'R' : 'W', tg->bytes_disp[rw], bio->bi_size, tg->bps[rw], diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 545b8d4c829d..f3799432676d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -988,9 +988,10 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime, st->min_vdisktime); - cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u" - " sect=%u", used_sl, cfqq->slice_dispatch, charge, - iops_mode(cfqd), cfqq->nr_sectors); + cfq_log_cfqq(cfqq->cfqd, cfqq, + "sl_used=%u disp=%u charge=%u iops=%u sect=%lu", + used_sl, cfqq->slice_dispatch, charge, + iops_mode(cfqd), cfqq->nr_sectors); cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl, unaccounted_sl); cfq_blkiocg_set_start_empty_time(&cfqg->blkg); @@ -2023,8 +2024,8 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) */ if (sample_valid(cic->ttime_samples) && (cfqq->slice_end - jiffies < cic->ttime_mean)) { - cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%d", - cic->ttime_mean); + cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%lu", + cic->ttime_mean); return; } diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index b22fb0d3db0f..8c7c2de7631a 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -169,7 +169,8 @@ extern void blk_trace_shutdown(struct request_queue *); extern int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, struct block_device *bdev, struct blk_user_trace_setup *buts); -extern void __trace_note_message(struct blk_trace *, const char *fmt, ...); +extern __attribute__((format(printf, 2, 3))) +void __trace_note_message(struct blk_trace *, const char *fmt, ...); /** * blk_add_trace_msg - Add a (simple) message to the blktrace stream -- cgit v1.2.3 From d4c208b86b8be4254eba0e74071496e599f94639 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 13 Jun 2011 12:45:48 +0200 Subject: block: use the passed in @bdev when claiming if partno is zero 6b4517a791 (block: implement bd_claiming and claiming block) introduced claiming block to support O_EXCL blkdev opens properly. bd_start_claiming() looks up the part 0 bdev and starts claiming block. The function assumed that there is only one part 0 bdev and always used bdget_disk(disk, 0) to look it up; unfortunately, this isn't true for some drivers (floppy) which use multiple block devices to denote different operating parameters for the same physical device. There can be multiple part 0 bdev's for the same device number. This incorrect assumption caused the wrong bdev to be used during claiming leading to unbalanced bd_holders as reported in the following bug. https://bugzilla.kernel.org/show_bug.cgi?id=28522 This patch updates bd_start_claiming() such that it uses the bdev specified as argument if its partno is zero. Note that this means that different bdev's can be used for the same device and O_EXCL check can be effectively bypassed. It has always been broken that way and floppy is fortunately on its way out. Leave that breakage alone. Signed-off-by: Tejun Heo Reported-by: Alex Villacis Lasso Tested-by: Alex Villacis Lasso Cc: stable@kernel.org # >= v2.6.36 Signed-off-by: Jens Axboe --- fs/block_dev.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 1a2421f908f0..610e8e0b04b8 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -762,7 +762,19 @@ static struct block_device *bd_start_claiming(struct block_device *bdev, if (!disk) return ERR_PTR(-ENXIO); - whole = bdget_disk(disk, 0); + /* + * Normally, @bdev should equal what's returned from bdget_disk() + * if partno is 0; however, some drivers (floppy) use multiple + * bdev's for the same physical device and @bdev may be one of the + * aliases. Keep @bdev if partno is 0. This means claimer + * tracking is broken for those devices but it has always been that + * way. + */ + if (partno) + whole = bdget_disk(disk, 0); + else + whole = bdgrab(bdev); + module_put(disk->fops->owner); put_disk(disk); if (!whole) -- cgit v1.2.3 From 9d5ae7cd6cb9ead43336fec1094184d1dc740fbd Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Fri, 3 Jun 2011 20:24:03 +0000 Subject: omap: pandora: fix NAND support Commit d5ce2b65 "omap3630: nand: fix device size to work in polled mode" changed values for .devsize in nand platform data, now we have to pass NAND_BUSWIDTH_16 instead of '1' to select 16bit NAND. Update pandora's platform data accordingly, also specify appropriate transfer type. Signed-off-by: Grazvydas Ignotas Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap3pandora.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 1d10736c6d3c..a3d655c0a49b 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -86,7 +86,8 @@ static struct mtd_partition omap3pandora_nand_partitions[] = { static struct omap_nand_platform_data pandora_nand_data = { .cs = 0, - .devsize = 1, /* '0' for 8-bit, '1' for 16-bit device */ + .devsize = NAND_BUSWIDTH_16, + .xfer_type = NAND_OMAP_PREFETCH_DMA, .parts = omap3pandora_nand_partitions, .nr_parts = ARRAY_SIZE(omap3pandora_nand_partitions), }; -- cgit v1.2.3 From e3f88ae9960920598cad132c553019ee79ff3aca Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Mon, 13 Jun 2011 16:23:46 +0530 Subject: spi-pl022: Add missing return value update Return error on out of range cpsdvsr value. Acked-by: Linus Walleij Signed-off-by: Virupax Sadashivpetimath Signed-off-by: Grant Likely --- drivers/spi/amba-pl022.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 6a9e58dd36c7..d18ce9e946d8 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -1861,6 +1861,7 @@ static int pl022_setup(struct spi_device *spi) } if ((clk_freq.cpsdvsr < CPSDVR_MIN) || (clk_freq.cpsdvsr > CPSDVR_MAX)) { + status = -EINVAL; dev_err(&spi->dev, "cpsdvsr is configured incorrectly\n"); goto err_config_params; -- cgit v1.2.3 From ac08aedfa5d3de0dcb3825b598d16c2e57991f54 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 13 Jun 2011 11:28:50 -0400 Subject: Btrfs: check the return value from set_anon_super Al Viro noticed we weren't checking for set_anon_super failures. This adds the required checks. Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9f68c6898653..20c111b3fa0d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1312,7 +1312,9 @@ again: spin_lock_init(&root->cache_lock); init_waitqueue_head(&root->cache_wait); - set_anon_super(&root->anon_super, NULL); + ret = set_anon_super(&root->anon_super, NULL); + if (ret) + goto fail; if (btrfs_root_refs(&root->root_item) == 0) { ret = -ENOENT; -- cgit v1.2.3 From f4c44016218a6fce357715b9bbabbbbe1f69853c Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 13 Jun 2011 11:30:47 -0400 Subject: Btrfs: drop the delalloc_bytes check in shrink_delalloc Even when delalloc_bytes is zero, we may need to sleep while waiting for delalloc space. Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b42efc2ded51..1f61bf5b4960 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3314,10 +3314,6 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, if (reserved == 0) return 0; - /* nothing to shrink - nothing to reclaim */ - if (root->fs_info->delalloc_bytes == 0) - return 0; - max_reclaim = min(reserved, to_reclaim); while (loops < 1024) { -- cgit v1.2.3 From 6fdf658c9a0e51e6663f2769f6d310c2843a862b Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 13 Jun 2011 15:37:35 +0300 Subject: Bluetooth: Fix L2CAP security check With older userspace versions (using hciops) it might not have the key type to check if the key has sufficient security for any security level so it is necessary to check the return of hci_conn_auth to make sure the connection is authenticated Signed-off-by: Luiz Augusto von Dentz Acked-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3163330cd4f1..b9aa9862d14b 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -611,8 +611,8 @@ auth: if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; - hci_conn_auth(conn, sec_level, auth_type); - return 0; + if (!hci_conn_auth(conn, sec_level, auth_type)) + return 0; encrypt: if (conn->link_mode & HCI_LM_ENCRYPT) -- cgit v1.2.3 From e9c039052be59753e6bcc7c8b59763899dc1161c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 13 Jun 2011 19:05:58 +0100 Subject: ASoC: Remove unused and about to be broken SND_SOC_CUSTOM I/O bus This will be removed in -next so let's drop it from mainline as soon as we can in order to minimise surprises. Signed-off-by: Mark Brown --- include/sound/soc.h | 3 +-- sound/soc/soc-cache.c | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index f1de3e0c75bc..3a4bd3a3c68d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -248,8 +248,7 @@ typedef int (*hw_write_t)(void *,const char* ,int); extern struct snd_ac97_bus_ops soc_ac97_ops; enum snd_soc_control_type { - SND_SOC_CUSTOM = 1, - SND_SOC_I2C, + SND_SOC_I2C = 1, SND_SOC_SPI, }; diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index c005ceb70c9d..039b9532b270 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -409,9 +409,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; switch (control) { - case SND_SOC_CUSTOM: - break; - case SND_SOC_I2C: #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) codec->hw_write = (hw_write_t)i2c_master_send; -- cgit v1.2.3 From de1b794130b130e77ffa975bb58cb843744f9ae5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 13 Jun 2011 15:38:22 -0400 Subject: jbd2: Fix oops in jbd2_journal_remove_journal_head() jbd2_journal_remove_journal_head() can oops when trying to access journal_head returned by bh2jh(). This is caused for example by the following race: TASK1 TASK2 jbd2_journal_commit_transaction() ... processing t_forget list __jbd2_journal_refile_buffer(jh); if (!jh->b_transaction) { jbd_unlock_bh_state(bh); jbd2_journal_try_to_free_buffers() jbd2_journal_grab_journal_head(bh) jbd_lock_bh_state(bh) __journal_try_to_free_buffer() jbd2_journal_put_journal_head(jh) jbd2_journal_remove_journal_head(bh); jbd2_journal_put_journal_head() in TASK2 sees that b_jcount == 0 and buffer is not part of any transaction and thus frees journal_head before TASK1 gets to doing so. Note that even buffer_head can be released by try_to_free_buffers() after jbd2_journal_put_journal_head() which adds even larger opportunity for oops (but I didn't see this happen in reality). Fix the problem by making transactions hold their own journal_head reference (in b_jcount). That way we don't have to remove journal_head explicitely via jbd2_journal_remove_journal_head() and instead just remove journal_head when b_jcount drops to zero. The result of this is that [__]jbd2_journal_refile_buffer(), [__]jbd2_journal_unfile_buffer(), and __jdb2_journal_remove_checkpoint() can free journal_head which needs modification of a few callers. Also we have to be careful because once journal_head is removed, buffer_head might be freed as well. So we have to get our own buffer_head reference where it matters. Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" --- fs/jbd2/checkpoint.c | 28 +++++++++------- fs/jbd2/commit.c | 33 +++++++++++-------- fs/jbd2/journal.c | 91 ++++++++++++++++----------------------------------- fs/jbd2/transaction.c | 67 +++++++++++++++++++------------------ include/linux/jbd2.h | 2 -- 5 files changed, 99 insertions(+), 122 deletions(-) diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 6a79fd0a1a32..2c62c5aae82f 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -97,10 +97,14 @@ static int __try_to_free_cp_buf(struct journal_head *jh) if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh) && !buffer_write_io_error(bh)) { + /* + * Get our reference so that bh cannot be freed before + * we unlock it + */ + get_bh(bh); JBUFFER_TRACE(jh, "remove from checkpoint list"); ret = __jbd2_journal_remove_checkpoint(jh) + 1; jbd_unlock_bh_state(bh); - jbd2_journal_remove_journal_head(bh); BUFFER_TRACE(bh, "release"); __brelse(bh); } else { @@ -223,8 +227,8 @@ restart: spin_lock(&journal->j_list_lock); goto restart; } + get_bh(bh); if (buffer_locked(bh)) { - atomic_inc(&bh->b_count); spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); wait_on_buffer(bh); @@ -243,7 +247,6 @@ restart: */ released = __jbd2_journal_remove_checkpoint(jh); jbd_unlock_bh_state(bh); - jbd2_journal_remove_journal_head(bh); __brelse(bh); } @@ -284,7 +287,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, int ret = 0; if (buffer_locked(bh)) { - atomic_inc(&bh->b_count); + get_bh(bh); spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); wait_on_buffer(bh); @@ -316,12 +319,12 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, ret = 1; if (unlikely(buffer_write_io_error(bh))) ret = -EIO; + get_bh(bh); J_ASSERT_JH(jh, !buffer_jbddirty(bh)); BUFFER_TRACE(bh, "remove from checkpoint"); __jbd2_journal_remove_checkpoint(jh); spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); - jbd2_journal_remove_journal_head(bh); __brelse(bh); } else { /* @@ -554,7 +557,8 @@ int jbd2_cleanup_journal_tail(journal_t *journal) /* * journal_clean_one_cp_list * - * Find all the written-back checkpoint buffers in the given list and release them. + * Find all the written-back checkpoint buffers in the given list and + * release them. * * Called with the journal locked. * Called with j_list_lock held. @@ -663,8 +667,8 @@ out: * checkpoint lists. * * The function returns 1 if it frees the transaction, 0 otherwise. + * The function can free jh and bh. * - * This function is called with the journal locked. * This function is called with j_list_lock held. * This function is called with jbd_lock_bh_state(jh2bh(jh)) */ @@ -684,13 +688,14 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) } journal = transaction->t_journal; + JBUFFER_TRACE(jh, "removing from transaction"); __buffer_unlink(jh); jh->b_cp_transaction = NULL; + jbd2_journal_put_journal_head(jh); if (transaction->t_checkpoint_list != NULL || transaction->t_checkpoint_io_list != NULL) goto out; - JBUFFER_TRACE(jh, "transaction has no more buffers"); /* * There is one special case to worry about: if we have just pulled the @@ -701,10 +706,8 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) * The locking here around t_state is a bit sleazy. * See the comment at the end of jbd2_journal_commit_transaction(). */ - if (transaction->t_state != T_FINISHED) { - JBUFFER_TRACE(jh, "belongs to running/committing transaction"); + if (transaction->t_state != T_FINISHED) goto out; - } /* OK, that was the last buffer for the transaction: we can now safely remove this transaction from the log */ @@ -723,7 +726,6 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) wake_up(&journal->j_wait_logspace); ret = 1; out: - JBUFFER_TRACE(jh, "exit"); return ret; } @@ -742,6 +744,8 @@ void __jbd2_journal_insert_checkpoint(struct journal_head *jh, J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh))); J_ASSERT_JH(jh, jh->b_cp_transaction == NULL); + /* Get reference for checkpointing transaction */ + jbd2_journal_grab_journal_head(jh2bh(jh)); jh->b_cp_transaction = transaction; if (!transaction->t_checkpoint_list) { diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 7f21cf3aaf92..eef6979821a4 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -848,10 +848,16 @@ restart_loop: while (commit_transaction->t_forget) { transaction_t *cp_transaction; struct buffer_head *bh; + int try_to_free = 0; jh = commit_transaction->t_forget; spin_unlock(&journal->j_list_lock); bh = jh2bh(jh); + /* + * Get a reference so that bh cannot be freed before we are + * done with it. + */ + get_bh(bh); jbd_lock_bh_state(bh); J_ASSERT_JH(jh, jh->b_transaction == commit_transaction); @@ -914,28 +920,27 @@ restart_loop: __jbd2_journal_insert_checkpoint(jh, commit_transaction); if (is_journal_aborted(journal)) clear_buffer_jbddirty(bh); - JBUFFER_TRACE(jh, "refile for checkpoint writeback"); - __jbd2_journal_refile_buffer(jh); - jbd_unlock_bh_state(bh); } else { J_ASSERT_BH(bh, !buffer_dirty(bh)); - /* The buffer on BJ_Forget list and not jbddirty means + /* + * The buffer on BJ_Forget list and not jbddirty means * it has been freed by this transaction and hence it * could not have been reallocated until this * transaction has committed. *BUT* it could be * reallocated once we have written all the data to * disk and before we process the buffer on BJ_Forget - * list. */ - JBUFFER_TRACE(jh, "refile or unfile freed buffer"); - __jbd2_journal_refile_buffer(jh); - if (!jh->b_transaction) { - jbd_unlock_bh_state(bh); - /* needs a brelse */ - jbd2_journal_remove_journal_head(bh); - release_buffer_page(bh); - } else - jbd_unlock_bh_state(bh); + * list. + */ + if (!jh->b_next_transaction) + try_to_free = 1; } + JBUFFER_TRACE(jh, "refile or unfile buffer"); + __jbd2_journal_refile_buffer(jh); + jbd_unlock_bh_state(bh); + if (try_to_free) + release_buffer_page(bh); /* Drops bh reference */ + else + __brelse(bh); cond_resched_lock(&journal->j_list_lock); } spin_unlock(&journal->j_list_lock); diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 9a7826990304..0dfa5b598e68 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -2078,10 +2078,9 @@ static void journal_free_journal_head(struct journal_head *jh) * When a buffer has its BH_JBD bit set it is immune from being released by * core kernel code, mainly via ->b_count. * - * A journal_head may be detached from its buffer_head when the journal_head's - * b_transaction, b_cp_transaction and b_next_transaction pointers are NULL. - * Various places in JBD call jbd2_journal_remove_journal_head() to indicate that the - * journal_head can be dropped if needed. + * A journal_head is detached from its buffer_head when the journal_head's + * b_jcount reaches zero. Running transaction (b_transaction) and checkpoint + * transaction (b_cp_transaction) hold their references to b_jcount. * * Various places in the kernel want to attach a journal_head to a buffer_head * _before_ attaching the journal_head to a transaction. To protect the @@ -2094,17 +2093,16 @@ static void journal_free_journal_head(struct journal_head *jh) * (Attach a journal_head if needed. Increments b_jcount) * struct journal_head *jh = jbd2_journal_add_journal_head(bh); * ... + * (Get another reference for transaction) + * jbd2_journal_grab_journal_head(bh); * jh->b_transaction = xxx; + * (Put original reference) * jbd2_journal_put_journal_head(jh); - * - * Now, the journal_head's b_jcount is zero, but it is safe from being released - * because it has a non-zero b_transaction. */ /* * Give a buffer_head a journal_head. * - * Doesn't need the journal lock. * May sleep. */ struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh) @@ -2168,61 +2166,29 @@ static void __journal_remove_journal_head(struct buffer_head *bh) struct journal_head *jh = bh2jh(bh); J_ASSERT_JH(jh, jh->b_jcount >= 0); - - get_bh(bh); - if (jh->b_jcount == 0) { - if (jh->b_transaction == NULL && - jh->b_next_transaction == NULL && - jh->b_cp_transaction == NULL) { - J_ASSERT_JH(jh, jh->b_jlist == BJ_None); - J_ASSERT_BH(bh, buffer_jbd(bh)); - J_ASSERT_BH(bh, jh2bh(jh) == bh); - BUFFER_TRACE(bh, "remove journal_head"); - if (jh->b_frozen_data) { - printk(KERN_WARNING "%s: freeing " - "b_frozen_data\n", - __func__); - jbd2_free(jh->b_frozen_data, bh->b_size); - } - if (jh->b_committed_data) { - printk(KERN_WARNING "%s: freeing " - "b_committed_data\n", - __func__); - jbd2_free(jh->b_committed_data, bh->b_size); - } - bh->b_private = NULL; - jh->b_bh = NULL; /* debug, really */ - clear_buffer_jbd(bh); - __brelse(bh); - journal_free_journal_head(jh); - } else { - BUFFER_TRACE(bh, "journal_head was locked"); - } + J_ASSERT_JH(jh, jh->b_transaction == NULL); + J_ASSERT_JH(jh, jh->b_next_transaction == NULL); + J_ASSERT_JH(jh, jh->b_cp_transaction == NULL); + J_ASSERT_JH(jh, jh->b_jlist == BJ_None); + J_ASSERT_BH(bh, buffer_jbd(bh)); + J_ASSERT_BH(bh, jh2bh(jh) == bh); + BUFFER_TRACE(bh, "remove journal_head"); + if (jh->b_frozen_data) { + printk(KERN_WARNING "%s: freeing b_frozen_data\n", __func__); + jbd2_free(jh->b_frozen_data, bh->b_size); } + if (jh->b_committed_data) { + printk(KERN_WARNING "%s: freeing b_committed_data\n", __func__); + jbd2_free(jh->b_committed_data, bh->b_size); + } + bh->b_private = NULL; + jh->b_bh = NULL; /* debug, really */ + clear_buffer_jbd(bh); + journal_free_journal_head(jh); } /* - * jbd2_journal_remove_journal_head(): if the buffer isn't attached to a transaction - * and has a zero b_jcount then remove and release its journal_head. If we did - * see that the buffer is not used by any transaction we also "logically" - * decrement ->b_count. - * - * We in fact take an additional increment on ->b_count as a convenience, - * because the caller usually wants to do additional things with the bh - * after calling here. - * The caller of jbd2_journal_remove_journal_head() *must* run __brelse(bh) at some - * time. Once the caller has run __brelse(), the buffer is eligible for - * reaping by try_to_free_buffers(). - */ -void jbd2_journal_remove_journal_head(struct buffer_head *bh) -{ - jbd_lock_bh_journal_head(bh); - __journal_remove_journal_head(bh); - jbd_unlock_bh_journal_head(bh); -} - -/* - * Drop a reference on the passed journal_head. If it fell to zero then try to + * Drop a reference on the passed journal_head. If it fell to zero then * release the journal_head from the buffer_head. */ void jbd2_journal_put_journal_head(struct journal_head *jh) @@ -2232,11 +2198,12 @@ void jbd2_journal_put_journal_head(struct journal_head *jh) jbd_lock_bh_journal_head(bh); J_ASSERT_JH(jh, jh->b_jcount > 0); --jh->b_jcount; - if (!jh->b_jcount && !jh->b_transaction) { + if (!jh->b_jcount) { __journal_remove_journal_head(bh); + jbd_unlock_bh_journal_head(bh); __brelse(bh); - } - jbd_unlock_bh_journal_head(bh); + } else + jbd_unlock_bh_journal_head(bh); } /* diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 547b101049e5..2d7109414cdd 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -30,6 +30,7 @@ #include static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); +static void __jbd2_journal_unfile_buffer(struct journal_head *jh); /* * jbd2_get_transaction: obtain a new transaction_t object. @@ -764,7 +765,6 @@ repeat: if (!jh->b_transaction) { JBUFFER_TRACE(jh, "no transaction"); J_ASSERT_JH(jh, !jh->b_next_transaction); - jh->b_transaction = transaction; JBUFFER_TRACE(jh, "file as BJ_Reserved"); spin_lock(&journal->j_list_lock); __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved); @@ -895,8 +895,6 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh) * committed and so it's safe to clear the dirty bit. */ clear_buffer_dirty(jh2bh(jh)); - jh->b_transaction = transaction; - /* first access by this transaction */ jh->b_modified = 0; @@ -1230,8 +1228,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) __jbd2_journal_file_buffer(jh, transaction, BJ_Forget); } else { __jbd2_journal_unfile_buffer(jh); - jbd2_journal_remove_journal_head(bh); - __brelse(bh); if (!buffer_jbd(bh)) { spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); @@ -1554,19 +1550,32 @@ void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh) mark_buffer_dirty(bh); /* Expose it to the VM */ } -void __jbd2_journal_unfile_buffer(struct journal_head *jh) +/* + * Remove buffer from all transactions. + * + * Called with bh_state lock and j_list_lock + * + * jh and bh may be already freed when this function returns. + */ +static void __jbd2_journal_unfile_buffer(struct journal_head *jh) { __jbd2_journal_temp_unlink_buffer(jh); jh->b_transaction = NULL; + jbd2_journal_put_journal_head(jh); } void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh) { - jbd_lock_bh_state(jh2bh(jh)); + struct buffer_head *bh = jh2bh(jh); + + /* Get reference so that buffer cannot be freed before we unlock it */ + get_bh(bh); + jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); __jbd2_journal_unfile_buffer(jh); spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(jh2bh(jh)); + jbd_unlock_bh_state(bh); + __brelse(bh); } /* @@ -1593,8 +1602,6 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) if (jh->b_jlist == BJ_None) { JBUFFER_TRACE(jh, "remove from checkpoint list"); __jbd2_journal_remove_checkpoint(jh); - jbd2_journal_remove_journal_head(bh); - __brelse(bh); } } spin_unlock(&journal->j_list_lock); @@ -1657,7 +1664,6 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal, /* * We take our own ref against the journal_head here to avoid * having to add tons of locking around each instance of - * jbd2_journal_remove_journal_head() and * jbd2_journal_put_journal_head(). */ jh = jbd2_journal_grab_journal_head(bh); @@ -1695,10 +1701,9 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) int may_free = 1; struct buffer_head *bh = jh2bh(jh); - __jbd2_journal_unfile_buffer(jh); - if (jh->b_cp_transaction) { JBUFFER_TRACE(jh, "on running+cp transaction"); + __jbd2_journal_temp_unlink_buffer(jh); /* * We don't want to write the buffer anymore, clear the * bit so that we don't confuse checks in @@ -1709,8 +1714,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) may_free = 0; } else { JBUFFER_TRACE(jh, "on running transaction"); - jbd2_journal_remove_journal_head(bh); - __brelse(bh); + __jbd2_journal_unfile_buffer(jh); } return may_free; } @@ -1988,6 +1992,8 @@ void __jbd2_journal_file_buffer(struct journal_head *jh, if (jh->b_transaction) __jbd2_journal_temp_unlink_buffer(jh); + else + jbd2_journal_grab_journal_head(bh); jh->b_transaction = transaction; switch (jlist) { @@ -2039,9 +2045,10 @@ void jbd2_journal_file_buffer(struct journal_head *jh, * already started to be used by a subsequent transaction, refile the * buffer on that transaction's metadata list. * - * Called under journal->j_list_lock - * + * Called under j_list_lock * Called under jbd_lock_bh_state(jh2bh(jh)) + * + * jh and bh may be already free when this function returns */ void __jbd2_journal_refile_buffer(struct journal_head *jh) { @@ -2065,6 +2072,11 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh) was_dirty = test_clear_buffer_jbddirty(bh); __jbd2_journal_temp_unlink_buffer(jh); + /* + * We set b_transaction here because b_next_transaction will inherit + * our jh reference and thus __jbd2_journal_file_buffer() must not + * take a new one. + */ jh->b_transaction = jh->b_next_transaction; jh->b_next_transaction = NULL; if (buffer_freed(bh)) @@ -2081,30 +2093,21 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh) } /* - * For the unlocked version of this call, also make sure that any - * hanging journal_head is cleaned up if necessary. - * - * __jbd2_journal_refile_buffer is usually called as part of a single locked - * operation on a buffer_head, in which the caller is probably going to - * be hooking the journal_head onto other lists. In that case it is up - * to the caller to remove the journal_head if necessary. For the - * unlocked jbd2_journal_refile_buffer call, the caller isn't going to be - * doing anything else to the buffer so we need to do the cleanup - * ourselves to avoid a jh leak. - * - * *** The journal_head may be freed by this call! *** + * __jbd2_journal_refile_buffer() with necessary locking added. We take our + * bh reference so that we can safely unlock bh. + * + * The jh and bh may be freed by this call. */ void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh) { struct buffer_head *bh = jh2bh(jh); + /* Get reference so that buffer cannot be freed before we unlock it */ + get_bh(bh); jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); - __jbd2_journal_refile_buffer(jh); jbd_unlock_bh_state(bh); - jbd2_journal_remove_journal_head(bh); - spin_unlock(&journal->j_list_lock); __brelse(bh); } diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 4ecb7b16b278..d087c2e7b2aa 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1024,7 +1024,6 @@ struct journal_s /* Filing buffers */ extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *); -extern void __jbd2_journal_unfile_buffer(struct journal_head *); extern void __jbd2_journal_refile_buffer(struct journal_head *); extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *); extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); @@ -1165,7 +1164,6 @@ extern void jbd2_journal_release_jbd_inode(journal_t *journal, struct jbd2_in */ struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh); struct journal_head *jbd2_journal_grab_journal_head(struct buffer_head *bh); -void jbd2_journal_remove_journal_head(struct buffer_head *bh); void jbd2_journal_put_journal_head(struct journal_head *jh); /* -- cgit v1.2.3 From cd51875d53ae1459a2b09b4338166a218c0635a7 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 9 Jun 2011 12:58:53 +0400 Subject: CIFS: Fix sparse error cifs_sb_master_tlink was declared as inline, but without a definition. Remove the declaration and move the definition up. Signed-off-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bb659eb73810..9190018f97e1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2149,7 +2149,10 @@ cifs_put_tlink(struct tcon_link *tlink) } static inline struct tcon_link * -cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb); +cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb) +{ + return cifs_sb->master_tlink; +} static int compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) @@ -3484,12 +3487,6 @@ out: return tcon; } -static inline struct tcon_link * -cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb) -{ - return cifs_sb->master_tlink; -} - struct cifs_tcon * cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) { -- cgit v1.2.3 From 7fdbaa1b8daa1009b705985b903e3d2ebccad456 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 10 Jun 2011 16:14:57 -0400 Subject: cifs: don't allow cifs_reconnect to exit with NULL socket pointer It's possible for the following set of events to happen: cifsd calls cifs_reconnect which reconnects the socket. A userspace process then calls cifs_negotiate_protocol to handle the NEGOTIATE and gets a reply. But, while processing the reply, cifsd calls cifs_reconnect again. Eventually the GlobalMid_Lock is dropped and the reply from the earlier NEGOTIATE completes and the tcpStatus is set to CifsGood. cifs_reconnect then goes through and closes the socket and sets the pointer to zero, but because the status is now CifsGood, the new socket is not created and cifs_reconnect exits with the socket pointer set to NULL. Fix this by only setting the tcpStatus to CifsGood if the tcpStatus is CifsNeedNegotiate, and by making sure that generic_ip_connect is always called at least once in cifs_reconnect. Note that this is not a perfect fix for this issue. It's still possible that the NEGOTIATE reply is handled after the socket has been closed and reconnected. In that case, the socket state will look correct but it no NEGOTIATE was performed on it be for the wrong socket. In that situation though the server should just shut down the socket on the next attempted send, rather than causing the oops that occurs today. Cc: # .38.x: fd88ce9: [CIFS] cifs: clarify the meaning of tcpStatus == CifsGood Reported-and-Tested-by: Ben Greear Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9190018f97e1..fa73e2a51cf2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -152,7 +152,7 @@ cifs_reconnect(struct TCP_Server_Info *server) mid_entry->callback(mid_entry); } - while (server->tcpStatus == CifsNeedReconnect) { + do { try_to_freeze(); /* we should try only the port we connected to before */ @@ -167,7 +167,7 @@ cifs_reconnect(struct TCP_Server_Info *server) server->tcpStatus = CifsNeedNegotiate; spin_unlock(&GlobalMid_Lock); } - } + } while (server->tcpStatus == CifsNeedReconnect); return rc; } @@ -3374,7 +3374,7 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) } if (rc == 0) { spin_lock(&GlobalMid_Lock); - if (server->tcpStatus != CifsExiting) + if (server->tcpStatus == CifsNeedNegotiate) server->tcpStatus = CifsGood; else rc = -EHOSTDOWN; -- cgit v1.2.3 From 3e715513643f0207c8f3c22010b54954cd697474 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 13 Jun 2011 11:50:41 -0400 Subject: cifs: show sec= option in /proc/mounts Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 989442dcfb45..e9def996e383 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -352,6 +352,37 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) } } +static void +cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) +{ + seq_printf(s, ",sec="); + + switch (server->secType) { + case LANMAN: + seq_printf(s, "lanman"); + break; + case NTLMv2: + seq_printf(s, "ntlmv2"); + break; + case NTLM: + seq_printf(s, "ntlm"); + break; + case Kerberos: + seq_printf(s, "krb5"); + break; + case RawNTLMSSP: + seq_printf(s, "ntlmssp"); + break; + default: + /* shouldn't ever happen */ + seq_printf(s, "unknown"); + break; + } + + if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + seq_printf(s, "i"); +} + /* * cifs_show_options() is for displaying mount options in /proc/mounts. * Not all settable options are displayed but most of the important @@ -365,6 +396,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) struct sockaddr *srcaddr; srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; + cifs_show_security(s, tcon->ses->server); + seq_printf(s, ",unc=%s", tcon->treeName); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) -- cgit v1.2.3 From 8d1bca328b7c17af33bcf966d799c556ecbf370f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 11 Jun 2011 21:17:10 -0400 Subject: cifs: correctly handle NULL tcon pointer in CIFSTCon Long ago (in commit 00e485b0), I added some code to handle share-level passwords in CIFSTCon. That code ignored the fact that it's legit to pass in a NULL tcon pointer when connecting to the IPC$ share on the server. This wasn't really a problem until recently as we only called CIFSTCon this way when the server returned -EREMOTE. With the introduction of commit c1508ca2 however, it gets called this way on every mount, causing an oops when share-level security is in effect. Fix this by simply treating a NULL tcon pointer as if user-level security were in effect. I'm not aware of any servers that protect the IPC$ share with a specific password anyway. Also, add a comment to the top of CIFSTCon to ensure that we don't make the same mistake again. Cc: Reported-by: Martijn Uffing Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index fa73e2a51cf2..12cf72dd0c42 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3174,6 +3174,10 @@ out: return rc; } +/* + * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon + * pointer may be NULL. + */ int CIFSTCon(unsigned int xid, struct cifs_ses *ses, const char *tree, struct cifs_tcon *tcon, @@ -3208,7 +3212,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, pSMB->AndXCommand = 0xFF; pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); bcc_ptr = &pSMB->Password[0]; - if ((ses->server->sec_mode) & SECMODE_USER) { + if (!tcon || (ses->server->sec_mode & SECMODE_USER)) { pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ *bcc_ptr = 0; /* password is null byte */ bcc_ptr++; /* skip password */ -- cgit v1.2.3 From b9cabe52c27cf834137f3aaa46da23bcf32284e8 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 12 Jun 2011 04:28:16 +0000 Subject: ieee802154: Don't leak memory in ieee802154_nl_fill_phy In net/ieee802154/nl-phy.c::ieee802154_nl_fill_phy() I see two small issues. 1) If the allocation of 'buf' fails we may just as well return -EMSGSIZE directly rather than jumping to 'out:' and do a pointless kfree(0). 2) We do not free 'buf' unless we jump to one of the error labels and this leaks memory. This patch should address both. Signed-off-by: Jesper Juhl Acked-by: Dmitry Eremin-Solenikov Signed-off-by: David S. Miller --- net/ieee802154/nl-phy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index ed0eab39f531..02548b292b53 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -44,7 +44,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid, pr_debug("%s\n", __func__); if (!buf) - goto out; + return -EMSGSIZE; hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, IEEE802154_LIST_PHY); @@ -65,6 +65,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid, pages * sizeof(uint32_t), buf); mutex_unlock(&phy->pib_lock); + kfree(buf); return genlmsg_end(msg, hdr); nla_put_failure: -- cgit v1.2.3 From 1ffde03d2aa112750468cff07efc9e0a504517dd Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 12 Jun 2011 09:40:49 +0000 Subject: 3c503: fix broken IRQ autoprobing Fix broken IRQ autoprobing in 3c503 driver: - improper IRQ freeing (does not free IRQs causes WARN) - missing break when an working IRQ is found The driver works with this patch. Signed-off-by: Ondrej Zary Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/3c503.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index d84f6e8903a5..5b732988d493 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -412,7 +412,7 @@ el2_open(struct net_device *dev) outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR); outb_p(0x00, E33G_IDCFR); msleep(1); - free_irq(*irqp, el2_probe_interrupt); + free_irq(*irqp, &seen); if (!seen) continue; @@ -422,6 +422,7 @@ el2_open(struct net_device *dev) continue; if (retval < 0) goto err_disable; + break; } while (*++irqp); if (*irqp == 0) { -- cgit v1.2.3 From 2c53b436a30867eb6b47dd7bab23ba638d1fb0d2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 13 Jun 2011 15:29:59 -0700 Subject: Linux 3.0-rc3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 72c0e321f2da..badb9239e2bb 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Sneaky Weasel # *DOCUMENTATION* -- cgit v1.2.3 From 9281b2a2e2e02ad4bcc2fdd11797709b815d5f8e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 13 Jun 2011 08:17:36 +0000 Subject: net/hplance: hplance_init() should be __devinit WARNING: vmlinux.o(.devinit.text+0x253e): Section mismatch in reference from the function hplance_init_one() to the function .init.text:hplance_init() The forward declaration had the correct attribute, but the actual function definition hadn't. Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/hplance.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index b6060f7538df..a900d5bf2948 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -135,7 +135,7 @@ static void __devexit hplance_remove_one(struct dio_dev *d) } /* Initialise a single lance board at the given DIO device */ -static void __init hplance_init(struct net_device *dev, struct dio_dev *d) +static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d) { unsigned long va = (d->resource.start + DIO_VIRADDRBASE); struct hplance_private *lp; -- cgit v1.2.3 From 773e9b442693b250aa6c452cb0cf5a9343f51cef Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 7 Jun 2011 20:57:14 -0700 Subject: ceph: fix page alignment corrections dd if=/dev/urandom of=/mnt/fs_depot/dd10 bs=500 seek=8388 count=1 dd if=/mnt/fs_depot/dd10 of=/root/dd10out bs=500 skip=8388 count=1 Reported-by: Henry C Chang Signed-off-by: Sage Weil --- fs/ceph/file.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 9542f07d0b93..2be0f35afdfb 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -290,7 +290,6 @@ static int striped_read(struct inode *inode, struct ceph_inode_info *ci = ceph_inode(inode); u64 pos, this_len; int io_align, page_align; - int page_off = off & ~PAGE_CACHE_MASK; /* first byte's offset in page */ int left, pages_left; int read; struct page **page_pos; @@ -326,12 +325,11 @@ more: ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : ""); if (ret > 0) { - int didpages = - ((pos & ~PAGE_CACHE_MASK) + ret) >> PAGE_CACHE_SHIFT; + int didpages = (page_align + ret) >> PAGE_CACHE_SHIFT; if (read < pos - off) { dout(" zero gap %llu to %llu\n", off + read, pos); - ceph_zero_page_vector_range(page_off + read, + ceph_zero_page_vector_range(page_align + read, pos - off - read, pages); } pos += ret; @@ -356,7 +354,7 @@ more: left = inode->i_size - pos; dout("zero tail %d\n", left); - ceph_zero_page_vector_range(page_off + read, left, + ceph_zero_page_vector_range(page_align + read, left, pages); read += left; } -- cgit v1.2.3 From 9bb0ce2b0b734f3325ea5cd6b351856eeac94f78 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 13 Jun 2011 16:20:18 -0700 Subject: libceph: fix page calculation for non-page-aligned io Set the page count correctly for non-page-aligned IO. We were already doing this correctly for alignment, but not the page count. Fixes DIRECT_IO writes from unaligned pages. Signed-off-by: Sage Weil --- net/ceph/osd_client.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 9cb627a4073a..7330c2757c0c 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -477,8 +477,9 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, calc_layout(osdc, vino, layout, off, plen, req, ops); req->r_file_layout = *layout; /* keep a copy */ - /* in case it differs from natural alignment that calc_layout - filled in for us */ + /* in case it differs from natural (file) alignment that + calc_layout filled in for us */ + req->r_num_pages = calc_pages_for(page_align, *plen); req->r_page_alignment = page_align; ceph_osdc_build_request(req, off, plen, ops, @@ -2027,8 +2028,9 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, int want = calc_pages_for(req->r_page_alignment, data_len); if (unlikely(req->r_num_pages < want)) { - pr_warning("tid %lld reply %d > expected %d pages\n", - tid, want, m->nr_pages); + pr_warning("tid %lld reply has %d bytes %d pages, we" + " had only %d pages ready\n", tid, data_len, + want, req->r_num_pages); *skip = 1; ceph_msg_put(m); m = NULL; -- cgit v1.2.3 From d7f124f129a6aea99938e0d4172c741b56fefeda Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 13 Jun 2011 16:22:18 -0700 Subject: ceph: fix sync and dio writes across stripe boundaries We were iterating across stripe boundaries properly, but not moving the write buffer pointer forward. This caused us to rewrite the same data after the break. Fix by adjusting the data pointer forward, and recalculating the io and buffer alignment after the break. Signed-off-by: Sage Weil --- fs/ceph/file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 2be0f35afdfb..4698a5c553dc 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -476,9 +476,6 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, else pos = *offset; - io_align = pos & ~PAGE_MASK; - buf_align = (unsigned long)data & ~PAGE_MASK; - ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left); if (ret < 0) return ret; @@ -502,6 +499,8 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, * boundary. this isn't atomic, unfortunately. :( */ more: + io_align = pos & ~PAGE_MASK; + buf_align = (unsigned long)data & ~PAGE_MASK; len = left; if (file->f_flags & O_DIRECT) { /* write from beginning of first page, regardless of @@ -591,6 +590,7 @@ out: pos += len; written += len; left -= len; + data += written; if (left) goto more; -- cgit v1.2.3 From 96bf8bd1c953c3b9d89eac9f13dfdbf5e580060f Mon Sep 17 00:00:00 2001 From: Greg Dietsche Date: Mon, 13 Jun 2011 09:40:38 -0500 Subject: savage: remove unnecessary if statement the code always returns ret regardless, so if(ret) check is unnecessary. v2: fixed up the spelling. Signed-off-by: Greg Dietsche Reviewed-by: Nicolas Kaiser Signed-off-by: Dave Airlie --- drivers/gpu/drm/savage/savage_bci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index bf5f83ea14fe..cb1ee4e0050a 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -647,9 +647,6 @@ int savage_driver_firstopen(struct drm_device *dev) ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE, _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, &dev_priv->aperture); - if (ret) - return ret; - return ret; } -- cgit v1.2.3 From 82ba3fef67829813d0ed4c45231235084a07f081 Mon Sep 17 00:00:00 2001 From: Jay Estabrook Date: Thu, 9 Jun 2011 18:18:39 -0400 Subject: alpha/drm: Cleanup Alpha support in DRM generic code Remove an obsolete Alpha adjustment, and modify another, to go with the current Alpha architecture support. Signed-off-by: Jay Estabrook Tested-by: Matt Turner Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_bufs.c | 3 --- drivers/gpu/drm/drm_vm.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 3e257a50bf56..e1bd713d91a2 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -182,9 +182,6 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, kfree(map); return -EINVAL; } -#endif -#ifdef __alpha__ - map->offset += dev->hose->mem_space->start; #endif /* Some drivers preinitialize some maps, without the X Server * needing to be aware of it. Therefore, we just return success diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 2c3fcbdfd8ff..5db96d45fc71 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -526,7 +526,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) { #ifdef __alpha__ - return dev->hose->dense_mem_base - dev->hose->mem_space->start; + return dev->hose->dense_mem_base; #else return 0; #endif -- cgit v1.2.3 From 83533c132a55aac735028f6fb9b956e8c078db1f Mon Sep 17 00:00:00 2001 From: Jay Estabrook Date: Thu, 9 Jun 2011 18:19:12 -0400 Subject: alpha, drm: Remove obsolete Alpha support in MGA DRM code Remove an obsolete Alpha adjustment in the drm for MGA on Alpha. Signed-off-by: Jay Estabrook Tested-by: Matt Turner Signed-off-by: Dave Airlie --- drivers/gpu/drm/mga/mga_drv.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h index 1084fa4d261b..54558a01969a 100644 --- a/drivers/gpu/drm/mga/mga_drv.h +++ b/drivers/gpu/drm/mga/mga_drv.h @@ -195,29 +195,10 @@ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, #define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER() -#if defined(__linux__) && defined(__alpha__) -#define MGA_BASE(reg) ((unsigned long)(dev_priv->mmio->handle)) -#define MGA_ADDR(reg) (MGA_BASE(reg) + reg) - -#define MGA_DEREF(reg) (*(volatile u32 *)MGA_ADDR(reg)) -#define MGA_DEREF8(reg) (*(volatile u8 *)MGA_ADDR(reg)) - -#define MGA_READ(reg) (_MGA_READ((u32 *)MGA_ADDR(reg))) -#define MGA_READ8(reg) (_MGA_READ((u8 *)MGA_ADDR(reg))) -#define MGA_WRITE(reg, val) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF(reg) = val; } while (0) -#define MGA_WRITE8(reg, val) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8(reg) = val; } while (0) - -static inline u32 _MGA_READ(u32 *addr) -{ - DRM_MEMORYBARRIER(); - return *(volatile u32 *)addr; -} -#else #define MGA_READ8(reg) DRM_READ8(dev_priv->mmio, (reg)) #define MGA_READ(reg) DRM_READ32(dev_priv->mmio, (reg)) #define MGA_WRITE8(reg, val) DRM_WRITE8(dev_priv->mmio, (reg), (val)) #define MGA_WRITE(reg, val) DRM_WRITE32(dev_priv->mmio, (reg), (val)) -#endif #define DWGREG0 0x1c00 #define DWGREG0_END 0x1dff -- cgit v1.2.3 From 7ad35cf288fd63a19bf50e490440a992de808b2b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 25 May 2011 14:00:49 +1000 Subject: x86/uv/x2apic: update for change in pci bridge handling. When I added 3448a19da479b6bd1e28e2a2be9fa16c6a6feb39 I forgot about the special uv handling code for this, so this patch fixes it up. Acked-by: Jesse Barnes Acked-by: Ingo Molnar Signed-off-by: Dave Airlie --- arch/x86/kernel/apic/x2apic_uv_x.c | 8 ++++---- drivers/pci/pci.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index b511a011b7d0..adc66c3a1fef 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -632,14 +632,14 @@ late_initcall(uv_init_heartbeat); /* Direct Legacy VGA I/O traffic to designated IOH */ int uv_set_vga_state(struct pci_dev *pdev, bool decode, - unsigned int command_bits, bool change_bridge) + unsigned int command_bits, u32 flags) { int domain, bus, rc; - PR_DEVEL("devfn %x decode %d cmd %x chg_brdg %d\n", - pdev->devfn, decode, command_bits, change_bridge); + PR_DEVEL("devfn %x decode %d cmd %x flags %d\n", + pdev->devfn, decode, command_bits, flags); - if (!change_bridge) + if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE)) return 0; if ((command_bits & PCI_COMMAND_IO) == 0) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 56098b3e17c0..5f10c23dff94 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3271,11 +3271,11 @@ void __init pci_register_set_vga_state(arch_set_vga_state_t func) } static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode, - unsigned int command_bits, bool change_bridge) + unsigned int command_bits, u32 flags) { if (arch_set_vga_state) return arch_set_vga_state(dev, decode, command_bits, - change_bridge); + flags); return 0; } -- cgit v1.2.3 From ab21e60beaa96f2c55604f633dfe74076c531df7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Jun 2011 12:53:30 -0400 Subject: drm/radeon/kms: fix mac g5 quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apple uses the same subsystem pci ids for lots of hardware much of which is wired up differently. In this case, the G5 imac and the G5 tower. Only apply the quirk configuration to G5 towers. Reported-by: Joachim Henke Signed-off-by: Alex Deucher Cc: Joachim Henke Cc: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index d1b95b70af61..797c8bcbb6a4 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1553,9 +1553,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) (rdev->pdev->subsystem_device == 0x4a48)) { /* Mac X800 */ rdev->mode_info.connector_table = CT_MAC_X800; - } else if ((rdev->pdev->device == 0x4150) && - (rdev->pdev->subsystem_vendor == 0x1002) && - (rdev->pdev->subsystem_device == 0x4150)) { + } else if (of_machine_is_compatible("PowerMac7,2") || + of_machine_is_compatible("PowerMac7,3")) { /* Mac G5 9600 */ rdev->mode_info.connector_table = CT_MAC_G5_9600; } else -- cgit v1.2.3 From a27bb4b209dd6c327fa4e7185f2487f9508a58db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 10 Jun 2011 14:41:26 +0000 Subject: drm/radeon/kms: do bounds checking for 3D_LOAD_VBPNTR and bump array limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To my knowledge, the limit is 16 on r300. (the docs don't say what the limit is) The lack of bounds checking can be abused to do all sorts of things (from bypassing parts of the CS checker to crashing the kernel). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=36745 Cc: stable@kernel.org Signed-off-by: Marek Olšák Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100_track.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index 2fef9de7f363..686f9dc5d4bd 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -63,7 +63,7 @@ struct r100_cs_track { unsigned num_arrays; unsigned max_indx; unsigned color_channel_mask; - struct r100_cs_track_array arrays[11]; + struct r100_cs_track_array arrays[16]; struct r100_cs_track_cb cb[R300_MAX_CB]; struct r100_cs_track_cb zb; struct r100_cs_track_cb aa; @@ -146,6 +146,12 @@ static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, ib = p->ib->ptr; track = (struct r100_cs_track *)p->track; c = radeon_get_ib_value(p, idx++) & 0x1F; + if (c > 16) { + DRM_ERROR("Only 16 vertex buffers are allowed %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return -EINVAL; + } track->num_arrays = c; for (i = 0; i < (c - 1); i+=2, idx+=3) { r = r100_cs_packet_next_reloc(p, &reloc); -- cgit v1.2.3 From b65552f06ca866f587a0a50d1f4dbdd3a00ec532 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 12 Jun 2011 20:53:44 +0000 Subject: drm/i915: Don't leak in i915_gem_shmem_pread_slow() It seems to me that we are leaking 'user_pages' in drivers/gpu/drm/i915/i915_gem.c::i915_gem_shmem_pread_slow() if read_cache_page_gfp() fails. Signed-off-by: Jesper Juhl Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 12d32579b951..94c84d744100 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -465,8 +465,10 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, GFP_HIGHUSER | __GFP_RECLAIMABLE); - if (IS_ERR(page)) - return PTR_ERR(page); + if (IS_ERR(page)) { + ret = PTR_ERR(page); + goto out; + } if (do_bit17_swizzling) { slow_shmem_bit17_copy(page, -- cgit v1.2.3 From 66aa6962ff520804f9874e57ea97995153f499d8 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 30 May 2011 19:45:43 +0000 Subject: drm: Compare only lower 32 bits of framebuffer map offsets Drivers using multiple framebuffers got broken by commit 41c2e75e60200a860a74b7c84a6375c105e7437f which ignored the framebuffer (or register) map offset when looking for existing maps. The rationale was that the kernel-userspace ABI is fixed at a 32-bit offset, so the real offsets could not always be handed over for comparison. Instead of ignoring the offset we will compare the lower 32 bit. Drivers using multiple framebuffers should just make sure that the lower 32 bit are different. The existing drivers in question are practically limited to 32-bit systems so that should be fine for them. It is assumed that current drivers always specify a correct framebuffer map offset, even if this offset was ignored since above commit. So this patch should not change anything for drivers using only one framebuffer. Drivers needing multiple framebuffers with 64-bit map offsets will need to cook up something, for instance keeping an ID in the lower bit which is to be aligned away when it comes to using the offset. All of above applies to _DRM_REGISTERS as well. Signed-off-by: Tormod Volden Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_bufs.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index e1bd713d91a2..61e1ef90d4e5 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -46,10 +46,11 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, list_for_each_entry(entry, &dev->maplist, head) { /* * Because the kernel-userspace ABI is fixed at a 32-bit offset - * while PCI resources may live above that, we ignore the map - * offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS. - * It is assumed that each driver will have only one resource of - * each type. + * while PCI resources may live above that, we only compare the + * lower 32 bits of the map offset for maps of type + * _DRM_FRAMEBUFFER or _DRM_REGISTERS. + * It is assumed that if a driver have more than one resource + * of each type, the lower 32 bits are different. */ if (!entry->map || map->type != entry->map->type || @@ -59,9 +60,12 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, case _DRM_SHM: if (map->flags != _DRM_CONTAINS_LOCK) break; + return entry; case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: - return entry; + if ((entry->map->offset & 0xffffffff) == + (map->offset & 0xffffffff)) + return entry; default: /* Make gcc happy */ ; } -- cgit v1.2.3 From dab104a73694b06fe4a162cb39d678716da62a67 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Thu, 2 Jun 2011 14:09:32 +1000 Subject: m68knommu: fix linker script exported name sections The recent commit titled "module: Sort exported symbols" (f02e8a65) changed the exported symbol name sections. Bring the m68knommu linker script into line with those changes - including the sorting of the symbol names. Signed-off-by: Greg Ungerer --- arch/m68k/kernel/vmlinux.lds_no.S | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/m68k/kernel/vmlinux.lds_no.S b/arch/m68k/kernel/vmlinux.lds_no.S index f4d715cdca0e..7dc4087a9545 100644 --- a/arch/m68k/kernel/vmlinux.lds_no.S +++ b/arch/m68k/kernel/vmlinux.lds_no.S @@ -84,52 +84,52 @@ SECTIONS { /* Kernel symbol table: Normal symbols */ . = ALIGN(4); __start___ksymtab = .; - *(__ksymtab) + *(SORT(___ksymtab+*)) __stop___ksymtab = .; /* Kernel symbol table: GPL-only symbols */ __start___ksymtab_gpl = .; - *(__ksymtab_gpl) + *(SORT(___ksymtab_gpl+*)) __stop___ksymtab_gpl = .; /* Kernel symbol table: Normal unused symbols */ __start___ksymtab_unused = .; - *(__ksymtab_unused) + *(SORT(___ksymtab_unused+*)) __stop___ksymtab_unused = .; /* Kernel symbol table: GPL-only unused symbols */ __start___ksymtab_unused_gpl = .; - *(__ksymtab_unused_gpl) + *(SORT(___ksymtab_unused_gpl+*)) __stop___ksymtab_unused_gpl = .; /* Kernel symbol table: GPL-future symbols */ __start___ksymtab_gpl_future = .; - *(__ksymtab_gpl_future) + *(SORT(___ksymtab_gpl_future+*)) __stop___ksymtab_gpl_future = .; /* Kernel symbol table: Normal symbols */ __start___kcrctab = .; - *(__kcrctab) + *(SORT(___kcrctab+*)) __stop___kcrctab = .; /* Kernel symbol table: GPL-only symbols */ __start___kcrctab_gpl = .; - *(__kcrctab_gpl) + *(SORT(___kcrctab_gpl+*)) __stop___kcrctab_gpl = .; /* Kernel symbol table: Normal unused symbols */ __start___kcrctab_unused = .; - *(__kcrctab_unused) + *(SORT(___kcrctab_unused+*)) __stop___kcrctab_unused = .; /* Kernel symbol table: GPL-only unused symbols */ __start___kcrctab_unused_gpl = .; - *(__kcrctab_unused_gpl) + *(SORT(___kcrctab_unused_gpl+*)) __stop___kcrctab_unused_gpl = .; /* Kernel symbol table: GPL-future symbols */ __start___kcrctab_gpl_future = .; - *(__kcrctab_gpl_future) + *(SORT(___kcrctab_gpl_future+*)) __stop___kcrctab_gpl_future = .; /* Kernel symbol table: strings */ -- cgit v1.2.3 From 62356725987fa44bbebeb656b2a0d8c803e32ef2 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Thu, 2 Jun 2011 15:50:48 +1000 Subject: m68knommu: create config options for CPU classes There are 3 families of CPU core types that we support in the m68knommu architecture branch. They are . traditional 68000 . CPU32 (a 68020 core derivative without MMU or bitfield instructions) . ColdFire It will be useful going forward to have a CONFIG_ option defined for each type. We already have one for ColdFire (CONFIG_COLDFIRE), so add for the other 2 families, CONFIG_M68000 and CONFIG_MCPU32. Signed-off-by: Greg Ungerer --- arch/m68k/Kconfig.nommu | 52 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/arch/m68k/Kconfig.nommu b/arch/m68k/Kconfig.nommu index fc98f9b9d4d2..b004dc1b1710 100644 --- a/arch/m68k/Kconfig.nommu +++ b/arch/m68k/Kconfig.nommu @@ -14,6 +14,33 @@ config GENERIC_CLOCKEVENTS bool default n +config M68000 + bool + help + The Freescale (was Motorola) 68000 CPU is the first generation of + the well known M68K family of processors. The CPU core as well as + being available as a stand alone CPU was also used in many + System-On-Chip devices (eg 68328, 68302, etc). It does not contain + a paging MMU. + +config MCPU32 + bool + help + The Freescale (was then Motorola) CPU32 is a CPU core that is + based on the 68020 processor. For the most part it is used in + System-On-Chip parts, and does not contain a paging MMU. + +config COLDFIRE + bool + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + help + The Freescale ColdFire family of processors is a modern derivitive + of the 68000 processor family. They are mainly targeted at embedded + applications, and are all System-On-Chip (SOC) devices, as opposed + to stand alone CPUs. They implement a subset of the original 68000 + processor instruction set. + config COLDFIRE_SW_A7 bool default n @@ -36,26 +63,31 @@ choice config M68328 bool "MC68328" + select M68000 help Motorola 68328 processor support. config M68EZ328 bool "MC68EZ328" + select M68000 help Motorola 68EX328 processor support. config M68VZ328 bool "MC68VZ328" + select M68000 help Motorola 68VZ328 processor support. config M68360 bool "MC68360" + select MCPU32 help Motorola 68360 processor support. config M5206 bool "MCF5206" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_MBAR help @@ -63,6 +95,7 @@ config M5206 config M5206e bool "MCF5206e" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_MBAR help @@ -70,6 +103,7 @@ config M5206e config M520x bool "MCF520x" + select COLDFIRE select GENERIC_CLOCKEVENTS select HAVE_CACHE_SPLIT help @@ -77,6 +111,7 @@ config M520x config M523x bool "MCF523x" + select COLDFIRE select GENERIC_CLOCKEVENTS select HAVE_CACHE_SPLIT select HAVE_IPSBAR @@ -85,6 +120,7 @@ config M523x config M5249 bool "MCF5249" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_MBAR help @@ -92,6 +128,7 @@ config M5249 config M5271 bool "MCF5271" + select COLDFIRE select HAVE_CACHE_SPLIT select HAVE_IPSBAR help @@ -99,6 +136,7 @@ config M5271 config M5272 bool "MCF5272" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_MBAR help @@ -106,6 +144,7 @@ config M5272 config M5275 bool "MCF5275" + select COLDFIRE select HAVE_CACHE_SPLIT select HAVE_IPSBAR help @@ -113,6 +152,7 @@ config M5275 config M528x bool "MCF528x" + select COLDFIRE select GENERIC_CLOCKEVENTS select HAVE_CACHE_SPLIT select HAVE_IPSBAR @@ -121,6 +161,7 @@ config M528x config M5307 bool "MCF5307" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_CACHE_CB select HAVE_MBAR @@ -129,12 +170,14 @@ config M5307 config M532x bool "MCF532x" + select COLDFIRE select HAVE_CACHE_CB help Freescale (Motorola) ColdFire 532x processor support. config M5407 bool "MCF5407" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_CACHE_CB select HAVE_MBAR @@ -143,6 +186,7 @@ config M5407 config M547x bool "MCF547x" + select COLDFIRE select HAVE_CACHE_CB select HAVE_MBAR help @@ -150,6 +194,7 @@ config M547x config M548x bool "MCF548x" + select COLDFIRE select HAVE_CACHE_CB select HAVE_MBAR help @@ -168,13 +213,6 @@ config M54xx depends on (M548x || M547x) default y -config COLDFIRE - bool - depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M54xx) - select GENERIC_GPIO - select ARCH_REQUIRE_GPIOLIB - default y - config CLOCK_SET bool "Enable setting the CPU clock frequency" default n -- cgit v1.2.3 From 734c3ce3bd4d51c932893b9f6d32b9ded31acdff Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Thu, 2 Jun 2011 16:07:33 +1000 Subject: m68k: use kernel processor defines for conditional optimizations Older m68k-linux compilers will include pre-defined symbols that confuse what processor it is being targeted for. For example gcc-4.1.2 will pre-define __mc68020__ even if you specify the target processor as -m68000 on the gcc command line. Newer versions of gcc have this corrected. In a few places the m68k code uses defined(__mc68020__) for optimizations that include instructions that are specific to the CPU 68020 and above. When compiling with older compilers this will be true even when we have selected to compile for the older 68000 processors. Switch to using the kernel processor defines, CONFIG_M68020 and friends. Signed-off-by: Greg Ungerer --- arch/m68k/kernel/m68k_ksyms.c | 3 +-- arch/m68k/lib/memcpy.c | 9 ++++----- arch/m68k/lib/memset.c | 9 ++++----- arch/m68k/lib/muldi3.c | 21 ++++++++++----------- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 33f82769547c..1b7a14d1a000 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -14,8 +14,7 @@ EXPORT_SYMBOL(__ashrdi3); EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(__muldi3); -#if !defined(__mc68020__) && !defined(__mc68030__) && \ - !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcpu32__) +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) /* * Simpler 68k and ColdFire parts also need a few other gcc functions. */ diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c index 62182c81e91c..064889316974 100644 --- a/arch/m68k/lib/memcpy.c +++ b/arch/m68k/lib/memcpy.c @@ -34,8 +34,10 @@ void *memcpy(void *to, const void *from, size_t n) if (temp) { long *lto = to; const long *lfrom = from; -#if defined(__mc68020__) || defined(__mc68030__) || \ - defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) + for (; temp; temp--) + *lto++ = *lfrom++; +#else asm volatile ( " movel %2,%3\n" " andw #7,%3\n" @@ -56,9 +58,6 @@ void *memcpy(void *to, const void *from, size_t n) " jpl 4b" : "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1) : "0" (lfrom), "1" (lto), "2" (temp)); -#else - for (; temp; temp--) - *lto++ = *lfrom++; #endif to = lto; from = lfrom; diff --git a/arch/m68k/lib/memset.c b/arch/m68k/lib/memset.c index f649e6a2e644..8a7639f0a2fe 100644 --- a/arch/m68k/lib/memset.c +++ b/arch/m68k/lib/memset.c @@ -32,8 +32,10 @@ void *memset(void *s, int c, size_t count) temp = count >> 2; if (temp) { long *ls = s; -#if defined(__mc68020__) || defined(__mc68030__) || \ - defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) + for (; temp; temp--) + *ls++ = c; +#else size_t temp1; asm volatile ( " movel %1,%2\n" @@ -55,9 +57,6 @@ void *memset(void *s, int c, size_t count) " jpl 1b" : "=a" (ls), "=d" (temp), "=&d" (temp1) : "d" (c), "0" (ls), "1" (temp)); -#else - for (; temp; temp--) - *ls++ = c; #endif s = ls; } diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c index 079bafca073e..79e928a525d0 100644 --- a/arch/m68k/lib/muldi3.c +++ b/arch/m68k/lib/muldi3.c @@ -19,17 +19,7 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#if defined(__mc68020__) || defined(__mc68030__) || \ - defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) - -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mulu%.l %3,%1:%0" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ - : "%0" ((USItype)(u)), \ - "dmi" ((USItype)(v))) - -#else +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) #define SI_TYPE_SIZE 32 #define __BITS4 (SI_TYPE_SIZE / 4) @@ -61,6 +51,15 @@ Boston, MA 02111-1307, USA. */ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ } while (0) +#else + +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) + #endif #define __umulsidi3(u, v) \ -- cgit v1.2.3 From 9b2dc8b665932a8e681a7ab3237f60475e75e161 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 13 Jun 2011 14:48:22 +0900 Subject: md/raid5: fix raid5_set_bi_hw_segments The @bio->bi_phys_segments consists of active stripes count in the lower 16 bits and processed stripes count in the upper 16 bits. So logical-OR operator should be bitwise one. This bug has been present since 2.6.27 and the fix is suitable for any -stable kernel since then. Fortunately the bad code is only used on error paths and is relatively unlikely to be hit. Cc: stable@kernel.org Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f9d2fbc64977..af8a9a89e4da 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -129,7 +129,7 @@ static inline int raid5_dec_bi_hw_segments(struct bio *bio) static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt) { - bio->bi_phys_segments = raid5_bi_phys_segments(bio) || (cnt << 16); + bio->bi_phys_segments = raid5_bi_phys_segments(bio) | (cnt << 16); } /* Find first data disk in a raid6 stripe */ -- cgit v1.2.3 From b062962edb086011e94ec4d9eb3f6a6d814f2a8f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 14 Jun 2011 14:20:19 +1000 Subject: md/raid5: fix FUA request handling in ops_run_io() Commit e9c7469bb4f5 ("md: implment REQ_FLUSH/FUA support") introduced R5_WantFUA flag and set rw to WRITE_FUA in that case. However remaining code still checks whether rw is exactly same as WRITE or not, so FUAed-write ends up with being treated as READ. Fix it. This bug has been present since 2.6.37 and the fix is suitable for any -stable kernel since then. It is not clear why this has not caused more problems. Cc: Tejun Heo Cc: stable@kernel.org Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/raid5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index af8a9a89e4da..b7dcc677dda4 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -514,7 +514,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi = &sh->dev[i].req; bi->bi_rw = rw; - if (rw == WRITE) + if (rw & WRITE) bi->bi_end_io = raid5_end_write_request; else bi->bi_end_io = raid5_end_read_request; @@ -548,13 +548,13 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi->bi_io_vec[0].bv_offset = 0; bi->bi_size = STRIPE_SIZE; bi->bi_next = NULL; - if (rw == WRITE && + if ((rw & WRITE) && test_bit(R5_ReWrite, &sh->dev[i].flags)) atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); generic_make_request(bi); } else { - if (rw == WRITE) + if (rw & WRITE) set_bit(STRIPE_DEGRADED, &sh->state); pr_debug("skip op %ld on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); -- cgit v1.2.3 From fcde90759a985d8bfa4391346a821cc12fc16207 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 14 Jun 2011 14:23:57 +1000 Subject: md/raid5: remove unusual use of bio_iovec_idx() In the bio_for_each_segment loop, bvl always points current bio_vec, so the same as bio_iovec_idx(, i). Let's get rid of it. Cc: Dan Williams Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/raid5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index b7dcc677dda4..b72edf35ec54 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -585,7 +585,7 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, init_async_submit(&submit, flags, tx, NULL, NULL, NULL); bio_for_each_segment(bvl, bio, i) { - int len = bio_iovec_idx(bio, i)->bv_len; + int len = bvl->bv_len; int clen; int b_offset = 0; @@ -601,8 +601,8 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, clen = len; if (clen > 0) { - b_offset += bio_iovec_idx(bio, i)->bv_offset; - bio_page = bio_iovec_idx(bio, i)->bv_page; + b_offset += bvl->bv_offset; + bio_page = bvl->bv_page; if (frombio) tx = async_memcpy(page, bio_page, page_offset, b_offset, clen, &submit); -- cgit v1.2.3 From 4e78c724d47e2342aa8fde61f6b8536f662f795f Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 13 Jun 2011 13:49:11 +0900 Subject: TOMOYO: Fix oops in tomoyo_mount_acl(). In tomoyo_mount_acl() since 2.6.36, kern_path() was called without checking dev_name != NULL. As a result, an unprivileged user can trigger oops by issuing mount(NULL, "/", "ext3", 0, NULL) request. Fix this by checking dev_name != NULL before calling kern_path(dev_name). Signed-off-by: Tetsuo Handa Cc: stable@kernel.org Signed-off-by: James Morris --- security/tomoyo/mount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 162a864dba24..9fc2e15841c9 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -138,7 +138,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, } if (need_dev) { /* Get mount point or device file. */ - if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) { + if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) { error = -ENOENT; goto out; } -- cgit v1.2.3 From 37f7ec38ea5c31180461f82e895e13fdd549b595 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 13 Jun 2011 23:52:02 +0200 Subject: ALSA: 6fire: Fix double-free bug in usb6fire_fw_ezusb_upload() We have a double-free bug in sound/usb/6fire/firmware.c::usb6fire_fw_ezusb_upload(). We already call release_firmware(fw) on line 258, so when we then do it again after usb6fire_fw_ezusb_write() returns <0, we have a double-free. Easily fixed by just removing the last call to release_firmware(). Signed-off-by: Jesper Juhl Signed-off-by: Takashi Iwai --- sound/usb/6fire/firmware.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index a91719d5918b..1e3ae3327dd3 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -270,7 +270,6 @@ static int usb6fire_fw_ezusb_upload( data = 0x00; /* resume ezusb cpu */ ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); if (ret < 0) { - release_firmware(fw); snd_printk(KERN_ERR PREFIX "unable to upload ezusb " "firmware %s: end message.\n", fwname); return ret; -- cgit v1.2.3 From dcee0bb713d0ba0d32c5ce6fe0c5aa22e6fc274a Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 9 Jun 2011 06:35:08 +0000 Subject: dmaengine: shdma: SH_DMAC_MAX_CHANNELS message fix Fix the recently added SH_DMAC_MAX_CHANNELS handling code in 300e5f9 dmaengine: shdma: Fix SH_DMAC_MAX_CHANNELS handling Without this fix the shdma driver outputs silly messages in case SH_DMAC_MAX_CHANNELS happens to match the platform data: sh-dma-engine sh-dma-engine.0: Attempting to register 20 DMA channels when a max imum of 20 are supported. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/dma/shdma.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 2a638f9f09a2..028330044201 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1221,6 +1221,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev) } else { do { for (i = chanirq_res->start; i <= chanirq_res->end; i++) { + if (irq_cnt >= SH_DMAC_MAX_CHANNELS) { + irq_cap = 1; + break; + } + if ((errirq_res->flags & IORESOURCE_BITS) == IORESOURCE_IRQ_SHAREABLE) chan_flag[irq_cnt] = IRQF_SHARED; @@ -1230,15 +1235,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev) "Found IRQ %d for channel %d\n", i, irq_cnt); chan_irq[irq_cnt++] = i; - - if (irq_cnt >= SH_DMAC_MAX_CHANNELS) - break; } - if (irq_cnt >= SH_DMAC_MAX_CHANNELS) { - irq_cap = 1; + if (irq_cnt >= SH_DMAC_MAX_CHANNELS) break; - } + chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, ++irqres); } while (irq_cnt < pdata->channel_num && chanirq_res); -- cgit v1.2.3 From 5294206053f9ab522fbd6bfde1cf7629dc564d5e Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 9 Jun 2011 09:02:25 +0000 Subject: ARM: mach-shmobile: AG5EVM SDHI1 platform data update Add a flag for SDHI1 to enable SDIO IRQ, and remove DMA Engine slave id:s to disable DMA as a workaround. Tested on sh73a0/AG5EVM with a BCM4318-based SDIO card. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ag5evm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index c95258c274c1..1e2aba23e0d6 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -382,10 +382,8 @@ void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state) } static struct sh_mobile_sdhi_info sh_sdhi1_platdata = { - .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, - .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, - .tmio_caps = MMC_CAP_NONREMOVABLE, + .tmio_caps = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ, .tmio_ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .set_pwr = ag5evm_sdhi1_set_pwr, }; -- cgit v1.2.3 From e2a53b7c5bcfb63114c02c32117ed62eae463dc2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 9 Jun 2011 07:03:37 +0000 Subject: ARM: mach-shmobile: Mackerel USB platform data update This patch updates the board specific USB support code for the sh7372 Mackerel board. With this patch applied port CN22 is driven by the recently added renesas_usbhs driver using the first USB controller included in sh7372 aka USBHS0. Hotplugging of USBHS0 unfortunately has to be handled by software polling. The sh7372 SoC itself obviously supports hotplug notification by IRQ but on the Mackerel board this IRQ happens to be used for the touch screen. Also fix the pinmux configuration to avoid setting up unused pins and fix minor spelling errors. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-mackerel.c | 225 +++++++++++++++++++++++--------- 1 file changed, 160 insertions(+), 65 deletions(-) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 776f20560e72..1037bd2ffdb9 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -126,7 +126,7 @@ * ------+--------------------+--------------------+------- * IRQ0 | ICR1A.IRQ0SA=0010 | SDHI2 card detect | Low * IRQ6 | ICR1A.IRQ6SA=0011 | Ether(LAN9220) | High - * IRQ7 | ICR1A.IRQ7SA=0010 | LCD Tuch Panel | Low + * IRQ7 | ICR1A.IRQ7SA=0010 | LCD Touch Panel | Low * IRQ8 | ICR2A.IRQ8SA=0010 | MMC/SD card detect | Low * IRQ9 | ICR2A.IRQ9SA=0010 | KEY(TCA6408) | Low * IRQ21 | ICR4A.IRQ21SA=0011 | Sensor(ADXL345) | High @@ -165,10 +165,10 @@ * USB1 can become Host by r8a66597, and become Function by renesas_usbhs. * But don't select both drivers in same time. * These uses same IRQ number for request_irq(), and aren't supporting - * IRQF_SHARD / IORESOURCE_IRQ_SHAREABLE. + * IRQF_SHARED / IORESOURCE_IRQ_SHAREABLE. * * Actually these are old/new version of USB driver. - * This mean its register will be broken if it supports SHARD IRQ, + * This mean its register will be broken if it supports shared IRQ, */ /* @@ -562,7 +562,136 @@ out: clk_put(hdmi_ick); } -/* USB1 (Host) */ +/* USBHS0 is connected to CN22 which takes a USB Mini-B plug + * + * The sh7372 SoC has IRQ7 set aside for USBHS0 hotplug, + * but on this particular board IRQ7 is already used by + * the touch screen. This leaves us with software polling. + */ +#define USBHS0_POLL_INTERVAL (HZ * 5) + +struct usbhs_private { + unsigned int usbphyaddr; + unsigned int usbcrcaddr; + struct renesas_usbhs_platform_info info; + struct delayed_work work; + struct platform_device *pdev; +}; + +#define usbhs_get_priv(pdev) \ + container_of(renesas_usbhs_get_info(pdev), \ + struct usbhs_private, info) + +#define usbhs_is_connected(priv) \ + (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) + +static int usbhs_get_vbus(struct platform_device *pdev) +{ + return usbhs_is_connected(usbhs_get_priv(pdev)); +} + +static void usbhs_phy_reset(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + /* init phy */ + __raw_writew(0x8a0a, priv->usbcrcaddr); +} + +static int usbhs0_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + +static void usbhs0_work_function(struct work_struct *work) +{ + struct usbhs_private *priv = container_of(work, struct usbhs_private, + work.work); + + renesas_usbhs_call_notify_hotplug(priv->pdev); + schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL); +} + +static int usbhs0_hardware_init(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + priv->pdev = pdev; + INIT_DELAYED_WORK(&priv->work, usbhs0_work_function); + schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL); + return 0; +} + +static void usbhs0_hardware_exit(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + cancel_delayed_work_sync(&priv->work); +} + +static u32 usbhs0_pipe_cfg[] = { + USB_ENDPOINT_XFER_CONTROL, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_BULK, +}; + +static struct usbhs_private usbhs0_private = { + .usbcrcaddr = 0xe605810c, /* USBCR2 */ + .info = { + .platform_callback = { + .hardware_init = usbhs0_hardware_init, + .hardware_exit = usbhs0_hardware_exit, + .phy_reset = usbhs_phy_reset, + .get_id = usbhs0_get_id, + .get_vbus = usbhs_get_vbus, + }, + .driver_param = { + .buswait_bwait = 4, + .pipe_type = usbhs0_pipe_cfg, + .pipe_size = ARRAY_SIZE(usbhs0_pipe_cfg), + }, + }, +}; + +static struct resource usbhs0_resources[] = { + [0] = { + .name = "USBHS0", + .start = 0xe6890000, + .end = 0xe68900e6 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = evt2irq(0x1ca0) /* USB0_USB0I0 */, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usbhs0_device = { + .name = "renesas_usbhs", + .id = 0, + .dev = { + .platform_data = &usbhs0_private.info, + }, + .num_resources = ARRAY_SIZE(usbhs0_resources), + .resource = usbhs0_resources, +}; + +/* USBHS1 is connected to CN31 which takes a USB Mini-AB plug + * + * Use J30 to select between Host and Function. This setting + * can however not be detected by software. Hotplug of USBHS1 + * is provided via IRQ8. + */ +#define IRQ8 evt2irq(0x0300) + +/* USBHS1 USB Host support via r8a66597_hcd */ static void usb1_host_port_power(int port, int power) { if (!power) /* only power-on is supported for now */ @@ -579,9 +708,9 @@ static struct r8a66597_platdata usb1_host_data = { static struct resource usb1_host_resources[] = { [0] = { - .name = "USBHS", - .start = 0xE68B0000, - .end = 0xE68B00E6 - 1, + .name = "USBHS1", + .start = 0xe68b0000, + .end = 0xe68b00e6 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -602,37 +731,14 @@ static struct platform_device usb1_host_device = { .resource = usb1_host_resources, }; -/* USB1 (Function) */ +/* USBHS1 USB Function support via renesas_usbhs */ + #define USB_PHY_MODE (1 << 4) #define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) #define USB_PHY_ON (1 << 1) #define USB_PHY_OFF (1 << 0) #define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF) -struct usbhs_private { - unsigned int irq; - unsigned int usbphyaddr; - unsigned int usbcrcaddr; - struct renesas_usbhs_platform_info info; -}; - -#define usbhs_get_priv(pdev) \ - container_of(renesas_usbhs_get_info(pdev), \ - struct usbhs_private, info) - -#define usbhs_is_connected(priv) \ - (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) - -static int usbhs1_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -static int usbhs1_get_vbus(struct platform_device *pdev) -{ - return usbhs_is_connected(usbhs_get_priv(pdev)); -} - static irqreturn_t usbhs1_interrupt(int irq, void *data) { struct platform_device *pdev = data; @@ -654,12 +760,10 @@ static int usbhs1_hardware_init(struct platform_device *pdev) struct usbhs_private *priv = usbhs_get_priv(pdev); int ret; - irq_set_irq_type(priv->irq, IRQ_TYPE_LEVEL_HIGH); - /* clear interrupt status */ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); - ret = request_irq(priv->irq, usbhs1_interrupt, 0, + ret = request_irq(IRQ8, usbhs1_interrupt, IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), pdev); if (ret) { dev_err(&pdev->dev, "request_irq err\n"); @@ -679,15 +783,7 @@ static void usbhs1_hardware_exit(struct platform_device *pdev) /* clear interrupt status */ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); - free_irq(priv->irq, pdev); -} - -static void usbhs1_phy_reset(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - /* init phy */ - __raw_writew(0x8a0a, priv->usbcrcaddr); + free_irq(IRQ8, pdev); } static u32 usbhs1_pipe_cfg[] = { @@ -710,16 +806,14 @@ static u32 usbhs1_pipe_cfg[] = { }; static struct usbhs_private usbhs1_private = { - .irq = evt2irq(0x0300), /* IRQ8 */ - .usbphyaddr = 0xE60581E2, /* USBPHY1INTAP */ - .usbcrcaddr = 0xE6058130, /* USBCR4 */ + .usbphyaddr = 0xe60581e2, /* USBPHY1INTAP */ + .usbcrcaddr = 0xe6058130, /* USBCR4 */ .info = { .platform_callback = { .hardware_init = usbhs1_hardware_init, .hardware_exit = usbhs1_hardware_exit, - .phy_reset = usbhs1_phy_reset, - .get_id = usbhs1_get_id, - .get_vbus = usbhs1_get_vbus, + .phy_reset = usbhs_phy_reset, + .get_vbus = usbhs_get_vbus, }, .driver_param = { .buswait_bwait = 4, @@ -731,9 +825,9 @@ static struct usbhs_private usbhs1_private = { static struct resource usbhs1_resources[] = { [0] = { - .name = "USBHS", - .start = 0xE68B0000, - .end = 0xE68B00E6 - 1, + .name = "USBHS1", + .start = 0xe68b0000, + .end = 0xe68b00e6 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -752,7 +846,6 @@ static struct platform_device usbhs1_device = { .resource = usbhs1_resources, }; - /* LED */ static struct gpio_led mackerel_leds[] = { { @@ -1203,6 +1296,7 @@ static struct platform_device *mackerel_devices[] __initdata = { &nor_flash_device, &smc911x_device, &lcdc_device, + &usbhs0_device, &usb1_host_device, &usbhs1_device, &leds_device, @@ -1301,6 +1395,7 @@ static void __init mackerel_map_io(void) #define GPIO_PORT9CR 0xE6051009 #define GPIO_PORT10CR 0xE605100A +#define GPIO_PORT167CR 0xE60520A7 #define GPIO_PORT168CR 0xE60520A8 #define SRCR4 0xe61580bc #define USCCR1 0xE6058144 @@ -1354,17 +1449,17 @@ static void __init mackerel_init(void) gpio_request(GPIO_PORT151, NULL); /* LCDDON */ gpio_direction_output(GPIO_PORT151, 1); - /* USB enable */ - gpio_request(GPIO_FN_VBUS0_1, NULL); - gpio_request(GPIO_FN_IDIN_1_18, NULL); - gpio_request(GPIO_FN_PWEN_1_115, NULL); - gpio_request(GPIO_FN_OVCN_1_114, NULL); - gpio_request(GPIO_FN_EXTLP_1, NULL); - gpio_request(GPIO_FN_OVCN2_1, NULL); - gpio_pull_down(GPIO_PORT168CR); - - /* setup USB phy */ - __raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */ + /* USBHS0 */ + gpio_request(GPIO_FN_VBUS0_0, NULL); + gpio_pull_down(GPIO_PORT168CR); /* VBUS0_0 pull down */ + + /* USBHS1 */ + gpio_request(GPIO_FN_VBUS0_1, NULL); + gpio_pull_down(GPIO_PORT167CR); /* VBUS0_1 pull down */ + gpio_request(GPIO_FN_IDIN_1_113, NULL); + + /* USB phy tweak to make the r8a66597_hcd host driver work */ + __raw_writew(0x8a0a, 0xe6058130); /* USBCR4 */ /* enable FSI2 port A (ak4643) */ gpio_request(GPIO_FN_FSIAIBT, NULL); -- cgit v1.2.3 From 485b2ab55477f46cd1f7d16ba9f87cd074051811 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 9 Jun 2011 06:20:03 +0000 Subject: ARM: mach-shmobile: sh73a0 gic_arch_extn.irq_set_wake() fix Initialize ->irq_set_wake() in gic_arch_extn to unbreak wake up from the KEYSC device on AG5EVM in case of Suspend-to-RAM. Without this patch "echo mem > /sys/power/state" and a key press results in the following message on resume: WARNING: at kernel/irq/manage.c:507 irq_set_irq_wake+0x7c/0xd8() Unbalanced IRQ 103 wake disable Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/intc-sh73a0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index 5d0e1503ece6..a911a60e7719 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -250,6 +250,11 @@ static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id) return IRQ_HANDLED; } +static int sh73a0_set_wake(struct irq_data *data, unsigned int on) +{ + return 0; /* always allow wakeup */ +} + void __init sh73a0_init_irq(void) { void __iomem *gic_dist_base = __io(0xf0001000); @@ -257,6 +262,7 @@ void __init sh73a0_init_irq(void) void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); gic_init(0, 29, gic_dist_base, gic_cpu_base); + gic_arch_extn.irq_set_wake = sh73a0_set_wake; register_intc_controller(&intcs_desc); -- cgit v1.2.3 From 311057250e87f7470ccca8bd68bf9e67f6b6db09 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 14 Jun 2011 15:07:06 +0900 Subject: ARM: mach-shmobile: Correct SCIF port types for SH7367. While SH7377 and others were updated to properly use SCIFA/B port types, SH7367 was left behind. Fix it up accordingly. Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/setup-sh7367.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c index 2c10190dbb55..e546017f15de 100644 --- a/arch/arm/mach-shmobile/setup-sh7367.c +++ b/arch/arm/mach-shmobile/setup-sh7367.c @@ -38,7 +38,7 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc00), evt2irq(0xc00), evt2irq(0xc00), evt2irq(0xc00) }, }; @@ -57,7 +57,7 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc20), evt2irq(0xc20), evt2irq(0xc20), evt2irq(0xc20) }, }; @@ -76,7 +76,7 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc40), evt2irq(0xc40), evt2irq(0xc40), evt2irq(0xc40) }, }; @@ -95,7 +95,7 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc60), evt2irq(0xc60), evt2irq(0xc60), evt2irq(0xc60) }, }; @@ -114,7 +114,7 @@ static struct plat_sci_port scif4_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xd20), evt2irq(0xd20), evt2irq(0xd20), evt2irq(0xd20) }, }; @@ -133,7 +133,7 @@ static struct plat_sci_port scif5_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xd40), evt2irq(0xd40), evt2irq(0xd40), evt2irq(0xd40) }, }; @@ -152,7 +152,7 @@ static struct plat_sci_port scif6_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFB, .irqs = { evt2irq(0xd60), evt2irq(0xd60), evt2irq(0xd60), evt2irq(0xd60) }, }; -- cgit v1.2.3 From ca2585afa013ec2cf99a48e46d6b82df2e240493 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Jun 2011 08:14:32 +0200 Subject: ALSA: hda - Fix missing static inline to beep dummy function The commit 2308f4add3de9f6c9c9f02e49461e94d84bb200a missed static inline thus it resulted in multiple-definitions error at linking. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 4967eabe774e..55f0647458c7 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -54,7 +54,7 @@ static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) { return 0; } -void snd_hda_detach_beep_device(struct hda_codec *codec) +static inline void snd_hda_detach_beep_device(struct hda_codec *codec) { } #endif -- cgit v1.2.3 From 583af252ab07cd1e8721878463da5b7016c18fdc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 13 Jun 2011 04:42:15 +0000 Subject: drivers: sh: resume enabled clocks fix Extend the SH / SH-Mobile ARM clock framework to only resume clocks that have been enabled. Without this fix divide-by-zero is triggering on sh7372 FSIDIV during system wide resume of Suspend-to-RAM. Signed-off-by: Magnus Damm Reviewed-by: Simon Horman Signed-off-by: Paul Mundt --- drivers/sh/clk/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 4f64183b27fa..7e9c39951ecb 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -635,7 +635,7 @@ static void clks_core_resume(void) struct clk *clkp; list_for_each_entry(clkp, &clock_list, node) { - if (likely(clkp->ops)) { + if (likely(clkp->usecount && clkp->ops)) { unsigned long rate = clkp->rate; if (likely(clkp->ops->set_parent)) -- cgit v1.2.3 From 201fbceb258650157fcc4fd746abcdd3a571eada Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Fri, 10 Jun 2011 13:10:48 +0000 Subject: sh, exec: remove redundant set_fs(USER_DS) The address limit is already set in flush_old_exec() so those calls to set_fs(USER_DS) are redundant. Signed-off-by: Mathias Krause Signed-off-by: Paul Mundt --- arch/sh/include/asm/processor_64.h | 1 - arch/sh/kernel/process_32.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index 2a541ddb5a1b..e25c4c7d6b63 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h @@ -150,7 +150,6 @@ struct thread_struct { #define SR_USER (SR_MMU | SR_FD) #define start_thread(_regs, new_pc, new_sp) \ - set_fs(USER_DS); \ _regs->sr = SR_USER; /* User mode. */ \ _regs->pc = new_pc - 4; /* Compensate syscall exit */ \ _regs->pc |= 1; /* Set SHmedia ! */ \ diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index b473f0c06fbc..aaf6d59c2012 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -102,8 +102,6 @@ EXPORT_SYMBOL(kernel_thread); void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned long new_sp) { - set_fs(USER_DS); - regs->pr = 0; regs->sr = SR_FD; regs->pc = new_pc; -- cgit v1.2.3 From e6b8480cdf27953c3d13e6e34dd075f8287b02f0 Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Sun, 12 Jun 2011 10:52:33 +0000 Subject: efifb: Fix call to wrong unregister function platform_device_unregister() needs to unregister the device, not the driver. Signed-off-by: Wanlong Gao Signed-off-by: Maarten Lankhorst Acked-by: Andy Lutomirski Signed-off-by: Paul Mundt --- drivers/video/efifb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 69c49dfce9cf..784139aed079 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -541,7 +541,7 @@ static int __init efifb_init(void) */ ret = platform_driver_probe(&efifb_driver, efifb_probe); if (ret) { - platform_device_unregister(&efifb_driver); + platform_device_unregister(&efifb_device); return ret; } -- cgit v1.2.3 From d64c132ffe04c0941d3008f178f8cca157dd7f16 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 13 Jun 2011 18:12:58 +0000 Subject: fbdev/atyfb: Fix 2 defined-but-not-used warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_FB_ATY_BACKLIGHT=y but CONFIG_PCI=n: drivers/video/aty/atyfb_base.c:2272: warning: ‘aty_bl_exit’ defined but not used If CONFIG_ATARI=y for a modular build: drivers/video/aty/atyfb_base.c:2794: warning: ‘store_video_par’ defined but not used Signed-off-by: Geert Uytterhoeven Signed-off-by: Paul Mundt --- drivers/video/aty/atyfb_base.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index ebb893c49e90..d7aaec5667bf 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -248,10 +248,6 @@ static int atyfb_sync(struct fb_info *info); static int aty_init(struct fb_info *info); -#ifdef CONFIG_ATARI -static int store_video_par(char *videopar, unsigned char m64_num); -#endif - static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); @@ -2268,11 +2264,13 @@ error: return; } +#ifdef CONFIG_PCI static void aty_bl_exit(struct backlight_device *bd) { backlight_device_unregister(bd); printk("aty: Backlight unloaded\n"); } +#endif /* CONFIG_PCI */ #endif /* CONFIG_FB_ATY_BACKLIGHT */ @@ -2789,7 +2787,7 @@ aty_init_exit: return ret; } -#ifdef CONFIG_ATARI +#if defined(CONFIG_ATARI) && !defined(MODULE) static int __devinit store_video_par(char *video_str, unsigned char m64_num) { char *p; @@ -2818,7 +2816,7 @@ static int __devinit store_video_par(char *video_str, unsigned char m64_num) phys_vmembase[m64_num] = 0; return -1; } -#endif /* CONFIG_ATARI */ +#endif /* CONFIG_ATARI && !MODULE */ /* * Blank the display. -- cgit v1.2.3 From 1123d93963cbd2546449d4d9f0c568e323cb0ac6 Mon Sep 17 00:00:00 2001 From: Max Asbock Date: Mon, 13 Jun 2011 10:18:32 -0700 Subject: timerfd: Fix wakeup of processes when timer is cancelled on clock change Currently processes waiting with poll on cancelable timerfd timers are not woken up when the timers are canceled. When the system time is set the clock_was_set() function calls timerfd_clock_was_set() to cancel and wake up processes waiting on potential cancelable timerfd timers. However the wake up currently has no effect because in the case of timerfd_read it is dependent on ctx->ticks not being 0. timerfd_poll also requires ctx->ticks being non zero. As a consequence processes waiting on cancelable timers only get woken up when the timers expire. This patch fixes this by incrementing ctx->ticks before calling wake_up. Signed-off-by: Max Asbock Cc: kay.sievers@vrfy.org Cc: virtuoso@slind.org Cc: johnstul Link: http://lkml.kernel.org/r/1307985512.4710.41.camel@w-amax.beaverton.ibm.com Signed-off-by: Thomas Gleixner --- fs/timerfd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/timerfd.c b/fs/timerfd.c index f67acbdda5e8..dffeb3795af1 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -61,7 +61,9 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) /* * Called when the clock was set to cancel the timers in the cancel - * list. + * list. This will wake up processes waiting on these timers. The + * wake-up requires ctx->ticks to be non zero, therefore we increment + * it before calling wake_up_locked(). */ void timerfd_clock_was_set(void) { @@ -76,6 +78,7 @@ void timerfd_clock_was_set(void) spin_lock_irqsave(&ctx->wqh.lock, flags); if (ctx->moffs.tv64 != moffs.tv64) { ctx->moffs.tv64 = KTIME_MAX; + ctx->ticks++; wake_up_locked(&ctx->wqh); } spin_unlock_irqrestore(&ctx->wqh.lock, flags); -- cgit v1.2.3 From 7bbf1d46b28455aed6aa6df772b91d51408c6c81 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 1 Jun 2011 11:08:01 +0200 Subject: avr32: fix use of non-existing portnr variable in at32_map_usart() This patch fixes the use of the non-existing portnr variable in at32_map_usart() to use the provided line number instead. Typo was introduced in commit 2b348e2f82f532e3aff8e0ce9293033b3294c1e0. Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/at32ap700x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index aa677e2a3823..1b7ad97524b8 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1044,7 +1044,7 @@ void __init at32_map_usart(unsigned int hw_id, unsigned int line, int flags) } pdata = pdev->dev.platform_data; - pdata->num = portnr; + pdata->num = line; at32_usarts[line] = pdev; } -- cgit v1.2.3 From 4137b31566fd112c8e2d9d4701de5e7a000bcc2d Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 8 Jun 2011 10:47:25 +0200 Subject: avr32/at32ap: fix mapping of platform device id for USART This patch will fix the mapping of the platform device id when mapping USART peripheral ID to UART platform device id. Not setting the platform device id will in most cases (when you map USART > 0 to UART 0) make the console not available. Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/at32ap700x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 1b7ad97524b8..7fbf0dcb9afe 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1043,6 +1043,7 @@ void __init at32_map_usart(unsigned int hw_id, unsigned int line, int flags) data->regs = (void __iomem *)pdev->resource[0].start; } + pdev->id = line; pdata = pdev->dev.platform_data; pdata->num = line; at32_usarts[line] = pdev; -- cgit v1.2.3 From a527a1453dd6dd89f07f1e5b2d24fc6559922461 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 1 Jun 2011 15:10:49 +0200 Subject: avr32: set CONFIG_CC_OPTIMIZE_FOR_SIZE=y for all defconfigs This patch makes sure the kconfig option CC_OPTIMIZE_FOR_SIZE is set to yes for all default configuration files. This ensures the kernel is optimized for size, and avoids potential relocation truncated to fit problems. Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/configs/atngw100_defconfig | 1 + arch/avr32/configs/atngw100_evklcd100_defconfig | 1 + arch/avr32/configs/atngw100_evklcd101_defconfig | 1 + arch/avr32/configs/atngw100_mrmt_defconfig | 1 + arch/avr32/configs/atngw100mkii_defconfig | 1 + arch/avr32/configs/atngw100mkii_evklcd100_defconfig | 1 + arch/avr32/configs/atngw100mkii_evklcd101_defconfig | 1 + arch/avr32/configs/atstk1002_defconfig | 1 + arch/avr32/configs/atstk1003_defconfig | 1 + arch/avr32/configs/atstk1004_defconfig | 1 + arch/avr32/configs/atstk1006_defconfig | 1 + arch/avr32/configs/favr-32_defconfig | 1 + arch/avr32/configs/hammerhead_defconfig | 1 + arch/avr32/configs/merisc_defconfig | 1 + arch/avr32/configs/mimc200_defconfig | 1 + 15 files changed, 15 insertions(+) diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig index 6f9ca56de1f6..a06bfccc2840 100644 --- a/arch/avr32/configs/atngw100_defconfig +++ b/arch/avr32/configs/atngw100_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100_evklcd100_defconfig b/arch/avr32/configs/atngw100_evklcd100_defconfig index 7eece0af34c9..d8f1fe80d210 100644 --- a/arch/avr32/configs/atngw100_evklcd100_defconfig +++ b/arch/avr32/configs/atngw100_evklcd100_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100_evklcd101_defconfig b/arch/avr32/configs/atngw100_evklcd101_defconfig index 387eb9d6e423..d4c5b19ec950 100644 --- a/arch/avr32/configs/atngw100_evklcd101_defconfig +++ b/arch/avr32/configs/atngw100_evklcd101_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig index 19f6ceeeff7b..6cb786c0baf6 100644 --- a/arch/avr32/configs/atngw100_mrmt_defconfig +++ b/arch/avr32/configs/atngw100_mrmt_defconfig @@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_SLUB_DEBUG is not set diff --git a/arch/avr32/configs/atngw100mkii_defconfig b/arch/avr32/configs/atngw100mkii_defconfig index f0fe237133a9..6e0dca4d3131 100644 --- a/arch/avr32/configs/atngw100mkii_defconfig +++ b/arch/avr32/configs/atngw100mkii_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig index e4a7c1dc8380..7f2a344a5fa8 100644 --- a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig +++ b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig index 6f37f70c2c37..085eeba88f67 100644 --- a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig +++ b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig index 4fb01f5ab42f..d1a887e64055 100644 --- a/arch/avr32/configs/atstk1002_defconfig +++ b/arch/avr32/configs/atstk1002_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig index 9faaf9b900f2..956f2819ad45 100644 --- a/arch/avr32/configs/atstk1003_defconfig +++ b/arch/avr32/configs/atstk1003_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig index 3d2a5d85f970..40c69f38c61a 100644 --- a/arch/avr32/configs/atstk1004_defconfig +++ b/arch/avr32/configs/atstk1004_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig index 1ed8f22d4fe2..511eb8af356d 100644 --- a/arch/avr32/configs/atstk1006_defconfig +++ b/arch/avr32/configs/atstk1006_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig index aeadc955db32..19973b06170c 100644 --- a/arch/avr32/configs/favr-32_defconfig +++ b/arch/avr32/configs/favr-32_defconfig @@ -6,6 +6,7 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/hammerhead_defconfig b/arch/avr32/configs/hammerhead_defconfig index 1692beeb7ed3..6f45681196d1 100644 --- a/arch/avr32/configs/hammerhead_defconfig +++ b/arch/avr32/configs/hammerhead_defconfig @@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/merisc_defconfig b/arch/avr32/configs/merisc_defconfig index 8b670a6530bf..3befab966827 100644 --- a/arch/avr32/configs/merisc_defconfig +++ b/arch/avr32/configs/merisc_defconfig @@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set CONFIG_MODULES=y diff --git a/arch/avr32/configs/mimc200_defconfig b/arch/avr32/configs/mimc200_defconfig index 5a51f2e7ffb9..1bee51f22154 100644 --- a/arch/avr32/configs/mimc200_defconfig +++ b/arch/avr32/configs/mimc200_defconfig @@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set -- cgit v1.2.3 From 3000f0077a5745918830f40826c23fe5bf934b8b Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Sun, 15 May 2011 00:23:32 +0200 Subject: avr32: add some more at91 to cpu.h definition Somme common drivers will need those at91 cpu_is_xxx() definitions. Those definitions are already in Linus' tree so if we want to use them in common drivers, we will need them in AVR32 cpu.h file. Signed-off-by: Nicolas Ferre Acked-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/include/mach/cpu.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/avr32/mach-at32ap/include/mach/cpu.h b/arch/avr32/mach-at32ap/include/mach/cpu.h index 9c96a130f3a8..8181293115e4 100644 --- a/arch/avr32/mach-at32ap/include/mach/cpu.h +++ b/arch/avr32/mach-at32ap/include/mach/cpu.h @@ -31,8 +31,20 @@ #define cpu_is_at91sam9263() (0) #define cpu_is_at91sam9rl() (0) #define cpu_is_at91cap9() (0) +#define cpu_is_at91cap9_revB() (0) +#define cpu_is_at91cap9_revC() (0) #define cpu_is_at91sam9g10() (0) +#define cpu_is_at91sam9g20() (0) #define cpu_is_at91sam9g45() (0) #define cpu_is_at91sam9g45es() (0) +#define cpu_is_at91sam9m10() (0) +#define cpu_is_at91sam9g46() (0) +#define cpu_is_at91sam9m11() (0) +#define cpu_is_at91sam9x5() (0) +#define cpu_is_at91sam9g15() (0) +#define cpu_is_at91sam9g35() (0) +#define cpu_is_at91sam9x35() (0) +#define cpu_is_at91sam9g25() (0) +#define cpu_is_at91sam9x25() (0) #endif /* __ASM_ARCH_CPU_H */ -- cgit v1.2.3 From c162755491f7ca9853cb9f2aaa3ff3677c1bda78 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Mon, 6 Jun 2011 18:19:20 +0200 Subject: avr32: make intc_resume() return void to conform to syscore_ops This patch removes the unneeded, and now wrong, return 0 from intc_resume() and lets the function return void instead. This matches the resume callback in struct syscore_ops. Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/intc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c index 3e3646186c9f..c9ac2f8e8f64 100644 --- a/arch/avr32/mach-at32ap/intc.c +++ b/arch/avr32/mach-at32ap/intc.c @@ -167,14 +167,12 @@ static int intc_suspend(void) return 0; } -static int intc_resume(void) +static void intc_resume(void) { int i; for (i = 0; i < 64; i++) intc_writel(&intc0, INTPR0 + 4 * i, intc0.saved_ipr[i]); - - return 0; } #else #define intc_suspend NULL -- cgit v1.2.3 From ff71db2f0784cfff38fa7b55908867a24ccc3216 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Fri, 10 Jun 2011 15:09:05 +0200 Subject: avr32, exec: remove redundant set_fs(USER_DS) The address limit is already set in flush_old_exec() so this set_fs(USER_DS) is redundant. Signed-off-by: Mathias Krause Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/include/asm/processor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h index 49a88f5a9d2f..108502bc6770 100644 --- a/arch/avr32/include/asm/processor.h +++ b/arch/avr32/include/asm/processor.h @@ -131,7 +131,6 @@ struct thread_struct { */ #define start_thread(regs, new_pc, new_sp) \ do { \ - set_fs(USER_DS); \ memset(regs, 0, sizeof(*regs)); \ regs->sr = MODE_USER; \ regs->pc = new_pc & ~1; \ -- cgit v1.2.3 From e9e35c5a2b2c803b5e2f25906d8ffe110670ceb6 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 14 Jun 2011 05:53:18 -0700 Subject: OMAP1: PM: register notifiers with generic clock ops even when !PM_RUNTIME When runtime PM is disabled, device clocks need to be enabled on device add and disabled on device remove. This currently is not happening because in the !PM_RUNTIME case, no notifiers are registered for OMAP1 devices. Fix this by ensuring notifiers are registered, even in the !PM_RUNTIME case. Reported-by: Janusz Krzysztofik Tested-by: Janusz Krzysztofik Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/Makefile | 4 ++-- arch/arm/mach-omap1/pm_bus.c | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index af98117043d2..5b114d1558c8 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -4,14 +4,14 @@ # Common support obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o -obj-y += clock.o clock_data.o opp_data.o reset.o +obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o # Power Management -obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o +obj-$(CONFIG_PM) += pm.o sleep.o # DSP obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c index fe31d933f0ed..334fb8871bc3 100644 --- a/arch/arm/mach-omap1/pm_bus.c +++ b/arch/arm/mach-omap1/pm_bus.c @@ -56,9 +56,13 @@ static struct dev_power_domain default_power_domain = { USE_PLATFORM_PM_SLEEP_OPS }, }; +#define OMAP1_PWR_DOMAIN (&default_power_domain) +#else +#define OMAP1_PWR_DOMAIN NULL +#endif /* CONFIG_PM_RUNTIME */ static struct pm_clk_notifier_block platform_bus_notifier = { - .pwr_domain = &default_power_domain, + .pwr_domain = OMAP1_PWR_DOMAIN, .con_ids = { "ick", "fck", NULL, }, }; @@ -72,4 +76,4 @@ static int __init omap1_pm_runtime_init(void) return 0; } core_initcall(omap1_pm_runtime_init); -#endif /* CONFIG_PM_RUNTIME */ + -- cgit v1.2.3 From 040d15c86747cf44fcf6b8ee19d805d4ef20caf3 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 14 Jun 2011 15:51:18 +0000 Subject: [CIFS] trivial cleanup fscache cFYI and cERROR messages ... for uniformity and cleaner debug logs. Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French --- fs/cifs/cache.c | 6 +++--- fs/cifs/fscache.c | 51 ++++++++++++++++++++++++--------------------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c index dd8584d35a14..545509c3313b 100644 --- a/fs/cifs/cache.c +++ b/fs/cifs/cache.c @@ -92,7 +92,7 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data, break; default: - cERROR(1, "CIFS: Unknown network family '%d'", sa->sa_family); + cERROR(1, "Unknown network family '%d'", sa->sa_family); key_len = 0; break; } @@ -152,7 +152,7 @@ static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer, sharename = extract_sharename(tcon->treeName); if (IS_ERR(sharename)) { - cFYI(1, "CIFS: couldn't extract sharename\n"); + cFYI(1, "%s: couldn't extract sharename\n", __func__); sharename = NULL; return 0; } @@ -302,7 +302,7 @@ static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data) pagevec_init(&pvec, 0); first = 0; - cFYI(1, "cifs inode 0x%p now uncached", cifsi); + cFYI(1, "%s: cifs inode 0x%p now uncached", __func__, cifsi); for (;;) { nr_pages = pagevec_lookup(&pvec, diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index d368a47ba5eb..816696621ec9 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -28,14 +28,14 @@ void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) server->fscache = fscache_acquire_cookie(cifs_fscache_netfs.primary_index, &cifs_fscache_server_index_def, server); - cFYI(1, "CIFS: get client cookie (0x%p/0x%p)", server, - server->fscache); + cFYI(1, "%s: (0x%p/0x%p)", __func__, server, + server->fscache); } void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) { - cFYI(1, "CIFS: release client cookie (0x%p/0x%p)", server, - server->fscache); + cFYI(1, "%s: (0x%p/0x%p)", __func__, server, + server->fscache); fscache_relinquish_cookie(server->fscache, 0); server->fscache = NULL; } @@ -47,13 +47,13 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) tcon->fscache = fscache_acquire_cookie(server->fscache, &cifs_fscache_super_index_def, tcon); - cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)", - server->fscache, tcon->fscache); + cFYI(1, "%s: (0x%p/0x%p)", __func__, server->fscache, + tcon->fscache); } void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) { - cFYI(1, "CIFS: releasing superblock cookie (0x%p)", tcon->fscache); + cFYI(1, "%s: (0x%p)", __func__, tcon->fscache); fscache_relinquish_cookie(tcon->fscache, 0); tcon->fscache = NULL; } @@ -70,8 +70,8 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { cifsi->fscache = fscache_acquire_cookie(tcon->fscache, &cifs_fscache_inode_object_def, cifsi); - cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, - cifsi->fscache); + cFYI(1, "%s: got FH cookie (0x%p/0x%p)", __func__, + tcon->fscache, cifsi->fscache); } } @@ -80,8 +80,7 @@ void cifs_fscache_release_inode_cookie(struct inode *inode) struct cifsInodeInfo *cifsi = CIFS_I(inode); if (cifsi->fscache) { - cFYI(1, "CIFS releasing inode cookie (0x%p)", - cifsi->fscache); + cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); fscache_relinquish_cookie(cifsi->fscache, 0); cifsi->fscache = NULL; } @@ -92,8 +91,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode) struct cifsInodeInfo *cifsi = CIFS_I(inode); if (cifsi->fscache) { - cFYI(1, "CIFS disabling inode cookie (0x%p)", - cifsi->fscache); + cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); fscache_relinquish_cookie(cifsi->fscache, 1); cifsi->fscache = NULL; } @@ -121,8 +119,8 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode) cifs_sb_master_tcon(cifs_sb)->fscache, &cifs_fscache_inode_object_def, cifsi); - cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p", - cifsi->fscache, old); + cFYI(1, "%s: new cookie 0x%p oldcookie 0x%p", + __func__, cifsi->fscache, old); } } @@ -132,8 +130,8 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp) struct inode *inode = page->mapping->host; struct cifsInodeInfo *cifsi = CIFS_I(inode); - cFYI(1, "CIFS: fscache release page (0x%p/0x%p)", - page, cifsi->fscache); + cFYI(1, "%s: (0x%p/0x%p)", __func__, page, + cifsi->fscache); if (!fscache_maybe_release_page(cifsi->fscache, page, gfp)) return 0; } @@ -144,8 +142,7 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp) static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx, int error) { - cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)", - page, error); + cFYI(1, "%s: (0x%p/%d)", __func__, page, error); if (!error) SetPageUptodate(page); unlock_page(page); @@ -158,7 +155,7 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) { int ret; - cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p", + cFYI(1, "%s: (fsc:%p, p:%p, i:0x%p", __func__, CIFS_I(inode)->fscache, page, inode); ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, cifs_readpage_from_fscache_complete, @@ -167,11 +164,11 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) switch (ret) { case 0: /* page found in fscache, read submitted */ - cFYI(1, "CIFS: readpage_from_fscache: submitted"); + cFYI(1, "%s: submitted", __func__); return ret; case -ENOBUFS: /* page won't be cached */ case -ENODATA: /* page not in cache */ - cFYI(1, "CIFS: readpage_from_fscache %d", ret); + cFYI(1, "%s: %d", __func__, ret); return 1; default: @@ -190,7 +187,7 @@ int __cifs_readpages_from_fscache(struct inode *inode, { int ret; - cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)", + cFYI(1, "%s: (0x%p/%u/0x%p)", __func__, CIFS_I(inode)->fscache, *nr_pages, inode); ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, pages, nr_pages, @@ -199,12 +196,12 @@ int __cifs_readpages_from_fscache(struct inode *inode, mapping_gfp_mask(mapping)); switch (ret) { case 0: /* read submitted to the cache for all pages */ - cFYI(1, "CIFS: readpages_from_fscache: submitted"); + cFYI(1, "%s: submitted", __func__); return ret; case -ENOBUFS: /* some pages are not cached and can't be */ case -ENODATA: /* some pages are not cached */ - cFYI(1, "CIFS: readpages_from_fscache: no page"); + cFYI(1, "%s: no page", __func__); return 1; default: @@ -218,7 +215,7 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) { int ret; - cFYI(1, "CIFS: readpage_to_fscache(fsc: %p, p: %p, i: %p", + cFYI(1, "%s: (fsc: %p, p: %p, i: %p)", __func__, CIFS_I(inode)->fscache, page, inode); ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL); if (ret != 0) @@ -230,7 +227,7 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) struct cifsInodeInfo *cifsi = CIFS_I(inode); struct fscache_cookie *cookie = cifsi->fscache; - cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p)", page, cookie); + cFYI(1, "%s: (0x%p/0x%p)", __func__, page, cookie); fscache_wait_on_page_write(cookie, page); fscache_uncache_page(cookie, page); } -- cgit v1.2.3 From c46a131c0c0f4c2457e6b1e430c578a5cb057334 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 5 Jun 2011 11:12:31 +0000 Subject: xfs: fix ->mknod() return value on xfs_get_acl() failure ->mknod() should return negative on errors and PTR_ERR() gives already negative value... Signed-off-by: Al Viro Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/linux-2.6/xfs_iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index dd21784525a8..d44d92cd12b1 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -182,7 +182,7 @@ xfs_vn_mknod( if (IS_POSIXACL(dir)) { default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT); if (IS_ERR(default_acl)) - return -PTR_ERR(default_acl); + return PTR_ERR(default_acl); if (!default_acl) mode &= ~current_umask(); -- cgit v1.2.3 From 1252b3013b790c77e1c4f077a40542f86df37fb4 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 14 Jun 2011 16:19:54 +0000 Subject: [CIFS] update cifs version to 1.73 Signed-off-by: Steve French --- fs/cifs/cifsfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 64313f778ebf..0900e1658c96 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -129,5 +129,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern const struct export_operations cifs_export_ops; #endif /* CIFS_NFSD_EXPORT */ -#define CIFS_VERSION "1.72" +#define CIFS_VERSION "1.73" #endif /* _CIFSFS_H */ -- cgit v1.2.3 From ded509880f6a0213b09f8ae7bef84acb16eaccbf Mon Sep 17 00:00:00 2001 From: "Roy.Li" Date: Fri, 20 May 2011 10:38:06 +0800 Subject: SELinux: skip file_name_trans_write() when policy downgraded. When policy version is less than POLICYDB_VERSION_FILENAME_TRANS, skip file_name_trans_write(). Signed-off-by: Roy.Li Signed-off-by: Eric Paris --- security/selinux/ss/policydb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 102e9ec1b77a..d246aca3f4fb 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -3222,6 +3222,9 @@ static int filename_trans_write(struct policydb *p, void *fp) __le32 buf[1]; int rc; + if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) + return 0; + nel = 0; rc = hashtab_map(p->filename_trans, hashtab_cnt, &nel); if (rc) -- cgit v1.2.3 From df3c3931ec58cca3409c71b18ad6da0cd71fe163 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 14 Jun 2011 12:48:19 +0300 Subject: Bluetooth: Fix accepting connect requests for defer_setup When authentication completes we shouldn't blindly accept any pending L2CAP connect requests. If the socket has the defer_setup feature enabled it should still wait for user space acceptance of the connect request. The issue only happens for non-SSP connections since with SSP the L2CAP Connect request may not be sent for non-SDP PSMs before authentication has completed successfully. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e64a1c2df238..56fdd9162da9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -4002,21 +4002,30 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) } } else if (sk->sk_state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; - __u16 result; + __u16 res, stat; if (!status) { - sk->sk_state = BT_CONFIG; - result = L2CAP_CR_SUCCESS; + if (bt_sk(sk)->defer_setup) { + struct sock *parent = bt_sk(sk)->parent; + res = L2CAP_CR_PEND; + stat = L2CAP_CS_AUTHOR_PEND; + parent->sk_data_ready(parent, 0); + } else { + sk->sk_state = BT_CONFIG; + res = L2CAP_CR_SUCCESS; + stat = L2CAP_CS_NO_INFO; + } } else { sk->sk_state = BT_DISCONN; l2cap_sock_set_timer(sk, HZ / 10); - result = L2CAP_CR_SEC_BLOCK; + res = L2CAP_CR_SEC_BLOCK; + stat = L2CAP_CS_NO_INFO; } rsp.scid = cpu_to_le16(chan->dcid); rsp.dcid = cpu_to_le16(chan->scid); - rsp.result = cpu_to_le16(result); - rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); + rsp.result = cpu_to_le16(res); + rsp.status = cpu_to_le16(stat); l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); } -- cgit v1.2.3 From 60b8b1de0dd2bf246f0e074d287bb3f0bc42a755 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Tue, 14 Jun 2011 12:45:10 -0700 Subject: x86 idle: APM requires pm_idle/default_idle unconditionally when a module [ Also from Ben Hutchings and Vitaliy Ivanov ] Commit 06ae40ce073d ("x86 idle: EXPORT_SYMBOL(default_idle, pm_idle) only when APM demands it") removed the export for pm_idle/default_idle unless the apm module was modularised and CONFIG_APM_CPU_IDLE was set. But the apm module uses pm_idle/default_idle unconditionally, CONFIG_APM_CPU_IDLE only affects the bios idle threshold. Adjust the export accordingly. [ Used #ifdef instead of #if defined() as it's shorter, and what both Ben and Vitaliy used.. Andy, you're out-voted ;) - Linus ] Reported-by: Randy Dunlap Acked-by: Jiri Kosina Acked-by: Ingo Molnar Acked-by: Len Brown Signed-off-by: Andy Whitcroft Signed-off-by: Vitaliy Ivanov Signed-off-by: Ben Hutchings Signed-off-by: Linus Torvalds --- arch/x86/kernel/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 2e4928d45a2d..e1ba8cb24e4e 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -337,7 +337,7 @@ EXPORT_SYMBOL(boot_option_idle_override); * Powermanagement idle function, if any.. */ void (*pm_idle)(void); -#if defined(CONFIG_APM_MODULE) && defined(CONFIG_APM_CPU_IDLE) +#ifdef CONFIG_APM_MODULE EXPORT_SYMBOL(pm_idle); #endif @@ -399,7 +399,7 @@ void default_idle(void) cpu_relax(); } } -#if defined(CONFIG_APM_MODULE) && defined(CONFIG_APM_CPU_IDLE) +#ifdef CONFIG_APM_MODULE EXPORT_SYMBOL(default_idle); #endif -- cgit v1.2.3 From 357f45db920393aac983a137bd74095f612d5a01 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 13 Jun 2011 22:50:41 +0200 Subject: USB: TI 3410/5052 USB Serial Driver: Fix mem leak when firmware is too big. If the size of the firmware exceeds TI_FIRMWARE_BUF_SIZE we'll leak 'fw_p' by failing to call release_firmware(). This patch fixes the leak. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index c6d92a530086..ea8445689c85 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1745,6 +1745,7 @@ static int ti_download_firmware(struct ti_device *tdev) } if (fw_p->size > TI_FIRMWARE_BUF_SIZE) { dev_err(&dev->dev, "%s - firmware too large %zu\n", __func__, fw_p->size); + release_firmware(fw_p); return -ENOENT; } -- cgit v1.2.3 From 9a432736904d386cda28b987b38ba14dae960ecc Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 30 May 2011 20:38:55 -0700 Subject: rcu: Simplify curing of load woes Make the functions creating the kthreads wake them up. Leverage the fact that the per-node and boost kthreads can run anywhere, thus dispensing with the need to wake them up once the incoming CPU has gone fully online. Signed-off-by: Paul E. McKenney Tested-by: Daniel J Blueman --- kernel/rcutree.c | 65 ++++++++++++++++--------------------------------- kernel/rcutree_plugin.h | 11 +-------- 2 files changed, 22 insertions(+), 54 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 89419ff92e99..0a8ec5b2e208 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1635,6 +1635,20 @@ static int rcu_cpu_kthread(void *arg) * to manipulate rcu_cpu_kthread_task. There might be another CPU * attempting to access it during boot, but the locking in kthread_bind() * will enforce sufficient ordering. + * + * Please note that we cannot simply refuse to wake up the per-CPU + * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state, + * which can result in softlockup complaints if the task ends up being + * idle for more than a couple of minutes. + * + * However, please note also that we cannot bind the per-CPU kthread to its + * CPU until that CPU is fully online. We also cannot wait until the + * CPU is fully online before we create its per-CPU kthread, as this would + * deadlock the system when CPU notifiers tried waiting for grace + * periods. So we bind the per-CPU kthread to its CPU only if the CPU + * is online. If its CPU is not yet fully online, then the code in + * rcu_cpu_kthread() will wait until it is fully online, and then do + * the binding. */ static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) { @@ -1647,12 +1661,14 @@ static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu); if (IS_ERR(t)) return PTR_ERR(t); - kthread_bind(t, cpu); + if (cpu_online(cpu)) + kthread_bind(t, cpu); per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL); - per_cpu(rcu_cpu_kthread_task, cpu) = t; sp.sched_priority = RCU_KTHREAD_PRIO; sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + per_cpu(rcu_cpu_kthread_task, cpu) = t; + wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */ return 0; } @@ -1759,12 +1775,11 @@ static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp, raw_spin_unlock_irqrestore(&rnp->lock, flags); sp.sched_priority = 99; sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ } return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index); } -static void rcu_wake_one_boost_kthread(struct rcu_node *rnp); - /* * Spawn all kthreads -- called as soon as the scheduler is running. */ @@ -1772,30 +1787,18 @@ static int __init rcu_spawn_kthreads(void) { int cpu; struct rcu_node *rnp; - struct task_struct *t; rcu_kthreads_spawnable = 1; for_each_possible_cpu(cpu) { per_cpu(rcu_cpu_has_work, cpu) = 0; - if (cpu_online(cpu)) { + if (cpu_online(cpu)) (void)rcu_spawn_one_cpu_kthread(cpu); - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (t) - wake_up_process(t); - } } rnp = rcu_get_root(rcu_state); (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - if (rnp->node_kthread_task) - wake_up_process(rnp->node_kthread_task); if (NUM_RCU_NODES > 1) { - rcu_for_each_leaf_node(rcu_state, rnp) { + rcu_for_each_leaf_node(rcu_state, rnp) (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - t = rnp->node_kthread_task; - if (t) - wake_up_process(t); - rcu_wake_one_boost_kthread(rnp); - } } return 0; } @@ -2220,31 +2223,6 @@ static void __cpuinit rcu_prepare_kthreads(int cpu) } } -/* - * kthread_create() creates threads in TASK_UNINTERRUPTIBLE state, - * but the RCU threads are woken on demand, and if demand is low this - * could be a while triggering the hung task watchdog. - * - * In order to avoid this, poke all tasks once the CPU is fully - * up and running. - */ -static void __cpuinit rcu_online_kthreads(int cpu) -{ - struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); - struct rcu_node *rnp = rdp->mynode; - struct task_struct *t; - - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (t) - wake_up_process(t); - - t = rnp->node_kthread_task; - if (t) - wake_up_process(t); - - rcu_wake_one_boost_kthread(rnp); -} - /* * Handle CPU online/offline notification events. */ @@ -2262,7 +2240,6 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self, rcu_prepare_kthreads(cpu); break; case CPU_ONLINE: - rcu_online_kthreads(cpu); case CPU_DOWN_FAILED: rcu_node_kthread_setaffinity(rnp, -1); rcu_cpu_kthread_setrt(cpu, 1); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index c8bff3099a89..ea2e2fb79e81 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1299,15 +1299,10 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, raw_spin_unlock_irqrestore(&rnp->lock, flags); sp.sched_priority = RCU_KTHREAD_PRIO; sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ return 0; } -static void __cpuinit rcu_wake_one_boost_kthread(struct rcu_node *rnp) -{ - if (rnp->boost_kthread_task) - wake_up_process(rnp->boost_kthread_task); -} - #else /* #ifdef CONFIG_RCU_BOOST */ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) @@ -1331,10 +1326,6 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, return 0; } -static void __cpuinit rcu_wake_one_boost_kthread(struct rcu_node *rnp) -{ -} - #endif /* #else #ifdef CONFIG_RCU_BOOST */ #ifndef CONFIG_SMP -- cgit v1.2.3 From 09223371deac67d08ca0b70bd18787920284c967 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 14 Jun 2011 13:26:25 +0800 Subject: rcu: Use softirq to address performance regression Commit a26ac2455ffcf3(rcu: move TREE_RCU from softirq to kthread) introduced performance regression. In an AIM7 test, this commit degraded performance by about 40%. The commit runs rcu callbacks in a kthread instead of softirq. We observed high rate of context switch which is caused by this. Out test system has 64 CPUs and HZ is 1000, so we saw more than 64k context switch per second which is caused by RCU's per-CPU kthread. A trace showed that most of the time the RCU per-CPU kthread doesn't actually handle any callbacks, but instead just does a very small amount of work handling grace periods. This means that RCU's per-CPU kthreads are making the scheduler do quite a bit of work in order to allow a very small amount of RCU-related processing to be done. Alex Shi's analysis determined that this slowdown is due to lock contention within the scheduler. Unfortunately, as Peter Zijlstra points out, the scheduler's real-time semantics require global action, which means that this contention is inherent in real-time scheduling. (Yes, perhaps someone will come up with a workaround -- otherwise, -rt is not going to do well on large SMP systems -- but this patch will work around this issue in the meantime. And "the meantime" might well be forever.) This patch therefore re-introduces softirq processing to RCU, but only for core RCU work. RCU callbacks are still executed in kthread context, so that only a small amount of RCU work runs in softirq context in the common case. This should minimize ksoftirqd execution, allowing us to skip boosting of ksoftirqd for CONFIG_RCU_BOOST=y kernels. Signed-off-by: Shaohua Li Tested-by: "Alex,Shi" Signed-off-by: Paul E. McKenney --- Documentation/filesystems/proc.txt | 1 + include/linux/interrupt.h | 1 + include/trace/events/irq.h | 3 ++- kernel/rcutree.c | 23 +++++++++++++++++++---- kernel/rcutree.h | 1 + kernel/rcutree_plugin.h | 9 +++++++++ kernel/softirq.c | 2 +- tools/perf/util/trace-event-parse.c | 1 + 8 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index f48178024067..db3b1aba32a3 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -843,6 +843,7 @@ Provides counts of softirq handlers serviced since boot time, for each cpu. TASKLET: 0 0 0 290 SCHED: 27035 26983 26971 26746 HRTIMER: 0 0 0 0 + RCU: 1678 1769 2178 2250 1.3 IDE devices in /proc/ide diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 6c12989839d9..f6efed0039ed 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -414,6 +414,7 @@ enum TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, + RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS }; diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h index ae045ca7d356..1c09820df585 100644 --- a/include/trace/events/irq.h +++ b/include/trace/events/irq.h @@ -20,7 +20,8 @@ struct softirq_action; softirq_name(BLOCK_IOPOLL), \ softirq_name(TASKLET), \ softirq_name(SCHED), \ - softirq_name(HRTIMER)) + softirq_name(HRTIMER), \ + softirq_name(RCU)) /** * irq_handler_entry - called immediately before the irq action handler diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 0a8ec5b2e208..ae5c9ea68662 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -100,6 +100,7 @@ static char rcu_kthreads_spawnable; static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu); static void invoke_rcu_cpu_kthread(void); +static void __invoke_rcu_cpu_kthread(void); #define RCU_KTHREAD_PRIO 1 /* RT priority for per-CPU kthreads. */ @@ -1442,13 +1443,21 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) } /* If there are callbacks ready, invoke them. */ - rcu_do_batch(rsp, rdp); + if (cpu_has_callbacks_ready_to_invoke(rdp)) + __invoke_rcu_cpu_kthread(); +} + +static void rcu_kthread_do_work(void) +{ + rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); + rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); + rcu_preempt_do_callbacks(); } /* * Do softirq processing for the current CPU. */ -static void rcu_process_callbacks(void) +static void rcu_process_callbacks(struct softirq_action *unused) { __rcu_process_callbacks(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); @@ -1465,7 +1474,7 @@ static void rcu_process_callbacks(void) * the current CPU with interrupts disabled, the rcu_cpu_kthread_task * cannot disappear out from under us. */ -static void invoke_rcu_cpu_kthread(void) +static void __invoke_rcu_cpu_kthread(void) { unsigned long flags; @@ -1479,6 +1488,11 @@ static void invoke_rcu_cpu_kthread(void) local_irq_restore(flags); } +static void invoke_rcu_cpu_kthread(void) +{ + raise_softirq(RCU_SOFTIRQ); +} + /* * Wake up the specified per-rcu_node-structure kthread. * Because the per-rcu_node kthreads are immortal, we don't need @@ -1613,7 +1627,7 @@ static int rcu_cpu_kthread(void *arg) *workp = 0; local_irq_restore(flags); if (work) - rcu_process_callbacks(); + rcu_kthread_do_work(); local_bh_enable(); if (*workp != 0) spincnt++; @@ -2387,6 +2401,7 @@ void __init rcu_init(void) rcu_init_one(&rcu_sched_state, &rcu_sched_data); rcu_init_one(&rcu_bh_state, &rcu_bh_data); __rcu_init_preempt(); + open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); /* * We don't need protection against CPU-hotplug here because diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 7b9a08b4aaea..0fed6b934d2a 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -439,6 +439,7 @@ static void rcu_preempt_offline_cpu(int cpu); #endif /* #ifdef CONFIG_HOTPLUG_CPU */ static void rcu_preempt_check_callbacks(int cpu); static void rcu_preempt_process_callbacks(void); +static void rcu_preempt_do_callbacks(void); void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index ea2e2fb79e81..38d09c5f2b41 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -602,6 +602,11 @@ static void rcu_preempt_process_callbacks(void) &__get_cpu_var(rcu_preempt_data)); } +static void rcu_preempt_do_callbacks(void) +{ + rcu_do_batch(&rcu_preempt_state, &__get_cpu_var(rcu_preempt_data)); +} + /* * Queue a preemptible-RCU callback for invocation after a grace period. */ @@ -997,6 +1002,10 @@ static void rcu_preempt_process_callbacks(void) { } +static void rcu_preempt_do_callbacks(void) +{ +} + /* * Wait for an rcu-preempt grace period, but make it happen quickly. * But because preemptible RCU does not exist, map to rcu-sched. diff --git a/kernel/softirq.c b/kernel/softirq.c index 13960170cad4..40cf63ddd4b3 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -58,7 +58,7 @@ DEFINE_PER_CPU(struct task_struct *, ksoftirqd); char *softirq_to_name[NR_SOFTIRQS] = { "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL", - "TASKLET", "SCHED", "HRTIMER" + "TASKLET", "SCHED", "HRTIMER", "RCU" }; /* diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 1e88485c16a0..0a7ed5b5e281 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -2187,6 +2187,7 @@ static const struct flag flags[] = { { "TASKLET_SOFTIRQ", 6 }, { "SCHED_SOFTIRQ", 7 }, { "HRTIMER_SOFTIRQ", 8 }, + { "RCU_SOFTIRQ", 9 }, { "HRTIMER_NORESTART", 0 }, { "HRTIMER_RESTART", 1 }, -- cgit v1.2.3 From ada9c93312f7ec49514c68c211595ce2601cebae Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 15:50:11 -0700 Subject: signal.c: fix kernel-doc notation Fix kernel-doc warnings in signal.c: Warning(kernel/signal.c:2374): No description found for parameter 'nset' Warning(kernel/signal.c:2374): Excess function parameter 'set' description in 'sys_rt_sigprocmask' Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/signal.c b/kernel/signal.c index 86c32b884f8e..ff7678603328 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2365,7 +2365,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset) /** * sys_rt_sigprocmask - change the list of currently blocked signals * @how: whether to add, remove, or set signals - * @set: stores pending signals + * @nset: stores pending signals * @oset: previous value of signal mask if non-null * @sigsetsize: size of sigset_t type */ -- cgit v1.2.3 From d521dd944e461371cb309c7c3568483cd2b6f5f2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 14 Jun 2011 14:27:22 +0000 Subject: fbdev: sh_mobile_hdmi: fix regression: statically enable RTPM A recent modification to the runtime PM code on mach-shmobile made a wrong RTPM implementation in the sh_mobile_hdmi driver apparent, which broke HDMI hotplug detection support on ap4evb. This patch does not implement a proper dynamic RTPM support for sh_mobile_hdmi, instead it restores the previous working state by statically enabling it. A more power-efficient solution should be implemented for the next kernel version. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_hdmi.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 6ae40b630dc9..7d54e2c612f7 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c @@ -1127,23 +1127,16 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) struct fb_info *info = hdmi->info; unsigned long parent_rate = 0, hdmi_rate; - /* A device has been plugged in */ - pm_runtime_get_sync(hdmi->dev); - ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); - if (ret < 0) { - pm_runtime_put(hdmi->dev); + if (ret < 0) goto out; - } hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; /* Reconfigure the clock */ ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate); - if (ret < 0) { - pm_runtime_put(hdmi->dev); + if (ret < 0) goto out; - } msleep(10); sh_hdmi_configure(hdmi); @@ -1191,7 +1184,6 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) fb_set_suspend(hdmi->info, 1); console_unlock(); - pm_runtime_put(hdmi->dev); } out: @@ -1312,7 +1304,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn); pm_runtime_enable(&pdev->dev); - pm_runtime_resume(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); /* Product and revision IDs are 0 in sh-mobile version */ dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", @@ -1340,7 +1332,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) ecodec: free_irq(irq, hdmi); ereqirq: - pm_runtime_suspend(&pdev->dev); + pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); iounmap(hdmi->base); emap: @@ -1377,7 +1369,7 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) free_irq(irq, hdmi); /* Wait for already scheduled work */ cancel_delayed_work_sync(&hdmi->edid_work); - pm_runtime_suspend(&pdev->dev); + pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable(hdmi->hdmi_clk); clk_put(hdmi->hdmi_clk); -- cgit v1.2.3 From 05a7929f31a0d516a9c19012bf27a1ea5058dc7a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 15 Jun 2011 06:16:35 +0000 Subject: ARM: mach-shmobile: mackerel: tidyup usbhs driver settings - usb0 pipe is same as default. own pipe config is not needed - usb1 lost get_id function Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-mackerel.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 1037bd2ffdb9..7e1d37584321 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -629,19 +629,6 @@ static void usbhs0_hardware_exit(struct platform_device *pdev) cancel_delayed_work_sync(&priv->work); } -static u32 usbhs0_pipe_cfg[] = { - USB_ENDPOINT_XFER_CONTROL, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_BULK, -}; - static struct usbhs_private usbhs0_private = { .usbcrcaddr = 0xe605810c, /* USBCR2 */ .info = { @@ -654,8 +641,6 @@ static struct usbhs_private usbhs0_private = { }, .driver_param = { .buswait_bwait = 4, - .pipe_type = usbhs0_pipe_cfg, - .pipe_size = ARRAY_SIZE(usbhs0_pipe_cfg), }, }, }; @@ -786,6 +771,11 @@ static void usbhs1_hardware_exit(struct platform_device *pdev) free_irq(IRQ8, pdev); } +static int usbhs1_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + static u32 usbhs1_pipe_cfg[] = { USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, @@ -812,6 +802,7 @@ static struct usbhs_private usbhs1_private = { .platform_callback = { .hardware_init = usbhs1_hardware_init, .hardware_exit = usbhs1_hardware_exit, + .get_id = usbhs1_get_id, .phy_reset = usbhs_phy_reset, .get_vbus = usbhs_get_vbus, }, -- cgit v1.2.3 From 8dd0de8be31b4b966d17750a0b10df2f575c91ac Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 14 Jun 2011 18:36:24 -0400 Subject: sched: Fix need_resched() when checking peempt The RT preempt check tests the wrong task if NEED_RESCHED is set. It currently checks the local CPU task. It is supposed to check the task that is running on the runqueue we are about to wake another task on. Signed-off-by: Hillf Danton Reviewed-by: Yong Zhang Signed-off-by: Steven Rostedt Link: http://lkml.kernel.org/r/20110614223657.450239027@goodmis.org Signed-off-by: Ingo Molnar --- kernel/sched_rt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 88725c939e0b..9b8d5dce946e 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1096,7 +1096,7 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag * to move current somewhere else, making room for our non-migratable * task. */ - if (p->prio == rq->curr->prio && !need_resched()) + if (p->prio == rq->curr->prio && !test_tsk_need_resched(rq->curr)) check_preempt_equal_prio(rq, p); #endif } -- cgit v1.2.3 From 0da938c44921cfb690283d3b0c9c48a10375db2c Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Jun 2011 18:36:25 -0400 Subject: sched: Check if lowest_mask is initialized in find_lowest_rq() On system boot up, the lowest_mask is initialized with an early_initcall(). But RT tasks may wake up on other early_initcall() callers before the lowest_mask is initialized, causing a system crash. Commit "d72bce0e67 rcu: Cure load woes" was the first commit to wake up RT tasks in early init. Before this commit this bug should not happen. Reported-by: Andrew Theurer Tested-by: Andrew Theurer Tested-by: Paul E. McKenney Signed-off-by: Steven Rostedt Acked-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20110614223657.824872966@goodmis.org Signed-off-by: Ingo Molnar --- kernel/sched_rt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 9b8d5dce946e..10d018212bab 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1239,6 +1239,10 @@ static int find_lowest_rq(struct task_struct *task) int this_cpu = smp_processor_id(); int cpu = task_cpu(task); + /* Make sure the mask is initialized first */ + if (unlikely(!lowest_mask)) + return -1; + if (task->rt.nr_cpus_allowed == 1) return -1; /* No other targets possible */ -- cgit v1.2.3 From a7b21165c06f28230768d203285d06cac4f18f0b Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Mon, 13 Jun 2011 09:49:27 +0530 Subject: mwifiex: Fixing NULL pointer dereference Following OOPS was seen when booting with card inserted BUG: unable to handle kernel NULL pointer dereference at 0000004c IP: [] cfg80211_get_drvinfo+0x21/0x115 [cfg80211] *pde = 00000000 Oops: 0000 [#1] SMP Modules linked in: iwl3945 iwl_legacy mwifiex_sdio mac80211 11 sdhci_pci sdhci pl2303 'ethtool' on the mwifiex device returned this OOPS as wiphy_dev() returned NULL. Adding missing set_wiphy_dev() call to fix the problem. Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 660831ce293c..687c1f223497 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1288,6 +1288,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, *(unsigned long *) wdev_priv = (unsigned long) priv; + set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev); + ret = wiphy_register(wdev->wiphy); if (ret < 0) { dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", -- cgit v1.2.3 From 3373b28e5af4a0b3c6cb39372581dcc1e41322ff Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Mon, 13 Jun 2011 16:26:15 +0530 Subject: mwl8k: Tell firmware to generate CCMP header Post commit e4eefec73ea0a740bfe8736e3ac30dfe92fe392b, the stack is not generating the CCMP header for us anymore. This broke the CCMP functionality since firmware was not doing this either. Set a flag to tell the firmware to generate the CCMP header Signed-off-by: Nishant Sarmukadam Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 32261189bcef..aeac3cc4dbe4 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2474,6 +2474,7 @@ struct mwl8k_cmd_set_hw_spec { * faster client. */ #define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400 +#define MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR 0x00000200 #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 @@ -2510,7 +2511,8 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON | - MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY); + MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY | + MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); -- cgit v1.2.3 From 8fe7e94eb71430cf63a742f3c19739d82a662758 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 1 Jun 2011 15:31:44 +0200 Subject: oprofile, x86: Fix race in nmi handler while starting counters In some rare cases, nmis are generated immediately after the nmi handler of the cpu was started. This causes the counter not to be enabled. Before enabling the nmi handlers we need to set variable ctr_running first and make sure its value is written to memory. Also, the patch makes all existing barriers a memory barrier instead of a compiler barrier only. Reported-by: Suravee Suthikulpanit Cc: # .35+ Signed-off-by: Robert Richter --- arch/x86/oprofile/nmi_int.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index cf9750004a08..68894fdc034b 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -112,8 +112,10 @@ static void nmi_cpu_start(void *dummy) static int nmi_start(void) { get_online_cpus(); - on_each_cpu(nmi_cpu_start, NULL, 1); ctr_running = 1; + /* make ctr_running visible to the nmi handler: */ + smp_mb(); + on_each_cpu(nmi_cpu_start, NULL, 1); put_online_cpus(); return 0; } @@ -504,15 +506,18 @@ static int nmi_setup(void) nmi_enabled = 0; ctr_running = 0; - barrier(); + /* make variables visible to the nmi handler: */ + smp_mb(); err = register_die_notifier(&profile_exceptions_nb); if (err) goto fail; get_online_cpus(); register_cpu_notifier(&oprofile_cpu_nb); - on_each_cpu(nmi_cpu_setup, NULL, 1); nmi_enabled = 1; + /* make nmi_enabled visible to the nmi handler: */ + smp_mb(); + on_each_cpu(nmi_cpu_setup, NULL, 1); put_online_cpus(); return 0; @@ -531,7 +536,8 @@ static void nmi_shutdown(void) nmi_enabled = 0; ctr_running = 0; put_online_cpus(); - barrier(); + /* make variables visible to the nmi handler: */ + smp_mb(); unregister_die_notifier(&profile_exceptions_nb); msrs = &get_cpu_var(cpu_msrs); model->shutdown(msrs); -- cgit v1.2.3 From e72888e91cc902ccdc089f237b6eed7587e2b4df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 15 Jun 2011 15:14:49 +0200 Subject: ALSA: lola - Fix section mismatch Add missing __devinit. Signed-off-by: Takashi Iwai --- sound/pci/lola/lola.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 34b24286d279..2692e5ae5f2d 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c @@ -445,7 +445,7 @@ static void lola_reset_setups(struct lola *chip) lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */ } -static int lola_parse_tree(struct lola *chip) +static int __devinit lola_parse_tree(struct lola *chip) { unsigned int val; int nid, err; -- cgit v1.2.3 From 9e3bd4e24e94d60d2e0762e919aab6c9a7fc0c5b Mon Sep 17 00:00:00 2001 From: Weston Andros Adamson Date: Tue, 31 May 2011 21:46:50 -0400 Subject: NFS: fix umount of pnfs filesystems Unmounting a pnfs filesystem hangs using filelayout and possibly others. This fixes the use of the rcu protected node by making use of a new 'tmpnode' for the temporary purge list. Also, the spinlock shouldn't be held when calling synchronize_rcu(). Signed-off-by: Weston Andros Adamson Signed-off-by: Andy Adamson Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.h | 1 + fs/nfs/pnfs_dev.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 48d0a8e4d062..96bf4e6f45be 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -186,6 +186,7 @@ int pnfs_ld_read_done(struct nfs_read_data *); /* pnfs_dev.c */ struct nfs4_deviceid_node { struct hlist_node node; + struct hlist_node tmpnode; const struct pnfs_layoutdriver_type *ld; const struct nfs_client *nfs_client; struct nfs4_deviceid deviceid; diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index c65e133ce9c0..5944d4b369a2 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c @@ -174,6 +174,7 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d, const struct nfs4_deviceid *id) { INIT_HLIST_NODE(&d->node); + INIT_HLIST_NODE(&d->tmpnode); d->ld = ld; d->nfs_client = nfs_client; d->deviceid = *id; @@ -238,24 +239,29 @@ static void _deviceid_purge_client(const struct nfs_client *clp, long hash) { struct nfs4_deviceid_node *d; - struct hlist_node *n, *next; + struct hlist_node *n; HLIST_HEAD(tmp); + spin_lock(&nfs4_deviceid_lock); rcu_read_lock(); hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node) if (d->nfs_client == clp && atomic_read(&d->ref)) { hlist_del_init_rcu(&d->node); - hlist_add_head(&d->node, &tmp); + hlist_add_head(&d->tmpnode, &tmp); } rcu_read_unlock(); + spin_unlock(&nfs4_deviceid_lock); if (hlist_empty(&tmp)) return; synchronize_rcu(); - hlist_for_each_entry_safe(d, n, next, &tmp, node) + while (!hlist_empty(&tmp)) { + d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode); + hlist_del(&d->tmpnode); if (atomic_dec_and_test(&d->ref)) d->ld->free_deviceid_node(d); + } } void @@ -263,8 +269,8 @@ nfs4_deviceid_purge_client(const struct nfs_client *clp) { long h; - spin_lock(&nfs4_deviceid_lock); + if (!(clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_MDS)) + return; for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++) _deviceid_purge_client(clp, h); - spin_unlock(&nfs4_deviceid_lock); } -- cgit v1.2.3 From 0b760113a3a155269a3fba93a409c640031dd68f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 31 May 2011 15:15:34 -0400 Subject: NLM: Don't hang forever on NLM unlock requests If the NLM daemon is killed on the NFS server, we can currently end up hanging forever on an 'unlock' request, instead of aborting. Basically, if the rpcbind request fails, or the server keeps returning garbage, we really want to quit instead of retrying. Tested-by: Vasily Averin Signed-off-by: Trond Myklebust Cc: stable@kernel.org --- fs/lockd/clntproc.c | 8 +++++++- include/linux/sunrpc/sched.h | 3 ++- net/sunrpc/clnt.c | 3 +++ net/sunrpc/sched.c | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index adb45ec9038c..e374050a911c 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -708,7 +708,13 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) if (task->tk_status < 0) { dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status); - goto retry_rebind; + switch (task->tk_status) { + case -EACCES: + case -EIO: + goto die; + default: + goto retry_rebind; + } } if (status == NLM_LCK_DENIED_GRACE_PERIOD) { rpc_delay(task, NLMCLNT_GRACE_WAIT); diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index f73c482ec9c6..fe2d8e6b923b 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -84,7 +84,8 @@ struct rpc_task { #endif unsigned char tk_priority : 2,/* Task priority */ tk_garb_retry : 2, - tk_cred_retry : 2; + tk_cred_retry : 2, + tk_rebind_retry : 2; }; #define tk_xprt tk_client->cl_xprt diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index b84d7395535e..566bcfd067f6 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1175,6 +1175,9 @@ call_bind_status(struct rpc_task *task) status = -EOPNOTSUPP; break; } + if (task->tk_rebind_retry == 0) + break; + task->tk_rebind_retry--; rpc_delay(task, 3*HZ); goto retry_timeout; case -ETIMEDOUT: diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 6b43ee7221d5..a27406b1654f 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -792,6 +792,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta /* Initialize retry counters */ task->tk_garb_retry = 2; task->tk_cred_retry = 2; + task->tk_rebind_retry = 2; task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW; task->tk_owner = current->tgid; -- cgit v1.2.3 From 0f66b5984df2fe1617c05900a39a7ef493ca9de9 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Sat, 16 Oct 2010 22:07:46 -0700 Subject: NFS41: do not update isize if inode needs layoutcommit nfs_update_inode will update isize if there is no queued pages. For pNFS, layoutcommit is supposed to change file size on server, the same effect as queued pages. nfs_update_inode may be called when dirty pages are written back (nfsi->npages==0) but layoutcommit is not sent, and it will change client file size according to server file size. Then client ends up losing what it just writes back in pNFS path. So we should skip updating client file size if file needs layoutcommit. Signed-off-by: Peng Tao Cc: stable@kernel.org [2.6.39] Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 144f2a3c7185..3f1eb8180373 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1294,7 +1294,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) if (new_isize != cur_isize) { /* Do we perhaps have any outstanding writes, or has * the file grown beyond our last write? */ - if (nfsi->npages == 0 || new_isize > cur_isize) { + if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) || + new_isize > cur_isize) { i_size_write(inode, new_isize); invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; } -- cgit v1.2.3 From c9c30dd5f73dccaa326a54dfcf490316946aea87 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Sat, 11 Jun 2011 17:08:39 -0400 Subject: NFSv4.1: deprecate headerpadsz in CREATE_SESSION We don't support header padding yet so better off ditching it Reported-by: Sid Moore Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 4 ---- fs/nfs/nfs4xdr.c | 10 ++++++---- include/linux/nfs_xdr.h | 1 - 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d2c4b59c896d..3ca449789545 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5098,7 +5098,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) if (mxresp_sz == 0) mxresp_sz = NFS_MAX_FILE_IO_SIZE; /* Fore channel attributes */ - args->fc_attrs.headerpadsz = 0; args->fc_attrs.max_rqst_sz = mxrqst_sz; args->fc_attrs.max_resp_sz = mxresp_sz; args->fc_attrs.max_ops = NFS4_MAX_OPS; @@ -5111,7 +5110,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) args->fc_attrs.max_ops, args->fc_attrs.max_reqs); /* Back channel attributes */ - args->bc_attrs.headerpadsz = 0; args->bc_attrs.max_rqst_sz = PAGE_SIZE; args->bc_attrs.max_resp_sz = PAGE_SIZE; args->bc_attrs.max_resp_sz_cached = 0; @@ -5131,8 +5129,6 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args struct nfs4_channel_attrs *sent = &args->fc_attrs; struct nfs4_channel_attrs *rcvd = &session->fc_attrs; - if (rcvd->headerpadsz > sent->headerpadsz) - return -EINVAL; if (rcvd->max_resp_sz > sent->max_resp_sz) return -EINVAL; /* diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index d869a5e5464b..c4b7d6c04948 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -1725,7 +1725,7 @@ static void encode_create_session(struct xdr_stream *xdr, *p++ = cpu_to_be32(args->flags); /*flags */ /* Fore Channel */ - *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ + *p++ = cpu_to_be32(0); /* header padding size */ *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ @@ -1734,7 +1734,7 @@ static void encode_create_session(struct xdr_stream *xdr, *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ /* Back Channel */ - *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ + *p++ = cpu_to_be32(0); /* header padding size */ *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ @@ -4997,12 +4997,14 @@ static int decode_chan_attrs(struct xdr_stream *xdr, struct nfs4_channel_attrs *attrs) { __be32 *p; - u32 nr_attrs; + u32 nr_attrs, val; p = xdr_inline_decode(xdr, 28); if (unlikely(!p)) goto out_overflow; - attrs->headerpadsz = be32_to_cpup(p++); + val = be32_to_cpup(p++); /* headerpadsz */ + if (val) + return -EINVAL; /* no support for header padding yet */ attrs->max_rqst_sz = be32_to_cpup(p++); attrs->max_resp_sz = be32_to_cpup(p++); attrs->max_resp_sz_cached = be32_to_cpup(p++); diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 5e8444a11adf..00848d86ffb2 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -158,7 +158,6 @@ struct nfs_seqid; /* nfs41 sessions channel attributes */ struct nfs4_channel_attrs { - u32 headerpadsz; u32 max_rqst_sz; u32 max_resp_sz; u32 max_resp_sz_cached; -- cgit v1.2.3 From 1d92a08da23848a38eece4df7eaa4e8ec0e6c699 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 14 Jun 2011 12:07:38 -0400 Subject: NFSv4.1: Fix a refcounting issue in the pNFS device id cache When we add something to the global device id cache, we need to bump the reference count, so that the cache itself holds a reference. Signed-off-by: Trond Myklebust --- fs/nfs/pnfs_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index 5944d4b369a2..f0f8e1e22f6c 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c @@ -209,6 +209,7 @@ nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new) hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); spin_unlock(&nfs4_deviceid_lock); + atomic_inc(&new->ref); return new; } -- cgit v1.2.3 From 533eb4611c9eea53072eb6a61d5a6393b6a77ed7 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Mon, 13 Jun 2011 18:25:56 -0400 Subject: NFSv4.1: allow nfs_fhget to succeed with mounted on fileid Commit 28331a46d88459788c8fca72dbb0415cd7f514c9 "Ensure we request the ordinary fileid when doing readdirplus" changed the meaning of NFS_ATTR_FATTR_FILEID which used to be set when FATTR4_WORD1_MOUNTED_ON_FILED was requested. Allow nfs_fhget to succeed with only a mounted on fileid when crossing a mountpoint or a referral. Ask for the fileid of the absent file system if mounted_on_fileid is not supported. Signed-off-by: Andy Adamson cc:stable@kernel.org [2.6.39] Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 3 ++- fs/nfs/internal.h | 11 +++++++++++ fs/nfs/nfs4proc.c | 33 +++++++++++++++++++++++---------- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 3f1eb8180373..6f4850deb272 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -256,7 +256,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) nfs_attr_check_mountpoint(sb, fattr); - if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) + if (((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) && + !nfs_attr_use_mounted_on_fileid(fattr)) goto out_no_inode; if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) goto out_no_inode; diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index b9056cbe68d6..2a55347a2daa 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -45,6 +45,17 @@ static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; } +static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr) +{ + if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) || + (((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) && + ((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0))) + return 0; + + fattr->fileid = fattr->mounted_on_fileid; + return 1; +} + struct nfs_clone_mount { const struct super_block *sb; const struct dentry *dentry; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3ca449789545..289c539bd6b3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2265,12 +2265,14 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, return nfs4_map_errors(status); } +static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); /* * Get locations and (maybe) other attributes of a referral. * Note that we'll actually follow the referral later when * we detect fsid mismatch in inode revalidation */ -static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle) +static int nfs4_get_referral(struct inode *dir, const struct qstr *name, + struct nfs_fattr *fattr, struct nfs_fh *fhandle) { int status = -ENOMEM; struct page *page = NULL; @@ -2288,15 +2290,16 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct goto out; /* Make sure server returned a different fsid for the referral */ if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) { - dprintk("%s: server did not return a different fsid for a referral at %s\n", __func__, name->name); + dprintk("%s: server did not return a different fsid for" + " a referral at %s\n", __func__, name->name); status = -EIO; goto out; } + /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */ + nfs_fixup_referral_attributes(&locations->fattr); + /* replace the lookup nfs_fattr with the locations nfs_fattr */ memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr)); - fattr->valid |= NFS_ATTR_FATTR_V4_REFERRAL; - if (!fattr->mode) - fattr->mode = S_IFDIR; memset(fhandle, 0, sizeof(struct nfs_fh)); out: if (page) @@ -4667,11 +4670,15 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list, return len; } +/* + * nfs_fhget will use either the mounted_on_fileid or the fileid + */ static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) { - if (!((fattr->valid & NFS_ATTR_FATTR_FILEID) && - (fattr->valid & NFS_ATTR_FATTR_FSID) && - (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL))) + if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) || + (fattr->valid & NFS_ATTR_FATTR_FILEID)) && + (fattr->valid & NFS_ATTR_FATTR_FSID) && + (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL))) return; fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | @@ -4686,7 +4693,6 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, struct nfs_server *server = NFS_SERVER(dir); u32 bitmask[2] = { [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, - [1] = FATTR4_WORD1_MOUNTED_ON_FILEID, }; struct nfs4_fs_locations_arg args = { .dir_fh = NFS_FH(dir), @@ -4705,11 +4711,18 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, int status; dprintk("%s: start\n", __func__); + + /* Ask for the fileid of the absent filesystem if mounted_on_fileid + * is not supported */ + if (NFS_SERVER(dir)->attr_bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) + bitmask[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID; + else + bitmask[0] |= FATTR4_WORD0_FILEID; + nfs_fattr_init(&fs_locations->fattr); fs_locations->server = server; fs_locations->nlocations = 0; status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); - nfs_fixup_referral_attributes(&fs_locations->fattr); dprintk("%s: returned status = %d\n", __func__, status); return status; } -- cgit v1.2.3 From cec765cf5891c7fc3d905832b481bfb6fd55825d Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Mon, 13 Jun 2011 18:36:17 -0400 Subject: NFSv4.1: allow zero fh array in filelayout decode layout Signed-off-by: Andy Adamson cc:stable@kernel.org [2.6.39] Signed-off-by: Trond Myklebust --- fs/nfs/nfs4filelayout.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 426908809c97..5d6f369b15d0 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -552,13 +552,18 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, __func__, nfl_util, fl->num_fh, fl->first_stripe_index, fl->pattern_offset); - if (!fl->num_fh) + /* Note that a zero value for num_fh is legal for STRIPE_SPARSE. + * Futher checking is done in filelayout_check_layout */ + if (fl->num_fh < 0 || fl->num_fh > + max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT)) goto out_err; - fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), - gfp_flags); - if (!fl->fh_array) - goto out_err; + if (fl->num_fh > 0) { + fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), + gfp_flags); + if (!fl->fh_array) + goto out_err; + } for (i = 0; i < fl->num_fh; i++) { /* Do we want to use a mempool here? */ -- cgit v1.2.3 From a2e1d4f2e5ed83850de92a491ef225824cb457bd Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Mon, 13 Jun 2011 18:54:53 -0400 Subject: nfs4.1: fix several problems with _pnfs_return_layout _pnfs_return_layout had the following problems: - it did not call pnfs_free_lseg_list on all paths - it unintentionally did a forgetful return when there was no outstanding io - it raced with concurrent LAYOUTGETS Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 8 ++++---- fs/nfs/pnfs.c | 8 +++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 289c539bd6b3..5879b23e0c99 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5706,6 +5706,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) { struct nfs4_layoutreturn *lrp = calldata; struct nfs_server *server; + struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout; dprintk("--> %s\n", __func__); @@ -5717,16 +5718,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) nfs_restart_rpc(task, lrp->clp); return; } + spin_lock(&lo->plh_inode->i_lock); if (task->tk_status == 0) { - struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout; - if (lrp->res.lrs_present) { - spin_lock(&lo->plh_inode->i_lock); pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); - spin_unlock(&lo->plh_inode->i_lock); } else BUG_ON(!list_empty(&lo->plh_segs)); } + lo->plh_block_lgets--; + spin_unlock(&lo->plh_inode->i_lock); dprintk("<-- %s\n", __func__); } diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 8c1309d852a6..25de6b27bdf4 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -634,12 +634,14 @@ _pnfs_return_layout(struct inode *ino) spin_lock(&ino->i_lock); lo = nfsi->layout; - if (!lo || !mark_matching_lsegs_invalid(lo, &tmp_list, NULL)) { + if (!lo) { spin_unlock(&ino->i_lock); - dprintk("%s: no layout segments to return\n", __func__); - goto out; + dprintk("%s: no layout to return\n", __func__); + return status; } stateid = nfsi->layout->plh_stateid; + mark_matching_lsegs_invalid(lo, &tmp_list, NULL); + lo->plh_block_lgets++; /* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr(lo); spin_unlock(&ino->i_lock); -- cgit v1.2.3 From d771e3a43e23a37398b7e05a9d1b1036d698263c Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Tue, 14 Jun 2011 16:30:16 -0400 Subject: NFSv4.1: fix break condition in pnfs_find_lseg The break condition to skip out of the loop got broken when cmp_layout was change. Essentially, we want to stop looking once we know no layout on the remainder of the list can match the first byte of the looked-up range. Reported-by: Peng Tao Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 25de6b27bdf4..d066aad608ad 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -889,7 +889,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, ret = get_lseg(lseg); break; } - if (cmp_layout(range, &lseg->pls_range) > 0) + if (lseg->pls_range.offset > range->offset) break; } -- cgit v1.2.3 From c7fd06228b994190d8369a2a0acf5224e4e13d1a Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 15 Jun 2011 00:55:44 +0100 Subject: NFS: (d)printks should use %zd for ssize_t arguments (d)printks should use %zd for ssize_t arguments not %ld, otherwise they might get a warning. I see the following with MN10300. fs/nfs/objlayout/objlayout.c: In function 'objlayout_read_done': fs/nfs/objlayout/objlayout.c:294: warning: format '%ld' expects type 'long int', but argument 3 has type 'ssize_t' Signed-off-by: David Howells cc: Trond Myklebust cc: linux-nfs@vger.kernel.org Signed-off-by: Trond Myklebust --- fs/nfs/objlayout/objlayout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index dc3956c0de80..1d06f8e2adea 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c @@ -291,7 +291,7 @@ objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync) struct nfs_read_data *rdata; state->status = status; - dprintk("%s: Begin status=%ld eof=%d\n", __func__, status, eof); + dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof); rdata = state->rpcdata; rdata->task.tk_status = status; if (status >= 0) { -- cgit v1.2.3 From 1ed3a8539af7b36aa5c977f304e80f7fc8d27bfc Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Wed, 15 Jun 2011 11:39:57 -0400 Subject: NFSv4.1: need to put_layout_hdr on _pnfs_return_layout error path We always get a reference on the layout header and we rely on nfs4_layoutreturn_release to put it. If we hit an allocation error before starting the rpc proc we bail out early without dereferncing the layout header properly. Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index d066aad608ad..8f9582281252 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -652,6 +652,7 @@ _pnfs_return_layout(struct inode *ino) lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); if (unlikely(lrp == NULL)) { status = -ENOMEM; + put_layout_hdr(lo); goto out; } -- cgit v1.2.3 From ea0ded748bdea78f9e2fefb571f7d6ce9edb4f89 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 15 Jun 2011 12:31:02 -0400 Subject: nfs4.1: prevent race that allowed use of freed layout in _pnfs_return_layout mark_matching_lsegs_invalid could put the last ref to the layout, so the get_layout_hdr needs to be called first. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 8f9582281252..730d4dbbaf68 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -640,10 +640,10 @@ _pnfs_return_layout(struct inode *ino) return status; } stateid = nfsi->layout->plh_stateid; - mark_matching_lsegs_invalid(lo, &tmp_list, NULL); - lo->plh_block_lgets++; /* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr(lo); + mark_matching_lsegs_invalid(lo, &tmp_list, NULL); + lo->plh_block_lgets++; spin_unlock(&ino->i_lock); pnfs_free_lseg_list(&tmp_list); -- cgit v1.2.3 From 71d7aed014457147e8f71a843d5fbf03235e4a85 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 14 Jun 2011 14:24:32 -0400 Subject: Btrfs: fix path leakage on subvol deletion The delayed ref patch accidently removed the btrfs_free_path in btrfs_unlink_subvol, this puts it back and means we don't leak a path. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c15636b17874..5813dec5101c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3076,6 +3076,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, ret = btrfs_update_inode(trans, root, dir); BUG_ON(ret); + btrfs_free_path(path); return 0; } -- cgit v1.2.3 From 8351583e3f6e430ce8f71913909a96ad5cc6a2f6 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 14 Jun 2011 15:16:14 -0400 Subject: Btrfs: protect the pending_snapshots list with trans_lock Currently there is nothing protecting the pending_snapshots list on the transaction. We only hold the directory mutex that we are snapshotting and a read lock on the subvol_sem, so we could race with somebody else creating a snapshot in a different directory and end up with list corruption. So protect this list with the trans_lock. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b793d112d1f6..a3c4751e07db 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -482,8 +482,10 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, ret = btrfs_snap_reserve_metadata(trans, pending_snapshot); BUG_ON(ret); + spin_lock(&root->fs_info->trans_lock); list_add(&pending_snapshot->list, &trans->transaction->pending_snapshots); + spin_unlock(&root->fs_info->trans_lock); if (async_transid) { *async_transid = trans->transid; ret = btrfs_commit_transaction_async(trans, -- cgit v1.2.3 From ed0ca14021e5ae3147602128641aa7f742ab227c Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 14 Jun 2011 16:22:15 -0400 Subject: Btrfs: set no_trans_join after trying to expand the transaction We can lockup if we try to allow new writers join the transaction and we have flushoncommit set or have a pending snapshot. This is because we set no_trans_join and then loop around and try to wait for ordered extents again. The problem is the ordered endio stuff needs to join the transaction, which it can't do because no_trans_join is set. So instead wait until after this loop to set no_trans_join and then make sure to wait for num_writers == 1 in case anybody got started in between us exiting the loop and setting no_trans_join. This could easily be reproduced by mounting -o flushoncommit and running xfstest 13. It cannot be reproduced with this patch. Thanks, Reported-by: Jim Schutt Signed-off-by: Josef Bacik --- fs/btrfs/transaction.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2b3590b9fe98..56695595e036 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1241,12 +1241,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, schedule_timeout(1); finish_wait(&cur_trans->writer_wait, &wait); - spin_lock(&root->fs_info->trans_lock); - root->fs_info->trans_no_join = 1; - spin_unlock(&root->fs_info->trans_lock); } while (atomic_read(&cur_trans->num_writers) > 1 || (should_grow && cur_trans->num_joined != joined)); + /* + * Ok now we need to make sure to block out any other joins while we + * commit the transaction. We could have started a join before setting + * no_join so make sure to wait for num_writers to == 1 again. + */ + spin_lock(&root->fs_info->trans_lock); + root->fs_info->trans_no_join = 1; + spin_unlock(&root->fs_info->trans_lock); + wait_event(cur_trans->writer_wait, + atomic_read(&cur_trans->num_writers) == 1); + ret = create_pending_snapshots(trans, root->fs_info); BUG_ON(ret); -- cgit v1.2.3 From 330605423ca6eafafb8dcc27502bce1c585d1b06 Mon Sep 17 00:00:00 2001 From: Ilia Kolomisnky Date: Wed, 15 Jun 2011 06:52:26 +0300 Subject: Bluetooth: Fix L2CAP connection establishment In hci_conn_security ( which is used during L2CAP connection establishment ) test for HCI_CONN_ENCRYPT_PEND state also sets this state, which is bogus and leads to connection time-out on L2CAP sockets in certain situations (especially when using non-ssp devices ) Signed-off-by: Ilia Kolomisnky Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index b9aa9862d14b..d3a05b9ade7a 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -608,7 +608,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) goto encrypt; auth: - if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) + if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; if (!hci_conn_auth(conn, sec_level, auth_type)) -- cgit v1.2.3 From 900cba8881b39dfbc7c8062098504ab93f5387a8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 18 Dec 2009 10:31:31 +0100 Subject: xen: support CONFIG_MAXSMP The MAXSMP config option requires CPUMASK_OFFSTACK, which in turn requires we init the memory for the maps while we bring up the cpus. MAXSMP also increases NR_CPUS to 4096. This increase in size exposed an issue in the argument construction for multicalls from xen_flush_tlb_others. The args should only need space for the actual number of cpus. Also in 2.6.39 it exposes a bootup problem. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] set_cpu_sibling_map+0x123/0x30d ... Call Trace: [] ? xen_restore_fl_direct_reloc+0x4/0x4 [] xen_smp_prepare_cpus+0x36/0x135 .. CC: stable@kernel.org Signed-off-by: Andrew Jones [v2: Updated to compile on 3.0] [v3: Updated to compile when CONFIG_SMP is not defined] Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 3 ++- arch/x86/xen/smp.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index afe1d54f980c..673e968df3cf 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include @@ -1231,7 +1232,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus, { struct { struct mmuext_op op; - DECLARE_BITMAP(mask, NR_CPUS); + DECLARE_BITMAP(mask, num_processors); } *args; struct multicall_space mcs; diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 41038c01de40..b4533a86d7e4 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -205,11 +205,18 @@ static void __init xen_smp_prepare_boot_cpu(void) static void __init xen_smp_prepare_cpus(unsigned int max_cpus) { unsigned cpu; + unsigned int i; xen_init_lock_cpu(0); smp_store_cpu_info(0); cpu_data(0).x86_max_cores = 1; + + for_each_possible_cpu(i) { + zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL); + zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL); + zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL); + } set_cpu_sibling_map(0); if (xen_smp_intr_init(0)) -- cgit v1.2.3 From b5328cd14557880e9eb757a8a9c8a88f1b23533a Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 15 Jun 2011 14:24:29 -0400 Subject: xen: Fix compile warning when CONFIG_SMP is not defined. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .. which is quite benign. drivers/xen/events.c:398: warning: unused variable ‘desc’ Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 553da68bd510..30df85d8fca8 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -395,9 +395,9 @@ static void unmask_evtchn(int port) static void xen_irq_init(unsigned irq) { struct irq_info *info; +#ifdef CONFIG_SMP struct irq_desc *desc = irq_to_desc(irq); -#ifdef CONFIG_SMP /* By default all event channels notify CPU#0. */ cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); #endif -- cgit v1.2.3 From 9e2dfdb3081edfae66a49013517e80dd8a0469fa Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 15 Jun 2011 14:32:02 -0400 Subject: nfs4.1: mark layout as bad on error path in _pnfs_return_layout Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 730d4dbbaf68..539b94cb6c0f 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -652,6 +652,8 @@ _pnfs_return_layout(struct inode *ino) lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); if (unlikely(lrp == NULL)) { status = -ENOMEM; + set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags); + set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags); put_layout_hdr(lo); goto out; } -- cgit v1.2.3 From 37aa9a2eb4d9b1a4aec1fd18bb2bb6bca029de27 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Wed, 15 Jun 2011 14:35:00 +0100 Subject: perf: clear out make flags when calling kernel make kernelver When generating the perf version from the kernel version using 'make kernelver' it is necessary to clear out any MAKEFLAGS otherwise they may trigger additional output which pollute the contents. Signed-off-by: Andy Whitcroft Signed-off-by: Michal Marek --- tools/perf/util/PERF-VERSION-GEN | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 9c5fb4d93824..ad73300f7bac 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN @@ -23,7 +23,7 @@ if test -d ../../.git -o -f ../../.git && then VN=$(echo "$VN" | sed -e 's/-/./g'); else - VN=$(make -sC ../.. kernelversion) + VN=$(MAKEFLAGS= make -sC ../.. kernelversion) fi VN=$(expr "$VN" : v*'\(.*\)') -- cgit v1.2.3 From 569658dddf276ceb0780776e7f5d61d9f8d8cb88 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 15 Jun 2011 22:15:47 +0200 Subject: kbuild: Call depmod.sh via shell The script has the executable bit in git, but plain old patch(1) can't create executable files. Reported-by: Tetsuo Handa Signed-off-by: Michal Marek --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 43509373f37a..67640639d8f3 100644 --- a/Makefile +++ b/Makefile @@ -1526,7 +1526,8 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)) # Run depmod only if we have System.map and depmod is executable quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) - cmd_depmod = $(srctree)/scripts/depmod.sh $(DEPMOD) $(KERNELRELEASE) + cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \ + $(KERNELRELEASE) # Create temporary dir for module support files # clean it up only when building all modules -- cgit v1.2.3 From b2abe50688dcb470e2e46109da7e7e02245ed59b Mon Sep 17 00:00:00 2001 From: Tom Goetz Date: Mon, 16 May 2011 15:06:26 -0400 Subject: xen: When calling power_off, don't call the halt function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .. As it won't actually power off the machine. Reported-by: Sven Köhler Tested-by: Sven Köhler Signed-off-by: Tom Goetz Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/enlighten.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index dd7b88f2ec7a..5525163a0398 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1033,6 +1033,13 @@ static void xen_machine_halt(void) xen_reboot(SHUTDOWN_poweroff); } +static void xen_machine_power_off(void) +{ + if (pm_power_off) + pm_power_off(); + xen_reboot(SHUTDOWN_poweroff); +} + static void xen_crash_shutdown(struct pt_regs *regs) { xen_reboot(SHUTDOWN_crash); @@ -1058,7 +1065,7 @@ int xen_panic_handler_init(void) static const struct machine_ops xen_machine_ops __initconst = { .restart = xen_restart, .halt = xen_machine_halt, - .power_off = xen_machine_halt, + .power_off = xen_machine_power_off, .shutdown = xen_machine_halt, .crash_shutdown = xen_crash_shutdown, .emergency_restart = xen_emergency_restart, -- cgit v1.2.3 From fa75ac379e63c2864e9049b5e8615e40f65c1e70 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Sun, 5 Jun 2011 23:10:04 -0700 Subject: xhci: Reject double add of active endpoints. While trying to switch a UAS device from the BOT configuration to the UAS configuration via the bConfigurationValue file, Tanya ran into an issue in the USB core. usb_disable_device() sets entries in udev->ep_out and udev->ep_out to NULL, but doesn't call into the xHCI bandwidth management functions to remove the BOT configuration endpoints from the xHCI host's internal structures. The USB core would then attempt to add endpoints for the UAS configuration, and some of the endpoints had the same address as endpoints in the BOT configuration. The xHCI driver blindly added the endpoints again, but the xHCI host controller rejected the Configure Endpoint command because active endpoints were added without being dropped. Make the xHCI driver reject calls to xhci_add_endpoint() that attempt to add active endpoints without first calling xhci_drop_endpoint(). This should be backported to kernels as old as 2.6.31. Signed-off-by: Sarah Sharp Reported-by: Tanya Brokhman Cc: stable@kernel.org --- drivers/usb/host/xhci.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 06e7023258d0..e5a01713f937 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1401,6 +1401,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, u32 added_ctxs; unsigned int last_ctx; u32 new_add_flags, new_drop_flags, new_slot_info; + struct xhci_virt_device *virt_dev; int ret = 0; ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); @@ -1425,11 +1426,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return 0; } - in_ctx = xhci->devs[udev->slot_id]->in_ctx; - out_ctx = xhci->devs[udev->slot_id]->out_ctx; + virt_dev = xhci->devs[udev->slot_id]; + in_ctx = virt_dev->in_ctx; + out_ctx = virt_dev->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); + + /* If this endpoint is already in use, and the upper layers are trying + * to add it again without dropping it, reject the addition. + */ + if (virt_dev->eps[ep_index].ring && + !(le32_to_cpu(ctrl_ctx->drop_flags) & + xhci_get_endpoint_flag(&ep->desc))) { + xhci_warn(xhci, "Trying to add endpoint 0x%x " + "without dropping it.\n", + (unsigned int) ep->desc.bEndpointAddress); + return -EINVAL; + } + /* If the HCD has already noted the endpoint is enabled, * ignore this request. */ @@ -1445,8 +1460,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, * process context, not interrupt context (or so documenation * for usb_set_interface() and usb_set_configuration() claim). */ - if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id], - udev, ep, GFP_NOIO) < 0) { + if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) { dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n", __func__, ep->desc.bEndpointAddress); return -ENOMEM; -- cgit v1.2.3 From fccf4e86200b8f5edd9a65da26f150e32ba79808 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Sun, 5 Jun 2011 23:22:22 -0700 Subject: USB: Free bandwidth when usb_disable_device is called. Tanya ran into an issue when trying to switch a UAS device from the BOT configuration to the UAS configuration via the bConfigurationValue sysfs file. Before installing the UAS configuration, set_bConfigurationValue() calls usb_disable_device(). That function is supposed to remove all host controller resources associated with that device, but it leaves some state in the xHCI host controller. Commit 0791971ba8fbc44e4f476079f856335ed45e6324 usb: allow drivers to use allocated bandwidth until unbound added a call to usb_disable_device() in usb_set_configuration(), before the xHCI bandwidth functions were invoked. That commit fixed a bug, but also introduced a bug that is triggered when a configured device is switched to a new configuration. usb_disable_device() goes through all the motions of unbinding the drivers attached to active interfaces and removing the USB core structures associated with those interfaces, but it doesn't actually remove the endpoints from the internal xHCI host controller bandwidth structures. When usb_disable_device() calls usb_disable_endpoint() with reset_hardware set to true, the entries in udev->ep_out and udev->ep_in will be set to NULL. Usually, when the USB core installs a new configuration, usb_hcd_alloc_bandwidth() will drop all non-NULL endpoints in udev->ep_out and udev->ep_in before adding any new endpoints. However, when the new UAS configuration was added, all those entries were null, so none of the old endpoints in the BOT configuration were dropped. The xHCI driver blindly added the UAS configuration endpoints, and some of the endpoint addresses overlapped with the old BOT configuration endpoints. This caused the xHCI host to reject the Configure Endpoint command. Now that the xHCI driver code is cleaned up to reject a double-add of active endpoints, we need to fix the USB core to properly drop old endpoints in usb_disable_device(). If the host controller driver needs bandwidth checking support, make usb_disable_device() call usb_disable_endpoint() with reset_hardware set to false, drop the endpoints from the xHCI host controller, and then call usb_disable_endpoint() again with reset_hardware set to true. The first call to usb_disable_endpoint() will cancel any pending URBs and wait on them to be freed in usb_hcd_disable_endpoint(), but will keep the pointers in udev->ep_out and udev->ep in intact. Then usb_hcd_alloc_bandwidth() will use those pointers to know which endpoints to drop. The final call to usb_disable_endpoint() will do two things: 1. It will call usb_hcd_disable_endpoint() again, which should be harmless since the ep->urb_list should be empty after the first call to usb_disable_endpoint() returns. 2. It will set the entries in udev->ep_out and udev->ep in to NULL, and call usb_hcd_disable_endpoint(). That call will have no effect, since the xHCI driver doesn't set the endpoint_disable function pointer. Note that usb_disable_device() will now need to be called with hcd->bandwidth_mutex held. This should be backported to kernels as old as 2.6.32. Signed-off-by: Sarah Sharp Reported-by: Tanya Brokhman Cc: ablay@codeaurora.org Cc: Alan Stern Cc: stable@kernel.org --- drivers/usb/core/hub.c | 3 +++ drivers/usb/core/message.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90ae1753dda1..ca339bc799e4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1634,6 +1634,7 @@ void usb_disconnect(struct usb_device **pdev) { struct usb_device *udev = *pdev; int i; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); if (!udev) { pr_debug ("%s nodev\n", __func__); @@ -1661,7 +1662,9 @@ void usb_disconnect(struct usb_device **pdev) * so that the hardware is now fully quiesced. */ dev_dbg (&udev->dev, "unregistering device\n"); + mutex_lock(hcd->bandwidth_mutex); usb_disable_device(udev, 0); + mutex_unlock(hcd->bandwidth_mutex); usb_hcd_synchronize_unlinks(udev); usb_remove_ep_devs(&udev->ep0); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 5701e857392b..64c7ab4702df 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1135,10 +1135,13 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf, * Deallocates hcd/hardware state for the endpoints (nuking all or most * pending urbs) and usbcore state for the interfaces, so that usbcore * must usb_set_configuration() before any interfaces could be used. + * + * Must be called with hcd->bandwidth_mutex held. */ void usb_disable_device(struct usb_device *dev, int skip_ep0) { int i; + struct usb_hcd *hcd = bus_to_hcd(dev->bus); /* getting rid of interfaces will disconnect * any drivers bound to them (a key side effect) @@ -1172,6 +1175,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, skip_ep0 ? "non-ep0" : "all"); + if (hcd->driver->check_bandwidth) { + /* First pass: Cancel URBs, leave endpoint pointers intact. */ + for (i = skip_ep0; i < 16; ++i) { + usb_disable_endpoint(dev, i, false); + usb_disable_endpoint(dev, i + USB_DIR_IN, false); + } + /* Remove endpoints from the host controller internal state */ + usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); + /* Second pass: remove endpoint pointers */ + } for (i = skip_ep0; i < 16; ++i) { usb_disable_endpoint(dev, i, true); usb_disable_endpoint(dev, i + USB_DIR_IN, true); @@ -1727,6 +1740,7 @@ free_interfaces: /* if it's already configured, clear out old state first. * getting rid of old interfaces means unbinding their drivers. */ + mutex_lock(hcd->bandwidth_mutex); if (dev->state != USB_STATE_ADDRESS) usb_disable_device(dev, 1); /* Skip ep0 */ @@ -1739,7 +1753,6 @@ free_interfaces: * host controller will not allow submissions to dropped endpoints. If * this call fails, the device state is unchanged. */ - mutex_lock(hcd->bandwidth_mutex); ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); if (ret < 0) { mutex_unlock(hcd->bandwidth_mutex); -- cgit v1.2.3 From d23336329fa4c157ed6256d4279a73b87486a1b6 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 6 Jun 2011 00:53:47 -0700 Subject: xhci: Don't warn about zeroed bMaxBurst descriptor field. The USB 3.0 specification says that the bMaxBurst field in the SuperSpeed Endpoint Companion descriptor is supposed to indicate how many packets a SS device can handle before it needs to wait for an explicit handshake from the host controller. A zero value means the device can only handle one packet before it needs a handshake. Remove a warning in the xHCI driver that implies this is an invalid value. Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-mem.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 0f8e1d29a858..fcb7f7efc86d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1215,8 +1215,6 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); /* dig out max burst from ep companion desc */ max_packet = ep->ss_ep_comp.bMaxBurst; - if (!max_packet) - xhci_warn(xhci, "WARN no SS endpoint bMaxBurst\n"); ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet)); break; case USB_SPEED_HIGH: -- cgit v1.2.3 From 793925334f32e9026c22baee5c3c340f47d4ef7e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 15 Jun 2011 12:47:04 -0700 Subject: proc: Fix Oops on stat of /proc//ns/net Don't call iput with the inode half setup to be a namespace filedescriptor. Instead rearrange the code so that we don't initialize ei->ns_ops until after I ns_ops->get succeeds, preventing us from invoking ns_ops->put when ns_ops->get failed. Reported-by: Ingo Saitz Signed-off-by: Eric W. Biederman --- fs/proc/namespaces.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 781dec5bd682..be177f702acb 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c @@ -38,18 +38,21 @@ static struct dentry *proc_ns_instantiate(struct inode *dir, struct inode *inode; struct proc_inode *ei; struct dentry *error = ERR_PTR(-ENOENT); + void *ns; inode = proc_pid_make_inode(dir->i_sb, task); if (!inode) goto out; + ns = ns_ops->get(task); + if (!ns) + goto out_iput; + ei = PROC_I(inode); inode->i_mode = S_IFREG|S_IRUSR; inode->i_fop = &ns_file_operations; ei->ns_ops = ns_ops; - ei->ns = ns_ops->get(task); - if (!ei->ns) - goto out_iput; + ei->ns = ns; dentry->d_op = &pid_dentry_operations; d_add(dentry, inode); -- cgit v1.2.3 From e1cf486d881d853d710e2d86a7adfc5fd260990f Mon Sep 17 00:00:00 2001 From: Alex He Date: Fri, 3 Jun 2011 15:58:25 +0800 Subject: xHCI 1.0: Force Stopped Event(FSE) FSE shall occur on the TD natural boundary. The software ep_ring dequeue pointer exceed the hardware ep_ring dequeue pointer in these cases of Table-3. As a result, the event_trb(pointed by hardware dequeue pointer) of the FSE can't be found in the current TD(pointed by software dequeue pointer). What should we do is to figured out the FSE case and skip over it. Signed-off-by: Alex He Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-ring.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 800f417c7309..0c008497edfd 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2063,6 +2063,20 @@ static int handle_tx_event(struct xhci_hcd *xhci, /* Is this a TRB in the currently executing TD? */ event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, td->last_trb, event_dma); + + /* + * Skip the Force Stopped Event. The event_trb(event_dma) of FSE + * is not in the current TD pointed by ep_ring->dequeue because + * that the hardware dequeue pointer still at the previous TRB + * of the current TD. The previous TRB maybe a Link TD or the + * last TRB of the previous TD. The command completion handle + * will take care the rest. + */ + if (!event_seg && trb_comp_code == COMP_STOP_INVAL) { + ret = 0; + goto cleanup; + } + if (!event_seg) { if (!ep->skip || !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { -- cgit v1.2.3 From 578333ab95f70db13951d30a9ad6b565b61639a9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 15 Jun 2011 16:32:46 -0400 Subject: USB: change maintainership of ohci-hcd and ehci-hcd Following the loss of David Brownell, I volunteer to maintain the ohci-hcd and ehci-hcd drivers. This patch (as1472) makes it official. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 6 ++++-- drivers/usb/host/ehci-hcd.c | 4 ++++ drivers/usb/host/ohci-hcd.c | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index e50fc6eb99e0..4307673415f7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6430,8 +6430,9 @@ S: Maintained F: drivers/usb/misc/rio500* USB EHCI DRIVER +M: Alan Stern L: linux-usb@vger.kernel.org -S: Orphan +S: Maintained F: Documentation/usb/ehci.txt F: drivers/usb/host/ehci* @@ -6490,8 +6491,9 @@ S: Maintained F: sound/usb/midi.* USB OHCI DRIVER +M: Alan Stern L: linux-usb@vger.kernel.org -S: Orphan +S: Maintained F: Documentation/usb/ohci.txt F: drivers/usb/host/ohci* diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b435ed67dd5c..f8030ee928e8 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1,4 +1,8 @@ /* + * Enhanced Host Controller Interface (EHCI) driver for USB. + * + * Maintainer: Alan Stern + * * Copyright (c) 2000-2004 by David Brownell * * This program is free software; you can redistribute it and/or modify it diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 9aa10bdf3918..f9cf3f04b742 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1,5 +1,7 @@ /* - * OHCI HCD (Host Controller Driver) for USB. + * Open Host Controller Interface (OHCI) driver for USB. + * + * Maintainer: Alan Stern * * (C) Copyright 1999 Roman Weissgaerber * (C) Copyright 2000-2004 David Brownell -- cgit v1.2.3 From cbb330045e5df8f665ac60227ff898421fc8fb92 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 15 Jun 2011 16:29:16 -0400 Subject: USB: don't let the hub driver prevent system sleep This patch (as1465) continues implementation of the policy that errors during suspend or hibernation should not prevent the system from going to sleep. In this case, failure to turn on the Suspend feature for a hub port shouldn't be reported as an error. There are situations where this does actually occur (such as when the device plugged into that port was disconnected in the recent past), and it turns out to be harmless. There's no reason for it to prevent a system sleep. Also, don't allow the hub driver to fail a system suspend if the downstream ports aren't all suspended. This is also harmless (and should never happen, given the change mentioned above); printing a warning message in the kernel log is all we really need to do. Signed-off-by: Alan Stern CC: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90ae1753dda1..c2ac08755f27 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2362,6 +2362,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); + + /* System sleep transitions should never fail */ + if (!(msg.event & PM_EVENT_AUTO)) + status = 0; } else { /* device has up to 10 msec to fully suspend */ dev_dbg(&udev->dev, "usb %ssuspend\n", @@ -2611,16 +2615,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) struct usb_device *hdev = hub->hdev; unsigned port1; - /* fail if children aren't already suspended */ + /* Warn if children aren't already suspended */ for (port1 = 1; port1 <= hdev->maxchild; port1++) { struct usb_device *udev; udev = hdev->children [port1-1]; if (udev && udev->can_submit) { - if (!(msg.event & PM_EVENT_AUTO)) - dev_dbg(&intf->dev, "port %d nyet suspended\n", - port1); - return -EBUSY; + dev_warn(&intf->dev, "port %d nyet suspended\n", port1); + if (msg.event & PM_EVENT_AUTO) + return -EBUSY; } } -- cgit v1.2.3 From 0af212ba8f123c2eba151af7726c34a50b127962 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 15 Jun 2011 16:27:43 -0400 Subject: USB: don't let errors prevent system sleep This patch (as1464) implements the recommended policy that most errors during suspend or hibernation should not prevent the system from going to sleep. In particular, failure to suspend a USB driver or a USB device should not prevent the sleep from succeeding: Failure to suspend a device won't matter, because the device will automatically go into suspend mode when the USB bus stops carrying packets. (This might be less true for USB-3.0 devices, but let's not worry about them now.) Failure of a driver to suspend might lead to trouble later on when the system wakes up, but it isn't sufficient reason to prevent the system from going to sleep. Signed-off-by: Alan Stern CC: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index e35a17687c05..81add81ab040 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1187,13 +1187,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) for (i = n - 1; i >= 0; --i) { intf = udev->actconfig->interface[i]; status = usb_suspend_interface(udev, intf, msg); + + /* Ignore errors during system sleep transitions */ + if (!(msg.event & PM_EVENT_AUTO)) + status = 0; if (status != 0) break; } } - if (status == 0) + if (status == 0) { status = usb_suspend_device(udev, msg); + /* Again, ignore errors during system sleep transitions */ + if (!(msg.event & PM_EVENT_AUTO)) + status = 0; + } + /* If the suspend failed, resume interfaces that did get suspended */ if (status != 0) { msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); -- cgit v1.2.3 From f300ea499721ca208fc4714b9105bfd7e9f75be0 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Wed, 15 Jun 2011 15:08:08 -0700 Subject: mm: remove khugepaged double thp vmstat update with CONFIG_NUMA=n Johannes noticed the vmstat update is already taken care of by khugepaged_alloc_hugepage() internally. The only places that are required to update the vmstat are the callers of alloc_hugepage (callers of khugepaged_alloc_hugepage aren't). Signed-off-by: Andrea Arcangeli Reported-by: Johannes Weiner Acked-by: Rik van Riel Reviewed-by: Minchan Kim Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/huge_memory.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 615d9743a3cb..81532f297fd2 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2234,11 +2234,8 @@ static void khugepaged_loop(void) while (likely(khugepaged_enabled())) { #ifndef CONFIG_NUMA hpage = khugepaged_alloc_hugepage(); - if (unlikely(!hpage)) { - count_vm_event(THP_COLLAPSE_ALLOC_FAILED); + if (unlikely(!hpage)) break; - } - count_vm_event(THP_COLLAPSE_ALLOC); #else if (IS_ERR(hpage)) { khugepaged_alloc_sleep(); -- cgit v1.2.3 From 0164f69d0cf1a6abbc936851f5b72ece92187cda Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 15 Jun 2011 15:08:09 -0700 Subject: mm/memory.c: fix kernel-doc notation Fix new kernel-doc warnings in mm/memory.c: Warning(mm/memory.c:1327): No description found for parameter 'tlb' Warning(mm/memory.c:1327): Excess function parameter 'tlbp' description in 'unmap_vmas' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index 6953d3926e01..b13e7dbc399b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1296,7 +1296,7 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb, /** * unmap_vmas - unmap a range of memory covered by a list of vma's - * @tlbp: address of the caller's struct mmu_gather + * @tlb: address of the caller's struct mmu_gather * @vma: the starting vma * @start_addr: virtual address at which to start unmapping * @end_addr: virtual address at which to end unmapping -- cgit v1.2.3 From b0825ee3a8c570df4873ee397fa453e67fdad5d7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 15 Jun 2011 15:08:10 -0700 Subject: lib/bitmap.c: fix kernel-doc notation Fix new kernel-doc warnings in lib/bitmap.c: Warning(lib/bitmap.c:596): No description found for parameter 'buf' Warning(lib/bitmap.c:596): Excess function parameter 'bp' description in '__bitmap_parselist' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bitmap.c b/lib/bitmap.c index 41baf02924e6..3f3b68199d74 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -572,7 +572,7 @@ EXPORT_SYMBOL(bitmap_scnlistprintf); /** * __bitmap_parselist - convert list format ASCII string to bitmap - * @bp: read nul-terminated user string from this buffer + * @buf: read nul-terminated user string from this buffer * @buflen: buffer size in bytes. If string is smaller than this * then it must be terminated with a \0. * @is_user: location of buffer, 0 indicates kernel space -- cgit v1.2.3 From 7f81c8890c15a10f5220bebae3b6dfae4961962a Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Wed, 15 Jun 2011 15:08:11 -0700 Subject: fs/exec.c: use BUILD_BUG_ON for VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP Commit a8bef8ff6ea1 ("mm: migration: avoid race between shift_arg_pages() and rmap_walk() during migration by not migrating temporary stacks") introduced a BUG_ON() to ensure that VM_STACK_FLAGS and VM_STACK_INCOMPLETE_SETUP do not overlap. The check is a compile time one, so BUILD_BUG_ON is more appropriate. Signed-off-by: Michal Hocko Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exec.c b/fs/exec.c index 97e0d52d72fd..b54f74f3cd80 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -277,7 +277,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm) * use STACK_TOP because that can depend on attributes which aren't * configured yet. */ - BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); + BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); vma->vm_end = STACK_TOP_MAX; vma->vm_start = vma->vm_end - PAGE_SIZE; vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; -- cgit v1.2.3 From a59ec1e7ff98cc4365d5b1bff4e7102e86b5716b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 15 Jun 2011 15:08:11 -0700 Subject: backlight: new driver for the ADP8870 backlight devices Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .../testing/sysfs-class-backlight-driver-adp8870 | 56 ++ drivers/video/backlight/Kconfig | 12 + drivers/video/backlight/Makefile | 1 + drivers/video/backlight/adp8870_bl.c | 1011 ++++++++++++++++++++ include/linux/i2c/adp8870.h | 153 +++ 5 files changed, 1233 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 create mode 100644 drivers/video/backlight/adp8870_bl.c create mode 100644 include/linux/i2c/adp8870.h diff --git a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 new file mode 100644 index 000000000000..aa11dbdd794b --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 @@ -0,0 +1,56 @@ +What: /sys/class/backlight//_max +What: /sys/class/backlight//l1_daylight_max +What: /sys/class/backlight//l2_bright_max +What: /sys/class/backlight//l3_office_max +What: /sys/class/backlight//l4_indoor_max +What: /sys/class/backlight//l5_dark_max +Date: Mai 2011 +KernelVersion: 2.6.40 +Contact: device-drivers-devel@blackfin.uclinux.org +Description: + Control the maximum brightness for + on this . Values are between 0 and 127. This file + will also show the brightness level stored for this + . + +What: /sys/class/backlight//_dim +What: /sys/class/backlight//l2_bright_dim +What: /sys/class/backlight//l3_office_dim +What: /sys/class/backlight//l4_indoor_dim +What: /sys/class/backlight//l5_dark_dim +Date: Mai 2011 +KernelVersion: 2.6.40 +Contact: device-drivers-devel@blackfin.uclinux.org +Description: + Control the dim brightness for + on this . Values are between 0 and 127, typically + set to 0. Full off when the backlight is disabled. + This file will also show the dim brightness level stored for + this . + +What: /sys/class/backlight//ambient_light_level +Date: Mai 2011 +KernelVersion: 2.6.40 +Contact: device-drivers-devel@blackfin.uclinux.org +Description: + Get conversion value of the light sensor. + This value is updated every 80 ms (when the light sensor + is enabled). Returns integer between 0 (dark) and + 8000 (max ambient brightness) + +What: /sys/class/backlight//ambient_light_zone +Date: Mai 2011 +KernelVersion: 2.6.40 +Contact: device-drivers-devel@blackfin.uclinux.org +Description: + Get/Set current ambient light zone. Reading returns + integer between 1..5 (1 = daylight, 2 = bright, ..., 5 = dark). + Writing a value between 1..5 forces the backlight controller + to enter the corresponding ambient light zone. + Writing 0 returns to normal/automatic ambient light level + operation. The ambient light sensing feature on these devices + is an extension to the API documented in + Documentation/ABI/stable/sysfs-class-backlight. + It can be enabled by writing the value stored in + /sys/class/backlight//max_brightness to + /sys/class/backlight//brightness. \ No newline at end of file diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 0c9373bedd1f..2d93c8d61ad5 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -302,6 +302,18 @@ config BACKLIGHT_ADP8860 To compile this driver as a module, choose M here: the module will be called adp8860_bl. +config BACKLIGHT_ADP8870 + tristate "Backlight Driver for ADP8870 using WLED" + depends on BACKLIGHT_CLASS_DEVICE && I2C + select NEW_LEDS + select LEDS_CLASS + help + If you have a LCD backlight connected to the ADP8870, + say Y here to enable this driver. + + To compile this driver as a module, choose M here: the module will + be called adp8870_bl. + config BACKLIGHT_88PM860X tristate "Backlight Driver for 88PM8606 using WLED" depends on MFD_88PM860X diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index b9ca8490df87..ee72adb8786e 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o +obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c new file mode 100644 index 000000000000..e320b62576e2 --- /dev/null +++ b/drivers/video/backlight/adp8870_bl.c @@ -0,0 +1,1011 @@ +/* + * Backlight driver for Analog Devices ADP8870 Backlight Devices + * + * Copyright 2009-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#define ADP8870_EXT_FEATURES +#define ADP8870_USE_LEDS + + +#define ADP8870_MFDVID 0x00 /* Manufacturer and device ID */ +#define ADP8870_MDCR 0x01 /* Device mode and status */ +#define ADP8870_INT_STAT 0x02 /* Interrupts status */ +#define ADP8870_INT_EN 0x03 /* Interrupts enable */ +#define ADP8870_CFGR 0x04 /* Configuration register */ +#define ADP8870_BLSEL 0x05 /* Sink enable backlight or independent */ +#define ADP8870_PWMLED 0x06 /* PWM Enable Selection Register */ +#define ADP8870_BLOFF 0x07 /* Backlight off timeout */ +#define ADP8870_BLDIM 0x08 /* Backlight dim timeout */ +#define ADP8870_BLFR 0x09 /* Backlight fade in and out rates */ +#define ADP8870_BLMX1 0x0A /* Backlight (Brightness Level 1-daylight) maximum current */ +#define ADP8870_BLDM1 0x0B /* Backlight (Brightness Level 1-daylight) dim current */ +#define ADP8870_BLMX2 0x0C /* Backlight (Brightness Level 2-bright) maximum current */ +#define ADP8870_BLDM2 0x0D /* Backlight (Brightness Level 2-bright) dim current */ +#define ADP8870_BLMX3 0x0E /* Backlight (Brightness Level 3-office) maximum current */ +#define ADP8870_BLDM3 0x0F /* Backlight (Brightness Level 3-office) dim current */ +#define ADP8870_BLMX4 0x10 /* Backlight (Brightness Level 4-indoor) maximum current */ +#define ADP8870_BLDM4 0x11 /* Backlight (Brightness Level 4-indoor) dim current */ +#define ADP8870_BLMX5 0x12 /* Backlight (Brightness Level 5-dark) maximum current */ +#define ADP8870_BLDM5 0x13 /* Backlight (Brightness Level 5-dark) dim current */ +#define ADP8870_ISCLAW 0x1A /* Independent sink current fade law register */ +#define ADP8870_ISCC 0x1B /* Independent sink current control register */ +#define ADP8870_ISCT1 0x1C /* Independent Sink Current Timer Register LED[7:5] */ +#define ADP8870_ISCT2 0x1D /* Independent Sink Current Timer Register LED[4:1] */ +#define ADP8870_ISCF 0x1E /* Independent sink current fade register */ +#define ADP8870_ISC1 0x1F /* Independent Sink Current LED1 */ +#define ADP8870_ISC2 0x20 /* Independent Sink Current LED2 */ +#define ADP8870_ISC3 0x21 /* Independent Sink Current LED3 */ +#define ADP8870_ISC4 0x22 /* Independent Sink Current LED4 */ +#define ADP8870_ISC5 0x23 /* Independent Sink Current LED5 */ +#define ADP8870_ISC6 0x24 /* Independent Sink Current LED6 */ +#define ADP8870_ISC7 0x25 /* Independent Sink Current LED7 (Brightness Level 1-daylight) */ +#define ADP8870_ISC7_L2 0x26 /* Independent Sink Current LED7 (Brightness Level 2-bright) */ +#define ADP8870_ISC7_L3 0x27 /* Independent Sink Current LED7 (Brightness Level 3-office) */ +#define ADP8870_ISC7_L4 0x28 /* Independent Sink Current LED7 (Brightness Level 4-indoor) */ +#define ADP8870_ISC7_L5 0x29 /* Independent Sink Current LED7 (Brightness Level 5-dark) */ +#define ADP8870_CMP_CTL 0x2D /* ALS Comparator Control Register */ +#define ADP8870_ALS1_EN 0x2E /* Main ALS comparator level enable */ +#define ADP8870_ALS2_EN 0x2F /* Second ALS comparator level enable */ +#define ADP8870_ALS1_STAT 0x30 /* Main ALS Comparator Status Register */ +#define ADP8870_ALS2_STAT 0x31 /* Second ALS Comparator Status Register */ +#define ADP8870_L2TRP 0x32 /* L2 comparator reference */ +#define ADP8870_L2HYS 0x33 /* L2 hysteresis */ +#define ADP8870_L3TRP 0x34 /* L3 comparator reference */ +#define ADP8870_L3HYS 0x35 /* L3 hysteresis */ +#define ADP8870_L4TRP 0x36 /* L4 comparator reference */ +#define ADP8870_L4HYS 0x37 /* L4 hysteresis */ +#define ADP8870_L5TRP 0x38 /* L5 comparator reference */ +#define ADP8870_L5HYS 0x39 /* L5 hysteresis */ +#define ADP8870_PH1LEVL 0x40 /* First phototransistor ambient light level-low byte register */ +#define ADP8870_PH1LEVH 0x41 /* First phototransistor ambient light level-high byte register */ +#define ADP8870_PH2LEVL 0x42 /* Second phototransistor ambient light level-low byte register */ +#define ADP8870_PH2LEVH 0x43 /* Second phototransistor ambient light level-high byte register */ + +#define ADP8870_MANUFID 0x3 /* Analog Devices AD8870 Manufacturer and device ID */ +#define ADP8870_DEVID(x) ((x) & 0xF) +#define ADP8870_MANID(x) ((x) >> 4) + +/* MDCR Device mode and status */ +#define D7ALSEN (1 << 7) +#define INT_CFG (1 << 6) +#define NSTBY (1 << 5) +#define DIM_EN (1 << 4) +#define GDWN_DIS (1 << 3) +#define SIS_EN (1 << 2) +#define CMP_AUTOEN (1 << 1) +#define BLEN (1 << 0) + +/* ADP8870_ALS1_EN Main ALS comparator level enable */ +#define L5_EN (1 << 3) +#define L4_EN (1 << 2) +#define L3_EN (1 << 1) +#define L2_EN (1 << 0) + +#define CFGR_BLV_SHIFT 3 +#define CFGR_BLV_MASK 0x7 +#define ADP8870_FLAG_LED_MASK 0xFF + +#define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) +#define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1)) +#define ALS_CMPR_CFG_VAL(filt) ((0x7 & (filt)) << 1) + +struct adp8870_bl { + struct i2c_client *client; + struct backlight_device *bl; + struct adp8870_led *led; + struct adp8870_backlight_platform_data *pdata; + struct mutex lock; + unsigned long cached_daylight_max; + int id; + int revid; + int current_brightness; +}; + +struct adp8870_led { + struct led_classdev cdev; + struct work_struct work; + struct i2c_client *client; + enum led_brightness new_brightness; + int id; + int flags; +}; + +static int adp8870_read(struct i2c_client *client, int reg, uint8_t *val) +{ + int ret; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) { + dev_err(&client->dev, "failed reading at 0x%02x\n", reg); + return ret; + } + + *val = ret; + return 0; +} + + +static int adp8870_write(struct i2c_client *client, u8 reg, u8 val) +{ + int ret = i2c_smbus_write_byte_data(client, reg, val); + if (ret) + dev_err(&client->dev, "failed to write\n"); + + return ret; +} + +static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&data->lock); + + ret = adp8870_read(client, reg, ®_val); + + if (!ret && ((reg_val & bit_mask) == 0)) { + reg_val |= bit_mask; + ret = adp8870_write(client, reg, reg_val); + } + + mutex_unlock(&data->lock); + return ret; +} + +static int adp8870_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&data->lock); + + ret = adp8870_read(client, reg, ®_val); + + if (!ret && (reg_val & bit_mask)) { + reg_val &= ~bit_mask; + ret = adp8870_write(client, reg, reg_val); + } + + mutex_unlock(&data->lock); + return ret; +} + +/* + * Independent sink / LED + */ +#if defined(ADP8870_USE_LEDS) +static void adp8870_led_work(struct work_struct *work) +{ + struct adp8870_led *led = container_of(work, struct adp8870_led, work); + adp8870_write(led->client, ADP8870_ISC1 + led->id - 1, + led->new_brightness >> 1); +} + +static void adp8870_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct adp8870_led *led; + + led = container_of(led_cdev, struct adp8870_led, cdev); + led->new_brightness = value; + /* + * Use workqueue for IO since I2C operations can sleep. + */ + schedule_work(&led->work); +} + +static int adp8870_led_setup(struct adp8870_led *led) +{ + struct i2c_client *client = led->client; + int ret = 0; + + ret = adp8870_write(client, ADP8870_ISC1 + led->id - 1, 0); + if (ret) + return ret; + + ret = adp8870_set_bits(client, ADP8870_ISCC, 1 << (led->id - 1)); + if (ret) + return ret; + + if (led->id > 4) + ret = adp8870_set_bits(client, ADP8870_ISCT1, + (led->flags & 0x3) << ((led->id - 5) * 2)); + else + ret = adp8870_set_bits(client, ADP8870_ISCT2, + (led->flags & 0x3) << ((led->id - 1) * 2)); + + return ret; +} + +static int __devinit adp8870_led_probe(struct i2c_client *client) +{ + struct adp8870_backlight_platform_data *pdata = + client->dev.platform_data; + struct adp8870_bl *data = i2c_get_clientdata(client); + struct adp8870_led *led, *led_dat; + struct led_info *cur_led; + int ret, i; + + + led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL); + if (led == NULL) { + dev_err(&client->dev, "failed to alloc memory\n"); + return -ENOMEM; + } + + ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law); + if (ret) + goto err_free; + + ret = adp8870_write(client, ADP8870_ISCT1, + (pdata->led_on_time & 0x3) << 6); + if (ret) + goto err_free; + + ret = adp8870_write(client, ADP8870_ISCF, + FADE_VAL(pdata->led_fade_in, pdata->led_fade_out)); + if (ret) + goto err_free; + + for (i = 0; i < pdata->num_leds; ++i) { + cur_led = &pdata->leds[i]; + led_dat = &led[i]; + + led_dat->id = cur_led->flags & ADP8870_FLAG_LED_MASK; + + if (led_dat->id > 7 || led_dat->id < 1) { + dev_err(&client->dev, "Invalid LED ID %d\n", + led_dat->id); + goto err; + } + + if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { + dev_err(&client->dev, "LED %d used by Backlight\n", + led_dat->id); + goto err; + } + + led_dat->cdev.name = cur_led->name; + led_dat->cdev.default_trigger = cur_led->default_trigger; + led_dat->cdev.brightness_set = adp8870_led_set; + led_dat->cdev.brightness = LED_OFF; + led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT; + led_dat->client = client; + led_dat->new_brightness = LED_OFF; + INIT_WORK(&led_dat->work, adp8870_led_work); + + ret = led_classdev_register(&client->dev, &led_dat->cdev); + if (ret) { + dev_err(&client->dev, "failed to register LED %d\n", + led_dat->id); + goto err; + } + + ret = adp8870_led_setup(led_dat); + if (ret) { + dev_err(&client->dev, "failed to write\n"); + i++; + goto err; + } + } + + data->led = led; + + return 0; + + err: + for (i = i - 1; i >= 0; --i) { + led_classdev_unregister(&led[i].cdev); + cancel_work_sync(&led[i].work); + } + + err_free: + kfree(led); + + return ret; +} + +static int __devexit adp8870_led_remove(struct i2c_client *client) +{ + struct adp8870_backlight_platform_data *pdata = + client->dev.platform_data; + struct adp8870_bl *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < pdata->num_leds; i++) { + led_classdev_unregister(&data->led[i].cdev); + cancel_work_sync(&data->led[i].work); + } + + kfree(data->led); + return 0; +} +#else +static int __devinit adp8870_led_probe(struct i2c_client *client) +{ + return 0; +} + +static int __devexit adp8870_led_remove(struct i2c_client *client) +{ + return 0; +} +#endif + +static int adp8870_bl_set(struct backlight_device *bl, int brightness) +{ + struct adp8870_bl *data = bl_get_data(bl); + struct i2c_client *client = data->client; + int ret = 0; + + if (data->pdata->en_ambl_sens) { + if ((brightness > 0) && (brightness < ADP8870_MAX_BRIGHTNESS)) { + /* Disable Ambient Light auto adjust */ + ret = adp8870_clr_bits(client, ADP8870_MDCR, + CMP_AUTOEN); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLMX1, brightness); + if (ret) + return ret; + } else { + /* + * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust + * restore daylight l1 sysfs brightness + */ + ret = adp8870_write(client, ADP8870_BLMX1, + data->cached_daylight_max); + if (ret) + return ret; + + ret = adp8870_set_bits(client, ADP8870_MDCR, + CMP_AUTOEN); + if (ret) + return ret; + } + } else { + ret = adp8870_write(client, ADP8870_BLMX1, brightness); + if (ret) + return ret; + } + + if (data->current_brightness && brightness == 0) + ret = adp8870_set_bits(client, + ADP8870_MDCR, DIM_EN); + else if (data->current_brightness == 0 && brightness) + ret = adp8870_clr_bits(client, + ADP8870_MDCR, DIM_EN); + + if (!ret) + data->current_brightness = brightness; + + return ret; +} + +static int adp8870_bl_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + return adp8870_bl_set(bl, brightness); +} + +static int adp8870_bl_get_brightness(struct backlight_device *bl) +{ + struct adp8870_bl *data = bl_get_data(bl); + + return data->current_brightness; +} + +static const struct backlight_ops adp8870_bl_ops = { + .update_status = adp8870_bl_update_status, + .get_brightness = adp8870_bl_get_brightness, +}; + +static int adp8870_bl_setup(struct backlight_device *bl) +{ + struct adp8870_bl *data = bl_get_data(bl); + struct i2c_client *client = data->client; + struct adp8870_backlight_platform_data *pdata = data->pdata; + int ret = 0; + + ret = adp8870_write(client, ADP8870_BLSEL, ~pdata->bl_led_assign); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_PWMLED, pdata->pwm_assign); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX1, pdata->l1_daylight_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM1, pdata->l1_daylight_dim); + if (ret) + return ret; + + if (pdata->en_ambl_sens) { + data->cached_daylight_max = pdata->l1_daylight_max; + ret = adp8870_write(client, ADP8870_BLMX2, + pdata->l2_bright_max); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLDM2, + pdata->l2_bright_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX3, + pdata->l3_office_max); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLDM3, + pdata->l3_office_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX4, + pdata->l4_indoor_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM4, + pdata->l4_indor_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX5, + pdata->l5_dark_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM5, + pdata->l5_dark_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L2TRP, pdata->l2_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L2HYS, pdata->l2_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L3TRP, pdata->l3_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L3HYS, pdata->l3_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L4TRP, pdata->l4_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L4HYS, pdata->l4_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L5TRP, pdata->l5_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L5HYS, pdata->l5_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_ALS1_EN, L5_EN | L4_EN | + L3_EN | L2_EN); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_CMP_CTL, + ALS_CMPR_CFG_VAL(pdata->abml_filt)); + if (ret) + return ret; + } + + ret = adp8870_write(client, ADP8870_CFGR, + BL_CFGR_VAL(pdata->bl_fade_law, 0)); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLFR, FADE_VAL(pdata->bl_fade_in, + pdata->bl_fade_out)); + if (ret) + return ret; + /* + * ADP8870 Rev0 requires GDWN_DIS bit set + */ + + ret = adp8870_set_bits(client, ADP8870_MDCR, BLEN | DIM_EN | NSTBY | + (data->revid == 0 ? GDWN_DIS : 0)); + + return ret; +} + +static ssize_t adp8870_show(struct device *dev, char *buf, int reg) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, reg, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + return sprintf(buf, "%u\n", reg_val); +} + +static ssize_t adp8870_store(struct device *dev, const char *buf, + size_t count, int reg) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&data->lock); + adp8870_write(data->client, reg, val); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t adp8870_bl_l5_dark_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX5); +} + +static ssize_t adp8870_bl_l5_dark_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX5); +} +static DEVICE_ATTR(l5_dark_max, 0664, adp8870_bl_l5_dark_max_show, + adp8870_bl_l5_dark_max_store); + + +static ssize_t adp8870_bl_l4_indoor_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX4); +} + +static ssize_t adp8870_bl_l4_indoor_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX4); +} +static DEVICE_ATTR(l4_indoor_max, 0664, adp8870_bl_l4_indoor_max_show, + adp8870_bl_l4_indoor_max_store); + + +static ssize_t adp8870_bl_l3_office_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX3); +} + +static ssize_t adp8870_bl_l3_office_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX3); +} + +static DEVICE_ATTR(l3_office_max, 0664, adp8870_bl_l3_office_max_show, + adp8870_bl_l3_office_max_store); + +static ssize_t adp8870_bl_l2_bright_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX2); +} + +static ssize_t adp8870_bl_l2_bright_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX2); +} +static DEVICE_ATTR(l2_bright_max, 0664, adp8870_bl_l2_bright_max_show, + adp8870_bl_l2_bright_max_store); + +static ssize_t adp8870_bl_l1_daylight_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX1); +} + +static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int ret = strict_strtoul(buf, 10, &data->cached_daylight_max); + if (ret) + return ret; + + return adp8870_store(dev, buf, count, ADP8870_BLMX1); +} +static DEVICE_ATTR(l1_daylight_max, 0664, adp8870_bl_l1_daylight_max_show, + adp8870_bl_l1_daylight_max_store); + +static ssize_t adp8870_bl_l5_dark_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM5); +} + +static ssize_t adp8870_bl_l5_dark_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM5); +} +static DEVICE_ATTR(l5_dark_dim, 0664, adp8870_bl_l5_dark_dim_show, + adp8870_bl_l5_dark_dim_store); + +static ssize_t adp8870_bl_l4_indoor_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM4); +} + +static ssize_t adp8870_bl_l4_indoor_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM4); +} +static DEVICE_ATTR(l4_indoor_dim, 0664, adp8870_bl_l4_indoor_dim_show, + adp8870_bl_l4_indoor_dim_store); + + +static ssize_t adp8870_bl_l3_office_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM3); +} + +static ssize_t adp8870_bl_l3_office_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM3); +} +static DEVICE_ATTR(l3_office_dim, 0664, adp8870_bl_l3_office_dim_show, + adp8870_bl_l3_office_dim_store); + +static ssize_t adp8870_bl_l2_bright_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM2); +} + +static ssize_t adp8870_bl_l2_bright_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM2); +} +static DEVICE_ATTR(l2_bright_dim, 0664, adp8870_bl_l2_bright_dim_show, + adp8870_bl_l2_bright_dim_store); + +static ssize_t adp8870_bl_l1_daylight_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM1); +} + +static ssize_t adp8870_bl_l1_daylight_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM1); +} +static DEVICE_ATTR(l1_daylight_dim, 0664, adp8870_bl_l1_daylight_dim_show, + adp8870_bl_l1_daylight_dim_store); + +#ifdef ADP8870_EXT_FEATURES +static ssize_t adp8870_bl_ambient_light_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + uint16_t ret_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, ADP8870_PH1LEVL, ®_val); + if (error < 0) { + mutex_unlock(&data->lock); + return error; + } + ret_val = reg_val; + error = adp8870_read(data->client, ADP8870_PH1LEVH, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + /* Return 13-bit conversion value for the first light sensor */ + ret_val += (reg_val & 0x1F) << 8; + + return sprintf(buf, "%u\n", ret_val); +} +static DEVICE_ATTR(ambient_light_level, 0444, + adp8870_bl_ambient_light_level_show, NULL); + +static ssize_t adp8870_bl_ambient_light_zone_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, ADP8870_CFGR, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + return sprintf(buf, "%u\n", + ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1); +} + +static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + unsigned long val; + uint8_t reg_val; + int ret; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + if (val == 0) { + /* Enable automatic ambient light sensing */ + adp8870_set_bits(data->client, ADP8870_MDCR, CMP_AUTOEN); + } else if ((val > 0) && (val < 6)) { + /* Disable automatic ambient light sensing */ + adp8870_clr_bits(data->client, ADP8870_MDCR, CMP_AUTOEN); + + /* Set user supplied ambient light zone */ + mutex_lock(&data->lock); + adp8870_read(data->client, ADP8870_CFGR, ®_val); + reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); + reg_val |= (val - 1) << CFGR_BLV_SHIFT; + adp8870_write(data->client, ADP8870_CFGR, reg_val); + mutex_unlock(&data->lock); + } + + return count; +} +static DEVICE_ATTR(ambient_light_zone, 0664, + adp8870_bl_ambient_light_zone_show, + adp8870_bl_ambient_light_zone_store); +#endif + +static struct attribute *adp8870_bl_attributes[] = { + &dev_attr_l5_dark_max.attr, + &dev_attr_l5_dark_dim.attr, + &dev_attr_l4_indoor_max.attr, + &dev_attr_l4_indoor_dim.attr, + &dev_attr_l3_office_max.attr, + &dev_attr_l3_office_dim.attr, + &dev_attr_l2_bright_max.attr, + &dev_attr_l2_bright_dim.attr, + &dev_attr_l1_daylight_max.attr, + &dev_attr_l1_daylight_dim.attr, +#ifdef ADP8870_EXT_FEATURES + &dev_attr_ambient_light_level.attr, + &dev_attr_ambient_light_zone.attr, +#endif + NULL +}; + +static const struct attribute_group adp8870_bl_attr_group = { + .attrs = adp8870_bl_attributes, +}; + +static int __devinit adp8870_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct backlight_properties props; + struct backlight_device *bl; + struct adp8870_bl *data; + struct adp8870_backlight_platform_data *pdata = + client->dev.platform_data; + uint8_t reg_val; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); + return -EIO; + } + + if (!pdata) { + dev_err(&client->dev, "no platform data?\n"); + return -EINVAL; + } + + ret = adp8870_read(client, ADP8870_MFDVID, ®_val); + if (ret < 0) + return -EIO; + + if (ADP8870_MANID(reg_val) != ADP8870_MANUFID) { + dev_err(&client->dev, "failed to probe\n"); + return -ENODEV; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->revid = ADP8870_DEVID(reg_val); + data->client = client; + data->pdata = pdata; + data->id = id->driver_data; + data->current_brightness = 0; + i2c_set_clientdata(client, data); + + mutex_init(&data->lock); + + memset(&props, 0, sizeof(props)); + props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS; + bl = backlight_device_register(dev_driver_string(&client->dev), + &client->dev, data, &adp8870_bl_ops, &props); + if (IS_ERR(bl)) { + dev_err(&client->dev, "failed to register backlight\n"); + ret = PTR_ERR(bl); + goto out2; + } + + data->bl = bl; + + if (pdata->en_ambl_sens) + ret = sysfs_create_group(&bl->dev.kobj, + &adp8870_bl_attr_group); + + if (ret) { + dev_err(&client->dev, "failed to register sysfs\n"); + goto out1; + } + + ret = adp8870_bl_setup(bl); + if (ret) { + ret = -EIO; + goto out; + } + + backlight_update_status(bl); + + dev_info(&client->dev, "Rev.%d Backlight\n", data->revid); + + if (pdata->num_leds) + adp8870_led_probe(client); + + return 0; + +out: + if (data->pdata->en_ambl_sens) + sysfs_remove_group(&data->bl->dev.kobj, + &adp8870_bl_attr_group); +out1: + backlight_device_unregister(bl); +out2: + i2c_set_clientdata(client, NULL); + kfree(data); + + return ret; +} + +static int __devexit adp8870_remove(struct i2c_client *client) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + + adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); + + if (data->led) + adp8870_led_remove(client); + + if (data->pdata->en_ambl_sens) + sysfs_remove_group(&data->bl->dev.kobj, + &adp8870_bl_attr_group); + + backlight_device_unregister(data->bl); + i2c_set_clientdata(client, NULL); + kfree(data); + + return 0; +} + +#ifdef CONFIG_PM +static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) +{ + adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); + + return 0; +} + +static int adp8870_i2c_resume(struct i2c_client *client) +{ + adp8870_set_bits(client, ADP8870_MDCR, NSTBY); + + return 0; +} +#else +#define adp8870_i2c_suspend NULL +#define adp8870_i2c_resume NULL +#endif + +static const struct i2c_device_id adp8870_id[] = { + { "adp8870", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adp8870_id); + +static struct i2c_driver adp8870_driver = { + .driver = { + .name = KBUILD_MODNAME, + }, + .probe = adp8870_probe, + .remove = __devexit_p(adp8870_remove), + .suspend = adp8870_i2c_suspend, + .resume = adp8870_i2c_resume, + .id_table = adp8870_id, +}; + +static int __init adp8870_init(void) +{ + return i2c_add_driver(&adp8870_driver); +} +module_init(adp8870_init); + +static void __exit adp8870_exit(void) +{ + i2c_del_driver(&adp8870_driver); +} +module_exit(adp8870_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("ADP8870 Backlight driver"); +MODULE_ALIAS("platform:adp8870-backlight"); diff --git a/include/linux/i2c/adp8870.h b/include/linux/i2c/adp8870.h new file mode 100644 index 000000000000..624dceccbd5b --- /dev/null +++ b/include/linux/i2c/adp8870.h @@ -0,0 +1,153 @@ +/* + * Definitions and platform data for Analog Devices + * Backlight drivers ADP8870 + * + * Copyright 2009-2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __LINUX_I2C_ADP8870_H +#define __LINUX_I2C_ADP8870_H + +#define ID_ADP8870 8870 + +#define ADP8870_MAX_BRIGHTNESS 0x7F +#define FLAG_OFFT_SHIFT 8 + +/* + * LEDs subdevice platform data + */ + +#define ADP8870_LED_DIS_BLINK (0 << FLAG_OFFT_SHIFT) +#define ADP8870_LED_OFFT_600ms (1 << FLAG_OFFT_SHIFT) +#define ADP8870_LED_OFFT_1200ms (2 << FLAG_OFFT_SHIFT) +#define ADP8870_LED_OFFT_1800ms (3 << FLAG_OFFT_SHIFT) + +#define ADP8870_LED_ONT_200ms 0 +#define ADP8870_LED_ONT_600ms 1 +#define ADP8870_LED_ONT_800ms 2 +#define ADP8870_LED_ONT_1200ms 3 + +#define ADP8870_LED_D7 (7) +#define ADP8870_LED_D6 (6) +#define ADP8870_LED_D5 (5) +#define ADP8870_LED_D4 (4) +#define ADP8870_LED_D3 (3) +#define ADP8870_LED_D2 (2) +#define ADP8870_LED_D1 (1) + +/* + * Backlight subdevice platform data + */ + +#define ADP8870_BL_D7 (1 << 6) +#define ADP8870_BL_D6 (1 << 5) +#define ADP8870_BL_D5 (1 << 4) +#define ADP8870_BL_D4 (1 << 3) +#define ADP8870_BL_D3 (1 << 2) +#define ADP8870_BL_D2 (1 << 1) +#define ADP8870_BL_D1 (1 << 0) + +#define ADP8870_FADE_T_DIS 0 /* Fade Timer Disabled */ +#define ADP8870_FADE_T_300ms 1 /* 0.3 Sec */ +#define ADP8870_FADE_T_600ms 2 +#define ADP8870_FADE_T_900ms 3 +#define ADP8870_FADE_T_1200ms 4 +#define ADP8870_FADE_T_1500ms 5 +#define ADP8870_FADE_T_1800ms 6 +#define ADP8870_FADE_T_2100ms 7 +#define ADP8870_FADE_T_2400ms 8 +#define ADP8870_FADE_T_2700ms 9 +#define ADP8870_FADE_T_3000ms 10 +#define ADP8870_FADE_T_3500ms 11 +#define ADP8870_FADE_T_4000ms 12 +#define ADP8870_FADE_T_4500ms 13 +#define ADP8870_FADE_T_5000ms 14 +#define ADP8870_FADE_T_5500ms 15 /* 5.5 Sec */ + +#define ADP8870_FADE_LAW_LINEAR 0 +#define ADP8870_FADE_LAW_SQUARE 1 +#define ADP8870_FADE_LAW_CUBIC1 2 +#define ADP8870_FADE_LAW_CUBIC2 3 + +#define ADP8870_BL_AMBL_FILT_80ms 0 /* Light sensor filter time */ +#define ADP8870_BL_AMBL_FILT_160ms 1 +#define ADP8870_BL_AMBL_FILT_320ms 2 +#define ADP8870_BL_AMBL_FILT_640ms 3 +#define ADP8870_BL_AMBL_FILT_1280ms 4 +#define ADP8870_BL_AMBL_FILT_2560ms 5 +#define ADP8870_BL_AMBL_FILT_5120ms 6 +#define ADP8870_BL_AMBL_FILT_10240ms 7 /* 10.24 sec */ + +/* + * Blacklight current 0..30mA + */ +#define ADP8870_BL_CUR_mA(I) ((I * 127) / 30) + +/* + * L2 comparator current 0..1106uA + */ +#define ADP8870_L2_COMP_CURR_uA(I) ((I * 255) / 1106) + +/* + * L3 comparator current 0..551uA + */ +#define ADP8870_L3_COMP_CURR_uA(I) ((I * 255) / 551) + +/* + * L4 comparator current 0..275uA + */ +#define ADP8870_L4_COMP_CURR_uA(I) ((I * 255) / 275) + +/* + * L5 comparator current 0..138uA + */ +#define ADP8870_L5_COMP_CURR_uA(I) ((I * 255) / 138) + +struct adp8870_backlight_platform_data { + u8 bl_led_assign; /* 1 = Backlight 0 = Individual LED */ + u8 pwm_assign; /* 1 = Enables PWM mode */ + + u8 bl_fade_in; /* Backlight Fade-In Timer */ + u8 bl_fade_out; /* Backlight Fade-Out Timer */ + u8 bl_fade_law; /* fade-on/fade-off transfer characteristic */ + + u8 en_ambl_sens; /* 1 = enable ambient light sensor */ + u8 abml_filt; /* Light sensor filter time */ + + u8 l1_daylight_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l1_daylight_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l2_bright_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l2_bright_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l3_office_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l3_office_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l4_indoor_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l4_indor_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l5_dark_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l5_dark_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + + u8 l2_trip; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */ + u8 l2_hyst; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */ + u8 l3_trip; /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */ + u8 l3_hyst; /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */ + u8 l4_trip; /* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */ + u8 l4_hyst; /* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */ + u8 l5_trip; /* use L5_COMP_CURR_uA(I) 0 <= I <= 138 uA */ + u8 l5_hyst; /* use L6_COMP_CURR_uA(I) 0 <= I <= 138 uA */ + + /** + * Independent Current Sinks / LEDS + * Sinks not assigned to the Backlight can be exposed to + * user space using the LEDS CLASS interface + */ + + int num_leds; + struct led_info *leds; + u8 led_fade_in; /* LED Fade-In Timer */ + u8 led_fade_out; /* LED Fade-Out Timer */ + u8 led_fade_law; /* fade-on/fade-off transfer characteristic */ + u8 led_on_time; +}; + +#endif /* __LINUX_I2C_ADP8870_H */ -- cgit v1.2.3 From e1bbd19bc4afef7adb80cca163800391c4f5773d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 15 Jun 2011 15:08:12 -0700 Subject: drivers/video/backlight/adp8870_bl.c: add missed props.type conversion Cc: Michael Hennerich Cc: Mike Frysinger Cc: Matthew Garrett Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/adp8870_bl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index e320b62576e2..05a8832bb3eb 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -889,6 +889,7 @@ static int __devinit adp8870_probe(struct i2c_client *client, mutex_init(&data->lock); memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS; bl = backlight_device_register(dev_driver_string(&client->dev), &client->dev, data, &adp8870_bl_ops, &props); -- cgit v1.2.3 From a433658c30974fc87ba3ff52d7e4e6299762aa3d Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 15 Jun 2011 15:08:13 -0700 Subject: vmscan,memcg: memcg aware swap token Currently, memcg reclaim can disable swap token even if the swap token mm doesn't belong in its memory cgroup. It's slightly risky. If an admin creates very small mem-cgroup and silly guy runs contentious heavy memory pressure workload, every tasks are going to lose swap token and then system may become unresponsive. That's bad. This patch adds 'memcg' parameter into disable_swap_token(). and if the parameter doesn't match swap token, VM doesn't disable it. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: KOSAKI Motohiro Reviewed-by: KAMEZAWA Hiroyuki Reviewed-by: Rik van Riel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/memcontrol.h | 6 ++++ include/linux/swap.h | 8 ++--- mm/memcontrol.c | 16 ++++----- mm/thrash.c | 87 ++++++++++++++++++++++++++++++++++++---------- mm/vmscan.c | 4 +-- 5 files changed, 85 insertions(+), 36 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 9724a38ee69d..50940da6adf3 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -84,6 +84,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem); extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page); extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p); +extern struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm); static inline int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup) @@ -246,6 +247,11 @@ static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page) return NULL; } +static inline struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) +{ + return NULL; +} + static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem) { return 1; diff --git a/include/linux/swap.h b/include/linux/swap.h index 384eb5fe530b..e70564647039 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -358,6 +358,7 @@ struct backing_dev_info; extern struct mm_struct *swap_token_mm; extern void grab_swap_token(struct mm_struct *); extern void __put_swap_token(struct mm_struct *); +extern void disable_swap_token(struct mem_cgroup *memcg); static inline int has_swap_token(struct mm_struct *mm) { @@ -370,11 +371,6 @@ static inline void put_swap_token(struct mm_struct *mm) __put_swap_token(mm); } -static inline void disable_swap_token(void) -{ - put_swap_token(swap_token_mm); -} - #ifdef CONFIG_CGROUP_MEM_RES_CTLR extern void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); @@ -500,7 +496,7 @@ static inline int has_swap_token(struct mm_struct *mm) return 0; } -static inline void disable_swap_token(void) +static inline void disable_swap_token(struct mem_cgroup *memcg) { } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index bd9052a5d3ad..e37c44d88d46 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -735,7 +735,7 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) struct mem_cgroup, css); } -static struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) +struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) { struct mem_cgroup *mem = NULL; @@ -5414,18 +5414,16 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss, struct cgroup *old_cont, struct task_struct *p) { - struct mm_struct *mm; + struct mm_struct *mm = get_task_mm(p); - if (!mc.to) - /* no need to move charge */ - return; - - mm = get_task_mm(p); if (mm) { - mem_cgroup_move_charge(mm); + if (mc.to) + mem_cgroup_move_charge(mm); + put_swap_token(mm); mmput(mm); } - mem_cgroup_clear_mc(); + if (mc.to) + mem_cgroup_clear_mc(); } #else /* !CONFIG_MMU */ static int mem_cgroup_can_attach(struct cgroup_subsys *ss, diff --git a/mm/thrash.c b/mm/thrash.c index 2372d4ed5dd8..6cdf86511385 100644 --- a/mm/thrash.c +++ b/mm/thrash.c @@ -21,11 +21,31 @@ #include #include #include +#include static DEFINE_SPINLOCK(swap_token_lock); struct mm_struct *swap_token_mm; +struct mem_cgroup *swap_token_memcg; static unsigned int global_faults; +#ifdef CONFIG_CGROUP_MEM_RES_CTLR +static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) +{ + struct mem_cgroup *memcg; + + memcg = try_get_mem_cgroup_from_mm(mm); + if (memcg) + css_put(mem_cgroup_css(memcg)); + + return memcg; +} +#else +static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) +{ + return NULL; +} +#endif + void grab_swap_token(struct mm_struct *mm) { int current_interval; @@ -38,40 +58,69 @@ void grab_swap_token(struct mm_struct *mm) return; /* First come first served */ - if (swap_token_mm == NULL) { - mm->token_priority = mm->token_priority + 2; - swap_token_mm = mm; + if (!swap_token_mm) + goto replace_token; + + if (mm == swap_token_mm) { + mm->token_priority += 2; goto out; } - if (mm != swap_token_mm) { - if (current_interval < mm->last_interval) - mm->token_priority++; - else { - if (likely(mm->token_priority > 0)) - mm->token_priority--; - } - /* Check if we deserve the token */ - if (mm->token_priority > swap_token_mm->token_priority) { - mm->token_priority += 2; - swap_token_mm = mm; - } - } else { - /* Token holder came in again! */ - mm->token_priority += 2; + if (current_interval < mm->last_interval) + mm->token_priority++; + else { + if (likely(mm->token_priority > 0)) + mm->token_priority--; } + /* Check if we deserve the token */ + if (mm->token_priority > swap_token_mm->token_priority) + goto replace_token; + out: mm->faultstamp = global_faults; mm->last_interval = current_interval; spin_unlock(&swap_token_lock); + return; + +replace_token: + mm->token_priority += 2; + swap_token_mm = mm; + swap_token_memcg = swap_token_memcg_from_mm(mm); + goto out; } /* Called on process exit. */ void __put_swap_token(struct mm_struct *mm) { spin_lock(&swap_token_lock); - if (likely(mm == swap_token_mm)) + if (likely(mm == swap_token_mm)) { swap_token_mm = NULL; + swap_token_memcg = NULL; + } spin_unlock(&swap_token_lock); } + +static bool match_memcg(struct mem_cgroup *a, struct mem_cgroup *b) +{ + if (!a) + return true; + if (!b) + return true; + if (a == b) + return true; + return false; +} + +void disable_swap_token(struct mem_cgroup *memcg) +{ + /* memcg reclaim don't disable unrelated mm token. */ + if (match_memcg(memcg, swap_token_memcg)) { + spin_lock(&swap_token_lock); + if (match_memcg(memcg, swap_token_memcg)) { + swap_token_mm = NULL; + swap_token_memcg = NULL; + } + spin_unlock(&swap_token_lock); + } +} diff --git a/mm/vmscan.c b/mm/vmscan.c index faa0a088f9cc..dbe6ea321df4 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2081,7 +2081,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, for (priority = DEF_PRIORITY; priority >= 0; priority--) { sc->nr_scanned = 0; if (!priority) - disable_swap_token(); + disable_swap_token(sc->mem_cgroup); total_scanned += shrink_zones(priority, zonelist, sc); /* * Don't shrink slabs when reclaiming memory from @@ -2407,7 +2407,7 @@ loop_again: /* The swap token gets in the way of swapout... */ if (!priority) - disable_swap_token(); + disable_swap_token(NULL); all_zones_ok = 1; balanced = 0; -- cgit v1.2.3 From 83cd81a34357a632509f7491eec81e62e71d65f7 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 15 Jun 2011 15:08:14 -0700 Subject: vmscan: implement swap token trace This is useful for observing swap token activity. example output: zsh-1845 [000] 598.962716: update_swap_token_priority: mm=ffff88015eaf7700 old_prio=1 new_prio=0 memtoy-1830 [001] 602.033900: update_swap_token_priority: mm=ffff880037a45880 old_prio=947 new_prio=949 memtoy-1830 [000] 602.041509: update_swap_token_priority: mm=ffff880037a45880 old_prio=949 new_prio=951 memtoy-1830 [000] 602.051959: update_swap_token_priority: mm=ffff880037a45880 old_prio=951 new_prio=953 memtoy-1830 [000] 602.052188: update_swap_token_priority: mm=ffff880037a45880 old_prio=953 new_prio=955 memtoy-1830 [001] 602.427184: put_swap_token: token_mm=ffff880037a45880 zsh-1789 [000] 602.427281: replace_swap_token: old_token_mm= (null) old_prio=0 new_token_mm=ffff88015eaf7018 new_prio=2 zsh-1789 [001] 602.433456: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=2 new_prio=4 zsh-1789 [000] 602.437613: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=4 new_prio=6 zsh-1789 [000] 602.443924: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=6 new_prio=8 zsh-1789 [000] 602.451873: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=8 new_prio=10 zsh-1789 [001] 602.462639: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=10 new_prio=12 Signed-off-by: KOSAKI Motohiro Acked-by: Rik van Riel Reviewed-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/trace/events/vmscan.h | 77 +++++++++++++++++++++++++++++++++++++++++++ mm/thrash.c | 11 ++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h index ea422aaa23e1..1798e0cee2a9 100644 --- a/include/trace/events/vmscan.h +++ b/include/trace/events/vmscan.h @@ -6,6 +6,8 @@ #include #include +#include +#include #include "gfpflags.h" #define RECLAIM_WB_ANON 0x0001u @@ -310,6 +312,81 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive, show_reclaim_flags(__entry->reclaim_flags)) ); +TRACE_EVENT(replace_swap_token, + TP_PROTO(struct mm_struct *old_mm, + struct mm_struct *new_mm), + + TP_ARGS(old_mm, new_mm), + + TP_STRUCT__entry( + __field(struct mm_struct*, old_mm) + __field(unsigned int, old_prio) + __field(struct mm_struct*, new_mm) + __field(unsigned int, new_prio) + ), + + TP_fast_assign( + __entry->old_mm = old_mm; + __entry->old_prio = old_mm ? old_mm->token_priority : 0; + __entry->new_mm = new_mm; + __entry->new_prio = new_mm->token_priority; + ), + + TP_printk("old_token_mm=%p old_prio=%u new_token_mm=%p new_prio=%u", + __entry->old_mm, __entry->old_prio, + __entry->new_mm, __entry->new_prio) +); + +DECLARE_EVENT_CLASS(put_swap_token_template, + TP_PROTO(struct mm_struct *swap_token_mm), + + TP_ARGS(swap_token_mm), + + TP_STRUCT__entry( + __field(struct mm_struct*, swap_token_mm) + ), + + TP_fast_assign( + __entry->swap_token_mm = swap_token_mm; + ), + + TP_printk("token_mm=%p", __entry->swap_token_mm) +); + +DEFINE_EVENT(put_swap_token_template, put_swap_token, + TP_PROTO(struct mm_struct *swap_token_mm), + TP_ARGS(swap_token_mm) +); + +DEFINE_EVENT_CONDITION(put_swap_token_template, disable_swap_token, + TP_PROTO(struct mm_struct *swap_token_mm), + TP_ARGS(swap_token_mm), + TP_CONDITION(swap_token_mm != NULL) +); + +TRACE_EVENT_CONDITION(update_swap_token_priority, + TP_PROTO(struct mm_struct *mm, + unsigned int old_prio), + + TP_ARGS(mm, old_prio), + + TP_CONDITION(mm->token_priority != old_prio), + + TP_STRUCT__entry( + __field(struct mm_struct*, mm) + __field(unsigned int, old_prio) + __field(unsigned int, new_prio) + ), + + TP_fast_assign( + __entry->mm = mm; + __entry->old_prio = old_prio; + __entry->new_prio = mm->token_priority; + ), + + TP_printk("mm=%p old_prio=%u new_prio=%u", + __entry->mm, __entry->old_prio, __entry->new_prio) +); #endif /* _TRACE_VMSCAN_H */ diff --git a/mm/thrash.c b/mm/thrash.c index 6cdf86511385..17d9e29e4c9c 100644 --- a/mm/thrash.c +++ b/mm/thrash.c @@ -23,6 +23,8 @@ #include #include +#include + static DEFINE_SPINLOCK(swap_token_lock); struct mm_struct *swap_token_mm; struct mem_cgroup *swap_token_memcg; @@ -49,6 +51,7 @@ static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) void grab_swap_token(struct mm_struct *mm) { int current_interval; + unsigned int old_prio = mm->token_priority; global_faults++; @@ -63,7 +66,7 @@ void grab_swap_token(struct mm_struct *mm) if (mm == swap_token_mm) { mm->token_priority += 2; - goto out; + goto update_priority; } if (current_interval < mm->last_interval) @@ -77,6 +80,9 @@ void grab_swap_token(struct mm_struct *mm) if (mm->token_priority > swap_token_mm->token_priority) goto replace_token; +update_priority: + trace_update_swap_token_priority(mm, old_prio); + out: mm->faultstamp = global_faults; mm->last_interval = current_interval; @@ -85,6 +91,7 @@ out: replace_token: mm->token_priority += 2; + trace_replace_swap_token(swap_token_mm, mm); swap_token_mm = mm; swap_token_memcg = swap_token_memcg_from_mm(mm); goto out; @@ -95,6 +102,7 @@ void __put_swap_token(struct mm_struct *mm) { spin_lock(&swap_token_lock); if (likely(mm == swap_token_mm)) { + trace_put_swap_token(swap_token_mm); swap_token_mm = NULL; swap_token_memcg = NULL; } @@ -118,6 +126,7 @@ void disable_swap_token(struct mem_cgroup *memcg) if (match_memcg(memcg, swap_token_memcg)) { spin_lock(&swap_token_lock); if (match_memcg(memcg, swap_token_memcg)) { + trace_disable_swap_token(swap_token_mm); swap_token_mm = NULL; swap_token_memcg = NULL; } -- cgit v1.2.3 From d7911ef30cb7bec52234c2b7a5c275ac8f07905a Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 15 Jun 2011 15:08:15 -0700 Subject: vmscan: implement swap token priority aging While testing for memcg aware swap token, I observed a swap token was often grabbed an intermittent running process (eg init, auditd) and they never release a token. Why? Some processes (eg init, auditd, audispd) wake up when a process exiting. And swap token can be get first page-in process when a process exiting makes no swap token owner. Thus such above intermittent running process often get a token. And currently, swap token priority is only decreased at page fault path. Then, if the process sleep immediately after to grab swap token, the swap token priority never be decreased. That's obviously undesirable. This patch implement very poor (and lightweight) priority aging. It only be affect to the above corner case and doesn't change swap tendency workload performance (eg multi process qsbench load) Signed-off-by: KOSAKI Motohiro Reviewed-by: Rik van Riel Reviewed-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/trace/events/vmscan.h | 20 +++++++++++++------- mm/thrash.c | 11 ++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h index 1798e0cee2a9..b2c33bd955fa 100644 --- a/include/trace/events/vmscan.h +++ b/include/trace/events/vmscan.h @@ -366,9 +366,10 @@ DEFINE_EVENT_CONDITION(put_swap_token_template, disable_swap_token, TRACE_EVENT_CONDITION(update_swap_token_priority, TP_PROTO(struct mm_struct *mm, - unsigned int old_prio), + unsigned int old_prio, + struct mm_struct *swap_token_mm), - TP_ARGS(mm, old_prio), + TP_ARGS(mm, old_prio, swap_token_mm), TP_CONDITION(mm->token_priority != old_prio), @@ -376,16 +377,21 @@ TRACE_EVENT_CONDITION(update_swap_token_priority, __field(struct mm_struct*, mm) __field(unsigned int, old_prio) __field(unsigned int, new_prio) + __field(struct mm_struct*, swap_token_mm) + __field(unsigned int, swap_token_prio) ), TP_fast_assign( - __entry->mm = mm; - __entry->old_prio = old_prio; - __entry->new_prio = mm->token_priority; + __entry->mm = mm; + __entry->old_prio = old_prio; + __entry->new_prio = mm->token_priority; + __entry->swap_token_mm = swap_token_mm; + __entry->swap_token_prio = swap_token_mm ? swap_token_mm->token_priority : 0; ), - TP_printk("mm=%p old_prio=%u new_prio=%u", - __entry->mm, __entry->old_prio, __entry->new_prio) + TP_printk("mm=%p old_prio=%u new_prio=%u swap_token_mm=%p token_prio=%u", + __entry->mm, __entry->old_prio, __entry->new_prio, + __entry->swap_token_mm, __entry->swap_token_prio) ); #endif /* _TRACE_VMSCAN_H */ diff --git a/mm/thrash.c b/mm/thrash.c index 17d9e29e4c9c..fabf2d0f5169 100644 --- a/mm/thrash.c +++ b/mm/thrash.c @@ -25,10 +25,13 @@ #include +#define TOKEN_AGING_INTERVAL (0xFF) + static DEFINE_SPINLOCK(swap_token_lock); struct mm_struct *swap_token_mm; struct mem_cgroup *swap_token_memcg; static unsigned int global_faults; +static unsigned int last_aging; #ifdef CONFIG_CGROUP_MEM_RES_CTLR static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) @@ -64,6 +67,11 @@ void grab_swap_token(struct mm_struct *mm) if (!swap_token_mm) goto replace_token; + if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) { + swap_token_mm->token_priority /= 2; + last_aging = global_faults; + } + if (mm == swap_token_mm) { mm->token_priority += 2; goto update_priority; @@ -81,7 +89,7 @@ void grab_swap_token(struct mm_struct *mm) goto replace_token; update_priority: - trace_update_swap_token_priority(mm, old_prio); + trace_update_swap_token_priority(mm, old_prio, swap_token_mm); out: mm->faultstamp = global_faults; @@ -94,6 +102,7 @@ replace_token: trace_replace_swap_token(swap_token_mm, mm); swap_token_mm = mm; swap_token_memcg = swap_token_memcg_from_mm(mm); + last_aging = global_faults; goto out; } -- cgit v1.2.3 From 50c35e5ba255fd8428cef8ff076da8d23bfd4909 Mon Sep 17 00:00:00 2001 From: Ying Han Date: Wed, 15 Jun 2011 15:08:16 -0700 Subject: memcg: add documentation for the memory.numastat API [akpm@linux-foundation.org: rework text, fit it into 80-cols] Signed-off-by: Ying Han Reviewed-by: KOSAKI Motohiro Acked-by: Balbir Singh Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cgroups/memory.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 7c163477fcd8..510d64570d60 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -70,6 +70,7 @@ Brief summary of control files. (See sysctl's vm.swappiness) memory.move_charge_at_immigrate # set/show controls of moving charges memory.oom_control # set/show oom controls. + memory.numa_stat # show the number of memory usage per numa node 1. History @@ -464,6 +465,24 @@ value for efficient access. (Of course, when necessary, it's synchronized.) If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP) value in memory.stat(see 5.2). +5.6 numa_stat + +This is similar to numa_maps but operates on a per-memcg basis. This is +useful for providing visibility into the numa locality information within +an memcg since the pages are allowed to be allocated from any physical +node. One of the usecases is evaluating application performance by +combining this information with the application's cpu allocation. + +We export "total", "file", "anon" and "unevictable" pages per-node for +each memcg. The ouput format of memory.numa_stat is: + +total= N0= N1= ... +file= N0= N1= ... +anon= N0= N1= ... +unevictable= N0= N1= ... + +And we have total = file + anon + unevictable. + 6. Hierarchy support The memory controller supports a deep hierarchy and hierarchical accounting. -- cgit v1.2.3 From ac5622418bbff9cd3dc607aa57dfb4f62a7f2043 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 15 Jun 2011 15:08:17 -0700 Subject: kmsg_dump.h: fix build when CONFIG_PRINTK is disabled Fix when CONFIG_PRINTK is not enabled: include/linux/kmsg_dump.h:56: error: 'EINVAL' undeclared (first use in this function) include/linux/kmsg_dump.h:61: error: 'EINVAL' undeclared (first use in this function) Looks like commit 595dd3d8bf95 ("kmsg_dump: fix build for CONFIG_PRINTK=n") uses EINVAL without having the needed header file(s), but I'm sure that I build tested that patch also. oh well. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kmsg_dump.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index 2a0d7d651dc3..ee0c952188de 100644 --- a/include/linux/kmsg_dump.h +++ b/include/linux/kmsg_dump.h @@ -12,6 +12,7 @@ #ifndef _LINUX_KMSG_DUMP_H #define _LINUX_KMSG_DUMP_H +#include #include enum kmsg_dump_reason { -- cgit v1.2.3 From 17441227f6258fc379c6ebfe21c3eec43b6f0de3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 15 Jun 2011 15:08:17 -0700 Subject: checkpatch: add warning for uses of printk_ratelimit Warn about uses of printk_ratelimit() because it uses a global state and can hide subsequent useful messages. Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8657f99bfb2b..b0aa2c680593 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1943,6 +1943,11 @@ sub process { WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); } +# check for uses of printk_ratelimit + if ($line =~ /\bprintk_ratelimit\s*\(/) { + WARN("Prefer printk_ratelimited or pr__ratelimited to printk_ratelimit\n" . $herecurr); + } + # printk should use KERN_* levels. Note that follow on printk's on the # same line do not need a level, so we use the current block context # to try and find and validate the current printk. In summary the current -- cgit v1.2.3 From 32e45ff43eaf5c17f5a82c9ad358d515622c2562 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 15 Jun 2011 15:08:20 -0700 Subject: mm: increase RECLAIM_DISTANCE to 30 Recently, Robert Mueller reported (http://lkml.org/lkml/2010/9/12/236) that zone_reclaim_mode doesn't work properly on his new NUMA server (Dual Xeon E5520 + Intel S5520UR MB). He is using Cyrus IMAPd and it's built on a very traditional single-process model. * a master process which reads config files and manages the other process * multiple imapd processes, one per connection * multiple pop3d processes, one per connection * multiple lmtpd processes, one per connection * periodical "cleanup" processes. There are thousands of independent processes. The problem is, recent Intel motherboard turn on zone_reclaim_mode by default and traditional prefork model software don't work well on it. Unfortunatelly, such models are still typical even in the 21st century. We can't ignore them. This patch raises the zone_reclaim_mode threshold to 30. 30 doesn't have any specific meaning. but 20 means that one-hop QPI/Hypertransport and such relatively cheap 2-4 socket machine are often used for traditional servers as above. The intention is that these machines don't use zone_reclaim_mode. Note: ia64 and Power have arch specific RECLAIM_DISTANCE definitions. This patch doesn't change such high-end NUMA machine behavior. Dave Hansen said: : I know specifically of pieces of x86 hardware that set the information : in the BIOS to '21' *specifically* so they'll get the zone_reclaim_mode : behavior which that implies. : : They've done performance testing and run very large and scary benchmarks : to make sure that they _want_ this turned on. What this means for them : is that they'll probably be de-optimized, at least on newer versions of : the kernel. : : If you want to do this for particular systems, maybe _that_'s what we : should do. Have a list of specific configurations that need the : defaults overridden either because they're buggy, or they have an : unusual hardware configuration not really reflected in the distance : table. And later said: : The original change in the hardware tables was for the benefit of a : benchmark. Said benchmark isn't going to get run on mainline until the : next batch of enterprise distros drops, at which point the hardware where : this was done will be irrelevant for the benchmark. I'm sure any new : hardware will just set this distance to another yet arbitrary value to : make the kernel do what it wants. :) : : Also, when the hardware got _set_ to this initially, I complained. So, I : guess I'm getting my way now, with this patch. I'm cool with it. Reported-by: Robert Mueller Signed-off-by: KOSAKI Motohiro Acked-by: Christoph Lameter Acked-by: David Rientjes Reviewed-by: KAMEZAWA Hiroyuki Cc: Benjamin Herrenschmidt Cc: "Luck, Tony" Acked-by: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/topology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/topology.h b/include/linux/topology.h index b91a40e847d2..fc839bfa7935 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -60,7 +60,7 @@ int arch_update_cpu_topology(void); * (in whatever arch specific measurement units returned by node_distance()) * then switch on zone reclaim on boot. */ -#define RECLAIM_DISTANCE 20 +#define RECLAIM_DISTANCE 30 #endif #ifndef PENALTY_FOR_NODE_WITH_CPUS #define PENALTY_FOR_NODE_WITH_CPUS (1) -- cgit v1.2.3 From 5a1e6f75831bf1f8e596d642cd8a2512f11548fc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 15 Jun 2011 15:08:21 -0700 Subject: drivers/misc/spear13xx_pcie_gadget.c: fix a memory leak in spear_pcie_gadget_probe error path In the case of goto err_kzalloc, we should kfree target. Signed-off-by: Axel Lin Acked-by: Pratyush Anand Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/spear13xx_pcie_gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c index 7aded90f9daa..cfbddbef11de 100644 --- a/drivers/misc/spear13xx_pcie_gadget.c +++ b/drivers/misc/spear13xx_pcie_gadget.c @@ -845,7 +845,7 @@ err_iounmap: err_iounmap_app: iounmap(config->va_app_base); err_kzalloc: - kfree(config); + kfree(target); err_rel_res: release_mem_region(res1->start, resource_size(res1)); err_rel_res0: -- cgit v1.2.3 From 4bbd61fb9726808e72ab2aa440401f6e5e1aa8f7 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Wed, 15 Jun 2011 15:08:22 -0700 Subject: drivers/misc/cs5535-mfgpt.c: fix wrong if condition Fix the wrong `if' condition for the check if the requested timer is available. The bitmap avail is used to store if a timer is used already. test_bit() is used to check if the requested timer is available. If a bit in the avail bitmap is set it means that the timer is available. The runtime effect would be that allocating a specific timer always fails (versus telling cs5535_mfgpt_alloc_timer to allocate the first available timer, which works). Signed-off-by: Christian Gmeiner Acked-by: Andres Salomon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/cs5535-mfgpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c index e01e08c8c88b..bc685bfc4c33 100644 --- a/drivers/misc/cs5535-mfgpt.c +++ b/drivers/misc/cs5535-mfgpt.c @@ -174,7 +174,7 @@ struct cs5535_mfgpt_timer *cs5535_mfgpt_alloc_timer(int timer_nr, int domain) timer_nr = t < max ? (int) t : -1; } else { /* check if the requested timer's available */ - if (test_bit(timer_nr, mfgpt->avail)) + if (!test_bit(timer_nr, mfgpt->avail)) timer_nr = -1; } -- cgit v1.2.3 From 5f1a19070b16c20cdc71ed0e981bfa19f8f6a4ee Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 15 Jun 2011 15:08:23 -0700 Subject: mm: fix wrong kunmap_atomic() pointer Running a ktest.pl test, I hit the following bug on x86_32: ------------[ cut here ]------------ WARNING: at arch/x86/mm/highmem_32.c:81 __kunmap_atomic+0x64/0xc1() Hardware name: Modules linked in: Pid: 93, comm: sh Not tainted 2.6.39-test+ #1 Call Trace: [] warn_slowpath_common+0x7c/0x91 [] ? __kunmap_atomic+0x64/0xc1 [] ? __kunmap_atomic+0x64/0xc1^M [] warn_slowpath_null+0x22/0x24 [] __kunmap_atomic+0x64/0xc1 [] unmap_vmas+0x43a/0x4e0 [] exit_mmap+0x91/0xd2 [] mmput+0x43/0xad [] exit_mm+0x111/0x119 [] do_exit+0x1ff/0x5fa [] ? set_current_blocked+0x3c/0x40 [] ? sigprocmask+0x7e/0x8e [] do_group_exit+0x65/0x88 [] sys_exit_group+0x18/0x1c [] sysenter_do_call+0x12/0x38 ---[ end trace 8055f74ea3c0eb62 ]--- Running a ktest.pl git bisect, found the culprit: commit e303297e6c3a ("mm: extended batches for generic mmu_gather") But although this was the commit triggering the bug, it was not the one originally responsible for the bug. That was commit d16dfc550f53 ("mm: mmu_gather rework"). The code in zap_pte_range() has something that looks like the following: pte = pte_offset_map_lock(mm, pmd, addr, &ptl); do { [...] } while (pte++, addr += PAGE_SIZE, addr != end); pte_unmap_unlock(pte - 1, ptl); The pte starts off pointing at the first element in the page table directory that was returned by the pte_offset_map_lock(). When it's done with the page, pte will be pointing to anything between the next entry and the first entry of the next page inclusive. By doing a pte - 1, this puts the pte back onto the original page, which is all that pte_unmap_unlock() needs. In most archs (64 bit), this is not an issue as the pte is ignored in the pte_unmap_unlock(). But on 32 bit archs, where things may be kmapped, it is essential that the pte passed to pte_unmap_unlock() resides on the same page that was given by pte_offest_map_lock(). The problem came in d16dfc55 ("mm: mmu_gather rework") where it introduced a "break;" from the while loop. This alone did not seem to easily trigger the bug. But the modifications made by e303297e6 caused that "break;" to be hit on the first iteration, before the pte++. The pte not being incremented will now cause pte_unmap_unlock(pte - 1) to be pointing to the previous page. This will cause the wrong page to be unmapped, and also trigger the warning above. The simple solution is to just save the pointer given by pte_offset_map_lock() and use it in the unlock. Signed-off-by: Steven Rostedt Cc: Peter Zijlstra Cc: KAMEZAWA Hiroyuki Acked-by: Hugh Dickins Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index b13e7dbc399b..87d935333f0d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1112,11 +1112,13 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, int force_flush = 0; int rss[NR_MM_COUNTERS]; spinlock_t *ptl; + pte_t *start_pte; pte_t *pte; again: init_rss_vec(rss); - pte = pte_offset_map_lock(mm, pmd, addr, &ptl); + start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl); + pte = start_pte; arch_enter_lazy_mmu_mode(); do { pte_t ptent = *pte; @@ -1196,7 +1198,7 @@ again: add_mm_rss_vec(mm, rss); arch_leave_lazy_mmu_mode(); - pte_unmap_unlock(pte - 1, ptl); + pte_unmap_unlock(start_pte, ptl); /* * mmu_gather ran out of room to batch pages, we break out of -- cgit v1.2.3 From 3957c7768e5ea02fd3345176ddd340f820e5d285 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Wed, 15 Jun 2011 15:08:25 -0700 Subject: mm: compaction: fix special case -1 order checks Commit 56de7263fcf3 ("mm: compaction: direct compact when a high-order allocation fails") introduced a check for cc->order == -1 in compact_finished. We should continue compacting in that case because the request came from userspace and there is no particular order to compact for. Similar check has been added by 82478fb7 (mm: compaction: prevent division-by-zero during user-requested compaction) for compaction_suitable. The check is, however, done after zone_watermark_ok which uses order as a right hand argument for shifts. Not only watermark check is pointless if we can break out without it but it also uses 1 << -1 which is not well defined (at least from C standard). Let's move the -1 check above zone_watermark_ok. [minchan.kim@gmail.com> - caught compaction_suitable] Signed-off-by: Michal Hocko Cc: Mel Gorman Reviewed-by: Minchan Kim Reviewed-by: KAMEZAWA Hiroyuki Acked-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 021a2960ef9e..94bdbe1f7caf 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -420,13 +420,6 @@ static int compact_finished(struct zone *zone, if (cc->free_pfn <= cc->migrate_pfn) return COMPACT_COMPLETE; - /* Compaction run is not finished if the watermark is not met */ - watermark = low_wmark_pages(zone); - watermark += (1 << cc->order); - - if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0)) - return COMPACT_CONTINUE; - /* * order == -1 is expected when compacting via * /proc/sys/vm/compact_memory @@ -434,6 +427,13 @@ static int compact_finished(struct zone *zone, if (cc->order == -1) return COMPACT_CONTINUE; + /* Compaction run is not finished if the watermark is not met */ + watermark = low_wmark_pages(zone); + watermark += (1 << cc->order); + + if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0)) + return COMPACT_CONTINUE; + /* Direct compactor: Is a suitable page free? */ for (order = cc->order; order < MAX_ORDER; order++) { /* Job done if page is free of the right migratetype */ @@ -460,6 +460,13 @@ unsigned long compaction_suitable(struct zone *zone, int order) int fragindex; unsigned long watermark; + /* + * order == -1 is expected when compacting via + * /proc/sys/vm/compact_memory + */ + if (order == -1) + return COMPACT_CONTINUE; + /* * Watermarks for order-0 must be met for compaction. Note the 2UL. * This is because during migration, copies of pages need to be @@ -469,13 +476,6 @@ unsigned long compaction_suitable(struct zone *zone, int order) if (!zone_watermark_ok(zone, 0, watermark, 0, 0)) return COMPACT_SKIPPED; - /* - * order == -1 is expected when compacting via - * /proc/sys/vm/compact_memory - */ - if (order == -1) - return COMPACT_CONTINUE; - /* * fragmentation index determines if allocation failures are due to * low memory or external fragmentation -- cgit v1.2.3 From ca39599c633fb02aceac31a7e67563612e4fe347 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 15 Jun 2011 15:08:27 -0700 Subject: BUILD_BUG_ON_ZERO: fix sparse breakage BUILD_BUG_ON_ZERO and BUILD_BUG_ON_NULL must return values, even in the CHECKER case otherwise various users of it become syntactically invalid. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kernel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index fb0e7329fee1..953352a88336 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -671,8 +671,8 @@ struct sysinfo { #ifdef __CHECKER__ #define BUILD_BUG_ON_NOT_POWER_OF_2(n) -#define BUILD_BUG_ON_ZERO(e) -#define BUILD_BUG_ON_NULL(e) +#define BUILD_BUG_ON_ZERO(e) (0) +#define BUILD_BUG_ON_NULL(e) ((void*)0) #define BUILD_BUG_ON(condition) #else /* __CHECKER__ */ -- cgit v1.2.3 From bd5dc17be87b3a3073d50b23802647db3ae3fa8e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 15 Jun 2011 15:08:28 -0700 Subject: uts: make default hostname configurable, rather than always using "(none)" The "hostname" tool falls back to setting the hostname to "localhost" if /etc/hostname does not exist. Distribution init scripts have the same fallback. However, if userspace never calls sethostname, such as when booting with init=/bin/sh, or otherwise booting a minimal system without the usual init scripts, the default hostname of "(none)" remains, unhelpfully appearing in various places such as prompts ("root@(none):~#") and logs. Furthermore, "(none)" doesn't typically resolve to anything useful. Make the default hostname configurable. This removes the need for the standard fallback, provides a useful default for systems that never call sethostname, and makes minimal systems that much more useful with less configuration. Distributions could choose to use "localhost" here to avoid the fallback, while embedded systems may wish to use a specific target hostname. Signed-off-by: Josh Triplett Acked-by: Linus Torvalds Acked-by: David Miller Cc: Serge Hallyn Cc: Kel Modderman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/uts.h | 2 +- init/Kconfig | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/linux/uts.h b/include/linux/uts.h index 73eb1ed36ec4..6ddbd86377de 100644 --- a/include/linux/uts.h +++ b/include/linux/uts.h @@ -9,7 +9,7 @@ #endif #ifndef UTS_NODENAME -#define UTS_NODENAME "(none)" /* set by sethostname() */ +#define UTS_NODENAME CONFIG_DEFAULT_HOSTNAME /* set by sethostname() */ #endif #ifndef UTS_DOMAINNAME diff --git a/init/Kconfig b/init/Kconfig index ebafac4231ee..e0a22e42d39a 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -204,6 +204,15 @@ config KERNEL_LZO endchoice +config DEFAULT_HOSTNAME + string "Default hostname" + default "(none)" + help + This option determines the default system hostname before userspace + calls sethostname(2). The kernel traditionally uses "(none)" here, + but you may wish to use a different default here to make a minimal + system more usable with less configuration. + config SWAP bool "Support for paging of anonymous memory (swap)" depends on MMU && BLOCK -- cgit v1.2.3 From 185e595f770219f2329e590a6be69e6e89e152af Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Wed, 15 Jun 2011 15:08:30 -0700 Subject: MAINTAINERS: Balbir has moved Update my email address. Email will start to the old address bouncing soon Signed-off-by: Balbir Singh Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2cc3a9430503..88c016d209ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4144,7 +4144,7 @@ F: include/linux/mm.h F: mm/ MEMORY RESOURCE CONTROLLER -M: Balbir Singh +M: Balbir Singh M: Daisuke Nishimura M: KAMEZAWA Hiroyuki L: linux-mm@kvack.org @@ -4889,7 +4889,7 @@ F: mm/percpu*.c F: arch/*/include/asm/percpu.h PER-TASK DELAY ACCOUNTING -M: Balbir Singh +M: Balbir Singh S: Maintained F: include/linux/delayacct.h F: kernel/delayacct.c @@ -6097,7 +6097,7 @@ F: include/target/ F: Documentation/target/ TASKSTATS STATISTICS INTERFACE -M: Balbir Singh +M: Balbir Singh S: Maintained F: Documentation/accounting/taskstats* F: include/linux/taskstats* -- cgit v1.2.3 From 9d8f776bfb812dd23fcdbb698e9ac4298fc3c624 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 15 Jun 2011 15:08:31 -0700 Subject: drivers/leds/leds-asic3: make LEDS_ASIC3 depend on LEDS_CLASS We call led_classdev_unregister/led_classdev_register in asic3_led_remove/asic3_led_probe, thus make LEDS_ASIC3 depend on LEDS_CLASS. This patch fixes below build error if LEDS_CLASS is not configured. LD .tmp_vmlinux1 drivers/built-in.o: In function `asic3_led_remove': clkdev.c:(.devexit.text+0x1860): undefined reference to `led_classdev_unregister' drivers/built-in.o: In function `asic3_led_probe': clkdev.c:(.devinit.text+0xcee8): undefined reference to `led_classdev_register' make: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Axel Lin Cc: Paul Parsons Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 23f0d5e99f35..883813d7843c 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -391,6 +391,7 @@ config LEDS_NETXBIG config LEDS_ASIC3 bool "LED support for the HTC ASIC3" + depends on LEDS_CLASS depends on MFD_ASIC3 default y help -- cgit v1.2.3 From be5ce2f1c93295711be4ae5565f9194ed9776ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Jun 2011 15:08:31 -0700 Subject: leds: move LEDS_GPIO_REGISTER out of menuconfig NEW_LEDS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 4440673a95e6 ("leds: provide helper to register "leds-gpio" devices") broke the display of the NEW_LEDS menu as it didn't depend on NEW_LEDS and so made "LED drivers" and "LED Triggers" appear at the same level as "LED Support" instead of below it as it was before 4440673a. Moving LEDS_GPIO_REGISTER out of the menuconfig NEW_LEDS fixes this unintended side effect. Reported-by: Axel Lin Signed-off-by: Uwe Kleine-König Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 883813d7843c..1032730cd17b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -1,3 +1,10 @@ +config LEDS_GPIO_REGISTER + bool + help + This option provides the function gpio_led_register_device. + As this function is used by arch code it must not be compiled as a + module. + menuconfig NEW_LEDS bool "LED Support" help @@ -14,13 +21,6 @@ config LEDS_CLASS This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. -config LEDS_GPIO_REGISTER - bool - help - This option provides the function gpio_led_register_device. - As this function is used by arch code it must not be compiled as a - module. - if NEW_LEDS comment "LED drivers" -- cgit v1.2.3 From 9e6f343852cb16ea961ba5be2ca8dde609aa6f23 Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Wed, 15 Jun 2011 15:08:32 -0700 Subject: MAINTAINERS: add videobuf2 maintainers Add maintainers for the videobuf2 V4L2 driver framework. Signed-off-by: Pawel Osciak Acked-by: Marek Szyprowski Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 88c016d209ff..518442ab25af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6716,6 +6716,14 @@ S: Maintained F: Documentation/filesystems/vfat.txt F: fs/fat/ +VIDEOBUF2 FRAMEWORK +M: Pawel Osciak +M: Marek Szyprowski +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/video/videobuf2-* +F: include/media/videobuf2-* + VIRTIO CONSOLE DRIVER M: Amit Shah L: virtualization@lists.linux-foundation.org -- cgit v1.2.3 From 49b24d6b41c576ba43153fc94695f871cce139a5 Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Wed, 15 Jun 2011 15:08:34 -0700 Subject: include/asm-generic/pgtable.h: fix unbalanced parenthesis Signed-off-by: Nicolas Kaiser Reviewed-by: Andrea Arcangeli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-generic/pgtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index e9b8e5926bef..76bff2bff15e 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -88,7 +88,7 @@ static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, pmd_t pmd = *pmdp; pmd_clear(mm, address, pmdp); return pmd; -}) +} #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif -- cgit v1.2.3 From 26575f9544530127757297d4de8fb2f2c75f1f69 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 15 Jun 2011 15:08:35 -0700 Subject: w1: W1_MASTER_DS1WM should depend on GENERIC_HARDIRQS On m68k (which doesn't support generic hardirqs yet): drivers/w1/masters/ds1wm.c: In function `ds1wm_probe': drivers/w1/masters/ds1wm.c: error: implicit declaration of function `irq_set_irq_type' Signed-off-by: Geert Uytterhoeven Cc: Evgeniy Polyakov Cc: Jean-Franois Dagenais Cc: Matt Reimer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/masters/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 00d615d7aa21..979d6eed9a0f 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -42,7 +42,7 @@ config W1_MASTER_MXC config W1_MASTER_DS1WM tristate "Maxim DS1WM 1-wire busmaster" - depends on W1 + depends on W1 && GENERIC_HARDIRQS help Say Y here to enable the DS1WM 1-wire driver, such as that in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like -- cgit v1.2.3 From de695e159e3fd679594eb45449d2638d54434c32 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 15 Jun 2011 15:08:37 -0700 Subject: init/calibrate.c: remove annoying printk Remove calibrate_delay_direct()'s KERN_DEBUG printk related to bogomips calculation as it appears when booting every core on setups with 'ignore_loglevel' which dmesg people scan for possible issues. As the message doesn't show very useful information to the widest audience of kernel boot message gazers, it should be removed. Introduced by commit d2b463135f84 ("init/calibrate.c: fix for critical bogoMIPS intermittent calculation failure"). Signed-off-by: Borislav Petkov Cc: Andrew Worsley Cc: Phil Carmody Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/calibrate.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/init/calibrate.c b/init/calibrate.c index cfd7000c9d71..2568d22a304e 100644 --- a/init/calibrate.c +++ b/init/calibrate.c @@ -93,9 +93,6 @@ static unsigned long __cpuinit calibrate_delay_direct(void) * If the upper limit and lower limit of the timer_rate is * >= 12.5% apart, redo calibration. */ - printk(KERN_DEBUG "calibrate_delay_direct() timer_rate_max=%lu " - "timer_rate_min=%lu pre_start=%lu pre_end=%lu\n", - timer_rate_max, timer_rate_min, pre_start, pre_end); if (start >= post_end) printk(KERN_NOTICE "calibrate_delay_direct() ignoring " "timer_rate as we had a TSC wrap around" -- cgit v1.2.3 From 959ecc48fc7506b9d7825ea70e40d92d9b308033 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:38 -0700 Subject: mm/memory_hotplug.c: fix building of node hotplug zonelist During memory hotplug we refresh zonelists when we online a page in a new zone. It means that the node's zonelist is not initialized until pages are onlined. So for example, "nid" passed by MEM_GOING_ONLINE notifier will point to NODE_DATA(nid) which has no zone fallback list. Moreover, if we hot-add cpu-only nodes, alloc_pages() will do no fallback. This patch makes a zonelist when a new pgdata is available. Note: in production, at fujitsu, memory should be onlined before cpu and our server didn't have any memory-less nodes and had no problems. But recent changes in MEM_GOING_ONLINE+page_cgroup will access not initialized zonelist of node. Anyway, there are memory-less node and we need some care. Signed-off-by: KAMEZAWA Hiroyuki Cc: Mel Gorman Cc: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 9f646374e32f..02159c755136 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -494,6 +494,12 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) /* init node's zones as empty zones, we don't have any present pages.*/ free_area_init_node(nid, zones_size, start_pfn, zholes_size); + /* + * The node we allocated has no zone fallback lists. For avoiding + * to access not-initialized zonelist, build here. + */ + build_all_zonelists(NULL); + return pgdat; } -- cgit v1.2.3 From b0320c7b7d1ac1bd5c2d9dff3258524ab39bad32 Mon Sep 17 00:00:00 2001 From: Rafael Aquini Date: Wed, 15 Jun 2011 15:08:39 -0700 Subject: mm: fix negative commitlimit when gigantic hugepages are allocated When 1GB hugepages are allocated on a system, free(1) reports less available memory than what really is installed in the box. Also, if the total size of hugepages allocated on a system is over half of the total memory size, CommitLimit becomes a negative number. The problem is that gigantic hugepages (order > MAX_ORDER) can only be allocated at boot with bootmem, thus its frames are not accounted to 'totalram_pages'. However, they are accounted to hugetlb_total_pages() What happens to turn CommitLimit into a negative number is this calculation, in fs/proc/meminfo.c: allowed = ((totalram_pages - hugetlb_total_pages()) * sysctl_overcommit_ratio / 100) + total_swap_pages; A similar calculation occurs in __vm_enough_memory() in mm/mmap.c. Also, every vm statistic which depends on 'totalram_pages' will render confusing values, as if system were 'missing' some part of its memory. Impact of this bug: When gigantic hugepages are allocated and sysctl_overcommit_memory == OVERCOMMIT_NEVER. In a such situation, __vm_enough_memory() goes through the mentioned 'allowed' calculation and might end up mistakenly returning -ENOMEM, thus forcing the system to start reclaiming pages earlier than it would be ususal, and this could cause detrimental impact to overall system's performance, depending on the workload. Besides the aforementioned scenario, I can only think of this causing annoyances with memory reports from /proc/meminfo and free(1). [akpm@linux-foundation.org: standardize comment layout] Reported-by: Russ Anderson Signed-off-by: Rafael Aquini Acked-by: Russ Anderson Cc: Andrea Arcangeli Cc: Christoph Lameter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 6402458fee38..bfcf153bc829 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1111,6 +1111,14 @@ static void __init gather_bootmem_prealloc(void) WARN_ON(page_count(page) != 1); prep_compound_huge_page(page, h->order); prep_new_huge_page(h, page, page_to_nid(page)); + /* + * If we had gigantic hugepages allocated at boot time, we need + * to restore the 'stolen' pages to totalram_pages in order to + * fix confusing memory reports from free(1) and another + * side-effects, like CommitLimit going negative. + */ + if (h->order > (MAX_ORDER - 1)) + totalram_pages += 1 << h->order; } } -- cgit v1.2.3 From 45d16f09ddd66597e561876f5652c05bf986360a Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 15 Jun 2011 15:08:40 -0700 Subject: leds: fix the incorrect display in menuconfig Seems when a config option does not have a dependency of the menuconfig, it messes the display of the rest configs, even if it's a hidden one. Signed-off-by: Eric Miao Cc: Richard Purdie Cc: Valdis Kletnieks Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 1032730cd17b..713d43b4e563 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -14,15 +14,14 @@ menuconfig NEW_LEDS This is not related to standard keyboard LEDs which are controlled via the input system. +if NEW_LEDS + config LEDS_CLASS bool "LED Class Support" - depends on NEW_LEDS help This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. -if NEW_LEDS - comment "LED drivers" config LEDS_88PM860X -- cgit v1.2.3 From 8957712710e045044e3c44375c6a87d7ffa17d51 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:41 -0700 Subject: mm: memory.numa_stat: fix file permission Commit 406eb0c9ba76 ("memcg: add memory.numastat api for numa statistics") adds memory.numa_stat file for memory cgroup. But the file permissions are wrong. [kamezawa@bluextal linux-2.6]$ ls -l /cgroup/memory/A/memory.numa_stat ---------- 1 root root 0 Jun 9 18:36 /cgroup/memory/A/memory.numa_stat This patch fixes the permission as [root@bluextal kamezawa]# ls -l /cgroup/memory/A/memory.numa_stat -r--r--r-- 1 root root 0 Jun 10 16:49 /cgroup/memory/A/memory.numa_stat Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e37c44d88d46..02a7947608ad 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4640,6 +4640,7 @@ static struct cftype mem_cgroup_files[] = { { .name = "numa_stat", .open = mem_control_numa_stat_open, + .mode = S_IRUGO, }, #endif }; -- cgit v1.2.3 From 37573e8c718277103f61f03741bdc5606d31b07e Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:42 -0700 Subject: memcg: fix init_page_cgroup nid with sparsemem Commit 21a3c9646873 ("memcg: allocate memory cgroup structures in local nodes") makes page_cgroup allocation as NUMA aware. But that caused a problem https://bugzilla.kernel.org/show_bug.cgi?id=36192. The problem was getting a NID from invalid struct pages, which was not initialized because it was out-of-node, out of [node_start_pfn, node_end_pfn) Now, with sparsemem, page_cgroup_init scans pfn from 0 to max_pfn. But this may scan a pfn which is not on any node and can access memmap which is not initialized. This makes page_cgroup_init() for SPARSEMEM node aware and remove a code to get nid from page->flags. (Then, we'll use valid NID always.) [akpm@linux-foundation.org: try to fix up comments] Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_cgroup.c | 71 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 74ccff61d1be..53bffc6c293e 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c @@ -162,13 +162,13 @@ static void free_page_cgroup(void *addr) } #endif -static int __meminit init_section_page_cgroup(unsigned long pfn) +static int __meminit init_section_page_cgroup(unsigned long pfn, int nid) { struct page_cgroup *base, *pc; struct mem_section *section; unsigned long table_size; unsigned long nr; - int nid, index; + int index; nr = pfn_to_section_nr(pfn); section = __nr_to_section(nr); @@ -176,7 +176,6 @@ static int __meminit init_section_page_cgroup(unsigned long pfn) if (section->page_cgroup) return 0; - nid = page_to_nid(pfn_to_page(pfn)); table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; base = alloc_page_cgroup(table_size, nid); @@ -196,7 +195,11 @@ static int __meminit init_section_page_cgroup(unsigned long pfn) pc = base + index; init_page_cgroup(pc, nr); } - + /* + * The passed "pfn" may not be aligned to SECTION. For the calculation + * we need to apply a mask. + */ + pfn &= PAGE_SECTION_MASK; section->page_cgroup = base - pfn; total_usage += table_size; return 0; @@ -225,10 +228,20 @@ int __meminit online_page_cgroup(unsigned long start_pfn, start = start_pfn & ~(PAGES_PER_SECTION - 1); end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION); + if (nid == -1) { + /* + * In this case, "nid" already exists and contains valid memory. + * "start_pfn" passed to us is a pfn which is an arg for + * online__pages(), and start_pfn should exist. + */ + nid = pfn_to_nid(start_pfn); + VM_BUG_ON(!node_state(nid, N_ONLINE)); + } + for (pfn = start; !fail && pfn < end; pfn += PAGES_PER_SECTION) { if (!pfn_present(pfn)) continue; - fail = init_section_page_cgroup(pfn); + fail = init_section_page_cgroup(pfn, nid); } if (!fail) return 0; @@ -284,25 +297,47 @@ static int __meminit page_cgroup_callback(struct notifier_block *self, void __init page_cgroup_init(void) { unsigned long pfn; - int fail = 0; + int nid; if (mem_cgroup_disabled()) return; - for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) { - if (!pfn_present(pfn)) - continue; - fail = init_section_page_cgroup(pfn); - } - if (fail) { - printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n"); - panic("Out of memory"); - } else { - hotplug_memory_notifier(page_cgroup_callback, 0); + for_each_node_state(nid, N_HIGH_MEMORY) { + unsigned long start_pfn, end_pfn; + + start_pfn = node_start_pfn(nid); + end_pfn = node_end_pfn(nid); + /* + * start_pfn and end_pfn may not be aligned to SECTION and the + * page->flags of out of node pages are not initialized. So we + * scan [start_pfn, the biggest section's pfn < end_pfn) here. + */ + for (pfn = start_pfn; + pfn < end_pfn; + pfn = ALIGN(pfn + 1, PAGES_PER_SECTION)) { + + if (!pfn_valid(pfn)) + continue; + /* + * Nodes's pfns can be overlapping. + * We know some arch can have a nodes layout such as + * -------------pfn--------------> + * N0 | N1 | N2 | N0 | N1 | N2|.... + */ + if (pfn_to_nid(pfn) != nid) + continue; + if (init_section_page_cgroup(pfn, nid)) + goto oom; + } } + hotplug_memory_notifier(page_cgroup_callback, 0); printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage); - printk(KERN_INFO "please try 'cgroup_disable=memory' option if you don't" - " want memory cgroups\n"); + printk(KERN_INFO "please try 'cgroup_disable=memory' option if you " + "don't want memory cgroups\n"); + return; +oom: + printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n"); + panic("Out of memory"); } void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat) -- cgit v1.2.3 From 733eda7ac316cd4e550fa096e4ed42356dc546e7 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:43 -0700 Subject: memcg: clear mm->owner when last possible owner leaves The following crash was reported: > Call Trace: > [] mem_cgroup_from_task+0x15/0x17 > [] __mem_cgroup_try_charge+0x148/0x4b4 > [] ? need_resched+0x23/0x2d > [] ? preempt_schedule+0x46/0x4f > [] mem_cgroup_charge_common+0x9a/0xce > [] mem_cgroup_newpage_charge+0x5d/0x5f > [] khugepaged+0x5da/0xfaf > [] ? __init_waitqueue_head+0x4b/0x4b > [] ? add_mm_counter.constprop.5+0x13/0x13 > [] kthread+0xa8/0xb0 > [] ? sub_preempt_count+0xa1/0xb4 > [] kernel_thread_helper+0x4/0x10 > [] ? retint_restore_args+0x13/0x13 > [] ? __init_kthread_worker+0x5a/0x5a What happens is that khugepaged tries to charge a huge page against an mm whose last possible owner has already exited, and the memory controller crashes when the stale mm->owner is used to look up the cgroup to charge. mm->owner has never been set to NULL with the last owner going away, but nobody cared until khugepaged came along. Even then it wasn't a problem because the final mmput() on an mm was forced to acquire and release mmap_sem in write-mode, preventing an exiting owner to go away while the mmap_sem was held, and until "692e0b3 mm: thp: optimize memcg charge in khugepaged", the memory cgroup charge was protected by mmap_sem in read-mode. Instead of going back to relying on the mmap_sem to enforce lifetime of a task, this patch ensures that mm->owner is properly set to NULL when the last possible owner is exiting, which the memory controller can handle just fine. [akpm@linux-foundation.org: tweak comments] Signed-off-by: Hugh Dickins Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Johannes Weiner Reported-by: Hugh Dickins Reported-by: Dave Jones Reviewed-by: Andrea Arcangeli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/exit.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/kernel/exit.c b/kernel/exit.c index 20a406471525..f2b321bae440 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -561,29 +561,28 @@ void exit_files(struct task_struct *tsk) #ifdef CONFIG_MM_OWNER /* - * Task p is exiting and it owned mm, lets find a new owner for it + * A task is exiting. If it owned this mm, find a new owner for the mm. */ -static inline int -mm_need_new_owner(struct mm_struct *mm, struct task_struct *p) -{ - /* - * If there are other users of the mm and the owner (us) is exiting - * we need to find a new owner to take on the responsibility. - */ - if (atomic_read(&mm->mm_users) <= 1) - return 0; - if (mm->owner != p) - return 0; - return 1; -} - void mm_update_next_owner(struct mm_struct *mm) { struct task_struct *c, *g, *p = current; retry: - if (!mm_need_new_owner(mm, p)) + /* + * If the exiting or execing task is not the owner, it's + * someone else's problem. + */ + if (mm->owner != p) return; + /* + * The current owner is exiting/execing and there are no other + * candidates. Do not leave the mm pointing to a possibly + * freed task structure. + */ + if (atomic_read(&mm->mm_users) <= 1) { + mm->owner = NULL; + return; + } read_lock(&tasklist_lock); /* -- cgit v1.2.3 From 7ae534d074e01e54d5cfbc9734b73fdfc855501f Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:44 -0700 Subject: memcg: fix wrong check of noswap with softlimit Hierarchical reclaim doesn't swap out if memsw and resource limits are thye same (memsw_is_minimum == true) because we would hit mem+swap limit anyway (during hard limit reclaim). If it comes to the soft limit we shouldn't consider memsw_is_minimum at all because it doesn't make much sense. Either the soft limit is bellow the hard limit and then we cannot hit mem+swap limit or the direct reclaim takes a precedence. Signed-off-by: KAMEZAWA Hiroyuki Reviewed-by: Michal Hocko Acked-by: Daisuke Nishimura Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 02a7947608ad..0b1a32cbd74d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1663,7 +1663,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT; /* If memsw_is_minimum==1, swap-out is of-no-use. */ - if (root_mem->memsw_is_minimum) + if (!check_soft && root_mem->memsw_is_minimum) noswap = true; while (1) { -- cgit v1.2.3 From 26fe616844491a41a1abc02e29f7a9d1ec2f8ddb Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:45 -0700 Subject: memcg: fix percpu cached charge draining frequency For performance, memory cgroup caches some "charge" from res_counter into per cpu cache. This works well but because it's cache, it needs to be flushed in some cases. Typical cases are 1. when someone hit limit. 2. when rmdir() is called and need to charges to be 0. But "1" has problem. Recently, with large SMP machines, we see many kworker runs because of flushing memcg's cache. Bad things in implementation are that even if a cpu contains a cache for memcg not related to a memcg which hits limit, drain code is called. This patch does A) check percpu cache contains a useful data or not. B) check other asynchronous percpu draining doesn't run. C) don't call local cpu callback. (*)This patch avoid changing the calling condition with hard-limit. When I run "cat 1Gfile > /dev/null" under 300M limit memcg, [Before] 13767 kamezawa 20 0 98.6m 424 416 D 10.0 0.0 0:00.61 cat 58 root 20 0 0 0 0 S 0.6 0.0 0:00.09 kworker/2:1 60 root 20 0 0 0 0 S 0.6 0.0 0:00.08 kworker/4:1 4 root 20 0 0 0 0 S 0.3 0.0 0:00.02 kworker/0:0 57 root 20 0 0 0 0 S 0.3 0.0 0:00.05 kworker/1:1 61 root 20 0 0 0 0 S 0.3 0.0 0:00.05 kworker/5:1 62 root 20 0 0 0 0 S 0.3 0.0 0:00.05 kworker/6:1 63 root 20 0 0 0 0 S 0.3 0.0 0:00.05 kworker/7:1 [After] 2676 root 20 0 98.6m 416 416 D 9.3 0.0 0:00.87 cat 2626 kamezawa 20 0 15192 1312 920 R 0.3 0.0 0:00.28 top 1 root 20 0 19384 1496 1204 S 0.0 0.0 0:00.66 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0 4 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0 [akpm@linux-foundation.org: make percpu_charge_mutex static, tweak comments] Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Daisuke Nishimura Reviewed-by: Michal Hocko Tested-by: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 54 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0b1a32cbd74d..c39a177bb641 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -359,7 +359,7 @@ enum charge_type { static void mem_cgroup_get(struct mem_cgroup *mem); static void mem_cgroup_put(struct mem_cgroup *mem); static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem); -static void drain_all_stock_async(void); +static void drain_all_stock_async(struct mem_cgroup *mem); static struct mem_cgroup_per_zone * mem_cgroup_zoneinfo(struct mem_cgroup *mem, int nid, int zid) @@ -1671,7 +1671,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, if (victim == root_mem) { loop++; if (loop >= 1) - drain_all_stock_async(); + drain_all_stock_async(root_mem); if (loop >= 2) { /* * If we have not been able to reclaim @@ -1934,9 +1934,11 @@ struct memcg_stock_pcp { struct mem_cgroup *cached; /* this never be root cgroup */ unsigned int nr_pages; struct work_struct work; + unsigned long flags; +#define FLUSHING_CACHED_CHARGE (0) }; static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock); -static atomic_t memcg_drain_count; +static DEFINE_MUTEX(percpu_charge_mutex); /* * Try to consume stocked charge on this cpu. If success, one page is consumed @@ -1984,6 +1986,7 @@ static void drain_local_stock(struct work_struct *dummy) { struct memcg_stock_pcp *stock = &__get_cpu_var(memcg_stock); drain_stock(stock); + clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags); } /* @@ -2008,26 +2011,45 @@ static void refill_stock(struct mem_cgroup *mem, unsigned int nr_pages) * expects some charges will be back to res_counter later but cannot wait for * it. */ -static void drain_all_stock_async(void) +static void drain_all_stock_async(struct mem_cgroup *root_mem) { - int cpu; - /* This function is for scheduling "drain" in asynchronous way. - * The result of "drain" is not directly handled by callers. Then, - * if someone is calling drain, we don't have to call drain more. - * Anyway, WORK_STRUCT_PENDING check in queue_work_on() will catch if - * there is a race. We just do loose check here. + int cpu, curcpu; + /* + * If someone calls draining, avoid adding more kworker runs. */ - if (atomic_read(&memcg_drain_count)) + if (!mutex_trylock(&percpu_charge_mutex)) return; /* Notify other cpus that system-wide "drain" is running */ - atomic_inc(&memcg_drain_count); get_online_cpus(); + /* + * Get a hint for avoiding draining charges on the current cpu, + * which must be exhausted by our charging. It is not required that + * this be a precise check, so we use raw_smp_processor_id() instead of + * getcpu()/putcpu(). + */ + curcpu = raw_smp_processor_id(); for_each_online_cpu(cpu) { struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu); - schedule_work_on(cpu, &stock->work); + struct mem_cgroup *mem; + + if (cpu == curcpu) + continue; + + mem = stock->cached; + if (!mem) + continue; + if (mem != root_mem) { + if (!root_mem->use_hierarchy) + continue; + /* check whether "mem" is under tree of "root_mem" */ + if (!css_is_ancestor(&mem->css, &root_mem->css)) + continue; + } + if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) + schedule_work_on(cpu, &stock->work); } put_online_cpus(); - atomic_dec(&memcg_drain_count); + mutex_unlock(&percpu_charge_mutex); /* We don't wait for flush_work */ } @@ -2035,9 +2057,9 @@ static void drain_all_stock_async(void) static void drain_all_stock_sync(void) { /* called when force_empty is called */ - atomic_inc(&memcg_drain_count); + mutex_lock(&percpu_charge_mutex); schedule_on_each_cpu(drain_local_stock); - atomic_dec(&memcg_drain_count); + mutex_unlock(&percpu_charge_mutex); } /* -- cgit v1.2.3 From fbc29a25e484be073e7d762c9f7f1d4bf8aecc48 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:46 -0700 Subject: memcg: avoid percpu cached charge draining at softlimit Based on Michal Hocko's comment. We are not draining per cpu cached charges during soft limit reclaim because background reclaim doesn't care about charges. It tries to free some memory and charges will not give any. Cached charges might influence only selection of the biggest soft limit offender but as the call is done only after the selection has been already done it makes no change. Signed-off-by: KAMEZAWA Hiroyuki Cc: Daisuke Nishimura Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c39a177bb641..cf7d027a8844 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1670,7 +1670,13 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, victim = mem_cgroup_select_victim(root_mem); if (victim == root_mem) { loop++; - if (loop >= 1) + /* + * We are not draining per cpu cached charges during + * soft limit reclaim because global reclaim doesn't + * care about charges. It tries to free some memory and + * charges will not give any. + */ + if (!check_soft && loop >= 1) drain_all_stock_async(root_mem); if (loop >= 2) { /* -- cgit v1.2.3 From b0461a44a2f1fc052fc949ae19c3a5d684627b09 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 15 Jun 2011 15:08:46 -0700 Subject: MAINTAINERS: add entry for legacy eeprom driver I shall maintain the legacy eeprom driver, until we finally get rid of it. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 518442ab25af..6c59eb90fdf4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3819,6 +3819,12 @@ S: Maintained F: drivers/leds/ F: include/linux/leds.h +LEGACY EEPROM DRIVER +M: Jean Delvare +S: Maintained +F: Documentation/misc-devices/eeprom +F: drivers/misc/eeprom/eeprom.c + LEGO USB Tower driver M: Juergen Stuber L: legousb-devel@lists.sourceforge.net -- cgit v1.2.3 From d2c32258798f813dc2be6cbc32f78aa5ac5cb205 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 15 Jun 2011 15:08:47 -0700 Subject: gcov: disable CONFIG_CONSTRUCTORS when not needed by CONFIG_GCOV_KERNEL CONFIG_CONSTRUCTORS controls support for running constructor functions at kernel init time. According to commit b99b87f70c7785ab ("kernel: constructor support"), gcov (CONFIG_GCOV_KERNEL) needs this. However, CONFIG_CONSTRUCTORS currently defaults to y, with no option to disable it, and CONFIG_GCOV_KERNEL depends on it. Instead, default it to n and have CONFIG_GCOV_KERNEL select it, so that the normal case of CONFIG_GCOV_KERNEL=n will result in CONFIG_CONSTRUCTORS=n. Observed in the short list of =y values in a minimal kernel configuration. Signed-off-by: Josh Triplett Acked-by: WANG Cong Acked-by: Peter Oberparleiter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/Kconfig | 1 - kernel/gcov/Kconfig | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index e0a22e42d39a..412c21b00d51 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -19,7 +19,6 @@ config DEFCONFIG_LIST config CONSTRUCTORS bool depends on !UML - default y config HAVE_IRQ_WORK bool diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig index b8cadf70b1fb..5bf924d80b5c 100644 --- a/kernel/gcov/Kconfig +++ b/kernel/gcov/Kconfig @@ -2,7 +2,8 @@ menu "GCOV-based kernel profiling" config GCOV_KERNEL bool "Enable gcov-based kernel profiling" - depends on DEBUG_FS && CONSTRUCTORS + depends on DEBUG_FS + select CONSTRUCTORS default n ---help--- This option enables gcov-based code profiling (e.g. for code coverage -- cgit v1.2.3 From 5db8a73a8d7cc6a66afbf25ed7fda338caa8f5f9 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Wed, 15 Jun 2011 15:08:48 -0700 Subject: mm/memory-failure.c: fix page isolated count mismatch Pages isolated for migration are accounted with the vmstat counters NR_ISOLATE_[ANON|FILE]. Callers of migrate_pages() are expected to increment these counters when pages are isolated from the LRU. Once the pages have been migrated, they are put back on the LRU or freed and the isolated count is decremented. Memory failure is not properly accounting for pages it isolates causing the NR_ISOLATED counters to be negative. On SMP builds, this goes unnoticed as negative counters are treated as 0 due to expected per-cpu drift. On UP builds, the counter is treated by too_many_isolated() as a large value causing processes to enter D state during page reclaim or compaction. This patch accounts for pages isolated by memory failure correctly. [mel@csn.ul.ie: rewrote changelog] Reviewed-by: Andrea Arcangeli Signed-off-by: Minchan Kim Cc: Andi Kleen Acked-by: Mel Gorman Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory-failure.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 5c8f7e08928d..eac0ba561491 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -52,6 +52,7 @@ #include #include #include +#include #include "internal.h" int sysctl_memory_failure_early_kill __read_mostly = 0; @@ -1468,7 +1469,8 @@ int soft_offline_page(struct page *page, int flags) put_page(page); if (!ret) { LIST_HEAD(pagelist); - + inc_zone_page_state(page, NR_ISOLATED_ANON + + page_is_file_cache(page)); list_add(&page->lru, &pagelist); ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0, true); -- cgit v1.2.3 From a582a738c763e106f47eab24b8146c698a9c700b Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 15 Jun 2011 15:08:49 -0700 Subject: compaction: checks correct fragmentation index fragmentation_index() returns -1000 when the allocation might succeed This doesn't match the comment and code in compaction_suitable(). I thought compaction_suitable should return COMPACT_PARTIAL in -1000 case, because in this case allocation could succeed depending on watermarks. The impact of this is that compaction starts and compact_finished() is called which rechecks the watermarks and the free lists. It should have the same result in that compaction should not start but is more expensive. Acked-by: Mel Gorman Signed-off-by: Shaohua Li Cc: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 94bdbe1f7caf..cf7086c6dc07 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -480,7 +480,8 @@ unsigned long compaction_suitable(struct zone *zone, int order) * fragmentation index determines if allocation failures are due to * low memory or external fragmentation * - * index of -1 implies allocations might succeed dependingon watermarks + * index of -1000 implies allocations might succeed depending on + * watermarks * index towards 0 implies failure is due to lack of memory * index towards 1000 implies failure is due to fragmentation * @@ -490,7 +491,8 @@ unsigned long compaction_suitable(struct zone *zone, int order) if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold) return COMPACT_SKIPPED; - if (fragindex == -1 && zone_watermark_ok(zone, order, watermark, 0, 0)) + if (fragindex == -1000 && zone_watermark_ok(zone, order, watermark, + 0, 0)) return COMPACT_PARTIAL; return COMPACT_CONTINUE; -- cgit v1.2.3 From 7454f4ba40b419eb999a3c61a99da662bf1a2bb8 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 15 Jun 2011 15:08:50 -0700 Subject: mm: compaction: ensure that the compaction free scanner does not move to the next zone Compaction works with two scanners, a migration and a free scanner. When the scanners crossover, migration within the zone is complete. The location of the scanner is recorded on each cycle to avoid excesive scanning. When a zone is small and mostly reserved, it's very easy for the migration scanner to be close to the end of the zone. Then the following situation can occurs o migration scanner isolates some pages near the end of the zone o free scanner starts at the end of the zone but finds that the migration scanner is already there o free scanner gets reinitialised for the next cycle as cc->migrate_pfn + pageblock_nr_pages moving the free scanner into the next zone o migration scanner moves into the next zone When this happens, NR_ISOLATED accounting goes haywire because some of the accounting happens against the wrong zone. One zones counter remains positive while the other goes negative even though the overall global count is accurate. This was reported on X86-32 with !SMP because !SMP allows the negative counters to be visible. The fact that it is the bug should theoritically be possible there. Signed-off-by: Mel Gorman Reviewed-by: Minchan Kim Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mm/compaction.c b/mm/compaction.c index cf7086c6dc07..9b94eaf537e4 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -144,9 +144,20 @@ static void isolate_freepages(struct zone *zone, int nr_freepages = cc->nr_freepages; struct list_head *freelist = &cc->freepages; + /* + * Initialise the free scanner. The starting point is where we last + * scanned from (or the end of the zone if starting). The low point + * is the end of the pageblock the migration scanner is using. + */ pfn = cc->free_pfn; low_pfn = cc->migrate_pfn + pageblock_nr_pages; - high_pfn = low_pfn; + + /* + * Take care that if the migration scanner is at the end of the zone + * that the free scanner does not accidentally move to the next zone + * in the next isolation cycle. + */ + high_pfn = min(low_pfn, pfn); /* * Isolate free pages until enough are available to migrate the -- cgit v1.2.3 From d179e84ba5da1d0024087d1759a2938817a00f3f Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Wed, 15 Jun 2011 15:08:51 -0700 Subject: mm: vmscan: do not use page_count without a page pin It is unsafe to run page_count during the physical pfn scan because compound_head could trip on a dangling pointer when reading page->first_page if the compound page is being freed by another CPU. [mgorman@suse.de: split out patch] Signed-off-by: Andrea Arcangeli Signed-off-by: Mel Gorman Reviewed-by: Michal Hocko Reviewed-by: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index dbe6ea321df4..8ff834e19c24 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1124,8 +1124,20 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, nr_lumpy_dirty++; scan++; } else { - /* the page is freed already. */ - if (!page_count(cursor_page)) + /* + * Check if the page is freed already. + * + * We can't use page_count() as that + * requires compound_head and we don't + * have a pin on the page here. If a + * page is tail, we may or may not + * have isolated the head, so assume + * it's not free, it'd be tricky to + * track the head status without a + * page pin. + */ + if (!PageTail(cursor_page) && + !atomic_read(&cursor_page->_count)) continue; break; } -- cgit v1.2.3 From f9e35b3b41f47c4e17d8132edbcab305a6aaa4b0 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 15 Jun 2011 15:08:52 -0700 Subject: mm: compaction: abort compaction if too many pages are isolated and caller is asynchronous V2 Asynchronous compaction is used when promoting to huge pages. This is all very nice but if there are a number of processes in compacting memory, a large number of pages can be isolated. An "asynchronous" process can stall for long periods of time as a result with a user reporting that firefox can stall for 10s of seconds. This patch aborts asynchronous compaction if too many pages are isolated as it's better to fail a hugepage promotion than stall a process. [minchan.kim@gmail.com: return COMPACT_PARTIAL for abort] Reported-and-tested-by: Ury Stankevich Signed-off-by: Mel Gorman Reviewed-by: Minchan Kim Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 9b94eaf537e4..6cc604bd5649 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -251,11 +251,18 @@ static bool too_many_isolated(struct zone *zone) return isolated > (inactive + active) / 2; } +/* possible outcome of isolate_migratepages */ +typedef enum { + ISOLATE_ABORT, /* Abort compaction now */ + ISOLATE_NONE, /* No pages isolated, continue scanning */ + ISOLATE_SUCCESS, /* Pages isolated, migrate */ +} isolate_migrate_t; + /* * Isolate all pages that can be migrated from the block pointed to by * the migrate scanner within compact_control. */ -static unsigned long isolate_migratepages(struct zone *zone, +static isolate_migrate_t isolate_migratepages(struct zone *zone, struct compact_control *cc) { unsigned long low_pfn, end_pfn; @@ -272,7 +279,7 @@ static unsigned long isolate_migratepages(struct zone *zone, /* Do not cross the free scanner or scan within a memory hole */ if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) { cc->migrate_pfn = end_pfn; - return 0; + return ISOLATE_NONE; } /* @@ -281,10 +288,14 @@ static unsigned long isolate_migratepages(struct zone *zone, * delay for some time until fewer pages are isolated */ while (unlikely(too_many_isolated(zone))) { + /* async migration should just abort */ + if (!cc->sync) + return ISOLATE_ABORT; + congestion_wait(BLK_RW_ASYNC, HZ/10); if (fatal_signal_pending(current)) - return 0; + return ISOLATE_ABORT; } /* Time to isolate some pages for migration */ @@ -369,7 +380,7 @@ static unsigned long isolate_migratepages(struct zone *zone, trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); - return cc->nr_migratepages; + return ISOLATE_SUCCESS; } /* @@ -535,8 +546,15 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) unsigned long nr_migrate, nr_remaining; int err; - if (!isolate_migratepages(zone, cc)) + switch (isolate_migratepages(zone, cc)) { + case ISOLATE_ABORT: + ret = COMPACT_PARTIAL; + goto out; + case ISOLATE_NONE: continue; + case ISOLATE_SUCCESS: + ; + } nr_migrate = cc->nr_migratepages; err = migrate_pages(&cc->migratepages, compaction_alloc, @@ -560,6 +578,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) } +out: /* Release free pages and check accounting */ cc->nr_freepages -= release_freepages(&cc->freepages); VM_BUG_ON(cc->nr_freepages != 0); -- cgit v1.2.3 From 31b5f8eeece4c0d70b649bfac7759cf7e3f915dd Mon Sep 17 00:00:00 2001 From: "akpm@linux-foundation.org" Date: Wed, 15 Jun 2011 15:08:52 -0700 Subject: Documentation/feature-removal-schedule.txt: remove ns_cgroup from feature-removal-schedule.txt Commit a77aea92010acf ("cgroup: remove the ns_cgroup") removed the ns_cgroup but it forgot to remove the related doc in feature-removal-schedule.txt. Signed-off-by: WANG Cong Cc: Daniel Lezcano Cc: Serge E. Hallyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 1a9446b59153..72e238465b0b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -481,23 +481,6 @@ Who: FUJITA Tomonori ---------------------------- -What: namespace cgroup (ns_cgroup) -When: 2.6.38 -Why: The ns_cgroup leads to some problems: - * cgroup creation is out-of-control - * cgroup name can conflict when pids are looping - * it is not possible to have a single process handling - a lot of namespaces without falling in a exponential creation time - * we may want to create a namespace without creating a cgroup - - The ns_cgroup is replaced by a compatibility flag 'clone_children', - where a newly created cgroup will copy the parent cgroup values. - The userspace has to manually create a cgroup and add a task to - the 'tasks' file. -Who: Daniel Lezcano - ----------------------------- - What: iwlwifi disable_hw_scan module parameters When: 2.6.40 Why: Hareware scan is the prefer method for iwlwifi devices for -- cgit v1.2.3 From 273ef9509b7903e50f36aaf9f1d5dc9087fca506 Mon Sep 17 00:00:00 2001 From: Nils Carlson Date: Wed, 15 Jun 2011 15:08:54 -0700 Subject: drivers/char/hpet.c: fix periodic-emulation for delayed interrupts When interrupts are delayed due to interrupt masking or due to other interrupts being serviced the HPET periodic-emuation would fail. This happened because given an interval t and a time for the current interrupt m we would compute the next time as t + m. This works until we are delayed for > t, in which case we would be writing a new value which is in fact in the past. This can be solved by computing the next time instead as (k * t) + m where k is large enough to be in the future. The exact computation of k is described in a comment to the code. More detail: Assuming an interval of 5 between each expected interrupt we have a normal case of t0: interrupt, read t0 from comparator, set next interrupt t0 + 5 t5: interrupt, read t5 from comparator, set next interrupt t5 + 5 t10: interrupt, read t10 from comparator, set next interrupt t10 + 5 ... So, what happens when the interrupt is serviced too late? t0: interrupt, read t0 from comparator, set next interrupt t0 + 5 t11: delayed interrupt serviced, read t5 from comparator, set next interrupt t5 + 5, which is in the past! ... counter loops ... t10: Much much later, get the next interrupt. This can happen either because we have interrupts masked for too long (some stupid driver goes on a printk rampage) or just because we are pushing the limits of the interval (too small a period), or both most probably. My solution is to read the main counter as well and set the next interrupt to occur at the right interval, for example: t0: interrupt, read t0 from comparator, set next interrupt t0 + 5 t11: delayed interrupt serviced, read t5 from comparator, set next interrupt t15 as t10 has been missed. t15: back on track. Signed-off-by: Nils Carlson Cc: John Stultz Cc: Thomas Gleixner Cc: Clemens Ladisch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hpet.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 051474c65b78..34d6a1cab8de 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -163,11 +163,32 @@ static irqreturn_t hpet_interrupt(int irq, void *data) * This has the effect of treating non-periodic like periodic. */ if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) { - unsigned long m, t; + unsigned long m, t, mc, base, k; + struct hpet __iomem *hpet = devp->hd_hpet; + struct hpets *hpetp = devp->hd_hpets; t = devp->hd_ireqfreq; m = read_counter(&devp->hd_timer->hpet_compare); - write_counter(t + m, &devp->hd_timer->hpet_compare); + mc = read_counter(&hpet->hpet_mc); + /* The time for the next interrupt would logically be t + m, + * however, if we are very unlucky and the interrupt is delayed + * for longer than t then we will completely miss the next + * interrupt if we set t + m and an application will hang. + * Therefore we need to make a more complex computation assuming + * that there exists a k for which the following is true: + * k * t + base < mc + delta + * (k + 1) * t + base > mc + delta + * where t is the interval in hpet ticks for the given freq, + * base is the theoretical start value 0 < base < t, + * mc is the main counter value at the time of the interrupt, + * delta is the time it takes to write the a value to the + * comparator. + * k may then be computed as (mc - base + delta) / t . + */ + base = mc % t; + k = (mc - base + hpetp->hp_delta) / t; + write_counter(t * (k + 1) + base, + &devp->hd_timer->hpet_compare); } if (devp->hd_flags & HPET_SHARED_IRQ) -- cgit v1.2.3 From fb139dfeef9558a12ffdbf9e26951fd1a9304f3b Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 15 Jun 2011 15:08:55 -0700 Subject: drivers/tty/serial/pch_uart.c: don't oops if dmi_get_system_info returns NULL If dmi_get_system_info() returns NULL, pch_uart_init_port() will dereferencea a zero pointer. This oops was observed on an Atom based board which has no BIOS, but a bootloder which doesn't provide DMI data. Signed-off-by: Alexander Stein Cc: Greg KH Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/tty/serial/pch_uart.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index f2cb7503fcb2..465210930890 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1397,6 +1397,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, int fifosize, base_baud; int port_type; struct pch_uart_driver_data *board; + const char *board_name; board = &drv_dat[id->driver_data]; port_type = board->port_type; @@ -1412,7 +1413,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, base_baud = 1843200; /* 1.8432MHz */ /* quirk for CM-iTC board */ - if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC")) + board_name = dmi_get_system_info(DMI_BOARD_NAME); + if (board_name && strstr(board_name, "CM-iTC")) base_baud = 192000000; /* 192.0MHz */ switch (port_type) { -- cgit v1.2.3 From c7cbb02222eccb82bfd42696b01abceddae663f2 Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Wed, 15 Jun 2011 15:08:56 -0700 Subject: rtc: fix build warnings in defconfigs RTC_CLASS is changed to bool, so 'm' is invalid. Signed-off-by: Wanlong Gao Acked-by: Mike Frysinger Acked-by: Wolfram Sang Acked-by: Hans-Christian Egtvedt Acked-by: Benjamin Herrenschmidt Cc: Guan Xuetao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/configs/davinci_all_defconfig | 2 +- arch/arm/configs/netx_defconfig | 2 +- arch/arm/configs/viper_defconfig | 2 +- arch/arm/configs/xcep_defconfig | 2 +- arch/arm/configs/zeus_defconfig | 2 +- arch/avr32/configs/atngw100_mrmt_defconfig | 2 +- arch/blackfin/configs/CM-BF548_defconfig | 2 +- arch/mips/configs/mtx1_defconfig | 2 +- arch/powerpc/configs/52xx/pcm030_defconfig | 2 +- arch/powerpc/configs/ps3_defconfig | 2 +- arch/sh/configs/titan_defconfig | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index 889922ad229c..67b5abb6f857 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig @@ -157,7 +157,7 @@ CONFIG_LEDS_GPIO=m CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_XFS_FS=m diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig index 316af5479d90..9c0ad7993986 100644 --- a/arch/arm/configs/netx_defconfig +++ b/arch/arm/configs/netx_defconfig @@ -60,7 +60,7 @@ CONFIG_FB_ARMCLCD=y # CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_INOTIFY=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig index 8b0c717378fa..1d01ddd33122 100644 --- a/arch/arm/configs/viper_defconfig +++ b/arch/arm/configs/viper_defconfig @@ -142,7 +142,7 @@ CONFIG_USB_GADGETFS=m CONFIG_USB_FILE_STORAGE=m CONFIG_USB_G_SERIAL=m CONFIG_USB_G_PRINTER=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=m CONFIG_RTC_DRV_SA1100=m CONFIG_EXT2_FS=m diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig index 5b5504143647..721832ffe2d7 100644 --- a/arch/arm/configs/xcep_defconfig +++ b/arch/arm/configs/xcep_defconfig @@ -73,7 +73,7 @@ CONFIG_SENSORS_MAX6650=m # CONFIG_VGA_CONSOLE is not set # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_SA1100=m CONFIG_DMADEVICES=y # CONFIG_DNOTIFY is not set diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig index 960f65514d88..59577ad3f4ef 100644 --- a/arch/arm/configs/zeus_defconfig +++ b/arch/arm/configs/zeus_defconfig @@ -158,7 +158,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_ISL1208=m CONFIG_RTC_DRV_PXA=m CONFIG_EXT2_FS=y diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig index 6cb786c0baf6..77ca4f905d2c 100644 --- a/arch/avr32/configs/atngw100_mrmt_defconfig +++ b/arch/avr32/configs/atngw100_mrmt_defconfig @@ -110,7 +110,7 @@ CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_S35390A=m CONFIG_RTC_DRV_AT32AP700X=m CONFIG_DMADEVICES=y diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig index 31d954216c05..9f1d08401fca 100644 --- a/arch/blackfin/configs/CM-BF548_defconfig +++ b/arch/blackfin/configs/CM-BF548_defconfig @@ -112,7 +112,7 @@ CONFIG_USB_G_SERIAL=m CONFIG_USB_G_PRINTER=m CONFIG_MMC=m CONFIG_SDH_BFIN=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_BFIN=m CONFIG_EXT2_FS=m # CONFIG_DNOTIFY is not set diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index 37862b2ce363..807c97eed8a8 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -678,7 +678,7 @@ CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_INTF_DEV_UIE_EMUL=y CONFIG_RTC_DRV_TEST=m CONFIG_RTC_DRV_DS1307=m diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig index 7f7e4a878602..22e719575c60 100644 --- a/arch/powerpc/configs/52xx/pcm030_defconfig +++ b/arch/powerpc/configs/52xx/pcm030_defconfig @@ -85,7 +85,7 @@ CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_HCD_PPC_OF_BE=y # CONFIG_USB_OHCI_HCD_PCI is not set CONFIG_USB_STORAGE=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_PCF8563=m CONFIG_EXT2_FS=m CONFIG_EXT3_FS=m diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 6472322bf13b..185c292b0f1c 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig @@ -141,7 +141,7 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_EHCI_HCD_PPC_OF is not set CONFIG_USB_OHCI_HCD=m CONFIG_USB_STORAGE=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_PS3=m CONFIG_EXT2_FS=m CONFIG_EXT3_FS=m diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig index 0f558914e760..e2cbd92d520b 100644 --- a/arch/sh/configs/titan_defconfig +++ b/arch/sh/configs/titan_defconfig @@ -227,7 +227,7 @@ CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_ARK3116=m CONFIG_USB_SERIAL_PL2303=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_SH=m CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y -- cgit v1.2.3 From 2b472611a32a72f4a118c069c2d62a1a3f087afd Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 15 Jun 2011 15:08:58 -0700 Subject: ksm: fix NULL pointer dereference in scan_get_next_rmap_item() Andrea Righi reported a case where an exiting task can race against ksmd::scan_get_next_rmap_item (http://lkml.org/lkml/2011/6/1/742) easily triggering a NULL pointer dereference in ksmd. ksm_scan.mm_slot == &ksm_mm_head with only one registered mm CPU 1 (__ksm_exit) CPU 2 (scan_get_next_rmap_item) list_empty() is false lock slot == &ksm_mm_head list_del(slot->mm_list) (list now empty) unlock lock slot = list_entry(slot->mm_list.next) (list is empty, so slot is still ksm_mm_head) unlock slot->mm == NULL ... Oops Close this race by revalidating that the new slot is not simply the list head again. Andrea's test case: #include #include #include #include #define BUFSIZE getpagesize() int main(int argc, char **argv) { void *ptr; if (posix_memalign(&ptr, getpagesize(), BUFSIZE) < 0) { perror("posix_memalign"); exit(1); } if (madvise(ptr, BUFSIZE, MADV_MERGEABLE) < 0) { perror("madvise"); exit(1); } *(char *)NULL = 0; return 0; } Reported-by: Andrea Righi Tested-by: Andrea Righi Cc: Andrea Arcangeli Signed-off-by: Hugh Dickins Signed-off-by: Chris Wright Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/ksm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/ksm.c b/mm/ksm.c index d708b3ef2260..9a68b0cf0a1c 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -1302,6 +1302,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page) slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list); ksm_scan.mm_slot = slot; spin_unlock(&ksm_mmlist_lock); + /* + * Although we tested list_empty() above, a racing __ksm_exit + * of the last mm on the list may have removed it since then. + */ + if (slot == &ksm_mm_head) + return NULL; next_mm: ksm_scan.address = 0; ksm_scan.rmap_list = &slot->rmap_list; -- cgit v1.2.3 From ec8f9ceacef719a844ca269d654502af6a00a273 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 15 Jun 2011 15:08:59 -0700 Subject: drivers/misc/apds990x.c: apds990x_chip_on() should depend on CONFIG_PM || CONFIG_PM_RUNTIME Fixes this warning: drivers/misc/apds990x.c: At top level: drivers/misc/apds990x.c:613: warning: `apds990x_chip_on' defined but not used Signed-off-by: Geert Uytterhoeven Cc: Samu Onkalo Cc: Jonathan Cameron Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/apds990x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c index 200311fea369..e2a52e5cf449 100644 --- a/drivers/misc/apds990x.c +++ b/drivers/misc/apds990x.c @@ -609,6 +609,7 @@ static int apds990x_detect(struct apds990x_chip *chip) return ret; } +#if defined(CONFIG_PM) || defined(CONFIG_PM_RUNTIME) static int apds990x_chip_on(struct apds990x_chip *chip) { int err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), @@ -624,6 +625,7 @@ static int apds990x_chip_on(struct apds990x_chip *chip) apds990x_mode_on(chip); return 0; } +#endif static int apds990x_chip_off(struct apds990x_chip *chip) { -- cgit v1.2.3 From 21c5977a836e399fc710ff2c5367845ed5c2527f Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Jun 2011 15:09:01 -0700 Subject: alpha: fix several security issues Fix several security issues in Alpha-specific syscalls. Untested, but mostly trivial. 1. Signedness issue in osf_getdomainname allows copying out-of-bounds kernel memory to userland. 2. Signedness issue in osf_sysinfo allows copying large amounts of kernel memory to userland. 3. Typo (?) in osf_getsysinfo bounds minimum instead of maximum copy size, allowing copying large amounts of kernel memory to userland. 4. Usage of user pointer in osf_wait4 while under KERNEL_DS allows privilege escalation via writing return value of sys_wait4 to kernel memory. Signed-off-by: Dan Rosenberg Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/osf_sys.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 376f22130791..326f0a2d56e5 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -409,7 +409,7 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen) return -EFAULT; len = namelen; - if (namelen > 32) + if (len > 32) len = 32; down_read(&uts_sem); @@ -594,7 +594,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) down_read(&uts_sem); res = sysinfo_table[offset]; len = strlen(res)+1; - if (len > count) + if ((unsigned long)len > (unsigned long)count) len = count; if (copy_to_user(buf, res, len)) err = -EFAULT; @@ -649,7 +649,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer, return 1; case GSI_GET_HWRPB: - if (nbytes < sizeof(*hwrpb)) + if (nbytes > sizeof(*hwrpb)) return -EINVAL; if (copy_to_user(buffer, hwrpb, nbytes) != 0) return -EFAULT; @@ -1008,6 +1008,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, { struct rusage r; long ret, err; + unsigned int status = 0; mm_segment_t old_fs; if (!ur) @@ -1016,13 +1017,15 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r); + ret = sys_wait4(pid, (unsigned int __user *) &status, options, + (struct rusage __user *) &r); set_fs (old_fs); if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) return -EFAULT; err = 0; + err |= put_user(status, ustatus); err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); -- cgit v1.2.3 From 04c55715cbd5de526046745bca3d3b6ffa6641c6 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 15 Jun 2011 12:57:09 -0700 Subject: Documentation: update printk-formats.txt This patch updates the incomplete documentation concerning the printk extended format specifiers. Signed-off-by: Andrew Murray Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/printk-formats.txt | 119 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 1b5a5ddbc3ef..5df176ed59b8 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -9,7 +9,121 @@ If variable is of Type, use printk format specifier: size_t %zu or %zx ssize_t %zd or %zx -Raw pointer value SHOULD be printed with %p. +Raw pointer value SHOULD be printed with %p. The kernel supports +the following extended format specifiers for pointer types: + +Symbols/Function Pointers: + + %pF versatile_init+0x0/0x110 + %pf versatile_init + %pS versatile_init+0x0/0x110 + %ps versatile_init + %pB prev_fn_of_versatile_init+0x88/0x88 + + For printing symbols and function pointers. The 'S' and 's' specifiers + result in the symbol name with ('S') or without ('s') offsets. Where + this is used on a kernel without KALLSYMS - the symbol address is + printed instead. + + The 'B' specifier results in the symbol name with offsets and should be + used when printing stack backtraces. The specifier takes into + consideration the effect of compiler optimisations which may occur + when tail-call's are used and marked with the noreturn GCC attribute. + + On ia64, ppc64 and parisc64 architectures function pointers are + actually function descriptors which must first be resolved. The 'F' and + 'f' specifiers perform this resolution and then provide the same + functionality as the 'S' and 's' specifiers. + +Kernel Pointers: + + %pK 0x01234567 or 0x0123456789abcdef + + For printing kernel pointers which should be hidden from unprivileged + users. The behaviour of %pK depends on the kptr_restrict sysctl - see + Documentation/sysctl/kernel.txt for more details. + +Struct Resources: + + %pr [mem 0x60000000-0x6fffffff flags 0x2200] or + [mem 0x0000000060000000-0x000000006fffffff flags 0x2200] + %pR [mem 0x60000000-0x6fffffff pref] or + [mem 0x0000000060000000-0x000000006fffffff pref] + + For printing struct resources. The 'R' and 'r' specifiers result in a + printed resource with ('R') or without ('r') a decoded flags member. + +MAC/FDDI addresses: + + %pM 00:01:02:03:04:05 + %pMF 00-01-02-03-04-05 + %pm 000102030405 + + For printing 6-byte MAC/FDDI addresses in hex notation. The 'M' and 'm' + specifiers result in a printed address with ('M') or without ('m') byte + separators. The default byte separator is the colon (':'). + + Where FDDI addresses are concerned the 'F' specifier can be used after + the 'M' specifier to use dash ('-') separators instead of the default + separator. + +IPv4 addresses: + + %pI4 1.2.3.4 + %pi4 001.002.003.004 + %p[Ii][hnbl] + + For printing IPv4 dot-separated decimal addresses. The 'I4' and 'i4' + specifiers result in a printed address with ('i4') or without ('I4') + leading zeros. + + The additional 'h', 'n', 'b', and 'l' specifiers are used to specify + host, network, big or little endian order addresses respectively. Where + no specifier is provided the default network/big endian order is used. + +IPv6 addresses: + + %pI6 0001:0002:0003:0004:0005:0006:0007:0008 + %pi6 00010002000300040005000600070008 + %pI6c 1:2:3:4:5:6:7:8 + + For printing IPv6 network-order 16-bit hex addresses. The 'I6' and 'i6' + specifiers result in a printed address with ('I6') or without ('i6') + colon-separators. Leading zeros are always used. + + The additional 'c' specifier can be used with the 'I' specifier to + print a compressed IPv6 address as described by + http://tools.ietf.org/html/rfc5952 + +UUID/GUID addresses: + + %pUb 00010203-0405-0607-0809-0a0b0c0d0e0f + %pUB 00010203-0405-0607-0809-0A0B0C0D0E0F + %pUl 03020100-0504-0706-0809-0a0b0c0e0e0f + %pUL 03020100-0504-0706-0809-0A0B0C0E0E0F + + For printing 16-byte UUID/GUIDs addresses. The additional 'l', 'L', + 'b' and 'B' specifiers are used to specify a little endian order in + lower ('l') or upper case ('L') hex characters - and big endian order + in lower ('b') or upper case ('B') hex characters. + + Where no additional specifiers are used the default little endian + order with lower case hex characters will be printed. + +struct va_format: + + %pV + + For printing struct va_format structures. These contain a format string + and va_list as follows: + + struct va_format { + const char *fmt; + va_list *va; + }; + + Do not use this feature without some mechanism to verify the + correctness of the format string and va_list arguments. u64 SHOULD be printed with %llu/%llx, (unsigned long long): @@ -32,4 +146,5 @@ Reminder: sizeof() result is of type size_t. Thank you for your cooperation and attention. -By Randy Dunlap +By Randy Dunlap and +Andrew Murray -- cgit v1.2.3 From 06a2c45d6b4a7586eba7cd20dd656b08d8b63c2f Mon Sep 17 00:00:00 2001 From: "Maxin B. John" Date: Wed, 15 Jun 2011 12:58:29 -0700 Subject: Documentation: update kmemleak supported archs Instead of listing the architectures that are supported by kmemleak in Documentation/kmemleak.txt, just refer people to the list of supported architecutures in lib/Kconfig.debug so that Documentation/kmemleak.txt does not need more updates for this. Signed-off-by: Maxin B. John Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/kmemleak.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt index 090e6ee04536..51063e681ca4 100644 --- a/Documentation/kmemleak.txt +++ b/Documentation/kmemleak.txt @@ -11,7 +11,9 @@ with the difference that the orphan objects are not freed but only reported via /sys/kernel/debug/kmemleak. A similar method is used by the Valgrind tool (memcheck --leak-check) to detect the memory leaks in user-space applications. -Kmemleak is supported on x86, arm, powerpc, sparc, sh, microblaze and tile. + +Please check DEBUG_KMEMLEAK dependencies in lib/Kconfig.debug for supported +architectures. Usage ----- -- cgit v1.2.3 From f6e07d38078e82a6aeaae00bb134591ef5ac1167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Sommer?= Date: Wed, 15 Jun 2011 12:59:45 -0700 Subject: Documentation: update cgroupfs mount point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to commit 676db4af0430 ("cgroupfs: create /sys/fs/cgroup to mount cgroupfs on") the canonical mountpoint for the cgroup filesystem is /sys/fs/cgroup. Hence, this should be used in the documentation. Signed-off-by: Jörg Sommer Acked-by: Paul Menage Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/accounting/cgroupstats.txt | 4 +- Documentation/cgroups/blkio-controller.txt | 29 +++++++------- Documentation/cgroups/cgroups.txt | 58 +++++++++++++++++----------- Documentation/cgroups/cpuacct.txt | 21 +++++----- Documentation/cgroups/cpusets.txt | 28 +++++++------- Documentation/cgroups/devices.txt | 6 +-- Documentation/cgroups/freezer-subsystem.txt | 20 +++++----- Documentation/cgroups/memory.txt | 17 ++++---- Documentation/scheduler/sched-design-CFS.txt | 7 ++-- Documentation/scheduler/sched-rt-group.txt | 7 ++-- Documentation/vm/hwpoison.txt | 6 +-- 11 files changed, 109 insertions(+), 94 deletions(-) diff --git a/Documentation/accounting/cgroupstats.txt b/Documentation/accounting/cgroupstats.txt index eda40fd39cad..d16a9849e60e 100644 --- a/Documentation/accounting/cgroupstats.txt +++ b/Documentation/accounting/cgroupstats.txt @@ -21,7 +21,7 @@ information will not be available. To extract cgroup statistics a utility very similar to getdelays.c has been developed, the sample output of the utility is shown below -~/balbir/cgroupstats # ./getdelays -C "/cgroup/a" +~/balbir/cgroupstats # ./getdelays -C "/sys/fs/cgroup/a" sleeping 1, blocked 0, running 1, stopped 0, uninterruptible 0 -~/balbir/cgroupstats # ./getdelays -C "/cgroup" +~/balbir/cgroupstats # ./getdelays -C "/sys/fs/cgroup" sleeping 155, blocked 0, running 1, stopped 0, uninterruptible 2 diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index 465351d4cf85..b1b1bfadc9c0 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt @@ -28,16 +28,19 @@ cgroups. Here is what you can do. - Enable group scheduling in CFQ CONFIG_CFQ_GROUP_IOSCHED=y -- Compile and boot into kernel and mount IO controller (blkio). +- Compile and boot into kernel and mount IO controller (blkio); see + cgroups.txt, Why are cgroups needed?. - mount -t cgroup -o blkio none /cgroup + mount -t tmpfs cgroup_root /sys/fs/cgroup + mkdir /sys/fs/cgroup/blkio + mount -t cgroup -o blkio none /sys/fs/cgroup/blkio - Create two cgroups - mkdir -p /cgroup/test1/ /cgroup/test2 + mkdir -p /sys/fs/cgroup/blkio/test1/ /sys/fs/cgroup/blkio/test2 - Set weights of group test1 and test2 - echo 1000 > /cgroup/test1/blkio.weight - echo 500 > /cgroup/test2/blkio.weight + echo 1000 > /sys/fs/cgroup/blkio/test1/blkio.weight + echo 500 > /sys/fs/cgroup/blkio/test2/blkio.weight - Create two same size files (say 512MB each) on same disk (file1, file2) and launch two dd threads in different cgroup to read those files. @@ -46,12 +49,12 @@ cgroups. Here is what you can do. echo 3 > /proc/sys/vm/drop_caches dd if=/mnt/sdb/zerofile1 of=/dev/null & - echo $! > /cgroup/test1/tasks - cat /cgroup/test1/tasks + echo $! > /sys/fs/cgroup/blkio/test1/tasks + cat /sys/fs/cgroup/blkio/test1/tasks dd if=/mnt/sdb/zerofile2 of=/dev/null & - echo $! > /cgroup/test2/tasks - cat /cgroup/test2/tasks + echo $! > /sys/fs/cgroup/blkio/test2/tasks + cat /sys/fs/cgroup/blkio/test2/tasks - At macro level, first dd should finish first. To get more precise data, keep on looking at (with the help of script), at blkio.disk_time and @@ -68,13 +71,13 @@ Throttling/Upper Limit policy - Enable throttling in block layer CONFIG_BLK_DEV_THROTTLING=y -- Mount blkio controller - mount -t cgroup -o blkio none /cgroup/blkio +- Mount blkio controller (see cgroups.txt, Why are cgroups needed?) + mount -t cgroup -o blkio none /sys/fs/cgroup/blkio - Specify a bandwidth rate on particular device for root group. The format for policy is ": ". - echo "8:16 1048576" > /cgroup/blkio/blkio.read_bps_device + echo "8:16 1048576" > /sys/fs/cgroup/blkio/blkio.read_bps_device Above will put a limit of 1MB/second on reads happening for root group on device having major/minor number 8:16. @@ -149,7 +152,7 @@ Proportional weight policy files Following is the format. - #echo dev_maj:dev_minor weight > /path/to/cgroup/blkio.weight_device + # echo dev_maj:dev_minor weight > blkio.weight_device Configure weight=300 on /dev/sdb (8:16) in this cgroup # echo 8:16 300 > blkio.weight_device # cat blkio.weight_device diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt index 0ed99f08f1f3..15bca101ff62 100644 --- a/Documentation/cgroups/cgroups.txt +++ b/Documentation/cgroups/cgroups.txt @@ -138,7 +138,7 @@ With the ability to classify tasks differently for different resources the admin can easily set up a script which receives exec notifications and depending on who is launching the browser he can - # echo browser_pid > /mnt///tasks + # echo browser_pid > /sys/fs/cgroup///tasks With only a single hierarchy, he now would potentially have to create a separate cgroup for every browser launched and associate it with @@ -153,9 +153,9 @@ apps enhanced CPU power, With ability to write pids directly to resource classes, it's just a matter of : - # echo pid > /mnt/network//tasks + # echo pid > /sys/fs/cgroup/network//tasks (after some time) - # echo pid > /mnt/network//tasks + # echo pid > /sys/fs/cgroup/network//tasks Without this ability, he would have to split the cgroup into multiple separate ones and then associate the new cgroups with the @@ -310,21 +310,24 @@ subsystem, this is the case for the cpuset. To start a new job that is to be contained within a cgroup, using the "cpuset" cgroup subsystem, the steps are something like: - 1) mkdir /dev/cgroup - 2) mount -t cgroup -ocpuset cpuset /dev/cgroup - 3) Create the new cgroup by doing mkdir's and write's (or echo's) in - the /dev/cgroup virtual file system. - 4) Start a task that will be the "founding father" of the new job. - 5) Attach that task to the new cgroup by writing its pid to the - /dev/cgroup tasks file for that cgroup. - 6) fork, exec or clone the job tasks from this founding father task. + 1) mount -t tmpfs cgroup_root /sys/fs/cgroup + 2) mkdir /sys/fs/cgroup/cpuset + 3) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset + 4) Create the new cgroup by doing mkdir's and write's (or echo's) in + the /sys/fs/cgroup virtual file system. + 5) Start a task that will be the "founding father" of the new job. + 6) Attach that task to the new cgroup by writing its pid to the + /sys/fs/cgroup/cpuset/tasks file for that cgroup. + 7) fork, exec or clone the job tasks from this founding father task. For example, the following sequence of commands will setup a cgroup named "Charlie", containing just CPUs 2 and 3, and Memory Node 1, and then start a subshell 'sh' in that cgroup: - mount -t cgroup cpuset -ocpuset /dev/cgroup - cd /dev/cgroup + mount -t tmpfs cgroup_root /sys/fs/cgroup + mkdir /sys/fs/cgroup/cpuset + mount -t cgroup cpuset -ocpuset /sys/fs/cgroup/cpuset + cd /sys/fs/cgroup/cpuset mkdir Charlie cd Charlie /bin/echo 2-3 > cpuset.cpus @@ -345,7 +348,7 @@ Creating, modifying, using the cgroups can be done through the cgroup virtual filesystem. To mount a cgroup hierarchy with all available subsystems, type: -# mount -t cgroup xxx /dev/cgroup +# mount -t cgroup xxx /sys/fs/cgroup The "xxx" is not interpreted by the cgroup code, but will appear in /proc/mounts so may be any useful identifying string that you like. @@ -354,23 +357,32 @@ Note: Some subsystems do not work without some user input first. For instance, if cpusets are enabled the user will have to populate the cpus and mems files for each new cgroup created before that group can be used. +As explained in section `1.2 Why are cgroups needed?' you should create +different hierarchies of cgroups for each single resource or group of +resources you want to control. Therefore, you should mount a tmpfs on +/sys/fs/cgroup and create directories for each cgroup resource or resource +group. + +# mount -t tmpfs cgroup_root /sys/fs/cgroup +# mkdir /sys/fs/cgroup/rg1 + To mount a cgroup hierarchy with just the cpuset and memory subsystems, type: -# mount -t cgroup -o cpuset,memory hier1 /dev/cgroup +# mount -t cgroup -o cpuset,memory hier1 /sys/fs/cgroup/rg1 To change the set of subsystems bound to a mounted hierarchy, just remount with different options: -# mount -o remount,cpuset,blkio hier1 /dev/cgroup +# mount -o remount,cpuset,blkio hier1 /sys/fs/cgroup/rg1 Now memory is removed from the hierarchy and blkio is added. Note this will add blkio to the hierarchy but won't remove memory or cpuset, because the new options are appended to the old ones: -# mount -o remount,blkio /dev/cgroup +# mount -o remount,blkio /sys/fs/cgroup/rg1 To Specify a hierarchy's release_agent: # mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \ - xxx /dev/cgroup + xxx /sys/fs/cgroup/rg1 Note that specifying 'release_agent' more than once will return failure. @@ -379,17 +391,17 @@ when the hierarchy consists of a single (root) cgroup. Supporting the ability to arbitrarily bind/unbind subsystems from an existing cgroup hierarchy is intended to be implemented in the future. -Then under /dev/cgroup you can find a tree that corresponds to the -tree of the cgroups in the system. For instance, /dev/cgroup +Then under /sys/fs/cgroup/rg1 you can find a tree that corresponds to the +tree of the cgroups in the system. For instance, /sys/fs/cgroup/rg1 is the cgroup that holds the whole system. If you want to change the value of release_agent: -# echo "/sbin/new_release_agent" > /dev/cgroup/release_agent +# echo "/sbin/new_release_agent" > /sys/fs/cgroup/rg1/release_agent It can also be changed via remount. -If you want to create a new cgroup under /dev/cgroup: -# cd /dev/cgroup +If you want to create a new cgroup under /sys/fs/cgroup/rg1: +# cd /sys/fs/cgroup/rg1 # mkdir my_cgroup Now you want to do something with this cgroup. diff --git a/Documentation/cgroups/cpuacct.txt b/Documentation/cgroups/cpuacct.txt index 8b930946c52a..9ad85df4b983 100644 --- a/Documentation/cgroups/cpuacct.txt +++ b/Documentation/cgroups/cpuacct.txt @@ -10,26 +10,25 @@ directly present in its group. Accounting groups can be created by first mounting the cgroup filesystem. -# mkdir /cgroups -# mount -t cgroup -ocpuacct none /cgroups - -With the above step, the initial or the parent accounting group -becomes visible at /cgroups. At bootup, this group includes all the -tasks in the system. /cgroups/tasks lists the tasks in this cgroup. -/cgroups/cpuacct.usage gives the CPU time (in nanoseconds) obtained by -this group which is essentially the CPU time obtained by all the tasks +# mount -t cgroup -ocpuacct none /sys/fs/cgroup + +With the above step, the initial or the parent accounting group becomes +visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in +the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup. +/sys/fs/cgroup/cpuacct.usage gives the CPU time (in nanoseconds) obtained +by this group which is essentially the CPU time obtained by all the tasks in the system. -New accounting groups can be created under the parent group /cgroups. +New accounting groups can be created under the parent group /sys/fs/cgroup. -# cd /cgroups +# cd /sys/fs/cgroup # mkdir g1 # echo $$ > g1 The above steps create a new group g1 and move the current shell process (bash) into it. CPU time consumed by this bash and its children can be obtained from g1/cpuacct.usage and the same is accumulated in -/cgroups/cpuacct.usage also. +/sys/fs/cgroup/cpuacct.usage also. cpuacct.stat file lists a few statistics which further divide the CPU time obtained by the cgroup into user and system times. Currently diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt index 98a30829af7a..5b0d78e55ccc 100644 --- a/Documentation/cgroups/cpusets.txt +++ b/Documentation/cgroups/cpusets.txt @@ -661,21 +661,21 @@ than stress the kernel. To start a new job that is to be contained within a cpuset, the steps are: - 1) mkdir /dev/cpuset - 2) mount -t cgroup -ocpuset cpuset /dev/cpuset + 1) mkdir /sys/fs/cgroup/cpuset + 2) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset 3) Create the new cpuset by doing mkdir's and write's (or echo's) in - the /dev/cpuset virtual file system. + the /sys/fs/cgroup/cpuset virtual file system. 4) Start a task that will be the "founding father" of the new job. 5) Attach that task to the new cpuset by writing its pid to the - /dev/cpuset tasks file for that cpuset. + /sys/fs/cgroup/cpuset tasks file for that cpuset. 6) fork, exec or clone the job tasks from this founding father task. For example, the following sequence of commands will setup a cpuset named "Charlie", containing just CPUs 2 and 3, and Memory Node 1, and then start a subshell 'sh' in that cpuset: - mount -t cgroup -ocpuset cpuset /dev/cpuset - cd /dev/cpuset + mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset + cd /sys/fs/cgroup/cpuset mkdir Charlie cd Charlie /bin/echo 2-3 > cpuset.cpus @@ -710,14 +710,14 @@ Creating, modifying, using the cpusets can be done through the cpuset virtual filesystem. To mount it, type: -# mount -t cgroup -o cpuset cpuset /dev/cpuset +# mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset -Then under /dev/cpuset you can find a tree that corresponds to the -tree of the cpusets in the system. For instance, /dev/cpuset +Then under /sys/fs/cgroup/cpuset you can find a tree that corresponds to the +tree of the cpusets in the system. For instance, /sys/fs/cgroup/cpuset is the cpuset that holds the whole system. -If you want to create a new cpuset under /dev/cpuset: -# cd /dev/cpuset +If you want to create a new cpuset under /sys/fs/cgroup/cpuset: +# cd /sys/fs/cgroup/cpuset # mkdir my_cpuset Now you want to do something with this cpuset. @@ -765,12 +765,12 @@ wrapper around the cgroup filesystem. The command -mount -t cpuset X /dev/cpuset +mount -t cpuset X /sys/fs/cgroup/cpuset is equivalent to -mount -t cgroup -ocpuset,noprefix X /dev/cpuset -echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent +mount -t cgroup -ocpuset,noprefix X /sys/fs/cgroup/cpuset +echo "/sbin/cpuset_release_agent" > /sys/fs/cgroup/cpuset/release_agent 2.2 Adding/removing cpus ------------------------ diff --git a/Documentation/cgroups/devices.txt b/Documentation/cgroups/devices.txt index 57ca4c89fe5c..16624a7f8222 100644 --- a/Documentation/cgroups/devices.txt +++ b/Documentation/cgroups/devices.txt @@ -22,16 +22,16 @@ removed from the child(ren). An entry is added using devices.allow, and removed using devices.deny. For instance - echo 'c 1:3 mr' > /cgroups/1/devices.allow + echo 'c 1:3 mr' > /sys/fs/cgroup/1/devices.allow allows cgroup 1 to read and mknod the device usually known as /dev/null. Doing - echo a > /cgroups/1/devices.deny + echo a > /sys/fs/cgroup/1/devices.deny will remove the default 'a *:* rwm' entry. Doing - echo a > /cgroups/1/devices.allow + echo a > /sys/fs/cgroup/1/devices.allow will add the 'a *:* rwm' entry to the whitelist. diff --git a/Documentation/cgroups/freezer-subsystem.txt b/Documentation/cgroups/freezer-subsystem.txt index 41f37fea1276..c21d77742a07 100644 --- a/Documentation/cgroups/freezer-subsystem.txt +++ b/Documentation/cgroups/freezer-subsystem.txt @@ -59,28 +59,28 @@ is non-freezable. * Examples of usage : - # mkdir /containers - # mount -t cgroup -ofreezer freezer /containers - # mkdir /containers/0 - # echo $some_pid > /containers/0/tasks + # mkdir /sys/fs/cgroup/freezer + # mount -t cgroup -ofreezer freezer /sys/fs/cgroup/freezer + # mkdir /sys/fs/cgroup/freezer/0 + # echo $some_pid > /sys/fs/cgroup/freezer/0/tasks to get status of the freezer subsystem : - # cat /containers/0/freezer.state + # cat /sys/fs/cgroup/freezer/0/freezer.state THAWED to freeze all tasks in the container : - # echo FROZEN > /containers/0/freezer.state - # cat /containers/0/freezer.state + # echo FROZEN > /sys/fs/cgroup/freezer/0/freezer.state + # cat /sys/fs/cgroup/freezer/0/freezer.state FREEZING - # cat /containers/0/freezer.state + # cat /sys/fs/cgroup/freezer/0/freezer.state FROZEN to unfreeze all tasks in the container : - # echo THAWED > /containers/0/freezer.state - # cat /containers/0/freezer.state + # echo THAWED > /sys/fs/cgroup/freezer/0/freezer.state + # cat /sys/fs/cgroup/freezer/0/freezer.state THAWED This is the basic mechanism which should do the right thing for user space task diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 510d64570d60..ffec2416aa74 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -264,16 +264,17 @@ b. Enable CONFIG_RESOURCE_COUNTERS c. Enable CONFIG_CGROUP_MEM_RES_CTLR d. Enable CONFIG_CGROUP_MEM_RES_CTLR_SWAP (to use swap extension) -1. Prepare the cgroups -# mkdir -p /cgroups -# mount -t cgroup none /cgroups -o memory +1. Prepare the cgroups (see cgroups.txt, Why are cgroups needed?) +# mount -t tmpfs none /sys/fs/cgroup +# mkdir /sys/fs/cgroup/memory +# mount -t cgroup none /sys/fs/cgroup/memory -o memory 2. Make the new group and move bash into it -# mkdir /cgroups/0 -# echo $$ > /cgroups/0/tasks +# mkdir /sys/fs/cgroup/memory/0 +# echo $$ > /sys/fs/cgroup/memory/0/tasks Since now we're in the 0 cgroup, we can alter the memory limit: -# echo 4M > /cgroups/0/memory.limit_in_bytes +# echo 4M > /sys/fs/cgroup/memory/0/memory.limit_in_bytes NOTE: We can use a suffix (k, K, m, M, g or G) to indicate values in kilo, mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.) @@ -281,11 +282,11 @@ mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.) NOTE: We can write "-1" to reset the *.limit_in_bytes(unlimited). NOTE: We cannot set limits on the root cgroup any more. -# cat /cgroups/0/memory.limit_in_bytes +# cat /sys/fs/cgroup/memory/0/memory.limit_in_bytes 4194304 We can check the usage: -# cat /cgroups/0/memory.usage_in_bytes +# cat /sys/fs/cgroup/memory/0/memory.usage_in_bytes 1216512 A successful write to this file does not guarantee a successful set of diff --git a/Documentation/scheduler/sched-design-CFS.txt b/Documentation/scheduler/sched-design-CFS.txt index 99961993257a..91ecff07cede 100644 --- a/Documentation/scheduler/sched-design-CFS.txt +++ b/Documentation/scheduler/sched-design-CFS.txt @@ -223,9 +223,10 @@ When CONFIG_FAIR_GROUP_SCHED is defined, a "cpu.shares" file is created for each group created using the pseudo filesystem. See example steps below to create task groups and modify their CPU share using the "cgroups" pseudo filesystem. - # mkdir /dev/cpuctl - # mount -t cgroup -ocpu none /dev/cpuctl - # cd /dev/cpuctl + # mount -t tmpfs cgroup_root /sys/fs/cgroup + # mkdir /sys/fs/cgroup/cpu + # mount -t cgroup -ocpu none /sys/fs/cgroup/cpu + # cd /sys/fs/cgroup/cpu # mkdir multimedia # create "multimedia" group of tasks # mkdir browser # create "browser" group of tasks diff --git a/Documentation/scheduler/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt index 605b0d40329d..71b54d549987 100644 --- a/Documentation/scheduler/sched-rt-group.txt +++ b/Documentation/scheduler/sched-rt-group.txt @@ -129,9 +129,8 @@ priority! Enabling CONFIG_RT_GROUP_SCHED lets you explicitly allocate real CPU bandwidth to task groups. -This uses the /cgroup virtual file system and -"/cgroup//cpu.rt_runtime_us" to control the CPU time reserved for each -control group. +This uses the cgroup virtual file system and "/cpu.rt_runtime_us" +to control the CPU time reserved for each control group. For more information on working with control groups, you should read Documentation/cgroups/cgroups.txt as well. @@ -150,7 +149,7 @@ For now, this can be simplified to just the following (but see Future plans): =============== There is work in progress to make the scheduling period for each group -("/cgroup//cpu.rt_period_us") configurable as well. +("/cpu.rt_period_us") configurable as well. The constraint on the period is that a subgroup must have a smaller or equal period to its parent. But realistically its not very useful _yet_ diff --git a/Documentation/vm/hwpoison.txt b/Documentation/vm/hwpoison.txt index 12f9ba20ccb7..550068466605 100644 --- a/Documentation/vm/hwpoison.txt +++ b/Documentation/vm/hwpoison.txt @@ -129,12 +129,12 @@ Limit injection to pages owned by memgroup. Specified by inode number of the memcg. Example: - mkdir /cgroup/hwpoison + mkdir /sys/fs/cgroup/mem/hwpoison usemem -m 100 -s 1000 & - echo `jobs -p` > /cgroup/hwpoison/tasks + echo `jobs -p` > /sys/fs/cgroup/mem/hwpoison/tasks - memcg_ino=$(ls -id /cgroup/hwpoison | cut -f1 -d' ') + memcg_ino=$(ls -id /sys/fs/cgroup/mem/hwpoison | cut -f1 -d' ') echo $memcg_ino > /debug/hwpoison/corrupt-filter-memcg page-types -p `pidof init` --hwpoison # shall do nothing -- cgit v1.2.3 From 67de0162fbb78713fcb23cb2502b380faa8bde73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Sommer?= Date: Wed, 15 Jun 2011 13:00:47 -0700 Subject: Documentation: fix cgroup typos and formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix format and spelling. Signed-off-by: Jörg Sommer Acked-by: Paul Menage Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/cgroups/blkio-controller.txt | 2 +- Documentation/cgroups/cgroups.txt | 2 +- Documentation/cgroups/memory.txt | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index b1b1bfadc9c0..cd45c8ea7463 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt @@ -111,7 +111,7 @@ Hierarchical Cgroups CFQ and throttling will practically treat all groups at same level. pivot - / | \ \ + / / \ \ root test1 test2 test3 Down the line we can implement hierarchical accounting/control support diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt index 15bca101ff62..cd67e90003c0 100644 --- a/Documentation/cgroups/cgroups.txt +++ b/Documentation/cgroups/cgroups.txt @@ -142,7 +142,7 @@ and depending on who is launching the browser he can With only a single hierarchy, he now would potentially have to create a separate cgroup for every browser launched and associate it with -approp network and other resource class. This may lead to +appropriate network and other resource class. This may lead to proliferation of such cgroups. Also lets say that the administrator would like to give enhanced network diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index ffec2416aa74..06eb6d957c83 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -1,8 +1,8 @@ Memory Resource Controller -NOTE: The Memory Resource Controller has been generically been referred - to as the memory controller in this document. Do not confuse memory - controller used here with the memory controller that is used in hardware. +NOTE: The Memory Resource Controller has generically been referred to as the + memory controller in this document. Do not confuse memory controller + used here with the memory controller that is used in hardware. (For editors) In this document: @@ -182,7 +182,7 @@ behind this approach is that a cgroup that aggressively uses a shared page will eventually get charged for it (once it is uncharged from the cgroup that brought it in -- this will happen on memory pressure). -Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used.. +Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used. When you do swapoff and make swapped-out pages of shmem(tmpfs) to be backed into memory in force, charges for pages are accounted against the caller of swapoff rather than the users of shmem. @@ -214,7 +214,7 @@ affecting global LRU, memory+swap limit is better than just limiting swap from OS point of view. * What happens when a cgroup hits memory.memsw.limit_in_bytes -When a cgroup his memory.memsw.limit_in_bytes, it's useless to do swap-out +When a cgroup hits memory.memsw.limit_in_bytes, it's useless to do swap-out in this cgroup. Then, swap-out will not be done by cgroup routine and file caches are dropped. But as mentioned above, global LRU can do swapout memory from it for sanity of the system's memory management state. You can't forbid @@ -491,13 +491,13 @@ The hierarchy is created by creating the appropriate cgroups in the cgroup filesystem. Consider for example, the following cgroup filesystem hierarchy - root + root / | \ - / | \ - a b c - | \ - | \ - d e + / | \ + a b c + | \ + | \ + d e In the diagram above, with hierarchical accounting enabled, all memory usage of e, is accounted to its ancestors up until the root (i.e, c and root), -- cgit v1.2.3 From 13fca640bb8ab611a50e0ba120b186faa2994d6c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 15 Jun 2011 21:53:52 -0700 Subject: Revert "fs/exec.c: use BUILD_BUG_ON for VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP" This reverts commit 7f81c8890c15a10f5220bebae3b6dfae4961962a. It turns out that it's not actually a build-time check on x86-64 UML, which does some seriously crazy stuff with VM_STACK_FLAGS. The VM_STACK_FLAGS define depends on the arch-supplied VM_STACK_DEFAULT_FLAGS value, and on x86-64 UML we have arch/um/sys-x86_64/shared/sysdep/vm-flags.h: #define VM_STACK_DEFAULT_FLAGS \ (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) #define VM_STACK_DEFAULT_FLAGS vm_stack_flags (yes, seriously: two different #define's for that thing, with the first one being inside an "#ifdef TIF_IA32") It's possible that it is UML that should just be fixed in this area, but for now let's just undo the (very small) optimization. Reported-by: Randy Dunlap Acked-by: Andrew Morton Cc: Michal Hocko Cc: Richard Weinberger Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exec.c b/fs/exec.c index b54f74f3cd80..97e0d52d72fd 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -277,7 +277,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm) * use STACK_TOP because that can depend on attributes which aren't * configured yet. */ - BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); + BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); vma->vm_end = STACK_TOP_MAX; vma->vm_start = vma->vm_end - PAGE_SIZE; vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; -- cgit v1.2.3 From fb2e73947461d55a3166f94a8a545b78d6635262 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 15 Jun 2011 06:08:18 +0000 Subject: sh: ecovec: Add renesas_usbhs support Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/boards/mach-ecovec24/setup.c | 48 ++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 3a32741cc0ac..513cb1a2e6c8 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -232,6 +233,52 @@ static struct platform_device usb1_common_device = { .resource = usb1_common_resources, }; +/* + * USBHS + */ +static int usbhs_get_id(struct platform_device *pdev) +{ + return gpio_get_value(GPIO_PTB3); +} + +static struct renesas_usbhs_platform_info usbhs_info = { + .platform_callback = { + .get_id = usbhs_get_id, + }, + .driver_param = { + .buswait_bwait = 4, + .detection_delay = 5, + }, +}; + +static struct resource usbhs_resources[] = { + [0] = { + .start = 0xa4d90000, + .end = 0xa4d90124 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 66, + .end = 66, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usbhs_device = { + .name = "renesas_usbhs", + .id = 1, + .dev = { + .dma_mask = NULL, /* not use dma */ + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbhs_info, + }, + .num_resources = ARRAY_SIZE(usbhs_resources), + .resource = usbhs_resources, + .archdata = { + .hwblk_id = HWBLK_USB1, + }, +}; + /* LCDC */ const static struct fb_videomode ecovec_lcd_modes[] = { { @@ -897,6 +944,7 @@ static struct platform_device *ecovec_devices[] __initdata = { &sh_eth_device, &usb0_host_device, &usb1_common_device, + &usbhs_device, &lcdc_device, &ceu0_device, &ceu1_device, -- cgit v1.2.3 From 261a9af671a79b750cb170bac620601d686535c1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 15 Jun 2011 06:08:28 +0000 Subject: sh: sh7724: Add USBHS DMAEngine support Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/include/cpu-sh4/cpu/sh7724.h | 8 +++++++ arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h index 3daef8ecbc63..cbc47e6bcab5 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7724.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h @@ -298,6 +298,14 @@ enum { SHDMA_SLAVE_SCIF4_RX, SHDMA_SLAVE_SCIF5_TX, SHDMA_SLAVE_SCIF5_RX, + SHDMA_SLAVE_USB0D0_TX, + SHDMA_SLAVE_USB0D0_RX, + SHDMA_SLAVE_USB0D1_TX, + SHDMA_SLAVE_USB0D1_RX, + SHDMA_SLAVE_USB1D0_TX, + SHDMA_SLAVE_USB1D0_RX, + SHDMA_SLAVE_USB1D1_TX, + SHDMA_SLAVE_USB1D1_RX, SHDMA_SLAVE_SDHI0_TX, SHDMA_SLAVE_SDHI0_RX, SHDMA_SLAVE_SDHI1_TX, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index 0333fe9e3881..134a397b1918 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -92,6 +92,46 @@ static const struct sh_dmae_slave_config sh7724_dmae_slaves[] = { .addr = 0xa4e50024, .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x36, + }, { + .slave_id = SHDMA_SLAVE_USB0D0_TX, + .addr = 0xA4D80100, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0x73, + }, { + .slave_id = SHDMA_SLAVE_USB0D0_RX, + .addr = 0xA4D80100, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0x73, + }, { + .slave_id = SHDMA_SLAVE_USB0D1_TX, + .addr = 0xA4D80120, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0x77, + }, { + .slave_id = SHDMA_SLAVE_USB0D1_RX, + .addr = 0xA4D80120, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0x77, + }, { + .slave_id = SHDMA_SLAVE_USB1D0_TX, + .addr = 0xA4D90100, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xab, + }, { + .slave_id = SHDMA_SLAVE_USB1D0_RX, + .addr = 0xA4D90100, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xab, + }, { + .slave_id = SHDMA_SLAVE_USB1D1_TX, + .addr = 0xA4D90120, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xaf, + }, { + .slave_id = SHDMA_SLAVE_USB1D1_RX, + .addr = 0xA4D90120, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xaf, }, { .slave_id = SHDMA_SLAVE_SDHI0_TX, .addr = 0x04ce0030, -- cgit v1.2.3 From a46e0899eec7a3069bcadd45dfba7bf67c6ed016 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 15 Jun 2011 15:47:09 -0700 Subject: rcu: use softirq instead of kthreads except when RCU_BOOST=y This patch #ifdefs RCU kthreads out of the kernel unless RCU_BOOST=y, thus eliminating context-switch overhead if RCU priority boosting has not been configured. Signed-off-by: Paul E. McKenney --- kernel/rcutree.c | 59 ++++++++++++++++++++++++++++++++++++------------- kernel/rcutree.h | 8 +++++-- kernel/rcutree_plugin.h | 41 +++++++++++++++++++++------------- kernel/rcutree_trace.c | 32 +++++++++++++++++++-------- 4 files changed, 99 insertions(+), 41 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index ae5c9ea68662..429d4949f0eb 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -87,6 +87,8 @@ static struct rcu_state *rcu_state; int rcu_scheduler_active __read_mostly; EXPORT_SYMBOL_GPL(rcu_scheduler_active); +#ifdef CONFIG_RCU_BOOST + /* * Control variables for per-CPU and per-rcu_node kthreads. These * handle all flavors of RCU. @@ -98,9 +100,11 @@ DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); DEFINE_PER_CPU(char, rcu_cpu_has_work); static char rcu_kthreads_spawnable; +#endif /* #ifdef CONFIG_RCU_BOOST */ + static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu); -static void invoke_rcu_cpu_kthread(void); -static void __invoke_rcu_cpu_kthread(void); +static void invoke_rcu_core(void); +static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp); #define RCU_KTHREAD_PRIO 1 /* RT priority for per-CPU kthreads. */ @@ -1089,6 +1093,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) int need_report = 0; struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu); struct rcu_node *rnp; +#ifdef CONFIG_RCU_BOOST struct task_struct *t; /* Stop the CPU's kthread. */ @@ -1097,6 +1102,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) per_cpu(rcu_cpu_kthread_task, cpu) = NULL; kthread_stop(t); } +#endif /* #ifdef CONFIG_RCU_BOOST */ /* Exclude any attempts to start a new grace period. */ raw_spin_lock_irqsave(&rsp->onofflock, flags); @@ -1232,7 +1238,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) /* Re-raise the RCU softirq if there are callbacks remaining. */ if (cpu_has_callbacks_ready_to_invoke(rdp)) - invoke_rcu_cpu_kthread(); + invoke_rcu_core(); } /* @@ -1278,7 +1284,7 @@ void rcu_check_callbacks(int cpu, int user) } rcu_preempt_check_callbacks(cpu); if (rcu_pending(cpu)) - invoke_rcu_cpu_kthread(); + invoke_rcu_core(); } #ifdef CONFIG_SMP @@ -1444,9 +1450,11 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) /* If there are callbacks ready, invoke them. */ if (cpu_has_callbacks_ready_to_invoke(rdp)) - __invoke_rcu_cpu_kthread(); + invoke_rcu_callbacks(rsp, rdp); } +#ifdef CONFIG_RCU_BOOST + static void rcu_kthread_do_work(void) { rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); @@ -1454,6 +1462,8 @@ static void rcu_kthread_do_work(void) rcu_preempt_do_callbacks(); } +#endif /* #ifdef CONFIG_RCU_BOOST */ + /* * Do softirq processing for the current CPU. */ @@ -1474,25 +1484,22 @@ static void rcu_process_callbacks(struct softirq_action *unused) * the current CPU with interrupts disabled, the rcu_cpu_kthread_task * cannot disappear out from under us. */ -static void __invoke_rcu_cpu_kthread(void) +static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) { - unsigned long flags; - - local_irq_save(flags); - __this_cpu_write(rcu_cpu_has_work, 1); - if (__this_cpu_read(rcu_cpu_kthread_task) == NULL) { - local_irq_restore(flags); + if (likely(!rsp->boost)) { + rcu_do_batch(rsp, rdp); return; } - wake_up_process(__this_cpu_read(rcu_cpu_kthread_task)); - local_irq_restore(flags); + invoke_rcu_callbacks_kthread(); } -static void invoke_rcu_cpu_kthread(void) +static void invoke_rcu_core(void) { raise_softirq(RCU_SOFTIRQ); } +#ifdef CONFIG_RCU_BOOST + /* * Wake up the specified per-rcu_node-structure kthread. * Because the per-rcu_node kthreads are immortal, we don't need @@ -1818,6 +1825,18 @@ static int __init rcu_spawn_kthreads(void) } early_initcall(rcu_spawn_kthreads); +#else /* #ifdef CONFIG_RCU_BOOST */ + +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +{ +} + +static void rcu_cpu_kthread_setrt(int cpu, int to_rt) +{ +} + +#endif /* #else #ifdef CONFIG_RCU_BOOST */ + static void __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), struct rcu_state *rsp) @@ -2224,6 +2243,8 @@ static void __cpuinit rcu_prepare_cpu(int cpu) rcu_preempt_init_percpu_data(cpu); } +#ifdef CONFIG_RCU_BOOST + static void __cpuinit rcu_prepare_kthreads(int cpu) { struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); @@ -2237,6 +2258,14 @@ static void __cpuinit rcu_prepare_kthreads(int cpu) } } +#else /* #ifdef CONFIG_RCU_BOOST */ + +static void __cpuinit rcu_prepare_kthreads(int cpu) +{ +} + +#endif /* #else #ifdef CONFIG_RCU_BOOST */ + /* * Handle CPU online/offline notification events. */ diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 0fed6b934d2a..434288c7ad88 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -369,6 +369,7 @@ struct rcu_state { /* period because */ /* force_quiescent_state() */ /* was running. */ + u8 boost; /* Subject to priority boost. */ unsigned long gpnum; /* Current gp number. */ unsigned long completed; /* # of last completed gp. */ @@ -439,7 +440,6 @@ static void rcu_preempt_offline_cpu(int cpu); #endif /* #ifdef CONFIG_HOTPLUG_CPU */ static void rcu_preempt_check_callbacks(int cpu); static void rcu_preempt_process_callbacks(void); -static void rcu_preempt_do_callbacks(void); void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp); @@ -451,11 +451,15 @@ static void rcu_preempt_send_cbs_to_online(void); static void __init __rcu_init_preempt(void); static void rcu_needs_cpu_flush(void); static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); +static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); +static void invoke_rcu_callbacks_kthread(void); +#ifdef CONFIG_RCU_BOOST +static void rcu_preempt_do_callbacks(void); static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, cpumask_var_t cm); -static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp, int rnp_index); +#endif /* #ifdef CONFIG_RCU_BOOST */ #endif /* #ifndef RCU_TREE_NONCORE */ diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 38d09c5f2b41..2772386c0421 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -602,11 +602,15 @@ static void rcu_preempt_process_callbacks(void) &__get_cpu_var(rcu_preempt_data)); } +#ifdef CONFIG_RCU_BOOST + static void rcu_preempt_do_callbacks(void) { rcu_do_batch(&rcu_preempt_state, &__get_cpu_var(rcu_preempt_data)); } +#endif /* #ifdef CONFIG_RCU_BOOST */ + /* * Queue a preemptible-RCU callback for invocation after a grace period. */ @@ -1002,10 +1006,6 @@ static void rcu_preempt_process_callbacks(void) { } -static void rcu_preempt_do_callbacks(void) -{ -} - /* * Wait for an rcu-preempt grace period, but make it happen quickly. * But because preemptible RCU does not exist, map to rcu-sched. @@ -1257,6 +1257,23 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) } } +/* + * Wake up the per-CPU kthread to invoke RCU callbacks. + */ +static void invoke_rcu_callbacks_kthread(void) +{ + unsigned long flags; + + local_irq_save(flags); + __this_cpu_write(rcu_cpu_has_work, 1); + if (__this_cpu_read(rcu_cpu_kthread_task) == NULL) { + local_irq_restore(flags); + return; + } + wake_up_process(__this_cpu_read(rcu_cpu_kthread_task)); + local_irq_restore(flags); +} + /* * Set the affinity of the boost kthread. The CPU-hotplug locks are * held, so no one should be messing with the existence of the boost @@ -1297,6 +1314,7 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, if (&rcu_preempt_state != rsp) return 0; + rsp->boost = 1; if (rnp->boost_kthread_task != NULL) return 0; t = kthread_create(rcu_boost_kthread, (void *)rnp, @@ -1319,22 +1337,15 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) raw_spin_unlock_irqrestore(&rnp->lock, flags); } -static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, - cpumask_var_t cm) +static void invoke_rcu_callbacks_kthread(void) { + WARN_ON_ONCE(1); } static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) { } -static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, - struct rcu_node *rnp, - int rnp_index) -{ - return 0; -} - #endif /* #else #ifdef CONFIG_RCU_BOOST */ #ifndef CONFIG_SMP @@ -1509,7 +1520,7 @@ static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff); * * Because it is not legal to invoke rcu_process_callbacks() with irqs * disabled, we do one pass of force_quiescent_state(), then do a - * invoke_rcu_cpu_kthread() to cause rcu_process_callbacks() to be invoked + * invoke_rcu_core() to cause rcu_process_callbacks() to be invoked * later. The per-cpu rcu_dyntick_drain variable controls the sequencing. */ int rcu_needs_cpu(int cpu) @@ -1560,7 +1571,7 @@ int rcu_needs_cpu(int cpu) /* If RCU callbacks are still pending, RCU still needs this CPU. */ if (c) - invoke_rcu_cpu_kthread(); + invoke_rcu_core(); return c; } diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c index 9678cc3650f5..4e144876dc68 100644 --- a/kernel/rcutree_trace.c +++ b/kernel/rcutree_trace.c @@ -46,6 +46,8 @@ #define RCU_TREE_NONCORE #include "rcutree.h" +#ifdef CONFIG_RCU_BOOST + DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status); DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_cpu); DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); @@ -58,6 +60,8 @@ static char convert_kthread_status(unsigned int kthread_status) return "SRWOY"[kthread_status]; } +#endif /* #ifdef CONFIG_RCU_BOOST */ + static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) { if (!rdp->beenonline) @@ -76,7 +80,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs); #endif /* #ifdef CONFIG_NO_HZ */ seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d ktl=%x b=%ld", + seq_printf(m, " ql=%ld qs=%c%c%c%c", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]], @@ -84,13 +88,16 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->nxttail[RCU_NEXT_READY_TAIL]], ".W"[rdp->nxttail[RCU_DONE_TAIL] != rdp->nxttail[RCU_WAIT_TAIL]], - ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]], + ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]); +#ifdef CONFIG_RCU_BOOST + seq_printf(m, " kt=%d/%c/%d ktl=%x", per_cpu(rcu_cpu_has_work, rdp->cpu), convert_kthread_status(per_cpu(rcu_cpu_kthread_status, rdp->cpu)), per_cpu(rcu_cpu_kthread_cpu, rdp->cpu), - per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff, - rdp->blimit); + per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff); +#endif /* #ifdef CONFIG_RCU_BOOST */ + seq_printf(m, " b=%ld", rdp->blimit); seq_printf(m, " ci=%lu co=%lu ca=%lu\n", rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); } @@ -147,18 +154,21 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs); #endif /* #ifdef CONFIG_NO_HZ */ seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, ",%ld,\"%c%c%c%c\",%d,\"%c\",%ld", rdp->qlen, + seq_printf(m, ",%ld,\"%c%c%c%c\"", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]], ".R"[rdp->nxttail[RCU_WAIT_TAIL] != rdp->nxttail[RCU_NEXT_READY_TAIL]], ".W"[rdp->nxttail[RCU_DONE_TAIL] != rdp->nxttail[RCU_WAIT_TAIL]], - ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]], + ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]); +#ifdef CONFIG_RCU_BOOST + seq_printf(m, ",%d,\"%c\"", per_cpu(rcu_cpu_has_work, rdp->cpu), convert_kthread_status(per_cpu(rcu_cpu_kthread_status, - rdp->cpu)), - rdp->blimit); + rdp->cpu))); +#endif /* #ifdef CONFIG_RCU_BOOST */ + seq_printf(m, ",%ld", rdp->blimit); seq_printf(m, ",%lu,%lu,%lu\n", rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); } @@ -169,7 +179,11 @@ static int show_rcudata_csv(struct seq_file *m, void *unused) #ifdef CONFIG_NO_HZ seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\","); #endif /* #ifdef CONFIG_NO_HZ */ - seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\",\"ci\",\"co\",\"ca\"\n"); + seq_puts(m, "\"of\",\"ri\",\"ql\",\"qs\""); +#ifdef CONFIG_RCU_BOOST + seq_puts(m, "\"kt\",\"ktl\""); +#endif /* #ifdef CONFIG_RCU_BOOST */ + seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n"); #ifdef CONFIG_TREE_PREEMPT_RCU seq_puts(m, "\"rcu_preempt:\"\n"); PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data_csv, m); -- cgit v1.2.3 From 45e97ab65026a3391cb2c938f834ca5db4d2e5b3 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 15 Jun 2011 11:26:47 +0200 Subject: drm: populate irq_by_busid-member for pci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 8410ea (drm: rework PCI/platform driver interface) implemented drm_pci_irq_by_busid() but forgot to make it available in the drm_pci_bus-struct. This caused a freeze on my Radeon9600-equipped laptop when executing glxgears. Thanks to Michel for noticing the flaw. [airlied: made function static also] Reported-by: Michel Dänzer Signed-off-by: Wolfram Sang Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index e1aee4f6a7c6..b6a19cb07caf 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -251,7 +251,7 @@ err: } -int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) +static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) { if ((p->busnum >> 8) != drm_get_pci_domain(dev) || (p->busnum & 0xff) != dev->pdev->bus->number || @@ -292,6 +292,7 @@ static struct drm_bus drm_pci_bus = { .get_name = drm_pci_get_name, .set_busid = drm_pci_set_busid, .set_unique = drm_pci_set_unique, + .irq_by_busid = drm_pci_irq_by_busid, .agp_init = drm_pci_agp_init, }; -- cgit v1.2.3 From 1c88d74f3a0b748b0c7e88e91e9d0503815d5689 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 14 Jun 2011 19:15:53 +0000 Subject: drm/radeon/kms: signed fix for evergreen thermal temperature is signed. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 86157b172c88..7e3d96e7ac04 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* get temperature in millidegrees */ int evergreen_get_temp(struct radeon_device *rdev) { - u32 temp, toffset, actual_temp = 0; + u32 temp, toffset; + int actual_temp = 0; if (rdev->family == CHIP_JUNIPER) { toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> -- cgit v1.2.3 From 7c88d2b80ba5c175398013842782461a3b980130 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 14 Jun 2011 15:27:38 +0000 Subject: drm/radeon/kms: be more pedantic about the g5 quirk (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I don't think Apple offered any other cards for this mac, so I doubt this will be an issue, but just to be on the safe side, check the pci ids as well. v2: fix spelling in commit message Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher Cc: Joachim Henke Cc: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 797c8bcbb6a4..e4594676a07c 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1553,9 +1553,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) (rdev->pdev->subsystem_device == 0x4a48)) { /* Mac X800 */ rdev->mode_info.connector_table = CT_MAC_X800; - } else if (of_machine_is_compatible("PowerMac7,2") || - of_machine_is_compatible("PowerMac7,3")) { - /* Mac G5 9600 */ + } else if ((of_machine_is_compatible("PowerMac7,2") || + of_machine_is_compatible("PowerMac7,3")) && + (rdev->pdev->device == 0x4150) && + (rdev->pdev->subsystem_vendor == 0x1002) && + (rdev->pdev->subsystem_device == 0x4150)) { + /* Mac G5 tower 9600 */ rdev->mode_info.connector_table = CT_MAC_G5_9600; } else #endif /* CONFIG_PPC_PMAC */ -- cgit v1.2.3 From e6ba759980e65084b0db9f1684d9d65a2a3e1741 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 22:02:51 +0000 Subject: drm/radeon/kms: clear wb memory by default Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e680501c78ea..7cfaa7e2f3b5 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -215,6 +215,8 @@ int radeon_wb_init(struct radeon_device *rdev) return r; } + /* clear wb memory */ + memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE); /* disable event_write fences */ rdev->wb.use_event = false; /* disabled via module param */ -- cgit v1.2.3 From f49dadb82dde88092827b6d058e7164e75e96759 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 14 Jun 2011 06:13:54 +0000 Subject: drm: make debug levels match in edid failure code. this puts the header and followup at the same loglevel as the hex dump code. Signed-off-by: Dave Airlie Reviewed-by: Alex Deucher --- drivers/gpu/drm/drm_edid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0a9357c66ff8..3618d29c79a2 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -184,9 +184,9 @@ drm_edid_block_valid(u8 *raw_edid) bad: if (raw_edid) { - DRM_ERROR("Raw EDID:\n"); + printk(KERN_ERR "Raw EDID:\n"); print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); - printk("\n"); + printk(KERN_ERR "\n"); } return 0; } -- cgit v1.2.3 From 4a9a8b71e12d41abb71c4e741bff524f016cfef4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 14 Jun 2011 06:13:55 +0000 Subject: drm/radeon: workaround a hw bug on some radeon chipsets with all-0 EDIDs. Some RS690 chipsets seem to end up with floating connectors, either a DVI connector isn't actually populated, or an add-in HDMI card is available but not installed. In this case we seem to get a NULL byte response for each byte of the i2c transaction, so we detect this case and if we see it we don't do anymore DDC transactions on this connector. I've tested this on my RS690 without the HDMI card installed and it seems to work fine. Signed-off-by: Dave Airlie Reviewed-by: Alex Deucher --- drivers/gpu/drm/drm_edid.c | 15 +++++++++++++++ drivers/gpu/drm/radeon/radeon_connectors.c | 7 +++++++ include/drm/drm_crtc.h | 2 ++ 3 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3618d29c79a2..09292193dafe 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, return ret == 2 ? 0 : -1; } +static bool drm_edid_is_zero(u8 *in_edid, int length) +{ + int i; + u32 *raw_edid = (u32 *)in_edid; + + for (i = 0; i < length / 4; i++) + if (*(raw_edid + i) != 0) + return false; + return true; +} + static u8 * drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) { @@ -273,6 +284,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) goto out; if (drm_edid_block_valid(block)) break; + if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { + connector->null_edid_counter++; + goto carp; + } } if (i == 4) goto carp; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 9c2929c7e79f..c04e18ee8a87 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -836,6 +836,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", drm_get_connector_name(connector)); + /* rs690 seems to have a problem with connectors not existing and always + * return a block of 0's. If we see this just stop polling on this output */ + if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) { + ret = connector_status_disconnected; + DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); + radeon_connector->ddc_bus = NULL; + } } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 9573e0ce3120..33d12f87f0e0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -520,6 +520,8 @@ struct drm_connector { uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; uint32_t force_encoder_id; struct drm_encoder *encoder; /* currently active encoder */ + + int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ }; /** -- cgit v1.2.3 From cafe8d8413399119c3f4cd575e0eb27e2654b9d5 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Sat, 4 Jun 2011 15:36:43 +0000 Subject: drivers/gpu/drm: use printk_ratelimited instead of printk_ratelimit Since printk_ratelimit() shouldn't be used anymore (see comment in include/linux/printk.h), replace it with printk_ratelimited. Signed-off-by: Christian Dietrich Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_ioc32.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index d61d185cf040..4a058c7af6c0 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -28,6 +28,7 @@ * IN THE SOFTWARE. */ #include +#include #include "drmP.h" #include "drm_core.h" @@ -253,10 +254,10 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd, return -EFAULT; m32.handle = (unsigned long)handle; - if (m32.handle != (unsigned long)handle && printk_ratelimit()) - printk(KERN_ERR "compat_drm_addmap truncated handle" - " %p for type %d offset %x\n", - handle, m32.type, m32.offset); + if (m32.handle != (unsigned long)handle) + printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle" + " %p for type %d offset %x\n", + handle, m32.type, m32.offset); if (copy_to_user(argp, &m32, sizeof(m32))) return -EFAULT; -- cgit v1.2.3 From 9be34c9d526c305efb332ad53460b57d5f8edb3e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 16 Jun 2011 00:35:09 -0700 Subject: mm: get rid of the most spurious find_vma_prev() users We have some users of this function that date back to before the vma list was doubly linked, and just are silly. These days, you can find the previous vma by just following the vma->vm_prev pointer. In some cases you don't need any find_vma() lookup at all, and in other cases you're better off with the regular "find_vma()" that uses the vma cache front-end lookup. Some "find_vma_prev()" users are still valid, though. For example, in the case of a stack that grows up, it can be the case that we don't find any 'vma' at all (because we're looking up an address that is past the last vma), and that the stack that we want to grow is the 'prev' vma. But that kind of special case aside, we generally should prefer to use 'find_vma()'. Noticed due to a totally unrelated POWER memory corruption bug that just happened to hit in 'find_vma_prev()' and made me go "Hmm - why are we using that function here?". Signed-off-by: Linus Torvalds --- mm/mmap.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index bbdc9af5e117..d49736ff8a8d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -906,14 +906,7 @@ struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *vma) if (anon_vma) return anon_vma; try_prev: - /* - * It is potentially slow to have to call find_vma_prev here. - * But it's only on the first write fault on the vma, not - * every time, and we could devise a way to avoid it later - * (e.g. stash info in next's anon_vma_node when assigning - * an anon_vma, or when trying vma_merge). Another time. - */ - BUG_ON(find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma); + near = vma->vm_prev; if (!near) goto none; @@ -2044,9 +2037,10 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) return -EINVAL; /* Find the first overlapping VMA */ - vma = find_vma_prev(mm, start, &prev); + vma = find_vma(mm, start); if (!vma) return 0; + prev = vma->vm_prev; /* we have start < vma->vm_end */ /* if it doesn't overlap, we have nothing.. */ -- cgit v1.2.3 From 203db2952bc87f5d610c9ad53a7d02b85897721f Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Jun 2011 23:03:38 +0200 Subject: tools/perf: Fix static build of perf tool To build a statically linked version of the perf tool all needed libraries must be added in the correct order to get the symbols resolved. Currently this is broken when, e.g. python or newt support is enabled -- libpython needs libpthread which is an unconditional link dependency of the perf tool; libslang needs libm, another unconditional dependency. To solve the problem in the long run without the need to keep track of transitive library dependencies, simply make the linker look at the EXTLIBS multiple times until it has all symbols resolved. Signed-off-by: Mathias Krause Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/1308171818-20370-1-git-send-email-minipli@googlemail.com Signed-off-by: Ingo Molnar --- tools/perf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 032ba6398a5c..940257b5774e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -633,7 +633,7 @@ prefix_SQ = $(subst ','\'',$(prefix)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) -LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS) +LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group ALL_CFLAGS += $(BASIC_CFLAGS) ALL_CFLAGS += $(ARCH_CFLAGS) -- cgit v1.2.3 From c3a4924565e2eecf2539871abd123d35be6d76d5 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 16 Jun 2011 12:21:34 +0200 Subject: Revert "HID: magicmouse: ignore 'ivalid report id' while switching modes" This reverts commit 23746a66d7d9e73402c68ef00d708796b97ebd72. It turned out that the actual reason for failure is not the device firmware, but bug in Bluetooth stack, which will be fixed by patch by Ville Tervo which corrects the mask handling for CSR 1.1 Dongles. Reported-and-tested-by: Ed Tomlinson Reported-and-tested-by: Chase Douglas Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index a5eda4c8127a..0ec91c18a421 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -501,17 +501,9 @@ static int magicmouse_probe(struct hid_device *hdev, } report->size = 6; - /* - * The device reponds with 'invalid report id' when feature - * report switching it into multitouch mode is sent to it. - * - * This results in -EIO from the _raw low-level transport callback, - * but there seems to be no other way of switching the mode. - * Thus the super-ugly hacky success check below. - */ ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), HID_FEATURE_REPORT); - if (ret != -EIO) { + if (ret != sizeof(feature)) { hid_err(hdev, "unable to request touch data (%d)\n", ret); goto err_stop_hw; } -- cgit v1.2.3 From 55b220cafadd71b9f83759f7b396998b2547dc5f Mon Sep 17 00:00:00 2001 From: Ambresh K Date: Wed, 15 Jun 2011 13:40:45 -0700 Subject: gpio/omap4: Fix missing interrupts during device wakeup due to IOPAD. If gpio pins from bank[2-5] are marked as wakeup enable and if the wake is through gpio IO pad wakeup, then that wakeup gpio interrupt is lost. In the current implementation, GPIO driver stores the context of DATAIN of all the gpio in the bank. During GPIO resuming, it checks DATAIN with wakeup enabled pins of gpio bank. If there is status change, then manually toggle GPIO_LEVELDETECT to generate pseudo interrupt. Reported-by: Philippe Mazet Tested-by: Philippe Mazet Signed-off-by: Ambresh K Signed-off-by: Grant Likely --- drivers/gpio/gpio-omap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 01f74a8459d9..35bebde23e83 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -469,8 +469,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, + OMAP24XX_GPIO_CLEARWKUENA); } } - /* This part needs to be executed always for OMAP34xx */ - if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) { + /* This part needs to be executed always for OMAP{34xx, 44xx} */ + if (cpu_is_omap34xx() || cpu_is_omap44xx() || + (bank->non_wakeup_gpios & gpio_bit)) { /* * Log the edge gpio and manually trigger the IRQ * after resume if the input level changes -- cgit v1.2.3 From 158f1e95180d01ebfd7cd5c8de23050528303f26 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 17:06:02 -0700 Subject: gpio: include linux/gpio.h where needed Some files use GPIOF_ macros but don't include the header file for them. These macros are being moved to , so add includes for where needed. Signed-off-by: Randy Dunlap Signed-off-by: Grant Likely --- arch/arm/mach-pxa/spitz_pm.c | 1 + drivers/pcmcia/pxa2xx_vpac270.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 7fe74067d85f..094279aefe9c 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c index 435002dfc3ca..712baab3c83d 100644 --- a/drivers/pcmcia/pxa2xx_vpac270.c +++ b/drivers/pcmcia/pxa2xx_vpac270.c @@ -11,6 +11,7 @@ * */ +#include #include #include -- cgit v1.2.3 From c001fb72a7b705f902bdfdd05b5d2408efe6f848 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 17:05:11 -0700 Subject: gpio: add GPIOF_ values regardless on kconfig settings Make GPIOF_ defined values available even when GPIOLIB nor GENERIC_GPIO is enabled by moving them to . Fixes these build errors in linux-next: sound/soc/codecs/ak4641.c:524: error: 'GPIOF_OUT_INIT_LOW' undeclared (first use in this function) sound/soc/codecs/wm8915.c:2921: error: 'GPIOF_OUT_INIT_LOW' undeclared (first use in this function) Signed-off-by: Randy Dunlap Signed-off-by: Grant Likely --- include/asm-generic/gpio.h | 10 ---------- include/linux/gpio.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index fcdcb5d5c995..d494001b1226 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -170,16 +170,6 @@ extern int __gpio_cansleep(unsigned gpio); extern int __gpio_to_irq(unsigned gpio); -#define GPIOF_DIR_OUT (0 << 0) -#define GPIOF_DIR_IN (1 << 0) - -#define GPIOF_INIT_LOW (0 << 1) -#define GPIOF_INIT_HIGH (1 << 1) - -#define GPIOF_IN (GPIOF_DIR_IN) -#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) -#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) - /** * struct gpio - a structure describing a GPIO with configuration * @gpio: the GPIO number diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 32d47e710661..17b5a0d80e42 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -3,6 +3,17 @@ /* see Documentation/gpio.txt */ +/* make these flag values available regardless of GPIO kconfig options */ +#define GPIOF_DIR_OUT (0 << 0) +#define GPIOF_DIR_IN (1 << 0) + +#define GPIOF_INIT_LOW (0 << 1) +#define GPIOF_INIT_HIGH (1 << 1) + +#define GPIOF_IN (GPIOF_DIR_IN) +#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) +#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) + #ifdef CONFIG_GENERIC_GPIO #include -- cgit v1.2.3 From 63f6fe92c6b3cbf4c0bbbea4b31fdd3d68e21e4d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 16 Jun 2011 17:16:37 +0200 Subject: netfilter: ip_tables: fix compile with debug Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 764743843503..24e556e83a3b 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -566,7 +566,7 @@ check_entry(const struct ipt_entry *e, const char *name) const struct xt_entry_target *t; if (!ip_checkentry(&e->ip)) { - duprintf("ip check failed %p %s.\n", e, par->match->name); + duprintf("ip check failed %p %s.\n", e, name); return -EINVAL; } -- cgit v1.2.3 From 58d5a0257d2fd89fbe4451f704193cc95b0a9c97 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jun 2011 17:24:17 +0200 Subject: netfilter: ipt_ecn: fix protocol check in ecn_mt_check() Check for protocol inversion in ecn_mt_check() and remove the unnecessary runtime check for IPPROTO_TCP in ecn_mt(). Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ipt_ecn.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index af6e9c778345..aaa85be1b2d8 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c @@ -76,8 +76,6 @@ static bool ecn_mt(const struct sk_buff *skb, struct xt_action_param *par) return false; if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { - if (ip_hdr(skb)->protocol != IPPROTO_TCP) - return false; if (!match_tcp(skb, info, &par->hotdrop)) return false; } @@ -97,7 +95,7 @@ static int ecn_mt_check(const struct xt_mtchk_param *par) return -EINVAL; if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && - ip->proto != IPPROTO_TCP) { + (ip->proto != IPPROTO_TCP || ip->invflags & IPT_INV_PROTO)) { pr_info("cannot match TCP bits in rule for non-tcp packets\n"); return -EINVAL; } -- cgit v1.2.3 From db898aa2ef6529fa80891e754d353063611c77de Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jun 2011 17:24:55 +0200 Subject: netfilter: ipt_ecn: fix inversion for IP header ECN match Userspace allows to specify inversion for IP header ECN matches, the kernel silently accepts it, but doesn't invert the match result. Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ipt_ecn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index aaa85be1b2d8..2b57e52c746c 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c @@ -25,7 +25,8 @@ MODULE_LICENSE("GPL"); static inline bool match_ip(const struct sk_buff *skb, const struct ipt_ecn_info *einfo) { - return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect; + return ((ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect) ^ + !!(einfo->invert & IPT_ECN_OP_MATCH_IP); } static inline bool match_tcp(const struct sk_buff *skb, -- cgit v1.2.3 From 2c38de4c1f8da799bdca0e4bb40ca13f2174d3e8 Mon Sep 17 00:00:00 2001 From: Nicolas Cavallari Date: Thu, 16 Jun 2011 17:27:04 +0200 Subject: netfilter: fix looped (broad|multi)cast's MAC handling By default, when broadcast or multicast packet are sent from a local application, they are sent to the interface then looped by the kernel to other local applications, going throught netfilter hooks in the process. These looped packet have their MAC header removed from the skb by the kernel looping code. This confuse various netfilter's netlink queue, netlink log and the legacy ip_queue, because they try to extract a hardware address from these packets, but extracts a part of the IP header instead. This patch prevent NFQUEUE, NFLOG and ip_QUEUE to include a MAC header if there is none in the packet. Signed-off-by: Nicolas Cavallari Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_queue.c | 3 ++- net/ipv6/netfilter/ip6_queue.c | 3 ++- net/netfilter/nfnetlink_log.c | 3 ++- net/netfilter/nfnetlink_queue.c | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index f7f9bd7ba12d..5c9b9d963918 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -203,7 +203,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) else pmsg->outdev_name[0] = '\0'; - if (entry->indev && entry->skb->dev) { + if (entry->indev && entry->skb->dev && + entry->skb->mac_header != entry->skb->network_header) { pmsg->hw_type = entry->skb->dev->type; pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr); diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 065fe405fb58..249394863284 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -204,7 +204,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) else pmsg->outdev_name[0] = '\0'; - if (entry->indev && entry->skb->dev) { + if (entry->indev && entry->skb->dev && + entry->skb->mac_header != entry->skb->network_header) { pmsg->hw_type = entry->skb->dev->type; pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr); } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index e0ee010935e7..2e7ccbb43ddb 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -456,7 +456,8 @@ __build_packet_message(struct nfulnl_instance *inst, if (skb->mark) NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark)); - if (indev && skb->dev) { + if (indev && skb->dev && + skb->mac_header != skb->network_header) { struct nfulnl_msg_packet_hw phw; int len = dev_parse_header(skb, phw.hw_addr); if (len > 0) { diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index b83123f12b42..fdd2fafe0a14 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -335,7 +335,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, if (entskb->mark) NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark)); - if (indev && entskb->dev) { + if (indev && entskb->dev && + entskb->mac_header != entskb->network_header) { struct nfqnl_msg_packet_hw phw; int len = dev_parse_header(entskb, phw.hw_addr); if (len) { -- cgit v1.2.3 From 50338b889dc504c69e0cb316ac92d1b9e51f3c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=B6r=C3=B6k=20Edwin?= Date: Thu, 16 Jun 2011 00:06:14 +0300 Subject: fix wrong iput on d_inode introduced by e6bc45d65d MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Git bisection shows that commit e6bc45d65df8599fdbae73be9cec4ceed274db53 causes BUG_ONs under high I/O load: kernel BUG at fs/inode.c:1368! [ 2862.501007] Call Trace: [ 2862.501007] [] d_kill+0xf8/0x140 [ 2862.501007] [] dput+0xc9/0x190 [ 2862.501007] [] fput+0x15f/0x210 [ 2862.501007] [] filp_close+0x61/0x90 [ 2862.501007] [] sys_close+0xb1/0x110 [ 2862.501007] [] system_call_fastpath+0x16/0x1b A reliable way to reproduce this bug is: Login to KDE, run 'rsnapshot sync', and apt-get install openjdk-6-jdk, and apt-get remove openjdk-6-jdk. The buggy part of the patch is this: struct inode *inode = NULL; ..... - if (nd.last.name[nd.last.len]) - goto slashes; inode = dentry->d_inode; - if (inode) - ihold(inode); + if (nd.last.name[nd.last.len] || !inode) + goto slashes; + ihold(inode) ... if (inode) iput(inode); /* truncate the inode here */ If nd.last.name[nd.last.len] is nonzero (and thus goto slashes branch is taken), and dentry->d_inode is non-NULL, then this code now does an additional iput on the inode, which is wrong. Fix this by only setting the inode variable if nd.last.name[nd.last.len] is 0. Reference: https://lkml.org/lkml/2011/6/15/50 Reported-by: Norbert Preining Reported-by: Török Edwin Cc: "Theodore Ts'o" Cc: Al Viro Signed-off-by: Török Edwin Signed-off-by: Al Viro --- fs/namei.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 9802345df5e7..6301963b161f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2713,8 +2713,10 @@ static long do_unlinkat(int dfd, const char __user *pathname) error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ + if (nd.last.name[nd.last.len]) + goto slashes; inode = dentry->d_inode; - if (nd.last.name[nd.last.len] || !inode) + if (!inode) goto slashes; ihold(inode); error = mnt_want_write(nd.path.mnt); -- cgit v1.2.3 From 8aef18845266f5c05904c610088f2d1ed58f6be3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 16 Jun 2011 15:10:06 +0100 Subject: VFS: Fix vfsmount overput on simultaneous automount [Kudos to dhowells for tracking that crap down] If two processes attempt to cause automounting on the same mountpoint at the same time, the vfsmount holding the mountpoint will be left with one too few references on it, causing a BUG when the kernel tries to clean up. The problem is that lock_mount() drops the caller's reference to the mountpoint's vfsmount in the case where it finds something already mounted on the mountpoint as it transits to the mounted filesystem and replaces path->mnt with the new mountpoint vfsmount. During a pathwalk, however, we don't take a reference on the vfsmount if it is the same as the one in the nameidata struct, but do_add_mount() doesn't know this. The fix is to make sure we have a ref on the vfsmount of the mountpoint before calling do_add_mount(). However, if lock_mount() doesn't transit, we're then left with an extra ref on the mountpoint vfsmount which needs releasing. We can handle that in follow_managed() by not making assumptions about what we can and what we cannot get from lookup_mnt() as the current code does. The callers of follow_managed() expect that reference to path->mnt will be grabbed iff path->mnt has been changed. follow_managed() and follow_automount() keep track of whether such reference has been grabbed and assume that it'll happen in those and only those cases that'll have us return with changed path->mnt. That assumption is almost correct - it breaks in case of racing automounts and in even harder to hit race between following a mountpoint and a couple of mount --move. The thing is, we don't need to make that assumption at all - after the end of loop in follow_manage() we can check if path->mnt has ended up unchanged and do mntput() if needed. The BUG can be reproduced with the following test program: #include #include #include #include #include int main(int argc, char **argv) { int pid, ws; struct stat buf; pid = fork(); stat(argv[1], &buf); if (pid > 0) wait(&ws); return 0; } and the following procedure: (1) Mount an NFS volume that on the server has something else mounted on a subdirectory. For instance, I can mount / from my server: mount warthog:/ /mnt -t nfs4 -r On the server /data has another filesystem mounted on it, so NFS will see a change in FSID as it walks down the path, and will mark /mnt/data as being a mountpoint. This will cause the automount code to be triggered. !!! Do not look inside the mounted fs at this point !!! (2) Run the above program on a file within the submount to generate two simultaneous automount requests: /tmp/forkstat /mnt/data/testfile (3) Unmount the automounted submount: umount /mnt/data (4) Unmount the original mount: umount /mnt At this point the kernel should throw a BUG with something like the following: BUG: Dentry ffff880032e3c5c0{i=2,n=} still in use (1) [unmount of nfs4 0:12] Note that the bug appears on the root dentry of the original mount, not the mountpoint and not the submount because sys_umount() hasn't got to its final mntput_no_expire() yet, but this isn't so obvious from the call trace: [] shrink_dcache_for_umount+0x69/0x82 [] generic_shutdown_super+0x37/0x15b [] ? nfs_super_return_all_delegations+0x2e/0x1b1 [nfs] [] kill_anon_super+0x1d/0x7e [] nfs4_kill_super+0x60/0xb6 [nfs] [] deactivate_locked_super+0x34/0x83 [] deactivate_super+0x6f/0x7b [] mntput_no_expire+0x18d/0x199 [] mntput+0x3b/0x44 [] release_mounts+0xa2/0xbf [] sys_umount+0x47a/0x4ba [] ? trace_hardirqs_on_caller+0x1fd/0x22f [] system_call_fastpath+0x16/0x1b as do_umount() is inlined. However, you can see release_mounts() in there. Note also that it may be necessary to have multiple CPU cores to be able to trigger this bug. Tested-by: Jeff Layton Tested-by: Ian Kent Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/namei.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 6301963b161f..9e425e7e6c8f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -812,6 +812,11 @@ static int follow_automount(struct path *path, unsigned flags, if (!mnt) /* mount collision */ return 0; + if (!*need_mntput) { + /* lock_mount() may release path->mnt on error */ + mntget(path->mnt); + *need_mntput = true; + } err = finish_automount(mnt, path); switch (err) { @@ -819,12 +824,9 @@ static int follow_automount(struct path *path, unsigned flags, /* Someone else made a mount here whilst we were busy */ return 0; case 0: - dput(path->dentry); - if (*need_mntput) - mntput(path->mnt); + path_put(path); path->mnt = mnt; path->dentry = dget(mnt->mnt_root); - *need_mntput = true; return 0; default: return err; @@ -844,9 +846,10 @@ static int follow_automount(struct path *path, unsigned flags, */ static int follow_managed(struct path *path, unsigned flags) { + struct vfsmount *mnt = path->mnt; /* held by caller, must be left alone */ unsigned managed; bool need_mntput = false; - int ret; + int ret = 0; /* Given that we're not holding a lock here, we retain the value in a * local variable for each dentry as we look at it so that we don't see @@ -861,7 +864,7 @@ static int follow_managed(struct path *path, unsigned flags) BUG_ON(!path->dentry->d_op->d_manage); ret = path->dentry->d_op->d_manage(path->dentry, false); if (ret < 0) - return ret == -EISDIR ? 0 : ret; + break; } /* Transit to a mounted filesystem. */ @@ -887,14 +890,19 @@ static int follow_managed(struct path *path, unsigned flags) if (managed & DCACHE_NEED_AUTOMOUNT) { ret = follow_automount(path, flags, &need_mntput); if (ret < 0) - return ret == -EISDIR ? 0 : ret; + break; continue; } /* We didn't change the current path point */ break; } - return 0; + + if (need_mntput && path->mnt == mnt) + mntput(path->mnt); + if (ret == -EISDIR) + ret = 0; + return ret; } int follow_down_one(struct path *path) -- cgit v1.2.3 From e1d76719ea3f3f755d597cef9c2087bdda5fea43 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 15:00:18 -0700 Subject: staging: fix iio builds when IIO_RING_BUFFER is not enabled Fix build by moving enum list outside of #ifdef CONFIG_IIO_RING_BUFFER. drivers/staging/iio/accel/adis16201_core.c:413: error: 'ADIS16201_SCAN_SUPPLY' undeclared here (not in a function) drivers/staging/iio/accel/adis16201_core.c:417: error: 'ADIS16201_SCAN_TEMP' undeclared here (not in a function) .. drivers/staging/iio/accel/adis16203_core.c:374: error: 'ADIS16203_SCAN_SUPPLY' undeclared here (not in a function) drivers/staging/iio/accel/adis16203_core.c:378: error: 'ADIS16203_SCAN_AUX_ADC' undeclared here (not in a function) .. Signed-off-by: Randy Dunlap Acked-by: Jonathan Cameron Cc: linux-iio@vger.kernel.org Signed-off-by: Linus Torvalds --- drivers/staging/iio/accel/adis16201.h | 2 +- drivers/staging/iio/accel/adis16203.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h index 0b9b85424dfa..4cc1a5bfab40 100644 --- a/drivers/staging/iio/accel/adis16201.h +++ b/drivers/staging/iio/accel/adis16201.h @@ -81,7 +81,6 @@ struct adis16201_state { int adis16201_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER enum adis16201_scan { ADIS16201_SCAN_SUPPLY, ADIS16201_SCAN_ACC_X, @@ -92,6 +91,7 @@ enum adis16201_scan { ADIS16201_SCAN_INCLI_Y, }; +#ifdef CONFIG_IIO_RING_BUFFER void adis16201_remove_trigger(struct iio_dev *indio_dev); int adis16201_probe_trigger(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h index 8bb8ce50c248..175e21bb9b40 100644 --- a/drivers/staging/iio/accel/adis16203.h +++ b/drivers/staging/iio/accel/adis16203.h @@ -76,7 +76,6 @@ struct adis16203_state { int adis16203_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER enum adis16203_scan { ADIS16203_SCAN_SUPPLY, ADIS16203_SCAN_AUX_ADC, @@ -85,6 +84,7 @@ enum adis16203_scan { ADIS16203_SCAN_INCLI_Y, }; +#ifdef CONFIG_IIO_RING_BUFFER void adis16203_remove_trigger(struct iio_dev *indio_dev); int adis16203_probe_trigger(struct iio_dev *indio_dev); -- cgit v1.2.3 From 42c1edd345c8412d96e7a362ee06feb7be73bb6c Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Thu, 16 Jun 2011 17:29:22 +0200 Subject: netfilter: nf_nat: avoid double seq_adjust for loopback Avoid double seq adjustment for loopback traffic because it causes silent repetition of TCP data. One example is passive FTP with DNAT rule and difference in the length of IP addresses. This patch adds check if packet is sent and received via loopback device. As the same conntrack is used both for outgoing and incoming direction, we restrict seq adjustment to happen only in POSTROUTING. Signed-off-by: Julian Anastasov Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack.h | 6 ++++++ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index c7c42e7acc31..5d4f8e586e32 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -307,6 +307,12 @@ static inline int nf_ct_is_untracked(const struct nf_conn *ct) return test_bit(IPS_UNTRACKED_BIT, &ct->status); } +/* Packet is received from loopback */ +static inline bool nf_is_loopback_packet(const struct sk_buff *skb) +{ + return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK; +} + extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); extern unsigned int nf_conntrack_htable_size; extern unsigned int nf_conntrack_max; diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index db10075dd88e..de9da21113a1 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -121,7 +121,9 @@ static unsigned int ipv4_confirm(unsigned int hooknum, return ret; } - if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { + /* adjust seqs for loopback traffic only in outgoing direction */ + if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && + !nf_is_loopback_packet(skb)) { typeof(nf_nat_seq_adjust_hook) seq_adjust; seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); -- cgit v1.2.3 From 5e7f23373bf9a853e9256e81e86724cdd0a33c29 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 13 Jun 2011 22:31:12 +0100 Subject: afs: afs_fill_page reads too much, or wrong data afs_fill_page should read the page that is about to be written but the current implementation has a number of issues. If we aren't extending the file we always read PAGE_CACHE_SIZE at offset 0. If we are extending the file we try to read the entire file. Change afs_fill_page to read PAGE_CACHE_SIZE at the right offset, clamped to i_size. While here, avoid calling afs_fill_page when we are doing a PAGE_CACHE_SIZE write. Signed-off-by: Anton Blanchard Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/afs/write.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/fs/afs/write.c b/fs/afs/write.c index 789b3afb3423..b806285ff853 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -84,23 +84,21 @@ void afs_put_writeback(struct afs_writeback *wb) * partly or wholly fill a page that's under preparation for writing */ static int afs_fill_page(struct afs_vnode *vnode, struct key *key, - loff_t pos, unsigned len, struct page *page) + loff_t pos, struct page *page) { loff_t i_size; - unsigned eof; int ret; + int len; - _enter(",,%llu,%u", (unsigned long long)pos, len); - - ASSERTCMP(len, <=, PAGE_CACHE_SIZE); + _enter(",,%llu", (unsigned long long)pos); i_size = i_size_read(&vnode->vfs_inode); - if (pos + len > i_size) - eof = i_size; + if (pos + PAGE_CACHE_SIZE > i_size) + len = i_size - pos; else - eof = PAGE_CACHE_SIZE; + len = PAGE_CACHE_SIZE; - ret = afs_vnode_fetch_data(vnode, key, 0, eof, page); + ret = afs_vnode_fetch_data(vnode, key, pos, len, page); if (ret < 0) { if (ret == -ENOENT) { _debug("got NOENT from server" @@ -153,9 +151,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping, *pagep = page; /* page won't leak in error case: it eventually gets cleaned off LRU */ - if (!PageUptodate(page)) { - _debug("not up to date"); - ret = afs_fill_page(vnode, key, pos, len, page); + if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) { + ret = afs_fill_page(vnode, key, index << PAGE_CACHE_SHIFT, page); if (ret < 0) { kfree(candidate); _leave(" = %d [prep]", ret); -- cgit v1.2.3 From f9f07b6c1372b1436aa6b45333445b443ffd8c95 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 14 Jun 2011 00:58:27 +0200 Subject: vfs: Fix data corruption after failed write in __block_write_begin() I've got a report of a file corruption from fsxlinux on ext3. The important operations to the page were: mapwrite to a hole partial write to the page read - found the page zeroed from the end of the normal write The culprit seems to be that if get_block() fails in __block_write_begin() (e.g. transient ENOSPC in ext3), the function does ClearPageUptodate(page). Thus when we retry the write, the logic in __block_write_begin() thinks zeroing of the page is needed and overwrites old data. In fact, I don't see why we should ever need to zero the uptodate bit here - either the page was uptodate when we entered __block_write_begin() and it should stay so when we leave it, or it was not uptodate and noone had right to set it uptodate during __block_write_begin() so it remains !uptodate when we leave as well. So just remove clearing of the bit. Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/buffer.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 49c9aada0374..1a80b048ade8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1902,10 +1902,8 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, if (!buffer_uptodate(*wait_bh)) err = -EIO; } - if (unlikely(err)) { + if (unlikely(err)) page_zero_new_buffers(page, from, to); - ClearPageUptodate(page); - } return err; } EXPORT_SYMBOL(__block_write_begin); -- cgit v1.2.3 From 2e41ae225f742ded5b7d9847cd8bd605f27daba8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 14 Jun 2011 00:38:44 +0100 Subject: AFS: Set s_id in the superblock to the volume name Set s_id in the superblock to the name of the AFS volume that this superblock corresponds to. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/afs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/afs/super.c b/fs/afs/super.c index b7d48d7eaa1e..356dcf0929e8 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -313,6 +313,7 @@ static int afs_fill_super(struct super_block *sb, sb->s_magic = AFS_FS_MAGIC; sb->s_op = &afs_super_ops; sb->s_bdi = &as->volume->bdi; + strlcpy(sb->s_id, as->volume->vlocation->vldb.name, sizeof(sb->s_id)); /* allocate the root inode and dentry */ fid.vid = as->volume->vid; -- cgit v1.2.3 From d6e43f751f252c68ca69fa6d18665d88d69ef8b7 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 14 Jun 2011 00:45:44 +0100 Subject: AFS: Use i_generation not i_version for the vnode uniquifier Store the AFS vnode uniquifier in the i_generation field, not the i_version field of the inode struct. i_version can then be given the AFS data version number. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/afs/dir.c | 8 ++++---- fs/afs/fsclient.c | 3 ++- fs/afs/inode.c | 10 +++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 20c106f24927..1b0b19550015 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -584,11 +584,11 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, success: d_add(dentry, inode); - _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%llu }", + _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%u }", fid.vnode, fid.unique, dentry->d_inode->i_ino, - (unsigned long long)dentry->d_inode->i_version); + dentry->d_inode->i_generation); return NULL; } @@ -671,10 +671,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) * been deleted and replaced, and the original vnode ID has * been reused */ if (fid.unique != vnode->fid.unique) { - _debug("%s: file deleted (uq %u -> %u I:%llu)", + _debug("%s: file deleted (uq %u -> %u I:%u)", dentry->d_name.name, fid.unique, vnode->fid.unique, - (unsigned long long)dentry->d_inode->i_version); + dentry->d_inode->i_generation); spin_lock(&vnode->lock); set_bit(AFS_VNODE_DELETED, &vnode->flags); spin_unlock(&vnode->lock); diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 4bd0218473a9..346e3289abd7 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -89,7 +89,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, i_size_write(&vnode->vfs_inode, size); vnode->vfs_inode.i_uid = status->owner; vnode->vfs_inode.i_gid = status->group; - vnode->vfs_inode.i_version = vnode->fid.unique; + vnode->vfs_inode.i_generation = vnode->fid.unique; vnode->vfs_inode.i_nlink = status->nlink; mode = vnode->vfs_inode.i_mode; @@ -102,6 +102,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server; vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime; vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; + vnode->vfs_inode.i_version = data_version; } expected_version = status->data_version; diff --git a/fs/afs/inode.c b/fs/afs/inode.c index db66c5201474..0fdab6e03d87 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -75,7 +75,8 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key) inode->i_ctime.tv_nsec = 0; inode->i_atime = inode->i_mtime = inode->i_ctime; inode->i_blocks = 0; - inode->i_version = vnode->fid.unique; + inode->i_generation = vnode->fid.unique; + inode->i_version = vnode->status.data_version; inode->i_mapping->a_ops = &afs_fs_aops; /* check to see whether a symbolic link is really a mountpoint */ @@ -100,7 +101,7 @@ static int afs_iget5_test(struct inode *inode, void *opaque) struct afs_iget_data *data = opaque; return inode->i_ino == data->fid.vnode && - inode->i_version == data->fid.unique; + inode->i_generation == data->fid.unique; } /* @@ -122,7 +123,7 @@ static int afs_iget5_set(struct inode *inode, void *opaque) struct afs_vnode *vnode = AFS_FS_I(inode); inode->i_ino = data->fid.vnode; - inode->i_version = data->fid.unique; + inode->i_generation = data->fid.unique; vnode->fid = data->fid; vnode->volume = data->volume; @@ -380,8 +381,7 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry, inode = dentry->d_inode; - _enter("{ ino=%lu v=%llu }", inode->i_ino, - (unsigned long long)inode->i_version); + _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation); generic_fillattr(inode, stat); return 0; -- cgit v1.2.3 From a27a263bae072a499acc77b632238a6dacccf888 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 16 Jun 2011 12:02:23 +0000 Subject: xfs: make log devices with write back caches work There's no reason not to support cache flushing on external log devices. The only thing this really requires is flushing the data device first both in fsync and log commits. A side effect is that we also have to remove the barrier write test during mount, which has been superflous since the new FLUSH+FUA code anyway. Also use the chance to flush the RT subvolume write cache before the fsync commit, which is required for correct semantics. Signed-off-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/linux-2.6/xfs_file.c | 50 ++++++++++++++++++----------- fs/xfs/linux-2.6/xfs_super.c | 75 -------------------------------------------- fs/xfs/xfs_log.c | 11 ++++++- 3 files changed, 41 insertions(+), 95 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index f4213ba1ff85..7f782af286bf 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -131,19 +131,34 @@ xfs_file_fsync( { struct inode *inode = file->f_mapping->host; struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; int error = 0; int log_flushed = 0; trace_xfs_file_fsync(ip); - if (XFS_FORCED_SHUTDOWN(ip->i_mount)) + if (XFS_FORCED_SHUTDOWN(mp)) return -XFS_ERROR(EIO); xfs_iflags_clear(ip, XFS_ITRUNCATED); xfs_ioend_wait(ip); + if (mp->m_flags & XFS_MOUNT_BARRIER) { + /* + * If we have an RT and/or log subvolume we need to make sure + * to flush the write cache the device used for file data + * first. This is to ensure newly written file data make + * it to disk before logging the new inode size in case of + * an extending write. + */ + if (XFS_IS_REALTIME_INODE(ip)) + xfs_blkdev_issue_flush(mp->m_rtdev_targp); + else if (mp->m_logdev_targp != mp->m_ddev_targp) + xfs_blkdev_issue_flush(mp->m_ddev_targp); + } + /* * We always need to make sure that the required inode state is safe on * disk. The inode might be clean but we still might need to force the @@ -175,9 +190,9 @@ xfs_file_fsync( * updates. The sync transaction will also force the log. */ xfs_iunlock(ip, XFS_ILOCK_SHARED); - tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS); + tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); error = xfs_trans_reserve(tp, 0, - XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0); + XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); if (error) { xfs_trans_cancel(tp, 0); return -error; @@ -209,28 +224,25 @@ xfs_file_fsync( * force the log. */ if (xfs_ipincount(ip)) { - error = _xfs_log_force_lsn(ip->i_mount, + error = _xfs_log_force_lsn(mp, ip->i_itemp->ili_last_lsn, XFS_LOG_SYNC, &log_flushed); } xfs_iunlock(ip, XFS_ILOCK_SHARED); } - if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) { - /* - * If the log write didn't issue an ordered tag we need - * to flush the disk cache for the data device now. - */ - if (!log_flushed) - xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp); - - /* - * If this inode is on the RT dev we need to flush that - * cache as well. - */ - if (XFS_IS_REALTIME_INODE(ip)) - xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); - } + /* + * If we only have a single device, and the log force about was + * a no-op we might have to flush the data device cache here. + * This can only happen for fdatasync/O_DSYNC if we were overwriting + * an already allocated file and thus do not have any metadata to + * commit. + */ + if ((mp->m_flags & XFS_MOUNT_BARRIER) && + mp->m_logdev_targp == mp->m_ddev_targp && + !XFS_IS_REALTIME_INODE(ip) && + !log_flushed) + xfs_blkdev_issue_flush(mp->m_ddev_targp); return -error; } diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 1e3a7ce804dc..a1a881e68a9a 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -627,68 +627,6 @@ xfs_blkdev_put( blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); } -/* - * Try to write out the superblock using barriers. - */ -STATIC int -xfs_barrier_test( - xfs_mount_t *mp) -{ - xfs_buf_t *sbp = xfs_getsb(mp, 0); - int error; - - XFS_BUF_UNDONE(sbp); - XFS_BUF_UNREAD(sbp); - XFS_BUF_UNDELAYWRITE(sbp); - XFS_BUF_WRITE(sbp); - XFS_BUF_UNASYNC(sbp); - XFS_BUF_ORDERED(sbp); - - xfsbdstrat(mp, sbp); - error = xfs_buf_iowait(sbp); - - /* - * Clear all the flags we set and possible error state in the - * buffer. We only did the write to try out whether barriers - * worked and shouldn't leave any traces in the superblock - * buffer. - */ - XFS_BUF_DONE(sbp); - XFS_BUF_ERROR(sbp, 0); - XFS_BUF_UNORDERED(sbp); - - xfs_buf_relse(sbp); - return error; -} - -STATIC void -xfs_mountfs_check_barriers(xfs_mount_t *mp) -{ - int error; - - if (mp->m_logdev_targp != mp->m_ddev_targp) { - xfs_notice(mp, - "Disabling barriers, not supported with external log device"); - mp->m_flags &= ~XFS_MOUNT_BARRIER; - return; - } - - if (xfs_readonly_buftarg(mp->m_ddev_targp)) { - xfs_notice(mp, - "Disabling barriers, underlying device is readonly"); - mp->m_flags &= ~XFS_MOUNT_BARRIER; - return; - } - - error = xfs_barrier_test(mp); - if (error) { - xfs_notice(mp, - "Disabling barriers, trial barrier write failed"); - mp->m_flags &= ~XFS_MOUNT_BARRIER; - return; - } -} - void xfs_blkdev_issue_flush( xfs_buftarg_t *buftarg) @@ -1240,14 +1178,6 @@ xfs_fs_remount( switch (token) { case Opt_barrier: mp->m_flags |= XFS_MOUNT_BARRIER; - - /* - * Test if barriers are actually working if we can, - * else delay this check until the filesystem is - * marked writeable. - */ - if (!(mp->m_flags & XFS_MOUNT_RDONLY)) - xfs_mountfs_check_barriers(mp); break; case Opt_nobarrier: mp->m_flags &= ~XFS_MOUNT_BARRIER; @@ -1282,8 +1212,6 @@ xfs_fs_remount( /* ro -> rw */ if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { mp->m_flags &= ~XFS_MOUNT_RDONLY; - if (mp->m_flags & XFS_MOUNT_BARRIER) - xfs_mountfs_check_barriers(mp); /* * If this is the first remount to writeable state we @@ -1465,9 +1393,6 @@ xfs_fs_fill_super( if (error) goto out_free_sb; - if (mp->m_flags & XFS_MOUNT_BARRIER) - xfs_mountfs_check_barriers(mp); - error = xfs_filestream_mount(mp); if (error) goto out_free_sb; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 211930246f20..41d5b8f2bf92 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1372,8 +1372,17 @@ xlog_sync(xlog_t *log, XFS_BUF_ASYNC(bp); bp->b_flags |= XBF_LOG_BUFFER; - if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) + if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) { + /* + * If we have an external log device, flush the data device + * before flushing the log to make sure all meta data + * written back from the AIL actually made it to disk + * before writing out the new log tail LSN in the log buffer. + */ + if (log->l_mp->m_logdev_targp != log->l_mp->m_ddev_targp) + xfs_blkdev_issue_flush(log->l_mp->m_ddev_targp); XFS_BUF_ORDERED(bp); + } ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); -- cgit v1.2.3 From ee7b75fc4f3ae49e1f25bf56219bb5de3c29afaf Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 16 Jun 2011 13:15:41 -0400 Subject: NFSv4: Fix a readdir regression Commit 7ebb9315 (NFS: use secinfo when crossing mountpoints) introduces a regression when decoding an NFSv4 readdir entry that sets the rdattr_error field. By treating the resulting value as if it is a decoding error, the current code may cause us to skip valid readdir entries. Reported-by: Andy Adamson Cc: stable@kernel.org [2.6.39] Signed-off-by: Trond Myklebust --- fs/nfs/nfs4xdr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c4b7d6c04948..5db44a8dddf9 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -3098,7 +3098,7 @@ out_overflow: return -EIO; } -static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) +static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) { __be32 *p; @@ -3109,7 +3109,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) if (unlikely(!p)) goto out_overflow; bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; - return -be32_to_cpup(p); + *res = -be32_to_cpup(p); } return 0; out_overflow: @@ -4070,6 +4070,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, int status; umode_t fmode = 0; uint32_t type; + int32_t err; status = decode_attr_type(xdr, bitmap, &type); if (status < 0) @@ -4095,13 +4096,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, goto xdr_error; fattr->valid |= status; - status = decode_attr_error(xdr, bitmap); - if (status == -NFS4ERR_WRONGSEC) { - nfs_fixup_secinfo_attributes(fattr, fh); - status = 0; - } + err = 0; + status = decode_attr_error(xdr, bitmap, &err); if (status < 0) goto xdr_error; + if (err == -NFS4ERR_WRONGSEC) + nfs_fixup_secinfo_attributes(fattr, fh); status = decode_attr_filehandle(xdr, bitmap, fh); if (status < 0) -- cgit v1.2.3 From b5199515c25cca622495eb9c6a8a1d275e775088 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 16 Jun 2011 16:22:08 +0200 Subject: clocksource: Make watchdog robust vs. interruption The clocksource watchdog code is interruptible and it has been observed that this can trigger false positives which disable the TSC. The reason is that an interrupt storm or a long running interrupt handler between the read of the watchdog source and the read of the TSC brings the two far enough apart that the delta is larger than the unstable treshold. Move both reads into a short interrupt disabled region to avoid that. Reported-and-tested-by: Vernon Mauery Signed-off-by: Thomas Gleixner Cc: stable@kernel.org --- include/linux/clocksource.h | 1 + kernel/time/clocksource.c | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index d4646b48dc4a..18a1baf31f2d 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -188,6 +188,7 @@ struct clocksource { #ifdef CONFIG_CLOCKSOURCE_WATCHDOG /* Watchdog related data, used by the framework */ struct list_head wd_list; + cycle_t cs_last; cycle_t wd_last; #endif } ____cacheline_aligned; diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 1c95fd677328..e0980f0d9a0a 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -185,7 +185,6 @@ static struct clocksource *watchdog; static struct timer_list watchdog_timer; static DECLARE_WORK(watchdog_work, clocksource_watchdog_work); static DEFINE_SPINLOCK(watchdog_lock); -static cycle_t watchdog_last; static int watchdog_running; static int clocksource_watchdog_kthread(void *data); @@ -254,11 +253,6 @@ static void clocksource_watchdog(unsigned long data) if (!watchdog_running) goto out; - wdnow = watchdog->read(watchdog); - wd_nsec = clocksource_cyc2ns((wdnow - watchdog_last) & watchdog->mask, - watchdog->mult, watchdog->shift); - watchdog_last = wdnow; - list_for_each_entry(cs, &watchdog_list, wd_list) { /* Clocksource already marked unstable? */ @@ -268,19 +262,28 @@ static void clocksource_watchdog(unsigned long data) continue; } + local_irq_disable(); csnow = cs->read(cs); + wdnow = watchdog->read(watchdog); + local_irq_enable(); /* Clocksource initialized ? */ if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) { cs->flags |= CLOCK_SOURCE_WATCHDOG; - cs->wd_last = csnow; + cs->wd_last = wdnow; + cs->cs_last = csnow; continue; } - /* Check the deviation from the watchdog clocksource. */ - cs_nsec = clocksource_cyc2ns((csnow - cs->wd_last) & + wd_nsec = clocksource_cyc2ns((wdnow - cs->wd_last) & watchdog->mask, + watchdog->mult, watchdog->shift); + + cs_nsec = clocksource_cyc2ns((csnow - cs->cs_last) & cs->mask, cs->mult, cs->shift); - cs->wd_last = csnow; + cs->cs_last = csnow; + cs->wd_last = wdnow; + + /* Check the deviation from the watchdog clocksource. */ if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) { clocksource_unstable(cs, cs_nsec - wd_nsec); continue; @@ -318,7 +321,6 @@ static inline void clocksource_start_watchdog(void) return; init_timer(&watchdog_timer); watchdog_timer.function = clocksource_watchdog; - watchdog_last = watchdog->read(watchdog); watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL; add_timer_on(&watchdog_timer, cpumask_first(cpu_online_mask)); watchdog_running = 1; -- cgit v1.2.3 From acd049c6e99d2ad1195666195230f6881d1c1588 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Jun 2011 13:07:19 -0400 Subject: xen/setup: Fix for incorrect xen_extra_mem_start. The earlier attempts (24bdb0b62cc82120924762ae6bc85afc8c3f2b26) at fixing this problem caused other problems to surface (PV guests with no PCI passthrough would have SWIOTLB turned on - which meant 64MB of precious contingous DMA32 memory being eaten up per guest). The problem was: "on xen we add an extra memory region at the end of the e820, and on this particular machine this extra memory region would start below 4g and cross over the 4g boundary: [0xfee01000-0x192655000) Unfortunately e820_end_of_low_ram_pfn does not expect an e820 layout like that so it returns 4g, therefore initial_memory_mapping will map [0 - 0x100000000), that is a memory range that includes some reserved memory regions." The memory range was the IOAPIC regions, and with the 1-1 mapping turned on, it would map them as RAM, not as MMIO regions. This caused the hypervisor to complain. Fortunately this is experienced only under the initial domain so we guard for it. Acked-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/setup.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index be1a464f6d66..60aeeb56948f 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -227,11 +227,7 @@ char * __init xen_memory_setup(void) memcpy(map_raw, map, sizeof(map)); e820.nr_map = 0; -#ifdef CONFIG_X86_32 xen_extra_mem_start = mem_end; -#else - xen_extra_mem_start = max((1ULL << 32), mem_end); -#endif for (i = 0; i < memmap.nr_entries; i++) { unsigned long long end; @@ -266,6 +262,12 @@ char * __init xen_memory_setup(void) if (map[i].size > 0) e820_add_region(map[i].addr, map[i].size, map[i].type); } + /* Align the balloon area so that max_low_pfn does not get set + * to be at the _end_ of the PCI gap at the far end (fee01000). + * Note that xen_extra_mem_start gets set in the loop above to be + * past the last E820 region. */ + if (xen_initial_domain() && (xen_extra_mem_start < (1ULL<<32))) + xen_extra_mem_start = (1ULL<<32); /* * In domU, the ISA region is normal, usable memory, but we -- cgit v1.2.3 From 7263287af93db4d5cf324a30546f2143419b7900 Mon Sep 17 00:00:00 2001 From: Russ Gorby Date: Tue, 14 Jun 2011 13:23:28 -0700 Subject: tty: n_gsm: Fixed logic to decode break signal from modem status The modem status can be one or 2 octets and contains the V.24 signals and in the 2 octet case also the break signal. We were improperly decoding the break signal from the modem in the 2 octet case. Signed-off-by: Russ Gorby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 09e8c7d53af3..7290394e3131 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -984,10 +984,22 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data, */ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, - u32 modem) + u32 modem, int clen) { int mlines = 0; - u8 brk = modem >> 6; + u8 brk = 0; + + /* The modem status command can either contain one octet (v.24 signals) + or two octets (v.24 signals + break signals). The length field will + either be 2 or 3 respectively. This is specified in section + 5.4.6.3.7 of the 27.010 mux spec. */ + + if (clen == 2) + modem = modem & 0x7f; + else { + brk = modem & 0x7f; + modem = (modem >> 7) & 0x7f; + }; /* Flow control/ready to communicate */ if (modem & MDM_FC) { @@ -1061,7 +1073,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) return; } tty = tty_port_tty_get(&dlci->port); - gsm_process_modem(tty, dlci, modem); + gsm_process_modem(tty, dlci, modem, clen); if (tty) { tty_wakeup(tty); tty_kref_put(tty); @@ -1482,12 +1494,13 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci) * open we shovel the bits down it, if not we drop them. */ -static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) +static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen) { /* krefs .. */ struct tty_port *port = &dlci->port; struct tty_struct *tty = tty_port_tty_get(port); unsigned int modem = 0; + int len = clen; if (debug & 16) pr_debug("%d bytes for tty %p\n", len, tty); @@ -1507,7 +1520,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int len) if (len == 0) return; } - gsm_process_modem(tty, dlci, modem); + gsm_process_modem(tty, dlci, modem, clen); /* Line state will go via DLCI 0 controls only */ case 1: default: -- cgit v1.2.3 From 57f2104f39995bac332ddc492fbf60aa28e0c35e Mon Sep 17 00:00:00 2001 From: Russ Gorby Date: Tue, 14 Jun 2011 13:23:29 -0700 Subject: tty: n_gsm: improper skb_pull() use was leaking framed data gsm_dlci_data_output_framed() was doing: memcpy(dp, skb_pull(dlci->skb, len), len); The problem is skb_pull() returns the post-increment data ptr so the first chunk of dlci->skb->data is leaked. Signed-off-by: Russ Gorby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 7290394e3131..19b4ae052af8 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -875,7 +875,8 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, *dp++ = last << 7 | first << 6 | 1; /* EA */ len--; } - memcpy(dp, skb_pull(dlci->skb, len), len); + memcpy(dp, dlci->skb->data, len); + skb_pull(dlci->skb, len); __gsm_data_queue(dlci, msg); if (last) dlci->skb = NULL; -- cgit v1.2.3 From c16d51a32bbb61ac8fd96f78b5ce2fccfe0fb4c3 Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Mon, 13 Jun 2011 10:11:33 +0200 Subject: amba pl011: workaround for uart registers lockup This workaround aims to break the deadlock situation which raises during continuous transfer of data for long duration over uart with hardware flow control. It is observed that CTS interrupt cannot be cleared in uart interrupt register (ICR). Hence further transfer over uart gets blocked. It is seen that during such deadlock condition ICR don't get cleared even on multiple write. This leads pass_counter to decrease and finally reach zero. This can be taken as trigger point to run this UART_BT_WA. Workaround backups the register configuration, does soft reset of UART using BIT-0 of PRCC_K_SOFTRST_SET/CLEAR registers and restores the registers. This patch also provides support for uart init and exit function calls if present. Signed-off-by: Shreshtha Kumar Sahu Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 123 +++++++++++++++++++++++++++++++++++++++- include/linux/amba/serial.h | 3 + 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 8dc0541feecc..f5f6831b0a64 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -65,6 +66,30 @@ #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) #define UART_DUMMY_DR_RX (1 << 16) + +#define UART_WA_SAVE_NR 14 + +static void pl011_lockup_wa(unsigned long data); +static const u32 uart_wa_reg[UART_WA_SAVE_NR] = { + ST_UART011_DMAWM, + ST_UART011_TIMEOUT, + ST_UART011_LCRH_RX, + UART011_IBRD, + UART011_FBRD, + ST_UART011_LCRH_TX, + UART011_IFLS, + ST_UART011_XFCR, + ST_UART011_XON1, + ST_UART011_XON2, + ST_UART011_XOFF1, + ST_UART011_XOFF2, + UART011_CR, + UART011_IMSC +}; + +static u32 uart_wa_regdata[UART_WA_SAVE_NR]; +static DECLARE_TASKLET(pl011_lockup_tlet, pl011_lockup_wa, 0); + /* There is by now at least one vendor with differing details, so handle it */ struct vendor_data { unsigned int ifls; @@ -72,6 +97,7 @@ struct vendor_data { unsigned int lcrh_tx; unsigned int lcrh_rx; bool oversampling; + bool interrupt_may_hang; /* vendor-specific */ bool dma_threshold; }; @@ -90,9 +116,12 @@ static struct vendor_data vendor_st = { .lcrh_tx = ST_UART011_LCRH_TX, .lcrh_rx = ST_UART011_LCRH_RX, .oversampling = true, + .interrupt_may_hang = true, .dma_threshold = true, }; +static struct uart_amba_port *amba_ports[UART_NR]; + /* Deals with DMA transactions */ struct pl011_sgbuf { @@ -132,6 +161,7 @@ struct uart_amba_port { unsigned int lcrh_rx; /* vendor-specific */ bool autorts; char type[12]; + bool interrupt_may_hang; /* vendor-specific */ #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ bool using_tx_dma; @@ -1008,6 +1038,68 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap) #endif +/* + * pl011_lockup_wa + * This workaround aims to break the deadlock situation + * when after long transfer over uart in hardware flow + * control, uart interrupt registers cannot be cleared. + * Hence uart transfer gets blocked. + * + * It is seen that during such deadlock condition ICR + * don't get cleared even on multiple write. This leads + * pass_counter to decrease and finally reach zero. This + * can be taken as trigger point to run this UART_BT_WA. + * + */ +static void pl011_lockup_wa(unsigned long data) +{ + struct uart_amba_port *uap = amba_ports[0]; + void __iomem *base = uap->port.membase; + struct circ_buf *xmit = &uap->port.state->xmit; + struct tty_struct *tty = uap->port.state->port.tty; + int buf_empty_retries = 200; + int loop; + + /* Stop HCI layer from submitting data for tx */ + tty->hw_stopped = 1; + while (!uart_circ_empty(xmit)) { + if (buf_empty_retries-- == 0) + break; + udelay(100); + } + + /* Backup registers */ + for (loop = 0; loop < UART_WA_SAVE_NR; loop++) + uart_wa_regdata[loop] = readl(base + uart_wa_reg[loop]); + + /* Disable UART so that FIFO data is flushed out */ + writew(0x00, uap->port.membase + UART011_CR); + + /* Soft reset UART module */ + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->reset) + plat->reset(); + } + + /* Restore registers */ + for (loop = 0; loop < UART_WA_SAVE_NR; loop++) + writew(uart_wa_regdata[loop] , + uap->port.membase + uart_wa_reg[loop]); + + /* Initialise the old status of the modem signals */ + uap->old_status = readw(uap->port.membase + UART01x_FR) & + UART01x_FR_MODEM_ANY; + + if (readl(base + UART011_MIS) & 0x2) + printk(KERN_EMERG "UART_BT_WA: ***FAILED***\n"); + + /* Start Tx/Rx */ + tty->hw_stopped = 0; +} + static void pl011_stop_tx(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1158,8 +1250,11 @@ static irqreturn_t pl011_int(int irq, void *dev_id) if (status & UART011_TXIS) pl011_tx_chars(uap); - if (pass_counter-- == 0) + if (pass_counter-- == 0) { + if (uap->interrupt_may_hang) + tasklet_schedule(&pl011_lockup_tlet); break; + } status = readw(uap->port.membase + UART011_MIS); } while (status != 0); @@ -1339,6 +1434,14 @@ static int pl011_startup(struct uart_port *port) writew(uap->im, uap->port.membase + UART011_IMSC); spin_unlock_irq(&uap->port.lock); + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->init) + plat->init(); + } + return 0; clk_dis: @@ -1394,6 +1497,15 @@ static void pl011_shutdown(struct uart_port *port) * Shut down the clock producer */ clk_disable(uap->clk); + + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->exit) + plat->exit(); + } + } static void @@ -1700,6 +1812,14 @@ static int __init pl011_console_setup(struct console *co, char *options) if (!uap) return -ENODEV; + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->init) + plat->init(); + } + uap->port.uartclk = clk_get_rate(uap->clk); if (options) @@ -1774,6 +1894,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; uap->fifosize = vendor->fifosize; + uap->interrupt_may_hang = vendor->interrupt_may_hang; uap->port.dev = &dev->dev; uap->port.mapbase = dev->res.start; uap->port.membase = base; diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index 5479fdc849e9..514ed45c462e 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -201,6 +201,9 @@ struct amba_pl011_data { bool (*dma_filter)(struct dma_chan *chan, void *filter_param); void *dma_rx_param; void *dma_tx_param; + void (*init) (void); + void (*exit) (void); + void (*reset) (void); }; #endif -- cgit v1.2.3 From 1a7d4369b3fe1f8e5efe7f11a1c482055693852f Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Mon, 13 Jun 2011 10:11:44 +0200 Subject: amba pl011: platform data for reg lockup and glitch v2 This patch provides platform data for following - uart reset function to assist uart register lockup workaround - init/exit function to fix glitch in the tx pin in tty_open when tty port0 is opened a glitch is seen in the tx line of uart0. This happens in pl011_startup() when tx fifo interrupt is provoked into asserting. Now uart0 pins are enabled (alt function) only when init is complete and turned back to gpio when closed. Signed-off-by: Shreshtha Kumar Sahu Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-ux500/board-mop500-pins.c | 16 +++++++--- arch/arm/mach-ux500/board-mop500.c | 54 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index fd4cf1ca5efd..70cdbd60596a 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -110,10 +110,18 @@ static pin_cfg_t mop500_pins_common[] = { GPIO168_KP_O0, /* UART */ - GPIO0_U0_CTSn | PIN_INPUT_PULLUP, - GPIO1_U0_RTSn | PIN_OUTPUT_HIGH, - GPIO2_U0_RXD | PIN_INPUT_PULLUP, - GPIO3_U0_TXD | PIN_OUTPUT_HIGH, + /* uart-0 pins gpio configuration should be + * kept intact to prevent glitch in tx line + * when tty dev is opened. Later these pins + * are configured to uart mop500_pins_uart0 + * + * It will be replaced with uart configuration + * once the issue is solved. + */ + GPIO0_GPIO | PIN_INPUT_PULLUP, + GPIO1_GPIO | PIN_OUTPUT_HIGH, + GPIO2_GPIO | PIN_INPUT_PULLUP, + GPIO3_GPIO | PIN_OUTPUT_HIGH, GPIO29_U2_RXD | PIN_INPUT_PULLUP, GPIO30_U2_TXD | PIN_OUTPUT_HIGH, diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index bb26f40493e6..2a08c07dec6d 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -27,18 +27,21 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include #include +#include "pins-db8500.h" #include "ste-dma40-db8500.h" #include "devices-db8500.h" #include "board-mop500.h" @@ -393,12 +396,63 @@ static struct stedma40_chan_cfg uart2_dma_cfg_tx = { }; #endif + +static pin_cfg_t mop500_pins_uart0[] = { + GPIO0_U0_CTSn | PIN_INPUT_PULLUP, + GPIO1_U0_RTSn | PIN_OUTPUT_HIGH, + GPIO2_U0_RXD | PIN_INPUT_PULLUP, + GPIO3_U0_TXD | PIN_OUTPUT_HIGH, +}; + +#define PRCC_K_SOFTRST_SET 0x18 +#define PRCC_K_SOFTRST_CLEAR 0x1C +static void ux500_uart0_reset(void) +{ + void __iomem *prcc_rst_set, *prcc_rst_clr; + + prcc_rst_set = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE + + PRCC_K_SOFTRST_SET); + prcc_rst_clr = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE + + PRCC_K_SOFTRST_CLEAR); + + /* Activate soft reset PRCC_K_SOFTRST_CLEAR */ + writel((readl(prcc_rst_clr) | 0x1), prcc_rst_clr); + udelay(1); + + /* Release soft reset PRCC_K_SOFTRST_SET */ + writel((readl(prcc_rst_set) | 0x1), prcc_rst_set); + udelay(1); +} + +static void ux500_uart0_init(void) +{ + int ret; + + ret = nmk_config_pins(mop500_pins_uart0, + ARRAY_SIZE(mop500_pins_uart0)); + if (ret < 0) + pr_err("pl011: uart pins_enable failed\n"); +} + +static void ux500_uart0_exit(void) +{ + int ret; + + ret = nmk_config_pins_sleep(mop500_pins_uart0, + ARRAY_SIZE(mop500_pins_uart0)); + if (ret < 0) + pr_err("pl011: uart pins_disable failed\n"); +} + static struct amba_pl011_data uart0_plat = { #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, .dma_rx_param = &uart0_dma_cfg_rx, .dma_tx_param = &uart0_dma_cfg_tx, #endif + .init = ux500_uart0_init, + .exit = ux500_uart0_exit, + .reset = ux500_uart0_reset, }; static struct amba_pl011_data uart1_plat = { -- cgit v1.2.3 From 3bc46b312b1486b1fe2db4246a34a30160d26d8d Mon Sep 17 00:00:00 2001 From: Maxime Bizon Date: Fri, 10 Jun 2011 23:17:58 +0200 Subject: serial: bcm63xx_uart: fix irq storm after rx fifo overrun. RX fifo reset is required to clear irq. Signed-off-by: Maxime Bizon Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bcm63xx_uart.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index a1a0e55d0807..c0b68b9cad91 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -250,6 +250,20 @@ static void bcm_uart_do_rx(struct uart_port *port) /* get overrun/fifo empty information from ier * register */ iestat = bcm_uart_readl(port, UART_IR_REG); + + if (unlikely(iestat & UART_IR_STAT(UART_IR_RXOVER))) { + unsigned int val; + + /* fifo reset is required to clear + * interrupt */ + val = bcm_uart_readl(port, UART_CTL_REG); + val |= UART_CTL_RSTRXFIFO_MASK; + bcm_uart_writel(port, val, UART_CTL_REG); + + port->icount.overrun++; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + } + if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY))) break; @@ -284,10 +298,6 @@ static void bcm_uart_do_rx(struct uart_port *port) if (uart_handle_sysrq_char(port, c)) continue; - if (unlikely(iestat & UART_IR_STAT(UART_IR_RXOVER))) { - port->icount.overrun++; - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } if ((cstat & port->ignore_status_mask) == 0) tty_insert_flip_char(tty, c, flag); -- cgit v1.2.3 From 0ec5258d68c626922d92e2f0e4e5c689e5360a5d Mon Sep 17 00:00:00 2001 From: Torsten Schenk Date: Thu, 16 Jun 2011 21:06:27 +0200 Subject: ALSA: 6fire - Fix signedness bug Fixed remaining issues of the signedness bug discovered by Dan Carpenter. A check was remaining that tests if unsigned rt->rate is >= 0. Changed that so that rt->rate now consistently uses ARRAY_SIZE(rates) as invalid rate value and not -1. Signed-off-by: Torsten Schenk Signed-off-by: Takashi Iwai --- sound/usb/6fire/pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index b137b25865cc..d144cdb2f159 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -395,12 +395,12 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub) alsa_rt->hw = pcm_hw; if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (rt->rate >= 0) + if (rt->rate < ARRAY_SIZE(rates)) alsa_rt->hw.rates = rates_alsaid[rt->rate]; alsa_rt->hw.channels_max = OUT_N_CHANNELS; sub = &rt->playback; } else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) { - if (rt->rate >= 0) + if (rt->rate < ARRAY_SIZE(rates)) alsa_rt->hw.rates = rates_alsaid[rt->rate]; alsa_rt->hw.channels_max = IN_N_CHANNELS; sub = &rt->capture; -- cgit v1.2.3 From 46a310b80bc2c9ccc019649c9da91194cbc10944 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Jun 2011 15:36:38 -0400 Subject: [CPUFREQ] Don't set stat->last_index to -1 if the pol->cur has incorrect value. If the driver submitted an non-existing pol>cur value (say it used the default initialized value of zero), when the cpufreq stats tries to setup its initial values it incorrectly sets stat->last_index to -1 (or 0xfffff...). And cpufreq_stats_update tries to update at that index location and fails. This can be caused by: stat->last_index = freq_table_get_index(stat, policy->cur); not finding the appropiate frequency in the table (b/c the policy->cur is wrong) and we end up crashing. The fix however is concentrated in the 'cpufreq_stats_update' as the last_index (and old_index) are updated there. Which means it can reset the last_index to -1 again and on the next iteration cause a crash. Without this patch, the following crash is observed: powernow-k8: Found 1 AMD Athlon(tm) 64 Processor 3700+ (1 cpu cores) (version 2.20.00) powernow-k8: fid 0x2 (1000 MHz), vid 0x12 powernow-k8: fid 0xa (1800 MHz), vid 0xa powernow-k8: fid 0xc (2000 MHz), vid 0x8 powernow-k8: fid 0xe (2200 MHz), vid 0x8 Marking TSC unstable due to cpufreq changes powernow-k8: fid trans failed, fid 0x2, curr 0x0 BUG: unable to handle kernel paging request at ffff880807e07b78 IP: [] cpufreq_stats_update+0x46/0x5b .. snip.. Pid: 1, comm: swapper Not tainted 3.0.0-rc2 #45 MICRO-STAR INTERNATIONAL CO., LTD MS-7094/MS-7094 ..snip.. Call Trace: [] cpufreq_stat_notifier_trans+0x48/0x7c [] notifier_call_chain+0x32/0x5e [] __srcu_notifier_call_chain+0x47/0x63 [] srcu_notifier_call_chain+0xf/0x11 [] cpufreq_notify_transition+0x111/0x134 [] powernowk8_target+0x53b/0x617 [] __cpufreq_driver_target+0x2e/0x30 [] cpufreq_governor_dbs+0x339/0x356 [] __cpufreq_governor+0xa8/0xe9 [] __cpufreq_set_policy+0x132/0x13e [] cpufreq_add_dev_interface+0x272/0x28c Reported-by: Tobias Diedrich Tested-by: Tobias Diedrich Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 853f92d23ddb..faf7c5217848 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -298,11 +298,13 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb, old_index = stat->last_index; new_index = freq_table_get_index(stat, freq->new); - cpufreq_stats_update(freq->cpu); - if (old_index == new_index) + /* We can't do stat->time_in_state[-1]= .. */ + if (old_index == -1 || new_index == -1) return 0; - if (old_index == -1 || new_index == -1) + cpufreq_stats_update(freq->cpu); + + if (old_index == new_index) return 0; spin_lock(&cpufreq_stats_lock); -- cgit v1.2.3 From a9d3d2068064b7a6395871a49616d3784f802d50 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Jun 2011 15:36:39 -0400 Subject: [CPUFREQ] powernow-k8: Don't notify of successful transition if we failed (vid case). Before this patch if we failed the vid transition would still try to submit the "new" frequencies to cpufreq. That is incorrect - also we could submit a non-existing frequency value which would cause cpufreq to crash. The ultimate fix is in cpufreq to deal with incorrect values, but this patch improves the error recovery in the AMD powernowk8 driver. The failure that was reported was as follows: powernow-k8: Found 1 AMD Athlon(tm) 64 Processor 3700+ (1 cpu cores) (version 2.20.00) powernow-k8: fid 0x2 (1000 MHz), vid 0x12 powernow-k8: fid 0xa (1800 MHz), vid 0xa powernow-k8: fid 0xc (2000 MHz), vid 0x8 powernow-k8: fid 0xe (2200 MHz), vid 0x8 Marking TSC unstable due to cpufreq changes powernow-k8: fid trans failed, fid 0x2, curr 0x0 BUG: unable to handle kernel paging request at ffff880807e07b78 IP: [] cpufreq_stats_update+0x46/0x5b ... And transition fails and data->currfid ends up with 0. Since the machine does not support 800Mhz value when the calculation is done ('find_khz_freq_from_fid(data->currfid);') it reports the new frequency as 800000 which is bogus. This patch fixes the issue during target setting. The patch however does not fix the issue in 'powernowk8_cpu_init' where the pol->cur can also be set with the 800000 value: pol->cur = find_khz_freq_from_fid(data->currfid); dprintk("policy current frequency %d kHz\n", pol->cur); /* min/max the cpu is capable of */ if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) { The fix for that looks to update cpufreq_frequency_table_cpuinfo to check pol->cur.... but that would cause an regression in how the acpi-cpufreq driver works (it sets cpu->cur after calling cpufreq_frequency_table_cpuinfo). Instead the fix will be to let cpufreq gracefully handle bogus data (another patch). Acked-by: Borislav Petkov CC: andre.przywara@amd.com CC: Mark.Langsdorf@amd.com Reported-by: Tobias Diedrich Tested-by: Tobias Diedrich [v1: Rebased on v3.0-rc2, reduced patch to deal with vid case] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Dave Jones --- drivers/cpufreq/powernow-k8.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 83479b6fb9a1..287c56f6749a 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1079,6 +1079,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, } res = transition_fid_vid(data, fid, vid); + if (res) + return res; + freqs.new = find_khz_freq_from_fid(data->currfid); for_each_cpu(i, data->available_cores) { -- cgit v1.2.3 From fbb5b89eabea5ae7d621b7861863159560d8faa4 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Jun 2011 15:36:40 -0400 Subject: [CPUFREQ] powernow-k8: Don't try to transition if the pstate is incorrect This patch augments the pstate transition code to error out (instead of returning 0) when an incorrect pstate is provided. Suggested-by: Borislav Petkov CC: andre.przywara@amd.com CC: Mark.Langsdorf@amd.com Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Dave Jones --- drivers/cpufreq/powernow-k8.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 287c56f6749a..bce576d7478e 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1104,7 +1104,8 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, /* get MSR index for hardware pstate transition */ pstate = index & HW_PSTATE_MASK; if (pstate > data->max_hw_pstate) - return 0; + return -EINVAL; + freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate); -- cgit v1.2.3 From 99a15e21d96f6857dafab1e5167e5e8183215c9c Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 16 Jun 2011 12:56:19 -0700 Subject: migrate: don't account swapcache as shmem swapcache will reach the below code path in migrate_page_move_mapping, and swapcache is accounted as NR_FILE_PAGES but it's not accounted as NR_SHMEM. Hugh pointed out we must use PageSwapCache instead of comparing mapping to &swapper_space, to avoid build failure with CONFIG_SWAP=n. Signed-off-by: Andrea Arcangeli Acked-by: Hugh Dickins Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- mm/migrate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/migrate.c b/mm/migrate.c index e4a5c912983d..666e4e677414 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -288,7 +288,7 @@ static int migrate_page_move_mapping(struct address_space *mapping, */ __dec_zone_page_state(page, NR_FILE_PAGES); __inc_zone_page_state(newpage, NR_FILE_PAGES); - if (PageSwapBacked(page)) { + if (!PageSwapCache(page) && PageSwapBacked(page)) { __dec_zone_page_state(page, NR_SHMEM); __inc_zone_page_state(newpage, NR_SHMEM); } -- cgit v1.2.3 From f8b7fc6b514f34a51875dd48dff70d4d17a54f38 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 16 Jun 2011 08:26:32 -0700 Subject: rcu: Move RCU_BOOST #ifdefs to header file The commit "use softirq instead of kthreads except when RCU_BOOST=y" just applied #ifdef in place. This commit is a cleanup that moves the newly #ifdef'ed code to the header file kernel/rcutree_plugin.h. Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney --- kernel/rcutree.c | 383 +---------------------------------------------- kernel/rcutree.h | 5 + kernel/rcutree_plugin.h | 384 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 390 insertions(+), 382 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 429d4949f0eb..7e59ffb3d0ba 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1093,16 +1093,8 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) int need_report = 0; struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu); struct rcu_node *rnp; -#ifdef CONFIG_RCU_BOOST - struct task_struct *t; - /* Stop the CPU's kthread. */ - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (t != NULL) { - per_cpu(rcu_cpu_kthread_task, cpu) = NULL; - kthread_stop(t); - } -#endif /* #ifdef CONFIG_RCU_BOOST */ + rcu_stop_cpu_kthread(cpu); /* Exclude any attempts to start a new grace period. */ raw_spin_lock_irqsave(&rsp->onofflock, flags); @@ -1453,17 +1445,6 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) invoke_rcu_callbacks(rsp, rdp); } -#ifdef CONFIG_RCU_BOOST - -static void rcu_kthread_do_work(void) -{ - rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); - rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); - rcu_preempt_do_callbacks(); -} - -#endif /* #ifdef CONFIG_RCU_BOOST */ - /* * Do softirq processing for the current CPU. */ @@ -1498,345 +1479,6 @@ static void invoke_rcu_core(void) raise_softirq(RCU_SOFTIRQ); } -#ifdef CONFIG_RCU_BOOST - -/* - * Wake up the specified per-rcu_node-structure kthread. - * Because the per-rcu_node kthreads are immortal, we don't need - * to do anything to keep them alive. - */ -static void invoke_rcu_node_kthread(struct rcu_node *rnp) -{ - struct task_struct *t; - - t = rnp->node_kthread_task; - if (t != NULL) - wake_up_process(t); -} - -/* - * Set the specified CPU's kthread to run RT or not, as specified by - * the to_rt argument. The CPU-hotplug locks are held, so the task - * is not going away. - */ -static void rcu_cpu_kthread_setrt(int cpu, int to_rt) -{ - int policy; - struct sched_param sp; - struct task_struct *t; - - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (t == NULL) - return; - if (to_rt) { - policy = SCHED_FIFO; - sp.sched_priority = RCU_KTHREAD_PRIO; - } else { - policy = SCHED_NORMAL; - sp.sched_priority = 0; - } - sched_setscheduler_nocheck(t, policy, &sp); -} - -/* - * Timer handler to initiate the waking up of per-CPU kthreads that - * have yielded the CPU due to excess numbers of RCU callbacks. - * We wake up the per-rcu_node kthread, which in turn will wake up - * the booster kthread. - */ -static void rcu_cpu_kthread_timer(unsigned long arg) -{ - struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg); - struct rcu_node *rnp = rdp->mynode; - - atomic_or(rdp->grpmask, &rnp->wakemask); - invoke_rcu_node_kthread(rnp); -} - -/* - * Drop to non-real-time priority and yield, but only after posting a - * timer that will cause us to regain our real-time priority if we - * remain preempted. Either way, we restore our real-time priority - * before returning. - */ -static void rcu_yield(void (*f)(unsigned long), unsigned long arg) -{ - struct sched_param sp; - struct timer_list yield_timer; - - setup_timer_on_stack(&yield_timer, f, arg); - mod_timer(&yield_timer, jiffies + 2); - sp.sched_priority = 0; - sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp); - set_user_nice(current, 19); - schedule(); - sp.sched_priority = RCU_KTHREAD_PRIO; - sched_setscheduler_nocheck(current, SCHED_FIFO, &sp); - del_timer(&yield_timer); -} - -/* - * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU. - * This can happen while the corresponding CPU is either coming online - * or going offline. We cannot wait until the CPU is fully online - * before starting the kthread, because the various notifier functions - * can wait for RCU grace periods. So we park rcu_cpu_kthread() until - * the corresponding CPU is online. - * - * Return 1 if the kthread needs to stop, 0 otherwise. - * - * Caller must disable bh. This function can momentarily enable it. - */ -static int rcu_cpu_kthread_should_stop(int cpu) -{ - while (cpu_is_offline(cpu) || - !cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu)) || - smp_processor_id() != cpu) { - if (kthread_should_stop()) - return 1; - per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU; - per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id(); - local_bh_enable(); - schedule_timeout_uninterruptible(1); - if (!cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu))) - set_cpus_allowed_ptr(current, cpumask_of(cpu)); - local_bh_disable(); - } - per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; - return 0; -} - -/* - * Per-CPU kernel thread that invokes RCU callbacks. This replaces the - * earlier RCU softirq. - */ -static int rcu_cpu_kthread(void *arg) -{ - int cpu = (int)(long)arg; - unsigned long flags; - int spincnt = 0; - unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu); - char work; - char *workp = &per_cpu(rcu_cpu_has_work, cpu); - - for (;;) { - *statusp = RCU_KTHREAD_WAITING; - rcu_wait(*workp != 0 || kthread_should_stop()); - local_bh_disable(); - if (rcu_cpu_kthread_should_stop(cpu)) { - local_bh_enable(); - break; - } - *statusp = RCU_KTHREAD_RUNNING; - per_cpu(rcu_cpu_kthread_loops, cpu)++; - local_irq_save(flags); - work = *workp; - *workp = 0; - local_irq_restore(flags); - if (work) - rcu_kthread_do_work(); - local_bh_enable(); - if (*workp != 0) - spincnt++; - else - spincnt = 0; - if (spincnt > 10) { - *statusp = RCU_KTHREAD_YIELDING; - rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu); - spincnt = 0; - } - } - *statusp = RCU_KTHREAD_STOPPED; - return 0; -} - -/* - * Spawn a per-CPU kthread, setting up affinity and priority. - * Because the CPU hotplug lock is held, no other CPU will be attempting - * to manipulate rcu_cpu_kthread_task. There might be another CPU - * attempting to access it during boot, but the locking in kthread_bind() - * will enforce sufficient ordering. - * - * Please note that we cannot simply refuse to wake up the per-CPU - * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state, - * which can result in softlockup complaints if the task ends up being - * idle for more than a couple of minutes. - * - * However, please note also that we cannot bind the per-CPU kthread to its - * CPU until that CPU is fully online. We also cannot wait until the - * CPU is fully online before we create its per-CPU kthread, as this would - * deadlock the system when CPU notifiers tried waiting for grace - * periods. So we bind the per-CPU kthread to its CPU only if the CPU - * is online. If its CPU is not yet fully online, then the code in - * rcu_cpu_kthread() will wait until it is fully online, and then do - * the binding. - */ -static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) -{ - struct sched_param sp; - struct task_struct *t; - - if (!rcu_kthreads_spawnable || - per_cpu(rcu_cpu_kthread_task, cpu) != NULL) - return 0; - t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu); - if (IS_ERR(t)) - return PTR_ERR(t); - if (cpu_online(cpu)) - kthread_bind(t, cpu); - per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; - WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL); - sp.sched_priority = RCU_KTHREAD_PRIO; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); - per_cpu(rcu_cpu_kthread_task, cpu) = t; - wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */ - return 0; -} - -/* - * Per-rcu_node kthread, which is in charge of waking up the per-CPU - * kthreads when needed. We ignore requests to wake up kthreads - * for offline CPUs, which is OK because force_quiescent_state() - * takes care of this case. - */ -static int rcu_node_kthread(void *arg) -{ - int cpu; - unsigned long flags; - unsigned long mask; - struct rcu_node *rnp = (struct rcu_node *)arg; - struct sched_param sp; - struct task_struct *t; - - for (;;) { - rnp->node_kthread_status = RCU_KTHREAD_WAITING; - rcu_wait(atomic_read(&rnp->wakemask) != 0); - rnp->node_kthread_status = RCU_KTHREAD_RUNNING; - raw_spin_lock_irqsave(&rnp->lock, flags); - mask = atomic_xchg(&rnp->wakemask, 0); - rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */ - for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) { - if ((mask & 0x1) == 0) - continue; - preempt_disable(); - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (!cpu_online(cpu) || t == NULL) { - preempt_enable(); - continue; - } - per_cpu(rcu_cpu_has_work, cpu) = 1; - sp.sched_priority = RCU_KTHREAD_PRIO; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); - preempt_enable(); - } - } - /* NOTREACHED */ - rnp->node_kthread_status = RCU_KTHREAD_STOPPED; - return 0; -} - -/* - * Set the per-rcu_node kthread's affinity to cover all CPUs that are - * served by the rcu_node in question. The CPU hotplug lock is still - * held, so the value of rnp->qsmaskinit will be stable. - * - * We don't include outgoingcpu in the affinity set, use -1 if there is - * no outgoing CPU. If there are no CPUs left in the affinity set, - * this function allows the kthread to execute on any CPU. - */ -static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) -{ - cpumask_var_t cm; - int cpu; - unsigned long mask = rnp->qsmaskinit; - - if (rnp->node_kthread_task == NULL) - return; - if (!alloc_cpumask_var(&cm, GFP_KERNEL)) - return; - cpumask_clear(cm); - for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) - if ((mask & 0x1) && cpu != outgoingcpu) - cpumask_set_cpu(cpu, cm); - if (cpumask_weight(cm) == 0) { - cpumask_setall(cm); - for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++) - cpumask_clear_cpu(cpu, cm); - WARN_ON_ONCE(cpumask_weight(cm) == 0); - } - set_cpus_allowed_ptr(rnp->node_kthread_task, cm); - rcu_boost_kthread_setaffinity(rnp, cm); - free_cpumask_var(cm); -} - -/* - * Spawn a per-rcu_node kthread, setting priority and affinity. - * Called during boot before online/offline can happen, or, if - * during runtime, with the main CPU-hotplug locks held. So only - * one of these can be executing at a time. - */ -static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp, - struct rcu_node *rnp) -{ - unsigned long flags; - int rnp_index = rnp - &rsp->node[0]; - struct sched_param sp; - struct task_struct *t; - - if (!rcu_kthreads_spawnable || - rnp->qsmaskinit == 0) - return 0; - if (rnp->node_kthread_task == NULL) { - t = kthread_create(rcu_node_kthread, (void *)rnp, - "rcun%d", rnp_index); - if (IS_ERR(t)) - return PTR_ERR(t); - raw_spin_lock_irqsave(&rnp->lock, flags); - rnp->node_kthread_task = t; - raw_spin_unlock_irqrestore(&rnp->lock, flags); - sp.sched_priority = 99; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); - wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ - } - return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index); -} - -/* - * Spawn all kthreads -- called as soon as the scheduler is running. - */ -static int __init rcu_spawn_kthreads(void) -{ - int cpu; - struct rcu_node *rnp; - - rcu_kthreads_spawnable = 1; - for_each_possible_cpu(cpu) { - per_cpu(rcu_cpu_has_work, cpu) = 0; - if (cpu_online(cpu)) - (void)rcu_spawn_one_cpu_kthread(cpu); - } - rnp = rcu_get_root(rcu_state); - (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - if (NUM_RCU_NODES > 1) { - rcu_for_each_leaf_node(rcu_state, rnp) - (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - } - return 0; -} -early_initcall(rcu_spawn_kthreads); - -#else /* #ifdef CONFIG_RCU_BOOST */ - -static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) -{ -} - -static void rcu_cpu_kthread_setrt(int cpu, int to_rt) -{ -} - -#endif /* #else #ifdef CONFIG_RCU_BOOST */ - static void __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), struct rcu_state *rsp) @@ -2243,29 +1885,6 @@ static void __cpuinit rcu_prepare_cpu(int cpu) rcu_preempt_init_percpu_data(cpu); } -#ifdef CONFIG_RCU_BOOST - -static void __cpuinit rcu_prepare_kthreads(int cpu) -{ - struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); - struct rcu_node *rnp = rdp->mynode; - - /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */ - if (rcu_kthreads_spawnable) { - (void)rcu_spawn_one_cpu_kthread(cpu); - if (rnp->node_kthread_task == NULL) - (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - } -} - -#else /* #ifdef CONFIG_RCU_BOOST */ - -static void __cpuinit rcu_prepare_kthreads(int cpu) -{ -} - -#endif /* #else #ifdef CONFIG_RCU_BOOST */ - /* * Handle CPU online/offline notification events. */ diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 434288c7ad88..01b2ccda26fb 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -427,6 +427,7 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp); #ifdef CONFIG_HOTPLUG_CPU static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags); +static void rcu_stop_cpu_kthread(int cpu); #endif /* #ifdef CONFIG_HOTPLUG_CPU */ static void rcu_print_detail_task_stall(struct rcu_state *rsp); static void rcu_print_task_stall(struct rcu_node *rnp); @@ -460,6 +461,10 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp, int rnp_index); +static void invoke_rcu_node_kthread(struct rcu_node *rnp); +static void rcu_yield(void (*f)(unsigned long), unsigned long arg); #endif /* #ifdef CONFIG_RCU_BOOST */ +static void rcu_cpu_kthread_setrt(int cpu, int to_rt); +static void __cpuinit rcu_prepare_kthreads(int cpu); #endif /* #ifndef RCU_TREE_NONCORE */ diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 2772386c0421..14dc7dd00902 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1330,6 +1330,370 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, return 0; } +#ifdef CONFIG_HOTPLUG_CPU + +/* + * Stop the RCU's per-CPU kthread when its CPU goes offline,. + */ +static void rcu_stop_cpu_kthread(int cpu) +{ + struct task_struct *t; + + /* Stop the CPU's kthread. */ + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (t != NULL) { + per_cpu(rcu_cpu_kthread_task, cpu) = NULL; + kthread_stop(t); + } +} + +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ + +static void rcu_kthread_do_work(void) +{ + rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); + rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); + rcu_preempt_do_callbacks(); +} + +/* + * Wake up the specified per-rcu_node-structure kthread. + * Because the per-rcu_node kthreads are immortal, we don't need + * to do anything to keep them alive. + */ +static void invoke_rcu_node_kthread(struct rcu_node *rnp) +{ + struct task_struct *t; + + t = rnp->node_kthread_task; + if (t != NULL) + wake_up_process(t); +} + +/* + * Set the specified CPU's kthread to run RT or not, as specified by + * the to_rt argument. The CPU-hotplug locks are held, so the task + * is not going away. + */ +static void rcu_cpu_kthread_setrt(int cpu, int to_rt) +{ + int policy; + struct sched_param sp; + struct task_struct *t; + + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (t == NULL) + return; + if (to_rt) { + policy = SCHED_FIFO; + sp.sched_priority = RCU_KTHREAD_PRIO; + } else { + policy = SCHED_NORMAL; + sp.sched_priority = 0; + } + sched_setscheduler_nocheck(t, policy, &sp); +} + +/* + * Timer handler to initiate the waking up of per-CPU kthreads that + * have yielded the CPU due to excess numbers of RCU callbacks. + * We wake up the per-rcu_node kthread, which in turn will wake up + * the booster kthread. + */ +static void rcu_cpu_kthread_timer(unsigned long arg) +{ + struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg); + struct rcu_node *rnp = rdp->mynode; + + atomic_or(rdp->grpmask, &rnp->wakemask); + invoke_rcu_node_kthread(rnp); +} + +/* + * Drop to non-real-time priority and yield, but only after posting a + * timer that will cause us to regain our real-time priority if we + * remain preempted. Either way, we restore our real-time priority + * before returning. + */ +static void rcu_yield(void (*f)(unsigned long), unsigned long arg) +{ + struct sched_param sp; + struct timer_list yield_timer; + + setup_timer_on_stack(&yield_timer, f, arg); + mod_timer(&yield_timer, jiffies + 2); + sp.sched_priority = 0; + sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp); + set_user_nice(current, 19); + schedule(); + sp.sched_priority = RCU_KTHREAD_PRIO; + sched_setscheduler_nocheck(current, SCHED_FIFO, &sp); + del_timer(&yield_timer); +} + +/* + * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU. + * This can happen while the corresponding CPU is either coming online + * or going offline. We cannot wait until the CPU is fully online + * before starting the kthread, because the various notifier functions + * can wait for RCU grace periods. So we park rcu_cpu_kthread() until + * the corresponding CPU is online. + * + * Return 1 if the kthread needs to stop, 0 otherwise. + * + * Caller must disable bh. This function can momentarily enable it. + */ +static int rcu_cpu_kthread_should_stop(int cpu) +{ + while (cpu_is_offline(cpu) || + !cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu)) || + smp_processor_id() != cpu) { + if (kthread_should_stop()) + return 1; + per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU; + per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id(); + local_bh_enable(); + schedule_timeout_uninterruptible(1); + if (!cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu))) + set_cpus_allowed_ptr(current, cpumask_of(cpu)); + local_bh_disable(); + } + per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; + return 0; +} + +/* + * Per-CPU kernel thread that invokes RCU callbacks. This replaces the + * earlier RCU softirq. + */ +static int rcu_cpu_kthread(void *arg) +{ + int cpu = (int)(long)arg; + unsigned long flags; + int spincnt = 0; + unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu); + char work; + char *workp = &per_cpu(rcu_cpu_has_work, cpu); + + for (;;) { + *statusp = RCU_KTHREAD_WAITING; + rcu_wait(*workp != 0 || kthread_should_stop()); + local_bh_disable(); + if (rcu_cpu_kthread_should_stop(cpu)) { + local_bh_enable(); + break; + } + *statusp = RCU_KTHREAD_RUNNING; + per_cpu(rcu_cpu_kthread_loops, cpu)++; + local_irq_save(flags); + work = *workp; + *workp = 0; + local_irq_restore(flags); + if (work) + rcu_kthread_do_work(); + local_bh_enable(); + if (*workp != 0) + spincnt++; + else + spincnt = 0; + if (spincnt > 10) { + *statusp = RCU_KTHREAD_YIELDING; + rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu); + spincnt = 0; + } + } + *statusp = RCU_KTHREAD_STOPPED; + return 0; +} + +/* + * Spawn a per-CPU kthread, setting up affinity and priority. + * Because the CPU hotplug lock is held, no other CPU will be attempting + * to manipulate rcu_cpu_kthread_task. There might be another CPU + * attempting to access it during boot, but the locking in kthread_bind() + * will enforce sufficient ordering. + * + * Please note that we cannot simply refuse to wake up the per-CPU + * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state, + * which can result in softlockup complaints if the task ends up being + * idle for more than a couple of minutes. + * + * However, please note also that we cannot bind the per-CPU kthread to its + * CPU until that CPU is fully online. We also cannot wait until the + * CPU is fully online before we create its per-CPU kthread, as this would + * deadlock the system when CPU notifiers tried waiting for grace + * periods. So we bind the per-CPU kthread to its CPU only if the CPU + * is online. If its CPU is not yet fully online, then the code in + * rcu_cpu_kthread() will wait until it is fully online, and then do + * the binding. + */ +static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) +{ + struct sched_param sp; + struct task_struct *t; + + if (!rcu_kthreads_spawnable || + per_cpu(rcu_cpu_kthread_task, cpu) != NULL) + return 0; + t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu); + if (IS_ERR(t)) + return PTR_ERR(t); + if (cpu_online(cpu)) + kthread_bind(t, cpu); + per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; + WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL); + sp.sched_priority = RCU_KTHREAD_PRIO; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + per_cpu(rcu_cpu_kthread_task, cpu) = t; + wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */ + return 0; +} + +/* + * Per-rcu_node kthread, which is in charge of waking up the per-CPU + * kthreads when needed. We ignore requests to wake up kthreads + * for offline CPUs, which is OK because force_quiescent_state() + * takes care of this case. + */ +static int rcu_node_kthread(void *arg) +{ + int cpu; + unsigned long flags; + unsigned long mask; + struct rcu_node *rnp = (struct rcu_node *)arg; + struct sched_param sp; + struct task_struct *t; + + for (;;) { + rnp->node_kthread_status = RCU_KTHREAD_WAITING; + rcu_wait(atomic_read(&rnp->wakemask) != 0); + rnp->node_kthread_status = RCU_KTHREAD_RUNNING; + raw_spin_lock_irqsave(&rnp->lock, flags); + mask = atomic_xchg(&rnp->wakemask, 0); + rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */ + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) { + if ((mask & 0x1) == 0) + continue; + preempt_disable(); + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (!cpu_online(cpu) || t == NULL) { + preempt_enable(); + continue; + } + per_cpu(rcu_cpu_has_work, cpu) = 1; + sp.sched_priority = RCU_KTHREAD_PRIO; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + preempt_enable(); + } + } + /* NOTREACHED */ + rnp->node_kthread_status = RCU_KTHREAD_STOPPED; + return 0; +} + +/* + * Set the per-rcu_node kthread's affinity to cover all CPUs that are + * served by the rcu_node in question. The CPU hotplug lock is still + * held, so the value of rnp->qsmaskinit will be stable. + * + * We don't include outgoingcpu in the affinity set, use -1 if there is + * no outgoing CPU. If there are no CPUs left in the affinity set, + * this function allows the kthread to execute on any CPU. + */ +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +{ + cpumask_var_t cm; + int cpu; + unsigned long mask = rnp->qsmaskinit; + + if (rnp->node_kthread_task == NULL) + return; + if (!alloc_cpumask_var(&cm, GFP_KERNEL)) + return; + cpumask_clear(cm); + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) + if ((mask & 0x1) && cpu != outgoingcpu) + cpumask_set_cpu(cpu, cm); + if (cpumask_weight(cm) == 0) { + cpumask_setall(cm); + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++) + cpumask_clear_cpu(cpu, cm); + WARN_ON_ONCE(cpumask_weight(cm) == 0); + } + set_cpus_allowed_ptr(rnp->node_kthread_task, cm); + rcu_boost_kthread_setaffinity(rnp, cm); + free_cpumask_var(cm); +} + +/* + * Spawn a per-rcu_node kthread, setting priority and affinity. + * Called during boot before online/offline can happen, or, if + * during runtime, with the main CPU-hotplug locks held. So only + * one of these can be executing at a time. + */ +static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp, + struct rcu_node *rnp) +{ + unsigned long flags; + int rnp_index = rnp - &rsp->node[0]; + struct sched_param sp; + struct task_struct *t; + + if (!rcu_kthreads_spawnable || + rnp->qsmaskinit == 0) + return 0; + if (rnp->node_kthread_task == NULL) { + t = kthread_create(rcu_node_kthread, (void *)rnp, + "rcun%d", rnp_index); + if (IS_ERR(t)) + return PTR_ERR(t); + raw_spin_lock_irqsave(&rnp->lock, flags); + rnp->node_kthread_task = t; + raw_spin_unlock_irqrestore(&rnp->lock, flags); + sp.sched_priority = 99; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ + } + return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index); +} + +/* + * Spawn all kthreads -- called as soon as the scheduler is running. + */ +static int __init rcu_spawn_kthreads(void) +{ + int cpu; + struct rcu_node *rnp; + + rcu_kthreads_spawnable = 1; + for_each_possible_cpu(cpu) { + per_cpu(rcu_cpu_has_work, cpu) = 0; + if (cpu_online(cpu)) + (void)rcu_spawn_one_cpu_kthread(cpu); + } + rnp = rcu_get_root(rcu_state); + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); + if (NUM_RCU_NODES > 1) { + rcu_for_each_leaf_node(rcu_state, rnp) + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); + } + return 0; +} +early_initcall(rcu_spawn_kthreads); + +static void __cpuinit rcu_prepare_kthreads(int cpu) +{ + struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); + struct rcu_node *rnp = rdp->mynode; + + /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */ + if (rcu_kthreads_spawnable) { + (void)rcu_spawn_one_cpu_kthread(cpu); + if (rnp->node_kthread_task == NULL) + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); + } +} + #else /* #ifdef CONFIG_RCU_BOOST */ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) @@ -1346,6 +1710,26 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) { } +#ifdef CONFIG_HOTPLUG_CPU + +static void rcu_stop_cpu_kthread(int cpu) +{ +} + +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ + +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +{ +} + +static void rcu_cpu_kthread_setrt(int cpu, int to_rt) +{ +} + +static void __cpuinit rcu_prepare_kthreads(int cpu) +{ +} + #endif /* #else #ifdef CONFIG_RCU_BOOST */ #ifndef CONFIG_SMP -- cgit v1.2.3 From 826c7e4147f902737b281e8a5a7d7aa33fd63316 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 4 Jun 2011 19:34:56 +0000 Subject: Revert "drm/i915: Enable GMBUS for post-gen2 chipsets" Revert commit 8f9a3f9b63b8cd3f03be9dc53533f90bd4120e5f. This fixes a hang when loading the eeprom driver (see bug #35572.) GMBUS will be re-enabled later, differently. Signed-off-by: Jean Delvare Reported-by: Marek Otahal Tested-by: Yermandu Patapitafious Tested-by: Andrew Lutomirski Acked-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/intel_i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index d3b903bce7c5..d98cee60b602 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -401,8 +401,7 @@ int intel_setup_gmbus(struct drm_device *dev) bus->reg0 = i | GMBUS_RATE_100KHZ; /* XXX force bit banging until GMBUS is fully debugged */ - if (IS_GEN2(dev)) - bus->force_bit = intel_gpio_create(dev_priv, i); + bus->force_bit = intel_gpio_create(dev_priv, i); } intel_i2c_reset(dev_priv->dev); -- cgit v1.2.3 From ba7e05e95880ad80f012555fb8e925cb1f9a5d63 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Jun 2011 18:14:22 +0000 Subject: drm/radeon/kms: fix num crtcs for Cedar and Caicos Only support 4 rather than 6. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_asic.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 9bd162fc9b0c..b2449629537d 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = { int radeon_asic_init(struct radeon_device *rdev) { radeon_register_accessor_init(rdev); + + /* set the number of crtcs */ + if (rdev->flags & RADEON_SINGLE_CRTC) + rdev->num_crtc = 1; + else + rdev->num_crtc = 2; + switch (rdev->family) { case CHIP_R100: case CHIP_RV100: @@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev) case CHIP_JUNIPER: case CHIP_CYPRESS: case CHIP_HEMLOCK: + /* set num crtcs */ + if (rdev->family == CHIP_CEDAR) + rdev->num_crtc = 4; + else + rdev->num_crtc = 6; rdev->asic = &evergreen_asic; break; case CHIP_PALM: @@ -1027,10 +1039,17 @@ int radeon_asic_init(struct radeon_device *rdev) case CHIP_BARTS: case CHIP_TURKS: case CHIP_CAICOS: + /* set num crtcs */ + if (rdev->family == CHIP_CAICOS) + rdev->num_crtc = 4; + else + rdev->num_crtc = 6; rdev->asic = &btc_asic; break; case CHIP_CAYMAN: rdev->asic = &cayman_asic; + /* set num crtcs */ + rdev->num_crtc = 6; break; default: /* FIXME: not supported yet */ @@ -1042,18 +1061,6 @@ int radeon_asic_init(struct radeon_device *rdev) rdev->asic->set_memory_clock = NULL; } - /* set the number of crtcs */ - if (rdev->flags & RADEON_SINGLE_CRTC) - rdev->num_crtc = 1; - else { - if (ASIC_IS_DCE41(rdev)) - rdev->num_crtc = 2; - else if (ASIC_IS_DCE4(rdev)) - rdev->num_crtc = 6; - else - rdev->num_crtc = 2; - } - return 0; } -- cgit v1.2.3 From fbb87773655e7b0292756f9533c3fc21aca0797f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:31 -0400 Subject: drm/radeon/kms: rework atombios_get_encoder_mode() This should give us more reliable results if the table is called before an active device is set. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 03f124d626c2..39fa2258f235 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -660,21 +660,16 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if (radeon_encoder_is_dp_bridge(encoder)) return ATOM_ENCODER_MODE_DP; + /* DVO is always DVO */ + if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO) + return ATOM_ENCODER_MODE_DVO; + connector = radeon_get_connector_for_encoder(encoder); - if (!connector) { - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: - return ATOM_ENCODER_MODE_DVI; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: - default: - return ATOM_ENCODER_MODE_CRT; - } - } + /* if we don't have an active device yet, just use one of + * the connectors tied to the encoder. + */ + if (!connector) + connector = radeon_get_connector_for_encoder_init(encoder); radeon_connector = to_radeon_connector(connector); switch (connector->connector_type) { -- cgit v1.2.3 From 7ec478f835a391d27491493ebfd91f2bed98dbd9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:32 -0400 Subject: drm/radeon/kms: add missing external encoder action required for ddc. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 49611e2365d9..1b50ad8919d5 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -1200,6 +1200,7 @@ typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF 0x10 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING 0x11 #define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION 0x12 +#define EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP 0x14 // ucConfig #define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 -- cgit v1.2.3 From d629a3ceb4fc1ab5aab737b964100d114aba1173 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:33 -0400 Subject: drm/radeon/kms: add support for load detection on dp bridges dp to vga bridges for example. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 20 ++++++++++++ drivers/gpu/drm/radeon/radeon_encoders.c | 49 +++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index c04e18ee8a87..dc7852b3c5ca 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1235,6 +1235,16 @@ radeon_dp_detect(struct drm_connector *connector, bool force) ret = connector_status_connected; } } + + if ((ret == connector_status_disconnected) && + radeon_connector->dac_load_detect) { + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + struct drm_encoder_helper_funcs *encoder_funcs; + if (encoder) { + encoder_funcs = encoder->helper_private; + ret = encoder_funcs->detect(encoder, connector); + } + } } radeon_connector_update_scratch_regs(connector, ret); @@ -1408,6 +1418,10 @@ radeon_add_atom_connector(struct drm_device *dev, default: connector->interlace_allowed = true; connector->doublescan_allowed = true; + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); break; case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVID: @@ -1429,6 +1443,12 @@ radeon_add_atom_connector(struct drm_device *dev, connector->doublescan_allowed = true; else connector->doublescan_allowed = false; + if (connector_type == DRM_MODE_CONNECTOR_DVII) { + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + } break; case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_eDP: diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 39fa2258f235..d3449443aa1f 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1999,6 +1999,53 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec return connector_status_disconnected; } +static enum drm_connector_status +radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); + u32 bios_0_scratch; + + if (!ASIC_IS_DCE4(rdev)) + return connector_status_unknown; + + if (!ext_encoder) + return connector_status_unknown; + + if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0) + return connector_status_unknown; + + /* load detect on the dp bridge */ + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); + + bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); + + DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); + if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { + if (bios_0_scratch & ATOM_S0_CRT1_MASK) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { + if (bios_0_scratch & ATOM_S0_CRT2_MASK) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { + if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { + if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) + return connector_status_connected; /* CTV */ + else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) + return connector_status_connected; /* STV */ + } + return connector_status_disconnected; +} + static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -2162,7 +2209,7 @@ static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { .mode_set = radeon_atom_encoder_mode_set, .commit = radeon_atom_encoder_commit, .disable = radeon_atom_encoder_disable, - /* no detect for TMDS/LVDS yet */ + .detect = radeon_atom_dig_detect, }; static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { -- cgit v1.2.3 From 591a10e16c2a43f6f2ea5f307ab2a5afecfb9ed9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:34 -0400 Subject: drm/radeon/kms: fix support for DDC on dp bridges Need to set up the bridge for DDC prior to the i2c over aux transaction. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 20 ++++++++++++++++---- drivers/gpu/drm/radeon/radeon_encoders.c | 12 ++++++++++++ drivers/gpu/drm/radeon/radeon_mode.h | 1 + 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index dc7852b3c5ca..613e36f83b71 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -44,6 +44,8 @@ extern void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, struct drm_connector *drm_connector); +bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector); + void radeon_connector_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; @@ -1070,10 +1072,10 @@ static int radeon_dp_get_modes(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + struct drm_encoder *encoder = radeon_best_single_encoder(connector); int ret; if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { - struct drm_encoder *encoder; struct drm_display_mode *mode; if (!radeon_dig_connector->edp_on) @@ -1085,7 +1087,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector) ATOM_TRANSMITTER_ACTION_POWER_OFF); if (ret > 0) { - encoder = radeon_best_single_encoder(connector); if (encoder) { radeon_fixup_lvds_native_mode(encoder, connector); /* add scaled modes */ @@ -1109,8 +1110,14 @@ static int radeon_dp_get_modes(struct drm_connector *connector) /* add scaled modes */ radeon_add_common_modes(encoder, connector); } - } else + } else { + /* need to setup ddc on the bridge */ + if (radeon_connector_encoder_is_dp_bridge(connector)) { + if (encoder) + radeon_atom_ext_encoder_setup_ddc(encoder); + } ret = radeon_ddc_get_modes(radeon_connector); + } return ret; } @@ -1194,6 +1201,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force) struct radeon_connector *radeon_connector = to_radeon_connector(connector); enum drm_connector_status ret = connector_status_disconnected; struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + struct drm_encoder *encoder = radeon_best_single_encoder(connector); if (radeon_connector->edid) { kfree(radeon_connector->edid); @@ -1201,7 +1209,6 @@ radeon_dp_detect(struct drm_connector *connector, bool force) } if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { - struct drm_encoder *encoder = radeon_best_single_encoder(connector); if (encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_display_mode *native_mode = &radeon_encoder->native_mode; @@ -1221,6 +1228,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force) atombios_set_edp_panel_power(connector, ATOM_TRANSMITTER_ACTION_POWER_OFF); } else { + /* need to setup ddc on the bridge */ + if (radeon_connector_encoder_is_dp_bridge(connector)) { + if (encoder) + radeon_atom_ext_encoder_setup_ddc(encoder); + } radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { ret = connector_status_connected; diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index d3449443aa1f..8e058f1f46d6 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -2046,6 +2046,18 @@ radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connec return connector_status_disconnected; } +void +radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) +{ + struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); + + if (ext_encoder) + /* ddc_setup on the dp bridge */ + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); + +} + static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 977a341266b6..f734b3737dce 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -483,6 +483,7 @@ extern void radeon_atom_encoder_init(struct radeon_device *rdev); extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set); +extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, u8 write_byte, u8 *read_byte); -- cgit v1.2.3 From d6c669528a5367aaa5f4e712acef990b7148aee8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:36 -0400 Subject: drm/radeon/kms: issue blank/unblank commands for ext encoders Required for DPMS on some systems. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 8e058f1f46d6..aa2450ba0ff8 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1521,26 +1521,29 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) } if (ext_encoder) { - int action; - switch (mode) { case DRM_MODE_DPMS_ON: default: - if (ASIC_IS_DCE41(rdev)) - action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT; - else - action = ATOM_ENABLE; + if (ASIC_IS_DCE41(rdev)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); + } else + atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (ASIC_IS_DCE41(rdev)) - action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT; - else - action = ATOM_DISABLE; + if (ASIC_IS_DCE41(rdev)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); + } else + atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE); break; } - atombios_external_encoder_setup(encoder, ext_encoder, action); } radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); -- cgit v1.2.3 From f89931f345f26c43b109191fbfcfa506781111c0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:35 -0400 Subject: drm/radeon/kms: fix handling of DP to LVDS bridges They need to be treated like eDP rather than DP. May fix: https://bugzilla.kernel.org/show_bug.cgi?id=34822 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 613e36f83b71..cbfca3a24fdf 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1075,7 +1075,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) struct drm_encoder *encoder = radeon_best_single_encoder(connector); int ret; - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { struct drm_display_mode *mode; if (!radeon_dig_connector->edp_on) @@ -1208,7 +1209,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force) radeon_connector->edid = NULL; } - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { if (encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_display_mode *native_mode = &radeon_encoder->native_mode; @@ -1271,7 +1273,8 @@ static int radeon_dp_mode_valid(struct drm_connector *connector, /* XXX check mode bandwidth */ - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { struct drm_encoder *encoder = radeon_best_single_encoder(connector); if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) @@ -1281,7 +1284,7 @@ static int radeon_dp_mode_valid(struct drm_connector *connector, struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_display_mode *native_mode = &radeon_encoder->native_mode; - /* AVIVO hardware supports downscaling modes larger than the panel + /* AVIVO hardware supports downscaling modes larger than the panel * to the panel size, but I'm not sure this is desirable. */ if ((mode->hdisplay > native_mode->hdisplay) || -- cgit v1.2.3 From cc9f67a0a0b076b82ab1af3b2add82e19a33d5de Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Jun 2011 10:06:16 -0400 Subject: drm/radeon/kms/atom: AdjustPixelClock fixes for DP bridges Need to set the external transmitter type properly in AdjustPixelClock to get the properly output. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 7 +++++++ drivers/gpu/drm/radeon/radeon_mode.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 84a69e7fa11e..9541995e4b21 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -671,6 +671,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, DISPPLL_CONFIG_DUAL_LINK; } } + if (radeon_encoder_is_dp_bridge(encoder)) { + struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); + struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); + args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id; + } else + args.v3.sInput.ucExtTransmitterID = 0; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index f734b3737dce..6df4e3cec0c2 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -484,6 +484,7 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set); extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); +extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder); extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, u8 write_byte, u8 *read_byte); -- cgit v1.2.3 From 11b0a5b89adbfaf4e7d31f2482f49471dd983692 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Jun 2011 10:06:17 -0400 Subject: drm/radeon/kms: set DP link config properly for DP bridges DP clock and lanes were not set properly for DP bridges. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index aa2450ba0ff8..f55b64cb59d1 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -367,7 +367,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, } if (ASIC_IS_DCE3(rdev) && - (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) { + ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || + radeon_encoder_is_dp_bridge(encoder))) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); radeon_dp_set_link_config(connector, mode); } -- cgit v1.2.3 From b81157d016a48b8025ccfcb286827679b35f16aa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:39:06 -0400 Subject: drm/radeon/kms: use helper functions for fence read/write The existing code assumed scratch registers in a number of places while in most cases we are be using writeback and events rather than scratch registers. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_fence.c | 51 ++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 1f8229436570..021d2b6b556f 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -40,6 +40,35 @@ #include "radeon.h" #include "radeon_trace.h" +static void radeon_fence_write(struct radeon_device *rdev, u32 seq) +{ + if (rdev->wb.enabled) { + u32 scratch_index; + if (rdev->wb.use_event) + scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; + else + scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; + rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);; + } else + WREG32(rdev->fence_drv.scratch_reg, seq); +} + +static u32 radeon_fence_read(struct radeon_device *rdev) +{ + u32 seq; + + if (rdev->wb.enabled) { + u32 scratch_index; + if (rdev->wb.use_event) + scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; + else + scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; + seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); + } else + seq = RREG32(rdev->fence_drv.scratch_reg); + return seq; +} + int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) { unsigned long irq_flags; @@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) return 0; } fence->seq = atomic_add_return(1, &rdev->fence_drv.seq); - if (!rdev->cp.ready) { + if (!rdev->cp.ready) /* FIXME: cp is not running assume everythings is done right * away */ - WREG32(rdev->fence_drv.scratch_reg, fence->seq); - } else + radeon_fence_write(rdev, fence->seq); + else radeon_fence_ring_emit(rdev, fence); trace_radeon_fence_emit(rdev->ddev, fence->seq); @@ -73,15 +102,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev) bool wake = false; unsigned long cjiffies; - if (rdev->wb.enabled) { - u32 scratch_index; - if (rdev->wb.use_event) - scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; - else - scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; - seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); - } else - seq = RREG32(rdev->fence_drv.scratch_reg); + seq = radeon_fence_read(rdev); if (seq != rdev->fence_drv.last_seq) { rdev->fence_drv.last_seq = seq; rdev->fence_drv.last_jiffies = jiffies; @@ -251,7 +272,7 @@ retry: r = radeon_gpu_reset(rdev); if (r) return r; - WREG32(rdev->fence_drv.scratch_reg, fence->seq); + radeon_fence_write(rdev, fence->seq); rdev->gpu_lockup = false; } timeout = RADEON_FENCE_JIFFIES_TIMEOUT; @@ -351,7 +372,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev) write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); return r; } - WREG32(rdev->fence_drv.scratch_reg, 0); + radeon_fence_write(rdev, 0); atomic_set(&rdev->fence_drv.seq, 0); INIT_LIST_HEAD(&rdev->fence_drv.created); INIT_LIST_HEAD(&rdev->fence_drv.emited); @@ -391,7 +412,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) struct radeon_fence *fence; seq_printf(m, "Last signaled fence 0x%08X\n", - RREG32(rdev->fence_drv.scratch_reg)); + radeon_fence_read(rdev)); if (!list_empty(&rdev->fence_drv.emited)) { fence = list_entry(rdev->fence_drv.emited.prev, struct radeon_fence, list); -- cgit v1.2.3 From d40261236e8e278cb1936cb5e934262971692b10 Mon Sep 17 00:00:00 2001 From: "Marius B. Kotsbak" Date: Sun, 12 Jun 2011 02:35:02 +0000 Subject: net/usb: Add Samsung Kalmia driver for Samsung GT-B3730 Introducing driver for the network port of Samsung Kalmia based USB LTE modems. It has also an ACM interface that previous patches associates with the "option" module. To access those interfaces, the modem must first be switched from modem mode using a tool like usb_modeswitch. As the proprietary protocol has been discovered by watching the MS Windows driver behavior, there might be errors in the protocol handling, but stable and fast connection has been established for hours with Norwegian operator NetCom that distributes this modem with their LTE/4G subscription. More and updated information about how to use this driver is available here: http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=465 https://github.com/mkotsbak/Samsung-GT-B3730-linux-driver Signed-off-by: Marius B. Kotsbak Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 10 ++ drivers/net/usb/Makefile | 1 + drivers/net/usb/kalmia.c | 384 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 395 insertions(+) create mode 100644 drivers/net/usb/kalmia.c diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 9d4f9117260f..84d4608153c9 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -385,6 +385,16 @@ config USB_NET_CX82310_ETH router with USB ethernet port. This driver is for routers only, it will not work with ADSL modems (use cxacru driver instead). +config USB_NET_KALMIA + tristate "Samsung Kalmia based LTE USB modem" + depends on USB_USBNET + help + Choose this option if you have a Samsung Kalmia based USB modem + as Samsung GT-B3730. + + To compile this driver as a module, choose M here: the + module will be called kalmia. + config USB_HSO tristate "Option USB High Speed Mobile Devices" depends on USB && RFKILL diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index c7ec8a5f0a90..c203fa21f6b1 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o obj-$(CONFIG_USB_USBNET) += usbnet.o obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o +obj-$(CONFIG_USB_NET_KALMIA) += kalmia.o obj-$(CONFIG_USB_IPHETH) += ipheth.o obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c new file mode 100644 index 000000000000..d965fb1e013e --- /dev/null +++ b/drivers/net/usb/kalmia.c @@ -0,0 +1,384 @@ +/* + * USB network interface driver for Samsung Kalmia based LTE USB modem like the + * Samsung GT-B3730 and GT-B3710. + * + * Copyright (C) 2011 Marius Bjoernstad Kotsbak + * + * Sponsored by Quicklink Video Distribution Services Ltd. + * + * Based on the cdc_eem module. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The Samsung Kalmia based LTE USB modems have a CDC ACM port for modem control + * handled by the "option" module and an ethernet data port handled by this + * module. + * + * The stick must first be switched into modem mode by usb_modeswitch + * or similar tool. Then the modem gets sent two initialization packets by + * this module, which gives the MAC address of the device. User space can then + * connect the modem using AT commands through the ACM port and then use + * DHCP on the network interface exposed by this module. Network packets are + * sent to and from the modem in a proprietary format discovered after watching + * the behavior of the windows driver for the modem. + * + * More information about the use of the modem is available in usb_modeswitch + * forum and the project page: + * + * http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=465 + * https://github.com/mkotsbak/Samsung-GT-B3730-linux-driver + */ + +/* #define DEBUG */ +/* #define VERBOSE */ + +#define KALMIA_HEADER_LENGTH 6 +#define KALMIA_ALIGN_SIZE 4 +#define KALMIA_USB_TIMEOUT 10000 + +/*-------------------------------------------------------------------------*/ + +static int +kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len, + u8 *buffer, u8 expected_len) +{ + int act_len; + int status; + + netdev_dbg(dev->net, "Sending init packet"); + + status = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 0x02), + init_msg, init_msg_len, &act_len, KALMIA_USB_TIMEOUT); + if (status != 0) { + netdev_err(dev->net, + "Error sending init packet. Status %i, length %i\n", + status, act_len); + return status; + } + else if (act_len != init_msg_len) { + netdev_err(dev->net, + "Did not send all of init packet. Bytes sent: %i", + act_len); + } + else { + netdev_dbg(dev->net, "Successfully sent init packet."); + } + + status = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, 0x81), + buffer, expected_len, &act_len, KALMIA_USB_TIMEOUT); + + if (status != 0) + netdev_err(dev->net, + "Error receiving init result. Status %i, length %i\n", + status, act_len); + else if (act_len != expected_len) + netdev_err(dev->net, "Unexpected init result length: %i\n", + act_len); + + return status; +} + +static int +kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr) +{ + char init_msg_1[] = + { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00 }; + char init_msg_2[] = + { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4, + 0x00, 0x00 }; + char receive_buf[28]; + int status; + + status = kalmia_send_init_packet(dev, init_msg_1, sizeof(init_msg_1) + / sizeof(init_msg_1[0]), receive_buf, 24); + if (status != 0) + return status; + + status = kalmia_send_init_packet(dev, init_msg_2, sizeof(init_msg_2) + / sizeof(init_msg_2[0]), receive_buf, 28); + if (status != 0) + return status; + + memcpy(ethernet_addr, receive_buf + 10, ETH_ALEN); + + return status; +} + +static int +kalmia_bind(struct usbnet *dev, struct usb_interface *intf) +{ + u8 status; + u8 ethernet_addr[ETH_ALEN]; + + /* Don't bind to AT command interface */ + if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) + return -EINVAL; + + dev->in = usb_rcvbulkpipe(dev->udev, 0x81 & USB_ENDPOINT_NUMBER_MASK); + dev->out = usb_sndbulkpipe(dev->udev, 0x02 & USB_ENDPOINT_NUMBER_MASK); + dev->status = NULL; + + dev->net->hard_header_len += KALMIA_HEADER_LENGTH; + dev->hard_mtu = 1400; + dev->rx_urb_size = dev->hard_mtu * 10; // Found as optimal after testing + + status = kalmia_init_and_get_ethernet_addr(dev, ethernet_addr); + + if (status < 0) { + usb_set_intfdata(intf, NULL); + usb_driver_release_interface(driver_of(intf), intf); + return status; + } + + memcpy(dev->net->dev_addr, ethernet_addr, ETH_ALEN); + memcpy(dev->net->perm_addr, ethernet_addr, ETH_ALEN); + + return status; +} + +static struct sk_buff * +kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) +{ + struct sk_buff *skb2 = NULL; + u16 content_len; + unsigned char *header_start; + unsigned char ether_type_1, ether_type_2; + u8 remainder, padlen = 0; + + if (!skb_cloned(skb)) { + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + + if ((tailroom >= KALMIA_ALIGN_SIZE) && (headroom + >= KALMIA_HEADER_LENGTH)) + goto done; + + if ((headroom + tailroom) > (KALMIA_HEADER_LENGTH + + KALMIA_ALIGN_SIZE)) { + skb->data = memmove(skb->head + KALMIA_HEADER_LENGTH, + skb->data, skb->len); + skb_set_tail_pointer(skb, skb->len); + goto done; + } + } + + skb2 = skb_copy_expand(skb, KALMIA_HEADER_LENGTH, + KALMIA_ALIGN_SIZE, flags); + if (!skb2) + return NULL; + + dev_kfree_skb_any(skb); + skb = skb2; + + done: header_start = skb_push(skb, KALMIA_HEADER_LENGTH); + ether_type_1 = header_start[KALMIA_HEADER_LENGTH + 12]; + ether_type_2 = header_start[KALMIA_HEADER_LENGTH + 13]; + + netdev_dbg(dev->net, "Sending etherType: %02x%02x", ether_type_1, + ether_type_2); + + /* According to empiric data for data packages */ + header_start[0] = 0x57; + header_start[1] = 0x44; + content_len = skb->len - KALMIA_HEADER_LENGTH; + header_start[2] = (content_len & 0xff); /* low byte */ + header_start[3] = (content_len >> 8); /* high byte */ + + header_start[4] = ether_type_1; + header_start[5] = ether_type_2; + + /* Align to 4 bytes by padding with zeros */ + remainder = skb->len % KALMIA_ALIGN_SIZE; + if (remainder > 0) { + padlen = KALMIA_ALIGN_SIZE - remainder; + memset(skb_put(skb, padlen), 0, padlen); + } + + netdev_dbg( + dev->net, + "Sending package with length %i and padding %i. Header: %02x:%02x:%02x:%02x:%02x:%02x.", + content_len, padlen, header_start[0], header_start[1], + header_start[2], header_start[3], header_start[4], + header_start[5]); + + return skb; +} + +static int +kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + /* + * Our task here is to strip off framing, leaving skb with one + * data frame for the usbnet framework code to process. + */ + const u8 HEADER_END_OF_USB_PACKET[] = + { 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 }; + const u8 EXPECTED_UNKNOWN_HEADER_1[] = + { 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 }; + const u8 EXPECTED_UNKNOWN_HEADER_2[] = + { 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 }; + u8 i = 0; + + /* incomplete header? */ + if (skb->len < KALMIA_HEADER_LENGTH) + return 0; + + do { + struct sk_buff *skb2 = NULL; + u8 *header_start; + u16 usb_packet_length, ether_packet_length; + int is_last; + + header_start = skb->data; + + if (unlikely(header_start[0] != 0x57 || header_start[1] != 0x44)) { + if (!memcmp(header_start, EXPECTED_UNKNOWN_HEADER_1, + sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp( + header_start, EXPECTED_UNKNOWN_HEADER_2, + sizeof(EXPECTED_UNKNOWN_HEADER_2))) { + netdev_dbg( + dev->net, + "Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", + header_start[0], header_start[1], + header_start[2], header_start[3], + header_start[4], header_start[5], + skb->len - KALMIA_HEADER_LENGTH); + } + else { + netdev_err( + dev->net, + "Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", + header_start[0], header_start[1], + header_start[2], header_start[3], + header_start[4], header_start[5], + skb->len - KALMIA_HEADER_LENGTH); + return 0; + } + } + else + netdev_dbg( + dev->net, + "Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", + header_start[0], header_start[1], header_start[2], + header_start[3], header_start[4], header_start[5], + skb->len - KALMIA_HEADER_LENGTH); + + /* subtract start header and end header */ + usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH); + ether_packet_length = header_start[2] + (header_start[3] << 8); + skb_pull(skb, KALMIA_HEADER_LENGTH); + + /* Some small packets misses end marker */ + if (usb_packet_length < ether_packet_length) { + ether_packet_length = usb_packet_length + + KALMIA_HEADER_LENGTH; + is_last = true; + } + else { + netdev_dbg(dev->net, "Correct package length #%i", i + + 1); + + is_last = (memcmp(skb->data + ether_packet_length, + HEADER_END_OF_USB_PACKET, + sizeof(HEADER_END_OF_USB_PACKET)) == 0); + if (!is_last) { + header_start = skb->data + ether_packet_length; + netdev_dbg( + dev->net, + "End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", + header_start[0], header_start[1], + header_start[2], header_start[3], + header_start[4], header_start[5], + skb->len - KALMIA_HEADER_LENGTH); + } + } + + if (is_last) { + skb2 = skb; + } + else { + skb2 = skb_clone(skb, GFP_ATOMIC); + if (unlikely(!skb2)) + return 0; + } + + skb_trim(skb2, ether_packet_length); + + if (is_last) { + return 1; + } + else { + usbnet_skb_return(dev, skb2); + skb_pull(skb, ether_packet_length); + } + + i++; + } + while (skb->len); + + return 1; +} + +static const struct driver_info kalmia_info = { + .description = "Samsung Kalmia LTE USB dongle", + .flags = FLAG_WWAN, + .bind = kalmia_bind, + .rx_fixup = kalmia_rx_fixup, + .tx_fixup = kalmia_tx_fixup +}; + +/*-------------------------------------------------------------------------*/ + +static const struct usb_device_id products[] = { + /* The unswitched USB ID, to get the module auto loaded: */ + { USB_DEVICE(0x04e8, 0x689a) }, + /* The stick swithed into modem (by e.g. usb_modeswitch): */ + { USB_DEVICE(0x04e8, 0x6889), + .driver_info = (unsigned long) &kalmia_info, }, + { /* EMPTY == end of list */} }; +MODULE_DEVICE_TABLE( usb, products); + +static struct usb_driver kalmia_driver = { + .name = "kalmia", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume +}; + +static int __init kalmia_init(void) +{ + return usb_register(&kalmia_driver); +} +module_init( kalmia_init); + +static void __exit kalmia_exit(void) +{ + usb_deregister(&kalmia_driver); +} +module_exit( kalmia_exit); + +MODULE_AUTHOR("Marius Bjoernstad Kotsbak "); +MODULE_DESCRIPTION("Samsung Kalmia USB network driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 62b2bcb49cca72f6d3f39f831127a6ab315a475d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Luis=20V=C3=A1zquez=20Cao?= Date: Mon, 13 Jun 2011 15:04:43 +0000 Subject: IGMP snooping: set mrouters_only flag for IPv4 traffic properly Upon reception of a IGMP/IGMPv2 membership report the kernel sets the mrouters_only flag in a skb that may be a clone of the original skb, which means that sometimes the bridge loses track of membership report packets (cb buffers are tied to a specific skb and not shared) and it ends up forwading join requests to the bridge interface. This can cause unexpected membership timeouts and intermitent/permanent loss of connectivity as described in RFC 4541 [2.1.1. IGMP Forwarding Rules]: A snooping switch should forward IGMP Membership Reports only to those ports where multicast routers are attached. [...] Sending membership reports to other hosts can result, for IGMPv1 and IGMPv2, in unintentionally preventing a host from joining a specific multicast group. Signed-off-by: Fernando Luis Vazquez Cao Tested-by: Hayato Kakuta Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2f14eafdeeab..a6d87c17bb03 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1424,7 +1424,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, switch (ih->type) { case IGMP_HOST_MEMBERSHIP_REPORT: case IGMPV2_HOST_MEMBERSHIP_REPORT: - BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; + BR_INPUT_SKB_CB(skb)->mrouters_only = 1; err = br_ip4_multicast_add_group(br, port, ih->group); break; case IGMPV3_HOST_MEMBERSHIP_REPORT: -- cgit v1.2.3 From fc2af6c73fc9449cd5894a36bb76b8f8c0e49fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Luis=20V=C3=A1zquez=20Cao?= Date: Mon, 13 Jun 2011 15:06:58 +0000 Subject: IGMP snooping: set mrouters_only flag for IPv6 traffic properly Upon reception of a MGM report packet the kernel sets the mrouters_only flag in a skb that is a clone of the original skb, which means that the bridge loses track of MGM packets (cb buffers are tied to a specific skb and not shared) and it ends up forwading join requests to the bridge interface. This can cause unexpected membership timeouts and intermitent/permanent loss of connectivity as described in RFC 4541 [2.1.1. IGMP Forwarding Rules]: A snooping switch should forward IGMP Membership Reports only to those ports where multicast routers are attached. [...] Sending membership reports to other hosts can result, for IGMPv1 and IGMPv2, in unintentionally preventing a host from joining a specific multicast group. Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index a6d87c17bb03..29b9812c8da0 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1543,7 +1543,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, goto out; } mld = (struct mld_msg *)skb_transport_header(skb2); - BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; + BR_INPUT_SKB_CB(skb)->mrouters_only = 1; err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); break; } -- cgit v1.2.3 From d3ab6fde14b69c346939cd00765b3826a4760e5c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 13 Jun 2011 16:26:22 +0000 Subject: MAINTAINERS: Update EBTABLES mailing list It moved to netfilter-devel@vger.kernel.org. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6a1c430d2821..0f1515a9780d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2292,8 +2292,7 @@ F: drivers/scsi/eata_pio.* EBTABLES M: Bart De Schuymer -L: ebtables-user@lists.sourceforge.net -L: ebtables-devel@lists.sourceforge.net +L: netfilter-devel@vger.kernel.org W: http://ebtables.sourceforge.net/ S: Maintained F: include/linux/netfilter_bridge/ebt_*.h -- cgit v1.2.3 From e6539e2b7aee117619153daaf61566dba1e04205 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 14 Jun 2011 21:58:13 +0000 Subject: ppp: use PPP_TRANS instead of the magic number 0x20 Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- drivers/net/ppp_async.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index a1b82c9c67d2..c554a397e558 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -523,7 +523,7 @@ static void ppp_async_process(unsigned long arg) #define PUT_BYTE(ap, buf, c, islcp) do { \ if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\ *buf++ = PPP_ESCAPE; \ - *buf++ = c ^ 0x20; \ + *buf++ = c ^ PPP_TRANS; \ } else \ *buf++ = c; \ } while (0) @@ -896,7 +896,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, sp = skb_put(skb, n); memcpy(sp, buf, n); if (ap->state & SC_ESCAPE) { - sp[0] ^= 0x20; + sp[0] ^= PPP_TRANS; ap->state &= ~SC_ESCAPE; } } -- cgit v1.2.3 From f1dc045e685ea5424b3445c1ccaa0a25b3d661ec Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 14 Jun 2011 22:07:58 +0000 Subject: phylib: Allow BCM63XX PHY to be selected only on BCM63XX. This PHY is available integrated into BCM63xx series SOCs only. Signed-off-by: Ralf Baechle drivers/net/phy/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 392a6c4b72e5..a70244306c94 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -58,6 +58,7 @@ config BROADCOM_PHY config BCM63XX_PHY tristate "Drivers for Broadcom 63xx SOCs internal PHY" + depends on BCM63XX ---help--- Currently supports the 6348 and 6358 PHYs. -- cgit v1.2.3 From 2331038a96ecdad76c50ab223fd48d656d8a1184 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Tue, 14 Jun 2011 23:55:19 +0000 Subject: dp83640: fix phy status frame event parsing If two eternal time stamp events occur at nearly the same time, the phyter will add an extra word into the status frame. This commit fixes the parsing code to recognize and skip over the extra word. Signed-off-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index b0c9522bb535..ead323e56739 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -543,11 +543,20 @@ static void recalibrate(struct dp83640_clock *clock) /* time stamping methods */ -static void decode_evnt(struct dp83640_private *dp83640, - struct phy_txts *phy_txts, u16 ests) +static int decode_evnt(struct dp83640_private *dp83640, + void *data, u16 ests) { + struct phy_txts *phy_txts; struct ptp_clock_event event; int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK; + u16 ext_status = 0; + + if (ests & MULT_EVNT) { + ext_status = *(u16 *) data; + data += sizeof(ext_status); + } + + phy_txts = data; switch (words) { /* fall through in every case */ case 3: @@ -565,6 +574,9 @@ static void decode_evnt(struct dp83640_private *dp83640, event.timestamp = phy2txts(&dp83640->edata); ptp_clock_event(dp83640->clock->ptp_clock, &event); + + words = ext_status ? words + 2 : words + 1; + return words * sizeof(u16); } static void decode_rxts(struct dp83640_private *dp83640, @@ -643,9 +655,7 @@ static void decode_status_frame(struct dp83640_private *dp83640, } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) { - phy_txts = (struct phy_txts *) ptr; - decode_evnt(dp83640, phy_txts, ests); - size = sizeof(*phy_txts); + size = decode_evnt(dp83640, ptr, ests); } else { size = 0; -- cgit v1.2.3 From ae6e86b7fb15520ac64513ad643de63e0b077aa5 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Tue, 14 Jun 2011 23:55:20 +0000 Subject: dp83640: drop PHY status frames in the driver. The dp83640 PHY provides time stamp and other information via special PHY status frames. Previously, the driver decoded the frames and then let the network stack drop them. This works fine when the PTP messages come over UDP. However, when receiving PTP messages via L2 packets, this creates a problem. The status frames use the official PTP destination MAC address, and so they are delivered to user space along with the "real" frames, causing confusion for applications. This commit fixes the issue by simply dropping the PHY status frames in the driver. Signed-off-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index ead323e56739..2cd8dc5847b4 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1044,8 +1044,8 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, if (is_status_frame(skb, type)) { decode_status_frame(dp83640, skb); - /* Let the stack drop this frame. */ - return false; + kfree_skb(skb); + return true; } SKB_PTP_TYPE(skb) = type; -- cgit v1.2.3 From bebd097a0af8bd6c51f50a65f3a435019b0e906a Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 15 Jun 2011 05:25:01 +0000 Subject: tun: teach the tun/tap driver to support netpoll Commit 8d8fc29d02a33e4bd5f4fa47823c1fd386346093 changed the behavior of slave devices in regards to netpoll. Specifically it created a mutually exclusive relationship between being a slave and a netpoll-capable device. This creates problems for KVM because guests relied on needing netconsole active on a slave device to a bridge. Ideally libvirtd could just attach netconsole to the bridge device instead, but thats currently infeasible, because while the bridge device supports netpoll, it requires that all slave interface also support it, but the tun/tap driver currently does not. The most direct solution is to teach tun/tap to support netpoll, which is implemented by the patch below. I've not tested this yet, but its pretty straightforward. Signed-off-by: Neil Horman Reported-by: Rik van Riel CC: Rik van Riel CC: Maxim Krasnyansky CC: Cong Wang CC: "David S. Miller" Reviewed-by: Rik van Riel Tested-by: Rik van Riel Reviewed-by: WANG Cong Signed-off-by: David S. Miller --- drivers/net/tun.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 74e94054ab1a..5235f48be1be 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -460,7 +460,23 @@ static u32 tun_net_fix_features(struct net_device *dev, u32 features) return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); } - +#ifdef CONFIG_NET_POLL_CONTROLLER +static void tun_poll_controller(struct net_device *dev) +{ + /* + * Tun only receives frames when: + * 1) the char device endpoint gets data from user space + * 2) the tun socket gets a sendmsg call from user space + * Since both of those are syncronous operations, we are guaranteed + * never to have pending data when we poll for it + * so theres nothing to do here but return. + * We need this though so netpoll recognizes us as an interface that + * supports polling, which enables bridge devices in virt setups to + * still use netconsole + */ + return; +} +#endif static const struct net_device_ops tun_netdev_ops = { .ndo_uninit = tun_net_uninit, .ndo_open = tun_net_open, @@ -468,6 +484,9 @@ static const struct net_device_ops tun_netdev_ops = { .ndo_start_xmit = tun_net_xmit, .ndo_change_mtu = tun_net_change_mtu, .ndo_fix_features = tun_net_fix_features, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif }; static const struct net_device_ops tap_netdev_ops = { @@ -480,6 +499,9 @@ static const struct net_device_ops tap_netdev_ops = { .ndo_set_multicast_list = tun_net_mclist, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif }; /* Initialize net device. */ -- cgit v1.2.3 From a1b7f85e4f632f9cc342d8a34a3903feaf47a261 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Wed, 15 Jun 2011 12:38:25 +0000 Subject: caif: Bugfix - XOFF removed channel from caif-mux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XOFF was mixed up with DOWN indication, causing causing CAIF channel to be removed from mux and all incoming traffic to be lost after receiving flow-off. Fix this by replacing FLOW_OFF with DOWN notification. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/cfmuxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index 3a66b8c10e09..c23979e79dfa 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c @@ -255,7 +255,7 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) { - if ((ctrl == _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND || + if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND || ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) && layer->id != 0) { -- cgit v1.2.3 From e3cb78c772de593afa720687ce3abbed8d93b0c3 Mon Sep 17 00:00:00 2001 From: Antoine Reversat Date: Thu, 16 Jun 2011 10:47:13 +0000 Subject: vlan: don't call ndo_vlan_rx_register on hardware that doesn't have vlan support This patch removes the call to ndo_vlan_rx_register if the underlying device doesn't have hardware support for VLAN. Signed-off-by: Antoine Reversat Signed-off-by: David S. Miller --- net/8021q/vlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index c7a581a96894..917ecb93ea28 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -205,7 +205,7 @@ int register_vlan_dev(struct net_device *dev) grp->nr_vlans++; if (ngrp) { - if (ops->ndo_vlan_rx_register) + if (ops->ndo_vlan_rx_register && (real_dev->features & NETIF_F_HW_VLAN_RX)) ops->ndo_vlan_rx_register(real_dev, ngrp); rcu_assign_pointer(real_dev->vlgrp, ngrp); } -- cgit v1.2.3 From 118133e6580a0c912cda86109b6468b5ffe73f1c Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 16 Jun 2011 12:31:58 +0000 Subject: netdev: bfin_mac: fix memory leak when freeing dma descriptors The size of the desc array is not the size of the desc structure, so when we try to free up things, we leak some parts. Reported-by: Regis Dargent Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: David S. Miller --- drivers/net/bfin_mac.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 68d45ba2d9b9..6c019e148546 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -52,13 +52,13 @@ MODULE_DESCRIPTION(DRV_DESC); MODULE_ALIAS("platform:bfin_mac"); #if defined(CONFIG_BFIN_MAC_USE_L1) -# define bfin_mac_alloc(dma_handle, size) l1_data_sram_zalloc(size) -# define bfin_mac_free(dma_handle, ptr) l1_data_sram_free(ptr) +# define bfin_mac_alloc(dma_handle, size, num) l1_data_sram_zalloc(size*num) +# define bfin_mac_free(dma_handle, ptr, num) l1_data_sram_free(ptr) #else -# define bfin_mac_alloc(dma_handle, size) \ - dma_alloc_coherent(NULL, size, dma_handle, GFP_KERNEL) -# define bfin_mac_free(dma_handle, ptr) \ - dma_free_coherent(NULL, sizeof(*ptr), ptr, dma_handle) +# define bfin_mac_alloc(dma_handle, size, num) \ + dma_alloc_coherent(NULL, size*num, dma_handle, GFP_KERNEL) +# define bfin_mac_free(dma_handle, ptr, num) \ + dma_free_coherent(NULL, sizeof(*ptr)*num, ptr, dma_handle) #endif #define PKT_BUF_SZ 1580 @@ -95,7 +95,7 @@ static void desc_list_free(void) t = t->next; } } - bfin_mac_free(dma_handle, tx_desc); + bfin_mac_free(dma_handle, tx_desc, CONFIG_BFIN_TX_DESC_NUM); } if (rx_desc) { @@ -109,7 +109,7 @@ static void desc_list_free(void) r = r->next; } } - bfin_mac_free(dma_handle, rx_desc); + bfin_mac_free(dma_handle, rx_desc, CONFIG_BFIN_RX_DESC_NUM); } } @@ -126,13 +126,13 @@ static int desc_list_init(void) #endif tx_desc = bfin_mac_alloc(&dma_handle, - sizeof(struct net_dma_desc_tx) * + sizeof(struct net_dma_desc_tx), CONFIG_BFIN_TX_DESC_NUM); if (tx_desc == NULL) goto init_error; rx_desc = bfin_mac_alloc(&dma_handle, - sizeof(struct net_dma_desc_rx) * + sizeof(struct net_dma_desc_rx), CONFIG_BFIN_RX_DESC_NUM); if (rx_desc == NULL) goto init_error; -- cgit v1.2.3 From d8ad7d1123a960cc9f276bd499f9325c6f5e1bd1 Mon Sep 17 00:00:00 2001 From: Takao Indoh Date: Tue, 29 Mar 2011 12:35:04 -0400 Subject: generic-ipi: Fix kexec boot crash by initializing call_single_queue before enabling interrupts There is a problem that kdump(2nd kernel) sometimes hangs up due to a pending IPI from 1st kernel. Kernel panic occurs because IPI comes before call_single_queue is initialized. To fix the crash, rename init_call_single_data() to call_function_init() and call it in start_kernel() so that call_single_queue can be initialized before enabling interrupts. The details of the crash are: (1) 2nd kernel boots up (2) A pending IPI from 1st kernel comes when irqs are first enabled in start_kernel(). (3) Kernel tries to handle the interrupt, but call_single_queue is not initialized yet at this point. As a result, in the generic_smp_call_function_single_interrupt(), NULL pointer dereference occurs when list_replace_init() tries to access &q->list.next. Therefore this patch changes the name of init_call_single_data() to call_function_init() and calls it before local_irq_enable() in start_kernel(). Signed-off-by: Takao Indoh Reviewed-by: WANG Cong Acked-by: Neil Horman Acked-by: Vivek Goyal Acked-by: Peter Zijlstra Cc: Milton Miller Cc: Jens Axboe Cc: Paul E. McKenney Cc: kexec@lists.infradead.org Link: http://lkml.kernel.org/r/D6CBEE2F420741indou.takao@jp.fujitsu.com Signed-off-by: Ingo Molnar --- include/linux/smp.h | 5 ++++- init/main.c | 1 + kernel/smp.c | 5 +---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/smp.h b/include/linux/smp.h index 7ad824d510a2..8cc38d3bab0c 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -85,12 +85,15 @@ int smp_call_function_any(const struct cpumask *mask, * Generic and arch helpers */ #ifdef CONFIG_USE_GENERIC_SMP_HELPERS +void __init call_function_init(void); void generic_smp_call_function_single_interrupt(void); void generic_smp_call_function_interrupt(void); void ipi_call_lock(void); void ipi_call_unlock(void); void ipi_call_lock_irq(void); void ipi_call_unlock_irq(void); +#else +static inline void call_function_init(void) { } #endif /* @@ -134,7 +137,7 @@ static inline void smp_send_reschedule(int cpu) { } #define smp_prepare_boot_cpu() do {} while (0) #define smp_call_function_many(mask, func, info, wait) \ (up_smp_call_function(func, info)) -static inline void init_call_single_data(void) { } +static inline void call_function_init(void) { } static inline int smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, diff --git a/init/main.c b/init/main.c index cafba67c13bf..d7211faed2ad 100644 --- a/init/main.c +++ b/init/main.c @@ -542,6 +542,7 @@ asmlinkage void __init start_kernel(void) timekeeping_init(); time_init(); profile_init(); + call_function_init(); if (!irqs_disabled()) printk(KERN_CRIT "start_kernel(): bug: interrupts were " "enabled early\n"); diff --git a/kernel/smp.c b/kernel/smp.c index 73a195193558..fb67dfa8394e 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -74,7 +74,7 @@ static struct notifier_block __cpuinitdata hotplug_cfd_notifier = { .notifier_call = hotplug_cfd, }; -static int __cpuinit init_call_single_data(void) +void __init call_function_init(void) { void *cpu = (void *)(long)smp_processor_id(); int i; @@ -88,10 +88,7 @@ static int __cpuinit init_call_single_data(void) hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu); register_cpu_notifier(&hotplug_cfd_notifier); - - return 0; } -early_initcall(init_call_single_data); /* * csd_lock/csd_unlock used to serialize access to per-cpu csd resources -- cgit v1.2.3 From cf6f1ff17f56c275424c5a341fc4d27ccbbfa71c Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 17 Jun 2011 08:18:35 +0200 Subject: ALSA: isight: adjust for new queueing API Since commit 13882a82ee16 (optimize iso queueing by setting wake only after the last packet), drivers are required to call fw_iso_context_queue_flush() after queueing a batch of packets. The missing call would have an effect only if the controller queue underruns, but then the DMA would stop completely. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/firewire/isight.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 86ee16ca365e..440030818db7 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -209,6 +209,7 @@ static void isight_packet(struct fw_iso_context *context, u32 cycle, isight->packet_index = -1; return; } + fw_iso_context_queue_flush(isight->context); if (++index >= QUEUE_LENGTH) index = 0; -- cgit v1.2.3 From 2bc58a6fd76f89052c7f151d78fb2d8b804aacfe Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 13 Jun 2011 06:46:44 +0100 Subject: ARM: 6959/1: SMP build fix for entry-macro-multi.S The assembly code in entry-macro-multi.S does not build without the include asm/assembler.h in the case of CONFIG_SMP=y. Fixes the rather theoretical SMP build of mach-shmobile/entry-intc.c: arch/arm/include/asm/entry-macro-multi.S: Assembler messages: arch/arm/include/asm/entry-macro-multi.S:20: Error: bad instruction `alt_smp(test_for_ipi r0,r6,r5,lr)' arch/arm/include/asm/entry-macro-multi.S:20: Error: bad instruction `alt_up_b(9997f)' make[1]: *** [arch/arm/mach-shmobile/entry-intc.o] Error 1 make: *** [arch/arm/mach-shmobile] Error 2 make: *** Waiting for unfinished jobs.... Signed-off-by: Magnus Damm Signed-off-by: Russell King --- arch/arm/include/asm/assembler.h | 4 ++++ arch/arm/include/asm/entry-macro-multi.S | 2 ++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index bc2d2d75f706..65c3f2474f5e 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -13,6 +13,9 @@ * Do not include any C declarations in this file - it is included by * assembler source. */ +#ifndef __ASM_ASSEMBLER_H__ +#define __ASM_ASSEMBLER_H__ + #ifndef __ASSEMBLY__ #error "Only include this from assembly code" #endif @@ -290,3 +293,4 @@ .macro ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort .endm +#endif /* __ASM_ASSEMBLER_H__ */ diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S index ec0bbf79c71f..2da8547de6d6 100644 --- a/arch/arm/include/asm/entry-macro-multi.S +++ b/arch/arm/include/asm/entry-macro-multi.S @@ -1,3 +1,5 @@ +#include + /* * Interrupt handling. Preserves r7, r8, r9 */ -- cgit v1.2.3 From 343fda59823ca20f48578f816ec12e741214f509 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 16 Jun 2011 08:26:06 +0100 Subject: ARM: 6962/1: mach-h720x: fix build error The h7201/h7202 machines did not build since they define ARM_DMA_ZONE_OFFSET but do not select ZONE_DMA. Fix it up by selecting ZONE_DMA in their Kconfig. Cc: Sascha Hauer Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-h720x/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-h720x/Kconfig b/arch/arm/mach-h720x/Kconfig index 9b6982efbd22..abf356c02343 100644 --- a/arch/arm/mach-h720x/Kconfig +++ b/arch/arm/mach-h720x/Kconfig @@ -6,12 +6,14 @@ config ARCH_H7201 bool "gms30c7201" depends on ARCH_H720X select CPU_H7201 + select ZONE_DMA help Say Y here if you are using the Hynix GMS30C7201 Reference Board config ARCH_H7202 bool "hms30c7202" select CPU_H7202 + select ZONE_DMA depends on ARCH_H720X help Say Y here if you are using the Hynix HMS30C7202 Reference Board -- cgit v1.2.3 From 9a00318eadbb43db4e9c163c262a22a3c8b5a672 Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Thu, 16 Jun 2011 12:09:37 +0100 Subject: ARM: 6963/1: Thumb-2: Relax relocation requirements for non-function symbols The "Thumb bit" of a symbol is only really meaningful for function symbols (STT_FUNC). However, sometimes a branch is relocated against a non-function symbol; for example, PC-relative branches to anonymous assembler local symbols are typically fixed up against the start-of-section symbol, which is not a function symbol. Some inline assembler generates references of this type, such as fixup code generated by macros in . The existing relocation code for R_ARM_THM_CALL/R_ARM_THM_JUMP24 interprets this case as an error, because the target symbol appears to be an ARM symbol; but this is really not the case, since the target symbol is just a base in these cases. The addend defines the precise offset to the target location, but since the addend is encoded in a non-interworking Thumb branch instruction, there is no explicit Thumb bit in the addend. Because these instructions never interwork, the implied Thumb bit in the addend is 1, and the destination is Thumb by definition. This patch removes the extraneous Thumb bit check for non-function symbols, enabling modules containing the affected relocation types to be loaded. No modification to the actual relocation code is required, since this code does not take bit[0] of the location->destination offset into account in any case. Function symbols are always checked for interworking conflicts, as before. Signed-off-by: Dave Martin Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/module.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index fee7c36349eb..016d6a0830a3 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -193,8 +193,17 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset -= 0x02000000; offset += sym->st_value - loc; - /* only Thumb addresses allowed (no interworking) */ - if (!(offset & 1) || + /* + * For function symbols, only Thumb addresses are + * allowed (no interworking). + * + * For non-function symbols, the destination + * has no specific ARM/Thumb disposition, so + * the branch is resolved under the assumption + * that interworking is not required. + */ + if ((ELF32_ST_TYPE(sym->st_info) == STT_FUNC && + !(offset & 1)) || offset <= (s32)0xff000000 || offset >= (s32)0x01000000) { pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", -- cgit v1.2.3 From ad2409413d09fca763be1ac5161f2a9d82367903 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Jun 2011 14:23:46 +0200 Subject: ALSA: hda - Fix no NID error with VIA codecs The via driver spews warnigs like hda-codec: no NID for mapping control Independent HP:0:0 with some codecs because snd_hda_add_nid() is called with nid=0. This patch fixes it by skipping the call when no corresponding widget is found. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 605c99e1e520..c952582fb218 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -832,10 +832,13 @@ static int via_hp_build(struct hda_codec *codec) knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; knew->private_value = nid; - knew = via_clone_control(spec, &via_hp_mixer[1]); - if (knew == NULL) - return -ENOMEM; - knew->subdevice = side_mute_channel(spec); + nid = side_mute_channel(spec); + if (nid) { + knew = via_clone_control(spec, &via_hp_mixer[1]); + if (knew == NULL) + return -ENOMEM; + knew->subdevice = nid; + } return 0; } -- cgit v1.2.3 From 5afa9133cfe67f1bfead6049a9640c9262a7101c Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 17 Jun 2011 10:14:59 -0400 Subject: SUNRPC: Ensure the RPC client only quits on fatal signals Fix a couple of instances where we were exiting the RPC client on arbitrary signals. We should only do so on fatal signals. Cc: stable@kernel.org Signed-off-by: Trond Myklebust --- net/sunrpc/auth_gss/auth_gss.c | 4 ++-- net/sunrpc/clnt.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 339ba64cce1e..5daf6cc4faea 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -577,13 +577,13 @@ retry: } inode = &gss_msg->inode->vfs_inode; for (;;) { - prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE); + prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); spin_lock(&inode->i_lock); if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { break; } spin_unlock(&inode->i_lock); - if (signalled()) { + if (fatal_signal_pending(current)) { err = -ERESTARTSYS; goto out_intr; } diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 566bcfd067f6..8c9141583d6f 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1061,7 +1061,7 @@ call_allocate(struct rpc_task *task) dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); - if (RPC_IS_ASYNC(task) || !signalled()) { + if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) { task->tk_action = call_allocate; rpc_delay(task, HZ>>4); return; -- cgit v1.2.3 From e479c60456ef22b0869432887216186aabaed086 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 17 Jun 2011 04:35:37 -0400 Subject: spi/bfin_spi: fix handling of default bits per word setting The default bits per word setting should be 8 bits, but since most of our devices have been explicitly setting this up, we didn't notice when the default stopped working. At the moment, any default transfers without an explicit bit size setting error out with: bfin-spi bfin-spi.0: transfer: unsupported bits_per_word So in the transfer logic, have a bits_per_word setting of 0 fall into the 8 bit transfer logic. Signed-off-by: Mike Frysinger Signed-off-by: Grant Likely --- drivers/spi/spi_bfin5xx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index f706dba165cf..cc880c95e7de 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -681,13 +681,14 @@ static void bfin_spi_pump_transfers(unsigned long data) drv_data->cs_change = transfer->cs_change; /* Bits per word setup */ - bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; - if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) { + bits_per_word = transfer->bits_per_word ? : + message->spi->bits_per_word ? : 8; + if (bits_per_word % 16 == 0) { drv_data->n_bytes = bits_per_word/8; drv_data->len = (transfer->len) >> 1; cr_width = BIT_CTL_WORDSIZE; drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; - } else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) { + } else if (bits_per_word % 8 == 0) { drv_data->n_bytes = bits_per_word/8; drv_data->len = transfer->len; cr_width = 0; -- cgit v1.2.3 From 879669961b11e7f40b518784863a259f735a72bf Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 17 Jun 2011 11:25:59 +0100 Subject: KEYS/DNS: Fix ____call_usermodehelper() to not lose the session keyring ____call_usermodehelper() now erases any credentials set by the subprocess_inf::init() function. The problem is that commit 17f60a7da150 ("capabilites: allow the application of capability limits to usermode helpers") creates and commits new credentials with prepare_kernel_cred() after the call to the init() function. This wipes all keyrings after umh_keys_init() is called. The best way to deal with this is to put the init() call just prior to the commit_creds() call, and pass the cred pointer to init(). That means that umh_keys_init() and suchlike can modify the credentials _before_ they are published and potentially in use by the rest of the system. This prevents request_key() from working as it is prevented from passing the session keyring it set up with the authorisation token to /sbin/request-key, and so the latter can't assume the authority to instantiate the key. This causes the in-kernel DNS resolver to fail with ENOKEY unconditionally. Signed-off-by: David Howells Acked-by: Eric Paris Tested-by: Jeff Layton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- include/linux/kmod.h | 8 ++++---- kernel/kmod.c | 16 +++++++++------- security/keys/request_key.c | 3 +-- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 97e0d52d72fd..6075a1e727ae 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1996,7 +1996,7 @@ static void wait_for_dump_helpers(struct file *file) * is a special value that we use to trap recursive * core dumps */ -static int umh_pipe_setup(struct subprocess_info *info) +static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) { struct file *rp, *wp; struct fdtable *fdt; diff --git a/include/linux/kmod.h b/include/linux/kmod.h index d4a5c84c503d..0da38cf7db7b 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -45,7 +45,7 @@ static inline int request_module_nowait(const char *name, ...) { return -ENOSYS; #endif -struct key; +struct cred; struct file; enum umh_wait { @@ -62,7 +62,7 @@ struct subprocess_info { char **envp; enum umh_wait wait; int retval; - int (*init)(struct subprocess_info *info); + int (*init)(struct subprocess_info *info, struct cred *new); void (*cleanup)(struct subprocess_info *info); void *data; }; @@ -73,7 +73,7 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, /* Set various pieces of state into the subprocess_info structure */ void call_usermodehelper_setfns(struct subprocess_info *info, - int (*init)(struct subprocess_info *info), + int (*init)(struct subprocess_info *info, struct cred *new), void (*cleanup)(struct subprocess_info *info), void *data); @@ -87,7 +87,7 @@ void call_usermodehelper_freeinfo(struct subprocess_info *info); static inline int call_usermodehelper_fns(char *path, char **argv, char **envp, enum umh_wait wait, - int (*init)(struct subprocess_info *info), + int (*init)(struct subprocess_info *info, struct cred *new), void (*cleanup)(struct subprocess_info *), void *data) { struct subprocess_info *info; diff --git a/kernel/kmod.c b/kernel/kmod.c index ad6a81c58b44..47613dfb7b28 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -156,12 +156,6 @@ static int ____call_usermodehelper(void *data) */ set_user_nice(current, 0); - if (sub_info->init) { - retval = sub_info->init(sub_info); - if (retval) - goto fail; - } - retval = -ENOMEM; new = prepare_kernel_cred(current); if (!new) @@ -173,6 +167,14 @@ static int ____call_usermodehelper(void *data) new->cap_inheritable); spin_unlock(&umh_sysctl_lock); + if (sub_info->init) { + retval = sub_info->init(sub_info, new); + if (retval) { + abort_creds(new); + goto fail; + } + } + commit_creds(new); retval = kernel_execve(sub_info->path, @@ -388,7 +390,7 @@ EXPORT_SYMBOL(call_usermodehelper_setup); * context in which call_usermodehelper_exec is called. */ void call_usermodehelper_setfns(struct subprocess_info *info, - int (*init)(struct subprocess_info *info), + int (*init)(struct subprocess_info *info, struct cred *new), void (*cleanup)(struct subprocess_info *info), void *data) { diff --git a/security/keys/request_key.c b/security/keys/request_key.c index d31862e0aa1c..8e319a416eec 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -71,9 +71,8 @@ EXPORT_SYMBOL(complete_request_key); * This is called in context of freshly forked kthread before kernel_execve(), * so we can simply install the desired session_keyring at this point. */ -static int umh_keys_init(struct subprocess_info *info) +static int umh_keys_init(struct subprocess_info *info, struct cred *cred) { - struct cred *cred = (struct cred*)current_cred(); struct key *keyring = info->data; return install_session_keyring_to_cred(cred, keyring); -- cgit v1.2.3 From 7585717f304f5ed005cc4ad933a69aab3efbd136 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 13 Jun 2011 20:00:16 -0400 Subject: Btrfs: fix relocation races The recent commit to get rid of our trans_mutex introduced some races with block group relocation. The problem is that relocation needs to do some record keeping about each root, and it was relying on the transaction mutex to coordinate things in subtle ways. This fix adds a mutex just for the relocation code and makes sure it doesn't have a big impact on normal operations. The race is really fixed in btrfs_record_root_in_trans, which is where we step back and wait for the relocation code to finish accounting setup. Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 14 ++++++++++ fs/btrfs/disk-io.c | 1 + fs/btrfs/relocation.c | 30 ++++++++++++++------- fs/btrfs/transaction.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 105 insertions(+), 13 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8490ee063709..a2c91a102b72 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -967,6 +967,12 @@ struct btrfs_fs_info { struct srcu_struct subvol_srcu; spinlock_t trans_lock; + /* + * the reloc mutex goes with the trans lock, it is taken + * during commit to protect us from the relocation code + */ + struct mutex reloc_mutex; + struct list_head trans_list; struct list_head hashers; struct list_head dead_roots; @@ -1172,6 +1178,14 @@ struct btrfs_root { u32 type; u64 highest_objectid; + + /* btrfs_record_root_in_trans is a multi-step process, + * and it can race with the balancing code. But the + * race is very small, and only the first time the root + * is added to each transaction. So in_trans_setup + * is used to tell us when more checks are required + */ + unsigned long in_trans_setup; int ref_cows; int track_dirty; int in_radix; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 20c111b3fa0d..0b2b4b759136 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1620,6 +1620,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, spin_lock_init(&fs_info->fs_roots_radix_lock); spin_lock_init(&fs_info->delayed_iput_lock); spin_lock_init(&fs_info->defrag_inodes_lock); + mutex_init(&fs_info->reloc_mutex); init_completion(&fs_info->kobj_unregister); fs_info->tree_root = tree_root; diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index f25b10a22a0a..086b1e6b8614 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1368,7 +1368,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, int ret; if (!root->reloc_root) - return 0; + goto out; reloc_root = root->reloc_root; root_item = &reloc_root->root_item; @@ -1390,6 +1390,8 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, ret = btrfs_update_root(trans, root->fs_info->tree_root, &reloc_root->root_key, root_item); BUG_ON(ret); + +out: return 0; } @@ -2142,10 +2144,11 @@ int prepare_to_merge(struct reloc_control *rc, int err) u64 num_bytes = 0; int ret; - spin_lock(&root->fs_info->trans_lock); + mutex_lock(&root->fs_info->reloc_mutex); rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; rc->merging_rsv_size += rc->nodes_relocated * 2; - spin_unlock(&root->fs_info->trans_lock); + mutex_unlock(&root->fs_info->reloc_mutex); + again: if (!err) { num_bytes = rc->merging_rsv_size; @@ -2214,9 +2217,16 @@ int merge_reloc_roots(struct reloc_control *rc) int ret; again: root = rc->extent_root; - spin_lock(&root->fs_info->trans_lock); + + /* + * this serializes us with btrfs_record_root_in_transaction, + * we have to make sure nobody is in the middle of + * adding their roots to the list while we are + * doing this splice + */ + mutex_lock(&root->fs_info->reloc_mutex); list_splice_init(&rc->reloc_roots, &reloc_roots); - spin_unlock(&root->fs_info->trans_lock); + mutex_unlock(&root->fs_info->reloc_mutex); while (!list_empty(&reloc_roots)) { found = 1; @@ -3590,17 +3600,19 @@ next: static void set_reloc_control(struct reloc_control *rc) { struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; - spin_lock(&fs_info->trans_lock); + + mutex_lock(&fs_info->reloc_mutex); fs_info->reloc_ctl = rc; - spin_unlock(&fs_info->trans_lock); + mutex_unlock(&fs_info->reloc_mutex); } static void unset_reloc_control(struct reloc_control *rc) { struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; - spin_lock(&fs_info->trans_lock); + + mutex_lock(&fs_info->reloc_mutex); fs_info->reloc_ctl = NULL; - spin_unlock(&fs_info->trans_lock); + mutex_unlock(&fs_info->reloc_mutex); } static int check_extent_flags(u64 flags) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2b3590b9fe98..833996a0c628 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -126,28 +126,85 @@ static noinline int join_transaction(struct btrfs_root *root, int nofail) * to make sure the old root from before we joined the transaction is deleted * when the transaction commits */ -int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, +static int record_root_in_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root) { if (root->ref_cows && root->last_trans < trans->transid) { WARN_ON(root == root->fs_info->extent_root); WARN_ON(root->commit_root != root->node); + /* + * see below for in_trans_setup usage rules + * we have the reloc mutex held now, so there + * is only one writer in this function + */ + root->in_trans_setup = 1; + + /* make sure readers find in_trans_setup before + * they find our root->last_trans update + */ + smp_wmb(); + spin_lock(&root->fs_info->fs_roots_radix_lock); if (root->last_trans == trans->transid) { spin_unlock(&root->fs_info->fs_roots_radix_lock); return 0; } - root->last_trans = trans->transid; radix_tree_tag_set(&root->fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, BTRFS_ROOT_TRANS_TAG); spin_unlock(&root->fs_info->fs_roots_radix_lock); + root->last_trans = trans->transid; + + /* this is pretty tricky. We don't want to + * take the relocation lock in btrfs_record_root_in_trans + * unless we're really doing the first setup for this root in + * this transaction. + * + * Normally we'd use root->last_trans as a flag to decide + * if we want to take the expensive mutex. + * + * But, we have to set root->last_trans before we + * init the relocation root, otherwise, we trip over warnings + * in ctree.c. The solution used here is to flag ourselves + * with root->in_trans_setup. When this is 1, we're still + * fixing up the reloc trees and everyone must wait. + * + * When this is zero, they can trust root->last_trans and fly + * through btrfs_record_root_in_trans without having to take the + * lock. smp_wmb() makes sure that all the writes above are + * done before we pop in the zero below + */ btrfs_init_reloc_root(trans, root); + smp_wmb(); + root->in_trans_setup = 0; } return 0; } + +int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + if (!root->ref_cows) + return 0; + + /* + * see record_root_in_trans for comments about in_trans_setup usage + * and barriers + */ + smp_rmb(); + if (root->last_trans == trans->transid && + !root->in_trans_setup) + return 0; + + mutex_lock(&root->fs_info->reloc_mutex); + record_root_in_trans(trans, root); + mutex_unlock(&root->fs_info->reloc_mutex); + + return 0; +} + /* wait for commit against the current transaction to become unblocked * when this is done, it is safe to start a new transaction, but the current * transaction might not be fully on disk. @@ -882,7 +939,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, parent = dget_parent(dentry); parent_inode = parent->d_inode; parent_root = BTRFS_I(parent_inode)->root; - btrfs_record_root_in_trans(trans, parent_root); + record_root_in_trans(trans, parent_root); /* * insert the directory item @@ -900,7 +957,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ret = btrfs_update_inode(trans, parent_root, parent_inode); BUG_ON(ret); - btrfs_record_root_in_trans(trans, root); + record_root_in_trans(trans, root); btrfs_set_root_last_snapshot(&root->root_item, trans->transid); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); btrfs_check_and_init_root_item(new_root_item); @@ -1247,6 +1304,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, } while (atomic_read(&cur_trans->num_writers) > 1 || (should_grow && cur_trans->num_joined != joined)); + /* + * the reloc mutex makes sure that we stop + * the balancing code from coming in and moving + * extents around in the middle of the commit + */ + mutex_lock(&root->fs_info->reloc_mutex); + ret = create_pending_snapshots(trans, root->fs_info); BUG_ON(ret); @@ -1312,6 +1376,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, root->fs_info->running_transaction = NULL; root->fs_info->trans_no_join = 0; spin_unlock(&root->fs_info->trans_lock); + mutex_unlock(&root->fs_info->reloc_mutex); wake_up(&root->fs_info->transaction_wait); -- cgit v1.2.3 From f6ba6fe2d913da6707a71a413d6ec8ae98d6ce18 Mon Sep 17 00:00:00 2001 From: Alex He Date: Wed, 8 Jun 2011 18:34:06 +0800 Subject: xHCI 1.0: Incompatible Device Error It is one new TRB Completion Code for the xHCI spec v1.0. Asserted if the xHC detects a problem with a device that does not allow it to be successfully accessed, e.g. due to a device compliance or compatibility problem. This error may be returned by any command or transfer, and is fatal as far as the Slot is concerned. Return -EPROTO by urb->status or frame->status of ISOC for transfer case. And return -ENODEV for configure endpoint command, evaluate context command and address device command if there is an incompatible Device Error. The error codes will be sent back to the USB core to decide how to do. It's unnecessary for other commands because after the three commands run successfully means that the device has been accepted. Signed-off-by: Alex He Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-ring.c | 5 +++++ drivers/usb/host/xhci.c | 15 +++++++++++++++ drivers/usb/host/xhci.h | 2 ++ 3 files changed, 22 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 0c008497edfd..436332aa341b 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1733,6 +1733,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, frame->status = -EOVERFLOW; skip_td = true; break; + case COMP_DEV_ERR: case COMP_STALL: frame->status = -EPROTO; skip_td = true; @@ -2016,6 +2017,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), ep_index); goto cleanup; + case COMP_DEV_ERR: + xhci_warn(xhci, "WARN: detect an incompatible device"); + status = -EPROTO; + break; case COMP_MISSED_INT: /* * When encounter missed service error, one or more isoc tds diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index e5a01713f937..15eb4c3d793c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1551,6 +1551,11 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci, "and endpoint is not disabled.\n"); ret = -EINVAL; break; + case COMP_DEV_ERR: + dev_warn(&udev->dev, "ERROR: Incompatible device for endpoint " + "configure command.\n"); + ret = -ENODEV; + break; case COMP_SUCCESS: dev_dbg(&udev->dev, "Successful Endpoint Configure command\n"); ret = 0; @@ -1585,6 +1590,11 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1); ret = -EINVAL; break; + case COMP_DEV_ERR: + dev_warn(&udev->dev, "ERROR: Incompatible device for evaluate " + "context command.\n"); + ret = -ENODEV; + break; case COMP_MEL_ERR: /* Max Exit Latency too large error */ dev_warn(&udev->dev, "WARN: Max Exit Latency too large\n"); @@ -2867,6 +2877,11 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) dev_warn(&udev->dev, "Device not responding to set address.\n"); ret = -EPROTO; break; + case COMP_DEV_ERR: + dev_warn(&udev->dev, "ERROR: Incompatible device for address " + "device command.\n"); + ret = -ENODEV; + break; case COMP_SUCCESS: xhci_dbg(xhci, "Successful Address Device command\n"); break; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 7d1ea3bf5e1f..ba90af1c34b4 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -874,6 +874,8 @@ struct xhci_transfer_event { #define COMP_PING_ERR 20 /* Event Ring is full */ #define COMP_ER_FULL 21 +/* Incompatible Device Error */ +#define COMP_DEV_ERR 22 /* Missed Service Error - HC couldn't service an isoc ep within interval */ #define COMP_MISSED_INT 23 /* Successfully stopped command ring */ -- cgit v1.2.3 From c877b3b2ad5cb9d4fe523c5496185cc328ff3ae9 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 15 Jun 2011 23:47:21 +0200 Subject: xhci: Add reset on resume quirk for asrock p67 host The asrock p67 xhci controller completely dies on resume, add a quirk for this, to bring the host back online after a suspend. This should be backported to stable kernels as old as 2.6.37. Signed-off-by: Maarten Lankhorst Signed-off-by: Sarah Sharp Cc: stable@kernel.org --- drivers/usb/host/xhci-pci.c | 8 ++++++++ drivers/usb/host/xhci.c | 2 ++ drivers/usb/host/xhci.h | 1 + 3 files changed, 11 insertions(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 17541d09eabb..cb16de213f64 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -29,6 +29,9 @@ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 +#define PCI_VENDOR_ID_ETRON 0x1b6f +#define PCI_DEVICE_ID_ASROCK_P67 0x7023 + static const char hcd_name[] = "xhci_hcd"; /* called after powerup, by probe or system-pm "wakeup" */ @@ -134,6 +137,11 @@ static int xhci_pci_setup(struct usb_hcd *hcd) xhci->quirks |= XHCI_EP_LIMIT_QUIRK; xhci->limit_active_eps = 64; } + if (pdev->vendor == PCI_VENDOR_ID_ETRON && + pdev->device == PCI_DEVICE_ID_ASROCK_P67) { + xhci->quirks |= XHCI_RESET_ON_RESUME; + xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); + } /* Make sure the HC is halted. */ retval = xhci_halt(xhci); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 15eb4c3d793c..f5fe1ac301ab 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -759,6 +759,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) msleep(100); spin_lock_irq(&xhci->lock); + if (xhci->quirks & XHCI_RESET_ON_RESUME) + hibernated = true; if (!hibernated) { /* step 1: restore register */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ba90af1c34b4..d8bbf5ccb10d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1310,6 +1310,7 @@ struct xhci_hcd { */ #define XHCI_EP_LIMIT_QUIRK (1 << 5) #define XHCI_BROKEN_MSI (1 << 6) +#define XHCI_RESET_ON_RESUME (1 << 7) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ -- cgit v1.2.3 From b3df3f9c7df9a8d85e03e158d35487618a160901 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 15 Jun 2011 19:57:46 -0700 Subject: xhci: Always set urb->status to zero for isoc endpoints. When the xHCI driver encounters a Missed Service Interval event for an isochronous endpoint ring, it means the host controller skipped over one or more isochronous TDs. For TD that is skipped, skip_isoc_td() is called. This sets the frame descriptor status to -EXDEV, and also sets the value stored in the int pointed to by status to -EXDEV. If the isochronous TD happens to be the last TD in an URB, handle_tx_event() will use the status variable to give back the URB to the USB core. That means drivers will see urb->status as -EXDEV. It turns out that EHCI, UHCI, and OHCI always set urb->status to zero for an isochronous urb, regardless of what the frame status is. See itd_complete() in ehci-sched.c: } else { /* URB was too late */ desc->status = -EXDEV; } } /* handle completion now? */ if (likely ((urb_index + 1) != urb->number_of_packets)) goto done; /* ASSERT: it's really the last itd for this urb list_for_each_entry (itd, &stream->td_list, itd_list) BUG_ON (itd->urb == urb); */ /* give urb back to the driver; completion often (re)submits */ dev = urb->dev; ehci_urb_done(ehci, urb, 0); ehci_urb_done() completes the URB with the status of the third argument, which is always zero in this case. It turns out that many USB webcam drivers, such as uvcvideo, cannot handle urb->status set to a non-zero value. They will not resubmit their isochronous URBs in that case, and userspace will see a frozen video. Change the xHCI driver to be consistent with the EHCI and UHCI driver, and always set urb->status to 0 for isochronous URBs. This patch should be backported to kernels as old as 2.6.36 Signed-off-by: Sarah Sharp Cc: "Xu, Andiry" Cc: stable@kernel.org --- drivers/usb/host/xhci-ring.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 436332aa341b..70cacbbe7fb9 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1768,9 +1768,6 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, } } - if ((idx == urb_priv->length - 1) && *status == -EINPROGRESS) - *status = 0; - return finish_td(xhci, td, event_trb, event, ep, status, false); } @@ -1788,8 +1785,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, idx = urb_priv->td_cnt; frame = &td->urb->iso_frame_desc[idx]; - /* The transfer is partly done */ - *status = -EXDEV; + /* The transfer is partly done. */ frame->status = -EXDEV; /* calc actual length */ @@ -2177,6 +2173,11 @@ cleanup: urb->transfer_buffer_length, status); spin_unlock(&xhci->lock); + /* EHCI, UHCI, and OHCI always unconditionally set the + * urb->status of an isochronous endpoint to 0. + */ + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + status = 0; usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status); spin_lock(&xhci->lock); } -- cgit v1.2.3 From a9e758634f464ffb09344821a9f0b5a5c6df2b3e Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 16 Jun 2011 13:06:04 -0700 Subject: USB: Fix up URB error codes to reflect implementation. Documentation/usb/error-codes.txt mentions that urb->status can be set to -EXDEV, if the isochronous transfer was not fully completed. However, in practice, EHCI, UHCI, and OHCI all only set -EXDEV in the individual frame status, never in the URB status. Those host controller actually always pass in a zero status to usb_hcd_giveback_urb, and rely on the core to set the appropriate status value. The xHCI driver ran into issues with the uvcvideo driver when it tried to set -EXDEV in urb->status, because the driver refused to submit URBs, and the userspace camera application's video froze. Clean up the documentation to reflect the actual implementation. Signed-off-by: Sarah Sharp Acked-by: Alan Stern --- Documentation/usb/error-codes.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt index d83703ea74b2..b3f606b81a03 100644 --- a/Documentation/usb/error-codes.txt +++ b/Documentation/usb/error-codes.txt @@ -76,6 +76,13 @@ A transfer's actual_length may be positive even when an error has been reported. That's because transfers often involve several packets, so that one or more packets could finish before an error stops further endpoint I/O. +For isochronous URBs, the urb status value is non-zero only if the URB is +unlinked, the device is removed, the host controller is disabled, or the total +transferred length is less than the requested length and the URB_SHORT_NOT_OK +flag is set. Completion handlers for isochronous URBs should only see +urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO. +Individual frame descriptor status fields may report more status codes. + 0 Transfer completed successfully @@ -132,7 +139,7 @@ one or more packets could finish before an error stops further endpoint I/O. device removal events immediately. -EXDEV ISO transfer only partially completed - look at individual frame status for details + (only set in iso_frame_desc[n].status, not urb->status) -EINVAL ISO madness, if this happens: Log off and go home -- cgit v1.2.3 From 2ff7d09a1b0f20f2d9c1bde0e003d4e384de2313 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 1 Jun 2011 17:49:14 +0000 Subject: RDMA/cxgb4: Don't exceed hw IQ depth limit for user CQs Memory allocated for user CQs gets rounded up to the next page boundary. And after rounding, we recalculate the resulting IQ depth and we need to make sure we don't exceed the HW limits. This bug can result a much smaller CQ allocated than was expected if the HW size field is exceeded, resulting in CQ overflow failures. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/cq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index 8d8f8add6fcd..1720dc790d13 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -801,6 +801,10 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, if (ucontext) { memsize = roundup(memsize, PAGE_SIZE); hwentries = memsize / sizeof *chp->cq.queue; + while (hwentries > T4_MAX_IQ_SIZE) { + memsize -= PAGE_SIZE; + hwentries = memsize / sizeof *chp->cq.queue; + } } chp->cq.size = hwentries; chp->cq.memsize = memsize; -- cgit v1.2.3 From 3ed4498caf381a73d6259d3ffacc914b17a507ec Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 13 Jun 2011 17:54:22 +0000 Subject: btrfs: fix dereference of ERR_PTR value smatch reports: btrfs_recover_log_trees error: 'wc.replay_dest' dereferencing possible ERR_PTR() Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/tree-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 592396c6dc47..4ce8a9f41d1e 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3177,7 +3177,7 @@ again: tmp_key.offset = (u64)-1; wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); - BUG_ON(!wc.replay_dest); + BUG_ON(IS_ERR_OR_NULL(wc.replay_dest)); wc.replay_dest->log_root = log; btrfs_record_root_in_trans(trans, wc.replay_dest); -- cgit v1.2.3 From 9fe6a50fb764f508dd2de47a66e62e51388791fb Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 16 Jun 2011 09:04:57 +0000 Subject: btrfs: Remove unused sysfs code Removes code no longer used. The sysfs file itself is kept, because the btrfs developers expressed interest in putting new entries to sysfs. Signed-off-by: Maarten Lankhorst Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 1 - fs/btrfs/disk-io.c | 1 - fs/btrfs/sysfs.c | 146 ----------------------------------------------------- 3 files changed, 148 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index a2c91a102b72..8e948ec1ee6b 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1195,7 +1195,6 @@ struct btrfs_root { struct btrfs_key defrag_max; int defrag_running; char *name; - int in_sysfs; /* the dirty list is only used by non-reference counted roots */ struct list_head dirty_list; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0b2b4b759136..c25ef5a0ccd6 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1044,7 +1044,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, root->last_trans = 0; root->highest_objectid = 0; root->name = NULL; - root->in_sysfs = 0; root->inode_tree = RB_ROOT; INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); root->block_rsv = NULL; diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index c3c223ae6691..daac9ae6d731 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -28,152 +28,6 @@ #include "disk-io.h" #include "transaction.h" -static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_root_used(&root->root_item)); -} - -static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_root_limit(&root->root_item)); -} - -static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf) -{ - - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_super_bytes_used(&fs->super_copy)); -} - -static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_super_total_bytes(&fs->super_copy)); -} - -static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_super_sectorsize(&fs->super_copy)); -} - -/* this is for root attrs (subvols/snapshots) */ -struct btrfs_root_attr { - struct attribute attr; - ssize_t (*show)(struct btrfs_root *, char *); - ssize_t (*store)(struct btrfs_root *, const char *, size_t); -}; - -#define ROOT_ATTR(name, mode, show, store) \ -static struct btrfs_root_attr btrfs_root_attr_##name = __ATTR(name, mode, \ - show, store) - -ROOT_ATTR(blocks_used, 0444, root_blocks_used_show, NULL); -ROOT_ATTR(block_limit, 0644, root_block_limit_show, NULL); - -static struct attribute *btrfs_root_attrs[] = { - &btrfs_root_attr_blocks_used.attr, - &btrfs_root_attr_block_limit.attr, - NULL, -}; - -/* this is for super attrs (actual full fs) */ -struct btrfs_super_attr { - struct attribute attr; - ssize_t (*show)(struct btrfs_fs_info *, char *); - ssize_t (*store)(struct btrfs_fs_info *, const char *, size_t); -}; - -#define SUPER_ATTR(name, mode, show, store) \ -static struct btrfs_super_attr btrfs_super_attr_##name = __ATTR(name, mode, \ - show, store) - -SUPER_ATTR(blocks_used, 0444, super_blocks_used_show, NULL); -SUPER_ATTR(total_blocks, 0444, super_total_blocks_show, NULL); -SUPER_ATTR(blocksize, 0444, super_blocksize_show, NULL); - -static struct attribute *btrfs_super_attrs[] = { - &btrfs_super_attr_blocks_used.attr, - &btrfs_super_attr_total_blocks.attr, - &btrfs_super_attr_blocksize.attr, - NULL, -}; - -static ssize_t btrfs_super_attr_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, - super_kobj); - struct btrfs_super_attr *a = container_of(attr, - struct btrfs_super_attr, - attr); - - return a->show ? a->show(fs, buf) : 0; -} - -static ssize_t btrfs_super_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, size_t len) -{ - struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, - super_kobj); - struct btrfs_super_attr *a = container_of(attr, - struct btrfs_super_attr, - attr); - - return a->store ? a->store(fs, buf, len) : 0; -} - -static ssize_t btrfs_root_attr_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct btrfs_root *root = container_of(kobj, struct btrfs_root, - root_kobj); - struct btrfs_root_attr *a = container_of(attr, - struct btrfs_root_attr, - attr); - - return a->show ? a->show(root, buf) : 0; -} - -static ssize_t btrfs_root_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, size_t len) -{ - struct btrfs_root *root = container_of(kobj, struct btrfs_root, - root_kobj); - struct btrfs_root_attr *a = container_of(attr, - struct btrfs_root_attr, - attr); - return a->store ? a->store(root, buf, len) : 0; -} - -static void btrfs_super_release(struct kobject *kobj) -{ - struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, - super_kobj); - complete(&fs->kobj_unregister); -} - -static void btrfs_root_release(struct kobject *kobj) -{ - struct btrfs_root *root = container_of(kobj, struct btrfs_root, - root_kobj); - complete(&root->kobj_unregister); -} - -static const struct sysfs_ops btrfs_super_attr_ops = { - .show = btrfs_super_attr_show, - .store = btrfs_super_attr_store, -}; - -static const struct sysfs_ops btrfs_root_attr_ops = { - .show = btrfs_root_attr_show, - .store = btrfs_root_attr_store, -}; - /* /sys/fs/btrfs/ entry */ static struct kset *btrfs_kset; -- cgit v1.2.3 From 19fd294957e426bfdd8e19085096467ec18df5c4 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Wed, 15 Jun 2011 10:47:30 +0000 Subject: btrfs: fix wrong reservation when doing delayed inode operations We have migrated the space for the delayed inode items from trans_block_rsv to global_block_rsv, but we forgot to set trans->block_rsv to global_block_rsv when we doing delayed inode operations, and the following Oops happened: [ 9792.654889] ------------[ cut here ]------------ [ 9792.654898] WARNING: at fs/btrfs/extent-tree.c:5681 btrfs_alloc_free_block+0xca/0x27c [btrfs]() [ 9792.654899] Hardware name: To Be Filled By O.E.M. [ 9792.654900] Modules linked in: btrfs zlib_deflate libcrc32c ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables arc4 rt61pci rt2x00pci rt2x00lib snd_hda_codec_hdmi mac80211 snd_hda_codec_realtek cfg80211 snd_hda_intel edac_core snd_seq rfkill pcspkr serio_raw snd_hda_codec eeprom_93cx6 edac_mce_amd sp5100_tco i2c_piix4 k10temp snd_hwdep snd_seq_device snd_pcm floppy r8169 xhci_hcd mii snd_timer snd soundcore snd_page_alloc ipv6 firewire_ohci pata_acpi ata_generic firewire_core pata_via crc_itu_t radeon ttm drm_kms_helper drm i2c_algo_bit i2c_core [last unloaded: scsi_wait_scan] [ 9792.654919] Pid: 2762, comm: rm Tainted: G W 2.6.39+ #1 [ 9792.654920] Call Trace: [ 9792.654922] [] warn_slowpath_common+0x83/0x9b [ 9792.654925] [] warn_slowpath_null+0x1a/0x1c [ 9792.654933] [] btrfs_alloc_free_block+0xca/0x27c [btrfs] [ 9792.654945] [] ? map_extent_buffer+0x6e/0xa8 [btrfs] [ 9792.654953] [] __btrfs_cow_block+0xfc/0x30c [btrfs] [ 9792.654963] [] ? btrfs_buffer_uptodate+0x47/0x58 [btrfs] [ 9792.654970] [] ? read_block_for_search+0x94/0x368 [btrfs] [ 9792.654978] [] btrfs_cow_block+0xfe/0x146 [btrfs] [ 9792.654986] [] btrfs_search_slot+0x14d/0x4b6 [btrfs] [ 9792.654997] [] ? map_extent_buffer+0x6e/0xa8 [btrfs] [ 9792.655022] [] btrfs_lookup_inode+0x2f/0x8f [btrfs] [ 9792.655025] [] ? _cond_resched+0xe/0x22 [ 9792.655027] [] ? mutex_lock+0x29/0x50 [ 9792.655039] [] btrfs_update_delayed_inode+0x72/0x137 [btrfs] [ 9792.655051] [] btrfs_run_delayed_items+0x90/0xdb [btrfs] [ 9792.655062] [] btrfs_commit_transaction+0x228/0x654 [btrfs] [ 9792.655064] [] ? remove_wait_queue+0x3a/0x3a [ 9792.655075] [] btrfs_evict_inode+0x14d/0x202 [btrfs] [ 9792.655077] [] evict+0x71/0x111 [ 9792.655079] [] iput+0x12a/0x132 [ 9792.655081] [] do_unlinkat+0x106/0x155 [ 9792.655083] [] ? path_put+0x1f/0x23 [ 9792.655085] [] ? audit_syscall_entry+0x145/0x171 [ 9792.655087] [] ? putname+0x34/0x36 [ 9792.655090] [] sys_unlinkat+0x29/0x2b [ 9792.655092] [] system_call_fastpath+0x16/0x1b [ 9792.655093] ---[ end trace 02b696eb02b3f768 ]--- This patch fix it by setting the reservation of the transaction handle to the correct one. Reported-by: Josef Bacik Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/delayed-inode.c | 25 ++++++++++++++++++++----- fs/btrfs/delayed-inode.h | 1 - 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 6462c29d2d37..fc515b787e8c 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -297,7 +297,6 @@ struct btrfs_delayed_item *btrfs_alloc_delayed_item(u32 data_len) item->data_len = data_len; item->ins_or_del = 0; item->bytes_reserved = 0; - item->block_rsv = NULL; item->delayed_node = NULL; atomic_set(&item->refs, 1); } @@ -593,10 +592,8 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, num_bytes = btrfs_calc_trans_metadata_size(root, 1); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); - if (!ret) { + if (!ret) item->bytes_reserved = num_bytes; - item->block_rsv = dst_rsv; - } return ret; } @@ -604,10 +601,13 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, struct btrfs_delayed_item *item) { + struct btrfs_block_rsv *rsv; + if (!item->bytes_reserved) return; - btrfs_block_rsv_release(root, item->block_rsv, + rsv = &root->fs_info->global_block_rsv; + btrfs_block_rsv_release(root, rsv, item->bytes_reserved); } @@ -1014,6 +1014,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, struct btrfs_delayed_root *delayed_root; struct btrfs_delayed_node *curr_node, *prev_node; struct btrfs_path *path; + struct btrfs_block_rsv *block_rsv; int ret = 0; path = btrfs_alloc_path(); @@ -1021,6 +1022,9 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, return -ENOMEM; path->leave_spinning = 1; + block_rsv = trans->block_rsv; + trans->block_rsv = &root->fs_info->global_block_rsv; + delayed_root = btrfs_get_delayed_root(root); curr_node = btrfs_first_delayed_node(delayed_root); @@ -1045,6 +1049,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, } btrfs_free_path(path); + trans->block_rsv = block_rsv; return ret; } @@ -1052,6 +1057,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, struct btrfs_delayed_node *node) { struct btrfs_path *path; + struct btrfs_block_rsv *block_rsv; int ret; path = btrfs_alloc_path(); @@ -1059,6 +1065,9 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, return -ENOMEM; path->leave_spinning = 1; + block_rsv = trans->block_rsv; + trans->block_rsv = &node->root->fs_info->global_block_rsv; + ret = btrfs_insert_delayed_items(trans, path, node->root, node); if (!ret) ret = btrfs_delete_delayed_items(trans, path, node->root, node); @@ -1066,6 +1075,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, ret = btrfs_update_delayed_inode(trans, node->root, path, node); btrfs_free_path(path); + trans->block_rsv = block_rsv; return ret; } @@ -1116,6 +1126,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) struct btrfs_path *path; struct btrfs_delayed_node *delayed_node = NULL; struct btrfs_root *root; + struct btrfs_block_rsv *block_rsv; unsigned long nr = 0; int need_requeue = 0; int ret; @@ -1134,6 +1145,9 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) if (IS_ERR(trans)) goto free_path; + block_rsv = trans->block_rsv; + trans->block_rsv = &root->fs_info->global_block_rsv; + ret = btrfs_insert_delayed_items(trans, path, root, delayed_node); if (!ret) ret = btrfs_delete_delayed_items(trans, path, root, @@ -1176,6 +1190,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) nr = trans->blocks_used; + trans->block_rsv = block_rsv; btrfs_end_transaction_dmeta(trans, root); __btrfs_btree_balance_dirty(root, nr); free_path: diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index eb7d240aa648..cb79b6771e82 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -75,7 +75,6 @@ struct btrfs_delayed_item { struct list_head tree_list; /* used for batch insert/delete items */ struct list_head readdir_list; /* used for readdir items */ u64 bytes_reserved; - struct btrfs_block_rsv *block_rsv; struct btrfs_delayed_node *delayed_node; atomic_t refs; int ins_or_del; -- cgit v1.2.3 From 35a30d7ce54e087d8025a725d4e5a2fdee723a9f Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 13 Jun 2011 15:18:23 +0000 Subject: btrfs: fix uninitialized return value When allocation fails in btrfs_read_fs_root_no_name, ret is not set although it is returned, holding a garbage value. Signed-off-by: David Sterba Reviewed-by: Li Zefan Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c25ef5a0ccd6..1ac8db5dc0a3 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1299,12 +1299,12 @@ again: return root; root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS); - if (!root->free_ino_ctl) - goto fail; root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned), GFP_NOFS); - if (!root->free_ino_pinned) + if (!root->free_ino_pinned || !root->free_ino_ctl) { + ret = -ENOMEM; goto fail; + } btrfs_init_free_ino_ctl(root); mutex_init(&root->fs_commit_mutex); -- cgit v1.2.3 From 301c2c3f039a1f9478f6cbef60f2ccd4da9bd4a1 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Tue, 14 Jun 2011 20:59:21 +0000 Subject: RDMA/cxgb4: Don't truncate MR lengths Remove left-over code from T3 that limited MR sizes to 32b. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 273ffe49525a..0347eed4a167 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -625,7 +625,7 @@ pbl_done: mhp->attr.perms = c4iw_ib_to_tpt_access(acc); mhp->attr.va_fbo = virt; mhp->attr.page_size = shift - 12; - mhp->attr.len = (u32) length; + mhp->attr.len = length; err = register_mem(rhp, php, mhp, shift); if (err) -- cgit v1.2.3 From 8da7e7a55231543b84ac84e93ad5ca9d340773d7 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Tue, 14 Jun 2011 20:59:27 +0000 Subject: RDMA/cxgb4: Couple of abort fixes - fix a race where the driver could end up sending a close_con_req after an abort_rpl. In c4iw_ep_disconnect(), send abort or close request with the ep mutex held. - fix a hang where driver fails to wake up when a connection is reset during a normal close. Wake up any waiters in the interrupt path, and correctly cleanup after rdma_fini() failures. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/cm.c | 46 ++++++++++++++++++++++++++++++++-------- drivers/infiniband/hw/cxgb4/qp.c | 5 +---- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index f660cd04ec2f..31fb44085c9b 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1463,9 +1463,9 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) struct c4iw_qp_attributes attrs; int disconnect = 1; int release = 0; - int abort = 0; struct tid_info *t = dev->rdev.lldi.tids; unsigned int tid = GET_TID(hdr); + int ret; ep = lookup_tid(t, tid); PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); @@ -1501,10 +1501,12 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) start_ep_timer(ep); __state_set(&ep->com, CLOSING); attrs.next_state = C4IW_QP_STATE_CLOSING; - abort = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, + ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); - peer_close_upcall(ep); - disconnect = 1; + if (ret != -ECONNRESET) { + peer_close_upcall(ep); + disconnect = 1; + } break; case ABORTING: disconnect = 0; @@ -2109,15 +2111,16 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) break; } - mutex_unlock(&ep->com.mutex); if (close) { - if (abrupt) - ret = abort_connection(ep, NULL, gfp); - else + if (abrupt) { + close_complete_upcall(ep); + ret = send_abort(ep, NULL, gfp); + } else ret = send_halfclose(ep, gfp); if (ret) fatal = 1; } + mutex_unlock(&ep->com.mutex); if (fatal) release_ep_resources(ep); return ret; @@ -2301,6 +2304,31 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) return 0; } +static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) +{ + struct cpl_abort_req_rss *req = cplhdr(skb); + struct c4iw_ep *ep; + struct tid_info *t = dev->rdev.lldi.tids; + unsigned int tid = GET_TID(req); + + ep = lookup_tid(t, tid); + if (is_neg_adv_abort(req->status)) { + PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep, + ep->hwtid); + kfree_skb(skb); + return 0; + } + PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, + ep->com.state); + + /* + * Wake up any threads in rdma_init() or rdma_fini(). + */ + c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); + sched(dev, skb); + return 0; +} + /* * Most upcalls from the T4 Core go to sched() to * schedule the processing on a work queue. @@ -2317,7 +2345,7 @@ c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = { [CPL_PASS_ESTABLISH] = sched, [CPL_PEER_CLOSE] = sched, [CPL_CLOSE_CON_RPL] = sched, - [CPL_ABORT_REQ_RSS] = sched, + [CPL_ABORT_REQ_RSS] = peer_abort_intr, [CPL_RDMA_TERMINATE] = sched, [CPL_FW4_ACK] = sched, [CPL_SET_TCB_RPL] = set_tcb_rpl, diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 3b773b05a898..a41578e48c7b 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1207,11 +1207,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, c4iw_get_ep(&qhp->ep->com); } ret = rdma_fini(rhp, qhp, ep); - if (ret) { - if (internal) - c4iw_get_ep(&qhp->ep->com); + if (ret) goto err; - } break; case C4IW_QP_STATE_TERMINATE: set_state(qhp, C4IW_QP_STATE_TERMINATE); -- cgit v1.2.3 From 3126448451105fae59de0058c68692aa09aa4c37 Mon Sep 17 00:00:00 2001 From: Mitko Haralanov Date: Thu, 9 Jun 2011 20:27:26 +0000 Subject: IB/qib: Ensure that LOS and DFE are being turned off Due to timing, it is possible for the LOS and DFE to remain on. This is due to the link progressing to LinkUP prior to the driver getting the first Status Changed interrupt. By expanding the conditions under which LOS is turned off and DFE timeout is being set, timing is no longer an issue. Signed-off-by: Mitko Haralanov Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_iba7322.c | 25 ++++++++++++++++++------- drivers/infiniband/hw/qib/qib_intr.c | 6 +++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 9f53e68a096a..8ec5237031a0 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -469,6 +469,8 @@ static u8 ib_rate_to_delay[IB_RATE_120_GBPS + 1] = { #define IB_7322_LT_STATE_RECOVERIDLE 0x0f #define IB_7322_LT_STATE_CFGENH 0x10 #define IB_7322_LT_STATE_CFGTEST 0x11 +#define IB_7322_LT_STATE_CFGWAITRMTTEST 0x12 +#define IB_7322_LT_STATE_CFGWAITENH 0x13 /* link state machine states from IBC */ #define IB_7322_L_STATE_DOWN 0x0 @@ -498,8 +500,10 @@ static const u8 qib_7322_physportstate[0x20] = { IB_PHYSPORTSTATE_LINK_ERR_RECOVER, [IB_7322_LT_STATE_CFGENH] = IB_PHYSPORTSTATE_CFG_ENH, [IB_7322_LT_STATE_CFGTEST] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x12] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x13] = IB_PHYSPORTSTATE_CFG_WAIT_ENH, + [IB_7322_LT_STATE_CFGWAITRMTTEST] = + IB_PHYSPORTSTATE_CFG_TRAIN, + [IB_7322_LT_STATE_CFGWAITENH] = + IB_PHYSPORTSTATE_CFG_WAIT_ENH, [0x14] = IB_PHYSPORTSTATE_CFG_TRAIN, [0x15] = IB_PHYSPORTSTATE_CFG_TRAIN, [0x16] = IB_PHYSPORTSTATE_CFG_TRAIN, @@ -1692,7 +1696,9 @@ static void handle_serdes_issues(struct qib_pportdata *ppd, u64 ibcst) break; } - if (ibclt == IB_7322_LT_STATE_CFGTEST && + if (((ibclt >= IB_7322_LT_STATE_CFGTEST && + ibclt <= IB_7322_LT_STATE_CFGWAITENH) || + ibclt == IB_7322_LT_STATE_LINKUP) && (ibcst & SYM_MASK(IBCStatusA_0, LinkSpeedQDR))) { force_h1(ppd); ppd->cpspec->qdr_reforce = 1; @@ -7301,12 +7307,17 @@ static void ibsd_wr_allchans(struct qib_pportdata *ppd, int addr, unsigned data, static void serdes_7322_los_enable(struct qib_pportdata *ppd, int enable) { u64 data = qib_read_kreg_port(ppd, krp_serdesctrl); - printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS %s\n", - ppd->dd->unit, ppd->port, (enable ? "on" : "off")); - if (enable) + u8 state = SYM_FIELD(data, IBSerdesCtrl_0, RXLOSEN); + + if (enable && !state) { + printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS on\n", + ppd->dd->unit, ppd->port); data |= SYM_MASK(IBSerdesCtrl_0, RXLOSEN); - else + } else if (!enable && state) { + printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS off\n", + ppd->dd->unit, ppd->port); data &= ~SYM_MASK(IBSerdesCtrl_0, RXLOSEN); + } qib_write_kreg_port(ppd, krp_serdesctrl, data); } diff --git a/drivers/infiniband/hw/qib/qib_intr.c b/drivers/infiniband/hw/qib/qib_intr.c index a693c56ec8a6..6ae57d23004a 100644 --- a/drivers/infiniband/hw/qib/qib_intr.c +++ b/drivers/infiniband/hw/qib/qib_intr.c @@ -96,8 +96,12 @@ void qib_handle_e_ibstatuschanged(struct qib_pportdata *ppd, u64 ibcs) * states, or if it transitions from any of the up (INIT or better) * states into any of the down states (except link recovery), then * call the chip-specific code to take appropriate actions. + * + * ppd->lflags could be 0 if this is the first time the interrupt + * handlers has been called but the link is already up. */ - if (lstate >= IB_PORT_INIT && (ppd->lflags & QIBL_LINKDOWN) && + if (lstate >= IB_PORT_INIT && + (!ppd->lflags || (ppd->lflags & QIBL_LINKDOWN)) && ltstate == IB_PHYSPORTSTATE_LINKUP) { /* transitioned to UP */ if (dd->f_ib_updown(ppd, 1, ibcs)) -- cgit v1.2.3 From cab758ef30e0e40f783627abc4b66d1b48fecd49 Mon Sep 17 00:00:00 2001 From: Clive Stubbings Date: Thu, 16 Jun 2011 22:30:39 +0000 Subject: fs_enet: fix freescale FCC ethernet dp buffer alignment The RIPTR and TIPTR (receive/transmit internal temporary data pointer), used by microcode as a temporary buffer for data, must be 32-byte aligned according to the RM for MPC8247. Tested on mgcoge. Signed-off-by: Clive Stubbings Signed-off-by: Holger Brunck cc: Pantelis Antoniou cc: Vitaly Bordug cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/fs_enet/mac-fcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 7a84e45487e8..7583a9572bcc 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -105,7 +105,7 @@ static int do_pd_setup(struct fs_enet_private *fep) goto out_ep; fep->fcc.mem = (void __iomem *)cpm2_immr; - fpi->dpram_offset = cpm_dpalloc(128, 8); + fpi->dpram_offset = cpm_dpalloc(128, 32); if (IS_ERR_VALUE(fpi->dpram_offset)) { ret = fpi->dpram_offset; goto out_fcccp; -- cgit v1.2.3 From 1eddceadb0d6441cd39b2c38705a8f5fec86e770 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Jun 2011 03:45:15 +0000 Subject: net: rfs: enable RFS before first data packet is received MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le jeudi 16 juin 2011 à 23:38 -0400, David Miller a écrit : > From: Ben Hutchings > Date: Fri, 17 Jun 2011 00:50:46 +0100 > > > On Wed, 2011-06-15 at 04:15 +0200, Eric Dumazet wrote: > >> @@ -1594,6 +1594,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) > >> goto discard; > >> > >> if (nsk != sk) { > >> + sock_rps_save_rxhash(nsk, skb->rxhash); > >> if (tcp_child_process(sk, nsk, skb)) { > >> rsk = nsk; > >> goto reset; > >> > > > > I haven't tried this, but it looks reasonable to me. > > > > What about IPv6? The logic in tcp_v6_do_rcv() looks very similar. > > Indeed ipv6 side needs the same fix. > > Eric please add that part and resubmit. And in fact I might stick > this into net-2.6 instead of net-next-2.6 > OK, here is the net-2.6 based one then, thanks ! [PATCH v2] net: rfs: enable RFS before first data packet is received First packet received on a passive tcp flow is not correctly RFS steered. One sock_rps_record_flow() call is missing in inet_accept() But before that, we also must record rxhash when child socket is setup. Signed-off-by: Eric Dumazet CC: Tom Herbert CC: Ben Hutchings CC: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 1 + net/ipv4/tcp_ipv4.c | 1 + net/ipv6/tcp_ipv6.c | 1 + 3 files changed, 3 insertions(+) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 9c1926027a26..eae1f676f870 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -676,6 +676,7 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags) lock_sock(sk2); + sock_rps_record_flow(sk2); WARN_ON(!((1 << sk2->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a7d6671e33b8..708dc203b034 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1589,6 +1589,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) goto discard; if (nsk != sk) { + sock_rps_save_rxhash(nsk, skb->rxhash); if (tcp_child_process(sk, nsk, skb)) { rsk = nsk; goto reset; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d1fd28711ba5..87551ca568cd 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1644,6 +1644,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) * the new socket.. */ if(nsk != sk) { + sock_rps_save_rxhash(nsk, skb->rxhash); if (tcp_child_process(sk, nsk, skb)) goto reset; if (opt_skb) -- cgit v1.2.3 From d0fd64c1de437bdf91c32d4f84a53fa4b2150348 Mon Sep 17 00:00:00 2001 From: Pavel Shved Date: Fri, 17 Jun 2011 06:25:10 +0000 Subject: farsync: add module_put to error path in fst_open() The fst_open() function, after a successful try_module_get() may return an error code if hdlc_open() returns it. However, it does not put the module on this error path. This patch adds the necessary module_put() call. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Pavel Shved Signed-off-by: David S. Miller --- drivers/net/wan/farsync.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index e050bd65e037..777d1a4e81b2 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -2203,8 +2203,10 @@ fst_open(struct net_device *dev) if (port->mode != FST_RAW) { err = hdlc_open(dev); - if (err) + if (err) { + module_put(THIS_MODULE); return err; + } } fst_openport(port); -- cgit v1.2.3 From 2f9381e98471837b631743270de988e78aad1f96 Mon Sep 17 00:00:00 2001 From: Pavel Shved Date: Fri, 17 Jun 2011 06:25:11 +0000 Subject: gigaset: call module_put before restart of if_open() if_open() calls try_module_get(), and after an attempt to lock a mutex the if_open() function may return -ERESTARTSYS without putting the module. Then, when if_open() is executed again, try_module_get() is called making the reference counter of THIS_MODULE greater than one at successful exit from if_open(). The if_close() function puts the module only once, and as a result it can't be unloaded. This patch adds module_put call before the return from if_open(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Pavel Shved Signed-off-by: David S. Miller --- drivers/isdn/gigaset/interface.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 59de638225fe..e35058bcd7b9 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -156,8 +156,10 @@ static int if_open(struct tty_struct *tty, struct file *filp) if (!cs || !try_module_get(cs->driver->owner)) return -ENODEV; - if (mutex_lock_interruptible(&cs->mutex)) + if (mutex_lock_interruptible(&cs->mutex)) { + module_put(cs->driver->owner); return -ERESTARTSYS; + } tty->driver_data = cs; ++cs->open_count; -- cgit v1.2.3 From eeb1497277d6b1a0a34ed36b97e18f2bd7d6de0d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Jun 2011 16:25:39 -0400 Subject: inet_diag: fix inet_diag_bc_audit() A malicious user or buggy application can inject code and trigger an infinite loop in inet_diag_bc_audit() Also make sure each instruction is aligned on 4 bytes boundary, to avoid unaligned accesses. Reported-by: Dan Rosenberg Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 6ffe94ca5bc9..3267d3898437 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc) return 0; if (cc == len) return 1; - if (op->yes < 4) + if (op->yes < 4 || op->yes & 3) return 0; len -= op->yes; bc += op->yes; @@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc) static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) { - const unsigned char *bc = bytecode; + const void *bc = bytecode; int len = bytecode_len; while (len > 0) { - struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc; + const struct inet_diag_bc_op *op = bc; //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); switch (op->code) { @@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) case INET_DIAG_BC_S_LE: case INET_DIAG_BC_D_GE: case INET_DIAG_BC_D_LE: - if (op->yes < 4 || op->yes > len + 4) - return -EINVAL; case INET_DIAG_BC_JMP: - if (op->no < 4 || op->no > len + 4) + if (op->no < 4 || op->no > len + 4 || op->no & 3) return -EINVAL; if (op->no < len && !valid_cc(bytecode, bytecode_len, len - op->no)) return -EINVAL; break; case INET_DIAG_BC_NOP: - if (op->yes < 4 || op->yes > len + 4) - return -EINVAL; break; default: return -EINVAL; } + if (op->yes < 4 || op->yes > len + 4 || op->yes & 3) + return -EINVAL; bc += op->yes; len -= op->yes; } -- cgit v1.2.3 From e999376f094162aa425ae749aa1df95ab928d010 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 17 Jun 2011 16:14:09 -0400 Subject: Btrfs: avoid delayed metadata items during commits Snapshot creation has two phases. One is the initial snapshot setup, and the second is done during commit, while nobody is allowed to modify the root we are snapshotting. The delayed metadata insertion code can break that rule, it does a delayed inode update on the inode of the parent of the snapshot, and delayed directory item insertion. This makes sure to run the pending delayed operations before we record the snapshot root, which avoids corruptions. Signed-off-by: Chris Mason --- fs/btrfs/delayed-inode.c | 7 +++++++ fs/btrfs/delayed-inode.h | 4 ++++ fs/btrfs/transaction.c | 27 +++++++++++++++++---------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index fc515b787e8c..f1cbd028f7b3 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1237,6 +1237,13 @@ again: return 0; } +void btrfs_assert_delayed_root_empty(struct btrfs_root *root) +{ + struct btrfs_delayed_root *delayed_root; + delayed_root = btrfs_get_delayed_root(root); + WARN_ON(btrfs_first_delayed_node(delayed_root)); +} + void btrfs_balance_delayed_items(struct btrfs_root *root) { struct btrfs_delayed_root *delayed_root; diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index cb79b6771e82..d1a6a2915c66 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -137,4 +137,8 @@ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, /* for init */ int __init btrfs_delayed_inode_init(void); void btrfs_delayed_inode_exit(void); + +/* for debugging */ +void btrfs_assert_delayed_root_empty(struct btrfs_root *root); + #endif diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index c073d85e14f3..51dcec86757f 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -957,6 +957,15 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ret = btrfs_update_inode(trans, parent_root, parent_inode); BUG_ON(ret); + /* + * pull in the delayed directory update + * and the delayed inode item + * otherwise we corrupt the FS during + * snapshot + */ + ret = btrfs_run_delayed_items(trans, root); + BUG_ON(ret); + record_root_in_trans(trans, root); btrfs_set_root_last_snapshot(&root->root_item, trans->transid); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); @@ -1018,14 +1027,6 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, int ret; list_for_each_entry(pending, head, list) { - /* - * We must deal with the delayed items before creating - * snapshots, or we will create a snapthot with inconsistent - * information. - */ - ret = btrfs_run_delayed_items(trans, fs_info->fs_root); - BUG_ON(ret); - ret = create_pending_snapshot(trans, fs_info, pending); BUG_ON(ret); } @@ -1319,15 +1320,21 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, */ mutex_lock(&root->fs_info->reloc_mutex); - ret = create_pending_snapshots(trans, root->fs_info); + ret = btrfs_run_delayed_items(trans, root); BUG_ON(ret); - ret = btrfs_run_delayed_items(trans, root); + ret = create_pending_snapshots(trans, root->fs_info); BUG_ON(ret); ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); BUG_ON(ret); + /* + * make sure none of the code above managed to slip in a + * delayed item + */ + btrfs_assert_delayed_root_empty(root); + WARN_ON(cur_trans != trans->transaction); btrfs_scrub_pause(root); -- cgit v1.2.3 From 3744100e05c4e403ed21c99cd389c7e784664e4b Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 17 Jun 2011 22:58:54 +0200 Subject: r8169: fix static initializers. Signed-off-by: Francois Romieu --- drivers/net/r8169.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index ef1ce2ebeb4a..05d81780d1fd 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1621,7 +1621,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, * * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec */ - static const struct { + static const struct rtl_mac_info { u32 mask; u32 val; int mac_version; @@ -1689,7 +1689,8 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, /* Catch-all */ { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; + }; + const struct rtl_mac_info *p = mac_info; u32 reg; reg = RTL_R32(TxConfig); @@ -3681,7 +3682,7 @@ static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) { - static const struct { + static const struct rtl_cfg2_info { u32 mac_version; u32 clk; u32 val; @@ -3690,7 +3691,8 @@ static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; + }; + const struct rtl_cfg2_info *p = cfg2_info; unsigned int i; u32 clk; -- cgit v1.2.3 From 650f156775c2638cc02ed7df31186a09ba79666a Mon Sep 17 00:00:00 2001 From: Jeff Ohlstein Date: Fri, 17 Jun 2011 13:55:38 -0700 Subject: msm: timer: compensate for timer shift in msm_read_timer_count Some msm targets have timers whose lower bits are unreliable. So, we present our timers as lower frequency than they actually are, and ignore the bottom 5 bits on such targets. This compensation was erroneously removed from the msm_read_timer_count function, so restore it. This was broken by 94790ec25 "msm: timer: SMP timer support for msm". Signed-off-by: Jeff Ohlstein --- arch/arm/mach-msm/timer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 9bfdd5ad2441..2232032181be 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -102,7 +102,11 @@ static cycle_t msm_read_timer_count(struct clocksource *cs) { struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource); - return readl(clk->global_counter); + /* + * Shift timer count down by a constant due to unreliable lower bits + * on some targets. + */ + return readl(clk->global_counter) >> clk->shift; } static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt) -- cgit v1.2.3 From 498e720b96379d8ee9c294950a01534a73defcf3 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Fri, 17 Jun 2011 11:32:19 -0700 Subject: drm/i915: Fix gen6 (SNB) missed BLT ring interrupts. The failure appeared in dmesg as: [drm:i915_hangcheck_ring_idle] *ERROR* Hangcheck timer elapsed... blt ring idle [waiting on 35064155, at 35064155], missed IRQ? This works around that problem on by making the blitter command streamer write interrupt state to the Hardware Status Page when a MI_USER_INTERRUPT command is decoded, which appears to force the seqno out to memory before the interrupt happens. v1->v2: Moved to prior interrupt handler installation and RMW flags as per feedback. v2->v3: Removed RMW of flags (by anholt) Cc: stable@kernel.org Signed-off-by: Daniel J Blueman Signed-off-by: Eric Anholt Tested-by: Chris Wilson [v1] Tested-by: Eric Anholt [v1,v3] (incidence of the bug with a testcase went from avg 2/1000 to 0/12651 in the latest test run (plus more for v1)) Tested-by: Kenneth Graunke [v1] Tested-by: Robert Hooker [v1] Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=33394 Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_irq.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b9fafe3b045b..9e34a1abeb61 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1740,6 +1740,16 @@ void ironlake_irq_preinstall(struct drm_device *dev) INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); I915_WRITE(HWSTAM, 0xeffe); + if (IS_GEN6(dev)) { + /* Workaround stalls observed on Sandy Bridge GPUs by + * making the blitter command streamer generate a + * write to the Hardware Status Page for + * MI_USER_INTERRUPT. This appears to serialize the + * previous seqno write out before the interrupt + * happens. + */ + I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); + } /* XXX hotplug from PCH */ -- cgit v1.2.3 From bb4aa39676f73b4657b3edd893ae83881c430c0c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 16 Jun 2011 20:44:51 -0700 Subject: mm: avoid repeated anon_vma lock/unlock sequences in anon_vma_clone() In anon_vma_clone() we traverse the vma->anon_vma_chain of the source vma, locking the anon_vma for each entry. But they are all going to have the same root entry, which means that we're locking and unlocking the same lock over and over again. Which is expensive in locked operations, but can get _really_ expensive when that root entry sees any kind of lock contention. In fact, Tim Chen reports a big performance regression due to this: when we switched to use a mutex instead of a spinlock, the contention case gets much worse. So to alleviate this all, this commit creates a small helper function (lock_anon_vma_root()) that can be used to take the lock just once rather than taking and releasing it over and over again. We still have the same "take the lock and release" it behavior in the exit path (in unlink_anon_vmas()), but that one is a bit harder to fix since we're actually freeing the anon_vma entries as we go, and that will touch the lock too. Reported-and-tested-by: Tim Chen Tested-by: Hugh Dickins Cc: Peter Zijlstra Cc: Andi Kleen Signed-off-by: Linus Torvalds --- mm/rmap.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index 0eb463ea88dd..f286697c61dc 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -200,6 +200,32 @@ int anon_vma_prepare(struct vm_area_struct *vma) return -ENOMEM; } +/* + * This is a useful helper function for locking the anon_vma root as + * we traverse the vma->anon_vma_chain, looping over anon_vma's that + * have the same vma. + * + * Such anon_vma's should have the same root, so you'd expect to see + * just a single mutex_lock for the whole traversal. + */ +static inline struct anon_vma *lock_anon_vma_root(struct anon_vma *root, struct anon_vma *anon_vma) +{ + struct anon_vma *new_root = anon_vma->root; + if (new_root != root) { + if (WARN_ON_ONCE(root)) + mutex_unlock(&root->mutex); + root = new_root; + mutex_lock(&root->mutex); + } + return root; +} + +static inline void unlock_anon_vma_root(struct anon_vma *root) +{ + if (root) + mutex_unlock(&root->mutex); +} + static void anon_vma_chain_link(struct vm_area_struct *vma, struct anon_vma_chain *avc, struct anon_vma *anon_vma) @@ -208,13 +234,11 @@ static void anon_vma_chain_link(struct vm_area_struct *vma, avc->anon_vma = anon_vma; list_add(&avc->same_vma, &vma->anon_vma_chain); - anon_vma_lock(anon_vma); /* * It's critical to add new vmas to the tail of the anon_vma, * see comment in huge_memory.c:__split_huge_page(). */ list_add_tail(&avc->same_anon_vma, &anon_vma->head); - anon_vma_unlock(anon_vma); } /* @@ -224,16 +248,23 @@ static void anon_vma_chain_link(struct vm_area_struct *vma, int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) { struct anon_vma_chain *avc, *pavc; + struct anon_vma *root = NULL; list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) { + struct anon_vma *anon_vma; + avc = anon_vma_chain_alloc(); if (!avc) goto enomem_failure; - anon_vma_chain_link(dst, avc, pavc->anon_vma); + anon_vma = pavc->anon_vma; + root = lock_anon_vma_root(root, anon_vma); + anon_vma_chain_link(dst, avc, anon_vma); } + unlock_anon_vma_root(root); return 0; enomem_failure: + unlock_anon_vma_root(root); unlink_anon_vmas(dst); return -ENOMEM; } @@ -280,7 +311,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) get_anon_vma(anon_vma->root); /* Mark this anon_vma as the one where our new (COWed) pages go. */ vma->anon_vma = anon_vma; + anon_vma_lock(anon_vma); anon_vma_chain_link(vma, avc, anon_vma); + anon_vma_unlock(anon_vma); return 0; -- cgit v1.2.3 From eee2acbae95555006307395d8a6c91452d62851d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 17 Jun 2011 13:54:23 +0200 Subject: mm: avoid repeated anon_vma lock/unlock sequences in unlink_anon_vmas() This matches the anon_vma_clone() case, and uses the same lock helper functions. Because of the need to potentially release the anon_vma's, it's a bit more complex, though. We traverse the 'vma->anon_vma_chain' in two phases: the first loop gets the anon_vma lock (with the helper function that only takes the lock once for the whole loop), and removes any entries that don't need any more processing. The second phase just traverses the remaining list entries (without holding the anon_vma lock), and does any actual freeing of the anon_vma's that is required. Signed-off-by: Peter Zijlstra Tested-by: Hugh Dickins Tested-by: Tim Chen Cc: Andi Kleen Signed-off-by: Linus Torvalds --- mm/rmap.c | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index f286697c61dc..68756a77ef87 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -324,36 +324,43 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) return -ENOMEM; } -static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain) -{ - struct anon_vma *anon_vma = anon_vma_chain->anon_vma; - int empty; - - /* If anon_vma_fork fails, we can get an empty anon_vma_chain. */ - if (!anon_vma) - return; - - anon_vma_lock(anon_vma); - list_del(&anon_vma_chain->same_anon_vma); - - /* We must garbage collect the anon_vma if it's empty */ - empty = list_empty(&anon_vma->head); - anon_vma_unlock(anon_vma); - - if (empty) - put_anon_vma(anon_vma); -} - void unlink_anon_vmas(struct vm_area_struct *vma) { struct anon_vma_chain *avc, *next; + struct anon_vma *root = NULL; /* * Unlink each anon_vma chained to the VMA. This list is ordered * from newest to oldest, ensuring the root anon_vma gets freed last. */ list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { - anon_vma_unlink(avc); + struct anon_vma *anon_vma = avc->anon_vma; + + root = lock_anon_vma_root(root, anon_vma); + list_del(&avc->same_anon_vma); + + /* + * Leave empty anon_vmas on the list - we'll need + * to free them outside the lock. + */ + if (list_empty(&anon_vma->head)) + continue; + + list_del(&avc->same_vma); + anon_vma_chain_free(avc); + } + unlock_anon_vma_root(root); + + /* + * Iterate the list once more, it now only contains empty and unlinked + * anon_vmas, destroy them. Could not do before due to __put_anon_vma() + * needing to acquire the anon_vma->root->mutex. + */ + list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { + struct anon_vma *anon_vma = avc->anon_vma; + + put_anon_vma(anon_vma); + list_del(&avc->same_vma); anon_vma_chain_free(avc); } -- cgit v1.2.3 From dd34739c03f2f9a79403d33419c2e61e11b4c403 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 17 Jun 2011 19:05:36 -0700 Subject: mm: avoid anon_vma_chain allocation under anon_vma lock Hugh Dickins points out that lockdep (correctly) spots a potential deadlock on the anon_vma lock, because we now do a GFP_KERNEL allocation of anon_vma_chain while doing anon_vma_clone(). The problem is that page reclaim will want to take the anon_vma lock of any anonymous pages that it will try to reclaim. So re-organize the code in anon_vma_clone() slightly: first do just a GFP_NOWAIT allocation, which will usually work fine. But if that fails, let's just drop the lock and re-do the allocation, now with GFP_KERNEL. End result: not only do we avoid the locking problem, this also ends up getting better concurrency in case the allocation does need to block. Tim Chen reports that with all these anon_vma locking tweaks, we're now almost back up to the spinlock performance. Reported-and-tested-by: Hugh Dickins Tested-by: Tim Chen Cc: Peter Zijlstra Cc: Andi Kleen Signed-off-by: Linus Torvalds --- mm/rmap.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index 68756a77ef87..27dfd3b82b0f 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -112,9 +112,9 @@ static inline void anon_vma_free(struct anon_vma *anon_vma) kmem_cache_free(anon_vma_cachep, anon_vma); } -static inline struct anon_vma_chain *anon_vma_chain_alloc(void) +static inline struct anon_vma_chain *anon_vma_chain_alloc(gfp_t gfp) { - return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL); + return kmem_cache_alloc(anon_vma_chain_cachep, gfp); } static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain) @@ -159,7 +159,7 @@ int anon_vma_prepare(struct vm_area_struct *vma) struct mm_struct *mm = vma->vm_mm; struct anon_vma *allocated; - avc = anon_vma_chain_alloc(); + avc = anon_vma_chain_alloc(GFP_KERNEL); if (!avc) goto out_enomem; @@ -253,9 +253,14 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) { struct anon_vma *anon_vma; - avc = anon_vma_chain_alloc(); - if (!avc) - goto enomem_failure; + avc = anon_vma_chain_alloc(GFP_NOWAIT | __GFP_NOWARN); + if (unlikely(!avc)) { + unlock_anon_vma_root(root); + root = NULL; + avc = anon_vma_chain_alloc(GFP_KERNEL); + if (!avc) + goto enomem_failure; + } anon_vma = pavc->anon_vma; root = lock_anon_vma_root(root, anon_vma); anon_vma_chain_link(dst, avc, anon_vma); @@ -264,7 +269,6 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) return 0; enomem_failure: - unlock_anon_vma_root(root); unlink_anon_vmas(dst); return -ENOMEM; } @@ -294,7 +298,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) anon_vma = anon_vma_alloc(); if (!anon_vma) goto out_error; - avc = anon_vma_chain_alloc(); + avc = anon_vma_chain_alloc(GFP_KERNEL); if (!avc) goto out_error_free_anon_vma; -- cgit v1.2.3 From 0897554cdd9de8a9f6f93d9ba27c7ebfae286158 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Jun 2011 10:16:17 +1000 Subject: drm/nouveau: fix big-endian switch Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 80218887e0a0..144f79a350ae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -881,8 +881,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) #ifdef __BIG_ENDIAN /* Put the card in BE mode if it's not */ - if (nv_rd32(dev, NV03_PMC_BOOT_1)) - nv_wr32(dev, NV03_PMC_BOOT_1, 0x00000001); + if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001) + nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001); DRM_MEMORYBARRIER(); #endif -- cgit v1.2.3 From 2905544073f6ec235b44f624c66f52b61221a16c Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Sat, 11 Jun 2011 13:30:32 +0100 Subject: drm/nouveau/pm: Prevent overflow in nouveau_perf_init() While parsing the perf table, there is no check if the num of entries read from the vbios is less than the currently allocated number. In case of a buggy vbios this will cause overwriting of kernel memory, causing aditional problems. Add a simple check in order to prevent the case Signed-off-by: Emil Velikov Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_perf.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index 922fb6b664ed..ef9dec0e6f8b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -182,6 +182,11 @@ nouveau_perf_init(struct drm_device *dev) entries = perf[2]; } + if (entries > NOUVEAU_PM_MAX_LEVEL) { + NV_DEBUG(dev, "perf table has too many entries - buggy vbios?\n"); + entries = NOUVEAU_PM_MAX_LEVEL; + } + entry = perf + headerlen; for (i = 0; i < entries; i++) { struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; -- cgit v1.2.3 From f66b3d5540994cb92182312be24944864cec5a16 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 16 Jun 2011 14:40:27 +1000 Subject: drm/nv50/disp: fix gamma with page flipping overlay turned on Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 74a3f6872701..08da478ba544 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -409,7 +409,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct nouveau_channel *evo = dispc->sync; int ret; - ret = RING_SPACE(evo, 24); + ret = RING_SPACE(evo, chan ? 25 : 27); if (unlikely(ret)) return ret; @@ -458,8 +458,19 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, /* queue the flip on the crtc's "display sync" channel */ BEGIN_RING(evo, 0, 0x0100, 1); OUT_RING (evo, 0xfffe0000); - BEGIN_RING(evo, 0, 0x0084, 5); - OUT_RING (evo, chan ? 0x00000100 : 0x00000010); + if (chan) { + BEGIN_RING(evo, 0, 0x0084, 1); + OUT_RING (evo, 0x00000100); + } else { + BEGIN_RING(evo, 0, 0x0084, 1); + OUT_RING (evo, 0x00000010); + /* allows gamma somehow, PDISP will bitch at you if + * you don't wait for vblank before changing this.. + */ + BEGIN_RING(evo, 0, 0x00e0, 1); + OUT_RING (evo, 0x40000000); + } + BEGIN_RING(evo, 0, 0x0088, 4); OUT_RING (evo, dispc->sem.offset); OUT_RING (evo, 0xf00d0000 | dispc->sem.value); OUT_RING (evo, 0x74b1e000); -- cgit v1.2.3 From b16a5a18ff994532120c1d18e678bbc5fb477b62 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 17 Jun 2011 23:41:54 +1000 Subject: drm/nouveau: fix assumption that semaphore dmaobj is valid in x-chan sync The DDX modifies DMA_SEMAPHORE on nv50 in order to implement sync-to-vblank, things will go very wrong for cross-channel sync after this. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_fence.c | 59 ++++++++++++++------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 4b9f4493c9f9..7347075ca5b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -339,11 +339,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) int ret; if (dev_priv->chipset < 0x84) { - ret = RING_SPACE(chan, 3); + ret = RING_SPACE(chan, 4); if (ret) return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2); + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3); + OUT_RING (chan, NvSema); OUT_RING (chan, sema->mem->start); OUT_RING (chan, 1); } else @@ -351,10 +352,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) struct nouveau_vma *vma = &dev_priv->fence.bo->vma; u64 offset = vma->offset + sema->mem->start; - ret = RING_SPACE(chan, 5); + ret = RING_SPACE(chan, 7); if (ret) return ret; + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); + OUT_RING (chan, chan->vram_handle); BEGIN_RING(chan, NvSubSw, 0x0010, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); @@ -394,11 +397,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) int ret; if (dev_priv->chipset < 0x84) { - ret = RING_SPACE(chan, 4); + ret = RING_SPACE(chan, 5); if (ret) return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2); + OUT_RING (chan, NvSema); OUT_RING (chan, sema->mem->start); BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); OUT_RING (chan, 1); @@ -407,10 +411,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) struct nouveau_vma *vma = &dev_priv->fence.bo->vma; u64 offset = vma->offset + sema->mem->start; - ret = RING_SPACE(chan, 5); + ret = RING_SPACE(chan, 7); if (ret) return ret; + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); + OUT_RING (chan, chan->vram_handle); BEGIN_RING(chan, NvSubSw, 0x0010, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); @@ -504,22 +510,22 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) struct nouveau_gpuobj *obj = NULL; int ret; - if (dev_priv->card_type >= NV_C0) - goto out_initialised; + if (dev_priv->card_type < NV_C0) { + /* Create an NV_SW object for various sync purposes */ + ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); + if (ret) + return ret; - /* Create an NV_SW object for various sync purposes */ - ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); - if (ret) - return ret; + ret = RING_SPACE(chan, 2); + if (ret) + return ret; - /* we leave subchannel empty for nvc0 */ - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_RING(chan, NvSubSw, 0, 1); - OUT_RING(chan, NvSw); + BEGIN_RING(chan, NvSubSw, 0, 1); + OUT_RING (chan, NvSw); + FIRE_RING (chan); + } - /* Create a DMA object for the shared cross-channel sync area. */ + /* Setup area of memory shared between all channels for x-chan sync */ if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; @@ -534,23 +540,8 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) nouveau_gpuobj_ref(NULL, &obj); if (ret) return ret; - - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); - OUT_RING(chan, NvSema); - } else { - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); - OUT_RING (chan, chan->vram_handle); /* whole VM */ } - FIRE_RING(chan); - -out_initialised: INIT_LIST_HEAD(&chan->fence.pending); spin_lock_init(&chan->fence.lock); atomic_set(&chan->fence.last_sequence_irq, 0); -- cgit v1.2.3 From 808b4e639eb00394de9989fabca23196c337ee75 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 7 Jun 2011 15:14:26 -0400 Subject: hwmon: (coretemp) Drop unused struct members pdev_entry.cpu and pdev_entry.cpu_core_id aren't used anywhere in the driver code so we can drop these struct members. Signed-off-by: Jean Delvare Cc: Fenghua Yu Cc: Guenter Roeck Cc: Durgadoss R Signed-off-by: Guenter Roeck --- drivers/hwmon/coretemp.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 85e937984ff7..0070d5476dd0 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -97,9 +97,7 @@ struct platform_data { struct pdev_entry { struct list_head list; struct platform_device *pdev; - unsigned int cpu; u16 phys_proc_id; - u16 cpu_core_id; }; static LIST_HEAD(pdev_list); @@ -653,9 +651,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) } pdev_entry->pdev = pdev; - pdev_entry->cpu = cpu; pdev_entry->phys_proc_id = TO_PHYS_ID(cpu); - pdev_entry->cpu_core_id = TO_CORE_ID(cpu); list_add_tail(&pdev_entry->list, &pdev_list); mutex_unlock(&pdev_list_mutex); -- cgit v1.2.3 From 9a2d55be1168b56a5c65321dcce64c97798eaec7 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 24 May 2011 12:19:05 -0700 Subject: hwmon: (asus_atk0110) Consolidate sysfs attribute initialization Call sysfs_attr_init() from atk_init_attribute() to handle sysfs attribute initialization in a single function. Signed-off-by: Guenter Roeck Cc: Luca Tettamanti Acked-by: Jean Delvare --- drivers/hwmon/asus_atk0110.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index b5e892017e0c..dcb78a7a8047 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -268,6 +268,7 @@ static struct device_attribute atk_name_attr = static void atk_init_attribute(struct device_attribute *attr, char *name, sysfs_show_func show) { + sysfs_attr_init(&attr->attr); attr->attr.name = name; attr->attr.mode = 0444; attr->show = show; @@ -1188,19 +1189,15 @@ static int atk_create_files(struct atk_data *data) int err; list_for_each_entry(s, &data->sensor_list, list) { - sysfs_attr_init(&s->input_attr.attr); err = device_create_file(data->hwmon_dev, &s->input_attr); if (err) return err; - sysfs_attr_init(&s->label_attr.attr); err = device_create_file(data->hwmon_dev, &s->label_attr); if (err) return err; - sysfs_attr_init(&s->limit1_attr.attr); err = device_create_file(data->hwmon_dev, &s->limit1_attr); if (err) return err; - sysfs_attr_init(&s->limit2_attr.attr); err = device_create_file(data->hwmon_dev, &s->limit2_attr); if (err) return err; -- cgit v1.2.3 From 3cdb2052a6e365ad56202874e6a8a05a2bb336fc Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 24 May 2011 12:33:26 -0700 Subject: hwmon: (ibmaem) Initialize sysfs attributes Initialize dynamically allocated sysfs attributes before device_create_file() call to suppress lockdep_init_map() warning if lockdep debugging is enabled. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.34+ --- drivers/hwmon/ibmaem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 537409d07ee7..1a409c5bc9bc 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -947,6 +947,7 @@ static int aem_register_sensors(struct aem_data *data, /* Set up read-only sensors */ while (ro->label) { + sysfs_attr_init(&sensors->dev_attr.attr); sensors->dev_attr.attr.name = ro->label; sensors->dev_attr.attr.mode = S_IRUGO; sensors->dev_attr.show = ro->show; @@ -963,6 +964,7 @@ static int aem_register_sensors(struct aem_data *data, /* Set up read-write sensors */ while (rw->label) { + sysfs_attr_init(&sensors->dev_attr.attr); sensors->dev_attr.attr.name = rw->label; sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; sensors->dev_attr.show = rw->show; -- cgit v1.2.3 From fb794e0f7153918c33f2300986d995524ab711cf Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 24 May 2011 12:34:12 -0700 Subject: hwmon: (ibmpex) Initialize sysfs attributes Initialize dynamically allocated sysfs attributes before device_create_file() call to suppress lockdep_init_map() warning if lockdep debugging is enabled. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.34+ --- drivers/hwmon/ibmpex.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index 06d4eafcf76b..41dbf8161ed7 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -358,6 +358,7 @@ static int create_sensor(struct ibmpex_bmc_data *data, int type, else if (type == POWER_SENSOR) sprintf(n, power_sensor_name_templates[func], "power", counter); + sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr); data->sensors[sensor].attr[func].dev_attr.attr.name = n; data->sensors[sensor].attr[func].dev_attr.attr.mode = S_IRUGO; data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor; -- cgit v1.2.3 From b1e698db0939b04602ded2a2196ff69c92b49378 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 24 May 2011 12:34:55 -0700 Subject: hwmon: (s3c) Initialize sysfs attributes Initialize dynamically allocated sysfs attributes before device_create_file() call to suppress lockdep_init_map() warning if lockdep debugging is enabled. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.34+ --- drivers/hwmon/s3c-hwmon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c index 92b42db43bcf..b39f52e2752a 100644 --- a/drivers/hwmon/s3c-hwmon.c +++ b/drivers/hwmon/s3c-hwmon.c @@ -232,6 +232,7 @@ static int s3c_hwmon_create_attr(struct device *dev, attr = &attrs->in; attr->index = channel; + sysfs_attr_init(&attr->dev_attr.attr); attr->dev_attr.attr.name = attrs->in_name; attr->dev_attr.attr.mode = S_IRUGO; attr->dev_attr.show = s3c_hwmon_ch_show; @@ -249,6 +250,7 @@ static int s3c_hwmon_create_attr(struct device *dev, attr = &attrs->label; attr->index = channel; + sysfs_attr_init(&attr->dev_attr.attr); attr->dev_attr.attr.name = attrs->label_name; attr->dev_attr.attr.mode = S_IRUGO; attr->dev_attr.show = s3c_hwmon_label_show; -- cgit v1.2.3 From da40b0b6b4d3a81c5051fe6ae0544c48c13261c4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 18 Jun 2011 02:50:11 -0700 Subject: Input: evdev - try to wake up readers only if we have full packet We should only wake waiters on the event device when we actually post an EV_SYN/SYN_REPORT to the queue. Otherwise we end up making waiting threads runnable only to go right back to sleep because the device still isn't readable. Reported-by: Jeffrey Brown Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index be0921ef6b52..4cf25347b015 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -111,7 +111,8 @@ static void evdev_event(struct input_handle *handle, rcu_read_unlock(); - wake_up_interruptible(&evdev->wait); + if (type == EV_SYN && code == SYN_REPORT) + wake_up_interruptible(&evdev->wait); } static int evdev_fasync(int fd, struct file *file, int on) -- cgit v1.2.3 From b27af563befa95686c8d1abc491408aa6b9a31dc Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 15 Jun 2011 21:13:55 -0700 Subject: Input: omap-keypad - add missing input_sync() Otherwise the updated evdev driver (commit cdda911c34006f1089f3c87b1a1f, "Input: evdev - only signal polls on full packets") no longer works on top of omap-keypad. Tested on Amstrad Delta. Signed-off-by: Janusz Krzysztofik Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/omap-keypad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index f23a743817db..33d0bdc837c0 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -209,6 +209,7 @@ static void omap_kp_tasklet(unsigned long data) #endif } } + input_sync(omap_kp_data->input); memcpy(keypad_state, new_state, sizeof(keypad_state)); if (key_down) { -- cgit v1.2.3 From cca23d0b5350c9ca0473625c3f5879422ba534a6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sat, 18 Jun 2011 02:51:52 -0700 Subject: Input: sh_keysc - 8x8 MODE_6 fix According to the data sheet for G4, AP4 and AG5 KEYSC MODE_6 is 8x8 keys. Bump up MAXKEYS to 64 too. Signed-off-by: Magnus Damm Reviewed-by: Simon Horman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/sh_keysc.c | 2 +- include/linux/input/sh_keysc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 834cf98e7efb..6876700a4469 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -32,7 +32,7 @@ static const struct { [SH_KEYSC_MODE_3] = { 2, 4, 7 }, [SH_KEYSC_MODE_4] = { 3, 6, 6 }, [SH_KEYSC_MODE_5] = { 4, 6, 7 }, - [SH_KEYSC_MODE_6] = { 5, 7, 7 }, + [SH_KEYSC_MODE_6] = { 5, 8, 8 }, }; struct sh_keysc_priv { diff --git a/include/linux/input/sh_keysc.h b/include/linux/input/sh_keysc.h index 649dc7f12925..5d253cd93691 100644 --- a/include/linux/input/sh_keysc.h +++ b/include/linux/input/sh_keysc.h @@ -1,7 +1,7 @@ #ifndef __SH_KEYSC_H__ #define __SH_KEYSC_H__ -#define SH_KEYSC_MAXKEYS 49 +#define SH_KEYSC_MAXKEYS 64 struct sh_keysc_info { enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3, -- cgit v1.2.3 From c11760c6d80ab6aa20e383cf378a7287305f591c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Jun 2011 10:30:03 -0700 Subject: isofs: fix bh leak in isofs_fill_super() error case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In isofs_fill_super(), when an iso_primary_descriptor is found, it is kept in pri_bh. The error cases don't properly release it. Fix it. Reported-and-tested-by: 김원석 Cc: Andrew Morton Signed-off-by: Linus Torvalds --- fs/isofs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 3db5ba4568fc..b3cc8586984e 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -974,7 +974,7 @@ out_no_inode: out_no_read: printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n", __func__, s->s_id, iso_blknum, block); - goto out_freesbi; + goto out_freebh; out_bad_zone_size: printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n", sbi->s_log_zone_size); @@ -989,6 +989,7 @@ out_unknown_format: out_freebh: brelse(bh); + brelse(pri_bh); out_freesbi: kfree(opt.iocharset); kfree(sbi); -- cgit v1.2.3 From 9aa3c94ce59066f545521033007abb6441706068 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 18 Jun 2011 11:59:18 -0700 Subject: ipv4: fix multicast losses Knut Tidemann found that first packet of a multicast flow was not correctly received, and bisected the regression to commit b23dd4fe42b4 (Make output route lookup return rtable directly.) Special thanks to Knut, who provided a very nice bug report, including sample programs to demonstrate the bug. Reported-and-bisectedby: Knut Tidemann Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 045f0ec6a4a0..aa13ef105110 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1902,9 +1902,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); rth = rt_intern_hash(hash, rth, skb, dev->ifindex); - err = 0; - if (IS_ERR(rth)) - err = PTR_ERR(rth); + return IS_ERR(rth) ? PTR_ERR(rth) : 0; e_nobufs: return -ENOBUFS; -- cgit v1.2.3 From 7d68dc3f1003a38948c55c803c32d1989dd49198 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 14 Jun 2011 19:53:09 +0200 Subject: x86, efi: Do not reserve boot services regions within reserved areas Commit 916f676f8dc started reserving boot service code since some systems require you to keep that code around until SetVirtualAddressMap is called. However, in some cases those areas will overlap with reserved regions. The proper medium-term fix is to fix the bootloader to prevent the conflicts from occurring by moving the kernel to a better position, but the kernel should check for this possibility, and only reserve regions which can be reserved. Signed-off-by: Maarten Lankhorst Link: http://lkml.kernel.org/r/4DF7A005.1050407@gmail.com Acked-by: Matthew Garrett Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/include/asm/memblock.h | 2 +- arch/x86/mm/memblock.c | 4 ++-- arch/x86/platform/efi/efi.c | 29 +++++++++++++++++++++++++---- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/memblock.h b/arch/x86/include/asm/memblock.h index 19ae14ba6978..0cd3800f33b9 100644 --- a/arch/x86/include/asm/memblock.h +++ b/arch/x86/include/asm/memblock.h @@ -4,7 +4,6 @@ #define ARCH_DISCARD_MEMBLOCK u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align); -void memblock_x86_to_bootmem(u64 start, u64 end); void memblock_x86_reserve_range(u64 start, u64 end, char *name); void memblock_x86_free_range(u64 start, u64 end); @@ -19,5 +18,6 @@ u64 memblock_x86_hole_size(u64 start, u64 end); u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align); u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit); u64 memblock_x86_memory_in_range(u64 addr, u64 limit); +bool memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align); #endif diff --git a/arch/x86/mm/memblock.c b/arch/x86/mm/memblock.c index aa1169392b83..992da5ec5a64 100644 --- a/arch/x86/mm/memblock.c +++ b/arch/x86/mm/memblock.c @@ -8,7 +8,7 @@ #include /* Check for already reserved areas */ -static bool __init check_with_memblock_reserved_size(u64 *addrp, u64 *sizep, u64 align) +bool __init memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align) { struct memblock_region *r; u64 addr = *addrp, last; @@ -59,7 +59,7 @@ u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align) if (addr >= ei_last) continue; *sizep = ei_last - addr; - while (check_with_memblock_reserved_size(&addr, sizep, align)) + while (memblock_x86_check_reserved_size(&addr, sizep, align)) ; if (*sizep) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 0d3a4fa34560..474356b98ede 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -310,14 +310,31 @@ void __init efi_reserve_boot_services(void) for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; - unsigned long long start = md->phys_addr; - unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; + u64 start = md->phys_addr; + u64 size = md->num_pages << EFI_PAGE_SHIFT; if (md->type != EFI_BOOT_SERVICES_CODE && md->type != EFI_BOOT_SERVICES_DATA) continue; - - memblock_x86_reserve_range(start, start + size, "EFI Boot"); + /* Only reserve where possible: + * - Not within any already allocated areas + * - Not over any memory area (really needed, if above?) + * - Not within any part of the kernel + * - Not the bios reserved area + */ + if ((start+size >= virt_to_phys(_text) + && start <= virt_to_phys(_end)) || + !e820_all_mapped(start, start+size, E820_RAM) || + memblock_x86_check_reserved_size(&start, &size, + 1<num_pages = 0; + memblock_dbg(PFX "Could not reserve boot range " + "[0x%010llx-0x%010llx]\n", + start, start+size-1); + } else + memblock_x86_reserve_range(start, start+size, + "EFI Boot"); } } @@ -334,6 +351,10 @@ static void __init efi_free_boot_services(void) md->type != EFI_BOOT_SERVICES_DATA) continue; + /* Could not reserve boot area */ + if (!size) + continue; + free_bootmem_late(start, size); } } -- cgit v1.2.3 From c1f5c54b57341e872a9d375dccef7257f86033ef Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 18 Jun 2011 22:51:13 +0200 Subject: x86, MAINTAINERS: Add x86 MCE people Announce the new x86 MCE infrastructure maintainers. Acked-by: Borislav Petkov Acked-by: Tony Luck Acked-by: H. Peter Anvin Acked-by: Thomas Gleixner Link: http://lkml.kernel.org/n/tip-8hs7yob6wib4vblmrmbpbav4@git.kernel.org Signed-off-by: Ingo Molnar --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 502f2dd761eb..b12b8c13f53a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7007,6 +7007,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86. S: Maintained F: drivers/platform/x86 +X86 MCE INFRASTRUCTURE +M: Tony Luck +M: Borislav Petkov +L: linux-edac@vger.kernel.org +S: Maintained +F: arch/x86/kernel/cpu/mcheck/* + XEN HYPERVISOR INTERFACE M: Jeremy Fitzhardinge M: Konrad Rzeszutek Wilk -- cgit v1.2.3 From c44048dea28b3febd38417f36f7b2924d93f9bb2 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Thu, 26 May 2011 23:15:49 -0400 Subject: mmc: vub300: fix null dereferences in error handling Reported-by: Dan Carpenter Signed-off-by: Chris Ball --- drivers/mmc/host/vub300.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index cbb03305b77b..d4455ffbefd8 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -2096,7 +2096,7 @@ static struct mmc_host_ops vub300_mmc_ops = { static int vub300_probe(struct usb_interface *interface, const struct usb_device_id *id) { /* NOT irq */ - struct vub300_mmc_host *vub300 = NULL; + struct vub300_mmc_host *vub300; struct usb_host_interface *iface_desc; struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface)); int i; @@ -2118,23 +2118,20 @@ static int vub300_probe(struct usb_interface *interface, command_out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!command_out_urb) { retval = -ENOMEM; - dev_err(&vub300->udev->dev, - "not enough memory for the command_out_urb\n"); + dev_err(&udev->dev, "not enough memory for command_out_urb\n"); goto error0; } command_res_urb = usb_alloc_urb(0, GFP_KERNEL); if (!command_res_urb) { retval = -ENOMEM; - dev_err(&vub300->udev->dev, - "not enough memory for the command_res_urb\n"); + dev_err(&udev->dev, "not enough memory for command_res_urb\n"); goto error1; } /* this also allocates memory for our VUB300 mmc host device */ mmc = mmc_alloc_host(sizeof(struct vub300_mmc_host), &udev->dev); if (!mmc) { retval = -ENOMEM; - dev_err(&vub300->udev->dev, - "not enough memory for the mmc_host\n"); + dev_err(&udev->dev, "not enough memory for the mmc_host\n"); goto error4; } /* MMC core transfer sizes tunable parameters */ -- cgit v1.2.3 From b9c350a0a9d3564d20f5301f472b8841f8934c7d Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Tue, 24 May 2011 21:03:22 +0800 Subject: mmc: of_mmc_spi: add NO_IRQ define to of_mmc_spi.c Provide a dummy value of NO_IRQ for architectures that don't support it (such as MIPS). Fixes the build error for MIPS. Signed-off-by: Wanlong Gao Acked-by: Grant Likely Signed-off-by: Chris Ball --- drivers/mmc/host/of_mmc_spi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index e2aecb7f1d5c..ab66f2454dc4 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -25,6 +25,11 @@ #include #include +/* For archs that don't support NO_IRQ (such as mips), provide a dummy value */ +#ifndef NO_IRQ +#define NO_IRQ 0 +#endif + MODULE_LICENSE("GPL"); enum { -- cgit v1.2.3 From 742a0c7cae9bd0f913c71722289b8ec862d70a2b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 27 May 2011 16:54:05 +0200 Subject: mmc: sdhi: fix module unloading MMC host drivers must be able to process interrupts during mmc_remove_host(). Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mobile_sdhi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index b3654293017b..2353bb797d6c 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -165,13 +165,14 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) p->pdata = NULL; + tmio_mmc_host_remove(host); + for (i = 0; i < 3; i++) { irq = platform_get_irq(pdev, i); if (irq >= 0) free_irq(irq, host); } - tmio_mmc_host_remove(host); clk_disable(priv->clk); clk_put(priv->clk); kfree(priv); -- cgit v1.2.3 From be98ca652faa6468916a9b7608befff215a8ca70 Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Thu, 26 May 2011 11:19:05 -0500 Subject: mmc: Add PCI fixup quirks for Ricoh 1180:e823 reader Signed-off-by: Manoj Iyer Cc: Signed-off-by: Chris Ball --- drivers/pci/quirks.c | 2 ++ include/linux/pci_ids.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e8a140669f90..02145e9697a9 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2761,6 +2761,8 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832); #endif /*CONFIG_MMC_RICOH_MMC*/ #if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a311008af5e1..f8910e155566 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1537,6 +1537,7 @@ #define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 #define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 #define PCI_DEVICE_ID_RICOH_R5C822 0x0822 +#define PCI_DEVICE_ID_RICOH_R5CE823 0xe823 #define PCI_DEVICE_ID_RICOH_R5C832 0x0832 #define PCI_DEVICE_ID_RICOH_R5C843 0x0843 -- cgit v1.2.3 From b72336355bb4c92d4a2be3f975dbea47089c83c1 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 30 May 2011 22:11:17 +0200 Subject: KVM: MMU: Fix build warnings in walk_addr_generic() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On 3.0-rc1 I get In file included from arch/x86/kvm/mmu.c:2856: arch/x86/kvm/paging_tmpl.h: In function ‘paging32_walk_addr_generic’: arch/x86/kvm/paging_tmpl.h:124: warning: ‘ptep_user’ may be used uninitialized in this function In file included from arch/x86/kvm/mmu.c:2852: arch/x86/kvm/paging_tmpl.h: In function ‘paging64_walk_addr_generic’: arch/x86/kvm/paging_tmpl.h:124: warning: ‘ptep_user’ may be used uninitialized in this function caused by 6e2ca7d1802bf8ed9908435e34daa116662e7790. According to Takuya Yoshikawa, ptep_user won't be used uninitialized so shut up gcc. Cc: Takuya Yoshikawa Link: http://lkml.kernel.org/r/20110530094604.GC21833@liondog.tnic Signed-off-by: Borislav Petkov Signed-off-by: Avi Kivity --- arch/x86/kvm/paging_tmpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 6c4dc010c4cb..9d03ad4dd5ec 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -121,7 +121,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker, gva_t addr, u32 access) { pt_element_t pte; - pt_element_t __user *ptep_user; + pt_element_t __user *uninitialized_var(ptep_user); gfn_t table_gfn; unsigned index, pt_access, uninitialized_var(pte_access); gpa_t pte_gpa; -- cgit v1.2.3 From 5233dd51ece1615d54ab96c4cbe9ac3cc595e955 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 6 Jun 2011 14:27:47 -0300 Subject: KVM: VMX: do not overwrite uptodate vcpu->arch.cr3 on KVM_SET_SREGS Only decache guest CR3 value if vcpu->arch.cr3 is stale. Fixes loadvm with live guest. Signed-off-by: Marcelo Tosatti Tested-by: Markus Schade Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 4c3fa0f67469..d48ec60ea421 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2047,7 +2047,8 @@ static void ept_update_paging_mode_cr0(unsigned long *hw_cr0, unsigned long cr0, struct kvm_vcpu *vcpu) { - vmx_decache_cr3(vcpu); + if (!test_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail)) + vmx_decache_cr3(vcpu); if (!(cr0 & X86_CR0_PG)) { /* From paging/starting to nonpaging */ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, -- cgit v1.2.3 From a0a8eaba1661232f094654422bdabe2df4e26863 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 17 Jun 2011 10:25:39 +0800 Subject: KVM: MMU: fix opposite condition in mapping_level_dirty_bitmap The condition is opposite, it always maps huge page for the dirty tracked page Reported-by: Steve Signed-off-by: Steve Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index bd14bb4c8594..aee38623b768 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -565,7 +565,7 @@ gfn_to_memslot_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t gfn, static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn) { - return gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true); + return !gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true); } static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) -- cgit v1.2.3 From de2d1a524e94a79078d9fe22c57c0c6009237547 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Wed, 15 Jun 2011 20:50:04 -0700 Subject: KVM: Fix register corruption in pvclock_scale_delta The 128-bit multiply in pvclock.h was missing an output constraint for EDX which caused a register corruption to appear. Thanks to Ulrich for diagnosing the EDX corruption and Avi for providing this fix. Signed-off-by: Zachary Amsden Signed-off-by: Avi Kivity --- arch/x86/include/asm/pvclock.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index 31d84acc1512..a518c0a45044 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h @@ -22,6 +22,8 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) u64 product; #ifdef __i386__ u32 tmp1, tmp2; +#else + ulong tmp; #endif if (shift < 0) @@ -42,8 +44,11 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); #elif defined(__x86_64__) __asm__ ( - "mul %%rdx ; shrd $32,%%rdx,%%rax" - : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) ); + "mul %[mul_frac] ; shrd $32, %[hi], %[lo]" + : [lo]"=a"(product), + [hi]"=d"(tmp) + : "0"(delta), + [mul_frac]"rm"((u64)mul_frac)); #else #error implement me! #endif -- cgit v1.2.3 From df18d127f4fed7a0284bcfa8d2843800cdb63b72 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Fri, 17 Jun 2011 16:25:51 -0400 Subject: pnfs-obj: No longer needed to take an extra ref at add_device Andy's last device_cache patches, already take an extra reference on the newly inserted device_id. So we can remove it from obj-io. Without this patch the device_ids are leaked. Andy's patches are not in Linus tree yet. So I'm not sure if they are scheduled for this Kernel or the next. This patch should be added as part of these. CC: Andy Adamson Signed-off-by: Boaz Harrosh Signed-off-by: Trond Myklebust --- fs/nfs/objlayout/objio_osd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 9cf208df1f25..eb4aafa9f521 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -108,7 +108,6 @@ _dev_list_add(const struct nfs_server *nfss, de = n; } - atomic_inc(&de->id_node.ref); return de; } -- cgit v1.2.3 From cefa9993f161c1c2b6b91b7ea2e84a9bfbd43d2e Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Sun, 19 Jun 2011 16:13:01 -0700 Subject: netpoll: copy dev name of slaves to struct netpoll Otherwise we will not see the name of the slave dev in error message: [ 388.469446] (null): doesn't support polling, aborting. Signed-off-by: WANG Cong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 1 + net/bridge/br_device.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 652b30e525d0..eafe44a528ac 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1297,6 +1297,7 @@ static inline int slave_enable_netpoll(struct slave *slave) goto out; np->dev = slave->dev; + strlcpy(np->dev_name, slave->dev->name, IFNAMSIZ); err = __netpoll_setup(np); if (err) { kfree(np); diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index a6b2f86378c7..c188c803c09c 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -243,6 +243,7 @@ int br_netpoll_enable(struct net_bridge_port *p) goto out; np->dev = p->dev; + strlcpy(np->dev_name, p->dev->name, IFNAMSIZ); err = __netpoll_setup(np); if (err) { -- cgit v1.2.3 From 658924dc9ae2ca8e3c46f36306f5dbd501cf4688 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 19 Jun 2011 12:43:33 +0000 Subject: hp100: fix an skb->len race As soon as skb is given to hardware and spinlock released, TX completion can free skb under us. Therefore, we should update netdev stats before spinlock release. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/hp100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 8e10d2f6a5ad..c3ecb118c1df 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -1580,12 +1580,12 @@ static netdev_tx_t hp100_start_xmit_bm(struct sk_buff *skb, hp100_outl(ringptr->pdl_paddr, TX_PDA_L); /* Low Prio. Queue */ lp->txrcommit++; - spin_unlock_irqrestore(&lp->lock, flags); - /* Update statistics */ dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; + spin_unlock_irqrestore(&lp->lock, flags); + return NETDEV_TX_OK; drop: -- cgit v1.2.3 From 44da29d26bb8df3b0411ba902f2bc9b973ea38e4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 19 Jun 2011 12:52:36 +0000 Subject: sgi-xp: fix a use after free Its illegal to dereference skb after dev_kfree_skb(skb) Signed-off-by: Eric Dumazet CC: Robin Holt Signed-off-by: David S. Miller --- drivers/misc/sgi-xp/xpnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index ee5109a3cd98..42f067347bc7 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -495,14 +495,14 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + if (atomic_dec_return(&queued_msg->use_count) == 0) { dev_kfree_skb(skb); kfree(queued_msg); } - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - return NETDEV_TX_OK; } -- cgit v1.2.3 From 8323fa6ba313ae2664420ec34d56a7fb0bbbe525 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 17 Jun 2011 13:13:52 -0400 Subject: drm/radeon/kms/atom: fix duallink on some early DCE3.2 cards Certain revisions of the vbios on DCE3.2 cards have a bug in the transmitter control table which prevents duallink from being enabled properly on some cards. The action switch statement jumps to the wrong offset for the OUTPUT_ENABLE action. The fix is to use the ENABLE action rather than the OUTPUT_ENABLE action on the affected cards. In fixed version of the vbios, both actions jump to the same offset, so the change should be safe. Reported-and-tested-by: Dave Airlie Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index f55b64cb59d1..012f80251e50 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1431,7 +1431,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) if (is_dig) { switch (mode) { case DRM_MODE_DPMS_ON: - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + /* some early dce3.2 boards have a bug in their transmitter control table */ + if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + else + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); -- cgit v1.2.3 From 74d074eecbb4778e5f5ee7d59399da971682c532 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 17 Jun 2011 06:11:30 +0000 Subject: drm/radeon/kms: add missing param for dce3.2 DP transmitter setup This is used during phy init to set up the phy for DP. This may fix DP problems on DCE3.2 cards. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 012f80251e50..b293487e5aa3 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1090,9 +1090,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t break; } - if (is_dp) + if (is_dp) { args.v2.acConfig.fCoherentMode = 1; - else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + args.v2.acConfig.fDPConnector = 1; + } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v2.acConfig.fCoherentMode = 1; if (radeon_encoder->pixel_clock > 165000) -- cgit v1.2.3 From 682f1a54a03513fd6bcede56845f1ba21f48c182 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 18 Jun 2011 03:59:51 +0000 Subject: drm/radeon: avoid warnings from r600/eg irq handlers on powered off card. Since we were calling the wptr function before checking if the IH was even enabled, or the GPU wasn't shutdown, we'd get spam in the logs when the GPU readback 0xffffffff. This reorders things so we return early in the no IH and GPU shutdown cases. Reported-and-tested-by: ManDay on #radeon Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 17 +++++++---------- drivers/gpu/drm/radeon/r600.c | 15 +++++++-------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 7e3d96e7ac04..7162b7bacac0 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2695,28 +2695,25 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) int evergreen_irq_process(struct radeon_device *rdev) { - u32 wptr = evergreen_get_ih_wptr(rdev); - u32 rptr = rdev->ih.rptr; + u32 wptr; + u32 rptr; u32 src_id, src_data; u32 ring_index; unsigned long flags; bool queue_hotplug = false; - DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); - if (!rdev->ih.enabled) + if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; - spin_lock_irqsave(&rdev->ih.lock, flags); + wptr = evergreen_get_ih_wptr(rdev); + rptr = rdev->ih.rptr; + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + spin_lock_irqsave(&rdev->ih.lock, flags); if (rptr == wptr) { spin_unlock_irqrestore(&rdev->ih.lock, flags); return IRQ_NONE; } - if (rdev->shutdown) { - spin_unlock_irqrestore(&rdev->ih.lock, flags); - return IRQ_NONE; - } - restart_ih: /* display interrupts */ evergreen_irq_ack(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 7dd45ca64e29..dc9fde38ef49 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3294,27 +3294,26 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) int r600_irq_process(struct radeon_device *rdev) { - u32 wptr = r600_get_ih_wptr(rdev); - u32 rptr = rdev->ih.rptr; + u32 wptr; + u32 rptr; u32 src_id, src_data; u32 ring_index; unsigned long flags; bool queue_hotplug = false; - DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); - if (!rdev->ih.enabled) + if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; + wptr = r600_get_ih_wptr(rdev); + rptr = rdev->ih.rptr; + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + spin_lock_irqsave(&rdev->ih.lock, flags); if (rptr == wptr) { spin_unlock_irqrestore(&rdev->ih.lock, flags); return IRQ_NONE; } - if (rdev->shutdown) { - spin_unlock_irqrestore(&rdev->ih.lock, flags); - return IRQ_NONE; - } restart_ih: /* display interrupts */ -- cgit v1.2.3 From 4ee1c57fcadfb79a6515698d8001081b5b980e32 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 20 Jun 2011 15:25:35 +1000 Subject: drm/nouveau: drop leftover debugging this printk isn't really useful, just drop it for now. Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index f0d459bb46e4..525744d593c1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -262,7 +262,6 @@ static bool nouveau_dsm_detect(void) vga_count++; retval = nouveau_dsm_pci_probe(pdev); - printk("ret val is %d\n", retval); if (retval & NOUVEAU_DSM_HAS_MUX) has_dsm |= 1; if (retval & NOUVEAU_DSM_HAS_OPT) -- cgit v1.2.3 From 155d109b5f52ffd749219b27702462dcd9cf4f8d Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 20 Jun 2011 13:23:14 +0200 Subject: block: add REQ_SECURE to REQ_COMMON_MASK Add REQ_SECURE flag to REQ_COMMON_MASK so that init_request_from_bio() can pass it to @req->cmd_flags. Signed-off-by: Namhyung Kim Acked-by: Adrian Hunter Cc: stable@kernel.org # 2.6.36 and newer Signed-off-by: Jens Axboe --- include/linux/blk_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 2a7cea53ca0d..6395692b2e7a 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -167,7 +167,7 @@ enum rq_flag_bits { (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) #define REQ_COMMON_MASK \ (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_DISCARD | \ - REQ_NOIDLE | REQ_FLUSH | REQ_FUA) + REQ_NOIDLE | REQ_FLUSH | REQ_FUA | REQ_SECURE) #define REQ_CLONE_MASK REQ_COMMON_MASK #define REQ_RAHEAD (1 << __REQ_RAHEAD) -- cgit v1.2.3 From 161b6ae0e067e421b20bb35caf66bdb405c929ac Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sat, 28 May 2011 13:23:42 +0200 Subject: debugobjects: Fix boot crash when kmemleak and debugobjects enabled Order of initialization look like this: ... debugobjects kmemleak ...(lots of other subsystems)... workqueues (through early initcall) ... debugobjects use schedule_work for batch freeing of its data and kmemleak heavily use debugobjects, so when it comes to freeing and workqueues were not initialized yet, kernel crashes: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] __queue_work+0x29/0x41a [] queue_work_on+0x16/0x1d [] queue_work+0x29/0x55 [] schedule_work+0x13/0x15 [] free_object+0x90/0x95 [] debug_check_no_obj_freed+0x187/0x1d3 [] ? _raw_spin_unlock_irqrestore+0x30/0x4d [] ? free_object_rcu+0x68/0x6d [] kmem_cache_free+0x64/0x12c [] free_object_rcu+0x68/0x6d [] __rcu_process_callbacks+0x1b6/0x2d9 ... because system_wq is NULL. Fix it by checking if workqueues susbystem was initialized before using. Signed-off-by: Marcin Slusarz Cc: Catalin Marinas Cc: Tejun Heo Cc: Dipankar Sarma Cc: Paul E. McKenney Cc: stable@kernel.org Link: http://lkml.kernel.org/r/20110528112342.GA3068@joi.lan Signed-off-by: Thomas Gleixner --- lib/debugobjects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/debugobjects.c b/lib/debugobjects.c index 9d86e45086f5..a78b7c6e042c 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -198,7 +198,7 @@ static void free_object(struct debug_obj *obj) * initialized: */ if (obj_pool_free > ODEBUG_POOL_SIZE && obj_cache) - sched = !work_pending(&debug_obj_work); + sched = keventd_up() && !work_pending(&debug_obj_work); hlist_add_head(&obj->node, &obj_pool); obj_pool_free++; obj_pool_used--; -- cgit v1.2.3 From 6f2e810ad5d162c2bfa063c1811087277b299e4e Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 20 Jun 2011 10:27:07 +0200 Subject: ALSA: HDA: Remove quirk for an HP device The reporter, who is running kernel 2.6.38, reports that he needs to set model=auto for the headphone output to work correctly. BugLink: http://bugs.launchpad.net/bugs/761022 Cc: stable@kernel.org (v2.6.38+) Reported-by: Jo Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 61a774b3d3cb..c923b2cc9e53 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4883,7 +4883,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), - SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST), SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V), SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), -- cgit v1.2.3 From 105f4622104848ff1ee1f644d661bef9dec3eb27 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 7 Jun 2011 11:50:23 -0400 Subject: nfsd4: fix break_lease flags on nfsd open Thanks to Casey Bodley for pointing out that on a read open we pass 0, instead of O_RDONLY, to break_lease, with the result that a read open is treated like a write open for the purposes of lease breaking! Reported-by: Casey Bodley Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/vfs.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f3fb61b69a1e..fd0acca5370a 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -696,7 +696,15 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor } #endif /* CONFIG_NFSD_V3 */ +static int nfsd_open_break_lease(struct inode *inode, int access) +{ + unsigned int mode; + if (access & NFSD_MAY_NOT_BREAK_LEASE) + return 0; + mode = (access & NFSD_MAY_WRITE) ? O_WRONLY : O_RDONLY; + return break_lease(inode, mode | O_NONBLOCK); +} /* * Open an existing file or directory. @@ -744,12 +752,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, if (!inode->i_fop) goto out; - /* - * Check to see if there are any leases on this file. - * This may block while leases are broken. - */ - if (!(access & NFSD_MAY_NOT_BREAK_LEASE)) - host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0)); + host_err = nfsd_open_break_lease(inode, access); if (host_err) /* NOMEM or WOULDBLOCK */ goto out_nfserr; -- cgit v1.2.3 From 185bf87393afe6b966881e36c459949d90930a7a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 20 Jun 2011 10:10:24 +0300 Subject: ubifs: dereferencing an ERR_PTR in ubifs_mount() d251ed271d5 "ubifs: fix sget races" left out the goto from this error path so the static checkers complain that we're dereferencing "sb" when it's an ERR_PTR. Signed-off-by: Dan Carpenter Signed-off-by: Al Viro --- fs/ubifs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 8c892c2d5300..529be0582029 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -2146,6 +2146,7 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, if (IS_ERR(sb)) { err = PTR_ERR(sb); kfree(c); + goto out_close; } if (sb->s_root) { -- cgit v1.2.3 From 1712c20dae7b770b62b2e3272100b3b40af0157c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 19:59:04 -0400 Subject: bad_inode_permission() is safe from RCU mode return -EIO; is *not* a blocking operation, thank you very much. Nick, what the hell have you been smoking? Signed-off-by: Al Viro --- fs/bad_inode.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 9ad2369d9e35..bfcb18feb1df 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -231,9 +231,6 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer, static int bad_inode_permission(struct inode *inode, int mask, unsigned int flags) { - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - return -EIO; } -- cgit v1.2.3 From ec12781f192568f7ea860f440f890389ba393df7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:03:36 -0400 Subject: cifs_permission() doesn't need to bail out in RCU mode nothing potentially blocking except generic_permission(), which will DTRT Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e9def996e383..2f0c58646c10 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -257,9 +257,6 @@ static int cifs_permission(struct inode *inode, int mask, unsigned int flags) { struct cifs_sb_info *cifs_sb; - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - cifs_sb = CIFS_SB(inode->i_sb); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { -- cgit v1.2.3 From 6b419951f1e44c8a46fccfc6551eca9a9980acd6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:11:43 -0400 Subject: coda_ioctl_permission() is safe in RCU mode return (mask & MAY_EXEC) ? -EACCES : 0; is non-blocking... Signed-off-by: Al Viro --- fs/coda/pioctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 6cbb3afb36dc..cb140ef293e4 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -43,8 +43,6 @@ const struct file_operations coda_ioctl_operations = { /* the coda pioctl inode ops */ static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags) { - if (flags & IPERM_FLAG_RCU) - return -ECHILD; return (mask & MAY_EXEC) ? -EACCES : 0; } -- cgit v1.2.3 From a63ab94d67879bc0630ea9821c582ddf58ba5527 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:17:22 -0400 Subject: logfs doesn't need ->permission() at all ... and never did, what with its ->permission() being what we do by default when ->permission is NULL... Signed-off-by: Al Viro --- fs/logfs/dir.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index 9ed89d1663f8..1afae26cf236 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c @@ -555,13 +555,6 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry, return __logfs_create(dir, dentry, inode, target, destlen); } -static int logfs_permission(struct inode *inode, int mask, unsigned int flags) -{ - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - return generic_permission(inode, mask, flags, NULL); -} - static int logfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { @@ -820,7 +813,6 @@ const struct inode_operations logfs_dir_iops = { .mknod = logfs_mknod, .rename = logfs_rename, .rmdir = logfs_rmdir, - .permission = logfs_permission, .symlink = logfs_symlink, .unlink = logfs_unlink, }; -- cgit v1.2.3 From 730e908f3539066d4aa01f4720ebfc750ce4d045 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:21:44 -0400 Subject: nilfs2_permission() doesn't need to bail out in RCU mode Nothing blocking except for generic_permission(). Which will DTRT. Signed-off-by: Al Viro --- fs/nilfs2/inode.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index b954878ad6ce..b9b45fc2903e 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -801,12 +801,7 @@ out_err: int nilfs_permission(struct inode *inode, int mask, unsigned int flags) { - struct nilfs_root *root; - - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - - root = NILFS_I(inode)->i_root; + struct nilfs_root *root = NILFS_I(inode)->i_root; if ((mask & MAY_WRITE) && root && root->cno != NILFS_CPTREE_CURRENT_CNO) return -EROFS; /* snapshot is not writable */ -- cgit v1.2.3 From cf1279111686d9742cbc4145bc9d526c83f59fea Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:35:23 -0400 Subject: proc_fd_permission() is doesn't need to bail out in RCU mode nothing blocking except generic_permission() Signed-off-by: Al Viro --- fs/proc/base.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 14def991d9dd..8a84210ca080 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2169,11 +2169,7 @@ static const struct file_operations proc_fd_operations = { */ static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags) { - int rv; - - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - rv = generic_permission(inode, mask, flags, NULL); + int rv = generic_permission(inode, mask, flags, NULL); if (rv == 0) return 0; if (task_pid(current) == proc_pid(inode)) -- cgit v1.2.3 From 1d29b5a2ed7eb8862c9b66daf475f3e4c1a40299 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:37:33 -0400 Subject: reiserfs_permission() doesn't need to bail out in RCU mode nothing blocking other than generic_permission() (and check_acl callback does bail out in RCU mode). Signed-off-by: Al Viro --- fs/reiserfs/xattr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index e8a62f41b458..d78089690965 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -954,8 +954,6 @@ static int xattr_mount_check(struct super_block *s) int reiserfs_permission(struct inode *inode, int mask, unsigned int flags) { - if (flags & IPERM_FLAG_RCU) - return -ECHILD; /* * We don't do permission checks on the internal objects. * Permissions are determined by the "owning" object. -- cgit v1.2.3 From 1aec7036d0c2996c86ce483ca0a28f3b20807b43 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:42:00 -0400 Subject: proc_sys_permission() is OK in RCU mode nothing blocking there, since all instances of sysctl ->permissions() method are non-blocking - both of them, that is. Signed-off-by: Al Viro --- fs/proc/proc_sysctl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index f50133c11c24..d167de365a8d 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -304,9 +304,6 @@ static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags) struct ctl_table *table; int error; - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - /* Executable files are not allowed under /proc/sys/ */ if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) return -EACCES; -- cgit v1.2.3 From 6291176bcd71a2766a19a10cbd9bab07d289e1d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 19:20:48 -0400 Subject: kill obsolete comment for follow_down() Signed-off-by: Al Viro --- fs/namei.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 9e425e7e6c8f..975c40620fe9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1011,9 +1011,6 @@ failed: * Follow down to the covering mount currently visible to userspace. At each * point, the filesystem owning that dentry may be queried as to whether the * caller is permitted to proceed or not. - * - * Care must be taken as namespace_sem may be held (indicated by mounting_here - * being true). */ int follow_down(struct path *path) { -- cgit v1.2.3 From 8e833fd2e1f0107ee7a4b6bc4de3c9f0e9b0ed41 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 19 Jun 2011 01:56:53 -0400 Subject: fix comment in generic_permission() CAP_DAC_OVERRIDE is enough for MAY_EXEC on directory, even if no exec bits are set. Signed-off-by: Al Viro --- fs/namei.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 975c40620fe9..0223c41fb114 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -238,7 +238,8 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags, /* * Read/write DACs are always overridable. - * Executable DACs are overridable if at least one exec bit is set. + * Executable DACs are overridable for all directories and + * for non-directories that have least one exec bit set. */ if (!(mask & MAY_EXEC) || execute_ok(inode)) if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) -- cgit v1.2.3 From 482e0cd3dbaa70f2a2bead4b5f2c0d203ef654ba Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 19 Jun 2011 13:01:04 -0400 Subject: devcgroup_inode_permission: take "is it a device node" checks to inlined wrapper inode_permission() calls devcgroup_inode_permission() and almost all such calls are _not_ for device nodes; let's at least keep the common path straight... Signed-off-by: Al Viro --- include/linux/device_cgroup.h | 10 +++++++++- security/device_cgroup.c | 8 +------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/linux/device_cgroup.h b/include/linux/device_cgroup.h index 0b0d9c39ed67..7aad1f440867 100644 --- a/include/linux/device_cgroup.h +++ b/include/linux/device_cgroup.h @@ -2,8 +2,16 @@ #include #ifdef CONFIG_CGROUP_DEVICE -extern int devcgroup_inode_permission(struct inode *inode, int mask); +extern int __devcgroup_inode_permission(struct inode *inode, int mask); extern int devcgroup_inode_mknod(int mode, dev_t dev); +static inline int devcgroup_inode_permission(struct inode *inode, int mask) +{ + if (likely(!inode->i_rdev)) + return 0; + if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) + return 0; + return __devcgroup_inode_permission(inode, mask); +} #else static inline int devcgroup_inode_permission(struct inode *inode, int mask) { return 0; } diff --git a/security/device_cgroup.c b/security/device_cgroup.c index cd1f779fa51d..1be68269e1c2 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -474,17 +474,11 @@ struct cgroup_subsys devices_subsys = { .subsys_id = devices_subsys_id, }; -int devcgroup_inode_permission(struct inode *inode, int mask) +int __devcgroup_inode_permission(struct inode *inode, int mask) { struct dev_cgroup *dev_cgroup; struct dev_whitelist_item *wh; - dev_t device = inode->i_rdev; - if (!device) - return 0; - if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) - return 0; - rcu_read_lock(); dev_cgroup = task_devcgroup(current); -- cgit v1.2.3 From 206b6310fd0268a6ca50cf36f03b0f4eee5602ec Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 20 Jun 2011 10:30:04 -0500 Subject: jfs: old_agsize should be 64 bits in jfs_extendfs Signed-off-by: Dave Kleikamp --- fs/jfs/resize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index 8ea5efb5a34e..8d0c1c7c0820 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c @@ -80,7 +80,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) int log_formatted = 0; struct inode *iplist[1]; struct jfs_superblock *j_sb, *j_sb2; - uint old_agsize; + s64 old_agsize; int agsizechanged = 0; struct buffer_head *bh, *bh2; -- cgit v1.2.3 From 28e0fa894cd5996d3007ce82f07226f79beb7286 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 20 Jun 2011 10:32:46 -0500 Subject: jfs: Update agstart when resizing volume A comment indicates that the IAG's agstart does not need to be updated since it will always point to a block in the same aggregate group, but jfs_fsck isn't so forgiving and reports it as an error. I'm fixing this in jfsutils as well, so either a new kernel or new utilities will be sufficient to fix the problem. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_imap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index ed53a4740168..0533e8f3d19e 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -2921,10 +2921,9 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) continue; } - /* agstart that computes to the same ag is treated as same; */ agstart = le64_to_cpu(iagp->agstart); - /* iagp->agstart = agstart & ~(mp->db_agsize - 1); */ n = agstart >> mp->db_agl2size; + iagp->agstart = cpu_to_le64((s64)n << mp->db_agl2size); /* compute backed inodes */ numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts)) -- cgit v1.2.3 From d31b53e3cd069e02290ed8a648aa8c7618d6fe77 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 20 Jun 2011 10:53:46 -0500 Subject: JFS: Don't save agno in the inode Resizing the file system can result in an in-memory inode being remapped to a different aggregate group (AG). A cached AG number can cause problems when trying to free or allocate inodes. Instead, save the IAG's agstart address and calculate the agno when we need it. Signed-off-by: Dave Kleikamp --- fs/jfs/file.c | 6 +++--- fs/jfs/jfs_imap.c | 9 ++++----- fs/jfs/jfs_incore.h | 3 ++- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/jfs/file.c b/fs/jfs/file.c index c5ce6c1d1ff4..2f3f531f3606 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c @@ -66,9 +66,9 @@ static int jfs_open(struct inode *inode, struct file *file) struct jfs_inode_info *ji = JFS_IP(inode); spin_lock_irq(&ji->ag_lock); if (ji->active_ag == -1) { - ji->active_ag = ji->agno; - atomic_inc( - &JFS_SBI(inode->i_sb)->bmap->db_active[ji->agno]); + struct jfs_sb_info *jfs_sb = JFS_SBI(inode->i_sb); + ji->active_ag = BLKTOAG(addressPXD(&ji->ixpxd), jfs_sb); + atomic_inc( &jfs_sb->bmap->db_active[ji->active_ag]); } spin_unlock_irq(&ji->ag_lock); } diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 0533e8f3d19e..b78b2f978f04 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -397,7 +397,7 @@ int diRead(struct inode *ip) release_metapage(mp); /* set the ag for the inode */ - JFS_IP(ip)->agno = BLKTOAG(agstart, sbi); + JFS_IP(ip)->agstart = agstart; JFS_IP(ip)->active_ag = -1; return (rc); @@ -901,7 +901,7 @@ int diFree(struct inode *ip) /* get the allocation group for this ino. */ - agno = JFS_IP(ip)->agno; + agno = BLKTOAG(JFS_IP(ip)->agstart, JFS_SBI(ip->i_sb)); /* Lock the AG specific inode map information */ @@ -1315,12 +1315,11 @@ int diFree(struct inode *ip) static inline void diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp) { - struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); struct jfs_inode_info *jfs_ip = JFS_IP(ip); ip->i_ino = (iagno << L2INOSPERIAG) + ino; jfs_ip->ixpxd = iagp->inoext[extno]; - jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi); + jfs_ip->agstart = le64_to_cpu(iagp->agstart); jfs_ip->active_ag = -1; } @@ -1379,7 +1378,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip) */ /* get the ag number of this iag */ - agno = JFS_IP(pip)->agno; + agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb)); if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) { /* diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index 1439f119ec83..5097839b7709 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h @@ -50,8 +50,9 @@ struct jfs_inode_info { short btindex; /* btpage entry index*/ struct inode *ipimap; /* inode map */ unsigned long cflag; /* commit flags */ + long agstart; /* agstart of the containing IAG */ u16 bxflag; /* xflag of pseudo buffer? */ - unchar agno; /* ag number */ + unchar pad; signed char active_ag; /* ag currently allocating from */ lid_t blid; /* lid of pseudo buffer? */ lid_t atlhead; /* anonymous tlock list head */ -- cgit v1.2.3 From fa7ccfb17033bfb5bca86f6b909cab0b807efbc0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 18 Jun 2011 22:49:53 -0500 Subject: rtlwifi: rtl8192se: Handle duplicate PCI ID 0x10ec:0x8192 conflict with r8192e_pci There are two devices with PCI ID 0x10ec:0x8192, namely RTL8192E and RTL8192SE. The method of distinguishing them is by the revision ID at offset 0x8 of the PCI configuration space. If the value is 0x10, then the device uses rtl8192se for a driver. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 9f8ccae93317..254b64ba4bf6 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1624,6 +1624,16 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, pci_read_config_byte(pdev, 0x8, &revisionid); pci_read_config_word(pdev, 0x3C, &irqline); + /* PCI ID 0x10ec:0x8192 occurs for both RTL8192E, which uses + * r8192e_pci, and RTL8192SE, which uses this driver. If the + * revision ID is RTL_PCI_REVISION_ID_8192PCIE (0x01), then + * the correct driver is r8192e_pci, thus this routine should + * return false. + */ + if (deviceid == RTL_PCI_8192SE_DID && + revisionid == RTL_PCI_REVISION_ID_8192PCIE) + return false; + if (deviceid == RTL_PCI_8192_DID || deviceid == RTL_PCI_0044_DID || deviceid == RTL_PCI_0047_DID || @@ -1856,7 +1866,8 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x04, 0x07); /* find adapter */ - _rtl_pci_find_adapter(pdev, hw); + if (!_rtl_pci_find_adapter(pdev, hw)) + goto fail3; /* Init IO handler */ _rtl_pci_io_handler_init(&pdev->dev, hw); -- cgit v1.2.3 From c82b9d7fe7464aec78210544948564ffe3bb2d2b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 19 Jun 2011 20:26:15 +0000 Subject: netxen: fix race in skb->len access As soon as skb is given to hardware, TX completion can free skb under us. Therefore, we should update dev stats before kicking the device. Signed-off-by: Eric Dumazet CC: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index b644383017f9..c0788a31ff0f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1965,11 +1965,11 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netxen_tso_check(netdev, tx_ring, first_desc, skb); - netxen_nic_update_cmd_producer(adapter, tx_ring); - adapter->stats.txbytes += skb->len; adapter->stats.xmitcalled++; + netxen_nic_update_cmd_producer(adapter, tx_ring); + return NETDEV_TX_OK; drop_packet: -- cgit v1.2.3 From 8ad2475e3555346fbd738e77da12578b97d10505 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 19 Jun 2011 22:31:20 +0000 Subject: ipv4, ping: Remove duplicate icmp.h include Remove the duplicate inclusion of net/icmp.h from net/ipv4/ping.c Signed-off-by: Jesper Juhl Signed-off-by: David S. Miller --- net/ipv4/ping.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 9aaa67165f42..39b403f854c6 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 19345cb299e8234006c5125151ab723e851a1d24 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Sun, 19 Jun 2011 18:33:46 -0400 Subject: NFSv4.1: file layout must consider pg_bsize for coalescing Otherwise we end up overflowing the rpc buffer size on the receive end. Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/nfs4filelayout.c | 6 ++++-- fs/nfs/pagelist.c | 3 ++- include/linux/nfs_page.h | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 5d6f369b15d0..0bafcc91c27f 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -30,6 +30,7 @@ */ #include +#include #include "internal.h" #include "nfs4filelayout.h" @@ -666,8 +667,9 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, u64 p_stripe, r_stripe; u32 stripe_unit; - if (!pnfs_generic_pg_test(pgio, prev, req)) - return 0; + if (!pnfs_generic_pg_test(pgio, prev, req) || + !nfs_generic_pg_test(pgio, prev, req)) + return false; if (!pgio->pg_lseg) return 1; diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 7913961aff22..009855716286 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -204,7 +204,7 @@ nfs_wait_on_request(struct nfs_page *req) TASK_UNINTERRUPTIBLE); } -static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req) +bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req) { /* * FIXME: ideally we should be able to coalesce all requests @@ -218,6 +218,7 @@ static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_p return desc->pg_count + req->wb_bytes <= desc->pg_bsize; } +EXPORT_SYMBOL_GPL(nfs_generic_pg_test); /** * nfs_pageio_init - initialise a page io descriptor diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 3a34e80ae92f..25311b3bedf8 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -92,6 +92,9 @@ extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *, struct nfs_page *); extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc); extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t); +extern bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, + struct nfs_page *prev, + struct nfs_page *req); extern int nfs_wait_on_request(struct nfs_page *); extern void nfs_unlock_request(struct nfs_page *req); extern int nfs_set_page_tag_locked(struct nfs_page *req); -- cgit v1.2.3 From 384420409d9b5d4443940abace49363d26135412 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Sun, 19 Jun 2011 21:48:06 +0000 Subject: pxa168_eth: fix race in transmit path. Because the socket buffer is freed in the completion interrupt, it is not safe to access it after submitting it to the hardware. Cc: stable@kernel.org Cc: Sachin Sanap Cc: Zhangfei Gao Cc: Philip Rakity Signed-off-by: Richard Cochran Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/pxa168_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index 89f7540d90f9..5f597ca592bb 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -1273,7 +1273,7 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD); - stats->tx_bytes += skb->len; + stats->tx_bytes += length; stats->tx_packets++; dev->trans_start = jiffies; if (pep->tx_ring_size - pep->tx_desc_count <= 1) { -- cgit v1.2.3 From ecc90462b428db2ad2ee5081c45496ed10f3a633 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 20 Jun 2011 17:53:24 -0500 Subject: jfs: agstart field must be 64 bits The previous patch added the agstart field to jfs_ip, but declared it a long. We need to make sure its 64 bits on every platform. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_incore.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index 5097839b7709..584a4a1a6e81 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h @@ -50,7 +50,7 @@ struct jfs_inode_info { short btindex; /* btpage entry index*/ struct inode *ipimap; /* inode map */ unsigned long cflag; /* commit flags */ - long agstart; /* agstart of the containing IAG */ + u64 agstart; /* agstart of the containing IAG */ u16 bxflag; /* xflag of pseudo buffer? */ unchar pad; signed char active_ag; /* ag currently allocating from */ -- cgit v1.2.3 From fdb9c3cd5124c9a6e4c824ed2bca5b4602e84a1a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 21 Apr 2011 23:09:11 +0000 Subject: msm: timer: Fix DGT rate on 8960 and 8660 The DGT runs at 27 MHz divided by 4 on 8660 and 8960. Signed-off-by: Stephen Boyd Signed-off-by: David Brown --- arch/arm/mach-msm/timer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 2232032181be..63621f152c98 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -57,10 +57,12 @@ enum timer_location { #if defined(CONFIG_ARCH_QSD8X50) #define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */ #define MSM_DGT_SHIFT (0) -#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \ - defined(CONFIG_ARCH_MSM8960) +#elif defined(CONFIG_ARCH_MSM7X30) #define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */ #define MSM_DGT_SHIFT (0) +#elif defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960) +#define DGT_HZ (27000000 / 4) /* 27 MHz (PXO) / 4 by default */ +#define MSM_DGT_SHIFT (0) #else #define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */ #define MSM_DGT_SHIFT (5) -- cgit v1.2.3 From a377e187df725fe7e62d2cec59ec290c5a605d93 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Jun 2011 13:00:31 -0400 Subject: drm/radeon/kms/r6xx+: voltage fixes 0xff01 is not an actual voltage value, but a flag for the driver. If the power state as that value, skip setting the voltage. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 6 ++++++ drivers/gpu/drm/radeon/r600.c | 3 +++ drivers/gpu/drm/radeon/radeon_atombios.c | 4 ++++ drivers/gpu/drm/radeon/rv770.c | 3 +++ 4 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 7162b7bacac0..445af7981637 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -140,11 +140,17 @@ void evergreen_pm_misc(struct radeon_device *rdev) struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; if (voltage->type == VOLTAGE_SW) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) { radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); rdev->pm.current_vddc = voltage->voltage; DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); } + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->vddci == 0xff01) + return; if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) { radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI); rdev->pm.current_vddci = voltage->vddci; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index dc9fde38ef49..f79d2ccb6755 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -590,6 +590,9 @@ void r600_pm_misc(struct radeon_device *rdev) struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; if (voltage->voltage != rdev->pm.current_vddc) { radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); rdev->pm.current_vddc = voltage->voltage; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index fa62a503ae70..1e725d9f767f 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2607,6 +2607,10 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) return; + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage_level == 0xff01) + return; + switch (crev) { case 1: args.v1.ucVoltageType = voltage_type; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index ef8a5babe9f7..6f508ffd1035 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -105,6 +105,9 @@ void rv770_pm_misc(struct radeon_device *rdev) struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; if (voltage->voltage != rdev->pm.current_vddc) { radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); rdev->pm.current_vddc = voltage->voltage; -- cgit v1.2.3 From 79568f5be06c91071697c065f01f3ebfbeb25a61 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 20 Jun 2011 20:13:49 -0700 Subject: vfs: i_state needs to be 'unsigned long' for now Commit 13e12d14e2dc ("vfs: reorganize 'struct inode' layout a bit") moved things around a bit changed i_state to be unsigned int instead of unsigned long. That was to help structure layout for the 64-bit case, and shrink 'struct inode' a bit (admittedly that only happened when spinlock debugging was on and i_flags didn't pack with i_lock). However, Meelis Roos reports that this results in unaligned exceptions on sprc, and it turns out that the bit-locking primitives that we use for the I_NEW bit want to use the bitops. Which want 'unsigned long', not 'unsigned int'. We really should fix the bit locking code to not have that kind of requirement, but that's a much bigger change. So for now, revert that field back to 'unsigned long' (but keep the other re-ordering changes from the commit that caused this). Andi points out that we have played games with this in 'struct page', so it's solvable with other hacks too, but since right now the struct inode size advantage only happens with some rare config options, it's not worth fighting. It _would_ be worth fixing the bitlocking code, though. Especially since there is no type safety in the bitlocking code (this never caused any warnings, and worked fine on x86-64, because the bitlocks take a 'void *' and x86-64 doesn't care that deeply about alignment). So it's currently a very easy problem to trigger by mistake and never notice. Reported-by: Meelis Roos Cc: Andi Kleen Cc: David Miller Signed-off-by: Linus Torvalds --- include/linux/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 1c777878f1ea..6e73e2e9ae33 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -744,7 +744,7 @@ struct inode { spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned int i_flags; - unsigned int i_state; + unsigned long i_state; #ifdef CONFIG_SECURITY void *i_security; #endif -- cgit v1.2.3 From 56299378726d5f2ba8d3c8cbbd13cb280ba45e4f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 20 Jun 2011 20:25:46 -0700 Subject: Linux 3.0-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0499c2ee8541..41330a06e4ec 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Sneaky Weasel # *DOCUMENTATION* -- cgit v1.2.3 From c933790614529c06b221f73ff36e2456aecee30d Mon Sep 17 00:00:00 2001 From: Tony Vroon Date: Mon, 20 Jun 2011 22:11:11 +0100 Subject: ALSA: hda - Remove ALC268 model override for CPR2000 The "diverse" Quanta ID 0x0763 is overridden to ALC268_ACER. This keeps headphone automute and microphone input from operating on at least one laptop from Opti Systems. Without the override, the BIOS parser does a fine job setting the card up and everything works. Tested-By: Peter Schneider Signed-off-by: Tony Vroon Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c923b2cc9e53..475ed1e8ffc6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13871,7 +13871,6 @@ static const struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO), SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA), - SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), {} }; -- cgit v1.2.3 From 42467b32ce4f1ba933673b396f807110e3618ff5 Mon Sep 17 00:00:00 2001 From: Lydia Wang Date: Mon, 20 Jun 2011 14:14:37 +0800 Subject: ALSA: VIA HDA: Modify initial verbs list for VT1718S. Remove some invalid initial verbs and correct some wrong initial verbs for VT1718S codec. Signed-off-by: Lydia Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index c952582fb218..abee9ac15902 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -4283,9 +4283,6 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = { {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, - - /* Setup default input of Front HP to MW9 */ - {0x28, AC_VERB_SET_CONNECT_SEL, 0x1}, /* PW9 PW10 Output enable */ {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, {0x2e, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, @@ -4294,10 +4291,10 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = { /* Enable Boost Volume backdoor */ {0x1, 0xf88, 0x8}, /* MW0/1/2/3/4: un-mute index 0 (AOWx), mute index 1 (MW9) */ - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, @@ -4307,8 +4304,6 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = { /* set MUX1 = 2 (AOW4), MUX2 = 1 (AOW3) */ {0x34, AC_VERB_SET_CONNECT_SEL, 0x2}, {0x35, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* Unmute MW4's index 0 */ - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, { } }; -- cgit v1.2.3 From ba31a60d0fd8a3976d44d32f2b82491c62646b2a Mon Sep 17 00:00:00 2001 From: Lydia Wang Date: Mon, 20 Jun 2011 14:16:33 +0800 Subject: ALSA: VIA HDA: Mute/unmute mixer conncted to Headphone for VT1718S. When switch HP independent mode, mute/unmute connctions of mixer which is connected to headphone for VT1718S. Signed-off-by: Lydia Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index abee9ac15902..f1a80cd6afe4 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -745,12 +745,23 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol, struct via_spec *spec = codec->spec; hda_nid_t nid = kcontrol->private_value; unsigned int pinsel = ucontrol->value.enumerated.item[0]; + unsigned int parm0, parm1; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; - if (spec->codec_type == VT1718S) + if (spec->codec_type == VT1718S) { snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0); + /* Set correct mute switch for MW3 */ + parm0 = spec->hp_independent_mode ? + AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0); + parm1 = spec->hp_independent_mode ? + AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1); + snd_hda_codec_write(codec, 0x1b, 0, + AC_VERB_SET_AMP_GAIN_MUTE, parm0); + snd_hda_codec_write(codec, 0x1b, 0, + AC_VERB_SET_AMP_GAIN_MUTE, parm1); + } else snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel); -- cgit v1.2.3 From e905a83acd7bf8989c3d5ba3099b72675f5d7d29 Mon Sep 17 00:00:00 2001 From: Lydia Wang Date: Mon, 20 Jun 2011 14:17:56 +0800 Subject: ALSA: VIA HDA: Create a master amplifier control for VT1718S. Create a master volume and mute control of playback for VT1718S. Signed-off-by: Lydia Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index f1a80cd6afe4..f43bb0eaed8b 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -4462,6 +4462,19 @@ static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec, if (err < 0) return err; } else if (i == AUTO_SEQ_FRONT) { + /* add control to mixer index 0 */ + err = via_add_control(spec, VIA_CTL_WIDGET_VOL, + "Master Front Playback Volume", + HDA_COMPOSE_AMP_VAL(0x21, 3, 5, + HDA_INPUT)); + if (err < 0) + return err; + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, + "Master Front Playback Switch", + HDA_COMPOSE_AMP_VAL(0x21, 3, 5, + HDA_INPUT)); + if (err < 0) + return err; /* Front */ sprintf(name, "%s Playback Volume", chname[i]); err = via_add_control( -- cgit v1.2.3 From bf69d8484cbba2a59dd73cdd20b8d5e79cedce1f Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 21 Jun 2011 08:03:25 +0000 Subject: sh: fix compile error using sh7757lcr_defconfig Fix the complie error in ehci-hcd.c because it needs an additional configuration. CC drivers/usb/host/ehci-hcd.o drivers/usb/host/ehci-hcd.c:1288:2: error: #error "missing bus glue for ehci-hcd" make[3]: *** [drivers/usb/host/ehci-hcd.o] Error 1 make[2]: *** [drivers/usb/host] Error 2 make[1]: *** [drivers/usb] Error 2 make: *** [drivers] Error 2 Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/configs/sh7757lcr_defconfig | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig index 33ddb130a7c8..cfde98ddb29d 100644 --- a/arch/sh/configs/sh7757lcr_defconfig +++ b/arch/sh/configs/sh7757lcr_defconfig @@ -9,7 +9,6 @@ CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS_ALL=y CONFIG_SLAB=y @@ -39,8 +38,6 @@ CONFIG_IPV6=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_FW_LOADER is not set CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y @@ -56,18 +53,19 @@ CONFIG_SH_ETH=y # CONFIG_KEYBOARD_ATKBD is not set # CONFIG_MOUSE_PS2 is not set # CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_SH_SCI=y CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y -# CONFIG_LEGACY_PTYS is not set # CONFIG_HW_RANDOM is not set CONFIG_SPI=y CONFIG_SPI_SH=y # CONFIG_HWMON is not set -CONFIG_MFD_SH_MOBILE_SDHI=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_SH=y CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_SH=y CONFIG_USB_STORAGE=y CONFIG_MMC=y CONFIG_MMC_SDHI=y -- cgit v1.2.3 From f2b9726105824fdeea32a339e5072a358f89a25b Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 21 Jun 2011 08:28:27 +0000 Subject: sh: add platform_device of EHCI/OHCI to setup-sh7757 Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index 423dabf542d3..717a76b399b1 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -659,6 +659,54 @@ static struct platform_device spi0_device = { .resource = spi0_resources, }; +static struct resource usb_ehci_resources[] = { + [0] = { + .start = 0xfe4f1000, + .end = 0xfe4f10ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 57, + .end = 57, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usb_ehci_device = { + .name = "sh_ehci", + .id = -1, + .dev = { + .dma_mask = &usb_ehci_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(usb_ehci_resources), + .resource = usb_ehci_resources, +}; + +static struct resource usb_ohci_resources[] = { + [0] = { + .start = 0xfe4f1800, + .end = 0xfe4f18ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 57, + .end = 57, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usb_ohci_device = { + .name = "sh_ohci", + .id = -1, + .dev = { + .dma_mask = &usb_ohci_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(usb_ohci_resources), + .resource = usb_ohci_resources, +}; + static struct platform_device *sh7757_devices[] __initdata = { &scif2_device, &scif3_device, @@ -670,6 +718,8 @@ static struct platform_device *sh7757_devices[] __initdata = { &dma2_device, &dma3_device, &spi0_device, + &usb_ehci_device, + &usb_ohci_device, }; static int __init sh7757_devices_setup(void) -- cgit v1.2.3 From 5a5685525dbadbe31b8efb113c0d41be8cddda09 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 17 Jun 2011 04:33:13 +0000 Subject: ARM: mach-shmobile: mackerel: change usbhs devices order USB1 can use IRQ interrupt and notify function for usbhs driver, but USB0 is using polling for it. The priority of usbhs devices order USB1 > USB0 is good idea Signed-off-by: Kuninori Morimoto Reviewed-by: Simon Horman Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-mackerel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 7e1d37584321..3802f2afabef 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -1287,9 +1287,9 @@ static struct platform_device *mackerel_devices[] __initdata = { &nor_flash_device, &smc911x_device, &lcdc_device, - &usbhs0_device, &usb1_host_device, &usbhs1_device, + &usbhs0_device, &leds_device, &fsi_device, &fsi_ak4643_device, -- cgit v1.2.3 From 9e05cdde0c6bb8c3c3ee12e6d6123c6f9f85eea6 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 20 Jun 2011 23:00:11 +0000 Subject: ARM: mach-shmobile: ag5evm: consistently name sdhi info structures Name the SDHI1 instance sh_sdhi1_info to be consistent with sh_sdhi0_info. Signed-off-by: Simon Horman Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ag5evm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index 1e2aba23e0d6..ce5c2513c6ce 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -381,7 +381,7 @@ void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state) gpio_set_value(GPIO_PORT114, state); } -static struct sh_mobile_sdhi_info sh_sdhi1_platdata = { +static struct sh_mobile_sdhi_info sh_sdhi1_info = { .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, .tmio_caps = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ, .tmio_ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, @@ -413,7 +413,7 @@ static struct platform_device sdhi1_device = { .name = "sh_mobile_sdhi", .id = 1, .dev = { - .platform_data = &sh_sdhi1_platdata, + .platform_data = &sh_sdhi1_info, }, .num_resources = ARRAY_SIZE(sdhi1_resources), .resource = sdhi1_resources, -- cgit v1.2.3 From 573619d165b85152eeddd3b3871002c48cd94e42 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Jun 2011 16:46:01 +0100 Subject: ARM: SMP: wait for CPU to be marked active When we bring a CPU online, we should wait for it to become active before entering the idle thread, so we know that the scheduler and thread migration is going to work. Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 344e52b16c8c..e7f92a4321f3 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -318,9 +318,13 @@ asmlinkage void __cpuinit secondary_start_kernel(void) smp_store_cpu_info(cpu); /* - * OK, now it's safe to let the boot CPU continue + * OK, now it's safe to let the boot CPU continue. Wait for + * the CPU migration code to notice that the CPU is online + * before we continue. */ set_cpu_online(cpu, true); + while (!cpu_active(cpu)) + cpu_relax(); /* * OK, it's off to the idle thread for us -- cgit v1.2.3 From 946a105e16651c35e9cc670bff23812761f1ad35 Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Tue, 14 Jun 2011 14:20:44 +0100 Subject: ARM: 6961/1: zImage: Add build-time check for correctly-sized proc_type entries It is easy to mis-maintain the proc_types table such that the entries become wrongly-sized and misaligned when the kernel is built in Thumb-2. This patch adds an assembly-time check which will turn most common size/alignment mistakes in this table into build failures, to avoid having to debug the boot-time kernel hang which would happen if the resulting kernel were actually booted. Signed-off-by: Dave Martin Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/boot/compressed/head.S | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 942fad97e447..940b20178107 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -597,6 +597,8 @@ __common_mmu_cache_on: sub pc, lr, r0, lsr #32 @ properly flush pipeline #endif +#define PROC_ENTRY_SIZE (4*5) + /* * Here follow the relocatable cache support functions for the * various processors. This is a generic hook for locating an @@ -624,7 +626,7 @@ call_cache_fn: adr r12, proc_types ARM( addeq pc, r12, r3 ) @ call cache function THUMB( addeq r12, r3 ) THUMB( moveq pc, r12 ) @ call cache function - add r12, r12, #4*5 + add r12, r12, #PROC_ENTRY_SIZE b 1b /* @@ -794,6 +796,16 @@ proc_types: .size proc_types, . - proc_types + /* + * If you get a "non-constant expression in ".if" statement" + * error from the assembler on this line, check that you have + * not accidentally written a "b" instruction where you should + * have written W(b). + */ + .if (. - proc_types) % PROC_ENTRY_SIZE != 0 + .error "The size of one or more proc_types entries is wrong." + .endif + /* * Turn off the Cache and MMU. ARMv3 does not support * reading the control register, but ARMv4 does. -- cgit v1.2.3 From 082763a80ad11adbe8418fff1cfe466343035b7a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Jun 2011 08:13:00 +0100 Subject: ARM: 6969/1: plat-iop: fix build error The iop13xx_defconfig didn't build since the platform code uses defines from . Simply add the include so it compiles. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/plat-iop/cp6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-iop/cp6.c b/arch/arm/plat-iop/cp6.c index 9612a87e2a88..bab73e2c79db 100644 --- a/arch/arm/plat-iop/cp6.c +++ b/arch/arm/plat-iop/cp6.c @@ -18,6 +18,7 @@ */ #include #include +#include static int cp6_trap(struct pt_regs *regs, unsigned int instr) { -- cgit v1.2.3 From 8f7d5efbef8718a774ac5e347b4ec069f17fd9b4 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 10 Jun 2011 13:30:22 -0400 Subject: NFSv4.1: Fix some issues with pnfs_generic_pg_test 1. If the intention is to coalesce requests 'prev' and 'req' then we have to ensure at least that we have a layout starting at req_offset(prev). 2. If we're only requesting a minimal layout of length desc->pg_count, we need to test the length actually returned by the server before we allow the coalescing to occur. 3. We need to deal correctly with (pgio->lseg == NULL) 4. Fixup the test guarding the pnfs_update_layout. Signed-off-by: Trond Myklebust --- fs/nfs/objlayout/objio_osd.c | 3 +++ fs/nfs/pnfs.c | 12 +++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index eb4aafa9f521..8ff2ea3f10ef 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -1000,6 +1000,9 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, if (!pnfs_generic_pg_test(pgio, prev, req)) return false; + if (pgio->pg_lseg == NULL) + return true; + return pgio->pg_count + req->wb_bytes <= OBJIO_LSEG(pgio->pg_lseg)->max_io_size; } diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 539b94cb6c0f..0f42e02436ee 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -1064,19 +1064,21 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, gfp_flags = GFP_NOFS; } - if (pgio->pg_count == prev->wb_bytes) { + if (pgio->pg_lseg == NULL) { + if (pgio->pg_count != prev->wb_bytes) + return true; /* This is first coelesce call for a series of nfs_pages */ pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, prev->wb_context, - req_offset(req), + req_offset(prev), pgio->pg_count, access_type, gfp_flags); - return true; + if (pgio->pg_lseg == NULL) + return true; } - if (pgio->pg_lseg && - req_offset(req) > end_offset(pgio->pg_lseg->pls_range.offset, + if (req_offset(req) > end_offset(pgio->pg_lseg->pls_range.offset, pgio->pg_lseg->pls_range.length)) return false; -- cgit v1.2.3 From 19982ba8562e33083cb5bbb59a74855d8a9624ea Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 10 Jun 2011 13:30:23 -0400 Subject: NFSv4.1: Fix an off-by-one error in pnfs_generic_pg_test And document what is going on there... Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 0f42e02436ee..29c0ca7fc347 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -1078,11 +1078,22 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, return true; } - if (req_offset(req) > end_offset(pgio->pg_lseg->pls_range.offset, - pgio->pg_lseg->pls_range.length)) - return false; - - return true; + /* + * Test if a nfs_page is fully contained in the pnfs_layout_range. + * Note that this test makes several assumptions: + * - that the previous nfs_page in the struct nfs_pageio_descriptor + * is known to lie within the range. + * - that the nfs_page being tested is known to be contiguous with the + * previous nfs_page. + * - Layout ranges are page aligned, so we only have to test the + * start offset of the request. + * + * Please also note that 'end_offset' is actually the offset of the + * first byte that lies outside the pnfs_layout_range. FIXME? + * + */ + return req_offset(req) < end_offset(pgio->pg_lseg->pls_range.offset, + pgio->pg_lseg->pls_range.length); } EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); -- cgit v1.2.3 From 1650add23578b5ca35c1f1e863987180a8c03779 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 2 Jun 2011 15:07:35 -0400 Subject: NFS: Fix decode_secinfo_maxsz I initially did the calculation in bytes, and not words Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/nfs4xdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 5db44a8dddf9..6870bc61ceec 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -255,7 +255,7 @@ static int nfs4_stat_to_errno(int); #define decode_fs_locations_maxsz \ (0) #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) -#define decode_secinfo_maxsz (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN))) +#define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) #if defined(CONFIG_NFS_V4_1) #define NFS4_MAX_MACHINE_NAME_LEN (64) -- cgit v1.2.3 From 9a7b2d1f0eb0a6b674726c9a9d77ce83fd0b27fe Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Jun 2011 14:43:39 -0300 Subject: [media] pwc: better usb disconnect handling Unplugging a pwc cam while an app has the /dev/video# node open leads to an oops in pwc_video_close when the app closes the node, because the disconnect handler has free-ed the pdev struct pwc_video_close tries to use. Instead of adding some sort of bandaid for this. fix it properly using the v4l2 core's new(ish) behavior of keeping the v4l2_dev structure around until both unregister has been called, and all file handles referring to it have been closed: Embed the v4l2_dev structure in the pdev structure and define a v4l2 dev release callback releasing the pdev structure (and thus also the embedded v4l2 dev structure. Signed-off-by: Hans de Goede Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/pwc-ctrl.c | 2 +- drivers/media/video/pwc/pwc-if.c | 152 ++++++++++++------------------------- drivers/media/video/pwc/pwc.h | 4 +- 3 files changed, 50 insertions(+), 108 deletions(-) diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 1593f8deb810..760b4de13adf 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -1414,7 +1414,7 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { ARG_DEF(struct pwc_probe, probe) - strcpy(ARGR(probe).name, pdev->vdev->name); + strcpy(ARGR(probe).name, pdev->vdev.name); ARGR(probe).type = pdev->type; ARG_OUT(probe) break; diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 356cd42b593b..b0bde5a87c8a 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -40,7 +40,7 @@ Oh yes, convention: to disctinguish between all the various pointers to device-structures, I use these names for the pointer variables: udev: struct usb_device * - vdev: struct video_device * + vdev: struct video_device (member of pwc_dev) pdev: struct pwc_devive * */ @@ -152,6 +152,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); static unsigned int pwc_video_poll(struct file *file, poll_table *wait); static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); +static void pwc_video_release(struct video_device *vfd); static const struct v4l2_file_operations pwc_fops = { .owner = THIS_MODULE, @@ -164,41 +165,11 @@ static const struct v4l2_file_operations pwc_fops = { }; static struct video_device pwc_template = { .name = "Philips Webcam", /* Filled in later */ - .release = video_device_release, + .release = pwc_video_release, .fops = &pwc_fops, + .ioctl_ops = &pwc_ioctl_ops, }; -/***************************************************************************/ - -/* Okay, this is some magic that I worked out and the reasoning behind it... - - The biggest problem with any USB device is of course: "what to do - when the user unplugs the device while it is in use by an application?" - We have several options: - 1) Curse them with the 7 plagues when they do (requires divine intervention) - 2) Tell them not to (won't work: they'll do it anyway) - 3) Oops the kernel (this will have a negative effect on a user's uptime) - 4) Do something sensible. - - Of course, we go for option 4. - - It happens that this device will be linked to two times, once from - usb_device and once from the video_device in their respective 'private' - pointers. This is done when the device is probed() and all initialization - succeeded. The pwc_device struct links back to both structures. - - When a device is unplugged while in use it will be removed from the - list of known USB devices; I also de-register it as a V4L device, but - unfortunately I can't free the memory since the struct is still in use - by the file descriptor. This free-ing is then deferend until the first - opportunity. Crude, but it works. - - A small 'advantage' is that if a user unplugs the cam and plugs it back - in, it should get assigned the same video device minor, but unfortunately - it's non-trivial to re-link the cam back to the video device... (that - would surely be magic! :)) -*/ - /***************************************************************************/ /* Private functions */ @@ -1016,16 +987,15 @@ static ssize_t show_snapshot_button_status(struct device *class_dev, static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status, NULL); -static int pwc_create_sysfs_files(struct video_device *vdev) +static int pwc_create_sysfs_files(struct pwc_device *pdev) { - struct pwc_device *pdev = video_get_drvdata(vdev); int rc; - rc = device_create_file(&vdev->dev, &dev_attr_button); + rc = device_create_file(&pdev->vdev.dev, &dev_attr_button); if (rc) goto err; if (pdev->features & FEATURE_MOTOR_PANTILT) { - rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt); + rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt); if (rc) goto err_button; } @@ -1033,19 +1003,17 @@ static int pwc_create_sysfs_files(struct video_device *vdev) return 0; err_button: - device_remove_file(&vdev->dev, &dev_attr_button); + device_remove_file(&pdev->vdev.dev, &dev_attr_button); err: PWC_ERROR("Could not create sysfs files.\n"); return rc; } -static void pwc_remove_sysfs_files(struct video_device *vdev) +static void pwc_remove_sysfs_files(struct pwc_device *pdev) { - struct pwc_device *pdev = video_get_drvdata(vdev); - if (pdev->features & FEATURE_MOTOR_PANTILT) - device_remove_file(&vdev->dev, &dev_attr_pan_tilt); - device_remove_file(&vdev->dev, &dev_attr_button); + device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt); + device_remove_file(&pdev->vdev.dev, &dev_attr_button); } #ifdef CONFIG_USB_PWC_DEBUG @@ -1106,7 +1074,7 @@ static int pwc_video_open(struct file *file) if (ret >= 0) { PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n", - pdev->vdev->name, + pdev->vdev.name, pwc_sensor_type_to_string(i), i); } } @@ -1180,16 +1148,15 @@ static int pwc_video_open(struct file *file) return 0; } - -static void pwc_cleanup(struct pwc_device *pdev) +static void pwc_video_release(struct video_device *vfd) { - pwc_remove_sysfs_files(pdev->vdev); - video_unregister_device(pdev->vdev); + struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev); + int hint; -#ifdef CONFIG_USB_PWC_INPUT_EVDEV - if (pdev->button_dev) - input_unregister_device(pdev->button_dev); -#endif + /* search device_hint[] table if we occupy a slot, by any chance */ + for (hint = 0; hint < MAX_DEV_HINTS; hint++) + if (device_hint[hint].pdev == pdev) + device_hint[hint].pdev = NULL; kfree(pdev); } @@ -1199,7 +1166,7 @@ static int pwc_video_close(struct file *file) { struct video_device *vdev = file->private_data; struct pwc_device *pdev; - int i, hint; + int i; PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); @@ -1234,12 +1201,6 @@ static int pwc_video_close(struct file *file) } pdev->vopen--; PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); - } else { - pwc_cleanup(pdev); - /* search device_hint[] table if we occupy a slot, by any chance */ - for (hint = 0; hint < MAX_DEV_HINTS; hint++) - if (device_hint[hint].pdev == pdev) - device_hint[hint].pdev = NULL; } return 0; @@ -1715,19 +1676,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id init_waitqueue_head(&pdev->frameq); pdev->vcompression = pwc_preferred_compression; - /* Allocate video_device structure */ - pdev->vdev = video_device_alloc(); - if (!pdev->vdev) { - PWC_ERROR("Err, cannot allocate video_device struture. Failing probe."); - rc = -ENOMEM; - goto err_free_mem; - } - memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); - pdev->vdev->parent = &intf->dev; - pdev->vdev->lock = &pdev->modlock; - pdev->vdev->ioctl_ops = &pwc_ioctl_ops; - strcpy(pdev->vdev->name, name); - video_set_drvdata(pdev->vdev, pdev); + /* Init video_device structure */ + memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); + pdev->vdev.parent = &intf->dev; + pdev->vdev.lock = &pdev->modlock; + strcpy(pdev->vdev.name, name); + video_set_drvdata(&pdev->vdev, pdev); pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); PWC_DEBUG_PROBE("Release: %04x\n", pdev->release); @@ -1746,8 +1700,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id } } - pdev->vdev->release = video_device_release; - /* occupy slot */ if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = pdev; @@ -1759,16 +1711,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pwc_set_leds(pdev, 0, 0); pwc_camera_power(pdev, 0); - rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); + rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); if (rc < 0) { PWC_ERROR("Failed to register as video device (%d).\n", rc); - goto err_video_release; + goto err_free_mem; } - rc = pwc_create_sysfs_files(pdev->vdev); + rc = pwc_create_sysfs_files(pdev); if (rc) goto err_video_unreg; - PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev)); + PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev)); #ifdef CONFIG_USB_PWC_INPUT_EVDEV /* register webcam snapshot button input device */ @@ -1776,7 +1728,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id if (!pdev->button_dev) { PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); rc = -ENOMEM; - pwc_remove_sysfs_files(pdev->vdev); + pwc_remove_sysfs_files(pdev); goto err_video_unreg; } @@ -1794,7 +1746,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id if (rc) { input_free_device(pdev->button_dev); pdev->button_dev = NULL; - pwc_remove_sysfs_files(pdev->vdev); + pwc_remove_sysfs_files(pdev); goto err_video_unreg; } #endif @@ -1804,10 +1756,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id err_video_unreg: if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = NULL; - video_unregister_device(pdev->vdev); - pdev->vdev = NULL; /* So we don't try to release it below */ -err_video_release: - video_device_release(pdev->vdev); + video_unregister_device(&pdev->vdev); err_free_mem: kfree(pdev); return rc; @@ -1816,10 +1765,8 @@ err_free_mem: /* The user yanked out the cable... */ static void usb_pwc_disconnect(struct usb_interface *intf) { - struct pwc_device *pdev; - int hint; + struct pwc_device *pdev = usb_get_intfdata(intf); - pdev = usb_get_intfdata (intf); mutex_lock(&pdev->modlock); usb_set_intfdata (intf, NULL); if (pdev == NULL) { @@ -1836,30 +1783,25 @@ static void usb_pwc_disconnect(struct usb_interface *intf) } /* We got unplugged; this is signalled by an EPIPE error code */ - if (pdev->vopen) { - PWC_INFO("Disconnected while webcam is in use!\n"); - pdev->error_status = EPIPE; - } + pdev->error_status = EPIPE; + pdev->unplugged = 1; /* Alert waiting processes */ wake_up_interruptible(&pdev->frameq); - /* Wait until device is closed */ - if (pdev->vopen) { - pdev->unplugged = 1; - pwc_iso_stop(pdev); - } else { - /* Device is closed, so we can safely unregister it */ - PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); -disconnect_out: - /* search device_hint[] table if we occupy a slot, by any chance */ - for (hint = 0; hint < MAX_DEV_HINTS; hint++) - if (device_hint[hint].pdev == pdev) - device_hint[hint].pdev = NULL; - } + /* No need to keep the urbs around after disconnection */ + pwc_isoc_cleanup(pdev); +disconnect_out: mutex_unlock(&pdev->modlock); - pwc_cleanup(pdev); + + pwc_remove_sysfs_files(pdev); + video_unregister_device(&pdev->vdev); + +#ifdef CONFIG_USB_PWC_INPUT_EVDEV + if (pdev->button_dev) + input_unregister_device(pdev->button_dev); +#endif } diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index e947766337d6..083f8b15df73 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -162,9 +162,9 @@ struct pwc_imgbuf struct pwc_device { - struct video_device *vdev; + struct video_device vdev; - /* Pointer to our usb_device */ + /* Pointer to our usb_device, may be NULL after unplug */ struct usb_device *udev; int type; /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ -- cgit v1.2.3 From efc2924e733631a64c0afed8dbba2741d186998c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Jun 2011 17:12:49 -0700 Subject: drm/i915: Call intel_enable_plane from i9xx_crtc_mode_set (again) This change got placed in the ironlake path instead of the 9xx path during a recent code shuffle. Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 81a9059b6a94..aa43e7be6053 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4687,6 +4687,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(DSPCNTR(plane), dspcntr); POSTING_READ(DSPCNTR(plane)); + intel_enable_plane(dev_priv, plane, pipe); ret = intel_pipe_set_base(crtc, x, y, old_fb); @@ -5217,8 +5218,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(DSPCNTR(plane), dspcntr); POSTING_READ(DSPCNTR(plane)); - if (!HAS_PCH_SPLIT(dev)) - intel_enable_plane(dev_priv, plane, pipe); ret = intel_pipe_set_base(crtc, x, y, old_fb); -- cgit v1.2.3 From ec6a890dfed7dd245beba5e5bcdfcffbd934c284 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 21 Jun 2011 18:37:59 +0100 Subject: drm/i915: Apply HWSTAM workaround for BSD ring on SandyBridge ...we need to apply exactly the same workaround for missing interrupts from BSD as for the BLT ring, apparently. See also commit 498e720b96379d8ee9c294950a01534a73defcf3 (drm/i915: Fix gen6 (SNB) missed BLT ring interrupts). Reported-and-tested-by: nkalkhof@web.de Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38529 Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_irq.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9e34a1abeb61..ae2b49969b99 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1749,6 +1749,7 @@ void ironlake_irq_preinstall(struct drm_device *dev) * happens. */ I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); + I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT); } /* XXX hotplug from PCH */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2f967af8e62e..5d5def756c9e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -531,6 +531,7 @@ #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) +#define GEN6_BSD_HWSTAM 0x12098 #define GEN6_BSD_IMR 0x120a8 #define GEN6_BSD_USER_INTERRUPT (1 << 12) -- cgit v1.2.3 From e92d03bff9a0d0bcbb812c9b1290ca96c9338d45 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 14 Jun 2011 16:43:09 -0700 Subject: Revert "drm/i915: Kill GTT mappings when moving from GTT domain" This reverts commit 4a684a4117abd756291969336af454e8a958802f. Userland has always been required to set the object's domain to GTT before using it through a GTT mapping, it's not something that the kernel is supposed to enforce. (The pagefault support is so that we can handle multiple mappings without userland having to pin across them, not so that userland can use GTT after GPU domains without telling the kernel). Fixes 19.2% +/- 0.8% (n=6) performance regression in cairo-gl firefox-talos-gfx on my T420 latop. Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_gem.c | 10 ++++------ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 ---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 94c84d744100..c6389de53161 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1219,11 +1219,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ret = i915_gem_object_bind_to_gtt(obj, 0, true); if (ret) goto unlock; - } - ret = i915_gem_object_set_to_gtt_domain(obj, write); - if (ret) - goto unlock; + ret = i915_gem_object_set_to_gtt_domain(obj, write); + if (ret) + goto unlock; + } if (obj->tiling_mode == I915_TILING_NONE) ret = i915_gem_object_put_fence(obj); @@ -2926,8 +2926,6 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj) */ wmb(); - i915_gem_release_mmap(obj); - old_write_domain = obj->base.write_domain; obj->base.write_domain = 0; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 20a4cc5b818f..4934cf84c320 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -187,10 +187,6 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj, if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) i915_gem_clflush_object(obj); - /* blow away mappings if mapped through GTT */ - if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT) - i915_gem_release_mmap(obj); - if (obj->base.pending_write_domain) cd->flips |= atomic_read(&obj->pending_flip); -- cgit v1.2.3 From 129b656a0de9a229a72fe4bb6bacd134a1477b44 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 10 Jun 2011 16:05:51 -0700 Subject: PM / Runtime: Update doc: usage count no longer incremented across system PM Commit e8665002477f0278f84f898145b1f141ba26ee26 (PM: Allow pm_runtime_suspend() to succeed during system suspend) removed usage count increment across system PM. Update doc to reflect this. Signed-off-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- Documentation/power/runtime_pm.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 654097b130b4..22accb3eb40e 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -566,11 +566,6 @@ to do this is: pm_runtime_set_active(dev); pm_runtime_enable(dev); -The PM core always increments the run-time usage counter before calling the -->prepare() callback and decrements it after calling the ->complete() callback. -Hence disabling run-time PM temporarily like this will not cause any run-time -suspend callbacks to be lost. - 7. Generic subsystem callbacks Subsystems may wish to conserve code space by using the set of generic power -- cgit v1.2.3 From 78420884e680da8fbc3240de2d3106437042381e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 18 Jun 2011 19:53:57 +0200 Subject: PM: Update documentation regarding sysdevs The part of Documentation/power/devices.txt regarding sysdevs is not valid any more after commit 2e711c04dbbf7a7732a3f7073b1fc285d12b369d (PM: Remove sysdev suspend, resume and shutdown operations), so remove it. Signed-off-by: Rafael J. Wysocki --- Documentation/power/devices.txt | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 88880839ece4..ff923fe67d98 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -549,32 +549,6 @@ callbacks. The other platforms need not implement it or take it into account in any way. -System Devices --------------- -System devices (sysdevs) follow a slightly different API, which can be found in - - include/linux/sysdev.h - drivers/base/sys.c - -System devices will be suspended with interrupts disabled, and after all other -devices have been suspended. On resume, they will be resumed before any other -devices, and also with interrupts disabled. These things occur in special -"sysdev_driver" phases, which affect only system devices. - -Thus, after the suspend_noirq (or freeze_noirq or poweroff_noirq) phase, when -the non-boot CPUs are all offline and IRQs are disabled on the remaining online -CPU, then a sysdev_driver.suspend phase is carried out, and the system enters a -sleep state (or a system image is created). During resume (or after the image -has been created or loaded) a sysdev_driver.resume phase is carried out, IRQs -are enabled on the only online CPU, the non-boot CPUs are enabled, and the -resume_noirq (or thaw_noirq or restore_noirq) phase begins. - -Code to actually enter and exit the system-wide low power state sometimes -involves hardware details that are only known to the boot firmware, and -may leave a CPU running software (from SRAM or flash memory) that monitors -the system and manages its wakeup sequence. - - Device Low Power (suspend) States --------------------------------- Device low-power states aren't standard. One device might only handle -- cgit v1.2.3 From f76b168b6f117a49d36307053e1acbe30580ea5b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Sat, 18 Jun 2011 20:22:23 +0200 Subject: PM: Rename dev_pm_info.in_suspend to is_prepared This patch (as1473) renames the "in_suspend" field in struct dev_pm_info to "is_prepared", in preparation for an upcoming change. The new name is more descriptive of what the field really means. Signed-off-by: Alan Stern Signed-off-by: Rafael J. Wysocki Cc: stable@kernel.org --- drivers/base/power/main.c | 14 +++++++++----- drivers/usb/core/driver.c | 6 +++--- include/linux/device.h | 4 ++-- include/linux/pm.h | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index aa6320207745..bf5a59ac1957 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -57,7 +57,7 @@ static int async_error; */ void device_pm_init(struct device *dev) { - dev->power.in_suspend = false; + dev->power.is_prepared = false; init_completion(&dev->power.completion); complete_all(&dev->power.completion); dev->power.wakeup = NULL; @@ -91,7 +91,7 @@ void device_pm_add(struct device *dev) pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); mutex_lock(&dpm_list_mtx); - if (dev->parent && dev->parent->power.in_suspend) + if (dev->parent && dev->parent->power.is_prepared) dev_warn(dev, "parent %s should not be sleeping\n", dev_name(dev->parent)); list_add_tail(&dev->power.entry, &dpm_list); @@ -511,7 +511,11 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) dpm_wait(dev->parent, async); device_lock(dev); - dev->power.in_suspend = false; + /* + * This is a fib. But we'll allow new children to be added below + * a resumed device, even if the device hasn't been completed yet. + */ + dev->power.is_prepared = false; if (dev->pwr_domain) { pm_dev_dbg(dev, state, "power domain "); @@ -670,7 +674,7 @@ void dpm_complete(pm_message_t state) struct device *dev = to_device(dpm_prepared_list.prev); get_device(dev); - dev->power.in_suspend = false; + dev->power.is_prepared = false; list_move(&dev->power.entry, &list); mutex_unlock(&dpm_list_mtx); @@ -1042,7 +1046,7 @@ int dpm_prepare(pm_message_t state) put_device(dev); break; } - dev->power.in_suspend = true; + dev->power.is_prepared = true; if (!list_empty(&dev->power.entry)) list_move_tail(&dev->power.entry, &dpm_prepared_list); put_device(dev); diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index e35a17687c05..aa3cc465a601 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -375,7 +375,7 @@ static int usb_unbind_interface(struct device *dev) * Just re-enable it without affecting the endpoint toggles. */ usb_enable_interface(udev, intf, false); - } else if (!error && !intf->dev.power.in_suspend) { + } else if (!error && !intf->dev.power.is_prepared) { r = usb_set_interface(udev, intf->altsetting[0]. desc.bInterfaceNumber, 0); if (r < 0) @@ -960,7 +960,7 @@ void usb_rebind_intf(struct usb_interface *intf) } /* Try to rebind the interface */ - if (!intf->dev.power.in_suspend) { + if (!intf->dev.power.is_prepared) { intf->needs_binding = 0; rc = device_attach(&intf->dev); if (rc < 0) @@ -1107,7 +1107,7 @@ static int usb_resume_interface(struct usb_device *udev, if (intf->condition == USB_INTERFACE_UNBOUND) { /* Carry out a deferred switch to altsetting 0 */ - if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) { + if (intf->needs_altsetting0 && !intf->dev.power.is_prepared) { usb_set_interface(udev, intf->altsetting[0]. desc.bInterfaceNumber, 0); intf->needs_altsetting0 = 0; diff --git a/include/linux/device.h b/include/linux/device.h index c66111affca9..553fd37b173b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -654,13 +654,13 @@ static inline int device_is_registered(struct device *dev) static inline void device_enable_async_suspend(struct device *dev) { - if (!dev->power.in_suspend) + if (!dev->power.is_prepared) dev->power.async_suspend = true; } static inline void device_disable_async_suspend(struct device *dev) { - if (!dev->power.in_suspend) + if (!dev->power.is_prepared) dev->power.async_suspend = false; } diff --git a/include/linux/pm.h b/include/linux/pm.h index 3160648ccdda..cc536bd80984 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -425,7 +425,7 @@ struct dev_pm_info { pm_message_t power_state; unsigned int can_wakeup:1; unsigned int async_suspend:1; - unsigned int in_suspend:1; /* Owned by the PM core */ + bool is_prepared:1; /* Owned by the PM core */ spinlock_t lock; #ifdef CONFIG_PM_SLEEP struct list_head entry; -- cgit v1.2.3 From 8440f4b19494467883f8541b7aa28c7bbf6ac92b Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Sat, 18 Jun 2011 20:34:01 +0200 Subject: PM: Free memory bitmaps if opening /dev/snapshot fails When opening /dev/snapshot device, snapshot_open() creates memory bitmaps which are freed in snapshot_release(). But if any of the callbacks called by pm_notifier_call_chain() returns NOTIFY_BAD, open() fails, snapshot_release() is never called and bitmaps are not freed. Next attempt to open /dev/snapshot then triggers BUG_ON() check in create_basic_memory_bitmaps(). This happens e.g. when vmwatchdog module is active on s390x. Signed-off-by: Michal Kubecek Signed-off-by: Rafael J. Wysocki Cc: stable@kernel.org --- kernel/power/user.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/power/user.c b/kernel/power/user.c index 7d02d33be699..42ddbc6f0de6 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -113,8 +113,10 @@ static int snapshot_open(struct inode *inode, struct file *filp) if (error) pm_notifier_call_chain(PM_POST_RESTORE); } - if (error) + if (error) { + free_basic_memory_bitmaps(); atomic_inc(&snapshot_device_available); + } data->frozen = 0; data->ready = 0; data->platform_support = 0; -- cgit v1.2.3 From 6d0e0e84f66d32c33511984dd3badd32364b863c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Sat, 18 Jun 2011 22:42:09 +0200 Subject: PM: Fix async resume following suspend failure The PM core doesn't handle suspend failures correctly when it comes to asynchronously suspended devices. These devices are moved onto the dpm_suspended_list as soon as the corresponding async thread is started up, and they remain on the list even if they fail to suspend or the sleep transition is cancelled before they get suspended. As a result, when the PM core unwinds the transition, it tries to resume the devices even though they were never suspended. This patch (as1474) fixes the problem by adding a new "is_suspended" flag to dev_pm_info. Devices are resumed only if the flag is set. [rjw: * Moved the dev->power.is_suspended check into device_resume(), because we need to complete dev->power.completion and clear dev->power.is_prepared too for devices whose dev->power.is_suspended flags are unset. * Fixed __device_suspend() to avoid setting dev->power.is_suspended if async_error is different from zero.] Signed-off-by: Alan Stern Signed-off-by: Rafael J. Wysocki Cc: stable@kernel.org --- drivers/base/power/main.c | 14 ++++++++++++-- include/linux/pm.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index bf5a59ac1957..06f09bf89cb2 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -58,6 +58,7 @@ static int async_error; void device_pm_init(struct device *dev) { dev->power.is_prepared = false; + dev->power.is_suspended = false; init_completion(&dev->power.completion); complete_all(&dev->power.completion); dev->power.wakeup = NULL; @@ -517,6 +518,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) */ dev->power.is_prepared = false; + if (!dev->power.is_suspended) + goto Unlock; + if (dev->pwr_domain) { pm_dev_dbg(dev, state, "power domain "); error = pm_op(dev, &dev->pwr_domain->ops, state); @@ -552,6 +556,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) } End: + dev->power.is_suspended = false; + + Unlock: device_unlock(dev); complete_all(&dev->power.completion); @@ -839,11 +846,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) device_lock(dev); if (async_error) - goto End; + goto Unlock; if (pm_wakeup_pending()) { async_error = -EBUSY; - goto End; + goto Unlock; } if (dev->pwr_domain) { @@ -881,6 +888,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) } End: + dev->power.is_suspended = !error; + + Unlock: device_unlock(dev); complete_all(&dev->power.completion); diff --git a/include/linux/pm.h b/include/linux/pm.h index cc536bd80984..411e4f4be52b 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -426,6 +426,7 @@ struct dev_pm_info { unsigned int can_wakeup:1; unsigned int async_suspend:1; bool is_prepared:1; /* Owned by the PM core */ + bool is_suspended:1; /* Ditto */ spinlock_t lock; #ifdef CONFIG_PM_SLEEP struct list_head entry; -- cgit v1.2.3 From 4d1518f5668ef1b3dff6c3b30fa761fe5573cdaa Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 21 Jun 2011 23:24:33 +0200 Subject: PM / Runtime: Handle clocks correctly if CONFIG_PM_RUNTIME is unset Commit 85eb8c8d0b0900c073b0e6f89979ac9c439ade1a (PM / Runtime: Generic clock manipulation rountines for runtime PM (v6)) converted the shmobile platform to using generic code for runtime PM clock management, but it changed the behavior for CONFIG_PM_RUNTIME unset incorrectly. Specifically, for CONFIG_PM_RUNTIME unset pm_runtime_clk_notify() should enable clocks for action equal to BUS_NOTIFY_BIND_DRIVER and it should disable them for action equal to BUS_NOTIFY_UNBOUND_DRIVER (instead of BUS_NOTIFY_ADD_DEVICE and BUS_NOTIFY_DEL_DEVICE, respectively). Make this function behave as appropriate. Signed-off-by: Rafael J. Wysocki Acked-by: Magnus Damm --- drivers/base/power/clock_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index eaa8a854af03..ad367c4139b1 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -387,7 +387,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, clknb = container_of(nb, struct pm_clk_notifier_block, nb); switch (action) { - case BUS_NOTIFY_ADD_DEVICE: + case BUS_NOTIFY_BIND_DRIVER: if (clknb->con_ids[0]) { for (con_id = clknb->con_ids; *con_id; con_id++) enable_clock(dev, *con_id); @@ -395,7 +395,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, enable_clock(dev, NULL); } break; - case BUS_NOTIFY_DEL_DEVICE: + case BUS_NOTIFY_UNBOUND_DRIVER: if (clknb->con_ids[0]) { for (con_id = clknb->con_ids; *con_id; con_id++) disable_clock(dev, *con_id); -- cgit v1.2.3 From ca9c6890b598997165a7c85c001f382c910f12b0 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 21 Jun 2011 23:25:32 +0200 Subject: PM / Domains: Update documentation Commit 4d27e9dcff00a6425d779b065ec8892e4f391661 (PM: Make power domain callbacks take precedence over subsystem ones) forgot to update the device power management documentation to take changes made by it into account. Correct that mistake. Signed-off-by: Rafael J. Wysocki --- Documentation/power/devices.txt | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index ff923fe67d98..64565aac6e40 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -520,33 +520,20 @@ Support for power domains is provided through the pwr_domain field of struct device. This field is a pointer to an object of type struct dev_power_domain, defined in include/linux/pm.h, providing a set of power management callbacks analogous to the subsystem-level and device driver callbacks that are executed -for the given device during all power transitions, in addition to the respective -subsystem-level callbacks. Specifically, the power domain "suspend" callbacks -(i.e. ->runtime_suspend(), ->suspend(), ->freeze(), ->poweroff(), etc.) are -executed after the analogous subsystem-level callbacks, while the power domain -"resume" callbacks (i.e. ->runtime_resume(), ->resume(), ->thaw(), ->restore, -etc.) are executed before the analogous subsystem-level callbacks. Error codes -returned by the "suspend" and "resume" power domain callbacks are ignored. - -Power domain ->runtime_idle() callback is executed before the subsystem-level -->runtime_idle() callback and the result returned by it is not ignored. Namely, -if it returns error code, the subsystem-level ->runtime_idle() callback will not -be called and the helper function rpm_idle() executing it will return error -code. This mechanism is intended to help platforms where saving device state -is a time consuming operation and should only be carried out if all devices -in the power domain are idle, before turning off the shared power resource(s). -Namely, the power domain ->runtime_idle() callback may return error code until -the pm_runtime_idle() helper (or its asychronous version) has been called for -all devices in the power domain (it is recommended that the returned error code -be -EBUSY in those cases), preventing the subsystem-level ->runtime_idle() -callback from being run prematurely. - -The support for device power domains is only relevant to platforms needing to -use the same subsystem-level (e.g. platform bus type) and device driver power -management callbacks in many different power domain configurations and wanting -to avoid incorporating the support for power domains into the subsystem-level -callbacks. The other platforms need not implement it or take it into account -in any way. +for the given device during all power transitions, instead of the respective +subsystem-level callbacks. Specifically, if a device's pm_domain pointer is +not NULL, the ->suspend() callback from the object pointed to by it will be +executed instead of its subsystem's (e.g. bus type's) ->suspend() callback and +anlogously for all of the remaining callbacks. In other words, power management +domain callbacks, if defined for the given device, always take precedence over +the callbacks provided by the device's subsystem (e.g. bus type). + +The support for device power management domains is only relevant to platforms +needing to use the same device driver power management callbacks in many +different power domain configurations and wanting to avoid incorporating the +support for power domains into subsystem-level callbacks, for example by +modifying the platform bus type. Other platforms need not implement it or take +it into account in any way. Device Low Power (suspend) States -- cgit v1.2.3 From a5f76d5eba157bf637beb2dd18026db2917c512e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 21 Jun 2011 23:47:15 +0200 Subject: PCI / PM: Block races between runtime PM and system sleep After commit e8665002477f0278f84f898145b1f141ba26ee26 (PM: Allow pm_runtime_suspend() to succeed during system suspend) it is possible that a device resumed by the pm_runtime_resume(dev) in pci_pm_prepare() will be suspended immediately from a work item, timer function or otherwise, defeating the very purpose of calling pm_runtime_resume(dev) from there. To prevent that from happening it is necessary to increment the runtime PM usage counter of the device by replacing pm_runtime_resume() with pm_runtime_get_sync(). Moreover, the incremented runtime PM usage counter has to be decremented by the corresponding pci_pm_complete(), via pm_runtime_put_sync(). Signed-off-by: Rafael J. Wysocki Cc: stable@kernel.org Acked-by: Jesse Barnes --- drivers/pci/pci-driver.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 135df164a4c1..46767c53917a 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -624,7 +624,7 @@ static int pci_pm_prepare(struct device *dev) * system from the sleep state, we'll have to prevent it from signaling * wake-up. */ - pm_runtime_resume(dev); + pm_runtime_get_sync(dev); if (drv && drv->pm && drv->pm->prepare) error = drv->pm->prepare(dev); @@ -638,6 +638,8 @@ static void pci_pm_complete(struct device *dev) if (drv && drv->pm && drv->pm->complete) drv->pm->complete(dev); + + pm_runtime_put_sync(dev); } #else /* !CONFIG_PM_SLEEP */ -- cgit v1.2.3 From c008ba58af24dc5d0d8e9fe6e59d876910254761 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 16 Jun 2011 18:27:09 -0700 Subject: alarmtimers: Handle late rtc module loading The alarmtimers code currently picks a rtc device to use at late init time. However, if your rtc driver is loaded as a module, it may be registered after the alarmtimers late init code, leaving the alarmtimers nonfunctional. This patch moves the the rtcdevice selection to when we actually try to use it, allowing us to make use of rtc modules that may have been loaded at any point since bootup. CC: Thomas Gleixner CC: Meelis Roos Reported-by: Meelis Roos Signed-off-by: John Stultz --- kernel/time/alarmtimer.c | 137 +++++++++++++++++++++++------------------------ 1 file changed, 67 insertions(+), 70 deletions(-) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 2d966244ea60..98ecf4e36f2f 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -42,15 +42,72 @@ static struct alarm_base { clockid_t base_clockid; } alarm_bases[ALARM_NUMTYPE]; +/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */ +static ktime_t freezer_delta; +static DEFINE_SPINLOCK(freezer_delta_lock); + #ifdef CONFIG_RTC_CLASS /* rtc timer and device for setting alarm wakeups at suspend */ static struct rtc_timer rtctimer; static struct rtc_device *rtcdev; -#endif +static DEFINE_SPINLOCK(rtcdev_lock); -/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */ -static ktime_t freezer_delta; -static DEFINE_SPINLOCK(freezer_delta_lock); +/** + * has_wakealarm - check rtc device has wakealarm ability + * @dev: current device + * @name_ptr: name to be returned + * + * This helper function checks to see if the rtc device can wake + * from suspend. + */ +static int has_wakealarm(struct device *dev, void *name_ptr) +{ + struct rtc_device *candidate = to_rtc_device(dev); + + if (!candidate->ops->set_alarm) + return 0; + if (!device_may_wakeup(candidate->dev.parent)) + return 0; + + *(const char **)name_ptr = dev_name(dev); + return 1; +} + +/** + * alarmtimer_get_rtcdev - Return selected rtcdevice + * + * This function returns the rtc device to use for wakealarms. + * If one has not already been chosen, it checks to see if a + * functional rtc device is available. + */ +static struct rtc_device *alarmtimer_get_rtcdev(void) +{ + struct device *dev; + char *str; + unsigned long flags; + struct rtc_device *ret; + + spin_lock_irqsave(&rtcdev_lock, flags); + if (!rtcdev) { + /* Find an rtc device and init the rtc_timer */ + dev = class_find_device(rtc_class, NULL, &str, has_wakealarm); + /* If we have a device then str is valid. See has_wakealarm() */ + if (dev) { + rtcdev = rtc_class_open(str); + /* + * Drop the reference we got in class_find_device, + * rtc_open takes its own. + */ + put_device(dev); + rtc_timer_init(&rtctimer, NULL, NULL); + } + } + ret = rtcdev; + spin_unlock_irqrestore(&rtcdev_lock, flags); + + return ret; +} +#endif /** @@ -166,6 +223,7 @@ static int alarmtimer_suspend(struct device *dev) struct rtc_time tm; ktime_t min, now; unsigned long flags; + struct rtc_device *rtc; int i; spin_lock_irqsave(&freezer_delta_lock, flags); @@ -173,8 +231,9 @@ static int alarmtimer_suspend(struct device *dev) freezer_delta = ktime_set(0, 0); spin_unlock_irqrestore(&freezer_delta_lock, flags); + rtc = alarmtimer_get_rtcdev(); /* If we have no rtcdev, just return */ - if (!rtcdev) + if (!rtc) return 0; /* Find the soonest timer to expire*/ @@ -199,12 +258,12 @@ static int alarmtimer_suspend(struct device *dev) WARN_ON(min.tv64 < NSEC_PER_SEC); /* Setup an rtc timer to fire that far in the future */ - rtc_timer_cancel(rtcdev, &rtctimer); - rtc_read_time(rtcdev, &tm); + rtc_timer_cancel(rtc, &rtctimer); + rtc_read_time(rtc, &tm); now = rtc_tm_to_ktime(tm); now = ktime_add(now, min); - rtc_timer_start(rtcdev, &rtctimer, now, ktime_set(0, 0)); + rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); return 0; } @@ -638,65 +697,3 @@ static int __init alarmtimer_init(void) } device_initcall(alarmtimer_init); -#ifdef CONFIG_RTC_CLASS -/** - * has_wakealarm - check rtc device has wakealarm ability - * @dev: current device - * @name_ptr: name to be returned - * - * This helper function checks to see if the rtc device can wake - * from suspend. - */ -static int __init has_wakealarm(struct device *dev, void *name_ptr) -{ - struct rtc_device *candidate = to_rtc_device(dev); - - if (!candidate->ops->set_alarm) - return 0; - if (!device_may_wakeup(candidate->dev.parent)) - return 0; - - *(const char **)name_ptr = dev_name(dev); - return 1; -} - -/** - * alarmtimer_init_late - Late initializing of alarmtimer code - * - * This function locates a rtc device to use for wakealarms. - * Run as late_initcall to make sure rtc devices have been - * registered. - */ -static int __init alarmtimer_init_late(void) -{ - struct device *dev; - char *str; - - /* Find an rtc device and init the rtc_timer */ - dev = class_find_device(rtc_class, NULL, &str, has_wakealarm); - /* If we have a device then str is valid. See has_wakealarm() */ - if (dev) { - rtcdev = rtc_class_open(str); - /* - * Drop the reference we got in class_find_device, - * rtc_open takes its own. - */ - put_device(dev); - } - if (!rtcdev) { - printk(KERN_WARNING "No RTC device found, ALARM timers will" - " not wake from suspend"); - } - rtc_timer_init(&rtctimer, NULL, NULL); - - return 0; -} -#else -static int __init alarmtimer_init_late(void) -{ - printk(KERN_WARNING "Kernel not built with RTC support, ALARM timers" - " will not wake from suspend"); - return 0; -} -#endif -late_initcall(alarmtimer_init_late); -- cgit v1.2.3 From 58fa45973117ab7a79d5b6818275a887867fc4d7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 21 Jun 2011 08:01:20 +0000 Subject: netconsole: fix build when CONFIG_NETCONSOLE_DYNAMIC is turned on When NETCONSOLE_DYNAMIC=y and CONFIGFS_FS=m, there are build errors in netconsole: drivers/built-in.o: In function `drop_netconsole_target': netconsole.c:(.text+0x1a100f): undefined reference to `config_item_put' drivers/built-in.o: In function `make_netconsole_target': netconsole.c:(.text+0x1a10b9): undefined reference to `config_item_init_type_name' drivers/built-in.o: In function `write_msg': netconsole.c:(.text+0x1a11a4): undefined reference to `config_item_get' netconsole.c:(.text+0x1a1211): undefined reference to `config_item_put' drivers/built-in.o: In function `netconsole_netdev_event': netconsole.c:(.text+0x1a12cc): undefined reference to `config_item_put' netconsole.c:(.text+0x1a12ec): undefined reference to `config_item_get' netconsole.c:(.text+0x1a1366): undefined reference to `config_item_put' drivers/built-in.o: In function `init_netconsole': netconsole.c:(.init.text+0x953a): undefined reference to `config_group_init' netconsole.c:(.init.text+0x9560): undefined reference to `configfs_register_subsystem' drivers/built-in.o: In function `dynamic_netconsole_exit': netconsole.c:(.exit.text+0x809): undefined reference to `configfs_unregister_subsystem' so fix the NETCONSOLE_DYNAMIC depends clause to prevent this. Based on email suggestion from Ben Hutchings. Thanks. Fixes https://bugzilla.kernel.org/show_bug.cgi?id=37992 Reported-by: David Hill Signed-off-by: Randy Dunlap Cc: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 19f04a34783a..93359fab240e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -3416,7 +3416,8 @@ config NETCONSOLE config NETCONSOLE_DYNAMIC bool "Dynamic reconfiguration of logging targets" - depends on NETCONSOLE && SYSFS && CONFIGFS_FS + depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \ + !(NETCONSOLE=y && CONFIGFS_FS=m) help This option enables the ability to dynamically reconfigure target parameters (interface, IP addresses, port numbers, MAC addresses) -- cgit v1.2.3 From 1c6b39ad3f01514fd8dd84b5b412bafb75c19388 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 16 Jun 2011 18:47:37 -0700 Subject: alarmtimers: Return -ENOTSUPP if no RTC device is present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Toralf Förster and Richard Weinberger noted that if there is no RTC device, the alarm timers core prints out an annoying "ALARM timers will not wake from suspend" message. This warning has been removed in a previous patch, however the issue still remains: The original idea was to support alarm timers even if there was no rtc device, as long as the system didn't go into suspend. However, after further consideration, communicating to the application that alarmtimers are not fully functional seems like the better solution. So this patch makes it so we return -ENOTSUPP to any posix _ALARM clockid calls if there is no backing RTC device on the system. Further this changes the behavior where when there is no rtc device we will check for one on clock_getres, clock_gettime, timer_create, and timer_nsleep instead of on suspend. CC: Toralf Förster CC: Richard Weinberger CC: Thomas Gleixner Reported-by: Toralf Förster Reported by: Richard Weinberger Signed-off-by: John Stultz --- kernel/time/alarmtimer.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 98ecf4e36f2f..59f369f98a04 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -107,6 +107,9 @@ static struct rtc_device *alarmtimer_get_rtcdev(void) return ret; } +#else +#define alarmtimer_get_rtcdev() (0) +#define rtcdev (0) #endif @@ -231,7 +234,7 @@ static int alarmtimer_suspend(struct device *dev) freezer_delta = ktime_set(0, 0); spin_unlock_irqrestore(&freezer_delta_lock, flags); - rtc = alarmtimer_get_rtcdev(); + rtc = rtcdev; /* If we have no rtcdev, just return */ if (!rtc) return 0; @@ -381,6 +384,9 @@ static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp) { clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid; + if (!alarmtimer_get_rtcdev()) + return -ENOTSUPP; + return hrtimer_get_res(baseid, tp); } @@ -395,6 +401,9 @@ static int alarm_clock_get(clockid_t which_clock, struct timespec *tp) { struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; + if (!alarmtimer_get_rtcdev()) + return -ENOTSUPP; + *tp = ktime_to_timespec(base->gettime()); return 0; } @@ -410,6 +419,9 @@ static int alarm_timer_create(struct k_itimer *new_timer) enum alarmtimer_type type; struct alarm_base *base; + if (!alarmtimer_get_rtcdev()) + return -ENOTSUPP; + if (!capable(CAP_WAKE_ALARM)) return -EPERM; @@ -444,6 +456,9 @@ static void alarm_timer_get(struct k_itimer *timr, */ static int alarm_timer_del(struct k_itimer *timr) { + if (!rtcdev) + return -ENOTSUPP; + alarm_cancel(&timr->it.alarmtimer); return 0; } @@ -461,6 +476,9 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, struct itimerspec *new_setting, struct itimerspec *old_setting) { + if (!rtcdev) + return -ENOTSUPP; + /* Save old values */ old_setting->it_interval = ktime_to_timespec(timr->it.alarmtimer.period); @@ -600,6 +618,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, int ret = 0; struct restart_block *restart; + if (!alarmtimer_get_rtcdev()) + return -ENOTSUPP; + if (!capable(CAP_WAKE_ALARM)) return -EPERM; -- cgit v1.2.3 From 35052cffe0081904f3362c05818db900dd9dc7de Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 21 Jun 2011 10:29:51 +0100 Subject: MN10300: asm/uaccess.h needs to #include linux/kernel.h for might_sleep() MN10300's asm/uaccess.h needs to #include linux/kernel.h to get might_sleep() otherwise it fails to build on MN10300 allyesconfig. This fails in a few places with messages like the following: In file included from security/keys/trusted.c:14: include/linux/uaccess.h: In function '__copy_from_user_nocache': include/linux/uaccess.h:52: error: implicit declaration of function 'might_sleep' Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/include/asm/uaccess.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h index 3d6e60dad9d9..780560b330d9 100644 --- a/arch/mn10300/include/asm/uaccess.h +++ b/arch/mn10300/include/asm/uaccess.h @@ -15,6 +15,7 @@ * User space memory access functions */ #include +#include #include #include -- cgit v1.2.3 From b1d7dd80aadb9042e83f9778b484a2f92e0b04d4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 21 Jun 2011 14:32:05 +0100 Subject: KEYS: Fix error handling in construct_key_and_link() Fix error handling in construct_key_and_link(). If construct_alloc_key() returns an error, it shouldn't pass out through the normal path as the key_serial() called by the kleave() statement will oops when it gets an error code in the pointer: BUG: unable to handle kernel paging request at ffffffffffffff84 IP: [] request_key_and_link+0x4d7/0x52f .. Call Trace: [] request_key+0x41/0x75 [] cifs_get_spnego_key+0x206/0x226 [cifs] [] CIFS_SessSetup+0x511/0x1234 [cifs] [] cifs_setup_session+0x90/0x1ae [cifs] [] cifs_get_smb_ses+0x34b/0x40f [cifs] [] cifs_mount+0x13f/0x504 [cifs] [] cifs_do_mount+0xc4/0x672 [cifs] [] mount_fs+0x69/0x155 [] vfs_kern_mount+0x63/0xa0 [] do_kern_mount+0x4d/0xdf [] do_mount+0x63c/0x69f [] sys_mount+0x88/0xc2 [] system_call_fastpath+0x16/0x1b Signed-off-by: David Howells Acked-by: Jeff Layton Signed-off-by: Linus Torvalds --- security/keys/request_key.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 8e319a416eec..82465328c39b 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -469,7 +469,7 @@ static struct key *construct_key_and_link(struct key_type *type, } else if (ret == -EINPROGRESS) { ret = 0; } else { - key = ERR_PTR(ret); + goto couldnt_alloc_key; } key_put(dest_keyring); @@ -479,6 +479,7 @@ static struct key *construct_key_and_link(struct key_type *type, construction_failed: key_negate_and_link(key, key_negative_timeout, NULL, NULL); key_put(key); +couldnt_alloc_key: key_put(dest_keyring); kleave(" = %d", ret); return ERR_PTR(ret); -- cgit v1.2.3 From 32c90254ed4a0c698caa0794ebb4de63fcc69631 Mon Sep 17 00:00:00 2001 From: Xufeng Zhang Date: Tue, 21 Jun 2011 10:43:39 +0000 Subject: ipv6/udp: Use the correct variable to determine non-blocking condition udpv6_recvmsg() function is not using the correct variable to determine whether or not the socket is in non-blocking operation, this will lead to unexpected behavior when a UDP checksum error occurs. Consider a non-blocking udp receive scenario: when udpv6_recvmsg() is called by sock_common_recvmsg(), MSG_DONTWAIT bit of flags variable in udpv6_recvmsg() is cleared by "flags & ~MSG_DONTWAIT" in this call: err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, &addr_len); i.e. with udpv6_recvmsg() getting these values: int noblock = flags & MSG_DONTWAIT int flags = flags & ~MSG_DONTWAIT So, when udp checksum error occurs, the execution will go to csum_copy_err, and then the problem happens: csum_copy_err: ............... if (flags & MSG_DONTWAIT) return -EAGAIN; goto try_again; ............... But it will always go to try_again as MSG_DONTWAIT has been cleared from flags at call time -- only noblock contains the original value of MSG_DONTWAIT, so the test should be: if (noblock) return -EAGAIN; This is also consistent with what the ipv4/udp code does. Signed-off-by: Xufeng Zhang Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/ipv6/udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 41f8c9c08dba..1e7a43f500ab 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -453,7 +453,7 @@ csum_copy_err: } unlock_sock_fast(sk, slow); - if (flags & MSG_DONTWAIT) + if (noblock) return -EAGAIN; goto try_again; } -- cgit v1.2.3 From 9cfaa8def1c795a512bc04f2aec333b03724ca2e Mon Sep 17 00:00:00 2001 From: Xufeng Zhang Date: Tue, 21 Jun 2011 10:43:40 +0000 Subject: udp/recvmsg: Clear MSG_TRUNC flag when starting over for a new packet Consider this scenario: When the size of the first received udp packet is bigger than the receive buffer, MSG_TRUNC bit is set in msg->msg_flags. However, if checksum error happens and this is a blocking socket, it will goto try_again loop to receive the next packet. But if the size of the next udp packet is smaller than receive buffer, MSG_TRUNC flag should not be set, but because MSG_TRUNC bit is not cleared in msg->msg_flags before receive the next packet, MSG_TRUNC is still set, which is wrong. Fix this problem by clearing MSG_TRUNC flag when starting over for a new packet. Signed-off-by: Xufeng Zhang Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/ipv4/udp.c | 3 +++ net/ipv6/udp.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index abca870d8ff6..48cd88e62553 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1249,6 +1249,9 @@ csum_copy_err: if (noblock) return -EAGAIN; + + /* starting over for a new packet */ + msg->msg_flags &= ~MSG_TRUNC; goto try_again; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1e7a43f500ab..328985c40883 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -455,6 +455,9 @@ csum_copy_err: if (noblock) return -EAGAIN; + + /* starting over for a new packet */ + msg->msg_flags &= ~MSG_TRUNC; goto try_again; } -- cgit v1.2.3 From c02a02ee4db5cd8b95ee3cc705b535f443612583 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Mon, 13 Jun 2011 10:23:12 +0800 Subject: powerpc/85xx: fix NAND_CMD_READID read bytes number when nand_get_flash_type() is called, it will read 8 bytes of ID instead of 5, but the driver only read 5 bytes, so kernel will dump error messages like: fsl-lbc ffe124000.localbus: read_byte beyond end of buffer fsl-lbc ffe124000.localbus: read_byte beyond end of buffer fsl-lbc ffe124000.localbus: read_byte beyond end of buffer Signed-off-by: Shaohui Xie Acked-by: Scott Wood Signed-off-by: Kumar Gala --- drivers/mtd/nand/fsl_elbc_nand.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 0bb254c7d2b1..33d8aad8bba5 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -339,9 +339,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, (FIR_OP_UA << FIR_OP1_SHIFT) | (FIR_OP_RBW << FIR_OP2_SHIFT)); out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); - /* 5 bytes for manuf, device and exts */ - out_be32(&lbc->fbcr, 5); - elbc_fcm_ctrl->read_bytes = 5; + /* nand_get_flash_type() reads 8 bytes of entire ID string */ + out_be32(&lbc->fbcr, 8); + elbc_fcm_ctrl->read_bytes = 8; elbc_fcm_ctrl->use_mdr = 1; elbc_fcm_ctrl->mdr = 0; -- cgit v1.2.3 From f3fed682f78dfab384d3dc3f9ca7a7338a93c142 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 8 Jun 2011 14:03:05 -0500 Subject: powerpc/p1022ds: fix audio-related properties in the device tree On the Freescale P1022DS reference board, the SSI audio controller is connected in "asynchronous" mode to the codec's clocks, so the device tree needs an "fsl,ssi-asynchronous" property. Also remove the clock-frequency property from the wm8776 node, because the clock is enabled only if U-Boot enables it, and U-Boot will set the property if the clock is enabled. A future version of the P1022DS audio driver will configure the clock itself, but for now, the driver should not be told that the clock is running when it isn't. Also fix the FIFO depth to 15, instead of 16. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala --- arch/powerpc/boot/dts/p1022ds.dts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/boot/dts/p1022ds.dts b/arch/powerpc/boot/dts/p1022ds.dts index 4f685a779f4c..98d9426d4b85 100644 --- a/arch/powerpc/boot/dts/p1022ds.dts +++ b/arch/powerpc/boot/dts/p1022ds.dts @@ -209,8 +209,10 @@ wm8776:codec@1a { compatible = "wlf,wm8776"; reg = <0x1a>; - /* MCLK source is a stand-alone oscillator */ - clock-frequency = <12288000>; + /* + * clock-frequency will be set by U-Boot if + * the clock is enabled. + */ }; }; @@ -280,7 +282,8 @@ codec-handle = <&wm8776>; fsl,playback-dma = <&dma00>; fsl,capture-dma = <&dma01>; - fsl,fifo-depth = <16>; + fsl,fifo-depth = <15>; + fsl,ssi-asynchronous; }; dma@c300 { -- cgit v1.2.3 From 82a9a4809f4cb4ce3f17da99a8150df8455fa096 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Thu, 16 Jun 2011 14:09:17 -0500 Subject: powerpc/e500: fix breakage with fsl_rio_mcheck_exception The wrong MCSR bit was being used on e500mc. MCSR_BUS_RBERR only exists on e500v1/v2. Use MCSR_LD on e500mc, and remove all MCSR checking in fsl_rio_mcheck_exception as we now no longer call that function if the appropriate bit in MCSR is not set. If RIO support was enabled at compile-time, but was never probed, just return from fsl_rio_mcheck_exception rather than dereference a NULL pointer. TODO: There is still a remaining, though comparitively minor, issue in that this recovery mechanism will falsely engage if there's an unrelated MCSR_LD event at the same time as a RIO error. Signed-off-by: Scott Wood Signed-off-by: Kumar Gala --- arch/powerpc/kernel/traps.c | 2 +- arch/powerpc/sysdev/fsl_rio.c | 35 ++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 0ff4ab98d50c..6414a0d5ba65 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -425,7 +425,7 @@ int machine_check_e500mc(struct pt_regs *regs) unsigned long reason = mcsr; int recoverable = 1; - if (reason & MCSR_BUS_RBERR) { + if (reason & MCSR_LD) { recoverable = fsl_rio_mcheck_exception(regs); if (recoverable == 1) goto silent_out; diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 5b206a2fe17c..b3fd081d56f5 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -283,23 +283,24 @@ static void __iomem *rio_regs_win; #ifdef CONFIG_E500 int fsl_rio_mcheck_exception(struct pt_regs *regs) { - const struct exception_table_entry *entry = NULL; - unsigned long reason = mfspr(SPRN_MCSR); - - if (reason & MCSR_BUS_RBERR) { - reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR)); - if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) { - /* Check if we are prepared to handle this fault */ - entry = search_exception_tables(regs->nip); - if (entry) { - pr_debug("RIO: %s - MC Exception handled\n", - __func__); - out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), - 0); - regs->msr |= MSR_RI; - regs->nip = entry->fixup; - return 1; - } + const struct exception_table_entry *entry; + unsigned long reason; + + if (!rio_regs_win) + return 0; + + reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR)); + if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) { + /* Check if we are prepared to handle this fault */ + entry = search_exception_tables(regs->nip); + if (entry) { + pr_debug("RIO: %s - MC Exception handled\n", + __func__); + out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), + 0); + regs->msr |= MSR_RI; + regs->nip = entry->fixup; + return 1; } } -- cgit v1.2.3 From 80629b0b0fd5ca868dc8eced28e6101e39ac2ef6 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 22 Jun 2011 16:24:07 +0200 Subject: [S390] kvm-s390: fix kconfig dependencies A user can create the Kconfig combination !VIRTUALIZATION, S390_GUEST which results in the following warnings: warning: (S390_GUEST) selects VIRTIO which has unmet direct dependencies (VIRTUALIZATION) warning: (S390_GUEST && VIRTIO_PCI && VIRTIO_BALLOON) selects VIRTIO_RING which has unmet direct dependencies (VIRTUALIZATION && VIRTIO) warning: (S390_GUEST) selects VIRTIO which has unmet direct dependencies (VIRTUALIZATION) warning: (S390_GUEST && VIRTIO_PCI && VIRTIO_BALLOON) selects VIRTIO_RING which has unmet direct dependencies (VIRTUALIZATION && VIRTIO) S390_GUEST has to select VIRTUALIZATION before selecting VIRTIO and friends. Reported-by: Jan Glauber Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 90d77bd078f5..c03fef7a9c22 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -579,6 +579,7 @@ config S390_GUEST def_bool y prompt "s390 guest support for KVM (EXPERIMENTAL)" depends on 64BIT && EXPERIMENTAL + select VIRTUALIZATION select VIRTIO select VIRTIO_RING select VIRTIO_CONSOLE -- cgit v1.2.3 From b530ce7a1af5a9355be518557d86b33c6d2cf088 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 22 Jun 2011 16:24:08 +0200 Subject: [S390] s390: enforce HW limits for the initial sampling rate On specific configurations with hwsampler opcontrol --start returns an error on "echo 1 >/dev/oprofile/enable". Turns out that the hw sampling interval is not checked against the hardware limits. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/oprofile/init.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index 5995e9bc72d9..5e2ab03eaffd 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -151,6 +151,12 @@ static int oprofile_hwsampler_init(struct oprofile_operations *ops) if (oprofile_max_interval == 0) return -ENODEV; + /* The initial value should be sane */ + if (oprofile_hw_interval < oprofile_min_interval) + oprofile_hw_interval = oprofile_min_interval; + if (oprofile_hw_interval > oprofile_max_interval) + oprofile_hw_interval = oprofile_max_interval; + if (oprofile_timer_init(ops)) return -ENODEV; -- cgit v1.2.3 From 6815823431296082fa20c2f14007e194424660b8 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 22 Jun 2011 16:24:09 +0200 Subject: [S390] hwsampler: Set a sane default sampling rate The sampling interval for the hardware sampler is specified in cycles. (see SA23-2260-01 The Load-Program-Parameter and the CPU-Measurement Facilities) The current default value will therefore result in millions of samples. This patch changes the default sampling interval to 4M, which will result in ~1500 samples per second on a z196 reducing the overhead of sampling. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/oprofile/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index 5e2ab03eaffd..0e358c2cffeb 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -25,7 +25,7 @@ extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); #include "hwsampler.h" -#define DEFAULT_INTERVAL 4096 +#define DEFAULT_INTERVAL 4127518 #define DEFAULT_SDBT_BLOCKS 1 #define DEFAULT_SDB_BLOCKS 511 -- cgit v1.2.3 From 859c965149ab5004b58b1fffd98190b6664cb717 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 22 Jun 2011 16:24:10 +0200 Subject: [S390] allow setting of upper 32 bit in smp_ctl_set_bit The bit shift operation in smp_ctl_set_bit does not specify the type of the shifted bit so integer is used as default. Therefore it is not possible to set bits in the upper 32 bit of the control register if the kernel runs in 64 bit mode. Fix this by specifying the type as unsigned long. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 52420d2785b3..1d55c95f617c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -262,7 +262,7 @@ void smp_ctl_set_bit(int cr, int bit) memset(&parms.orvals, 0, sizeof(parms.orvals)); memset(&parms.andvals, 0xff, sizeof(parms.andvals)); - parms.orvals[cr] = 1 << bit; + parms.orvals[cr] = 1UL << bit; on_each_cpu(smp_ctl_bit_callback, &parms, 1); } EXPORT_SYMBOL(smp_ctl_set_bit); @@ -276,7 +276,7 @@ void smp_ctl_clear_bit(int cr, int bit) memset(&parms.orvals, 0, sizeof(parms.orvals)); memset(&parms.andvals, 0xff, sizeof(parms.andvals)); - parms.andvals[cr] = ~(1L << bit); + parms.andvals[cr] = ~(1UL << bit); on_each_cpu(smp_ctl_bit_callback, &parms, 1); } EXPORT_SYMBOL(smp_ctl_clear_bit); -- cgit v1.2.3 From 483f1798998ede75b2575cc1813c3d89ba64a34e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 22 Jun 2011 09:55:01 -0700 Subject: drm/i915: save/resume forcewake lock fixes The lock must be held for the saving and restoring of VGA state. Signed-off-by: Ben Widawsky CC: Alexander Zhaunerchyk CC: Andrey Rahmatullin Reviewed-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_suspend.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 60a94d2b5264..e8152d23d5b6 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -678,6 +678,7 @@ void i915_save_display(struct drm_device *dev) } /* VGA state */ + mutex_lock(&dev->struct_mutex); dev_priv->saveVGA0 = I915_READ(VGA0); dev_priv->saveVGA1 = I915_READ(VGA1); dev_priv->saveVGA_PD = I915_READ(VGA_PD); @@ -687,6 +688,7 @@ void i915_save_display(struct drm_device *dev) dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); i915_save_vga(dev); + mutex_unlock(&dev->struct_mutex); } void i915_restore_display(struct drm_device *dev) @@ -780,6 +782,8 @@ void i915_restore_display(struct drm_device *dev) I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL); else I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); + + mutex_lock(&dev->struct_mutex); I915_WRITE(VGA0, dev_priv->saveVGA0); I915_WRITE(VGA1, dev_priv->saveVGA1); I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); @@ -787,6 +791,7 @@ void i915_restore_display(struct drm_device *dev) udelay(150); i915_restore_vga(dev); + mutex_unlock(&dev->struct_mutex); } int i915_save_state(struct drm_device *dev) -- cgit v1.2.3 From 9935d12651c9e54ad266e17cd542ec717ccd0fc8 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 21 Jun 2011 10:48:31 -0500 Subject: rtl8192cu: Fix missing firmware load In commit 3ac5e26a1e935469a8bdae1d624bc3b59d1fcdc5 entitled "rtlwifi: rtl8192c-common: Change common firmware routines for addition of rtl8192se and rtl8192de", the firmware loading code was moved. Unfortunately, some necessary code was dropped for rtl8192cu. The dmesg output shows the following: rtl8192c: Loading firmware file rtlwifi/rtl8192cufw.bin rtl8192c_common:_rtl92c_fw_free_to_go():<0-0> Polling FW ready fail!! REG_MCUFWDL:0x00000006 . rtl8192c_common:rtl92c_download_fw():<0-0> Firmware is not ready to run! In addition, the interface will authenticate and associate, but cannot transfer data. This is reported as Kernel Bug #38012. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index bee7c1480f63..092e342c19df 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -53,6 +53,8 @@ MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + const struct firmware *firmware; + int err; rtlpriv->dm.dm_initialgain_enable = 1; rtlpriv->dm.dm_flag = 0; @@ -64,6 +66,24 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) ("Can't alloc buffer for fw.\n")); return 1; } + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Failed to request firmware!\n")); + return 1; + } + if (firmware->size > 0x4000) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); + release_firmware(firmware); + return 1; + } + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); + return 0; } -- cgit v1.2.3 From 7cdfa4a348b6b199a3189604f2085f1b214b6458 Mon Sep 17 00:00:00 2001 From: "Marius B. Kotsbak" Date: Wed, 22 Jun 2011 05:26:16 +0000 Subject: net/usb: kalmia: Various fixes for better support of non-x86 architectures. -Support for big endian. -Do not use USB buffers at the stack. -Safer/more efficient code for local constants. Signed-off-by: Marius B. Kotsbak Signed-off-by: David S. Miller --- drivers/net/usb/kalmia.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c index d965fb1e013e..d4edeb2af9be 100644 --- a/drivers/net/usb/kalmia.c +++ b/drivers/net/usb/kalmia.c @@ -100,27 +100,35 @@ kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len, static int kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr) { - char init_msg_1[] = + const static char init_msg_1[] = { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00 }; - char init_msg_2[] = + const static char init_msg_2[] = { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4, 0x00, 0x00 }; - char receive_buf[28]; + const static int buflen = 28; + char *usb_buf; int status; - status = kalmia_send_init_packet(dev, init_msg_1, sizeof(init_msg_1) - / sizeof(init_msg_1[0]), receive_buf, 24); + usb_buf = kmalloc(buflen, GFP_DMA | GFP_KERNEL); + if (!usb_buf) + return -ENOMEM; + + memcpy(usb_buf, init_msg_1, 12); + status = kalmia_send_init_packet(dev, usb_buf, sizeof(init_msg_1) + / sizeof(init_msg_1[0]), usb_buf, 24); if (status != 0) return status; - status = kalmia_send_init_packet(dev, init_msg_2, sizeof(init_msg_2) - / sizeof(init_msg_2[0]), receive_buf, 28); + memcpy(usb_buf, init_msg_2, 12); + status = kalmia_send_init_packet(dev, usb_buf, sizeof(init_msg_2) + / sizeof(init_msg_2[0]), usb_buf, 28); if (status != 0) return status; - memcpy(ethernet_addr, receive_buf + 10, ETH_ALEN); + memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN); + kfree(usb_buf); return status; } @@ -190,7 +198,8 @@ kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) dev_kfree_skb_any(skb); skb = skb2; - done: header_start = skb_push(skb, KALMIA_HEADER_LENGTH); +done: + header_start = skb_push(skb, KALMIA_HEADER_LENGTH); ether_type_1 = header_start[KALMIA_HEADER_LENGTH + 12]; ether_type_2 = header_start[KALMIA_HEADER_LENGTH + 13]; @@ -201,9 +210,8 @@ kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) header_start[0] = 0x57; header_start[1] = 0x44; content_len = skb->len - KALMIA_HEADER_LENGTH; - header_start[2] = (content_len & 0xff); /* low byte */ - header_start[3] = (content_len >> 8); /* high byte */ + put_unaligned_le16(content_len, &header_start[2]); header_start[4] = ether_type_1; header_start[5] = ether_type_2; @@ -231,13 +239,13 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) * Our task here is to strip off framing, leaving skb with one * data frame for the usbnet framework code to process. */ - const u8 HEADER_END_OF_USB_PACKET[] = + const static u8 HEADER_END_OF_USB_PACKET[] = { 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 }; - const u8 EXPECTED_UNKNOWN_HEADER_1[] = + const static u8 EXPECTED_UNKNOWN_HEADER_1[] = { 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 }; - const u8 EXPECTED_UNKNOWN_HEADER_2[] = + const static u8 EXPECTED_UNKNOWN_HEADER_2[] = { 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 }; - u8 i = 0; + int i = 0; /* incomplete header? */ if (skb->len < KALMIA_HEADER_LENGTH) @@ -285,7 +293,7 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* subtract start header and end header */ usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH); - ether_packet_length = header_start[2] + (header_start[3] << 8); + ether_packet_length = get_unaligned_le16(&header_start[2]); skb_pull(skb, KALMIA_HEADER_LENGTH); /* Some small packets misses end marker */ -- cgit v1.2.3 From 446b23a75804d7ffa4cca2d4d8f0afb822108c7e Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Mon, 20 Jun 2011 12:33:16 +0400 Subject: CIFS: Fix problem with 3.0-rc1 null user mount failure Figured it out: it was broken by b946845a9dc523c759cae2b6a0f6827486c3221a commit - "cifs: cifs_parse_mount_options: do not tokenize mount options in-place". So, as a quick fix I suggest to apply this patch. [PATCH] CIFS: Fix kfree() with constant string in a null user case Signed-off-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 12cf72dd0c42..19fdbda7aa95 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2937,7 +2937,11 @@ int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, if (volume_info->nullauth) { cFYI(1, "null user"); - volume_info->username = ""; + volume_info->username = kzalloc(1, GFP_KERNEL); + if (volume_info->username == NULL) { + rc = -ENOMEM; + goto out; + } } else if (volume_info->username) { /* BB fixme parse for domain name here */ cFYI(1, "Username: %s", volume_info->username); -- cgit v1.2.3 From 7553e8f2d5161a2b7a9b7a9f37be1b77e735552f Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Wed, 22 Jun 2011 18:13:01 -0700 Subject: mm, hotplug: fix error handling in mem_online_node() The error handling in mem_online_node() is incorrect: hotadd_new_pgdat() returns NULL if the new pgdat could not have been allocated and a pointer to it otherwise. mem_online_node() should fail if hotadd_new_pgdat() fails, not the inverse. This fixes an issue when memoryless nodes are not onlined and their sysfs interface is not registered when their first cpu is brought up. The bug was introduced by commit cf23422b9d76 ("cpu/mem hotplug: enable CPUs online before local memory online") iow v2.6.35. Signed-off-by: David Rientjes Reviewed-by: KOSAKI Motohiro Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 02159c755136..78dba9f04b5b 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -521,7 +521,7 @@ int mem_online_node(int nid) lock_memory_hotplug(); pgdat = hotadd_new_pgdat(nid, 0); - if (pgdat) { + if (!pgdat) { ret = -ENOMEM; goto out; } -- cgit v1.2.3 From f957db4fcdd8f03e186aa8f041f4049e76ab741c Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Wed, 22 Jun 2011 18:13:04 -0700 Subject: mm, hotplug: protect zonelist building with zonelists_mutex Commit 959ecc48fc75 ("mm/memory_hotplug.c: fix building of node hotplug zonelist") does not protect the build_all_zonelists() call with zonelists_mutex as needed. This can lead to races in constructing zonelist ordering if a concurrent build is underway. Protecting this with lock_memory_hotplug() is insufficient since zonelists can be rebuild though sysfs as well. Signed-off-by: David Rientjes Reviewed-by: KOSAKI Motohiro Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 78dba9f04b5b..c46887b5a11e 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -498,7 +498,9 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) * The node we allocated has no zone fallback lists. For avoiding * to access not-initialized zonelist, build here. */ + mutex_lock(&zonelists_mutex); build_all_zonelists(NULL); + mutex_unlock(&zonelists_mutex); return pgdat; } -- cgit v1.2.3 From d2a19da79d3ea5b7859248b0f132c479ed4505e2 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 22 Jun 2011 09:58:37 +0200 Subject: ALSA: HDA: Pinfix quirk for HP Z200 Workstation BIOS lists the internal speaker as an internal line-out. Change to internal speaker + model=auto for better auto-mute capabilities. BugLink: http://bugs.launchpad.net/bugs/754964 Reported-by: Marc Legris Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 475ed1e8ffc6..d21191dcfe88 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -12599,6 +12599,7 @@ static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = { */ enum { PINFIX_FSC_H270, + PINFIX_HP_Z200, }; static const struct alc_fixup alc262_fixups[] = { @@ -12611,9 +12612,17 @@ static const struct alc_fixup alc262_fixups[] = { { } } }, + [PINFIX_HP_Z200] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x16, 0x99130120 }, /* internal speaker */ + { } + } + }, }; static const struct snd_pci_quirk alc262_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200), SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270), {} }; @@ -12730,6 +12739,8 @@ static const struct snd_pci_quirk alc262_cfg_tbl[] = { ALC262_HP_BPC), SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series", ALC262_HP_BPC), + SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", + ALC262_AUTO), SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series", ALC262_HP_BPC), SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), -- cgit v1.2.3 From 5c18e80be9ff362f6523b097d495bb2e2f939946 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 23 Jun 2011 03:15:39 -0700 Subject: net/usb/kalmia: signedness bug in kalmia_bind() "status" should be an int here for the error handling to work. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/usb/kalmia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c index d4edeb2af9be..a9b6c63d54e4 100644 --- a/drivers/net/usb/kalmia.c +++ b/drivers/net/usb/kalmia.c @@ -135,7 +135,7 @@ kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr) static int kalmia_bind(struct usbnet *dev, struct usb_interface *intf) { - u8 status; + int status; u8 ethernet_addr[ETH_ALEN]; /* Don't bind to AT command interface */ -- cgit v1.2.3 From 0bb04bf3dfdfe1c981087cdfb0d9d772c3a0ba55 Mon Sep 17 00:00:00 2001 From: William Douglas Date: Thu, 23 Jun 2011 13:38:36 +0100 Subject: mrst_max3110: Change max missing message priority. Change print message to notice instead of error to clean up non critical messages showing on startup. The MAX3111 not being present is a normal path for end user systems. Signed-off-by: William Douglas [rebased on 3.0, switched to dev_dbg()] Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/tty/serial/mrst_max3110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 1bd28450ca40..3be1b0dd6f22 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c @@ -823,7 +823,7 @@ static int __devinit serial_m3110_probe(struct spi_device *spi) res = RC_TAG; ret = max3110_write_then_read(max, (u8 *)&res, (u8 *)&res, 2, 0); if (ret < 0 || res == 0 || res == 0xffff) { - printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)", + dev_dbg(&spi->dev, "MAX3111 deemed not present (conf reg %04x)", res); ret = -ENODEV; goto err_get_page; -- cgit v1.2.3 From 33b1e6939f5c37ab8e64280fd3d54046607b5c80 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 23 Jun 2011 13:39:00 +0100 Subject: serial: mrst_max3110: initialize waitqueue earlier The driver went to initialize its waitqueue at the start of the main processing thread. However, it is possible that this thread is not scheduled on a CPU before the write function is called which leads to a following error: BUG: spinlock bad magic on CPU#1, swapper/1 lock: f5f3ebdc, .magic: 00000000, .owner: /-1, .owner_cpu: 0 Pid: 1, comm: swapper Not tainted 3.0.0-rc2+ #67 Call Trace: [] spin_bug+0xa3/0xf0 [] do_raw_spin_lock+0x7d/0x150 [] _raw_spin_lock_irqsave+0x4e/0x60 [] __wake_up+0x1b/0x50 [] serial_m3110_con_write+0x55/0x60 [] __call_console_drivers+0x75/0x90 [] _call_console_drivers+0x49/0x80 [] console_unlock+0xca/0x1f0 [] vprintk+0x18f/0x4f0 [] printk+0x18/0x1a [] register_console+0x2e0/0x350 [] uart_add_one_port+0x33e/0x3d0 [] serial_m3110_probe+0x1c2/0x1df [] spi_drv_probe+0x17/0x20 ... Fix this by initializing the waitqueue before the main thread is created. Signed-off-by: Mika Westerberg Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/tty/serial/mrst_max3110.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 3be1b0dd6f22..a764bf99743b 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c @@ -421,7 +421,6 @@ static int max3110_main_thread(void *_max) int ret = 0; struct circ_buf *xmit = &max->con_xmit; - init_waitqueue_head(wq); pr_info(PR_FMT "start main thread\n"); do { @@ -838,6 +837,8 @@ static int __devinit serial_m3110_probe(struct spi_device *spi) max->con_xmit.head = 0; max->con_xmit.tail = 0; + init_waitqueue_head(&max->wq); + max->main_thread = kthread_run(max3110_main_thread, max, "max3110_main"); if (IS_ERR(max->main_thread)) { -- cgit v1.2.3 From 1b19ca9f0bdab7d5035821e1ec8f39df9a6e3ee0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 22 Jun 2011 11:55:50 +0100 Subject: Fix CPU spinlock lockups on secondary CPU bringup Secondary CPU bringup typically calls calibrate_delay() during its initialization. However, calibrate_delay() modifies a global variable (loops_per_jiffy) used for udelay() and __delay(). A side effect of 71c696b1 ("calibrate: extract fall-back calculation into own helper") introduced in the 2.6.39 merge window means that we end up with a substantial period where loops_per_jiffy is zero. This causes the spinlock debugging code to malfunction: u64 loops = loops_per_jiffy * HZ; for (;;) { for (i = 0; i < loops; i++) { if (arch_spin_trylock(&lock->raw_lock)) return; __delay(1); } ... } by never calling arch_spin_trylock() - resulting in the CPU locking up in an infinite loop inside __spin_lock_debug(). Work around this by only writing to loops_per_jiffy only once we have completed all the calibration decisions. Tested-by: Santosh Shilimkar Signed-off-by: Russell King Cc: (2.6.39-stable) -- Better solutions (such as omitting the calibration for secondary CPUs, or arranging for calibrate_delay() to return the LPJ value and leave it to the caller to decide where to store it) are a possibility, but would be much more invasive into each architecture. I think this is the best solution for -rc and stable, but it should be revisited for the next merge window. init/calibrate.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-) Signed-off-by: Linus Torvalds --- init/calibrate.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/init/calibrate.c b/init/calibrate.c index 2568d22a304e..aae2f40fea4c 100644 --- a/init/calibrate.c +++ b/init/calibrate.c @@ -245,30 +245,32 @@ recalibrate: void __cpuinit calibrate_delay(void) { + unsigned long lpj; static bool printed; if (preset_lpj) { - loops_per_jiffy = preset_lpj; + lpj = preset_lpj; if (!printed) pr_info("Calibrating delay loop (skipped) " "preset value.. "); } else if ((!printed) && lpj_fine) { - loops_per_jiffy = lpj_fine; + lpj = lpj_fine; pr_info("Calibrating delay loop (skipped), " "value calculated using timer frequency.. "); - } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) { + } else if ((lpj = calibrate_delay_direct()) != 0) { if (!printed) pr_info("Calibrating delay using timer " "specific routine.. "); } else { if (!printed) pr_info("Calibrating delay loop... "); - loops_per_jiffy = calibrate_delay_converge(); + lpj = calibrate_delay_converge(); } if (!printed) pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", - loops_per_jiffy/(500000/HZ), - (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy); + lpj/(500000/HZ), + (lpj/(5000/HZ)) % 100, lpj); + loops_per_jiffy = lpj; printed = true; } -- cgit v1.2.3 From 1190f6a067bf27b2ee7e06ec0776a17fe0f6c4d8 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 22 Jun 2011 17:33:57 -0400 Subject: cifs: fix wsize negotiation to respect max buffer size and active signing (try #4) Hopefully last version. Base signing check on CAP_UNIX instead of tcon->unix_ext, also clean up the comments a bit more. According to Hongwei Sun's blog posting here: http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx CAP_LARGE_WRITEX is ignored when signing is active. Also, the maximum size for a write without CAP_LARGE_WRITEX should be the maxBuf that the server sent in the NEGOTIATE request. Fix the wsize negotiation to take this into account. While we're at it, alter the other wsize definitions to use sizeof(WRITE_REQ) to allow for slightly larger amounts of data to potentially be written per request. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 19fdbda7aa95..c761935eab8c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2750,21 +2750,21 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, /* * When the server supports very large writes via POSIX extensions, we can - * allow up to 2^24 - PAGE_CACHE_SIZE. + * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including + * the RFC1001 length. * * Note that this might make for "interesting" allocation problems during - * writeback however (as we have to allocate an array of pointers for the - * pages). A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096. + * writeback however as we have to allocate an array of pointers for the + * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096. */ -#define CIFS_MAX_WSIZE ((1<<24) - PAGE_CACHE_SIZE) +#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4) /* - * When the server doesn't allow large posix writes, default to a wsize of - * 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size - * described in RFC1001. This allows space for the header without going over - * that by default. + * When the server doesn't allow large posix writes, only allow a wsize of + * 128k minus the size of the WRITE_AND_X header. That allows for a write up + * to the maximum size described by RFC1002. */ -#define CIFS_MAX_RFC1001_WSIZE (128 * 1024 - PAGE_CACHE_SIZE) +#define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4) /* * The default wsize is 1M. find_get_pages seems to return a maximum of 256 @@ -2783,11 +2783,18 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) /* can server support 24-bit write sizes? (via UNIX extensions) */ if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) - wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1001_WSIZE); + wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE); - /* no CAP_LARGE_WRITE_X? Limit it to 16 bits */ - if (!(server->capabilities & CAP_LARGE_WRITE_X)) - wsize = min_t(unsigned int, wsize, USHRT_MAX); + /* + * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set? + * Limit it to max buffer offered by the server, minus the size of the + * WRITEX header, not including the 4 byte RFC1001 length. + */ + if (!(server->capabilities & CAP_LARGE_WRITE_X) || + (!(server->capabilities & CAP_UNIX) && + (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)))) + wsize = min_t(unsigned int, wsize, + server->maxBuf - sizeof(WRITE_REQ) + 4); /* hard limit of CIFS_MAX_WSIZE */ wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); -- cgit v1.2.3 From f6d96e0da1ee3cfe67b719570fba3bb2ea057131 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard (Rtp)" Date: Wed, 22 Jun 2011 22:21:48 +0200 Subject: ASoC: imx: Remove unused Kconfig SND_MXC_SOC_SSI entry SND_MXC_SOC_SSI looks to be unused, so kill it. Signed-off-by: Arnaud Patard Acked-by: Sascha Hauer Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/imx/Kconfig | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index d8f130d39dd9..bb699bb55a50 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -11,9 +11,6 @@ menuconfig SND_IMX_SOC if SND_IMX_SOC -config SND_MXC_SOC_SSI - tristate - config SND_MXC_SOC_FIQ tristate @@ -24,7 +21,6 @@ config SND_MXC_SOC_WM1133_EV1 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL select SND_SOC_WM8350 - select SND_MXC_SOC_SSI select SND_MXC_SOC_FIQ help Enable support for audio on the i.MX31ADS with the WM1133-EV1 @@ -34,7 +30,6 @@ config SND_SOC_MX27VIS_AIC32X4 tristate "SoC audio support for Visstrim M10 boards" depends on MACH_IMX27_VISSTRIM_M10 select SND_SOC_TVL320AIC32X4 - select SND_MXC_SOC_SSI select SND_MXC_SOC_MX2 help Say Y if you want to add support for SoC audio on Visstrim SM10 @@ -44,7 +39,6 @@ config SND_SOC_PHYCORE_AC97 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" depends on MACH_PCM043 || MACH_PCA100 select SND_SOC_WM9712 - select SND_MXC_SOC_SSI select SND_MXC_SOC_FIQ help Say Y if you want to add support for SoC audio on Phytec phyCORE @@ -57,7 +51,6 @@ config SND_SOC_EUKREA_TLV320 || MACH_EUKREA_MBIMXSD35_BASEBOARD \ || MACH_EUKREA_MBIMXSD51_BASEBOARD select SND_SOC_TLV320AIC23 - select SND_MXC_SOC_SSI select SND_MXC_SOC_FIQ help Enable I2S based access to the TLV320AIC23B codec attached -- cgit v1.2.3 From 96dcabb99b9f63f2b65f2b0bfe5d4eb48f11b177 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard (Rtp)" Date: Wed, 22 Jun 2011 22:21:49 +0200 Subject: ASoC: imx: add missing module informations - add some modules aliases - add module license to avoid tainted kernel when loading the imx-pcm-audio driver Signed-off-by: Arnaud Patard Acked-by: Sascha Hauer Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/imx/imx-pcm-dma-mx2.c | 2 ++ sound/soc/imx/imx-ssi.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index aab7765f401a..4173b3d87f97 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -337,3 +337,5 @@ static void __exit snd_imx_pcm_exit(void) platform_driver_unregister(&imx_pcm_driver); } module_exit(snd_imx_pcm_exit); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:imx-pcm-audio"); diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 5b13feca7537..61fceb09cdb5 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -774,4 +774,4 @@ module_exit(imx_ssi_exit); MODULE_AUTHOR("Sascha Hauer, "); MODULE_DESCRIPTION("i.MX I2S/ac97 SoC Interface"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS("platform:imx-ssi"); -- cgit v1.2.3 From 53dea36c70c1857149a8c447224e3936eb8b5339 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 22 Jun 2011 20:48:25 +0200 Subject: ASoC: pxa-ssp: Correct check for stream presence Don't rely on the codec's channels_min information to decide wheter or not allocate a substream's DMA buffer. Rather check if the substream itself was allocated previously. Signed-off-by: Daniel Mack Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/pxa/pxa2xx-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index 2ce0b2d891d5..fab20a54e863 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -95,14 +95,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (dai->driver->playback.channels_min) { + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->driver->capture.channels_min) { + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) -- cgit v1.2.3 From 8618ccd352dcd01628f39eb1fca4f9a7bc077ea1 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Wed, 22 Jun 2011 23:29:20 -0700 Subject: drivers/ata/sata_dwc_460ex: Fix typo 'corrresponding' The patch below fixes a typo. Signed-off-by: Justin P. Mattock Signed-off-by: Jeff Garzik --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 1c4b3aa4c7c4..dc88a39e7db8 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -389,7 +389,7 @@ static void sata_dwc_tf_dump(struct ata_taskfile *tf) /* * Function: get_burst_length_encode * arguments: datalength: length in bytes of data - * returns value to be programmed in register corrresponding to data length + * returns value to be programmed in register corresponding to data length * This value is effectively the log(base 2) of the length */ static int get_burst_length_encode(int datalength) -- cgit v1.2.3 From cd691876d73e24b4c0a2e96993251abbe3a320df Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Jun 2011 12:13:10 +0200 Subject: libata: apply NOSETXFER horkage to the affected Pioneer drives regardless of firmware revision It's unlikely NOSETXFER works for a revision of drive but doesn't for another and pioneer doesn't seem to be fixing firmwares for the affected drives. Apply NOSETXFER to the affected pioneer drives regardless of firmware revision. http://article.gmane.org/gmane.linux.ide/49734 Signed-off-by: Tejun Heo Reported-by: fl-00@gmx.de Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 736bee5dafeb..000d03ae6653 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4143,9 +4143,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { * Devices which choke on SETXFER. Applies only if both the * device and controller are SATA. */ - { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, - { "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER }, - { "PIONEER DVD-RW DVR-216D", "1.08", ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVRTD08", NULL, ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVR-212D", NULL, ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER }, /* End Marker */ { } -- cgit v1.2.3 From 3f1e046ad3370d22d39529103667354eb50abc08 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Thu, 16 Jun 2011 08:28:36 -0700 Subject: libata/sas: only set FROZEN flag if new EH is supported On 16.06.2011 [08:28:39 -0500], Brian King wrote: > On 06/16/2011 02:51 AM, Tejun Heo wrote: > > On Wed, Jun 15, 2011 at 04:34:17PM -0700, Nishanth Aravamudan wrote: > >>> That looks like the right thing to do. For ipr's usage of > >>> libata, we don't have the concept of a port frozen state, so this flag > >>> should really never get set. The alternate way to fix this would be to > >>> only set ATA_PFLAG_FROZEN in ata_port_alloc if ap->ops->error_handler > >>> is not NULL. > >> > >> It seemed like ipr is as you say, but I wasn't sure if it was > >> appropriate to make the change above in the common libata-scis code or > >> not. I don't want to break some other device on accident. > >> > >> Also, I tried your suggestion, but I don't think that can happen in > >> ata_port_alloc? ata_port_alloc is allocated ap itself, and it seems like > >> ap->ops typically gets set only after ata_port_alloc returns? > > > > Maybe we can test error_handler in ata_sas_port_start()? > > Good point. Since libsas is converted to the new eh now, we would need to have > this test. Commit 7b3a24c57d2eeda8dba9c205342b12689c4679f9 ("ahci: don't enable port irq before handler is registered") caused a regression for CD-ROMs attached to the IPR SATA bus on Power machines: ata_port_alloc: ENTER ata_port_probe: ata1: bus probe begin ata1.00: ata_dev_read_id: ENTER ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40) ata1.00: ata_dev_read_id: ENTER ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40) ata1.00: limiting speed to UDMA7:PIO5 ata1.00: ata_dev_read_id: ENTER ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40) ata1.00: disabled ata_port_probe: ata1: bus probe end scsi_alloc_sdev: Allocation failure during SCSI scanning, some SCSI devices might not be configured The FROZEN flag added in that commit is only cleared by the new EH code, which is not used by ipr. Clear this flag in the SAS code if we don't support new EH. Reported-by: Benjamin Herrenschmidt Signed-off-by: Nishanth Aravamudan Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index d51f9795c064..927f968e99d9 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3797,6 +3797,12 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc); */ int ata_sas_port_start(struct ata_port *ap) { + /* + * the port is marked as frozen at allocation time, but if we don't + * have new eh, we won't thaw it + */ + if (!ap->ops->error_handler) + ap->pflags &= ~ATA_PFLAG_FROZEN; return 0; } EXPORT_SYMBOL_GPL(ata_sas_port_start); -- cgit v1.2.3 From 03ad2d501e7189245bf6bf9dfc2a30511dd50602 Mon Sep 17 00:00:00 2001 From: Alexey Charkov Date: Wed, 22 Jun 2011 23:20:13 +0200 Subject: rtc: vt8500: Fix build error & cleanup rtc_class_ops->update_irq_enable() Now that the generic code handles UIE mode irqs via periodic alarm interrupts, no one calls the rtc_class_ops->update_irq_enable() method anymore. Further the rtc_class_ops doesn't have a update_irq_enable element anymore, so this causes a build error. This patch removes the driver hooks and implementations of update_irq_enable and the associated setup. [wsa: updated commit-message and removed update_irq_enable-function, too] [jstultz: improve commit message, clarifying build issue] Signed-off-by: Alexey Charkov Signed-off-by: Wolfram Sang Signed-off-by: John Stultz --- drivers/rtc/rtc-vt8500.c | 45 +++------------------------------------------ 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index b8bc862903ae..efd6066b5cd2 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -78,7 +78,6 @@ struct vt8500_rtc { void __iomem *regbase; struct resource *res; int irq_alarm; - int irq_hz; struct rtc_device *rtc; spinlock_t lock; /* Protects this structure */ }; @@ -100,10 +99,6 @@ static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id) if (isr & 1) events |= RTC_AF | RTC_IRQF; - /* Only second/minute interrupts are supported */ - if (isr & 2) - events |= RTC_UF | RTC_IRQF; - rtc_update_irq(vt8500_rtc->rtc, 1, events); return IRQ_HANDLED; @@ -199,27 +194,12 @@ static int vt8500_alarm_irq_enable(struct device *dev, unsigned int enabled) return 0; } -static int vt8500_update_irq_enable(struct device *dev, unsigned int enabled) -{ - struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); - unsigned long tmp = readl(vt8500_rtc->regbase + VT8500_RTC_CR); - - if (enabled) - tmp |= VT8500_RTC_CR_SM_SEC | VT8500_RTC_CR_SM_ENABLE; - else - tmp &= ~VT8500_RTC_CR_SM_ENABLE; - - writel(tmp, vt8500_rtc->regbase + VT8500_RTC_CR); - return 0; -} - static const struct rtc_class_ops vt8500_rtc_ops = { .read_time = vt8500_rtc_read_time, .set_time = vt8500_rtc_set_time, .read_alarm = vt8500_rtc_read_alarm, .set_alarm = vt8500_rtc_set_alarm, .alarm_irq_enable = vt8500_alarm_irq_enable, - .update_irq_enable = vt8500_update_irq_enable, }; static int __devinit vt8500_rtc_probe(struct platform_device *pdev) @@ -248,13 +228,6 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) goto err_free; } - vt8500_rtc->irq_hz = platform_get_irq(pdev, 1); - if (vt8500_rtc->irq_hz < 0) { - dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n"); - ret = -ENXIO; - goto err_free; - } - vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start, resource_size(vt8500_rtc->res), "vt8500-rtc"); @@ -272,9 +245,8 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) goto err_release; } - /* Enable the second/minute interrupt generation and enable RTC */ - writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H - | VT8500_RTC_CR_SM_ENABLE | VT8500_RTC_CR_SM_SEC, + /* Enable RTC and set it to 24-hour mode */ + writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H, vt8500_rtc->regbase + VT8500_RTC_CR); vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, @@ -286,26 +258,16 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) goto err_unmap; } - ret = request_irq(vt8500_rtc->irq_hz, vt8500_rtc_irq, 0, - "rtc 1Hz", vt8500_rtc); - if (ret < 0) { - dev_err(&pdev->dev, "can't get irq %i, err %d\n", - vt8500_rtc->irq_hz, ret); - goto err_unreg; - } - ret = request_irq(vt8500_rtc->irq_alarm, vt8500_rtc_irq, 0, "rtc alarm", vt8500_rtc); if (ret < 0) { dev_err(&pdev->dev, "can't get irq %i, err %d\n", vt8500_rtc->irq_alarm, ret); - goto err_free_hz; + goto err_unreg; } return 0; -err_free_hz: - free_irq(vt8500_rtc->irq_hz, vt8500_rtc); err_unreg: rtc_device_unregister(vt8500_rtc->rtc); err_unmap: @@ -323,7 +285,6 @@ static int __devexit vt8500_rtc_remove(struct platform_device *pdev) struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev); free_irq(vt8500_rtc->irq_alarm, vt8500_rtc); - free_irq(vt8500_rtc->irq_hz, vt8500_rtc); rtc_device_unregister(vt8500_rtc->rtc); -- cgit v1.2.3 From 7fd29aa920273b70be50c14c4b7e2213fb6623ce Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 23 Jun 2011 23:48:32 +0000 Subject: target: Fix transport_get_lun_for_tmr failure cases This patch fixes two possible NULL pointer dereferences in target v4.0 code where se_tmr release path in core_tmr_release_req() can OOPs upon transport_get_lun_for_tmr() failure by attempting to access se_device or se_tmr->tmr_list without a valid member of se_device->tmr_list during transport_free_se_cmd() release. This patch moves the se_tmr->tmr_dev pointer assignment in transport_get_lun_for_tmr() until after possible -ENODEV failures during unpacked_lun lookup. This addresses an OOPs originally reported with LIO v4.1 upstream on .39 code here: TARGET_CORE[qla2xxx]: Detected NON_EXISTENT_LUN Access for 0x00000000 BUG: unable to handle kernel NULL pointer dereference at 0000000000000550 IP: [] __ticket_spin_trylock+0x4/0x20 PGD 0 Oops: 0000 [#1] SMP last sysfs file: /sys/devices/system/cpu/cpu23/cache/index2/shared_cpu_map CPU 1 Modules linked in: netconsole target_core_pscsi target_core_file tcm_qla2xxx target_core_iblock tcm_loop target_core_mod configfs ipmi_devintf ipmi_si ipmi_msghandler serio_raw i7core_edac ioatdma dca edac_core ps_bdrv ses enclosure usbhid usb_storage ahci qla2xxx hid uas e1000e mpt2sas libahci mlx4_core scsi_transport_fc scsi_transport_sas raid_class scsi_tgt [last unloaded: netconsole] Pid: 0, comm: kworker/0:0 Tainted: G W 2.6.39+ #1 Xyratex Storage Server RIP: 0010:[] []__ticket_spin_trylock+0x4/0x20 RSP: 0018:ffff88063e803c08 EFLAGS: 00010286 RAX: ffff880619ab45e0 RBX: 0000000000000550 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000550 RBP: ffff88063e803c08 R08: 0000000000000002 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000568 R13: 0000000000000001 R14: 0000000000000000 R15: ffff88060cd96a20 FS: 0000000000000000(0000) GS:ffff88063e800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000550 CR3: 0000000001a03000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process kworker/0:0 (pid: 0, threadinfo ffff880619ab8000, task ffff880619ab45e0) Stack: ffff88063e803c28 ffffffff812cf039 0000000000000550 0000000000000568 ffff88063e803c58 ffffffff8157071e ffffffffa028a1dc ffff88060f7e4600 0000000000000550 ffff880616961480 ffff88063e803c78 ffffffffa028a1dc Call Trace: [] do_raw_spin_trylock+0x19/0x50 [] _raw_spin_lock+0x3e/0x70 [] ? core_tmr_release_req+0x2c/0x60 [target_core_mod] [] core_tmr_release_req+0x2c/0x60 [target_core_mod] [] transport_free_se_cmd+0x22/0x50 [target_core_mod] [] transport_release_cmd_to_pool+0x20/0x40 [target_core_mod] [] transport_generic_free_cmd+0xa5/0xb0 [target_core_mod] [] tcm_qla2xxx_handle_tmr+0xc4/0xd0 [tcm_qla2xxx] [] __qla24xx_handle_abts+0xd3/0x150 [qla2xxx] [] qla_tgt_response_pkt+0x171/0x520 [qla2xxx] [] qla_tgt_response_pkt_all_vps+0x2d/0x220 [qla2xxx] [] qla24xx_process_response_queue+0x1a3/0x670 [qla2xxx] [] ? qla24xx_atio_pkt+0x81/0x120 [qla2xxx] [] ? qla24xx_msix_default+0x45/0x2a0 [qla2xxx] [] qla24xx_msix_default+0x1b8/0x2a0 [qla2xxx] [] handle_irq_event_percpu+0x54/0x210 [] handle_irq_event+0x48/0x70 [] ? handle_edge_irq+0x1e/0x110 [] handle_edge_irq+0x77/0x110 [] handle_irq+0x22/0x40 [] do_IRQ+0x5d/0xe0 [] common_interrupt+0x13/0x13 [] ? intel_idle+0xd7/0x130 [] ? intel_idle+0xd0/0x130 [] cpuidle_idle_call+0xab/0x1c0 [] cpu_idle+0xab/0xf0 [] start_secondary+0x1cb/0x1d2 Reported-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 3 ++- drivers/target/target_core_tmr.c | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 8407f9ca2b31..f8d8af7a0d41 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -192,7 +192,7 @@ int transport_get_lun_for_tmr( &SE_NODE_ACL(se_sess)->device_list[unpacked_lun]; if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) { se_lun = se_cmd->se_lun = se_tmr->tmr_lun = deve->se_lun; - dev = se_tmr->tmr_dev = se_lun->lun_se_dev; + dev = se_lun->lun_se_dev; se_cmd->pr_res_key = deve->pr_res_key; se_cmd->orig_fe_lun = unpacked_lun; se_cmd->se_orig_obj_ptr = SE_LUN(se_cmd)->lun_se_dev; @@ -216,6 +216,7 @@ int transport_get_lun_for_tmr( se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return -1; } + se_tmr->tmr_dev = dev; spin_lock(&dev->se_tmr_lock); list_add_tail(&se_tmr->tmr_list, &dev->dev_tmr_list); diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 59b8b9c5ad72..179063d81cdd 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -75,10 +75,16 @@ void core_tmr_release_req( { struct se_device *dev = tmr->tmr_dev; + if (!dev) { + kmem_cache_free(se_tmr_req_cache, tmr); + return; + } + spin_lock(&dev->se_tmr_lock); list_del(&tmr->tmr_list); - kmem_cache_free(se_tmr_req_cache, tmr); spin_unlock(&dev->se_tmr_lock); + + kmem_cache_free(se_tmr_req_cache, tmr); } static void core_tmr_handle_tas_abort( -- cgit v1.2.3 From 233888644d80cc44330062e5e978c9e3a14c9cb9 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 22 Jun 2011 01:02:21 -0700 Subject: target: Convert transport_deregister_session_configfs nacl_sess_lock to save irq state This patch converts transport_deregister_session_configfs() to save/restore spinlock IRQ state for struct se_node_acl->nacl_sess_lock access as tcm_qla2xxx logic expects to call transport_deregister_session_configfs() code with irq save already held for struct qla_hw_data. Reported-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4dafeb8b5638..4b9b7169bdd9 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -536,13 +536,13 @@ EXPORT_SYMBOL(transport_register_session); void transport_deregister_session_configfs(struct se_session *se_sess) { struct se_node_acl *se_nacl; - + unsigned long flags; /* * Used by struct se_node_acl's under ConfigFS to locate active struct se_session */ se_nacl = se_sess->se_node_acl; if ((se_nacl)) { - spin_lock_irq(&se_nacl->nacl_sess_lock); + spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags); list_del(&se_sess->sess_acl_list); /* * If the session list is empty, then clear the pointer. @@ -556,7 +556,7 @@ void transport_deregister_session_configfs(struct se_session *se_sess) se_nacl->acl_sess_list.prev, struct se_session, sess_acl_list); } - spin_unlock_irq(&se_nacl->nacl_sess_lock); + spin_unlock_irqrestore(&se_nacl->nacl_sess_lock, flags); } } EXPORT_SYMBOL(transport_deregister_session_configfs); -- cgit v1.2.3 From 552523dcbf0f33d44d816da310be8227a2c1502a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 15 Jun 2011 09:41:33 -0700 Subject: target: Fix ERR_PTR dereferencing bugs transport_init_session() and core_tmr_alloc_req() never return NULL, they only return ERR_PTRs on error. v2: Fix patch to return PTR_ERR(tl_nexus->se_sess) from Ankit Jain's feedback. Signed-off-by: Dan Carpenter Signed-off-by: Ankit Jain Signed-off-by: Nicholas Bellinger --- drivers/target/loopback/tcm_loop.c | 9 ++++++--- drivers/target/tcm_fc/tfc_sess.c | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index dee2a2c909f5..d4fee2a9d66a 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -386,7 +386,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) */ se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, (void *)tl_tmr, TMR_LUN_RESET); - if (!se_cmd->se_tmr_req) + if (IS_ERR(se_cmd->se_tmr_req)) goto release; /* * Locate the underlying TCM struct se_lun from sc->device->lun @@ -1017,6 +1017,7 @@ static int tcm_loop_make_nexus( struct se_portal_group *se_tpg; struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba; struct tcm_loop_nexus *tl_nexus; + int ret = -ENOMEM; if (tl_tpg->tl_hba->tl_nexus) { printk(KERN_INFO "tl_tpg->tl_hba->tl_nexus already exists\n"); @@ -1033,8 +1034,10 @@ static int tcm_loop_make_nexus( * Initialize the struct se_session pointer */ tl_nexus->se_sess = transport_init_session(); - if (!tl_nexus->se_sess) + if (IS_ERR(tl_nexus->se_sess)) { + ret = PTR_ERR(tl_nexus->se_sess); goto out; + } /* * Since we are running in 'demo mode' this call with generate a * struct se_node_acl for the tcm_loop struct se_portal_group with the SCSI @@ -1060,7 +1063,7 @@ static int tcm_loop_make_nexus( out: kfree(tl_nexus); - return -ENOMEM; + return ret; } static int tcm_loop_drop_nexus( diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index a3bd57f2ea32..03744c23095c 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -229,7 +229,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, return NULL; sess->se_sess = transport_init_session(); - if (!sess->se_sess) { + if (IS_ERR(sess->se_sess)) { kfree(sess); return NULL; } -- cgit v1.2.3 From 5eff5be0b1993f4291f2b8c6d035b408010f96c5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 13 Jun 2011 23:10:49 +0300 Subject: target: Drop bogus ERR_PTR usage in target_fabric_configfs_init In the original code, there were several places inside the target_fabric_configfs_init() function that returned NULL on error and one place the returned an ERR_PTR. There are two places that call this function and they only check for NULL returns; they don't check for ERR_PTRs. So I've changed the ERR_PTR so now the function only returns NULL on error. Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index ee6fad979b50..b17abd13c8e3 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -312,7 +312,7 @@ struct target_fabric_configfs *target_fabric_configfs_init( tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL); if (!(tf)) - return ERR_PTR(-ENOMEM); + return NULL; INIT_LIST_HEAD(&tf->tf_list); atomic_set(&tf->tf_access_cnt, 0); -- cgit v1.2.3 From 60d645a4e9e7e7ddc20e534fea82aa4e6947f911 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 15 Jun 2011 10:03:05 -0700 Subject: target: Fix incorrect strlen() NULL terminator checks This patch fixes a number of cases in target core using an incorrectly if (strlen(foo) > SOME_MAX_SIZE) As strlen() returns the number of characters in the string not counting the NULL character at the end. So if you do something like: char buf[10]; if (strlen("0123456789") > 10) return -ETOOLONG; snprintf(buf, 10, "0123456789"); printf("%s\n", buf); then the last "9" gets chopped off and only "012345678" is printed. Plus I threw in one small related cleanup. Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/loopback/tcm_loop.c | 4 ++-- drivers/target/target_core_configfs.c | 22 +++++++++++----------- drivers/target/target_core_device.c | 2 +- drivers/target/target_core_pr.c | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index d4fee2a9d66a..70c2e7fa6664 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -1143,7 +1143,7 @@ static ssize_t tcm_loop_tpg_store_nexus( * the fabric protocol_id set in tcm_loop_make_scsi_hba(), and call * tcm_loop_make_nexus() */ - if (strlen(page) > TL_WWN_ADDR_LEN) { + if (strlen(page) >= TL_WWN_ADDR_LEN) { printk(KERN_ERR "Emulated NAA Sas Address: %s, exceeds" " max: %d\n", page, TL_WWN_ADDR_LEN); return -EINVAL; @@ -1324,7 +1324,7 @@ struct se_wwn *tcm_loop_make_scsi_hba( return ERR_PTR(-EINVAL); check_len: - if (strlen(name) > TL_WWN_ADDR_LEN) { + if (strlen(name) >= TL_WWN_ADDR_LEN) { printk(KERN_ERR "Emulated NAA %s Address: %s, exceeds" " max: %d\n", name, tcm_loop_dump_proto_id(tl_hba), TL_WWN_ADDR_LEN); diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index b17abd13c8e3..25c1f49a7d8b 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -304,7 +304,7 @@ struct target_fabric_configfs *target_fabric_configfs_init( printk(KERN_ERR "Unable to locate passed fabric name\n"); return NULL; } - if (strlen(name) > TARGET_FABRIC_NAME_SIZE) { + if (strlen(name) >= TARGET_FABRIC_NAME_SIZE) { printk(KERN_ERR "Passed name: %s exceeds TARGET_FABRIC" "_NAME_SIZE\n", name); return NULL; @@ -851,7 +851,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( return -EOPNOTSUPP; } - if ((strlen(page) + 1) > INQUIRY_VPD_SERIAL_LEN) { + if (strlen(page) >= INQUIRY_VPD_SERIAL_LEN) { printk(KERN_ERR "Emulated VPD Unit Serial exceeds" " INQUIRY_VPD_SERIAL_LEN: %d\n", INQUIRY_VPD_SERIAL_LEN); return -EOVERFLOW; @@ -917,7 +917,7 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier( transport_dump_vpd_proto_id(vpd, buf, VPD_TMP_BUF_SIZE); - if ((len + strlen(buf) > PAGE_SIZE)) + if ((len + strlen(buf) >= PAGE_SIZE)) break; len += sprintf(page+len, "%s", buf); @@ -962,19 +962,19 @@ static ssize_t target_core_dev_wwn_show_attr_##_name( \ \ memset(buf, 0, VPD_TMP_BUF_SIZE); \ transport_dump_vpd_assoc(vpd, buf, VPD_TMP_BUF_SIZE); \ - if ((len + strlen(buf) > PAGE_SIZE)) \ + if ((len + strlen(buf) >= PAGE_SIZE)) \ break; \ len += sprintf(page+len, "%s", buf); \ \ memset(buf, 0, VPD_TMP_BUF_SIZE); \ transport_dump_vpd_ident_type(vpd, buf, VPD_TMP_BUF_SIZE); \ - if ((len + strlen(buf) > PAGE_SIZE)) \ + if ((len + strlen(buf) >= PAGE_SIZE)) \ break; \ len += sprintf(page+len, "%s", buf); \ \ memset(buf, 0, VPD_TMP_BUF_SIZE); \ transport_dump_vpd_ident(vpd, buf, VPD_TMP_BUF_SIZE); \ - if ((len + strlen(buf) > PAGE_SIZE)) \ + if ((len + strlen(buf) >= PAGE_SIZE)) \ break; \ len += sprintf(page+len, "%s", buf); \ } \ @@ -1299,7 +1299,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( &i_buf[0] : "", pr_reg->pr_res_key, pr_reg->pr_res_generation); - if ((len + strlen(buf) > PAGE_SIZE)) + if ((len + strlen(buf) >= PAGE_SIZE)) break; len += sprintf(page+len, "%s", buf); @@ -1496,7 +1496,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( ret = -ENOMEM; goto out; } - if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) { + if (strlen(i_port) >= PR_APTPL_MAX_IPORT_LEN) { printk(KERN_ERR "APTPL metadata initiator_node=" " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n", PR_APTPL_MAX_IPORT_LEN); @@ -1510,7 +1510,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( ret = -ENOMEM; goto out; } - if (strlen(isid) > PR_REG_ISID_LEN) { + if (strlen(isid) >= PR_REG_ISID_LEN) { printk(KERN_ERR "APTPL metadata initiator_isid" "= exceeds PR_REG_ISID_LEN: %d\n", PR_REG_ISID_LEN); @@ -1571,7 +1571,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( ret = -ENOMEM; goto out; } - if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) { + if (strlen(t_port) >= PR_APTPL_MAX_TPORT_LEN) { printk(KERN_ERR "APTPL metadata target_node=" " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n", PR_APTPL_MAX_TPORT_LEN); @@ -3052,7 +3052,7 @@ static struct config_group *target_core_call_addhbatotarget( int ret; memset(buf, 0, TARGET_CORE_NAME_MAX_LEN); - if (strlen(name) > TARGET_CORE_NAME_MAX_LEN) { + if (strlen(name) >= TARGET_CORE_NAME_MAX_LEN) { printk(KERN_ERR "Passed *name strlen(): %d exceeds" " TARGET_CORE_NAME_MAX_LEN: %d\n", (int)strlen(name), TARGET_CORE_NAME_MAX_LEN); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index f8d8af7a0d41..ba698ea62bb2 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1431,7 +1431,7 @@ struct se_lun_acl *core_dev_init_initiator_node_lun_acl( struct se_lun_acl *lacl; struct se_node_acl *nacl; - if (strlen(initiatorname) > TRANSPORT_IQN_LEN) { + if (strlen(initiatorname) >= TRANSPORT_IQN_LEN) { printk(KERN_ERR "%s InitiatorName exceeds maximum size.\n", TPG_TFO(tpg)->get_fabric_name()); *ret = -EOVERFLOW; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index a79f518ca6e2..b662db3a320b 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1916,7 +1916,7 @@ static int __core_scsi3_update_aptpl_buf( pr_reg->pr_res_mapped_lun); } - if ((len + strlen(tmp) > pr_aptpl_buf_len)) { + if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { printk(KERN_ERR "Unable to update renaming" " APTPL metadata\n"); spin_unlock(&T10_RES(su_dev)->registration_lock); @@ -1934,7 +1934,7 @@ static int __core_scsi3_update_aptpl_buf( TPG_TFO(tpg)->tpg_get_tag(tpg), lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count); - if ((len + strlen(tmp) > pr_aptpl_buf_len)) { + if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { printk(KERN_ERR "Unable to update renaming" " APTPL metadata\n"); spin_unlock(&T10_RES(su_dev)->registration_lock); @@ -1986,7 +1986,7 @@ static int __core_scsi3_write_aptpl_to_file( memset(iov, 0, sizeof(struct iovec)); memset(path, 0, 512); - if (strlen(&wwn->unit_serial[0]) > 512) { + if (strlen(&wwn->unit_serial[0]) >= 512) { printk(KERN_ERR "WWN value for struct se_device does not fit" " into path buffer\n"); return -1; -- cgit v1.2.3 From 61db952713a8bc1b18515db3f2eac354ec8990bd Mon Sep 17 00:00:00 2001 From: Kiran Patil Date: Wed, 22 Jun 2011 16:30:22 -0700 Subject: tcm_fc: Fix ft_send_tm LUN lookup OOPs This patch fixes a bug in ft_send_tm() that was incorrectly calling ft_get_lun_for_cmd() -> transport_get_lun_for_cmd(), instead of using transport_get_lun_for_tmr() for the proper struct se_lun lookup that was triggering an OOPs in the se_cmd->tmr_req failure path. This patch fixes the issue by re-arranging the codepath where transport_get_lun_for_tmr() is called after tmr request is allocated and made it available as part of se_cmd. It also drops the now unnecessary ft_get_lun_for_cmd() unpacking code, and uses scsilun_to_int() directly ahead of transport_get_lun_for_cmd() and transport_get_lun_for_tmr() usage. Signed-off-by: Patil, Kiran Signed-off-by: Robert Love Signed-off-by: Nicholas A. Bellinger --- drivers/target/tcm_fc/tcm_fc.h | 2 +- drivers/target/tcm_fc/tfc_cmd.c | 64 +++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index defff32b7880..7b82f1b7fef8 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h @@ -144,7 +144,7 @@ enum ft_cmd_state { */ struct ft_cmd { enum ft_cmd_state state; - u16 lun; /* LUN from request */ + u32 lun; /* LUN from request */ struct ft_sess *sess; /* session held for cmd */ struct fc_seq *seq; /* sequence in exchange mgr */ struct se_cmd se_cmd; /* Local TCM I/O descriptor */ diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index c056a1132ae1..b2a106729d49 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -94,29 +94,6 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) 16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0); } -/* - * Get LUN from CDB. - */ -static int ft_get_lun_for_cmd(struct ft_cmd *cmd, u8 *lunp) -{ - u64 lun; - - lun = lunp[1]; - switch (lunp[0] >> 6) { - case 0: - break; - case 1: - lun |= (lunp[0] & 0x3f) << 8; - break; - default: - return -1; - } - if (lun >= TRANSPORT_MAX_LUNS_PER_TPG) - return -1; - cmd->lun = lun; - return transport_get_lun_for_cmd(&cmd->se_cmd, NULL, lun); -} - static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd) { struct se_queue_obj *qobj; @@ -418,6 +395,7 @@ static void ft_send_tm(struct ft_cmd *cmd) { struct se_tmr_req *tmr; struct fcp_cmnd *fcp; + struct ft_sess *sess; u8 tm_func; fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp)); @@ -425,13 +403,6 @@ static void ft_send_tm(struct ft_cmd *cmd) switch (fcp->fc_tm_flags) { case FCP_TMF_LUN_RESET: tm_func = TMR_LUN_RESET; - if (ft_get_lun_for_cmd(cmd, fcp->fc_lun) < 0) { - ft_dump_cmd(cmd, __func__); - transport_send_check_condition_and_sense(&cmd->se_cmd, - cmd->se_cmd.scsi_sense_reason, 0); - ft_sess_put(cmd->sess); - return; - } break; case FCP_TMF_TGT_RESET: tm_func = TMR_TARGET_WARM_RESET; @@ -463,6 +434,36 @@ static void ft_send_tm(struct ft_cmd *cmd) return; } cmd->se_cmd.se_tmr_req = tmr; + + switch (fcp->fc_tm_flags) { + case FCP_TMF_LUN_RESET: + cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun); + if (transport_get_lun_for_tmr(&cmd->se_cmd, cmd->lun) < 0) { + /* + * Make sure to clean up newly allocated TMR request + * since "unable to handle TMR request because failed + * to get to LUN" + */ + FT_TM_DBG("Failed to get LUN for TMR func %d, " + "se_cmd %p, unpacked_lun %d\n", + tm_func, &cmd->se_cmd, cmd->lun); + ft_dump_cmd(cmd, __func__); + sess = cmd->sess; + transport_send_check_condition_and_sense(&cmd->se_cmd, + cmd->se_cmd.scsi_sense_reason, 0); + transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0); + ft_sess_put(sess); + return; + } + break; + case FCP_TMF_TGT_RESET: + case FCP_TMF_CLR_TASK_SET: + case FCP_TMF_ABT_TASK_SET: + case FCP_TMF_CLR_ACA: + break; + default: + return; + } transport_generic_handle_tmr(&cmd->se_cmd); } @@ -635,7 +636,8 @@ static void ft_send_cmd(struct ft_cmd *cmd) fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd); - ret = ft_get_lun_for_cmd(cmd, fcp->fc_lun); + cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun); + ret = transport_get_lun_for_cmd(&cmd->se_cmd, NULL, cmd->lun); if (ret < 0) { ft_dump_cmd(cmd, __func__); transport_send_check_condition_and_sense(&cmd->se_cmd, -- cgit v1.2.3 From 7c7cf3b9c31ed09822e5c186297991093ee13c49 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 13 Jun 2011 23:08:46 +0300 Subject: tcm_fc: Fix possible lock to unlock type deadlock There is a typo here, it should be an unlock instead of a lock. The original code will deadlock. Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/tcm_fc/tfc_sess.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 03744c23095c..7491e21cc6ae 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -332,7 +332,7 @@ void ft_sess_close(struct se_session *se_sess) lport = sess->tport->lport; port_id = sess->port_id; if (port_id == -1) { - mutex_lock(&ft_lport_lock); + mutex_unlock(&ft_lport_lock); return; } FT_SESS_DBG("port_id %x\n", port_id); -- cgit v1.2.3 From 95efa2863996b643083957079b9304fb3c01130f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 23 Jun 2011 23:28:46 +0000 Subject: tcm_fc: Fix conversion spec warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the following conversion specification warning for size_t drivers/target/tcm_fc/tfc_io.c: In function ‘ft_queue_data_in’: drivers/target/tcm_fc/tfc_io.c:209: warning: format ‘%x’ expects type ‘unsigned int’, but argument 5 has type ‘size_t’ Reported-by: Randy Dunlap Reported-by: Stephen Rothwell Signed-off-by: Nicholas Bellinger --- drivers/target/tcm_fc/tfc_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index 4c3c0efbe13f..8c4a24077d9d 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c @@ -203,7 +203,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd) /* XXX For now, initiator will retry */ if (printk_ratelimit()) printk(KERN_ERR "%s: Failed to send frame %p, " - "xid <0x%x>, remaining <0x%x>, " + "xid <0x%x>, remaining %zu, " "lso_max <0x%x>\n", __func__, fp, ep->xid, remaining, lport->lso_max); -- cgit v1.2.3 From d698a34da7c5626c3c16a6311c6290522e902e7f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 23 Jun 2011 00:49:29 -0400 Subject: drm/radeon/kms: fix num_banks tiling config for fusion The field is encoded: 0 = 4 banks 1 = 8 banks 2 = 16 banks Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 445af7981637..12d2fdc52414 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2013,9 +2013,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.tile_config |= (3 << 0); break; } - /* num banks is 8 on all fusion asics */ + /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ if (rdev->flags & RADEON_IS_IGP) - rdev->config.evergreen.tile_config |= 8 << 4; + rdev->config.evergreen.tile_config |= 1 << 4; else rdev->config.evergreen.tile_config |= ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; -- cgit v1.2.3 From ee4017f4ac8163737793cc64df535cd246792887 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 23 Jun 2011 12:19:32 -0400 Subject: drm/radeon/kms: handle special cases for vddc A voltage value of 0xff01 requires that the driver look up the max voltage for the board based using the atom SetVoltage command table. Setting the proper voltage should fix stability on some newer asics. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_atombios.c | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 27f45579e64b..ef0e0e016914 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -179,6 +179,7 @@ void radeon_pm_resume(struct radeon_device *rdev); void radeon_combios_get_power_modes(struct radeon_device *rdev); void radeon_atombios_get_power_modes(struct radeon_device *rdev); void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); +int radeon_atom_get_max_vddc(struct radeon_device *rdev, u16 *voltage); void rs690_pm_info(struct radeon_device *rdev); extern int rv6xx_get_temp(struct radeon_device *rdev); extern int rv770_get_temp(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 1e725d9f767f..bf2b61584cdb 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2320,6 +2320,14 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, le16_to_cpu(clock_info->r600.usVDDC); } + /* patch up vddc if necessary */ + if (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage == 0xff01) { + u16 vddc; + + if (radeon_atom_get_max_vddc(rdev, &vddc) == 0) + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc; + } + if (rdev->flags & RADEON_IS_IGP) { /* skip invalid modes */ if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) @@ -2630,7 +2638,35 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } +int radeon_atom_get_max_vddc(struct radeon_device *rdev, + u16 *voltage) +{ + union set_voltage args; + int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); + u8 frev, crev; + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return -EINVAL; + + switch (crev) { + case 1: + return -EINVAL; + case 2: + args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; + args.v2.ucVoltageMode = 0; + args.v2.usVoltageLevel = 0; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + *voltage = le16_to_cpu(args.v2.usVoltageLevel); + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + return -EINVAL; + } + return 0; +} void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) { -- cgit v1.2.3 From 778e24bb6dd8682318bb496d4bfdc32b501a6420 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 23 Jun 2011 01:34:59 +0000 Subject: xfs: reset inode per-lifetime state when recycling it XFS inodes has several per-lifetime state fields that determine the behaviour of the inode. These state fields are not all reset when an inode is reused from the reclaimable state. This can lead to unexpected behaviour of the new inode such as speculative preallocation not being truncated away in the expected manner for local files until the inode is subsequently truncated, freed or cycles out of the cache. It can also lead to an inode being considered to be a filestream inode or having been truncated when that is not the case. Rework the reinitialisation of the inode when it is recycled to ensure that it is pristine before it is reused. While there, also fix the resetting of state flags in the recycling error paths so the inode does not become unreclaimable. Signed-off-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/xfs_iget.c | 13 +++++++++---- fs/xfs/xfs_inode.h | 10 ++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index cb9b6d1469f7..3631783b2b53 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -253,16 +253,21 @@ xfs_iget_cache_hit( rcu_read_lock(); spin_lock(&ip->i_flags_lock); - ip->i_flags &= ~XFS_INEW; - ip->i_flags |= XFS_IRECLAIMABLE; - __xfs_inode_set_reclaim_tag(pag, ip); + ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM); + ASSERT(ip->i_flags & XFS_IRECLAIMABLE); trace_xfs_iget_reclaim_fail(ip); goto out_error; } spin_lock(&pag->pag_ici_lock); spin_lock(&ip->i_flags_lock); - ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM); + + /* + * Clear the per-lifetime state in the inode as we are now + * effectively a new inode and need to return to the initial + * state before reuse occurs. + */ + ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS; ip->i_flags |= XFS_INEW; __xfs_inode_clear_reclaim_tag(mp, pag, ip); inode->i_state = I_NEW; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 3ae6d58e5473..964cfea77686 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -383,6 +383,16 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) #define XFS_ITRUNCATED 0x0020 /* truncated down so flush-on-close */ #define XFS_IDIRTY_RELEASE 0x0040 /* dirty release already seen */ +/* + * Per-lifetime flags need to be reset when re-using a reclaimable inode during + * inode lookup. Thi prevents unintended behaviour on the new inode from + * ocurring. + */ +#define XFS_IRECLAIM_RESET_FLAGS \ + (XFS_IRECLAIMABLE | XFS_IRECLAIM | \ + XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \ + XFS_IFILESTREAM); + /* * Flags for inode locking. * Bit ranges: 1<<1 - 1<<16-1 -- iolock/ilock modes (bitfield) -- cgit v1.2.3 From df4368a146d2b350b8398babfe11e2088f741d67 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 23 Jun 2011 01:35:00 +0000 Subject: xfs: clear XFS_IDIRTY_RELEASE on truncate down When an inode is truncated down, speculative preallocation is removed from the inode. This should also reset the state bits for controlling whether preallocation is subsequently removed when the file is next closed. The flag is not being cleared, so repeated operations on a file that first involve a truncate (e.g. multiple repeated dd invocations on a file) give different file layouts for the second and subsequent invocations. Fix this by clearing the XFS_IDIRTY_RELEASE state bit when the XFS_ITRUNCATED bit is detected in xfs_release() and hence ensure that speculative delalloc is removed on files that have been truncated down. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_vnodeops.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index b7a5fe7c52c8..619720705bc6 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -960,8 +960,11 @@ xfs_release( * be exposed to that problem. */ truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); - if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) - xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE); + if (truncated) { + xfs_iflags_clear(ip, XFS_IDIRTY_RELEASE); + if (VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) + xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE); + } } if (ip->i_d.di_nlink == 0) -- cgit v1.2.3 From 4a33821236f2ef3af0081e8a5eec1301cbed3125 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 23 Jun 2011 01:35:01 +0000 Subject: xfs: prevent bogus assert when trying to remove non-existent attribute If the attribute fork on an inode is in btree format and has multiple levels (i.e node format rather than leaf format), then a lookup failure will trigger an assert failure in xfs_da_path_shift if the flag XFS_DA_OP_OKNOENT is not set. This flag is used to indicate to the directory btree code that not finding an entry is not a fatal error. In the case of doing a lookup for a directory name removal, this is valid as a user cannot insert an arbitrary name to remove from the directory btree. However, in the case of the attribute tree, a user has direct control over the attribute name and can ask for any random name to be removed without any validation. In this case, fsstress is asking for a non-existent user.selinux attribute to be removed, and that is causing xfs_da_path_shift() to fall off the bottom of the tree where it asserts that a lookup failure is allowed. Because the flag is not set, we die a horrible death on a debug enable kernel. Prevent this assert from firing on attribute removes by adding the op_flag XFS_DA_OP_OKNOENT to atribute removal operations. Discovered when testing on a SELinux enabled system by fsstress in test 070 by trying to remove a non-existent user.selinux attribute. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_attr.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index c86375378810..01d2072fb6d4 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -489,6 +489,13 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) args.total = 0; args.whichfork = XFS_ATTR_FORK; + /* + * we have no control over the attribute names that userspace passes us + * to remove, so we have to allow the name lookup prior to attribute + * removal to fail. + */ + args.op_flags = XFS_DA_OP_OKNOENT; + /* * Attach the dquots to the inode. */ -- cgit v1.2.3 From f920fe1cb74191a780d88937f36994231a8faba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Drewniak?= Date: Fri, 24 Jun 2011 02:07:35 -0400 Subject: pata_marvell: Add support for 88SE91A0, 88SE91A4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch enables support for Marvell IDE PATA controllers found on Asus P8P67LE motherboard. The formatting has been corrected and I also received a report from two users of this motherboard that the patch works. Signed-off-by: Paweł Drewniak Signed-off-by: Jeff Garzik --- drivers/ata/pata_marvell.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 75a6a0c0094f..5d7f58a7e34d 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -161,6 +161,9 @@ static const struct pci_device_id marvell_pci_tbl[] = { { PCI_DEVICE(0x11AB, 0x6121), }, { PCI_DEVICE(0x11AB, 0x6123), }, { PCI_DEVICE(0x11AB, 0x6145), }, + { PCI_DEVICE(0x1B4B, 0x91A0), }, + { PCI_DEVICE(0x1B4B, 0x91A4), }, + { } /* terminate list */ }; -- cgit v1.2.3 From 06c8a6a3e40265ff580428bbf51991617477f65b Mon Sep 17 00:00:00 2001 From: Damian Hobson-Garcia Date: Wed, 22 Jun 2011 07:46:25 +0000 Subject: fbdev: sh_mobile_meram: Correct pointer check for YCbCr chroma plane The check was intended to test if we have a valid pointer to write into, but it mistakenly checks the pointer contents instead. Since a valid pointer is mandatory for the chroma data if a YCbCr format is used, the pointer check has been removed. Signed-off-by: Damian Hobson-Garcia Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_meram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c index 9170c82b495c..cc7d7329dc15 100644 --- a/drivers/video/sh_mobile_meram.c +++ b/drivers/video/sh_mobile_meram.c @@ -218,7 +218,7 @@ static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, icb_offset = 0xc0000000 | (cfg->current_reg << 23); *icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24); - if ((*icb_addr_c) && is_nvcolor(cfg->pixelformat)) + if (is_nvcolor(cfg->pixelformat)) *icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24); } -- cgit v1.2.3 From 7a0ee92b4a510bc2dd026333f90031e883e0cde0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 23 Jun 2011 22:00:20 +0100 Subject: ARM: pm: proc-v7: fix missing struct processor pointers for suspend code Add the missing suspend/resume pointers for the suspend code. This is needed when building for multiple CPUs. Tested-by: Kevin Hilman Acked-by: Jean Pihet Signed-off-by: Russell King --- arch/arm/mm/proc-v7.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 3c3867850a30..e27c011a759c 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -418,9 +418,9 @@ ENTRY(v7_processor_functions) .word cpu_v7_dcache_clean_area .word cpu_v7_switch_mm .word cpu_v7_set_pte_ext - .word 0 - .word 0 - .word 0 + .word cpu_v7_suspend_size + .word cpu_v7_do_suspend + .word cpu_v7_do_resume .size v7_processor_functions, . - v7_processor_functions .section ".rodata" -- cgit v1.2.3 From 111b20d01346b9635b3223c7af4e40e43bee8dc6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 22 Jun 2011 15:41:58 +0100 Subject: ARM: pm: ensure ARMv7 CPUs save and restore the TLS register Ensure that the TLS register is saved and restored over a suspend cycle, so that userspace programs don't see a corrupted TLS value. Tested-by: Kevin Hilman Acked-by: Jean Pihet Signed-off-by: Russell King --- arch/arm/mm/proc-v7.S | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index e27c011a759c..089c0b5e454f 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -210,19 +210,21 @@ cpu_v7_name: /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */ .globl cpu_v7_suspend_size -.equ cpu_v7_suspend_size, 4 * 8 +.equ cpu_v7_suspend_size, 4 * 9 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_v7_do_suspend) stmfd sp!, {r4 - r11, lr} mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID mrc p15, 0, r5, c13, c0, 1 @ Context ID + mrc p15, 0, r6, c13, c0, 3 @ User r/o thread ID + stmia r0!, {r4 - r6} mrc p15, 0, r6, c3, c0, 0 @ Domain ID mrc p15, 0, r7, c2, c0, 0 @ TTB 0 mrc p15, 0, r8, c2, c0, 1 @ TTB 1 mrc p15, 0, r9, c1, c0, 0 @ Control register mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register mrc p15, 0, r11, c1, c0, 2 @ Co-processor access control - stmia r0, {r4 - r11} + stmia r0, {r6 - r11} ldmfd sp!, {r4 - r11, pc} ENDPROC(cpu_v7_do_suspend) @@ -230,9 +232,11 @@ ENTRY(cpu_v7_do_resume) mov ip, #0 mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache - ldmia r0, {r4 - r11} + ldmia r0!, {r4 - r6} mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID mcr p15, 0, r5, c13, c0, 1 @ Context ID + mcr p15, 0, r6, c13, c0, 3 @ User r/o thread ID + ldmia r0, {r6 - r11} mcr p15, 0, r6, c3, c0, 0 @ Domain ID mcr p15, 0, r7, c2, c0, 0 @ TTB 0 mcr p15, 0, r8, c2, c0, 1 @ TTB 1 -- cgit v1.2.3 From 3535ed3fa7a87244410696880000e03bc224315d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 16 Jun 2011 19:31:19 +0000 Subject: gx1fb: Fix section mismatch warnings Fix a chain of section mismatches in geode driver, beginning with: WARNING: drivers/video/geode/gx1fb.o(.data+0x70): Section mismatch in reference from the variable gx1fb_driver to the function .init.text:gx1fb_probe() The variable gx1fb_driver references the function __init gx1fb_probe() If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console Making the changes that Paul pointed out resulted in a few more changes being needed, so they are all included here. Signed-off-by: Randy Dunlap Signed-off-by: Paul Mundt --- drivers/video/geode/gx1fb_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index c6b554f72c6d..5a5d0928df33 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c @@ -29,7 +29,7 @@ static int crt_option = 1; static char panel_option[32] = ""; /* Modes relevant to the GX1 (taken from modedb.c) */ -static const struct fb_videomode __initdata gx1_modedb[] = { +static const struct fb_videomode __devinitdata gx1_modedb[] = { /* 640x480-60 VESA */ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, @@ -195,7 +195,7 @@ static int gx1fb_blank(int blank_mode, struct fb_info *info) return par->vid_ops->blank_display(info, blank_mode); } -static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev) +static int __devinit gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev) { struct geodefb_par *par = info->par; unsigned gx_base; @@ -268,7 +268,7 @@ static struct fb_ops gx1fb_ops = { .fb_imageblit = cfb_imageblit, }; -static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev) +static struct fb_info * __devinit gx1fb_init_fbinfo(struct device *dev) { struct geodefb_par *par; struct fb_info *info; @@ -318,7 +318,7 @@ static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev) return info; } -static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static int __devinit gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct geodefb_par *par; struct fb_info *info; @@ -382,7 +382,7 @@ static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id * return ret; } -static void gx1fb_remove(struct pci_dev *pdev) +static void __devexit gx1fb_remove(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); struct geodefb_par *par = info->par; @@ -441,7 +441,7 @@ static struct pci_driver gx1fb_driver = { .name = "gx1fb", .id_table = gx1fb_id_table, .probe = gx1fb_probe, - .remove = gx1fb_remove, + .remove = __devexit_p(gx1fb_remove), }; static int __init gx1fb_init(void) @@ -456,7 +456,7 @@ static int __init gx1fb_init(void) return pci_register_driver(&gx1fb_driver); } -static void __exit gx1fb_cleanup(void) +static void __devexit gx1fb_cleanup(void) { pci_unregister_driver(&gx1fb_driver); } -- cgit v1.2.3 From 9845afc8fa32de145d56c8e69b7900e10371255d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 16 Jun 2011 19:32:40 +0000 Subject: sm501fb: fix section mismatch warning Fix section mismatch warning in sm501fb: WARNING: drivers/video/sm501fb.o(.text+0x21d6): Section mismatch in reference from the function sm501fb_init_fb() to the variable .devinit.data:sm501_default_mode The function sm501fb_init_fb() references the variable __devinitdata sm501_default_mode. This is often because sm501fb_init_fb lacks a __devinitdata annotation or the annotation of sm501_default_mode is wrong. Signed-off-by: Randy Dunlap Signed-off-by: Paul Mundt --- drivers/video/sm501fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 87f0be1e78b5..6294dca95500 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -1664,7 +1664,7 @@ static void sm501fb_stop(struct sm501fb_info *info) resource_size(info->regs_res)); } -static int sm501fb_init_fb(struct fb_info *fb, +static int __devinit sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head, const char *fbname) { -- cgit v1.2.3 From 291600193e5c0c3f0a9af1f23a8076dd7417c02a Mon Sep 17 00:00:00 2001 From: Pavel Shved Date: Fri, 17 Jun 2011 16:25:12 +0000 Subject: hecubafb: add module_put on error path in hecubafb_probe() In hecubafb_probe(), after a successful try_module_get, vzalloc may fail and make the hecubafb_probe return, but the module is not put on this error path. This patch adds an exit point that calls module_put in such situation. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Pavel Shved Signed-off-by: Paul Mundt --- drivers/video/hecubafb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c index fbef15f7a218..614251a9af91 100644 --- a/drivers/video/hecubafb.c +++ b/drivers/video/hecubafb.c @@ -233,7 +233,7 @@ static int __devinit hecubafb_probe(struct platform_device *dev) videomemory = vzalloc(videomemorysize); if (!videomemory) - return retval; + goto err_videomem_alloc; info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev); if (!info) @@ -275,6 +275,7 @@ err_fbreg: framebuffer_release(info); err_fballoc: vfree(videomemory); +err_videomem_alloc: module_put(board->owner); return retval; } -- cgit v1.2.3 From 9377c51752970c305fae29ac634501fde44378cb Mon Sep 17 00:00:00 2001 From: William Katsak Date: Thu, 23 Jun 2011 13:16:29 +0000 Subject: udlfb: Correct sub-optimal resolution selection. The situation in which the problem occurred was with a Plugable UGA-2K-A connected to a Samsung EX2220X display. The driver indicates that 1920x1080 is a valid mode (the first mode available, in fact), but proceeds to set the framebuffer size to 1600x1200. The patch corrects what seems to be a logic error, regarding unsetting the FB_MISC_1ST_DETAIL flag, if the first (top/best) mode is invalid. The existing code unset the flag if ANY mode was invalid. Signed-off-by: William Katsak Signed-off-by: Paul Mundt --- drivers/video/udlfb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 52b0f3e8ccac..816a4fda04f5 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -1233,8 +1233,12 @@ static int dlfb_setup_modes(struct dlfb_data *dev, if (dlfb_is_valid_mode(&info->monspecs.modedb[i], info)) fb_add_videomode(&info->monspecs.modedb[i], &info->modelist); - else /* if we've removed top/best mode */ - info->monspecs.misc &= ~FB_MISC_1ST_DETAIL; + else { + if (i == 0) + /* if we've removed top/best mode */ + info->monspecs.misc + &= ~FB_MISC_1ST_DETAIL; + } } default_vmode = fb_find_best_display(&info->monspecs, -- cgit v1.2.3 From 39785eb1d3e6c58cc8bf8f6990956a58037ecc75 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 23 Jun 2011 20:20:26 +0000 Subject: fsl-diu-fb: remove check for pixel clock ranges The Freescale DIU framebuffer driver defines two constants, MIN_PIX_CLK and MAX_PIX_CLK, that are supposed to represent the lower and upper limits of the pixel clock. These values, however, are true only for one platform clock rate (533MHz) and only for the MPC8610. So the actual range for the pixel clock is chip-specific, which means the current values are almost always wrong. The chance of an out-of-range pixel clock being used are also remote. Rather than try to detect an out-of-range clock in the DIU driver, we depend on the board-specific pixel clock function (e.g. p1022ds_set_pixel_clock) to clamp the pixel clock to a supported value. Signed-off-by: Timur Tabi Signed-off-by: Paul Mundt --- drivers/video/fsl-diu-fb.c | 16 ---------------- include/linux/fsl-diu-fb.h | 6 ------ 2 files changed, 22 deletions(-) diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index bedf5be27f05..0acc7d65aeaa 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -555,8 +555,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, static int fsl_diu_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - unsigned long htotal, vtotal; - pr_debug("check_var xres: %d\n", var->xres); pr_debug("check_var yres: %d\n", var->yres); @@ -635,20 +633,6 @@ static int fsl_diu_check_var(struct fb_var_screeninfo *var, break; } - /* If the pixclock is below the minimum spec'd value then set to - * refresh rate for 60Hz since this is supported by most monitors. - * Refer to Documentation/fb/ for calculations. - */ - if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) { - htotal = var->xres + var->right_margin + var->hsync_len + - var->left_margin; - vtotal = var->yres + var->lower_margin + var->vsync_len + - var->upper_margin; - var->pixclock = (vtotal * htotal * 6UL) / 100UL; - var->pixclock = KHZ2PICOS(var->pixclock); - pr_debug("pixclock set for 60Hz refresh = %u ps\n", - var->pixclock); - } var->height = -1; var->width = -1; diff --git a/include/linux/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h index 781d4671415f..daa9952d2174 100644 --- a/include/linux/fsl-diu-fb.h +++ b/include/linux/fsl-diu-fb.h @@ -24,12 +24,6 @@ * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory() */ #define MEM_ALLOC_THRESHOLD (1024*768*4+32) -/* Minimum value that the pixel clock can be set to in pico seconds - * This is determined by platform clock/3 where the minimum platform - * clock is 533MHz. This gives 5629 pico seconds. - */ -#define MIN_PIX_CLK 5629 -#define MAX_PIX_CLK 96096 #include -- cgit v1.2.3 From 17e8c4e1ebf139743e3830439fa65fd906af4a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Minier?= Date: Mon, 20 Jun 2011 20:44:17 +0000 Subject: fbdev: amba: Link fb device to its parent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some pieces of userspace like debian-installer expect to find the fb0 driver name by readlink-ing /sys/class/graphics/fb0/device/driver but this was broken with amba-clcd as it sets up fb_info manually and missed the .device parent pointer. Signed-off-by: Loïc Minier Cc: Russell King Signed-off-by: Paul Mundt --- drivers/video/amba-clcd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 5fc983c5b92c..cf03ad067147 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -447,6 +447,8 @@ static int clcdfb_register(struct clcd_fb *fb) goto out; } + fb->fb.device = &fb->dev->dev; + fb->fb.fix.mmio_start = fb->dev->res.start; fb->fb.fix.mmio_len = resource_size(&fb->dev->res); -- cgit v1.2.3 From 6935d131dec9a85afe80512b5a12541592802e48 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 1 Mar 2011 07:58:47 +0000 Subject: sh: add to select the new configuration for USB EHCI/OHCI Because the USB EHCI/OHCI driver has new configuration for SH, the patch enables the EHCI and/or OHCI driver of the on-chip for some CPUs. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index f03338c2f088..df89ba5e104b 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -348,6 +348,7 @@ config CPU_SUBTYPE_SH7720 select SYS_SUPPORTS_CMT select ARCH_WANT_OPTIONAL_GPIOLIB select USB_ARCH_HAS_OHCI + select USB_OHCI_SH help Select SH7720 if you have a SH3-DSP SH7720 CPU. @@ -357,6 +358,7 @@ config CPU_SUBTYPE_SH7721 select CPU_HAS_DSP select SYS_SUPPORTS_CMT select USB_ARCH_HAS_OHCI + select USB_OHCI_SH help Select SH7721 if you have a SH3-DSP SH7721 CPU. @@ -440,6 +442,7 @@ config CPU_SUBTYPE_SH7763 bool "Support SH7763 processor" select CPU_SH4A select USB_ARCH_HAS_OHCI + select USB_OHCI_SH help Select SH7763 if you have a SH4A SH7763(R5S77631) CPU. @@ -467,7 +470,9 @@ config CPU_SUBTYPE_SH7786 select GENERIC_CLOCKEVENTS_BROADCAST if SMP select ARCH_WANT_OPTIONAL_GPIOLIB select USB_ARCH_HAS_OHCI + select USB_OHCI_SH select USB_ARCH_HAS_EHCI + select USB_EHCI_SH config CPU_SUBTYPE_SHX3 bool "Support SH-X3 processor" -- cgit v1.2.3 From 16866741bda5d16f3d30d1656ce941faf5dad34c Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 23 Jun 2011 23:54:40 +0200 Subject: ALSA: Remove unneeded version.h includes from sound/ In the sound/ directory there are two files (flagged by 'make versioncheck'); sound/pci/asihpi/asihpi.c and sound/soc/codecs/wm8991.c that include linux/version.h although they don't need it. This patch removes the unneeded includes. Signed-off-by: Jesper Juhl Signed-off-by: Takashi Iwai --- sound/pci/asihpi/asihpi.c | 1 - sound/soc/codecs/wm8991.c | 1 - 2 files changed, 2 deletions(-) diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 2ca6f4f85b41..e3569bdd3b64 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -27,7 +27,6 @@ #include "hpioctl.h" #include -#include #include #include #include diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 3c2ee1bb73cd..6af23d06870f 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From 50bc03ab5c7529fdfe4e01621efca7d26439ea00 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 21 Jun 2011 15:01:53 +0200 Subject: HID: hid-multitouch: ensure slots are initialized In case a device does not provide the feature "Maximum Contact Count", or set it at 0, the maxcontacts field may be at 0 while calling input_mt_init_slots. This patch ensures that hid-multitouch will allways report ABS_MT_SLOT and ABS_MT_TRACKING_ID to the user space. This corrects a bug found with some Ilitek devices that has been integrated in 3.0-rc0. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 0b2dcd0ee591..386765654cf6 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -271,6 +271,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, } return 1; case HID_DG_CONTACTID: + if (!td->maxcontacts) + td->maxcontacts = MT_DEFAULT_MAXCONTACT; input_mt_init_slots(hi->input, td->maxcontacts); td->last_slot_field = usage->hid; td->last_field_index = field->index; @@ -547,9 +549,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (ret) goto fail; - if (!td->maxcontacts) - td->maxcontacts = MT_DEFAULT_MAXCONTACT; - td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), GFP_KERNEL); if (!td->slots) { -- cgit v1.2.3 From 85a600825b425d52e466c6093dcdfeba85eb0044 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 21 Jun 2011 15:01:54 +0200 Subject: HID: hid-multitouch: correct VID for Stantum panels while merging hid-stantum into hid-multitouch, I did not correctly copy/paste the VIDs for those devices. This patch fixes it. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 386765654cf6..467b518a43b3 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -706,10 +706,10 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP)}, { .driver_data = MT_CLS_CONFIDENCE, - HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, + HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM)}, { .driver_data = MT_CLS_CONFIDENCE, - HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, + HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX)}, /* Touch International panels */ -- cgit v1.2.3 From c3ead6de4f6bd1c08a81f84e629e3dbf4a9078f0 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 21 Jun 2011 15:01:55 +0200 Subject: HID: hid-multitouch: add support for a new Lumio dual-touch panel Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-multitouch.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f7440e8ce3e7..6f3289a57888 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1423,6 +1423,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index aecb5a4b8d6d..a756ee6c7df5 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -449,6 +449,7 @@ #define USB_VENDOR_ID_LUMIO 0x202e #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 +#define USB_DEVICE_ID_CRYSTALTOUCH_DUAL 0x0007 #define USB_VENDOR_ID_MCC 0x09db #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 467b518a43b3..62cac4dc3b62 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -676,6 +676,9 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, + { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, + HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, + USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, /* MosArt panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, -- cgit v1.2.3 From 46e4edbf7ea9cf26665eb9f90c0fc7688d1a51ed Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 23 Jun 2011 23:59:32 +0200 Subject: Remove unneeded version.h includes from fs/ It was pointed out by 'make versioncheck' that some includes of linux/version.h were not needed in fs/ (fs/btrfs/ctree.h and fs/omfs/file.c). This patch removes them. Signed-off-by: Jesper Juhl Acked-by: Bob Copeland Signed-off-by: Linus Torvalds --- fs/btrfs/ctree.h | 1 - fs/omfs/file.c | 1 - 2 files changed, 2 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 300628795fdb..f30ac05dbda7 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -19,7 +19,6 @@ #ifndef __BTRFS_CTREE__ #define __BTRFS_CTREE__ -#include #include #include #include diff --git a/fs/omfs/file.c b/fs/omfs/file.c index d738a7e493dd..2c6d95257a4d 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c @@ -4,7 +4,6 @@ * Released under GPL v2. */ -#include #include #include #include -- cgit v1.2.3 From e4fb0edb7c03e5ec19b6f732f1dfbe911212dbde Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 20 Jun 2011 14:33:16 -0400 Subject: cifs: free blkcipher in smbhash This is currently leaked in the rc == 0 case. Reported-by: J. Bruce Fields Signed-off-by: Jeff Layton Reviewed-by: Shirish Pargaonkar Signed-off-by: Steve French --- fs/cifs/smbencrypt.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 1525d5e662b6..1c5b770c3141 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -90,12 +90,10 @@ smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) sg_init_one(&sgout, out, 8); rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8); - if (rc) { + if (rc) cERROR(1, "could not encrypt crypt key rc: %d\n", rc); - crypto_free_blkcipher(tfm_des); - goto smbhash_err; - } + crypto_free_blkcipher(tfm_des); smbhash_err: return rc; } -- cgit v1.2.3 From 1973f0faeb4a5f35597793c65d3c94d8fd386e10 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 24 Jun 2011 13:13:29 -0400 Subject: Btrfs: make sure to record the transid in new inodes When we create a new inode, we aren't filling in the field that records the transaction that last changed this inode. If we then go to fsync that inode, it will be skipped because the field isn't filled in. Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5813dec5101c..87f1e0cf26f8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4520,6 +4520,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, inode_tree_add(inode); trace_btrfs_inode_new(inode); + btrfs_set_inode_last_trans(trans, inode); return inode; fail: -- cgit v1.2.3 From 9b8e072a31180eb5cd6991d08524d9c4fa235ade Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 21 Jun 2011 07:18:26 -0400 Subject: cifs: mark CONFIG_CIFS_NFSD_EXPORT as BROKEN This does not work properly with CIFS as current servers do not enable support for the FILE_OPEN_BY_FILE_ID on SMB NTCreateX and not all NFS clients handle ESTALE. For now, it just plain doesn't work. Mark it BROKEN to discourage distros from enabling it. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 53ed1ad2c112..f66cc1625150 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -156,6 +156,6 @@ config CIFS_ACL config CIFS_NFSD_EXPORT bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)" - depends on CIFS && EXPERIMENTAL + depends on CIFS && EXPERIMENTAL && BROKEN help Allows NFS server to export a CIFS mounted share (nfsd over cifs) -- cgit v1.2.3 From 1e4e82baee8c2a8d753cbf6aa1a77326b71e59f0 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 24 Jun 2011 19:52:13 +0200 Subject: r8169: fix wrong register use. Signed-off-by: Francois Romieu Cc: Realtek linux nic maintainers --- drivers/net/r8169.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 05d81780d1fd..5990621fb5cd 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -742,7 +742,7 @@ static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd) msleep(2); for (i = 0; i < 5; i++) { udelay(100); - if (!(RTL_R32(ERIDR) & ERIAR_FLAG)) + if (!(RTL_R32(ERIAR) & ERIAR_FLAG)) break; } -- cgit v1.2.3 From 77e569edf5a33cd94dac67c714cf736675b0e2da Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 21 Jun 2011 11:03:01 -0700 Subject: iwlagn: Fix a bug introduced by the HUGE command removal Since we don't have HUGE command any more, there is no point in adding 1 to the num of slots in the command queue. Doing so is buggy and might corrupt memory. Bug introduced by 4ce7cc2b09553a91d4aea014c39674685715173a iwlagn: support multiple TBs per command Cc: Johannes Berg Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-tx.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 686e176b5ebd..157a642a5436 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -535,12 +535,7 @@ out_free_arrays: void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { - int actual_slots = slots_num; - - if (txq_id == priv->cmd_queue) - actual_slots++; - - memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); + memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * slots_num); txq->need_update = 0; -- cgit v1.2.3 From 5306c0807491e891125f4fb08b04340c91530f57 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Jun 2011 08:28:31 -0700 Subject: iwlagn: fix change_interface for P2P types When an interface changes type to a P2P type, iwlagn will erroneously set vif->type to the P2P type and not the reduced/split type. Fix this by keeping "newtype" in another variable for the assignment to vif->type. Cc: stable@kernel.org [2.6.38+] Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 213c80c6a668..45cc51c9c93e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1763,6 +1763,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_context *tmp; + enum nl80211_iftype newviftype = newtype; u32 interface_modes; int err; @@ -1818,7 +1819,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* success */ iwl_teardown_interface(priv, vif, true); - vif->type = newtype; + vif->type = newviftype; vif->p2p = newp2p; err = iwl_setup_interface(priv, ctx); WARN_ON(err); -- cgit v1.2.3 From dd8544661947ad6d8d87b3c9d4333bfa1583d1bc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 08:24:42 -0400 Subject: take bdi setup/destruction into cifs_mount/cifs_umount Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 12 +----------- fs/cifs/connect.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2f0c58646c10..5d3c4fa4b546 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -116,18 +116,12 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, spin_lock_init(&cifs_sb->tlink_tree_lock); cifs_sb->tlink_tree = RB_ROOT; - rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); - if (rc) - return rc; - - cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; - rc = cifs_mount(sb, cifs_sb, volume_info, devname); if (rc) { if (!silent) cERROR(1, "cifs_mount failed w/return code = %d", rc); - goto out_mount_failed; + return rc; } sb->s_magic = CIFS_MAGIC_NUMBER; @@ -171,9 +165,6 @@ out_no_root: iput(inode); cifs_umount(sb, cifs_sb); - -out_mount_failed: - bdi_destroy(&cifs_sb->bdi); return rc; } @@ -199,7 +190,6 @@ cifs_put_super(struct super_block *sb) } unload_nls(cifs_sb->local_nls); - bdi_destroy(&cifs_sb->bdi); kfree(cifs_sb); } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 12cf72dd0c42..78fd7557e35d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2983,6 +2983,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, struct tcon_link *tlink; #ifdef CONFIG_CIFS_DFS_UPCALL int referral_walks_count = 0; + + rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); + if (rc) + return rc; + + cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; + try_mount_again: /* cleanup activities if we're chasing a referral */ if (referral_walks_count) { @@ -3007,6 +3014,7 @@ try_mount_again: srvTcp = cifs_get_tcp_session(volume_info); if (IS_ERR(srvTcp)) { rc = PTR_ERR(srvTcp); + bdi_destroy(&cifs_sb->bdi); goto out; } @@ -3161,6 +3169,7 @@ mount_fail_check: cifs_put_smb_ses(pSesInfo); else cifs_put_tcp_session(srvTcp); + bdi_destroy(&cifs_sb->bdi); goto out; } @@ -3357,6 +3366,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) } spin_unlock(&cifs_sb->tlink_tree_lock); + bdi_destroy(&cifs_sb->bdi); return 0; } -- cgit v1.2.3 From 6d6861757dfadb7d6aec6bb34acd471210a755f9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 08:34:57 -0400 Subject: cifs: double free on mount failure if we get to out_super with ->s_root already set (e.g. with cifs_get_root() failure), we'll end up with cifs_put_super() called and ->mountdata freed twice. We'll also get cifs_sb freed twice and cifs_sb->local_nls dropped twice. The problem is, we can get to out_super both with and without ->s_root, which makes ->put_super() a bad place for such work. Switch to ->kill_sb(), have all that work done there after kill_anon_super(). Unlike ->put_super(), ->kill_sb() is called by deactivate_locked_super() whether we have ->s_root or not. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5d3c4fa4b546..dc76c7bccb15 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -184,11 +184,13 @@ cifs_put_super(struct super_block *sb) rc = cifs_umount(sb, cifs_sb); if (rc) cERROR(1, "cifs_umount failed with return code %d", rc); - if (cifs_sb->mountdata) { - kfree(cifs_sb->mountdata); - cifs_sb->mountdata = NULL; - } +} +static void cifs_kill_sb(struct super_block *sb) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); + kill_anon_super(sb); + kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); } @@ -729,8 +731,8 @@ out_shared: goto out; out_super: - kfree(cifs_sb->mountdata); deactivate_locked_super(sb); + goto out; out_cifs_sb: unload_nls(cifs_sb->local_nls); @@ -827,7 +829,7 @@ struct file_system_type cifs_fs_type = { .owner = THIS_MODULE, .name = "cifs", .mount = cifs_do_mount, - .kill_sb = kill_anon_super, + .kill_sb = cifs_kill_sb, /* .fs_flags */ }; const struct inode_operations cifs_dir_inode_ops = { -- cgit v1.2.3 From ca171baaad1420a29cca98be5bdf5596cd70b294 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 08:49:12 -0400 Subject: cifs: don't leak nls on mount failure if cifs_sb allocation fails, we still need to drop nls we'd stashed into volume_info - the one we would've copied to cifs_sb if we could allocate the latter. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index dc76c7bccb15..bfab2bc83726 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -672,6 +672,7 @@ cifs_do_mount(struct file_system_type *fs_type, cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); if (cifs_sb == NULL) { root = ERR_PTR(-ENOMEM); + unload_nls(volume_info->local_nls); goto out; } -- cgit v1.2.3 From 2c6292ae4be00454882246d07f38cdf15a823c2a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:05:48 -0400 Subject: cifs: don't pass superblock to cifs_mount() To close sget() races we'll need to be able to set cifs_sb up before we get the superblock, so we'll want to be able to do cifs_mount() earlier. Fortunately, it's easy to do - setting ->s_maxbytes can be done in cifs_read_super(), ditto for ->s_time_gran and as for putting MS_POSIXACL into ->s_flags, we can mirror it in ->mnt_cifs_flags until cifs_read_super() is called. Kill unused 'devname' argument, while we are at it... Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifs_fs_sb.h | 1 + fs/cifs/cifsfs.c | 13 ++++++++++++- fs/cifs/cifsproto.h | 6 +++--- fs/cifs/connect.c | 28 ++++++++++------------------ 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ffb1459dc6ec..7260e11e21f8 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -42,6 +42,7 @@ #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ +#define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ struct cifs_sb_info { struct rb_root tlink_tree; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index bfab2bc83726..8f7451f3c8e6 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -116,7 +116,7 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, spin_lock_init(&cifs_sb->tlink_tree_lock); cifs_sb->tlink_tree = RB_ROOT; - rc = cifs_mount(sb, cifs_sb, volume_info, devname); + rc = cifs_mount(cifs_sb, volume_info); if (rc) { if (!silent) @@ -124,6 +124,17 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, return rc; } + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) + sb->s_flags |= MS_POSIXACL; + + if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) + sb->s_maxbytes = MAX_LFS_FILESIZE; + else + sb->s_maxbytes = MAX_NON_LFS; + + /* BB FIXME fix time_gran to be larger for LANMAN sessions */ + sb->s_time_gran = 100; + sb->s_magic = CIFS_MAGIC_NUMBER; sb->s_op = &cifs_super_ops; sb->s_bdi = &cifs_sb->bdi; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 953f84413c77..5814fe543f95 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -157,8 +157,7 @@ extern int cifs_match_super(struct super_block *, void *); extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, const char *devname); -extern int cifs_mount(struct super_block *, struct cifs_sb_info *, - struct smb_vol *, const char *); +extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); extern int cifs_umount(struct super_block *, struct cifs_sb_info *); extern void cifs_dfs_release_automount_timer(void); void cifs_proc_init(void); @@ -218,7 +217,8 @@ extern int get_dfs_path(int xid, struct cifs_ses *pSesInfo, struct dfs_info3_param **preferrals, int remap); extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, - struct super_block *sb, struct smb_vol *vol); + struct cifs_sb_info *cifs_sb, + struct smb_vol *vol); extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData); extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 78fd7557e35d..3011ac8c9249 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2546,7 +2546,7 @@ ip_connect(struct TCP_Server_Info *server) } void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, - struct super_block *sb, struct smb_vol *vol_info) + struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info) { /* if we are reconnecting then should we check to see if * any requested capabilities changed locally e.g. via @@ -2600,22 +2600,23 @@ void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, cap &= ~CIFS_UNIX_POSIX_ACL_CAP; else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { cFYI(1, "negotiated posix acl support"); - if (sb) - sb->s_flags |= MS_POSIXACL; + if (cifs_sb) + cifs_sb->mnt_cifs_flags |= + CIFS_MOUNT_POSIXACL; } if (vol_info && vol_info->posix_paths == 0) cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { cFYI(1, "negotiate posix pathnames"); - if (sb) - CIFS_SB(sb)->mnt_cifs_flags |= + if (cifs_sb) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; } - if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) { + if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) { if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { - CIFS_SB(sb)->rsize = 127 * 1024; + cifs_sb->rsize = 127 * 1024; cFYI(DBG2, "larger reads not supported by srv"); } } @@ -2971,8 +2972,7 @@ out: } int -cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, - struct smb_vol *volume_info, const char *devname) +cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) { int rc = 0; int xid; @@ -3026,14 +3026,6 @@ try_mount_again: goto mount_fail_check; } - if (pSesInfo->capabilities & CAP_LARGE_FILES) - sb->s_maxbytes = MAX_LFS_FILESIZE; - else - sb->s_maxbytes = MAX_NON_LFS; - - /* BB FIXME fix time_gran to be larger for LANMAN sessions */ - sb->s_time_gran = 100; - /* search for existing tcon to this server share */ tcon = cifs_get_tcon(pSesInfo, volume_info); if (IS_ERR(tcon)) { @@ -3046,7 +3038,7 @@ try_mount_again: if (tcon->ses->capabilities & CAP_UNIX) { /* reset of caps checks mount to see if unix extensions disabled for just this mount */ - reset_cifs_unix_caps(xid, tcon, sb, volume_info); + reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info); if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && (le64_to_cpu(tcon->fsUnixInfo.Capability) & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { -- cgit v1.2.3 From d687ca380f1a8f3043f42efd2403cbe58c846e70 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:14:27 -0400 Subject: cifs: leak on mount if we share superblock cifs_sb and nls end up leaked... Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8f7451f3c8e6..4162ee45d043 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -701,6 +701,8 @@ cifs_do_mount(struct file_system_type *fs_type, if (sb->s_fs_info) { cFYI(1, "Use existing superblock"); + unload_nls(cifs_sb->local_nls); + kfree(cifs_sb); goto out_shared; } -- cgit v1.2.3 From 5d3bc605cafe3f367b1c43b673bf643245c81626 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:17:28 -0400 Subject: cifs: allocate mountdata earlier pull mountdata allocation up, so that it won't stand in the way when we lift cifs_mount() to location before sget(). Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4162ee45d043..ec19161dd278 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -687,6 +687,14 @@ cifs_do_mount(struct file_system_type *fs_type, goto out; } + cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); + if (cifs_sb->mountdata == NULL) { + root = ERR_PTR(-ENOMEM); + unload_nls(volume_info->local_nls); + kfree(cifs_sb); + goto out; + } + cifs_setup_cifs_sb(volume_info, cifs_sb); mnt_data.vol = volume_info; @@ -701,22 +709,12 @@ cifs_do_mount(struct file_system_type *fs_type, if (sb->s_fs_info) { cFYI(1, "Use existing superblock"); + kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); goto out_shared; } - /* - * Copy mount params for use in submounts. Better to do - * the copy here and deal with the error before cleanup gets - * complicated post-mount. - */ - cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); - if (cifs_sb->mountdata == NULL) { - root = ERR_PTR(-ENOMEM); - goto out_super; - } - sb->s_flags = flags; /* BB should we make this contingent on mount parm? */ sb->s_flags |= MS_NODIRATIME | MS_NOATIME; @@ -749,6 +747,7 @@ out_super: goto out; out_cifs_sb: + kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); -- cgit v1.2.3 From 2ced6f693581357b2a5bf8b031a702c624b12d0d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:20:04 -0400 Subject: cifs: initialize ->tlink_tree in cifs_setup_cifs_sb() no need to wait until cifs_read_super() and we need it done by the time cifs_mount() will be called. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 3 --- fs/cifs/connect.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ec19161dd278..61c7aa870f1c 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -113,9 +113,6 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, cifs_sb = CIFS_SB(sb); - spin_lock_init(&cifs_sb->tlink_tree_lock); - cifs_sb->tlink_tree = RB_ROOT; - rc = cifs_mount(cifs_sb, volume_info); if (rc) { diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 3011ac8c9249..9f09adf51edc 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2663,6 +2663,9 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, { INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); + spin_lock_init(&cifs_sb->tlink_tree_lock); + cifs_sb->tlink_tree = RB_ROOT; + if (pvolume_info->rsize > CIFSMaxBufSize) { cERROR(1, "rsize %d too large, using MaxBufSize", pvolume_info->rsize); -- cgit v1.2.3 From 2a9b99516c662d1713d58648e4a4c9aef72051bc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:27:16 -0400 Subject: sanitize cifs_umount() prototype a) superblock argument is unused b) it always returns 0 Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 6 ++---- fs/cifs/cifsproto.h | 2 +- fs/cifs/connect.c | 5 ++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 61c7aa870f1c..2af14d4577a7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -172,7 +172,7 @@ out_no_root: if (inode) iput(inode); - cifs_umount(sb, cifs_sb); + cifs_umount(cifs_sb); return rc; } @@ -189,9 +189,7 @@ cifs_put_super(struct super_block *sb) return; } - rc = cifs_umount(sb, cifs_sb); - if (rc) - cERROR(1, "cifs_umount failed with return code %d", rc); + cifs_umount(cifs_sb); } static void cifs_kill_sb(struct super_block *sb) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 5814fe543f95..257f312ede42 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -158,7 +158,7 @@ extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, const char *devname); extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); -extern int cifs_umount(struct super_block *, struct cifs_sb_info *); +extern void cifs_umount(struct cifs_sb_info *); extern void cifs_dfs_release_automount_timer(void); void cifs_proc_init(void); void cifs_proc_clean(void); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9f09adf51edc..b2702226634e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3339,8 +3339,8 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, return rc; } -int -cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) +void +cifs_umount(struct cifs_sb_info *cifs_sb) { struct rb_root *root = &cifs_sb->tlink_tree; struct rb_node *node; @@ -3362,7 +3362,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) spin_unlock(&cifs_sb->tlink_tree_lock); bdi_destroy(&cifs_sb->bdi); - return 0; } int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) -- cgit v1.2.3 From 97d1152acec0647b72f8c6ecc57da0d6fed574de Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:29:57 -0400 Subject: cifs: pull cifs_mount() call up ... to the point prior to sget(). Now we have cifs_sb set up early enough. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2af14d4577a7..4004bc647a72 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -104,8 +104,7 @@ cifs_sb_deactive(struct super_block *sb) } static int -cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, - const char *devname, int silent) +cifs_read_super(struct super_block *sb) { struct inode *inode; struct cifs_sb_info *cifs_sb; @@ -113,14 +112,6 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, cifs_sb = CIFS_SB(sb); - rc = cifs_mount(cifs_sb, volume_info); - - if (rc) { - if (!silent) - cERROR(1, "cifs_mount failed w/return code = %d", rc); - return rc; - } - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) sb->s_flags |= MS_POSIXACL; @@ -692,6 +683,17 @@ cifs_do_mount(struct file_system_type *fs_type, cifs_setup_cifs_sb(volume_info, cifs_sb); + rc = cifs_mount(cifs_sb, volume_info); + if (rc) { + if (!(flags & MS_SILENT)) + cERROR(1, "cifs_mount failed w/return code = %d", rc); + root = ERR_PTR(rc); + unload_nls(volume_info->local_nls); + kfree(cifs_sb->mountdata); + kfree(cifs_sb); + goto out; + } + mnt_data.vol = volume_info; mnt_data.cifs_sb = cifs_sb; mnt_data.flags = flags; @@ -699,11 +701,13 @@ cifs_do_mount(struct file_system_type *fs_type, sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); if (IS_ERR(sb)) { root = ERR_CAST(sb); + cifs_umount(cifs_sb); goto out_cifs_sb; } if (sb->s_fs_info) { cFYI(1, "Use existing superblock"); + cifs_umount(cifs_sb); kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); @@ -715,8 +719,7 @@ cifs_do_mount(struct file_system_type *fs_type, sb->s_flags |= MS_NODIRATIME | MS_NOATIME; sb->s_fs_info = cifs_sb; - rc = cifs_read_super(sb, volume_info, dev_name, - flags & MS_SILENT ? 1 : 0); + rc = cifs_read_super(sb); if (rc) { root = ERR_PTR(rc); goto out_super; -- cgit v1.2.3 From 98ab494dd1d25388981114057cf9446250cc7dc7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:32:10 -0400 Subject: cifs: move cifs_umount() call into ->kill_sb() instead of calling it manually in case if cifs_read_super() fails to set ->s_root, just call it from ->kill_sb(). cifs_put_super() is gone now *and* we have cifs_sb shutdown and destruction done after the superblock is gone from ->s_instances. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4004bc647a72..15de4561dbc5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -163,30 +163,14 @@ out_no_root: if (inode) iput(inode); - cifs_umount(cifs_sb); return rc; } -static void -cifs_put_super(struct super_block *sb) -{ - int rc = 0; - struct cifs_sb_info *cifs_sb; - - cFYI(1, "In cifs_put_super"); - cifs_sb = CIFS_SB(sb); - if (cifs_sb == NULL) { - cFYI(1, "Empty cifs superblock info passed to unmount"); - return; - } - - cifs_umount(cifs_sb); -} - static void cifs_kill_sb(struct super_block *sb) { struct cifs_sb_info *cifs_sb = CIFS_SB(sb); kill_anon_super(sb); + cifs_umount(cifs_sb); kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); @@ -537,7 +521,6 @@ static int cifs_drop_inode(struct inode *inode) } static const struct super_operations cifs_super_ops = { - .put_super = cifs_put_super, .statfs = cifs_statfs, .alloc_inode = cifs_alloc_inode, .destroy_inode = cifs_destroy_inode, -- cgit v1.2.3 From d757d71bfc30669a500b72792067e8d1c5d401a5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:42:43 -0400 Subject: cifs: pull freeing mountdata/dropping nls/freeing cifs_sb into cifs_umount() all callers of cifs_umount() proceed to do the same thing; pull it into cifs_umount() itself. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 15 +-------------- fs/cifs/connect.c | 3 +++ 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 15de4561dbc5..46960b7ee433 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -171,9 +171,6 @@ static void cifs_kill_sb(struct super_block *sb) struct cifs_sb_info *cifs_sb = CIFS_SB(sb); kill_anon_super(sb); cifs_umount(cifs_sb); - kfree(cifs_sb->mountdata); - unload_nls(cifs_sb->local_nls); - kfree(cifs_sb); } static int @@ -685,15 +682,12 @@ cifs_do_mount(struct file_system_type *fs_type, if (IS_ERR(sb)) { root = ERR_CAST(sb); cifs_umount(cifs_sb); - goto out_cifs_sb; + goto out; } if (sb->s_fs_info) { cFYI(1, "Use existing superblock"); cifs_umount(cifs_sb); - kfree(cifs_sb->mountdata); - unload_nls(cifs_sb->local_nls); - kfree(cifs_sb); goto out_shared; } @@ -725,13 +719,6 @@ out_shared: out_super: deactivate_locked_super(sb); - goto out; - -out_cifs_sb: - kfree(cifs_sb->mountdata); - unload_nls(cifs_sb->local_nls); - kfree(cifs_sb); - out: cifs_cleanup_volume_info(&volume_info); return root; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index b2702226634e..ca7fbe3d51a5 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3362,6 +3362,9 @@ cifs_umount(struct cifs_sb_info *cifs_sb) spin_unlock(&cifs_sb->tlink_tree_lock); bdi_destroy(&cifs_sb->bdi); + kfree(cifs_sb->mountdata); + unload_nls(cifs_sb->local_nls); + kfree(cifs_sb); } int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) -- cgit v1.2.3 From ee01a14d9ddcf3f832f9ceb837888501cb496e27 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:47:23 -0400 Subject: cifs: close sget() races have ->s_fs_info set by the set() callback passed to sget() Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 46960b7ee433..ba2b2da360d3 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -629,6 +629,13 @@ out: return dparent; } +static int cifs_set_super(struct super_block *sb, void *data) +{ + struct cifs_mnt_data *mnt_data = data; + sb->s_fs_info = mnt_data->cifs_sb; + return set_anon_super(sb, NULL); +} + static struct dentry * cifs_do_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) @@ -678,14 +685,14 @@ cifs_do_mount(struct file_system_type *fs_type, mnt_data.cifs_sb = cifs_sb; mnt_data.flags = flags; - sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); + sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data); if (IS_ERR(sb)) { root = ERR_CAST(sb); cifs_umount(cifs_sb); goto out; } - if (sb->s_fs_info) { + if (sb->s_root) { cFYI(1, "Use existing superblock"); cifs_umount(cifs_sb); goto out_shared; @@ -694,7 +701,6 @@ cifs_do_mount(struct file_system_type *fs_type, sb->s_flags = flags; /* BB should we make this contingent on mount parm? */ sb->s_flags |= MS_NODIRATIME | MS_NOATIME; - sb->s_fs_info = cifs_sb; rc = cifs_read_super(sb); if (rc) { -- cgit v1.2.3 From fa18f1bdce898f0efd0c8639c901d826d01be04f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:50:44 -0400 Subject: cifs: more breakage on mount failures if cifs_get_root() fails, we end up with ->mount() returning NULL, which is not what callers expect. Moreover, in case of superblock reuse we end up leaking a superblock reference... Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ba2b2da360d3..234e9d08db76 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -710,19 +710,16 @@ cifs_do_mount(struct file_system_type *fs_type, sb->s_flags |= MS_ACTIVE; +out_shared: root = cifs_get_root(volume_info, sb); - if (root == NULL) + if (root == NULL) { + root = ERR_PTR(-EINVAL); /* XXX */ goto out_super; + } cFYI(1, "dentry root is: %p", root); goto out; -out_shared: - root = cifs_get_root(volume_info, sb); - if (root) - cFYI(1, "dentry root is: %p", root); - goto out; - out_super: deactivate_locked_super(sb); out: -- cgit v1.2.3 From 5c4f1ad7c6aa3b729bd3a93b80f9417d7e978c32 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:56:55 -0400 Subject: cifs: tidy cifs_do_mount() up a bit Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 234e9d08db76..9a6696a5eb78 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -656,16 +656,13 @@ cifs_do_mount(struct file_system_type *fs_type, cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); if (cifs_sb == NULL) { root = ERR_PTR(-ENOMEM); - unload_nls(volume_info->local_nls); - goto out; + goto out_nls; } cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); if (cifs_sb->mountdata == NULL) { root = ERR_PTR(-ENOMEM); - unload_nls(volume_info->local_nls); - kfree(cifs_sb); - goto out; + goto out_cifs_sb; } cifs_setup_cifs_sb(volume_info, cifs_sb); @@ -675,10 +672,7 @@ cifs_do_mount(struct file_system_type *fs_type, if (!(flags & MS_SILENT)) cERROR(1, "cifs_mount failed w/return code = %d", rc); root = ERR_PTR(rc); - unload_nls(volume_info->local_nls); - kfree(cifs_sb->mountdata); - kfree(cifs_sb); - goto out; + goto out_mountdata; } mnt_data.vol = volume_info; @@ -695,22 +689,20 @@ cifs_do_mount(struct file_system_type *fs_type, if (sb->s_root) { cFYI(1, "Use existing superblock"); cifs_umount(cifs_sb); - goto out_shared; - } - - sb->s_flags = flags; - /* BB should we make this contingent on mount parm? */ - sb->s_flags |= MS_NODIRATIME | MS_NOATIME; + } else { + sb->s_flags = flags; + /* BB should we make this contingent on mount parm? */ + sb->s_flags |= MS_NODIRATIME | MS_NOATIME; + + rc = cifs_read_super(sb); + if (rc) { + root = ERR_PTR(rc); + goto out_super; + } - rc = cifs_read_super(sb); - if (rc) { - root = ERR_PTR(rc); - goto out_super; + sb->s_flags |= MS_ACTIVE; } - sb->s_flags |= MS_ACTIVE; - -out_shared: root = cifs_get_root(volume_info, sb); if (root == NULL) { root = ERR_PTR(-EINVAL); /* XXX */ @@ -725,6 +717,14 @@ out_super: out: cifs_cleanup_volume_info(&volume_info); return root; + +out_mountdata: + kfree(cifs_sb->mountdata); +out_cifs_sb: + kfree(cifs_sb); +out_nls: + unload_nls(volume_info->local_nls); + goto out; } static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, -- cgit v1.2.3 From 9403c9c598e91d473c0582066e47ed2289292e45 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 10:02:59 -0400 Subject: cifs: propagate errors from cifs_get_root() to mount(2) ... instead of just failing with -EINVAL Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9a6696a5eb78..35f9154615fa 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -554,7 +554,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) full_path = cifs_build_path_to_root(vol, cifs_sb, cifs_sb_master_tcon(cifs_sb)); if (full_path == NULL) - return NULL; + return ERR_PTR(-ENOMEM); cFYI(1, "Get root dentry for %s", full_path); @@ -583,7 +583,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dchild = d_alloc(dparent, &name); if (dchild == NULL) { dput(dparent); - dparent = NULL; + dparent = ERR_PTR(-ENOMEM); goto out; } } @@ -601,7 +601,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) if (rc) { dput(dchild); dput(dparent); - dparent = NULL; + dparent = ERR_PTR(rc); goto out; } alias = d_materialise_unique(dchild, inode); @@ -609,7 +609,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dput(dchild); if (IS_ERR(alias)) { dput(dparent); - dparent = NULL; + dparent = ERR_PTR(-EINVAL); /* XXX */ goto out; } dchild = alias; @@ -704,10 +704,8 @@ cifs_do_mount(struct file_system_type *fs_type, } root = cifs_get_root(volume_info, sb); - if (root == NULL) { - root = ERR_PTR(-EINVAL); /* XXX */ + if (IS_ERR(root)) goto out_super; - } cFYI(1, "dentry root is: %p", root); goto out; -- cgit v1.2.3 From a6b3ff9f0d7275e9e2ba3295f585d01f99aeb295 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 21 Jun 2011 03:13:03 +0000 Subject: MAINTAINERS: Remove Sven Eckelmann from BATMAN ADVANCED I cannot speak on behalf of the batman-adv developers due to conflicts in the opinion about the ongoing development. The batman-adv module is still maintained by Marek Lindner and Simon Wunderlich. Those are the main persons behind the visions of batman-adv. Therefore, the state of module hasn't changed. Signed-off-by: Sven Eckelmann Cc: b.a.t.m.a.n@lists.open-mesh.org Signed-off-by: David S. Miller --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index f0358cd91de3..3e112ee413c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1390,7 +1390,6 @@ F: include/linux/backlight.h BATMAN ADVANCED M: Marek Lindner M: Simon Wunderlich -M: Sven Eckelmann L: b.a.t.m.a.n@lists.open-mesh.org W: http://www.open-mesh.org/ S: Maintained -- cgit v1.2.3 From 7cacd43cdd2e4ebba9574635f05538f4053fd725 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 24 Jun 2011 17:42:14 -0700 Subject: MAINTAINERS: mark socketcan-core lists as subscribers-only The socketcan-core lists require subscription, so mark them as such. Signed-off-by: Mike Frysinger Signed-off-by: David S. Miller --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3e112ee413c8..03bf50c603d5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1638,7 +1638,7 @@ CAN NETWORK LAYER M: Oliver Hartkopp M: Oliver Hartkopp M: Urs Thuermann -L: socketcan-core@lists.berlios.de +L: socketcan-core@lists.berlios.de (subscribers-only) L: netdev@vger.kernel.org W: http://developer.berlios.de/projects/socketcan/ S: Maintained @@ -1650,7 +1650,7 @@ F: include/linux/can/raw.h CAN NETWORK DRIVERS M: Wolfgang Grandegger -L: socketcan-core@lists.berlios.de +L: socketcan-core@lists.berlios.de (subscribers-only) L: netdev@vger.kernel.org W: http://developer.berlios.de/projects/socketcan/ S: Maintained -- cgit v1.2.3 From b997d79a91f7b6be952b98cf9d9585b124558f5b Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 22 Jun 2011 06:35:45 +0000 Subject: qlge: Add maintainer. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03bf50c603d5..05aaf9221ad7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5180,6 +5180,7 @@ S: Supported F: drivers/net/qlcnic/ QLOGIC QLGE 10Gb ETHERNET DRIVER +M: Jitendra Kalsaria M: Ron Mercer M: linux-driver@qlogic.com L: netdev@vger.kernel.org -- cgit v1.2.3 From bd4265fe365c0f3945dd5ff1527e52bbe2bedfa2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 23 Jun 2011 02:39:12 +0000 Subject: bridge: Only flood unregistered groups to routers The bridge currently floods packets to groups that we have never seen before to all ports. This is not required by RFC4541 and in fact it is not desirable in environment where traffic to unregistered group is always present. This patch changes the behaviour so that we only send traffic to unregistered groups to ports marked as routers. The user can always force flooding behaviour to any given port by marking it as a router. Note that this change does not apply to traffic to 224.0.0.X as traffic to those groups must always be flooded to all ports. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 29b9812c8da0..2d85ca7111d3 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1379,8 +1379,11 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) return -EINVAL; - if (iph->protocol != IPPROTO_IGMP) + if (iph->protocol != IPPROTO_IGMP) { + if ((iph->daddr & IGMP_LOCAL_GROUP_MASK) != IGMP_LOCAL_GROUP) + BR_INPUT_SKB_CB(skb)->mrouters_only = 1; return 0; + } len = ntohs(iph->tot_len); if (skb->len < len || len < ip_hdrlen(skb)) -- cgit v1.2.3 From d6fe5f4eccc2a7d2ad885ecb26a192b08dcc7cd1 Mon Sep 17 00:00:00 2001 From: "John (Jay) Hernandez" Date: Thu, 23 Jun 2011 14:39:12 +0000 Subject: cxgb3: skb_record_rx_queue now records the queue index relative to the net_device. Fixed call to skb_record_rx_queue where we were passing the queue index relative to the adapter when it should have been relative to the net_device. Signed-off-by: John (Jay) Hernandez Signed-off-by: Divy Le Ray Reported-by: Shawn Bohrer Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 3f562ba2f0c9..76bf5892b962 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2026,7 +2026,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, skb->ip_summed = CHECKSUM_UNNECESSARY; } else skb_checksum_none_assert(skb); - skb_record_rx_queue(skb, qs - &adap->sge.qs[0]); + skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]); if (unlikely(p->vlan_valid)) { struct vlan_group *grp = pi->vlan_grp; @@ -2145,7 +2145,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, if (!complete) return; - skb_record_rx_queue(skb, qs - &adap->sge.qs[0]); + skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]); if (unlikely(cpl->vlan_valid)) { struct vlan_group *grp = pi->vlan_grp; -- cgit v1.2.3 From 5c1f9668692061b97125e343721c7514ca05a8bb Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 21 Jun 2011 11:24:33 +0800 Subject: at91: fix at91_set_serial_console: use platform device id Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/mach-at91/at91cap9_devices.c | 2 +- arch/arm/mach-at91/at91rm9200_devices.c | 2 +- arch/arm/mach-at91/at91sam9260_devices.c | 2 +- arch/arm/mach-at91/at91sam9261_devices.c | 2 +- arch/arm/mach-at91/at91sam9263_devices.c | 2 +- arch/arm/mach-at91/at91sam9g45_devices.c | 2 +- arch/arm/mach-at91/at91sam9rl_devices.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c index cd850ed6f335..dba0d8d8a4bd 100644 --- a/arch/arm/mach-at91/at91cap9_devices.c +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -1220,7 +1220,7 @@ void __init at91_set_serial_console(unsigned portnr) { if (portnr < ATMEL_MAX_UART) { atmel_default_console_device = at91_uarts[portnr]; - at91cap9_set_console_clock(portnr); + at91cap9_set_console_clock(at91_uarts[portnr]->id); } } diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index a0ba475be04c..7227755ffec6 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -1135,7 +1135,7 @@ void __init at91_set_serial_console(unsigned portnr) { if (portnr < ATMEL_MAX_UART) { atmel_default_console_device = at91_uarts[portnr]; - at91rm9200_set_console_clock(portnr); + at91rm9200_set_console_clock(at91_uarts[portnr]->id); } } diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 1fdeb9058a76..39f81f47b4ba 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -1173,7 +1173,7 @@ void __init at91_set_serial_console(unsigned portnr) { if (portnr < ATMEL_MAX_UART) { atmel_default_console_device = at91_uarts[portnr]; - at91sam9260_set_console_clock(portnr); + at91sam9260_set_console_clock(at91_uarts[portnr]->id); } } diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 3eb4538fceeb..5004bf0a05f2 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -1013,7 +1013,7 @@ void __init at91_set_serial_console(unsigned portnr) { if (portnr < ATMEL_MAX_UART) { atmel_default_console_device = at91_uarts[portnr]; - at91sam9261_set_console_clock(portnr); + at91sam9261_set_console_clock(at91_uarts[portnr]->id); } } diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index ffe081b77ed0..a050f41fc860 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -1395,7 +1395,7 @@ void __init at91_set_serial_console(unsigned portnr) { if (portnr < ATMEL_MAX_UART) { atmel_default_console_device = at91_uarts[portnr]; - at91sam9263_set_console_clock(portnr); + at91sam9263_set_console_clock(at91_uarts[portnr]->id); } } diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 05674865bc21..600bffb01edb 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -1550,7 +1550,7 @@ void __init at91_set_serial_console(unsigned portnr) { if (portnr < ATMEL_MAX_UART) { atmel_default_console_device = at91_uarts[portnr]; - at91sam9g45_set_console_clock(portnr); + at91sam9g45_set_console_clock(at91_uarts[portnr]->id); } } diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index c296045f2b6a..aacb19dc9225 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -1168,7 +1168,7 @@ void __init at91_set_serial_console(unsigned portnr) { if (portnr < ATMEL_MAX_UART) { atmel_default_console_device = at91_uarts[portnr]; - at91sam9rl_set_console_clock(portnr); + at91sam9rl_set_console_clock(at91_uarts[portnr]->id); } } -- cgit v1.2.3 From deba1a0d58b54905a5201cb9e1aa878cfc74ff70 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 21 Jun 2011 12:17:00 +0800 Subject: atmel_serial: fix internal port num the atmel_ports is link to the console number and not the device id this was not detected on at91 as we always register the dbgu on the console as ttyS0 tested on at91sam9263 by setting the dbgu as ttyS1 and use as console diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 70e5646..9b8a14f 100644 - a/arch/arm/mach-at91/board-sam9263ek.c + b/arch/arm/mach-at91/board-sam9263ek.c @@ -58,14 +58,14 @@ static void __init ek_init_early(void) /* Initialize processor: 16.367 MHz crystal */ at91_initialize(16367660); - /* DBGU on ttyS0. (Rx & Tx only) */ - at91_register_uart(0, 0, 0); + /* DBGU on ttyS1. (Rx & Tx only) */ + at91_register_uart(0, 1, 0); - /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */ - at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS); + /* USART0 on ttyS0. (Rx, Tx, RTS, CTS) */ + at91_register_uart(AT91SAM9263_ID_US0, 0, ATMEL_UART_CTS | ATMEL_UART_RTS); - /* set serial console to ttyS0 (ie, DBGU) */ - at91_set_serial_console(0); + /* set serial console to ttyS1 (ie, DBGU) */ + at91_set_serial_console(1); } /* Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Cc: Alan Cox Cc: Hans-Christian Egtvedt --- drivers/tty/serial/atmel_serial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 6d5d6e679fc7..af9b7814965a 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1709,12 +1709,13 @@ static int atmel_serial_resume(struct platform_device *pdev) static int __devinit atmel_serial_probe(struct platform_device *pdev) { struct atmel_uart_port *port; + struct atmel_uart_data *pdata = pdev->dev.platform_data; void *data; int ret; BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); - port = &atmel_ports[pdev->id]; + port = &atmel_ports[pdata->num]; port->backup_imr = 0; atmel_init_port(port, pdev); -- cgit v1.2.3 From 9d87159e571d73ccf87adf1ee3691b861253d900 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 21 Jun 2011 14:24:33 +0800 Subject: at91: fix udc, ehci and mmc clock device name for cap9/9g45/9rl Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Nicolas Ferre --- arch/arm/mach-at91/at91cap9.c | 4 ++-- arch/arm/mach-at91/at91sam9g45.c | 10 +++++----- arch/arm/mach-at91/at91sam9rl.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c index 17fae4a42ab5..5e6f8a7958a4 100644 --- a/arch/arm/mach-at91/at91cap9.c +++ b/arch/arm/mach-at91/at91cap9.c @@ -223,8 +223,8 @@ static struct clk *periph_clocks[] __initdata = { }; static struct clk_lookup periph_clocks_lookups[] = { - CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk), - CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk), + CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk), + CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk), CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk), CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk), diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 2bb6ff9af1c7..11e214121b23 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -217,11 +217,11 @@ static struct clk *periph_clocks[] __initdata = { static struct clk_lookup periph_clocks_lookups[] = { /* One additional fake clock for ohci */ CLKDEV_CON_ID("ohci_clk", &uhphs_clk), - CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci.0", &uhphs_clk), - CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk), - CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk), - CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk), - CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk), + CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk), + CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk), + CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk), + CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk), + CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk), diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index 1a40f16b66c8..29dff18ed130 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -191,8 +191,8 @@ static struct clk *periph_clocks[] __initdata = { }; static struct clk_lookup periph_clocks_lookups[] = { - CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk), - CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk), + CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk), + CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk), CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk), CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk), -- cgit v1.2.3 From c5efefac659870744f6e203e28abd095ac0f590b Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Thu, 2 Jun 2011 01:36:09 +0200 Subject: at91: Use "pclk" as con_id on at91cap9 and at91rm9200 Hello, I am not 100% sure this is the right thing to do, but it makes the atmel-ssc driver happy on my at91rm9200 board. This unifies the con_id across all at91 machines. The atmel-ssc driver expects the con_id to be "pclk" or it will fail probing. Signed-off-by: Joachim Eastwood Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/mach-at91/at91cap9.c | 4 ++-- arch/arm/mach-at91/at91rm9200.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c index 5e6f8a7958a4..f1013d08bb57 100644 --- a/arch/arm/mach-at91/at91cap9.c +++ b/arch/arm/mach-at91/at91cap9.c @@ -230,8 +230,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk), - CLKDEV_CON_DEV_ID("ssc", "ssc.0", &ssc0_clk), - CLKDEV_CON_DEV_ID("ssc", "ssc.1", &ssc1_clk), + CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), + CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), }; static struct clk_lookup usart_clocks_lookups[] = { diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index b228ce9e21a1..83a1a3fee554 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -199,9 +199,9 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk), CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk), CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk), - CLKDEV_CON_DEV_ID("ssc", "ssc.0", &ssc0_clk), - CLKDEV_CON_DEV_ID("ssc", "ssc.1", &ssc1_clk), - CLKDEV_CON_DEV_ID("ssc", "ssc.2", &ssc2_clk), + CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), + CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), + CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), }; static struct clk_lookup usart_clocks_lookups[] = { -- cgit v1.2.3 From e0f5406727f1dfdc47b8ba4a0ff6eae4b0b5ed4c Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Sat, 18 Jun 2011 20:26:38 +0000 Subject: Btrfs: fix type mismatch in find_free_extent() data parameter should be u64 because a full-sized chunk flags field is passed instead of 0/1 for distinguishing data from metadata. All underlying functions expect u64. Signed-off-by: Ilya Dryomov Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 1f61bf5b4960..71cd456fdb60 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4842,7 +4842,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, u64 num_bytes, u64 empty_size, u64 search_start, u64 search_end, u64 hint_byte, struct btrfs_key *ins, - int data) + u64 data) { int ret = 0; struct btrfs_root *root = orig_root->fs_info->extent_root; @@ -4869,7 +4869,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, space_info = __find_space_info(root->fs_info, data); if (!space_info) { - printk(KERN_ERR "No space info for %d\n", data); + printk(KERN_ERR "No space info for %llu\n", data); return -ENOSPC; } -- cgit v1.2.3 From 9b90f5135320bc74dc6c9a8c74d69fd4821d9282 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 24 Jun 2011 16:02:51 +0000 Subject: Btrfs: make sure to update total_bitmaps when freeing cache V3 A user reported this bug again where we have more bitmaps than we are supposed to. This is because we failed to load the free space cache, but don't update the ctl->total_bitmaps counter when we remove entries from the tree. This patch fixes this problem and we should be good to go again. Thanks, Signed-off-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 9f985a429877..bf0d61567f3d 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1893,9 +1893,12 @@ void __btrfs_remove_free_space_cache_locked(struct btrfs_free_space_ctl *ctl) while ((node = rb_last(&ctl->free_space_offset)) != NULL) { info = rb_entry(node, struct btrfs_free_space, offset_index); - unlink_free_space(ctl, info); - kfree(info->bitmap); - kmem_cache_free(btrfs_free_space_cachep, info); + if (!info->bitmap) { + unlink_free_space(ctl, info); + kmem_cache_free(btrfs_free_space_cachep, info); + } else { + free_bitmap(ctl, info); + } if (need_resched()) { spin_unlock(&ctl->tree_lock); cond_resched(); -- cgit v1.2.3 From 297c7f2f158f7dfa9ab5813260ff954f9c2f83d2 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Thu, 9 Jun 2011 23:40:27 +0000 Subject: mmc: sdio: fix runtime PM path during driver removal After commit e1866b3 "PM / Runtime: Rework runtime PM handling during driver removal" was introduced, the driver core stopped incrementing the runtime PM usage counter of the device during the invocation of the ->remove() callback. This indirectly broke SDIO's runtime PM path during driver removal, because no one calls _put_sync() anymore after ->remove() completes. This means that the power of runtime-PM-managed SDIO cards is kept high after their driver is removed (even if it was powered down beforehand). Fix that by directly calling _put_sync() when the last usage counter is downref'ed by the SDIO bus. Reported-and-tested-by: Daniel Drake Signed-off-by: Ohad Ben-Cohen Signed-off-by: Chris Ball --- drivers/mmc/core/sdio_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index d29b9c36919a..d2565df8a7fb 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -189,7 +189,7 @@ static int sdio_bus_remove(struct device *dev) /* Then undo the runtime PM settings in sdio_bus_probe() */ if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) - pm_runtime_put_noidle(dev); + pm_runtime_put_sync(dev); out: return ret; -- cgit v1.2.3 From 4a3dc6ef344ccfe80bf986aec0b05f51af000720 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Tue, 14 Jun 2011 15:59:59 +0530 Subject: mmc: omap_hsmmc: fix ocr mask usage The OMAP HSMMC driver uses an ocr_mask to determine the list of voltages supported by the card. It populates this mask based on the list of voltages supported by the regulator that supplies the voltage. Commit 64be97822b (omap4 hsmmc: Update ocr mask for MMC2 for regulator to use) passed a fixed ocr_mask from the OMAP4 SDP board file to limit the voltage to 2.9-3.0 Volts, and updated the driver to use this mask if provided, instead of using the regulator's supported voltages. However the commit is buggy - the ocr_mask is overridden by the regulator's capabilities anyway. Fix this. (The bug shows up when a system-wide suspend is attempted on the OMAP4 SDP/Blaze platforms. The eMMC card comes up at 3V, but drops to 1.65V after the system resumes). Signed-off-by: Anand Gadiyar Acked-by: Balaji T K Acked-by: Venkatraman S Tested-by: Kishore Kadiyala Signed-off-by: Sourav Poddar Signed-off-by: Chris Ball --- drivers/mmc/host/omap_hsmmc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5b2e2155b413..8707bcdebc43 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -429,7 +429,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) return -EINVAL; } } - mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg); /* Allow an aux regulator */ reg = regulator_get(host->dev, "vmmc_aux"); -- cgit v1.2.3 From a9120c33ffbb0b3448d833dae392edc90d6cfac2 Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Fri, 17 Jun 2011 20:14:21 +0200 Subject: mmc: omap_hsmmc: use original sg_len for dma_unmap_sg Don't use the returned sg_len from dma_map_sg() as inparameter to dma_unmap_sg(). Use the original sg_len for both dma_map_sg and dma_unmap_sg according to the documentation in DMA-API.txt. Signed-off-by: Per Forlin Reviewed-by: Venkatraman S Signed-off-by: Chris Ball --- drivers/mmc/host/omap_hsmmc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 8707bcdebc43..dedf3dab8a3b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -961,7 +961,8 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) spin_unlock(&host->irq_lock); if (host->use_dma && dma_ch != -1) { - dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, + dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, + host->data->sg_len, omap_hsmmc_get_dma_dir(host, host->data)); omap_free_dma(dma_ch); } @@ -1345,7 +1346,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) return; } - dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, omap_hsmmc_get_dma_dir(host, data)); req_in_progress = host->req_in_progress; -- cgit v1.2.3 From 7d8b4c2a4b73da8e3632603691838ca5b2a8c26d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 20 Jun 2011 16:51:10 +0200 Subject: mmc: tmio: fix regression in TMIO_MMC_WRPROTECT_DISABLE handling Commit b6147490e6aac82 ("mmc: tmio: split core functionality, DMA and MFD glue") broke handling of the TMIO_MMC_WRPROTECT_DISABLE flag by the tmio-mmc driver. This patch restores the original behaviour. Signed-off-by: Guennadi Liakhovetski Cc: Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc_pio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index ad6347bb02dd..0b09e8239aa0 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -824,8 +824,8 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc) struct tmio_mmc_host *host = mmc_priv(mmc); struct tmio_mmc_data *pdata = host->pdata; - return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || - !(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); + return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || + (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); } static int tmio_mmc_get_cd(struct mmc_host *mmc) -- cgit v1.2.3 From 3e713373ce07b9f59c3901e7d39bc1edccda28da Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 24 May 2011 12:24:07 +0200 Subject: mmc: sdhi: DMA slave ID 0 is invalid Don't try to allocate DMA resources if the platform didn't specify positive DMA slave IDs. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mobile_sdhi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 2353bb797d6c..ce500f03df85 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -92,7 +92,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) mmc_data->ocr_mask = p->tmio_ocr_mask; mmc_data->capabilities |= p->tmio_caps; - if (p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) { + if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { priv->param_tx.slave_id = p->dma_slave_tx; priv->param_rx.slave_id = p->dma_slave_rx; priv->dma_priv.chan_priv_tx = &priv->param_tx; -- cgit v1.2.3 From e9e8bcb8178e197d889ec31e79fa1ddc1732c8f9 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 21 Jun 2011 10:55:34 +0100 Subject: mmc: cb710: fix #ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HAVE_EFFICIENT_UNALIGNED_ACCESS is a config option, therefore it needs the CONFIG_ before it when used by the preprocessor. Signed-off-by: James Hogan Acked-by: Michał Mirosław Signed-off-by: Chris Ball --- drivers/misc/cb710/sgbuf2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/cb710/sgbuf2.c b/drivers/misc/cb710/sgbuf2.c index d019746551f3..2a40d0efdff5 100644 --- a/drivers/misc/cb710/sgbuf2.c +++ b/drivers/misc/cb710/sgbuf2.c @@ -47,7 +47,7 @@ static uint32_t sg_dwiter_read_buffer(struct sg_mapping_iter *miter) static inline bool needs_unaligned_copy(const void *ptr) { -#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS return false; #else return ((ptr - NULL) & 3) != 0; -- cgit v1.2.3 From c6e633ad916e2af244dbfd11abd2bc077870bdfd Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sat, 25 Jun 2011 19:20:11 +0100 Subject: mmc: sdio: reset card during power_restore mmc_sdio_power_restore() skips some steps that are performed in other power-related codepaths which are necessary to fully reset the card. Without this, runtime PM fails for SD8686 SDIO wifi on OLPC XO-1.5. Signed-off-by: Daniel Drake Signed-off-by: Chris Ball --- drivers/mmc/core/sdio.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 4d0c15bfa514..262fff019177 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -691,15 +691,54 @@ static int mmc_sdio_resume(struct mmc_host *host) static int mmc_sdio_power_restore(struct mmc_host *host) { int ret; + u32 ocr; BUG_ON(!host); BUG_ON(!host->card); mmc_claim_host(host); + + /* + * Reset the card by performing the same steps that are taken by + * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. + * + * sdio_reset() is technically not needed. Having just powered up the + * hardware, it should already be in reset state. However, some + * platforms (such as SD8686 on OLPC) do not instantly cut power, + * meaning that a reset is required when restoring power soon after + * powering off. It is harmless in other cases. + * + * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec, + * is not necessary for non-removable cards. However, it is required + * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and + * harmless in other situations. + * + * With these steps taken, mmc_select_voltage() is also required to + * restore the correct voltage setting of the card. + */ + sdio_reset(host); + mmc_go_idle(host); + mmc_send_if_cond(host, host->ocr_avail); + + ret = mmc_send_io_op_cond(host, 0, &ocr); + if (ret) + goto out; + + if (host->ocr_avail_sdio) + host->ocr_avail = host->ocr_avail_sdio; + + host->ocr = mmc_select_voltage(host, ocr & ~0x7F); + if (!host->ocr) { + ret = -EINVAL; + goto out; + } + ret = mmc_sdio_init_card(host, host->ocr, host->card, mmc_card_keep_power(host)); if (!ret && host->sdio_irqs) mmc_signal_sdio_irq(host); + +out: mmc_release_host(host); return ret; -- cgit v1.2.3 From ddd6fa7e794e62af3ec3eb4ffdc78489885701f2 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 23 Jun 2011 13:40:26 +0300 Subject: mmc: block: switch card to User Data Area when removing the block driver The MMC block driver and other drivers (e.g. mmc-test) will expect the card to be switched to the User Data Area eMMC partition when they start. Hence the MMC block driver should ensure it is that way when it is removed. Signed-off-by: Adrian Hunter Cc: Andrei Warkentin Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 71da5641e258..77cd083a51e4 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1297,6 +1297,9 @@ static void mmc_blk_remove(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); mmc_blk_remove_parts(card, md); + mmc_claim_host(card->host); + mmc_blk_part_switch(card, md); + mmc_release_host(card->host); mmc_blk_remove_req(md); mmc_set_drvdata(card, NULL); } -- cgit v1.2.3 From 4cf8c6dd2e261da94b87c4deadcc136ab022b6ac Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 23 Jun 2011 13:40:27 +0300 Subject: mmc: core: make erase timeout calculation allow for gated clock The erase timeout calculation may depend on clock rate which is zero if the clock is gated, so use mmc_host_clk_rate() which allows for that case. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 68091dda3f31..7843efe22359 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1245,7 +1245,7 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card, */ timeout_clks <<= 1; timeout_us += (timeout_clks * 1000) / - (card->host->ios.clock / 1000); + (mmc_host_clk_rate(card->host) / 1000); erase_timeout = timeout_us / 1000; -- cgit v1.2.3 From d09408ade08a08a710a247fb52aa50101e73ebf7 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 23 Jun 2011 13:40:28 +0300 Subject: mmc: queue: append partition subname to queue thread name For example, an eMMC with 2 boot partitions will have 3 threads. The names change from: 40 ? 00:00:00 mmcqd/0 41 ? 00:00:00 mmcqd/0 42 ? 00:00:00 mmcqd/0 to: 40 ? 00:00:00 mmcqd/0 41 ? 00:00:00 mmcqd/0boot0 42 ? 00:00:00 mmcqd/0boot1 Signed-off-by: Adrian Hunter Cc: Andrei Warkentin Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 2 +- drivers/mmc/card/queue.c | 8 +++++--- drivers/mmc/card/queue.h | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 77cd083a51e4..f85e42224559 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1024,7 +1024,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, INIT_LIST_HEAD(&md->part); md->usage = 1; - ret = mmc_init_queue(&md->queue, card, &md->lock); + ret = mmc_init_queue(&md->queue, card, &md->lock, subname); if (ret) goto err_putdisk; diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index c07322c2658c..3e2db1cf1cbb 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -106,10 +106,12 @@ static void mmc_request(struct request_queue *q) * @mq: mmc queue * @card: mmc card to attach this queue * @lock: queue lock + * @subname: partition subname * * Initialise a MMC card request queue. */ -int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock) +int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + spinlock_t *lock, const char *subname) { struct mmc_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; @@ -209,8 +211,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock sema_init(&mq->thread_sem, 1); - mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d", - host->index); + mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s", + host->index, subname ? subname : ""); if (IS_ERR(mq->thread)) { ret = PTR_ERR(mq->thread); diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index 64e66e0d4994..6223ef8dc9cd 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -19,7 +19,8 @@ struct mmc_queue { unsigned int bounce_sg_len; }; -extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *); +extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *, + const char *); extern void mmc_cleanup_queue(struct mmc_queue *); extern void mmc_queue_suspend(struct mmc_queue *); extern void mmc_queue_resume(struct mmc_queue *); -- cgit v1.2.3 From c31b55cd4eaf050bb5a15bd8251da1b3c7edeb1c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 23 Jun 2011 13:40:29 +0300 Subject: mmc: queue: bring discard_granularity/alignment into line with SCSI SCSI defines discard alignment as the offset to the first optimal discard. In the case of SD/MMC, that is always zero which is the default. SCSI defines discard granularity as a hint of a optimal discard size. That is much better expressed by the MMC "preferred erase size" (pref_erase) field. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/card/queue.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 3e2db1cf1cbb..6413afa318d2 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -135,12 +135,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, mq->queue->limits.max_discard_sectors = UINT_MAX; if (card->erased_byte == 0) mq->queue->limits.discard_zeroes_data = 1; - if (!mmc_can_trim(card) && is_power_of_2(card->erase_size)) { - mq->queue->limits.discard_granularity = - card->erase_size << 9; - mq->queue->limits.discard_alignment = - card->erase_size << 9; - } + mq->queue->limits.discard_granularity = card->pref_erase << 9; if (mmc_can_secure_erase_trim(card)) queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, mq->queue); -- cgit v1.2.3 From 8c9f3aaf8e174ca914889ab7a916586f8fd1e641 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 16 Jun 2011 09:19:13 -0700 Subject: drm/i915: split page flip queueing into per-chipset functions This makes things a little clearer and prevents us from running old code on a new chipset that may not be supported. Signed-off-by: Jesse Barnes Reviewied-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/intel_display.c | 269 ++++++++++++++++++++++++----------- 2 files changed, 189 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f63ee162f124..eddabf68e97a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -211,6 +211,9 @@ struct drm_i915_display_funcs { void (*fdi_link_train)(struct drm_crtc *crtc); void (*init_clock_gating)(struct drm_device *dev); void (*init_pch_clock_gating)(struct drm_device *dev); + int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj); /* clock updates for mode set */ /* cursor updates */ /* render clock increase/decrease */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index aa43e7be6053..0f4ed2a575a4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6261,6 +6261,164 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane) spin_unlock_irqrestore(&dev->event_lock, flags); } +static int intel_gen2_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + unsigned long offset; + u32 flip_mask; + int ret; + + ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); + if (ret) + goto out; + + /* Offset into the new buffer for cases of shared fbs between CRTCs */ + offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; + + ret = BEGIN_LP_RING(6); + if (ret) + goto out; + + /* Can't queue multiple flips, so wait for the previous + * one to finish before executing the next. + */ + if (intel_crtc->plane) + flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; + else + flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; + OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); + OUT_RING(MI_NOOP); + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); + OUT_RING(obj->gtt_offset + offset); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); +out: + return ret; +} + +static int intel_gen3_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + unsigned long offset; + u32 flip_mask; + int ret; + + ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); + if (ret) + goto out; + + /* Offset into the new buffer for cases of shared fbs between CRTCs */ + offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; + + ret = BEGIN_LP_RING(6); + if (ret) + goto out; + + if (intel_crtc->plane) + flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; + else + flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; + OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); + OUT_RING(MI_NOOP); + OUT_RING(MI_DISPLAY_FLIP_I915 | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); + OUT_RING(obj->gtt_offset + offset); + OUT_RING(MI_NOOP); + + ADVANCE_LP_RING(); +out: + return ret; +} + +static int intel_gen4_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + uint32_t pf, pipesrc; + int ret; + + ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); + if (ret) + goto out; + + ret = BEGIN_LP_RING(4); + if (ret) + goto out; + + /* i965+ uses the linear or tiled offsets from the + * Display Registers (which do not change across a page-flip) + * so we need only reprogram the base address. + */ + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); + OUT_RING(obj->gtt_offset | obj->tiling_mode); + + /* XXX Enabling the panel-fitter across page-flip is so far + * untested on non-native modes, so ignore it for now. + * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; + */ + pf = 0; + pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; + OUT_RING(pf | pipesrc); + ADVANCE_LP_RING(); +out: + return ret; +} + +static int intel_gen6_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + uint32_t pf, pipesrc; + int ret; + + ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); + if (ret) + goto out; + + ret = BEGIN_LP_RING(4); + if (ret) + goto out; + + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch | obj->tiling_mode); + OUT_RING(obj->gtt_offset); + + pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE; + pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; + OUT_RING(pf | pipesrc); + ADVANCE_LP_RING(); +out: + return ret; +} + +static int intel_default_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj) +{ + return -ENODEV; +} + static int intel_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event) @@ -6271,9 +6429,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, struct drm_i915_gem_object *obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; - unsigned long flags, offset; - int pipe = intel_crtc->pipe; - u32 pf, pipesrc; + unsigned long flags; int ret; work = kzalloc(sizeof *work, GFP_KERNEL); @@ -6302,9 +6458,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, obj = intel_fb->obj; mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); - if (ret) - goto cleanup_work; /* Reference the objects for the scheduled work. */ drm_gem_object_reference(&work->old_fb_obj->base); @@ -6316,91 +6469,18 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup_objs; - if (IS_GEN3(dev) || IS_GEN2(dev)) { - u32 flip_mask; - - /* Can't queue multiple flips, so wait for the previous - * one to finish before executing the next. - */ - ret = BEGIN_LP_RING(2); - if (ret) - goto cleanup_objs; - - if (intel_crtc->plane) - flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; - else - flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); - } - work->pending_flip_obj = obj; work->enable_stall_check = true; - /* Offset into the new buffer for cases of shared fbs between CRTCs */ - offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; - - ret = BEGIN_LP_RING(4); - if (ret) - goto cleanup_objs; - /* Block clients from rendering to the new back buffer until * the flip occurs and the object is no longer visible. */ atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); - switch (INTEL_INFO(dev)->gen) { - case 2: - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitch); - OUT_RING(obj->gtt_offset + offset); - OUT_RING(MI_NOOP); - break; - - case 3: - OUT_RING(MI_DISPLAY_FLIP_I915 | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitch); - OUT_RING(obj->gtt_offset + offset); - OUT_RING(MI_NOOP); - break; - - case 4: - case 5: - /* i965+ uses the linear or tiled offsets from the - * Display Registers (which do not change across a page-flip) - * so we need only reprogram the base address. - */ - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitch); - OUT_RING(obj->gtt_offset | obj->tiling_mode); - - /* XXX Enabling the panel-fitter across page-flip is so far - * untested on non-native modes, so ignore it for now. - * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; - */ - pf = 0; - pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff; - OUT_RING(pf | pipesrc); - break; - - case 6: - case 7: - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitch | obj->tiling_mode); - OUT_RING(obj->gtt_offset); - - pf = I915_READ(PF_CTL(pipe)) & PF_ENABLE; - pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff; - OUT_RING(pf | pipesrc); - break; - } - ADVANCE_LP_RING(); + ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); + if (ret) + goto cleanup_pending; mutex_unlock(&dev->struct_mutex); @@ -6408,10 +6488,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, return 0; +cleanup_pending: + atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); cleanup_objs: drm_gem_object_unreference(&work->old_fb_obj->base); drm_gem_object_unreference(&obj->base); -cleanup_work: mutex_unlock(&dev->struct_mutex); spin_lock_irqsave(&dev->event_lock, flags); @@ -7656,6 +7737,28 @@ static void intel_init_display(struct drm_device *dev) else dev_priv->display.get_fifo_size = i830_get_fifo_size; } + + /* Default just returns -ENODEV to indicate unsupported */ + dev_priv->display.queue_flip = intel_default_queue_flip; + + switch (INTEL_INFO(dev)->gen) { + case 2: + dev_priv->display.queue_flip = intel_gen2_queue_flip; + break; + + case 3: + dev_priv->display.queue_flip = intel_gen3_queue_flip; + break; + + case 4: + case 5: + dev_priv->display.queue_flip = intel_gen4_queue_flip; + break; + + case 6: + dev_priv->display.queue_flip = intel_gen6_queue_flip; + break; + } } /* -- cgit v1.2.3 From 7c9017e5b77118439952fe8dc22809bae4fae4b6 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 16 Jun 2011 12:18:54 -0700 Subject: drm/i915: add Ivy Bridge page flip support Use the blit ring for submitting flips since the render ring doesn't generate flip complete interrupts. Fixes bugs: https://bugs.freedesktop.org/show_bug.cgi?id=38362 https://bugs.freedesktop.org/show_bug.cgi?id=38392 https://bugs.freedesktop.org/show_bug.cgi?id=38393 Signed-off-by: Jesse Barnes Reviewed-by: Daniel Vetter Reviewed-by: Kenneth Graunke Reviewed-by: Ben Widawsky Tested-by: Jian J Zhao Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0f4ed2a575a4..21b6f93fe919 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6411,6 +6411,39 @@ out: return ret; } +/* + * On gen7 we currently use the blit ring because (in early silicon at least) + * the render ring doesn't give us interrpts for page flip completion, which + * means clients will hang after the first flip is queued. Fortunately the + * blit ring generates interrupts properly, so use it instead. + */ +static int intel_gen7_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; + int ret; + + ret = intel_pin_and_fence_fb_obj(dev, obj, ring); + if (ret) + goto out; + + ret = intel_ring_begin(ring, 4); + if (ret) + goto out; + + intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19)); + intel_ring_emit(ring, (fb->pitch | obj->tiling_mode)); + intel_ring_emit(ring, (obj->gtt_offset)); + intel_ring_emit(ring, (MI_NOOP)); + intel_ring_advance(ring); +out: + return ret; +} + static int intel_default_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -7758,6 +7791,9 @@ static void intel_init_display(struct drm_device *dev) case 6: dev_priv->display.queue_flip = intel_gen6_queue_flip; break; + case 7: + dev_priv->display.queue_flip = intel_gen7_queue_flip; + break; } } -- cgit v1.2.3 From 3181faa85bda3dc3f5e630a1846526c9caaa38e3 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 27 Jun 2011 09:03:47 +0200 Subject: cfq-iosched: fix a rcu warning I got a rcu warnning at boot. the ioc->ioc_data is rcu_deferenced, but doesn't hold rcu_read_lock. Signed-off-by: Shaohua Li Cc: stable@kernel.org # after ab4bd22d Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index f3799432676d..fd566c1e2617 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2773,11 +2773,14 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, smp_wmb(); cic->key = cfqd_dead_key(cfqd); + rcu_read_lock(); if (rcu_dereference(ioc->ioc_data) == cic) { + rcu_read_unlock(); spin_lock(&ioc->lock); rcu_assign_pointer(ioc->ioc_data, NULL); spin_unlock(&ioc->lock); - } + } else + rcu_read_unlock(); if (cic->cfqq[BLK_RW_ASYNC]) { cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); -- cgit v1.2.3 From 726e99ab88db059fe1422e15376ae404f8c66eb4 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 27 Jun 2011 09:03:48 +0200 Subject: cfq-iosched: make code consistent ioc->ioc_data is rcu protectd, so uses correct API to access it. This doesn't change any behavior, but just make code consistent. Signed-off-by: Shaohua Li Cc: stable@kernel.org # after ab4bd22d Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index fd566c1e2617..ae21919f15e1 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3087,7 +3087,8 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc, spin_lock_irqsave(&ioc->lock, flags); - BUG_ON(ioc->ioc_data == cic); + BUG_ON(rcu_dereference_check(ioc->ioc_data, + lockdep_is_held(&ioc->lock)) == cic); radix_tree_delete(&ioc->radix_root, cfqd->cic_index); hlist_del_rcu(&cic->cic_list); -- cgit v1.2.3 From 1107a08a1a3e0f54d535d37ee0c4192acce6a7f3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 27 Jun 2011 07:48:52 -0700 Subject: iwlagn: fix cmd queue unmap When we stop the device while a command is in flight that uses multiple TBs, we can leak the DMA buffers for the second and higher TBs. Fix this by using iwlagn_unmap_tfd() as we do when we normally recover the entry. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-tx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 157a642a5436..8f20065e6dac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -310,10 +310,7 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) i = get_cmd_index(q, q->read_ptr); if (txq->meta[i].flags & CMD_MAPPED) { - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(&txq->meta[i], mapping), - dma_unmap_len(&txq->meta[i], len), - PCI_DMA_BIDIRECTIONAL); + iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i]); txq->meta[i].flags = 0; } -- cgit v1.2.3 From e815407d395e0b7fd1aa9145d9d0c391191b833c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 27 Jun 2011 07:54:49 -0700 Subject: iwlagn: map command buffers BIDI Evidently, the device sometimes wants to write back to command buffers, even if I see no reason why it should. Allow it to do that. Tested-by: Andy Lutomirski Tested-by: Kyle McMartin Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-tx.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 8f20065e6dac..47074315903e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -126,7 +126,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) } static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, - struct iwl_tfd *tfd) + struct iwl_tfd *tfd, enum dma_data_direction dma_dir) { struct pci_dev *dev = priv->pci_dev; int i; @@ -151,7 +151,7 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), - iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); + iwl_tfd_tb_get_len(tfd, i), dma_dir); } /** @@ -167,7 +167,8 @@ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) struct iwl_tfd *tfd_tmp = txq->tfds; int index = txq->q.read_ptr; - iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index]); + iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index], + DMA_TO_DEVICE); /* free SKB */ if (txq->txb) { @@ -310,7 +311,8 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) i = get_cmd_index(q, q->read_ptr); if (txq->meta[i].flags & CMD_MAPPED) { - iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i]); + iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i], + DMA_BIDIRECTIONAL); txq->meta[i].flags = 0; } @@ -692,10 +694,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) continue; phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i], - cmd->len[i], PCI_DMA_TODEVICE); + cmd->len[i], DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) { iwlagn_unmap_tfd(priv, out_meta, - &txq->tfds[q->write_ptr]); + &txq->tfds[q->write_ptr], + DMA_BIDIRECTIONAL); idx = -ENOMEM; goto out; } @@ -799,7 +802,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; - iwlagn_unmap_tfd(priv, meta, &txq->tfds[index]); + iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { -- cgit v1.2.3 From 2f7e33d432d097a2a7f467b031bf18be91cb3d49 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Thu, 23 Jun 2011 07:27:13 +0000 Subject: btrfs: fix inconsonant inode information When iputting the inode, We may leave the delayed nodes if they have some delayed items that have not been dealt with. So when the inode is read again, we must look up the relative delayed node, and use the information in it to initialize the inode. Or we will get inconsonant inode information, it may cause that the same directory index number is allocated again, and hit the following oops: [ 5447.554187] err add delayed dir index item(name: pglog_0.965_0) into the insertion tree of the delayed node(root id: 262, inode id: 258, errno: -17) [ 5447.569766] ------------[ cut here ]------------ [ 5447.575361] kernel BUG at fs/btrfs/delayed-inode.c:1301! [SNIP] [ 5447.790721] Call Trace: [ 5447.793191] [] btrfs_insert_dir_item+0x189/0x1bb [btrfs] [ 5447.800156] [] btrfs_add_link+0x12b/0x191 [btrfs] [ 5447.806517] [] btrfs_add_nondir+0x31/0x58 [btrfs] [ 5447.812876] [] btrfs_create+0xf9/0x197 [btrfs] [ 5447.818961] [] vfs_create+0x72/0x92 [ 5447.824090] [] do_last+0x22c/0x40b [ 5447.829133] [] path_openat+0xc0/0x2ef [ 5447.834438] [] ? __perf_event_task_sched_out+0x24/0x44 [ 5447.841216] [] ? perf_event_task_sched_out+0x59/0x67 [ 5447.847846] [] do_filp_open+0x3d/0x87 [ 5447.853156] [] ? strncpy_from_user+0x43/0x4d [ 5447.859072] [] ? getname_flags+0x2e/0x80 [ 5447.864636] [] ? do_getname+0x14b/0x173 [ 5447.870112] [] ? audit_getname+0x16/0x26 [ 5447.875682] [] ? spin_lock+0xe/0x10 [ 5447.880882] [] do_sys_open+0x69/0xae [ 5447.886153] [] sys_open+0x20/0x22 [ 5447.891114] [] system_call_fastpath+0x16/0x1b Fix it by reusing the old delayed node. Reported-by: Jim Schutt Signed-off-by: Miao Xie Tested-by: Jim Schutt Signed-off-by: Chris Mason --- fs/btrfs/delayed-inode.c | 104 ++++++++++++++++++++++++++++++++++++----------- fs/btrfs/delayed-inode.h | 1 + fs/btrfs/inode.c | 12 +++++- 3 files changed, 91 insertions(+), 26 deletions(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index f1cbd028f7b3..98c68e658a9b 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -82,19 +82,16 @@ static inline struct btrfs_delayed_root *btrfs_get_delayed_root( return root->fs_info->delayed_root; } -static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( - struct inode *inode) +static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode) { - struct btrfs_delayed_node *node; struct btrfs_inode *btrfs_inode = BTRFS_I(inode); struct btrfs_root *root = btrfs_inode->root; u64 ino = btrfs_ino(inode); - int ret; + struct btrfs_delayed_node *node; -again: node = ACCESS_ONCE(btrfs_inode->delayed_node); if (node) { - atomic_inc(&node->refs); /* can be accessed */ + atomic_inc(&node->refs); return node; } @@ -102,8 +99,10 @@ again: node = radix_tree_lookup(&root->delayed_nodes_tree, ino); if (node) { if (btrfs_inode->delayed_node) { + atomic_inc(&node->refs); /* can be accessed */ + BUG_ON(btrfs_inode->delayed_node != node); spin_unlock(&root->inode_lock); - goto again; + return node; } btrfs_inode->delayed_node = node; atomic_inc(&node->refs); /* can be accessed */ @@ -113,6 +112,23 @@ again: } spin_unlock(&root->inode_lock); + return NULL; +} + +static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( + struct inode *inode) +{ + struct btrfs_delayed_node *node; + struct btrfs_inode *btrfs_inode = BTRFS_I(inode); + struct btrfs_root *root = btrfs_inode->root; + u64 ino = btrfs_ino(inode); + int ret; + +again: + node = btrfs_get_delayed_node(inode); + if (node) + return node; + node = kmem_cache_alloc(delayed_node_cache, GFP_NOFS); if (!node) return ERR_PTR(-ENOMEM); @@ -548,19 +564,6 @@ struct btrfs_delayed_item *__btrfs_next_delayed_item( return next; } -static inline struct btrfs_delayed_node *btrfs_get_delayed_node( - struct inode *inode) -{ - struct btrfs_inode *btrfs_inode = BTRFS_I(inode); - struct btrfs_delayed_node *delayed_node; - - delayed_node = btrfs_inode->delayed_node; - if (delayed_node) - atomic_inc(&delayed_node->refs); - - return delayed_node; -} - static inline struct btrfs_root *btrfs_get_fs_root(struct btrfs_root *root, u64 root_id) { @@ -1404,8 +1407,7 @@ end: int btrfs_inode_delayed_dir_index_count(struct inode *inode) { - struct btrfs_delayed_node *delayed_node = BTRFS_I(inode)->delayed_node; - int ret = 0; + struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode); if (!delayed_node) return -ENOENT; @@ -1415,11 +1417,14 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode) * a new directory index is added into the delayed node and index_cnt * is updated now. So we needn't lock the delayed node. */ - if (!delayed_node->index_cnt) + if (!delayed_node->index_cnt) { + btrfs_release_delayed_node(delayed_node); return -EINVAL; + } BTRFS_I(inode)->index_cnt = delayed_node->index_cnt; - return ret; + btrfs_release_delayed_node(delayed_node); + return 0; } void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, @@ -1613,6 +1618,57 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans, inode->i_ctime.tv_nsec); } +int btrfs_fill_inode(struct inode *inode, u32 *rdev) +{ + struct btrfs_delayed_node *delayed_node; + struct btrfs_inode_item *inode_item; + struct btrfs_timespec *tspec; + + delayed_node = btrfs_get_delayed_node(inode); + if (!delayed_node) + return -ENOENT; + + mutex_lock(&delayed_node->mutex); + if (!delayed_node->inode_dirty) { + mutex_unlock(&delayed_node->mutex); + btrfs_release_delayed_node(delayed_node); + return -ENOENT; + } + + inode_item = &delayed_node->inode_item; + + inode->i_uid = btrfs_stack_inode_uid(inode_item); + inode->i_gid = btrfs_stack_inode_gid(inode_item); + btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item)); + inode->i_mode = btrfs_stack_inode_mode(inode_item); + inode->i_nlink = btrfs_stack_inode_nlink(inode_item); + inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item)); + BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item); + BTRFS_I(inode)->sequence = btrfs_stack_inode_sequence(inode_item); + inode->i_rdev = 0; + *rdev = btrfs_stack_inode_rdev(inode_item); + BTRFS_I(inode)->flags = btrfs_stack_inode_flags(inode_item); + + tspec = btrfs_inode_atime(inode_item); + inode->i_atime.tv_sec = btrfs_stack_timespec_sec(tspec); + inode->i_atime.tv_nsec = btrfs_stack_timespec_nsec(tspec); + + tspec = btrfs_inode_mtime(inode_item); + inode->i_mtime.tv_sec = btrfs_stack_timespec_sec(tspec); + inode->i_mtime.tv_nsec = btrfs_stack_timespec_nsec(tspec); + + tspec = btrfs_inode_ctime(inode_item); + inode->i_ctime.tv_sec = btrfs_stack_timespec_sec(tspec); + inode->i_ctime.tv_nsec = btrfs_stack_timespec_nsec(tspec); + + inode->i_generation = BTRFS_I(inode)->generation; + BTRFS_I(inode)->index_cnt = (u64)-1; + + mutex_unlock(&delayed_node->mutex); + btrfs_release_delayed_node(delayed_node); + return 0; +} + int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode) { diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index d1a6a2915c66..8d27af4bd8b9 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -119,6 +119,7 @@ void btrfs_kill_delayed_inode_items(struct inode *inode); int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode); +int btrfs_fill_inode(struct inode *inode, u32 *rdev); /* Used for drop dead root */ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 87f1e0cf26f8..447612d3a16a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2509,6 +2509,11 @@ static void btrfs_read_locked_inode(struct inode *inode) int maybe_acls; u32 rdev; int ret; + bool filled = false; + + ret = btrfs_fill_inode(inode, &rdev); + if (!ret) + filled = true; path = btrfs_alloc_path(); BUG_ON(!path); @@ -2520,6 +2525,10 @@ static void btrfs_read_locked_inode(struct inode *inode) goto make_bad; leaf = path->nodes[0]; + + if (filled) + goto cache_acl; + inode_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_inode_item); if (!leaf->map_token) @@ -2556,7 +2565,7 @@ static void btrfs_read_locked_inode(struct inode *inode) BTRFS_I(inode)->index_cnt = (u64)-1; BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); - +cache_acl: /* * try to precache a NULL acl entry for files that don't have * any xattrs or acls @@ -2572,7 +2581,6 @@ static void btrfs_read_locked_inode(struct inode *inode) } btrfs_free_path(path); - inode_item = NULL; switch (inode->i_mode & S_IFMT) { case S_IFREG: -- cgit v1.2.3 From 8fcbd4dc7a1b338b393dcd6869deb1725cf1a9f3 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Sun, 12 Jun 2011 05:34:31 -0700 Subject: iwlagn: fix *_UCODE_API_MAX output in the firmware field Currently (3.0-rc2), modinfo iwlagn shows: firmware: iwlwifi-5150-IWL5150_UCODE_API_MAX.ucode firmware: iwlwifi-5000-IWL5000_UCODE_API_MAX.ucode firmware: iwlwifi-6000g2b-IWL6000G2_UCODE_API_MAX.ucode firmware: iwlwifi-6000g2a-IWL6000G2_UCODE_API_MAX.ucode firmware: iwlwifi-6050-IWL6050_UCODE_API_MAX.ucode firmware: iwlwifi-6000-IWL6000_UCODE_API_MAX.ucode firmware: iwlwifi-100-IWL100_UCODE_API_MAX.ucode firmware: iwlwifi-1000-IWL1000_UCODE_API_MAX.ucode firmware: iwlwifi-105-IWL105_UCODE_API_MAX.ucode firmware: iwlwifi-2030-IWL2030_UCODE_API_MAX.ucode firmware: iwlwifi-2000-IWL2000_UCODE_API_MAX.ucode which is obviously wrong, the user should not see the *_UCODE_API_MAX macros but the actual ucode API versions here. The problem are the #define *_MODULE_FIRMWARE(api) *_FW_PRE #api ".ucode" which do not expand api correctly (because this is a macro itself). Fixed by using __stringify() from linux/stringify.h. Further information about macro stringification can be found here: http://gcc.gnu.org/onlinedocs/cpp/Stringification.html Signed-off-by: Evgeni Golov Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-2000.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-5000.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 9 +++++---- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 61d4a11f566b..2a88e73bb39c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "iwl-eeprom.h" #include "iwl-dev.h" @@ -55,10 +56,10 @@ #define IWL100_UCODE_API_MIN 5 #define IWL1000_FW_PRE "iwlwifi-1000-" -#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" +#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE __stringify(api) ".ucode" #define IWL100_FW_PRE "iwlwifi-100-" -#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" +#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode" /* diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 2282279cffc4..3df76f53a41b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "iwl-eeprom.h" #include "iwl-dev.h" @@ -58,13 +59,13 @@ #define IWL105_UCODE_API_MIN 5 #define IWL2030_FW_PRE "iwlwifi-2030-" -#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" +#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode" #define IWL2000_FW_PRE "iwlwifi-2000-" -#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" +#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE __stringify(api) ".ucode" #define IWL105_FW_PRE "iwlwifi-105-" -#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE #api ".ucode" +#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode" static void iwl2000_set_ct_threshold(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f99f9c193352..e816c27db794 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "iwl-eeprom.h" #include "iwl-dev.h" @@ -57,10 +58,10 @@ #define IWL5150_UCODE_API_MIN 1 #define IWL5000_FW_PRE "iwlwifi-5000-" -#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" +#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE __stringify(api) ".ucode" #define IWL5150_FW_PRE "iwlwifi-5150-" -#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" +#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode" /* NIC configuration for 5000 series */ static void iwl5000_nic_config(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index fbe565c816e3..5b150bc70b06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "iwl-eeprom.h" #include "iwl-dev.h" @@ -58,16 +59,16 @@ #define IWL6000G2_UCODE_API_MIN 4 #define IWL6000_FW_PRE "iwlwifi-6000-" -#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" +#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE __stringify(api) ".ucode" #define IWL6050_FW_PRE "iwlwifi-6050-" -#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" +#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE __stringify(api) ".ucode" #define IWL6005_FW_PRE "iwlwifi-6000g2a-" -#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode" +#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE __stringify(api) ".ucode" #define IWL6030_FW_PRE "iwlwifi-6000g2b-" -#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode" +#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode" static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { -- cgit v1.2.3 From a66b98db570a638afd909459e1e6bfa272344bd3 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Thu, 23 Jun 2011 00:00:24 +0300 Subject: mac80211: fix rx->key NULL dereference during mic failure Sometimes when reporting a MIC failure rx->key may be unset. This code path is hit when receiving a packet meant for a multicast address, and decryption is performed in HW. Fortunately, the failing key_idx is not used for anything up to (and including) usermode, so we allow ourselves to drop it on the way up when a key cannot be retrieved. Signed-off-by: Arik Nemtsov Cc: stable@kernel.org Signed-off-by: John W. Linville --- include/net/cfg80211.h | 2 +- net/mac80211/wpa.c | 8 +++++++- net/wireless/nl80211.c | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0589f554788a..396e8fc8910e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2688,7 +2688,7 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, * @dev: network device * @addr: The source MAC address of the frame * @key_type: The key type that the received frame used - * @key_id: Key identifier (0..3) + * @key_id: Key identifier (0..3). Can be -1 if missing. * @tsc: The TSC value of the frame that generated the MIC failure (6 octets) * @gfp: allocation flags * diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 9dc3b5f26e80..d91c1a26630d 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -154,7 +154,13 @@ update_iv: return RX_CONTINUE; mic_fail: - mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, + /* + * In some cases the key can be unset - e.g. a multicast packet, in + * a driver that supports HW encryption. Send up the key idx only if + * the key is set. + */ + mac80211_ev_michael_mic_failure(rx->sdata, + rx->key ? rx->key->conf.keyidx : -1, (void *) skb->data, NULL, GFP_ATOMIC); return RX_DROP_UNUSABLE; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 98fa8eb6cc4b..f07602d7bf68 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6463,7 +6463,8 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, if (addr) NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); + if (key_id != -1) + NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); if (tsc) NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc); -- cgit v1.2.3 From 8b1ab60c767f33d79894ef66037ef851a7a88fc8 Mon Sep 17 00:00:00 2001 From: Arvid Brodin Date: Fri, 17 Jun 2011 18:45:37 +0200 Subject: usb/isp1760: Fix bug preventing the unlinking of control urbs Both control and bulk transfers use isp1760 slots of type ATL, but the driver unlink code for ATL slots only acts on urbs describing a bulk transfer, letting the code for INT slots take care of the unlink instead, which often ended up removing the interrupt transfer for root hub events instead. That's not good, and gets fixed by this patch. Signed-off-by: Arvid Brodin Cc: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index c9e6e454c625..55d3d5859ac5 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -1555,7 +1555,7 @@ static void kill_transfer(struct usb_hcd *hcd, struct urb *urb, /* We need to forcefully reclaim the slot since some transfers never return, e.g. interrupt transfers and NAKed bulk transfers. */ - if (usb_pipebulk(urb->pipe)) { + if (usb_pipecontrol(urb->pipe) || usb_pipebulk(urb->pipe)) { skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); skip_map |= (1 << qh->slot); reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map); -- cgit v1.2.3 From 309427b6351b763917caac3e4b2ab5651df99823 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Fri, 17 Jun 2011 17:30:23 +0200 Subject: USB: Add new FT232H chip to drivers/usb/serial/ftdi_sio.c appended patch adds support for the new FTDI FT232H chip. This chip is a single channel version of the dual FT2232H/quad FT4232H, coming with it's own default PID 0x6014 (FT2232H uses the same PID 0x6010 like FT2232C, FT4232H has also it's own PID). The patch was checked on an UM232H module and a terminal program with TX/RX shorted to that typing in the terminal reproduced the characters. Signed-off-by: Uwe Bonnes Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 19 ++++++++++++++----- drivers/usb/serial/ftdi_sio.h | 3 ++- drivers/usb/serial/ftdi_sio_ids.h | 1 + 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 162728977553..2e06b90aa1f8 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -179,6 +179,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_232H_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, @@ -848,7 +849,8 @@ static const char *ftdi_chip_name[] = { [FT2232C] = "FT2232C", [FT232RL] = "FT232RL", [FT2232H] = "FT2232H", - [FT4232H] = "FT4232H" + [FT4232H] = "FT4232H", + [FT232H] = "FT232H" }; @@ -1168,6 +1170,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, break; case FT2232H: /* FT2232H chip */ case FT4232H: /* FT4232H chip */ + case FT232H: /* FT232H chip */ if ((baud <= 12000000) & (baud >= 1200)) { div_value = ftdi_2232h_baud_to_divisor(baud); } else if (baud < 1200) { @@ -1429,9 +1432,12 @@ static void ftdi_determine_type(struct usb_serial_port *port) } else if (version < 0x600) { /* Assume it's an FT232BM (or FT245BM) */ priv->chip_type = FT232BM; - } else { - /* Assume it's an FT232R */ + } else if (version < 0x900) { + /* Assume it's an FT232RL */ priv->chip_type = FT232RL; + } else { + /* Assume it's an FT232H */ + priv->chip_type = FT232H; } dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]); } @@ -1559,7 +1565,8 @@ static int create_sysfs_attrs(struct usb_serial_port *port) priv->chip_type == FT2232C || priv->chip_type == FT232RL || priv->chip_type == FT2232H || - priv->chip_type == FT4232H)) { + priv->chip_type == FT4232H || + priv->chip_type == FT232H)) { retval = device_create_file(&port->dev, &dev_attr_latency_timer); } @@ -1580,7 +1587,8 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) priv->chip_type == FT2232C || priv->chip_type == FT232RL || priv->chip_type == FT2232H || - priv->chip_type == FT4232H) { + priv->chip_type == FT4232H || + priv->chip_type == FT232H) { device_remove_file(&port->dev, &dev_attr_latency_timer); } } @@ -2212,6 +2220,7 @@ static int ftdi_tiocmget(struct tty_struct *tty) case FT232RL: case FT2232H: case FT4232H: + case FT232H: len = 2; break; default: diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 213fe3d61282..19584faa86f9 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -156,7 +156,8 @@ enum ftdi_chip_type { FT2232C = 4, FT232RL = 5, FT2232H = 6, - FT4232H = 7 + FT4232H = 7, + FT232H = 8 }; enum ftdi_sio_baudrate { diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index ab1fcdf3c378..19156d1049fe 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -22,6 +22,7 @@ #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */ +#define FTDI_232H_PID 0x6014 /* Single channel hi-speed device */ #define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ #define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ -- cgit v1.2.3 From c27d5368ef1f7ea40bcd1fb2626f4c99d77e0080 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 20 Jun 2011 17:22:36 +0200 Subject: USB: ehci-ath79: fix a NULL pointer dereference Loading the ehci-hcd module on the ath79 platform causes a NULL pointer dereference: CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == c0252928, ra == c00de968 Oops[#1]: Cpu 0 $ 0 : 00000000 00000070 00000001 00000000 $ 4 : 802cf870 0000117e ffffffff 8019c7bc $ 8 : 0000000a 00000002 00000001 fffffffb $12 : 8026ef20 0000000f ffffff80 802dad3c $16 : 8077a2d4 8077a200 c00f3484 8019ed84 $20 : c00f0000 00000003 000000a0 80262c2c $24 : 00000002 80079da0 $28 : 80788000 80789c80 80262b14 c00de968 Hi : 00000000 Lo : b61f0000 epc : c0252928 __mod_vermagic5+0xc260/0xc7e8 [ehci_hcd] Not tainted ra : c00de968 usb_add_hcd+0x2a4/0x858 [usbcore] Status: 1000c003 KERNEL EXL IE Cause : 00800008 BadVA : 00000000 PrId : 00019374 (MIPS 24Kc) Modules linked in: ehci_hcd(+) pppoe pppox ipt_REJECT xt_TCPMSS ipt_LOG xt_comment xt_multiport xt_mac xt_limit iptable_mangle iptable_filte r ip_tables xt_tcpudp x_tables ppp_async ppp_generic slhc ath mac80211 usbcore nls_base input_polldev crc_ccitt cfg80211 compat input_core a rc4 aes_generic crypto_algapi Process insmod (pid: 379, threadinfo=80788000, task=80ca2180, tls=77fe52d0) Stack : c0253184 80c57d80 80789cac 8077a200 00000001 8019edc0 807fa800 8077a200 8077a290 c00f3484 8019ed84 c00f0000 00000003 000000a0 80262c2c c00de968 802d0000 800878cc c0253228 c02528e4 c0253184 80c57d80 80bf6800 80ca2180 8007b75c 00000000 8077a200 802cf830 802d0000 00000003 fffffff4 00000015 00000348 00000124 800b189c c024bb4c c0255000 801a27e8 c0253228 c02528e4 ... Call Trace: [] __mod_vermagic5+0xc260/0xc7e8 [ehci_hcd] It is caused by: commit c430131a02d677aa708f56342c1565edfdacb3c0 Author: Jan Andersson Date: Tue May 3 20:11:57 2011 +0200 USB: EHCI: Support controllers with big endian capability regs The two first HC capability registers (CAPLENGTH and HCIVERSION) are defined as one 8-bit and one 16-bit register. Most HC implementations have selected to treat these registers as part of a 32-bit register, giving the same layout for both big and small endian systems. This patch adds a new quirk, big_endian_capbase, to support controllers with big endian register interfaces that treat HCIVERSION and CAPLENGTH as individual registers. Signed-off-by: Jan Andersson Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman The reading of the HC capability register has been moved by that commit to a place where the ehci->caps field is not initialized yet. This patch moves the reading of the register back to the original place. Acked-by: Jan Andersson Cc: Alan Stern Signed-off-by: Gabor Juhos Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-ath79.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c index 98cc8a13169c..aa248c2f2c60 100644 --- a/drivers/usb/host/ehci-ath79.c +++ b/drivers/usb/host/ehci-ath79.c @@ -44,7 +44,6 @@ static int ehci_ath79_init(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct platform_device *pdev = to_platform_device(hcd->self.controller); const struct platform_device_id *id; - int hclength; int ret; id = platform_get_device_id(pdev); @@ -53,20 +52,23 @@ static int ehci_ath79_init(struct usb_hcd *hcd) return -EINVAL; } - hclength = HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); switch (id->driver_data) { case EHCI_ATH79_IP_V1: ehci->has_synopsys_hc_bug = 1; ehci->caps = hcd->regs; - ehci->regs = hcd->regs + hclength; + ehci->regs = hcd->regs + + HC_LENGTH(ehci, + ehci_readl(ehci, &ehci->caps->hc_capbase)); break; case EHCI_ATH79_IP_V2: hcd->has_tt = 1; ehci->caps = hcd->regs + 0x100; - ehci->regs = hcd->regs + 0x100 + hclength; + ehci->regs = hcd->regs + 0x100 + + HC_LENGTH(ehci, + ehci_readl(ehci, &ehci->caps->hc_capbase)); break; default: -- cgit v1.2.3 From 87abd0a92c72eea71542d6c972c67e39e584e989 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 21 Jun 2011 13:24:42 +0900 Subject: usb: r8a66597-hcd: fix cannot detect low/full speed device This controller can control "Transaction Translators", but the hcd->has_tt is not set. Since the commit d199c96d41d80a567493e12b8e96ea056a1350c1 ("USB: prevent buggy from crashing the USB stack") has checked it, the driver could not work the low/full speed device. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index db6f8b9c19b6..4586369dda00 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2517,6 +2517,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) INIT_LIST_HEAD(&r8a66597->child_device); hcd->rsrc_start = res->start; + hcd->has_tt = 1; ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger); if (ret != 0) { -- cgit v1.2.3 From 857aab34f04ff86666aa80e751ee696eff0113dd Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 17 Jun 2011 15:50:46 -0700 Subject: MAINTAINERS: add myself as maintainer of USB/IP Signed-off-by: matt mooney Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 4307673415f7..1f93f5084d26 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6462,6 +6462,12 @@ S: Maintained F: Documentation/usb/hiddev.txt F: drivers/hid/usbhid/ +USB/IP DRIVERS +M: Matt Mooney +L: linux-usb@vger.kernel.org +S: Maintained +F: drivers/staging/usbip/ + USB ISP116X DRIVER M: Olav Kongas L: linux-usb@vger.kernel.org -- cgit v1.2.3 From c6830c22603aaecf65405af23f6da2d55892f9cb Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Thu, 16 Jun 2011 17:28:07 +0900 Subject: Fix node_start/end_pfn() definition for mm/page_cgroup.c commit 21a3c96 uses node_start/end_pfn(nid) for detection start/end of nodes. But, it's not defined in linux/mmzone.h but defined in /arch/???/include/mmzone.h which is included only under CONFIG_NEED_MULTIPLE_NODES=y. Then, we see mm/page_cgroup.c: In function 'page_cgroup_init': mm/page_cgroup.c:308: error: implicit declaration of function 'node_start_pfn' mm/page_cgroup.c:309: error: implicit declaration of function 'node_end_pfn' So, fixiing page_cgroup.c is an idea... But node_start_pfn()/node_end_pfn() is a very generic macro and should be implemented in the same manner for all archs. (m32r has different implementation...) This patch removes definitions of node_start/end_pfn() in each archs and defines a unified one in linux/mmzone.h. It's not under CONFIG_NEED_MULTIPLE_NODES, now. A result of macro expansion is here (mm/page_cgroup.c) for !NUMA start_pfn = ((&contig_page_data)->node_start_pfn); end_pfn = ({ pg_data_t *__pgdat = (&contig_page_data); __pgdat->node_start_pfn + __pgdat->node_spanned_pages;}); for NUMA (x86-64) start_pfn = ((node_data[nid])->node_start_pfn); end_pfn = ({ pg_data_t *__pgdat = (node_data[nid]); __pgdat->node_start_pfn + __pgdat->node_spanned_pages;}); Changelog: - fixed to avoid using "nid" twice in node_end_pfn() macro. Reported-and-acked-by: Randy Dunlap Reported-and-tested-by: Ingo Molnar Acked-by: Mel Gorman Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Linus Torvalds --- arch/alpha/include/asm/mmzone.h | 1 - arch/m32r/include/asm/mmzone.h | 8 +------- arch/parisc/include/asm/mmzone.h | 7 ------- arch/powerpc/include/asm/mmzone.h | 7 ------- arch/sh/include/asm/mmzone.h | 4 ---- arch/sparc/include/asm/mmzone.h | 2 -- arch/tile/include/asm/mmzone.h | 11 ----------- arch/x86/include/asm/mmzone_32.h | 11 ----------- arch/x86/include/asm/mmzone_64.h | 3 --- include/linux/mmzone.h | 7 +++++++ 10 files changed, 8 insertions(+), 53 deletions(-) diff --git a/arch/alpha/include/asm/mmzone.h b/arch/alpha/include/asm/mmzone.h index 8af56ce346ad..445dc42e0334 100644 --- a/arch/alpha/include/asm/mmzone.h +++ b/arch/alpha/include/asm/mmzone.h @@ -56,7 +56,6 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n) * Given a kernel address, find the home node of the underlying memory. */ #define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr)) -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) /* * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory diff --git a/arch/m32r/include/asm/mmzone.h b/arch/m32r/include/asm/mmzone.h index 9f3b5accda88..115ced33febd 100644 --- a/arch/m32r/include/asm/mmzone.h +++ b/arch/m32r/include/asm/mmzone.h @@ -14,12 +14,6 @@ extern struct pglist_data *node_data[]; #define NODE_DATA(nid) (node_data[nid]) #define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn) -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define node_end_pfn(nid) \ -({ \ - pg_data_t *__pgdat = NODE_DATA(nid); \ - __pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1; \ -}) #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) /* @@ -44,7 +38,7 @@ static __inline__ int pfn_to_nid(unsigned long pfn) int node; for (node = 0 ; node < MAX_NUMNODES ; node++) - if (pfn >= node_start_pfn(node) && pfn <= node_end_pfn(node)) + if (pfn >= node_start_pfn(node) && pfn < node_end_pfn(node)) break; return node; diff --git a/arch/parisc/include/asm/mmzone.h b/arch/parisc/include/asm/mmzone.h index 9608d2cf214a..e67eb9c3d1bf 100644 --- a/arch/parisc/include/asm/mmzone.h +++ b/arch/parisc/include/asm/mmzone.h @@ -14,13 +14,6 @@ extern struct node_map_data node_data[]; #define NODE_DATA(nid) (&node_data[nid].pg_data) -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define node_end_pfn(nid) \ -({ \ - pg_data_t *__pgdat = NODE_DATA(nid); \ - __pgdat->node_start_pfn + __pgdat->node_spanned_pages; \ -}) - /* We have these possible memory map layouts: * Astro: 0-3.75, 67.75-68, 4-64 * zx1: 0-1, 257-260, 4-256 diff --git a/arch/powerpc/include/asm/mmzone.h b/arch/powerpc/include/asm/mmzone.h index fd3fd58bad84..7b589178be46 100644 --- a/arch/powerpc/include/asm/mmzone.h +++ b/arch/powerpc/include/asm/mmzone.h @@ -38,13 +38,6 @@ u64 memory_hotplug_max(void); #define memory_hotplug_max() memblock_end_of_DRAM() #endif -/* - * Following are macros that each numa implmentation must define. - */ - -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) - #else #define memory_hotplug_max() memblock_end_of_DRAM() #endif /* CONFIG_NEED_MULTIPLE_NODES */ diff --git a/arch/sh/include/asm/mmzone.h b/arch/sh/include/asm/mmzone.h index 8887baff5eff..15a8496960e6 100644 --- a/arch/sh/include/asm/mmzone.h +++ b/arch/sh/include/asm/mmzone.h @@ -9,10 +9,6 @@ extern struct pglist_data *node_data[]; #define NODE_DATA(nid) (node_data[nid]) -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \ - NODE_DATA(nid)->node_spanned_pages) - static inline int pfn_to_nid(unsigned long pfn) { int nid; diff --git a/arch/sparc/include/asm/mmzone.h b/arch/sparc/include/asm/mmzone.h index e8c648741ed4..99d9b9f577bf 100644 --- a/arch/sparc/include/asm/mmzone.h +++ b/arch/sparc/include/asm/mmzone.h @@ -8,8 +8,6 @@ extern struct pglist_data *node_data[]; #define NODE_DATA(nid) (node_data[nid]) -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) extern int numa_cpu_lookup_table[]; extern cpumask_t numa_cpumask_lookup_table[]; diff --git a/arch/tile/include/asm/mmzone.h b/arch/tile/include/asm/mmzone.h index c6344c4f32ac..9d3dbce8f953 100644 --- a/arch/tile/include/asm/mmzone.h +++ b/arch/tile/include/asm/mmzone.h @@ -40,17 +40,6 @@ static inline int pfn_to_nid(unsigned long pfn) return highbits_to_node[__pfn_to_highbits(pfn)]; } -/* - * Following are macros that each numa implmentation must define. - */ - -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define node_end_pfn(nid) \ -({ \ - pg_data_t *__pgdat = NODE_DATA(nid); \ - __pgdat->node_start_pfn + __pgdat->node_spanned_pages; \ -}) - #define kern_addr_valid(kaddr) virt_addr_valid((void *)kaddr) static inline int pfn_valid(int pfn) diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h index 5e83a416eca8..224e8c5eb307 100644 --- a/arch/x86/include/asm/mmzone_32.h +++ b/arch/x86/include/asm/mmzone_32.h @@ -48,17 +48,6 @@ static inline int pfn_to_nid(unsigned long pfn) #endif } -/* - * Following are macros that each numa implmentation must define. - */ - -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define node_end_pfn(nid) \ -({ \ - pg_data_t *__pgdat = NODE_DATA(nid); \ - __pgdat->node_start_pfn + __pgdat->node_spanned_pages; \ -}) - static inline int pfn_valid(int pfn) { int nid = pfn_to_nid(pfn); diff --git a/arch/x86/include/asm/mmzone_64.h b/arch/x86/include/asm/mmzone_64.h index b3f88d7867c7..129d9aa3ceb3 100644 --- a/arch/x86/include/asm/mmzone_64.h +++ b/arch/x86/include/asm/mmzone_64.h @@ -13,8 +13,5 @@ extern struct pglist_data *node_data[]; #define NODE_DATA(nid) (node_data[nid]) -#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) -#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \ - NODE_DATA(nid)->node_spanned_pages) #endif #endif /* _ASM_X86_MMZONE_64_H */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index c928dac6cad0..9f7c3ebcbbad 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -647,6 +647,13 @@ typedef struct pglist_data { #endif #define nid_page_nr(nid, pagenr) pgdat_page_nr(NODE_DATA(nid),(pagenr)) +#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) + +#define node_end_pfn(nid) ({\ + pg_data_t *__pgdat = NODE_DATA(nid);\ + __pgdat->node_start_pfn + __pgdat->node_spanned_pages;\ +}) + #include extern struct mutex zonelists_mutex; -- cgit v1.2.3 From 89089158d191ba0195b33ebf35f91ed217d44848 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 24 Jun 2011 09:28:32 -0700 Subject: Staging: fix more iio builds when IIO_RING_BUFFER is not enabled Fix lots more build errors in staging/iio when CONFIG_IIO_RING_BUFFER is not enabled by moving enums and defines outside of the CONFIG_IIO_RING_BUFFER ifdef block. Examples (one from each driver; there were 116 total errors): drivers/staging/iio/accel/adis16204_core.c:437: error: 'ADIS16204_SCAN_SUPPLY' undeclared here (not in a function) drivers/staging/iio/accel/adis16209_core.c:410: error: 'ADIS16209_SCAN_SUPPLY' undeclared here (not in a function) drivers/staging/iio/gyro/adis16260_core.c:420: error: 'ADIS16260_SCAN_GYRO' undeclared here (not in a function) drivers/staging/iio/imu/adis16400_core.c:565: error: 'ADIS16400_SCAN_SUPPLY' undeclared here (not in a function) Signed-off-by: Randy Dunlap Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16204.h | 2 +- drivers/staging/iio/accel/adis16209.h | 4 ++-- drivers/staging/iio/gyro/adis16260.h | 2 +- drivers/staging/iio/imu/adis16400.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h index 5310a4297688..1690c0d15690 100644 --- a/drivers/staging/iio/accel/adis16204.h +++ b/drivers/staging/iio/accel/adis16204.h @@ -84,7 +84,6 @@ struct adis16204_state { int adis16204_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER enum adis16204_scan { ADIS16204_SCAN_SUPPLY, ADIS16204_SCAN_ACC_X, @@ -93,6 +92,7 @@ enum adis16204_scan { ADIS16204_SCAN_TEMP, }; +#ifdef CONFIG_IIO_RING_BUFFER void adis16204_remove_trigger(struct iio_dev *indio_dev); int adis16204_probe_trigger(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h index 58d08db6f9b5..3153cbee0957 100644 --- a/drivers/staging/iio/accel/adis16209.h +++ b/drivers/staging/iio/accel/adis16209.h @@ -121,8 +121,6 @@ struct adis16209_state { int adis16209_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER - #define ADIS16209_SCAN_SUPPLY 0 #define ADIS16209_SCAN_ACC_X 1 #define ADIS16209_SCAN_ACC_Y 2 @@ -132,6 +130,8 @@ int adis16209_set_irq(struct iio_dev *indio_dev, bool enable); #define ADIS16209_SCAN_INCLI_Y 6 #define ADIS16209_SCAN_ROT 7 +#ifdef CONFIG_IIO_RING_BUFFER + void adis16209_remove_trigger(struct iio_dev *indio_dev); int adis16209_probe_trigger(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h index 702dc982f62f..24bf70e4b29b 100644 --- a/drivers/staging/iio/gyro/adis16260.h +++ b/drivers/staging/iio/gyro/adis16260.h @@ -104,7 +104,6 @@ struct adis16260_state { int adis16260_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER /* At the moment triggers are only used for ring buffer * filling. This may change! */ @@ -115,6 +114,7 @@ int adis16260_set_irq(struct iio_dev *indio_dev, bool enable); #define ADIS16260_SCAN_TEMP 3 #define ADIS16260_SCAN_ANGL 4 +#ifdef CONFIG_IIO_RING_BUFFER void adis16260_remove_trigger(struct iio_dev *indio_dev); int adis16260_probe_trigger(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h index db184d11dfc0..e87715b9acc6 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -158,7 +158,6 @@ struct adis16400_state { int adis16400_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER /* At the moment triggers are only used for ring buffer * filling. This may change! */ @@ -182,6 +181,7 @@ int adis16400_set_irq(struct iio_dev *indio_dev, bool enable); #define ADIS16300_SCAN_INCLI_X 12 #define ADIS16300_SCAN_INCLI_Y 13 +#ifdef CONFIG_IIO_RING_BUFFER void adis16400_remove_trigger(struct iio_dev *indio_dev); int adis16400_probe_trigger(struct iio_dev *indio_dev); -- cgit v1.2.3 From 6fab3e1fbc83e6d61e8c28ceab513274183a96f6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 23 Jun 2011 12:45:37 +0100 Subject: Staging: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi driver turns into tragedy: CC [M] drivers/staging/comedi/drivers.o drivers/staging/comedi/drivers.c: In function ‘comedi_buf_alloc’: drivers/staging/comedi/drivers.c:505:41: error: ‘PAGE_KERNEL_NOCACHE’ undeclared (first use in this function) drivers/staging/comedi/drivers.c:505:41: note: each undeclared identifier is rep orted only once for each function it appears in make[3]: *** [drivers/staging/comedi/drivers.o] Error 1 Restrict the driver to only those architectures that define PAGE_KERNEL_NOCACHE. PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as SGI IP27 are even uable to offer uncached operation - at least in the way an unwitting driver might assume. I haven't looked in details how the driver is using the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it XFS-style using cached memory and the flush_kernel_vmap_range / invalidate_kernel_vmap_range APIs in conjunction with the DMA API is a practical alternative. Signed-off-by: Ralf Baechle Reported-by: David Miller Reported-by: Stephen Rothwell Acked-by: Geert Uytterhoeven Cc: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 1502d80f6f78..bccdc12e843a 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -2,6 +2,7 @@ config COMEDI tristate "Data acquisition support (comedi)" default N depends on m + depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86 ---help--- Enable support a wide range of data acquisition devices for Linux. -- cgit v1.2.3 From fdf2df0e8ce634c9ee5f740a9303e8518ca78932 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 15:00:18 -0700 Subject: Staging: fix iio builds when IIO_RING_BUFFER is not enabled Fix build by moving enum list outside of #ifdef CONFIG_IIO_RING_BUFFER. drivers/staging/iio/accel/adis16201_core.c:413: error: 'ADIS16201_SCAN_SUPPLY' undeclared here (not in a function) drivers/staging/iio/accel/adis16201_core.c:417: error: 'ADIS16201_SCAN_TEMP' undeclared here (not in a function) drivers/staging/iio/accel/adis16201_core.c:422: error: 'ADIS16201_SCAN_ACC_X' undeclared here (not in a function) drivers/staging/iio/accel/adis16201_core.c:427: error: 'ADIS16201_SCAN_ACC_Y' undeclared here (not in a function) drivers/staging/iio/accel/adis16201_core.c:432: error: 'ADIS16201_SCAN_AUX_ADC' undeclared here (not in a function) drivers/staging/iio/accel/adis16201_core.c:436: error: 'ADIS16201_SCAN_INCLI_X' undeclared here (not in a function) drivers/staging/iio/accel/adis16201_core.c:441: error: 'ADIS16201_SCAN_INCLI_Y' undeclared here (not in a function) vers/staging/iio/accel/adis16203_core.c:374: error: 'ADIS16203_SCAN_SUPPLY' undeclared here (not in a function) drivers/staging/iio/accel/adis16203_core.c:378: error: 'ADIS16203_SCAN_AUX_ADC' undeclared here (not in a function) drivers/staging/iio/accel/adis16203_core.c:382: error: 'ADIS16203_SCAN_INCLI_X' undeclared here (not in a function) drivers/staging/iio/accel/adis16203_core.c:388: error: 'ADIS16203_SCAN_INCLI_Y' undeclared here (not in a function) drivers/staging/iio/accel/adis16203_core.c:392: error: 'ADIS16203_SCAN_TEMP' undeclared here (not in a function) Signed-off-by: Randy Dunlap Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16201.h | 2 +- drivers/staging/iio/accel/adis16203.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h index 0b9b85424dfa..4cc1a5bfab40 100644 --- a/drivers/staging/iio/accel/adis16201.h +++ b/drivers/staging/iio/accel/adis16201.h @@ -81,7 +81,6 @@ struct adis16201_state { int adis16201_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER enum adis16201_scan { ADIS16201_SCAN_SUPPLY, ADIS16201_SCAN_ACC_X, @@ -92,6 +91,7 @@ enum adis16201_scan { ADIS16201_SCAN_INCLI_Y, }; +#ifdef CONFIG_IIO_RING_BUFFER void adis16201_remove_trigger(struct iio_dev *indio_dev); int adis16201_probe_trigger(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h index 8bb8ce50c248..175e21bb9b40 100644 --- a/drivers/staging/iio/accel/adis16203.h +++ b/drivers/staging/iio/accel/adis16203.h @@ -76,7 +76,6 @@ struct adis16203_state { int adis16203_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER enum adis16203_scan { ADIS16203_SCAN_SUPPLY, ADIS16203_SCAN_AUX_ADC, @@ -85,6 +84,7 @@ enum adis16203_scan { ADIS16203_SCAN_INCLI_Y, }; +#ifdef CONFIG_IIO_RING_BUFFER void adis16203_remove_trigger(struct iio_dev *indio_dev); int adis16203_probe_trigger(struct iio_dev *indio_dev); -- cgit v1.2.3 From a534bb6eea72c0d082dd2faab85450e5554ba1c8 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 13 Jun 2011 16:39:31 +0300 Subject: Staging: mei: fix suspend failure wait_event_interruptible_timeout return value was wrongly used. The remaining timeout was used as the error code. This fix translated wait_event_interruptible_timeout return value into error code that can be propagated. [10291.674121] pci_pm_suspend(): mei_pci_suspend+0x0/0x8b [mei] returns 2500 It's thinkpad t400 with 00:03.0 Communication controller [0780]: Intel Corporation Mobile 4 Series Chipset MEI Controller [8086:2a44] (rev 07) Reported-by: Arkadiusz Miskiewicz Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mei/init.c | 2 +- drivers/staging/mei/wd.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/staging/mei/init.c b/drivers/staging/mei/init.c index d1ffa32cd141..685fcf639644 100644 --- a/drivers/staging/mei/init.c +++ b/drivers/staging/mei/init.c @@ -189,7 +189,7 @@ int mei_hw_init(struct mei_device *dev) mutex_lock(&dev->device_lock); } - if (!err && !dev->recvd_msg) { + if (err <= 0 && !dev->recvd_msg) { dev->mei_state = MEI_DISABLED; dev_dbg(&dev->pdev->dev, "wait_event_interruptible_timeout failed" diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c index 2564b038636a..fff53d0b5c6e 100644 --- a/drivers/staging/mei/wd.c +++ b/drivers/staging/mei/wd.c @@ -169,10 +169,15 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) ret = wait_event_interruptible_timeout(dev->wait_stop_wd, dev->wd_stopped, 10 * HZ); mutex_lock(&dev->device_lock); - if (!dev->wd_stopped) - dev_dbg(&dev->pdev->dev, "stop wd failed to complete.\n"); - else - dev_dbg(&dev->pdev->dev, "stop wd complete.\n"); + if (dev->wd_stopped) { + dev_dbg(&dev->pdev->dev, "stop wd complete ret=%d.\n", ret); + ret = 0; + } else { + if (!ret) + ret = -ETIMEDOUT; + dev_warn(&dev->pdev->dev, + "stop wd failed to complete ret=%d.\n", ret); + } if (preserve) dev->wd_timeout = wd_timeout; -- cgit v1.2.3 From 928f9111662574c1ac1dfa221c4e502ec713aed9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 31 May 2011 11:37:40 +0200 Subject: Staging: iio: Make IIO depend on GENERIC_HARDIRQS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On m68k (which doesn't support generic hardirqs yet): drivers/staging/iio/industrialio-trigger.c: In function ‘iio_trigger_poll’: drivers/staging/iio/industrialio-trigger.c:180: error: implicit declaration of function ‘generic_handle_irq’ drivers/staging/iio/industrialio-trigger.c: In function ‘iio_trigger_poll_chained’: drivers/staging/iio/industrialio-trigger.c:200: error: implicit declaration of function ‘handle_nested_irq’ drivers/staging/iio/industrialio-trigger.c: In function ‘iio_trig_release’: drivers/staging/iio/industrialio-trigger.c:379: error: implicit declaration of function ‘irq_modify_status’ drivers/staging/iio/industrialio-trigger.c:382: error: implicit declaration of function ‘irq_set_chip’ drivers/staging/iio/industrialio-trigger.c:384: error: implicit declaration of function ‘irq_set_handler’ drivers/staging/iio/industrialio-trigger.c:388: error: implicit declaration of function ‘irq_free_descs’ drivers/staging/iio/industrialio-trigger.c: In function ‘iio_trig_subirqmask’: drivers/staging/iio/industrialio-trigger.c:402: error: implicit declaration of function ‘irq_data_get_irq_chip’ drivers/staging/iio/industrialio-trigger.c:402: warning: initialization makes pointer from integer without a cast drivers/staging/iio/industrialio-trigger.c: In function ‘iio_trig_subirqunmask’: drivers/staging/iio/industrialio-trigger.c:411: warning: initialization makes pointer from integer without a cast drivers/staging/iio/industrialio-trigger.c: In function ‘iio_allocate_trigger’: drivers/staging/iio/industrialio-trigger.c:432: error: implicit declaration of function ‘irq_alloc_descs’ drivers/staging/iio/industrialio-trigger.c:455: error: ‘handle_simple_irq’ undeclared (first use in this function) drivers/staging/iio/industrialio-trigger.c:455: error: (Each undeclared identifier is reported only once drivers/staging/iio/industrialio-trigger.c:455: error: for each function it appears in.) Hence IIO_TRIGGER should depend on GENERIC_HARDIRQS. But as IIO_TRIGGER and IIO_RING_BUFFER form a maze of dependencies and selects, just make the whole IIO subsystem depend on GENERIC_HARDIRQS. This dependency also covers !S390, so that one can be removed again. Signed-off-by: Geert Uytterhoeven Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index f96d5b5d5141..d329635fb5c4 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -4,7 +4,7 @@ menuconfig IIO tristate "Industrial I/O support" - depends on !S390 + depends on GENERIC_HARDIRQS help The industrial I/O subsystem provides a unified framework for drivers for many different types of embedded sensors using a -- cgit v1.2.3 From 15e5201dfd4eebfce5e50b068ed40cb5f574fee6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 9 Jun 2011 13:16:13 -0700 Subject: Staging: brcm80211: disable drivers for PPC platforms Right now, bad things happen if you try to build these drivers for the PPC platform as it seems that the code only has been tested and built on the MIPS big endian platform. So disable it on the PPC32 and PPC64 platforms for now, hopefully this will be resolved in the future as I'm sure someone will want to use these chips with that platform someday. Reported-by: Stephen Rothwell Cc: Henry Ptasinski Cc: Brett Rudley Cc: Roland Vossen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/brcm80211/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig index f4cf9b23481e..2d1a29bdc0ee 100644 --- a/drivers/staging/brcm80211/Kconfig +++ b/drivers/staging/brcm80211/Kconfig @@ -7,6 +7,7 @@ config BRCMSMAC default n depends on PCI depends on WLAN && MAC80211 + depends on !PPC64 && !PPC32 select BRCMUTIL select FW_LOADER select CRC_CCITT @@ -20,6 +21,7 @@ config BRCMFMAC default n depends on MMC depends on WLAN && CFG80211 + depends on !PPC64 && !PPC32 select BRCMUTIL select FW_LOADER select WIRELESS_EXT -- cgit v1.2.3 From d4620396d7e9759dd3f37a8155827477cf2b5309 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Jun 2011 14:34:42 -0700 Subject: Staging: brcm80211: disable drivers except for X86 or MIPS platforms As David points out, the driver is also broken on SPARC, so might as well just only enable it on platforms where people have reported it working, instead of trying to list all of the ones where it doesn't work, as the working platform list is much smaller... Reported-by: David Miller Reported-by: Stephen Rothwell Cc: Henry Ptasinski Cc: Brett Rudley Cc: Roland Vossen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/brcm80211/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig index 2d1a29bdc0ee..379cf16e89f7 100644 --- a/drivers/staging/brcm80211/Kconfig +++ b/drivers/staging/brcm80211/Kconfig @@ -7,7 +7,7 @@ config BRCMSMAC default n depends on PCI depends on WLAN && MAC80211 - depends on !PPC64 && !PPC32 + depends on X86 || MIPS select BRCMUTIL select FW_LOADER select CRC_CCITT @@ -21,7 +21,7 @@ config BRCMFMAC default n depends on MMC depends on WLAN && CFG80211 - depends on !PPC64 && !PPC32 + depends on X86 || MIPS select BRCMUTIL select FW_LOADER select WIRELESS_EXT -- cgit v1.2.3 From a73738e9f85fa6ba3f1f9a6ea95b5e5fa99579a2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Jun 2011 14:43:34 -0700 Subject: Staging: comedi: fix build breakages on some platforms Some platforms do not have virt_to_bus(), so properly depend on CONFIG_VIRT_TO_BUS for the Comedi drivers that need this function. Reported-by: Stephen Rothwell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index bccdc12e843a..20008a4376e8 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -161,6 +161,7 @@ config COMEDI_PCL730 config COMEDI_PCL812 tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216" + depends on VIRT_TO_BUS default N ---help--- Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink @@ -172,6 +173,7 @@ config COMEDI_PCL812 config COMEDI_PCL816 tristate "Advantech PCL-814 and PCL-816 ISA card support" + depends on VIRT_TO_BUS default N ---help--- Enable support for Advantech PCL-814 and PCL-816 ISA cards @@ -181,6 +183,7 @@ config COMEDI_PCL816 config COMEDI_PCL818 tristate "Advantech PCL-718 and PCL-818 ISA card support" + depends on VIRT_TO_BUS default N ---help--- Enable support for Advantech PCL-818 ISA cards @@ -270,6 +273,7 @@ config COMEDI_DAS800 config COMEDI_DAS1800 tristate "DAS1800 and compatible ISA card support" + depends on VIRT_TO_BUS select COMEDI_FC default N ---help--- @@ -341,6 +345,7 @@ config COMEDI_DT2817 config COMEDI_DT282X tristate "Data Translation DT2821 series and DT-EZ ISA card support" select COMEDI_FC + depends on VIRT_TO_BUS default N ---help--- Enable support for Data Translation DT2821 series including DT-EZ @@ -420,6 +425,7 @@ config COMEDI_ADQ12B config COMEDI_NI_AT_A2150 tristate "NI AT-A2150 ISA card support" depends on COMEDI_NI_COMMON + depends on VIRT_TO_BUS default N ---help--- Enable support for National Instruments AT-A2150 cards @@ -537,6 +543,7 @@ if COMEDI_PCI_DRIVERS && PCI config COMEDI_ADDI_APCI_035 tristate "ADDI-DATA APCI_035 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_035 cards @@ -546,6 +553,7 @@ config COMEDI_ADDI_APCI_035 config COMEDI_ADDI_APCI_1032 tristate "ADDI-DATA APCI_1032 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_1032 cards @@ -555,6 +563,7 @@ config COMEDI_ADDI_APCI_1032 config COMEDI_ADDI_APCI_1500 tristate "ADDI-DATA APCI_1500 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_1500 cards @@ -564,6 +573,7 @@ config COMEDI_ADDI_APCI_1500 config COMEDI_ADDI_APCI_1516 tristate "ADDI-DATA APCI_1516 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_1516 cards @@ -573,6 +583,7 @@ config COMEDI_ADDI_APCI_1516 config COMEDI_ADDI_APCI_1564 tristate "ADDI-DATA APCI_1564 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_1564 cards @@ -582,6 +593,7 @@ config COMEDI_ADDI_APCI_1564 config COMEDI_ADDI_APCI_16XX tristate "ADDI-DATA APCI_16xx support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_16xx cards @@ -591,6 +603,7 @@ config COMEDI_ADDI_APCI_16XX config COMEDI_ADDI_APCI_2016 tristate "ADDI-DATA APCI_2016 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_2016 cards @@ -600,6 +613,7 @@ config COMEDI_ADDI_APCI_2016 config COMEDI_ADDI_APCI_2032 tristate "ADDI-DATA APCI_2032 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_2032 cards @@ -609,6 +623,7 @@ config COMEDI_ADDI_APCI_2032 config COMEDI_ADDI_APCI_2200 tristate "ADDI-DATA APCI_2200 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_2200 cards @@ -618,6 +633,7 @@ config COMEDI_ADDI_APCI_2200 config COMEDI_ADDI_APCI_3001 tristate "ADDI-DATA APCI_3001 support" + depends on VIRT_TO_BUS select COMEDI_FC default N ---help--- @@ -628,6 +644,7 @@ config COMEDI_ADDI_APCI_3001 config COMEDI_ADDI_APCI_3120 tristate "ADDI-DATA APCI_3520 support" + depends on VIRT_TO_BUS select COMEDI_FC default N ---help--- @@ -638,6 +655,7 @@ config COMEDI_ADDI_APCI_3120 config COMEDI_ADDI_APCI_3501 tristate "ADDI-DATA APCI_3501 support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_3501 cards @@ -647,6 +665,7 @@ config COMEDI_ADDI_APCI_3501 config COMEDI_ADDI_APCI_3XXX tristate "ADDI-DATA APCI_3xxx support" + depends on VIRT_TO_BUS default N ---help--- Enable support for ADDI-DATA APCI_3xxx cards @@ -713,6 +732,7 @@ config COMEDI_ADL_PCI9111 config COMEDI_ADL_PCI9118 tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support" select COMEDI_FC + depends on VIRT_TO_BUS default N ---help--- Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards @@ -1288,6 +1308,7 @@ config COMEDI_NI_LABPC depends on COMEDI_MITE select COMEDI_8255 select COMEDI_FC + depends on VIRT_TO_BUS default N ---help--- Enable support for National Instruments Lab-PC and compatibles -- cgit v1.2.3 From 5afa9d35782890e8fbd972f12ee5183ba5feb81d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 6 Jun 2011 11:25:19 -0600 Subject: i2c: tegra: Assign unused slave address On Tegra, we should always use the "new" I2C slave controller, to avoid issues with the old controller. This was implemented in commit 65a1a0a "i2c: tegra: Enable new slave mode." There is currently no driver for the Tegra I2C slave controller upstream. Additionally, the controller cannot be completely disabled. Instead, we need to: a) Set I2C_SL_CNFG_NACK to make the controller automatically NACK any incoming transactions. b) The controller's definition of NACK isn't identical to the I2C protocol's definition. Specifically, it will perform a standard NACK, but *also* continue to hold the clock line low in expectation of receiving more data. This can hang the bus, or at least cause transaction timeouts, if something starts a transaction that matches the controller's slave address. Since the default address is 0x00, the general call address, this does occur in practice. To avoid this, we explicitly program a slave address that is reserved for future expansion. For current boards, this guarantees the address will never be used. If a future board ever needs to use this address, we can add platform data to determine a board-specific safe address. 0xfc is picked by this patch. This patch is based on a change previously posted by: Wei Ni http://www.spinics.net/lists/linux-i2c/msg05437.html In turned based on internal changes by: Bharat Nihalani A semantically equivalent change has been contained in the various ChromeOS kernels for a while. I tested this change on top of 3.0-rc2 on Harmony, and interacted with the WM8903 I2C-based audio codec. Signed-off-by: Stephen Warren Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-tegra.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 4d9319665e32..fb3b4f8f8152 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -40,8 +40,10 @@ #define I2C_CNFG_NEW_MASTER_FSM (1<<11) #define I2C_STATUS 0x01C #define I2C_SL_CNFG 0x020 +#define I2C_SL_CNFG_NACK (1<<1) #define I2C_SL_CNFG_NEWSL (1<<2) #define I2C_SL_ADDR1 0x02c +#define I2C_SL_ADDR2 0x030 #define I2C_TX_FIFO 0x050 #define I2C_RX_FIFO 0x054 #define I2C_PACKET_TRANSFER_STATUS 0x058 @@ -337,7 +339,11 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (!i2c_dev->is_dvc) { u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); - i2c_writel(i2c_dev, sl_cfg | I2C_SL_CNFG_NEWSL, I2C_SL_CNFG); + sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL; + i2c_writel(i2c_dev, sl_cfg, I2C_SL_CNFG); + i2c_writel(i2c_dev, 0xfc, I2C_SL_ADDR1); + i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2); + } val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT | -- cgit v1.2.3 From 19820510c504d5ba572959c67a72d913afc187a6 Mon Sep 17 00:00:00 2001 From: Huisung Kang Date: Thu, 23 Jun 2011 21:37:33 +0900 Subject: i2c-s3c2410: Fix typo 'i2s' -> 'i2c' Signed-off-by: Huisung Kang Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 6c00c107ebf3..9ad18509c0c2 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -248,12 +248,12 @@ static inline int is_msgend(struct s3c24xx_i2c *i2c) return i2c->msg_ptr >= i2c->msg->len; } -/* i2s_s3c_irq_nextbyte +/* i2c_s3c_irq_nextbyte * * process an interrupt and work out what to do */ -static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) +static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) { unsigned long tmp; unsigned char byte; @@ -444,7 +444,7 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id) /* pretty much this leaves us with the fact that we've * transmitted or received whatever byte we last sent */ - i2s_s3c_irq_nextbyte(i2c, status); + i2c_s3c_irq_nextbyte(i2c, status); out: return IRQ_HANDLED; -- cgit v1.2.3 From b90ea76542c53300d39e76f72cf583cd0e0b1f68 Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Thu, 23 Jun 2011 21:37:20 +0900 Subject: i2c-s3c2410: Remove useless break code Signed-off-by: Jonghwan Choi Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 9ad18509c0c2..f84a63c6dd97 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -264,7 +264,6 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) case STATE_IDLE: dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__); goto out; - break; case STATE_STOP: dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); -- cgit v1.2.3 From 4a65163e3b2190445c1d94daa21d09c5af604d97 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 23 Jun 2011 17:07:54 -0400 Subject: i2c-bfin-twi: abort transfer is MEM bit is reset unexpectedly Sometimes, the first I2C transmit interrupt is not serviced in time (like when higher priority interrupts take too long). Since the RESTART bit is not set before the next I2C clock, when the TWI handler is finally called, the I2C session is aborted (MEM bit is reset) and both SMITSERV and MCOMP int status bits are set. So when this happens, abort the transfer. Reported-by: Isabelle Leonardi Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-bfin-twi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 52b545a795f2..cbc98aea5b09 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -193,7 +193,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, return; } if (twi_int_status & MCOMP) { - if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { + if ((read_MASTER_CTL(iface) & MEN) == 0 && + (iface->cur_mode == TWI_I2C_MODE_REPEAT || + iface->cur_mode == TWI_I2C_MODE_COMBINED)) { + iface->result = -1; + write_INT_MASK(iface, 0); + write_MASTER_CTL(iface, 0); + } else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { if (iface->readNum == 0) { /* set the read number to 1 and ask for manual * stop in block combine mode -- cgit v1.2.3 From 4d258b25d947521c8b913154db61ec55198243f8 Mon Sep 17 00:00:00 2001 From: Vitaliy Ivanov Date: Mon, 27 Jun 2011 19:07:08 +0300 Subject: Fix some kernel-doc warnings Fix 'make htmldocs' warnings: Warning(/include/linux/hrtimer.h:153): No description found for parameter 'clockid' Warning(/include/linux/device.h:604): Excess struct/union/enum/typedef member 'of_match' description in 'device' Warning(/include/net/sock.h:349): Excess struct/union/enum/typedef member 'sk_rmem_alloc' description in 'sock' Signed-off-by: Vitaliy Ivanov Acked-by: Grant Likely Acked-by: David S. Miller Signed-off-by: Linus Torvalds --- include/linux/device.h | 1 - include/linux/hrtimer.h | 1 + include/net/sock.h | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/device.h b/include/linux/device.h index 553fd37b173b..e4f62d8896b7 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -530,7 +530,6 @@ struct device_dma_parameters { * @dma_mem: Internal for coherent mem override. * @archdata: For arch-specific additions. * @of_node: Associated device tree node. - * @of_match: Matching of_device_id from driver. * @devt: For creating the sysfs "dev". * @devres_lock: Spinlock to protect the resource of the device. * @devres_head: The resources list of the device. diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 51932e5acf7c..fd0dc30c9f15 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -135,6 +135,7 @@ struct hrtimer_sleeper { * @cpu_base: per cpu clock base * @index: clock type index for per_cpu support when moving a * timer to a base on another cpu. + * @clockid: clock id for per_cpu support * @active: red black tree root node for the active timers * @resolution: the resolution of the clock, in nanoseconds * @get_time: function to retrieve the current time of the clock diff --git a/include/net/sock.h b/include/net/sock.h index f2046e404a61..c0b938cb4b1a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -178,7 +178,6 @@ struct sock_common { * @sk_dst_cache: destination cache * @sk_dst_lock: destination cache lock * @sk_policy: flow policy - * @sk_rmem_alloc: receive queue bytes committed * @sk_receive_queue: incoming packets * @sk_wmem_alloc: transmit queue bytes committed * @sk_write_queue: Packet sending queue -- cgit v1.2.3 From 5b8ba10198a109f8a02380648c5d29000caa9c55 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 27 Jun 2011 16:18:01 -0700 Subject: mm: move vmtruncate_range to truncate.c You would expect to find vmtruncate_range() next to vmtruncate() in mm/truncate.c: move it there. Signed-off-by: Hugh Dickins Acked-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 24 ------------------------ mm/truncate.c | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 87d935333f0d..40b7531ee8ba 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2798,30 +2798,6 @@ void unmap_mapping_range(struct address_space *mapping, } EXPORT_SYMBOL(unmap_mapping_range); -int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) -{ - struct address_space *mapping = inode->i_mapping; - - /* - * If the underlying filesystem is not going to provide - * a way to truncate a range of blocks (punch a hole) - - * we should return failure right now. - */ - if (!inode->i_op->truncate_range) - return -ENOSYS; - - mutex_lock(&inode->i_mutex); - down_write(&inode->i_alloc_sem); - unmap_mapping_range(mapping, offset, (end - offset), 1); - truncate_inode_pages_range(mapping, offset, end); - unmap_mapping_range(mapping, offset, (end - offset), 1); - inode->i_op->truncate_range(inode, offset, end); - up_write(&inode->i_alloc_sem); - mutex_unlock(&inode->i_mutex); - - return 0; -} - /* * We enter with non-exclusive mmap_sem (to exclude vma changes, * but allow concurrent faults), and pte mapped but not yet locked. diff --git a/mm/truncate.c b/mm/truncate.c index 3a29a6180212..5b4c3a4847e9 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -603,3 +603,27 @@ int vmtruncate(struct inode *inode, loff_t offset) return 0; } EXPORT_SYMBOL(vmtruncate); + +int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) +{ + struct address_space *mapping = inode->i_mapping; + + /* + * If the underlying filesystem is not going to provide + * a way to truncate a range of blocks (punch a hole) - + * we should return failure right now. + */ + if (!inode->i_op->truncate_range) + return -ENOSYS; + + mutex_lock(&inode->i_mutex); + down_write(&inode->i_alloc_sem); + unmap_mapping_range(mapping, offset, (end - offset), 1); + truncate_inode_pages_range(mapping, offset, end); + unmap_mapping_range(mapping, offset, (end - offset), 1); + inode->i_op->truncate_range(inode, offset, end); + up_write(&inode->i_alloc_sem); + mutex_unlock(&inode->i_mutex); + + return 0; +} -- cgit v1.2.3 From 072441e21ddcd1140606b7d4ef6eab579a86b0b3 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 27 Jun 2011 16:18:02 -0700 Subject: mm: move shmem prototypes to shmem_fs.h Before adding any more global entry points into shmem.c, gather such prototypes into shmem_fs.h. Remove mm's own declarations from swap.h, but for now leave the ones in mm.h: because shmem_file_setup() and shmem_zero_setup() are called from various places, and we should not force other subsystems to update immediately. Signed-off-by: Hugh Dickins Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/shmem_fs.h | 17 +++++++++++++++++ include/linux/swap.h | 10 ---------- mm/memcontrol.c | 1 + mm/swapfile.c | 2 +- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 2b7fec840517..cae65dc42bcc 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -5,6 +5,13 @@ #include #include +struct page; +struct file; +struct inode; +struct super_block; +struct user_struct; +struct vm_area_struct; + /* inode in-kernel data */ #define SHMEM_NR_DIRECT 16 @@ -45,7 +52,17 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode) return container_of(inode, struct shmem_inode_info, vfs_inode); } +/* + * Functions in mm/shmem.c called directly from elsewhere: + */ extern int init_tmpfs(void); extern int shmem_fill_super(struct super_block *sb, void *data, int silent); +extern struct file *shmem_file_setup(const char *name, + loff_t size, unsigned long flags); +extern int shmem_zero_setup(struct vm_area_struct *); +extern int shmem_lock(struct file *file, int lock, struct user_struct *user); +extern int shmem_unuse(swp_entry_t entry, struct page *page); +extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff, + struct page **pagep, swp_entry_t *ent); #endif diff --git a/include/linux/swap.h b/include/linux/swap.h index e70564647039..a273468f8285 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -300,16 +300,6 @@ static inline void scan_unevictable_unregister_node(struct node *node) extern int kswapd_run(int nid); extern void kswapd_stop(int nid); -#ifdef CONFIG_MMU -/* linux/mm/shmem.c */ -extern int shmem_unuse(swp_entry_t entry, struct page *page); -#endif /* CONFIG_MMU */ - -#ifdef CONFIG_CGROUP_MEM_RES_CTLR -extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff, - struct page **pagep, swp_entry_t *ent); -#endif - #ifdef CONFIG_SWAP /* linux/mm/page_io.c */ extern int swap_readpage(struct page *); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index cf7d027a8844..ddffc74cdebe 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/mm/swapfile.c b/mm/swapfile.c index d537d29e9b7b..ff8dc1a18cb4 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 94c1e62df4494b79782cb9c7279f827212d1de70 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 27 Jun 2011 16:18:03 -0700 Subject: tmpfs: take control of its truncate_range 2.6.35's new truncate convention gave tmpfs the opportunity to control its file truncation, no longer enforced from outside by vmtruncate(). We shall want to build upon that, to handle pagecache and swap together. Slightly redefine the ->truncate_range interface: let it now be called between the unmap_mapping_range()s, with the filesystem responsible for doing the truncate_inode_pages_range() from it - just as the filesystem is nowadays responsible for doing that from its ->setattr. Let's rename shmem_notify_change() to shmem_setattr(). Instead of calling the generic truncate_setsize(), bring that code in so we can call shmem_truncate_range() - which will later be updated to perform its own variant of truncate_inode_pages_range(). Remove the punch_hole unmap_mapping_range() from shmem_truncate_range(): now that the COW's unmap_mapping_range() comes after ->truncate_range, there is no need to call it a third time. Export shmem_truncate_range() and add it to the list in shmem_fs.h, so that i915_gem_object_truncate() can call it explicitly in future; get this patch in first, then update drm/i915 once this is available (until then, i915 will just be doing the truncate_inode_pages() twice). Though introduced five years ago, no other filesystem is implementing ->truncate_range, and its only other user is madvise(,,MADV_REMOVE): we expect to convert it to fallocate(,FALLOC_FL_PUNCH_HOLE,,) shortly, whereupon ->truncate_range can be removed from inode_operations - shmem_truncate_range() will help i915 across that transition too. Signed-off-by: Hugh Dickins Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/shmem_fs.h | 1 + mm/shmem.c | 51 +++++++++++++++++++++++++++--------------------- mm/truncate.c | 4 ++-- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index cae65dc42bcc..22a20af4d785 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -61,6 +61,7 @@ extern struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags); extern int shmem_zero_setup(struct vm_area_struct *); extern int shmem_lock(struct file *file, int lock, struct user_struct *user); +extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end); extern int shmem_unuse(swp_entry_t entry, struct page *page); extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff, struct page **pagep, swp_entry_t *ent); diff --git a/mm/shmem.c b/mm/shmem.c index d221a1cfd7b1..f1714758ea96 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -539,7 +539,7 @@ static void shmem_free_pages(struct list_head *next) } while (next); } -static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) +void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) { struct shmem_inode_info *info = SHMEM_I(inode); unsigned long idx; @@ -562,6 +562,8 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) spinlock_t *punch_lock; unsigned long upper_limit; + truncate_inode_pages_range(inode->i_mapping, start, end); + inode->i_ctime = inode->i_mtime = CURRENT_TIME; idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; if (idx >= info->next_index) @@ -738,16 +740,8 @@ done2: * lowered next_index. Also, though shmem_getpage checks * i_size before adding to cache, no recheck after: so fix the * narrow window there too. - * - * Recalling truncate_inode_pages_range and unmap_mapping_range - * every time for punch_hole (which never got a chance to clear - * SHMEM_PAGEIN at the start of vmtruncate_range) is expensive, - * yet hardly ever necessary: try to optimize them out later. */ truncate_inode_pages_range(inode->i_mapping, start, end); - if (punch_hole) - unmap_mapping_range(inode->i_mapping, start, - end - start, 1); } spin_lock(&info->lock); @@ -766,22 +760,23 @@ done2: shmem_free_pages(pages_to_free.next); } } +EXPORT_SYMBOL_GPL(shmem_truncate_range); -static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) +static int shmem_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; - loff_t newsize = attr->ia_size; int error; error = inode_change_ok(inode, attr); if (error) return error; - if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE) - && newsize != inode->i_size) { + if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { + loff_t oldsize = inode->i_size; + loff_t newsize = attr->ia_size; struct page *page = NULL; - if (newsize < inode->i_size) { + if (newsize < oldsize) { /* * If truncating down to a partial page, then * if that page is already allocated, hold it @@ -810,12 +805,19 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) spin_unlock(&info->lock); } } - - /* XXX(truncate): truncate_setsize should be called last */ - truncate_setsize(inode, newsize); + if (newsize != oldsize) { + i_size_write(inode, newsize); + inode->i_ctime = inode->i_mtime = CURRENT_TIME; + } + if (newsize < oldsize) { + loff_t holebegin = round_up(newsize, PAGE_SIZE); + unmap_mapping_range(inode->i_mapping, holebegin, 0, 1); + shmem_truncate_range(inode, newsize, (loff_t)-1); + /* unmap again to remove racily COWed private pages */ + unmap_mapping_range(inode->i_mapping, holebegin, 0, 1); + } if (page) page_cache_release(page); - shmem_truncate_range(inode, newsize, (loff_t)-1); } setattr_copy(inode, attr); @@ -832,7 +834,6 @@ static void shmem_evict_inode(struct inode *inode) struct shmem_xattr *xattr, *nxattr; if (inode->i_mapping->a_ops == &shmem_aops) { - truncate_inode_pages(inode->i_mapping, 0); shmem_unacct_size(info->flags, inode->i_size); inode->i_size = 0; shmem_truncate_range(inode, 0, (loff_t)-1); @@ -2706,7 +2707,7 @@ static const struct file_operations shmem_file_operations = { }; static const struct inode_operations shmem_inode_operations = { - .setattr = shmem_notify_change, + .setattr = shmem_setattr, .truncate_range = shmem_truncate_range, #ifdef CONFIG_TMPFS_XATTR .setxattr = shmem_setxattr, @@ -2739,7 +2740,7 @@ static const struct inode_operations shmem_dir_inode_operations = { .removexattr = shmem_removexattr, #endif #ifdef CONFIG_TMPFS_POSIX_ACL - .setattr = shmem_notify_change, + .setattr = shmem_setattr, .check_acl = generic_check_acl, #endif }; @@ -2752,7 +2753,7 @@ static const struct inode_operations shmem_special_inode_operations = { .removexattr = shmem_removexattr, #endif #ifdef CONFIG_TMPFS_POSIX_ACL - .setattr = shmem_notify_change, + .setattr = shmem_setattr, .check_acl = generic_check_acl, #endif }; @@ -2908,6 +2909,12 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user) return 0; } +void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) +{ + truncate_inode_pages_range(inode->i_mapping, start, end); +} +EXPORT_SYMBOL_GPL(shmem_truncate_range); + #ifdef CONFIG_CGROUP_MEM_RES_CTLR /** * mem_cgroup_get_shmem_target - find a page or entry assigned to the shmem file diff --git a/mm/truncate.c b/mm/truncate.c index 5b4c3a4847e9..29a9b8a5a31a 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -619,9 +619,9 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) mutex_lock(&inode->i_mutex); down_write(&inode->i_alloc_sem); unmap_mapping_range(mapping, offset, (end - offset), 1); - truncate_inode_pages_range(mapping, offset, end); - unmap_mapping_range(mapping, offset, (end - offset), 1); inode->i_op->truncate_range(inode, offset, end); + /* unmap again to remove racily COWed private pages */ + unmap_mapping_range(mapping, offset, (end - offset), 1); up_write(&inode->i_alloc_sem); mutex_unlock(&inode->i_mutex); -- cgit v1.2.3 From d9d90e5eb70e09903dadff42099b6c948f814050 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 27 Jun 2011 16:18:04 -0700 Subject: tmpfs: add shmem_read_mapping_page_gfp Although it is used (by i915) on nothing but tmpfs, read_cache_page_gfp() is unsuited to tmpfs, because it inserts a page into pagecache before calling the filesystem's ->readpage: tmpfs may have pages in swapcache which only it knows how to locate and switch to filecache. At present tmpfs provides a ->readpage method, and copes with this by copying pages; but soon we can simplify it by removing its ->readpage. Provide shmem_read_mapping_page_gfp() now, ready for that transition, Export shmem_read_mapping_page_gfp() and add it to list in shmem_fs.h, with shmem_read_mapping_page() inline for the common mapping_gfp case. (shmem_read_mapping_page_gfp or shmem_read_cache_page_gfp? Generally the read_mapping_page functions use the mapping's ->readpage, and the read_cache_page functions use the supplied filler, so I think read_cache_page_gfp was slightly misnamed.) Signed-off-by: Hugh Dickins Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/shmem_fs.h | 17 ++++++++++------- mm/shmem.c | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 22a20af4d785..aa08fa8fd79b 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -3,15 +3,9 @@ #include #include +#include #include -struct page; -struct file; -struct inode; -struct super_block; -struct user_struct; -struct vm_area_struct; - /* inode in-kernel data */ #define SHMEM_NR_DIRECT 16 @@ -61,9 +55,18 @@ extern struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags); extern int shmem_zero_setup(struct vm_area_struct *); extern int shmem_lock(struct file *file, int lock, struct user_struct *user); +extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, + pgoff_t index, gfp_t gfp_mask); extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end); extern int shmem_unuse(swp_entry_t entry, struct page *page); extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff, struct page **pagep, swp_entry_t *ent); +static inline struct page *shmem_read_mapping_page( + struct address_space *mapping, pgoff_t index) +{ + return shmem_read_mapping_page_gfp(mapping, index, + mapping_gfp_mask(mapping)); +} + #endif diff --git a/mm/shmem.c b/mm/shmem.c index f1714758ea96..fcedf5464eb7 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3035,3 +3035,26 @@ int shmem_zero_setup(struct vm_area_struct *vma) vma->vm_flags |= VM_CAN_NONLINEAR; return 0; } + +/** + * shmem_read_mapping_page_gfp - read into page cache, using specified page allocation flags. + * @mapping: the page's address_space + * @index: the page index + * @gfp: the page allocator flags to use if allocating + * + * This behaves as a tmpfs "read_cache_page_gfp(mapping, index, gfp)", + * with any new page allocations done using the specified allocation flags. + * But read_cache_page_gfp() uses the ->readpage() method: which does not + * suit tmpfs, since it may have pages in swapcache, and needs to find those + * for itself; although drivers/gpu/drm i915 and ttm rely upon this support. + * + * Provide a stub for those callers to start using now, then later + * flesh it out to call shmem_getpage() with additional gfp mask, when + * shmem_file_splice_read() is added and shmem_readpage() is removed. + */ +struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, + pgoff_t index, gfp_t gfp) +{ + return read_cache_page_gfp(mapping, index, gfp); +} +EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp); -- cgit v1.2.3 From 31c1771cdbf0edea96e109e24dae387d331b6d96 Mon Sep 17 00:00:00 2001 From: Priyanka Jain Date: Mon, 27 Jun 2011 16:18:04 -0700 Subject: drivers/rtc/rtc-ds1307.c: add support for RTC device pt7c4338 PT7C4338 chip is being manufactured by Pericom Technology Inc. It is a serial real-time clock which provides: 1) Low-power clock/calendar. 2) Programmable square-wave output. It has 56 bytes of nonvolatile RAM. Its register set is same as that of rtc device: DS1307. Signed-off-by: Priyanka Jain Acked-by: Timur Tabi Reviewed-by: Wolfram Sang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds1307.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 4724ba3acf1a..b2005b44e4f7 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -149,6 +149,7 @@ static const struct i2c_device_id ds1307_id[] = { { "ds1340", ds_1340 }, { "ds3231", ds_3231 }, { "m41t00", m41t00 }, + { "pt7c4338", ds_1307 }, { "rx8025", rx_8025 }, { } }; -- cgit v1.2.3 From 8c95aa60d2ae3c4e63705ee0f18e155898b09662 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 27 Jun 2011 16:18:05 -0700 Subject: um: add asm/percpu.h To make SLUB work on UML we need this_cpu_cmpxchg from asm-generic/percpu.h. Signed-off-by: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/asm/percpu.h | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 arch/um/include/asm/percpu.h diff --git a/arch/um/include/asm/percpu.h b/arch/um/include/asm/percpu.h new file mode 100644 index 000000000000..efe7508d8abd --- /dev/null +++ b/arch/um/include/asm/percpu.h @@ -0,0 +1,6 @@ +#ifndef __UM_PERCPU_H +#define __UM_PERCPU_H + +#include + +#endif /* __UM_PERCPU_H */ -- cgit v1.2.3 From 2b4b2482e70eba10dd98653a3a5ac68126565e24 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Mon, 27 Jun 2011 16:18:06 -0700 Subject: romfs: fix romfs_get_unmapped_area() argument check romfs_get_unmapped_area() checks argument `len' without considering PAGE_ALIGN which will cause do_mmap_pgoff() return -EINVAL error after commit f67d9b1576c ("nommu: add page_align to mmap"). Fix the check by changing it in same way ramfs_nommu_get_unmapped_area() was changed in ramfs/file-nommu.c. Signed-off-by: Bob Liu Cc: David Howells Cc: Paul Mundt Acked-by: Greg Ungerer Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/romfs/mmap-nommu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/romfs/mmap-nommu.c b/fs/romfs/mmap-nommu.c index f0511e816967..eed99428f104 100644 --- a/fs/romfs/mmap-nommu.c +++ b/fs/romfs/mmap-nommu.c @@ -27,14 +27,18 @@ static unsigned long romfs_get_unmapped_area(struct file *file, { struct inode *inode = file->f_mapping->host; struct mtd_info *mtd = inode->i_sb->s_mtd; - unsigned long isize, offset; + unsigned long isize, offset, maxpages, lpages; if (!mtd) goto cant_map_directly; + /* the mapping mustn't extend beyond the EOF */ + lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; isize = i_size_read(inode); offset = pgoff << PAGE_SHIFT; - if (offset > isize || len > isize || offset > isize - len) + + maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT; + if ((pgoff >= maxpages) || (maxpages - pgoff < lpages)) return (unsigned long) -EINVAL; /* we need to call down to the MTD layer to do the actual mapping */ -- cgit v1.2.3 From 507c5f1224014f9956e604ee8703b3bbea7da4a4 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Mon, 27 Jun 2011 16:18:07 -0700 Subject: include/linux/compat.h: declare compat_sys_sendmmsg() This is required for tilegx to be able to use the compat unistd.h header where compat_sys_sendmmsg() is now mentioned. Signed-off-by: Chris Metcalf Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compat.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/compat.h b/include/linux/compat.h index ddcb7db38e67..846bb1792572 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -467,6 +467,8 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, char __user *optval, unsigned int optlen); asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags); +asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, + unsigned vlen, unsigned int flags); asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags); asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, -- cgit v1.2.3 From aa2c96d6f329e66cc59352b0f12e8f04e6a9593b Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Mon, 27 Jun 2011 16:18:08 -0700 Subject: drivers/misc/lkdtm.c: fix race when crashpoint is hit multiple times before checking count We observed the crash point count going negative in cases where the crash point is hit multiple times before the check of "count == 0" is done. Because of this we never call lkdtm_do_action(). This patch just adds a spinlock to protect count. Reported-by: Tapan Dhimant Signed-off-by: Josh Hunt Acked-by: Ankita Garg Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/lkdtm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 81d7fa4ec0db..150cd7061b80 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -120,6 +120,7 @@ static int recur_count = REC_NUM_DEFAULT; static enum cname cpoint = CN_INVALID; static enum ctype cptype = CT_NONE; static int count = DEFAULT_COUNT; +static DEFINE_SPINLOCK(count_lock); module_param(recur_count, int, 0644); MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ @@ -230,11 +231,14 @@ static const char *cp_name_to_str(enum cname name) static int lkdtm_parse_commandline(void) { int i; + unsigned long flags; if (cpoint_count < 1 || recur_count < 1) return -EINVAL; + spin_lock_irqsave(&count_lock, flags); count = cpoint_count; + spin_unlock_irqrestore(&count_lock, flags); /* No special parameters */ if (!cpoint_type && !cpoint_name) @@ -349,6 +353,9 @@ static void lkdtm_do_action(enum ctype which) static void lkdtm_handler(void) { + unsigned long flags; + + spin_lock_irqsave(&count_lock, flags); count--; printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n", cp_name_to_str(cpoint), cp_type_to_str(cptype), count); @@ -357,6 +364,7 @@ static void lkdtm_handler(void) lkdtm_do_action(cptype); count = cpoint_count; } + spin_unlock_irqrestore(&count_lock, flags); } static int lkdtm_register_cpoint(enum cname which) -- cgit v1.2.3 From 9b679320a5fbf46454011e5c62e0b8991b0956d1 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 27 Jun 2011 16:18:09 -0700 Subject: mm/memory-failure.c: fix spinlock vs mutex order We cannot take a mutex while holding a spinlock, so flip the order and fix the locking documentation. Signed-off-by: Peter Zijlstra Acked-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory-failure.c | 21 ++++++--------------- mm/rmap.c | 5 ++--- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index eac0ba561491..740c4f52059c 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -391,10 +391,11 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill, struct task_struct *tsk; struct anon_vma *av; - read_lock(&tasklist_lock); av = page_lock_anon_vma(page); if (av == NULL) /* Not actually mapped anymore */ - goto out; + return; + + read_lock(&tasklist_lock); for_each_process (tsk) { struct anon_vma_chain *vmac; @@ -408,9 +409,8 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill, add_to_kill(tsk, page, vma, to_kill, tkc); } } - page_unlock_anon_vma(av); -out: read_unlock(&tasklist_lock); + page_unlock_anon_vma(av); } /* @@ -424,17 +424,8 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill, struct prio_tree_iter iter; struct address_space *mapping = page->mapping; - /* - * A note on the locking order between the two locks. - * We don't rely on this particular order. - * If you have some other code that needs a different order - * feel free to switch them around. Or add a reverse link - * from mm_struct to task_struct, then this could be all - * done without taking tasklist_lock and looping over all tasks. - */ - - read_lock(&tasklist_lock); mutex_lock(&mapping->i_mmap_mutex); + read_lock(&tasklist_lock); for_each_process(tsk) { pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); @@ -454,8 +445,8 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill, add_to_kill(tsk, page, vma, to_kill, tkc); } } - mutex_unlock(&mapping->i_mmap_mutex); read_unlock(&tasklist_lock); + mutex_unlock(&mapping->i_mmap_mutex); } /* diff --git a/mm/rmap.c b/mm/rmap.c index 27dfd3b82b0f..23295f65ae43 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -38,9 +38,8 @@ * in arch-dependent flush_dcache_mmap_lock, * within inode_wb_list_lock in __sync_single_inode) * - * (code doesn't rely on that order so it could be switched around) - * ->tasklist_lock - * anon_vma->mutex (memory_failure, collect_procs_anon) + * anon_vma->mutex,mapping->i_mutex (memory_failure, collect_procs_anon) + * ->tasklist_lock * pte map lock */ -- cgit v1.2.3 From 08142579b6ca35883c1ed066a2681de6f6917062 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 27 Jun 2011 16:18:10 -0700 Subject: mm: fix assertion mapping->nrpages == 0 in end_writeback() Under heavy memory and filesystem load, users observe the assertion mapping->nrpages == 0 in end_writeback() trigger. This can be caused by page reclaim reclaiming the last page from a mapping in the following race: CPU0 CPU1 ... shrink_page_list() __remove_mapping() __delete_from_page_cache() radix_tree_delete() evict_inode() truncate_inode_pages() truncate_inode_pages_range() pagevec_lookup() - finds nothing end_writeback() mapping->nrpages != 0 -> BUG page->mapping = NULL mapping->nrpages-- Fix the problem by doing a reliable check of mapping->nrpages under mapping->tree_lock in end_writeback(). Analyzed by Jay , lost in LKML, and dug out by Miklos Szeredi . Cc: Jay Cc: Miklos Szeredi Signed-off-by: Jan Kara Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/inode.c | 7 +++++++ include/linux/fs.h | 1 + mm/truncate.c | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/fs/inode.c b/fs/inode.c index 0f7e88a7803f..43566d17d1b8 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -423,7 +423,14 @@ EXPORT_SYMBOL(remove_inode_hash); void end_writeback(struct inode *inode) { might_sleep(); + /* + * We have to cycle tree_lock here because reclaim can be still in the + * process of removing the last page (in __delete_from_page_cache()) + * and we must not free mapping under it. + */ + spin_lock_irq(&inode->i_data.tree_lock); BUG_ON(inode->i_data.nrpages); + spin_unlock_irq(&inode->i_data.tree_lock); BUG_ON(!list_empty(&inode->i_data.private_list)); BUG_ON(!(inode->i_state & I_FREEING)); BUG_ON(inode->i_state & I_CLEAR); diff --git a/include/linux/fs.h b/include/linux/fs.h index 6e73e2e9ae33..b5b979247863 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -639,6 +639,7 @@ struct address_space { struct prio_tree_root i_mmap; /* tree of private and shared mappings */ struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */ struct mutex i_mmap_mutex; /* protect tree, count, list */ + /* Protected by tree_lock together with the radix tree */ unsigned long nrpages; /* number of total pages */ pgoff_t writeback_index;/* writeback starts here */ const struct address_space_operations *a_ops; /* methods */ diff --git a/mm/truncate.c b/mm/truncate.c index 29a9b8a5a31a..e13f22efaad7 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -304,6 +304,11 @@ EXPORT_SYMBOL(truncate_inode_pages_range); * @lstart: offset from which to truncate * * Called under (and serialised by) inode->i_mutex. + * + * Note: When this function returns, there can be a page in the process of + * deletion (inside __delete_from_page_cache()) in the specified range. Thus + * mapping->nrpages can be non-zero when this function returns even after + * truncation of the whole mapping. */ void truncate_inode_pages(struct address_space *mapping, loff_t lstart) { -- cgit v1.2.3 From 26c4caea9d697043cc5a458b96411b86d7f6babd Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Mon, 27 Jun 2011 16:18:11 -0700 Subject: taskstats: don't allow duplicate entries in listener mode Currently a single process may register exit handlers unlimited times. It may lead to a bloated listeners chain and very slow process terminations. Eg after 10KK sent TASKSTATS_CMD_ATTR_REGISTER_CPUMASKs ~300 Mb of kernel memory is stolen for the handlers chain and "time id" shows 2-7 seconds instead of normal 0.003. It makes it possible to exhaust all kernel memory and to eat much of CPU time by triggerring numerous exits on a single CPU. The patch limits the number of times a single process may register itself on a single CPU to one. One little issue is kept unfixed - as taskstats_exit() is called before exit_files() in do_exit(), the orphaned listener entry (if it was not explicitly deregistered) is kept until the next someone's exit() and implicit deregistration in send_cpu_listeners(). So, if a process registered itself as a listener exits and the next spawned process gets the same pid, it would inherit taskstats attributes. Signed-off-by: Vasiliy Kulikov Cc: Balbir Singh Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/taskstats.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 9ffea360a778..fc0f22005417 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -285,16 +285,18 @@ ret: static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) { struct listener_list *listeners; - struct listener *s, *tmp; + struct listener *s, *tmp, *s2; unsigned int cpu; if (!cpumask_subset(mask, cpu_possible_mask)) return -EINVAL; + s = NULL; if (isadd == REGISTER) { for_each_cpu(cpu, mask) { - s = kmalloc_node(sizeof(struct listener), GFP_KERNEL, - cpu_to_node(cpu)); + if (!s) + s = kmalloc_node(sizeof(struct listener), + GFP_KERNEL, cpu_to_node(cpu)); if (!s) goto cleanup; s->pid = pid; @@ -303,9 +305,16 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) listeners = &per_cpu(listener_array, cpu); down_write(&listeners->sem); + list_for_each_entry_safe(s2, tmp, &listeners->list, list) { + if (s2->pid == pid) + goto next_cpu; + } list_add(&s->list, &listeners->list); + s = NULL; +next_cpu: up_write(&listeners->sem); } + kfree(s); return 0; } -- cgit v1.2.3 From ac34a1a3c39da0a1b9188d12a9ce85506364ed2a Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Mon, 27 Jun 2011 16:18:12 -0700 Subject: memcg: fix direct softlimit reclaim to be called in limit path Commit d149e3b25d7c ("memcg: add the soft_limit reclaim in global direct reclaim") adds a softlimit hook to shrink_zones(). By this, soft limit is called as try_to_free_pages() do_try_to_free_pages() shrink_zones() mem_cgroup_soft_limit_reclaim() Then, direct reclaim is memcg softlimit hint aware, now. But, the memory cgroup's "limit" path can call softlimit shrinker. try_to_free_mem_cgroup_pages() do_try_to_free_pages() shrink_zones() mem_cgroup_soft_limit_reclaim() This will cause a global reclaim when a memcg hits limit. This is bug. soft_limit_reclaim() should be called when scanning_global_lru(sc) == true. And the commit adds a variable "total_scanned" for counting softlimit scanned pages....it's not "total". This patch removes the variable and update sc->nr_scanned instead of it. This will affect shrink_slab()'s scan condition but, global LRU is scanned by softlimit and I think this change makes sense. TODO: avoid too much scanning of a zone when softlimit did enough work. Signed-off-by: KAMEZAWA Hiroyuki Cc: Daisuke Nishimura Cc: Ying Han Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 8ff834e19c24..4f49535d4cd3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1995,14 +1995,13 @@ restart: * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it. */ -static unsigned long shrink_zones(int priority, struct zonelist *zonelist, +static void shrink_zones(int priority, struct zonelist *zonelist, struct scan_control *sc) { struct zoneref *z; struct zone *zone; unsigned long nr_soft_reclaimed; unsigned long nr_soft_scanned; - unsigned long total_scanned = 0; for_each_zone_zonelist_nodemask(zone, z, zonelist, gfp_zone(sc->gfp_mask), sc->nodemask) { @@ -2017,19 +2016,23 @@ static unsigned long shrink_zones(int priority, struct zonelist *zonelist, continue; if (zone->all_unreclaimable && priority != DEF_PRIORITY) continue; /* Let kswapd poll it */ + /* + * This steals pages from memory cgroups over softlimit + * and returns the number of reclaimed pages and + * scanned pages. This works for global memory pressure + * and balancing, not for a memcg's limit. + */ + nr_soft_scanned = 0; + nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone, + sc->order, sc->gfp_mask, + &nr_soft_scanned); + sc->nr_reclaimed += nr_soft_reclaimed; + sc->nr_scanned += nr_soft_scanned; + /* need some check for avoid more shrink_zone() */ } - nr_soft_scanned = 0; - nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone, - sc->order, sc->gfp_mask, - &nr_soft_scanned); - sc->nr_reclaimed += nr_soft_reclaimed; - total_scanned += nr_soft_scanned; - shrink_zone(priority, zone, sc); } - - return total_scanned; } static bool zone_reclaimable(struct zone *zone) @@ -2094,7 +2097,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, sc->nr_scanned = 0; if (!priority) disable_swap_token(sc->mem_cgroup); - total_scanned += shrink_zones(priority, zonelist, sc); + shrink_zones(priority, zonelist, sc); /* * Don't shrink slabs when reclaiming memory from * over limit cgroups -- cgit v1.2.3 From 5286bd953645408634daa880d04c73dd18d0224a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 27 Jun 2011 16:18:13 -0700 Subject: drivers/leds/leds-lp5521.c: fix section mismatches Fix this section mismatch: WARNING: drivers/leds/leds-lp5521.o(.text+0xf2c): Section mismatch in reference from the function lp5521_probe() to the function .init.text:lp5521_init_led() The function lp5521_probe() references the function __init lp5521_init_led(). This is often because lp5521_probe lacks a __init annotation or the annotation of lp5521_init_led is wrong. Fixing this mismatch triggers one more mismatch, fix that one as well. Signed-off-by: Ralf Baechle Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-lp5521.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index c0cff64a1ae6..cc1dc4817fac 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -593,7 +593,7 @@ static void lp5521_unregister_sysfs(struct i2c_client *client) &lp5521_led_attribute_group); } -static int __init lp5521_init_led(struct lp5521_led *led, +static int __devinit lp5521_init_led(struct lp5521_led *led, struct i2c_client *client, int chan, struct lp5521_platform_data *pdata) { @@ -637,7 +637,7 @@ static int __init lp5521_init_led(struct lp5521_led *led, return 0; } -static int lp5521_probe(struct i2c_client *client, +static int __devinit lp5521_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct lp5521_chip *chip; -- cgit v1.2.3 From 33721bd3d00e7a235f70ba4ec19eb64bcd060c0b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 27 Jun 2011 16:18:14 -0700 Subject: drivers/leds/leds-lp5523.c: fix section mismatches Fix this section mismatch: WARNING: drivers/leds/leds-lp5523.o(.text+0x12f4): Section mismatch in reference from the function lp5523_probe() to the function .init.text:lp5523_init_led() The function lp5523_probe() references the function __init lp5523_init_led(). This is often because lp5523_probe lacks a __init annotation or the annotation of lp5523_init_led is wrong. Fixing this one triggers one more mismatch, fix that one as well. Signed-off-by: Ralf Baechle Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-lp5523.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index e19fed25f137..5971e309b234 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -826,7 +826,7 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id) return 0; } -static int __init lp5523_init_led(struct lp5523_led *led, struct device *dev, +static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev, int chan, struct lp5523_platform_data *pdata) { char name[32]; @@ -872,7 +872,7 @@ static int __init lp5523_init_led(struct lp5523_led *led, struct device *dev, static struct i2c_driver lp5523_driver; -static int lp5523_probe(struct i2c_client *client, +static int __devinit lp5523_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct lp5523_chip *chip; -- cgit v1.2.3 From 1fc6e987d8f606371337211f52ff74c6753298a6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 27 Jun 2011 16:18:15 -0700 Subject: drivers/misc/ioc4.c: fix section mismatch / race condition Fix this section mismatch: WARNING: drivers/misc/ioc4.o(.data+0x144): Section mismatch in reference from the variable ioc4_load_modules_work to the function .devinit.text:ioc4_load_modules() The variable ioc4_load_modules_work references the function __devinit ioc4_load_modules() If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console This one is potentially fatal; by the time ioc4_load_modules is invoked it may already have been freed. For that reason ioc4_load_modules_work can't be turned to __devinitdata but also because it's referenced in ioc4_exit. Signed-off-by: Ralf Baechle Acked-by: Brent Casavant Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/ioc4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 668d41e594a9..df03dd3bd0e2 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c @@ -270,7 +270,7 @@ ioc4_variant(struct ioc4_driver_data *idd) return IOC4_VARIANT_PCI_RT; } -static void __devinit +static void ioc4_load_modules(struct work_struct *work) { request_module("sgiioc4"); -- cgit v1.2.3 From a39bce7bf60e728cb33b6b0415c3f44e7f1a102b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 27 Jun 2011 16:18:16 -0700 Subject: drivers/tty/serial/8250_pci.c: fix warning Fis the warning drivers/tty/serial/8250_pci.c:1457: warning: initialization from incompatible pointer type Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/tty/serial/8250_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 4b4968a294b2..78e98a5cef96 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -973,7 +973,7 @@ ce4100_serial_setup(struct serial_private *priv, static int pci_omegapci_setup(struct serial_private *priv, - struct pciserial_board *board, + const struct pciserial_board *board, struct uart_port *port, int idx) { return setup_port(priv, port, 2, idx * 8, 0); -- cgit v1.2.3 From 3142b651ad2232cf0e375c291ee4b893c8559df5 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 27 Jun 2011 16:18:17 -0700 Subject: drm/ttm: use shmem_read_mapping_page Soon tmpfs will stop supporting ->readpage and read_mapping_page(): once "tmpfs: add shmem_read_mapping_page_gfp" has been applied, this patch can be applied to ease the transition. ttm_tt_swapin() and ttm_tt_swapout() use shmem_read_mapping_page() in place of read_mapping_page(), since their swap_space has been created with shmem_file_setup(). Signed-off-by: Hugh Dickins Cc: Christoph Hellwig Cc: Thomas Hellstrom Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpu/drm/ttm/ttm_tt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 90e23e0bfadb..58c271ebc0f7 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -484,7 +485,7 @@ static int ttm_tt_swapin(struct ttm_tt *ttm) swap_space = swap_storage->f_path.dentry->d_inode->i_mapping; for (i = 0; i < ttm->num_pages; ++i) { - from_page = read_mapping_page(swap_space, i, NULL); + from_page = shmem_read_mapping_page(swap_space, i); if (IS_ERR(from_page)) { ret = PTR_ERR(from_page); goto out_err; @@ -557,7 +558,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) from_page = ttm->pages[i]; if (unlikely(from_page == NULL)) continue; - to_page = read_mapping_page(swap_space, i, NULL); + to_page = shmem_read_mapping_page(swap_space, i); if (unlikely(IS_ERR(to_page))) { ret = PTR_ERR(to_page); goto out_err; -- cgit v1.2.3 From 5949eac4d9b5bf936c12cb7ec3a09084c1326834 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 27 Jun 2011 16:18:18 -0700 Subject: drm/i915: use shmem_read_mapping_page Soon tmpfs will stop supporting ->readpage and read_cache_page_gfp(): once "tmpfs: add shmem_read_mapping_page_gfp" has been applied, this patch can be applied to ease the transition. Make i915_gem_object_get_pages_gtt() use shmem_read_mapping_page_gfp() in the one place it's needed; elsewhere use shmem_read_mapping_page(), with the mapping's gfp_mask properly initialized. Forget about __GFP_COLD: since tmpfs initializes its pages with memset, asking for a cold page is counter-productive. Include linux/shmem_fs.h also in drm_gem.c: with shmem_file_setup() now declared there too, we shall remove the prototype from linux/mm.h later. Signed-off-by: Hugh Dickins Cc: Christoph Hellwig Cc: Chris Wilson Cc: Keith Packard Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpu/drm/drm_gem.c | 1 + drivers/gpu/drm/i915/i915_gem.c | 31 ++++++++++++++----------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 74e4ff578017..4012fe423460 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "drmP.h" /** @file drm_gem.c diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c6389de53161..fa560ceba667 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -31,6 +31,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_drv.h" +#include #include #include #include @@ -359,8 +360,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, if ((page_offset + remain) > PAGE_SIZE) page_length = PAGE_SIZE - page_offset; - page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, - GFP_HIGHUSER | __GFP_RECLAIMABLE); + page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); if (IS_ERR(page)) return PTR_ERR(page); @@ -463,8 +463,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, if ((data_page_offset + page_length) > PAGE_SIZE) page_length = PAGE_SIZE - data_page_offset; - page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, - GFP_HIGHUSER | __GFP_RECLAIMABLE); + page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); if (IS_ERR(page)) { ret = PTR_ERR(page); goto out; @@ -797,8 +796,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, if ((page_offset + remain) > PAGE_SIZE) page_length = PAGE_SIZE - page_offset; - page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, - GFP_HIGHUSER | __GFP_RECLAIMABLE); + page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); if (IS_ERR(page)) return PTR_ERR(page); @@ -907,8 +905,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, if ((data_page_offset + page_length) > PAGE_SIZE) page_length = PAGE_SIZE - data_page_offset; - page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, - GFP_HIGHUSER | __GFP_RECLAIMABLE); + page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); if (IS_ERR(page)) { ret = PTR_ERR(page); goto out; @@ -1558,12 +1555,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, inode = obj->base.filp->f_path.dentry->d_inode; mapping = inode->i_mapping; + gfpmask |= mapping_gfp_mask(mapping); + for (i = 0; i < page_count; i++) { - page = read_cache_page_gfp(mapping, i, - GFP_HIGHUSER | - __GFP_COLD | - __GFP_RECLAIMABLE | - gfpmask); + page = shmem_read_mapping_page_gfp(mapping, i, gfpmask); if (IS_ERR(page)) goto err_pages; @@ -3565,6 +3560,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; + struct address_space *mapping; obj = kzalloc(sizeof(*obj), GFP_KERNEL); if (obj == NULL) @@ -3575,6 +3571,9 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, return NULL; } + mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; + mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE); + i915_gem_info_add_obj(dev_priv, size); obj->base.write_domain = I915_GEM_DOMAIN_CPU; @@ -3950,8 +3949,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev, page_count = obj->base.size / PAGE_SIZE; for (i = 0; i < page_count; i++) { - struct page *page = read_cache_page_gfp(mapping, i, - GFP_HIGHUSER | __GFP_RECLAIMABLE); + struct page *page = shmem_read_mapping_page(mapping, i); if (!IS_ERR(page)) { char *dst = kmap_atomic(page); memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE); @@ -4012,8 +4010,7 @@ i915_gem_attach_phys_object(struct drm_device *dev, struct page *page; char *dst, *src; - page = read_cache_page_gfp(mapping, i, - GFP_HIGHUSER | __GFP_RECLAIMABLE); + page = shmem_read_mapping_page(mapping, i); if (IS_ERR(page)) return PTR_ERR(page); -- cgit v1.2.3 From e2377fe0b65e3c7577ff6df1701c56ef477d336f Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 27 Jun 2011 16:18:19 -0700 Subject: drm/i915: use shmem_truncate_range The interface to ->truncate_range is changing very slightly: once "tmpfs: take control of its truncate_range" has been applied, this can be applied. For now there is only a slight inefficiency while this remains unapplied, but it will soon become essential for managing shmem's use of swap. Change i915_gem_object_truncate() to use shmem_truncate_range() directly: which should also spare i915 later change if we switch from inode_operations->truncate_range to file_operations->fallocate. Signed-off-by: Hugh Dickins Cc: Christoph Hellwig Cc: Chris Wilson Cc: Keith Packard Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/i915_gem.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fa560ceba667..85f713746a1f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1696,13 +1696,10 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj) /* Our goal here is to return as much of the memory as * is possible back to the system as we are called from OOM. * To do this we must instruct the shmfs to drop all of its - * backing pages, *now*. Here we mirror the actions taken - * when by shmem_delete_inode() to release the backing store. + * backing pages, *now*. */ inode = obj->base.filp->f_path.dentry->d_inode; - truncate_inode_pages(inode->i_mapping, 0); - if (inode->i_op->truncate_range) - inode->i_op->truncate_range(inode, 0, (loff_t)-1); + shmem_truncate_range(inode, 0, (loff_t)-1); obj->madv = __I915_MADV_PURGED; } -- cgit v1.2.3 From ecbec53b1d00ba582f71b210ed96cafc05ebd189 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 27 Jun 2011 16:18:20 -0700 Subject: drm/i915: more struct_mutex locking When auditing the locking in i915_gem.c (for a prospective change which I then abandoned), I noticed two places where struct_mutex is not held across GEM object manipulations that would usually require it. Since one is in initial setup and the other in driver unload, I'm guessing the mutex is not required for either; but post a patch in case it is. Signed-off-by: Hugh Dickins Cc: Chris Wilson Cc: Keith Packard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/i915_dma.c | 3 +-- drivers/gpu/drm/i915/intel_overlay.c | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0239e9974bf2..2b79588541e7 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2182,9 +2182,8 @@ int i915_driver_unload(struct drm_device *dev) /* Flush any outstanding unpin_work. */ flush_workqueue(dev_priv->wq); - i915_gem_free_all_phys_object(dev); - mutex_lock(&dev->struct_mutex); + i915_gem_free_all_phys_object(dev); i915_gem_cleanup_ringbuffer(dev); mutex_unlock(&dev->struct_mutex); if (I915_HAS_FBC(dev) && i915_powersave) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index a670c006982e..56a8e2aea19c 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1416,6 +1416,8 @@ void intel_setup_overlay(struct drm_device *dev) goto out_free; overlay->reg_bo = reg_bo; + mutex_lock(&dev->struct_mutex); + if (OVERLAY_NEEDS_PHYSICAL(dev)) { ret = i915_gem_attach_phys_object(dev, reg_bo, I915_GEM_PHYS_OVERLAY_REGS, @@ -1440,6 +1442,8 @@ void intel_setup_overlay(struct drm_device *dev) } } + mutex_unlock(&dev->struct_mutex); + /* init all values */ overlay->color_key = 0x0101fe; overlay->brightness = -19; @@ -1464,6 +1468,7 @@ out_unpin_bo: i915_gem_object_unpin(reg_bo); out_free_bo: drm_gem_object_unreference(®_bo->base); + mutex_unlock(&dev->struct_mutex); out_free: kfree(overlay); return; -- cgit v1.2.3 From b0af8dfdd67699e25083478c63eedef2e72ebd85 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 27 Jun 2011 19:12:22 -0700 Subject: Linux 3.0-rc5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 41330a06e4ec..dc670467fb8c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5 NAME = Sneaky Weasel # *DOCUMENTATION* -- cgit v1.2.3 From 33f99dc7fd948bbc808a24a0989c167f8973b643 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 22 Jun 2011 01:04:37 +0000 Subject: ipv4: Fix packet size calculation in __ip_append_data Git commit 59104f06 (ip: take care of last fragment in ip_append_data) added a check to see if we exceed the mtu when we add trailer_len. However, the mtu is already subtracted by the trailer length when the xfrm transfomation bundles are set up. So IPsec packets with mtu size get fragmented, or if the DF bit is set the packets will not be send even though they match the mtu perfectly fine. This patch actually reverts commit 59104f06. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index a8024eaa0e87..6b894d430e61 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -888,12 +888,9 @@ alloc_new_skb: * because we have no idea what fragment will be * the last. */ - if (datalen == length + fraggap) { + if (datalen == length + fraggap) alloclen += rt->dst.trailer_len; - /* make sure mtu is not reached */ - if (datalen > mtu - fragheaderlen - rt->dst.trailer_len) - datalen -= ALIGN(rt->dst.trailer_len, 8); - } + if (transhdrlen) { skb = sock_alloc_send_skb(sk, alloclen + hh_len + 15, -- cgit v1.2.3 From 353e5c9abd900de3d1a40925386ffe4abf76111e Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 22 Jun 2011 01:05:37 +0000 Subject: ipv4: Fix IPsec slowpath fragmentation problem ip_append_data() builds packets based on the mtu from dst_mtu(rt->dst.path). On IPsec the effective mtu is lower because we need to add the protocol headers and trailers later when we do the IPsec transformations. So after the IPsec transformations the packet might be too big, which leads to a slowpath fragmentation then. This patch fixes this by building the packets based on the lower IPsec mtu from dst_mtu(&rt->dst) and adapts the exthdr handling to this. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 6b894d430e61..4a7e16b5d3f3 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -802,8 +802,6 @@ static int __ip_append_data(struct sock *sk, skb = skb_peek_tail(queue); exthdrlen = !skb ? rt->dst.header_len : 0; - length += exthdrlen; - transhdrlen += exthdrlen; mtu = cork->fragsize; hh_len = LL_RESERVED_SPACE(rt->dst.dev); @@ -883,6 +881,8 @@ alloc_new_skb: else alloclen = fraglen; + alloclen += exthdrlen; + /* The last fragment gets additional space at tail. * Note, with MSG_MORE we overallocate on fragments, * because we have no idea what fragment will be @@ -923,11 +923,11 @@ alloc_new_skb: /* * Find where to start putting bytes. */ - data = skb_put(skb, fraglen); + data = skb_put(skb, fraglen + exthdrlen); skb_set_network_header(skb, exthdrlen); skb->transport_header = (skb->network_header + fragheaderlen); - data += fragheaderlen; + data += fragheaderlen + exthdrlen; if (fraggap) { skb->csum = skb_copy_and_csum_bits( @@ -1061,7 +1061,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, */ *rtp = NULL; cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(rt->dst.path); + rt->dst.dev->mtu : dst_mtu(&rt->dst); cork->dst = &rt->dst; cork->length = 0; cork->tx_flags = ipc->tx_flags; -- cgit v1.2.3 From 4274215d24633df7302069e51426659d4759c5ed Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 28 Jun 2011 16:59:42 +1000 Subject: md: avoid endless recovery loop when waiting for fail device to complete. If a device fails in a way that causes pending request to take a while to complete, md will not be able to immediately remove it from the array in remove_and_add_spares. It will then incorrectly look like a spare device and md will try to recover it even though it is failed. This leads to a recovery process starting and instantly aborting over and over again. We should check if the device is faulty before considering it to be a spare. This will avoid trying to start a recovery that cannot proceed. This bug was introduced in 2.6.26 so that patch is suitable for any kernel since then. Cc: stable@kernel.org Reported-by: Jim Paradis Signed-off-by: NeilBrown --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 4332fc2f25d4..91e31e260b4a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7088,6 +7088,7 @@ static int remove_and_add_spares(mddev_t *mddev) list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->raid_disk >= 0 && !test_bit(In_sync, &rdev->flags) && + !test_bit(Faulty, &rdev->flags) && !test_bit(Blocked, &rdev->flags)) spares++; if (rdev->raid_disk < 0 -- cgit v1.2.3 From 076bad7c4d2c51d9484f0ac60d68838139d2bf72 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 May 2011 14:46:55 +0100 Subject: watchdog: Handle multiple wm831x watchdogs being registered Due to the whole single instance based watchdog API we use static data for the wm831x watchdog which means that if the system tries to register a second one we end up trying to register the same miscdevice again, corrupting the miscdevice list. Work around this by checking for duplicate registrations until we get a watchdog core. Signed-off-by: Mark Brown Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wm831x_wdt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 8c4b2d5bb7da..871caea4e1c6 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -320,6 +320,11 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev) struct wm831x_watchdog_pdata *pdata; int reg, ret; + if (wm831x) { + dev_err(&pdev->dev, "wm831x watchdog already registered\n"); + return -EBUSY; + } + wm831x = dev_get_drvdata(pdev->dev.parent); ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG); -- cgit v1.2.3 From 9b19d40aa3ebaf1078779da10555da2ab8512422 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 15 Jun 2011 19:15:23 +0200 Subject: watchdog: mtx1-wdt: request gpio before using it Otherwise, the gpiolib autorequest feature will produce a WARN_ON(): WARNING: at drivers/gpio/gpiolib.c:101 0x8020ec6c() autorequest GPIO-215 [...] Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/mtx-1_wdt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 1479dc4d6129..aa011da1d5fb 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -214,6 +214,12 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev) int ret; mtx1_wdt_device.gpio = pdev->resource[0].start; + ret = gpio_request_one(mtx1_wdt_device.gpio, + GPIOF_OUT_INIT_HIGH, "mtx1-wdt"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request gpio"); + return ret; + } spin_lock_init(&mtx1_wdt_device.lock); init_completion(&mtx1_wdt_device.stop); @@ -239,6 +245,8 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev) mtx1_wdt_device.queue = 0; wait_for_completion(&mtx1_wdt_device.stop); } + + gpio_free(mtx1_wdt_device.gpio); misc_deregister(&mtx1_wdt_misc); return 0; } -- cgit v1.2.3 From 2ea4e76e997019ae25ac3417aa46e31ddf7ecb17 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 15 Jun 2011 19:15:41 +0200 Subject: watchdog: mtx1-wdt: fix GPIO toggling Commit e391be76 (MIPS: Alchemy: Clean up GPIO registers and accessors) changed the way the GPIO was toggled. Prior to this patch, we would always actively drive the GPIO output to either 0 or 1, this patch drove the GPIO active to 0, and put the GPIO in tristate to drive it to 1, unfortunately this does not work, revert back to active driving. Using a signed variable (gstate) to hold the gpio state and using a bit- wise operation on it also resulted in toggling value from 1 to -2 since the variable is signed. This value was then passed on to gpio_direction_ output, which always perform a if (value) ... to set the value to the gpio, so we were always writing a 1 to this GPIO instead of 1 -> 0 -> 1 ... Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/mtx-1_wdt.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index aa011da1d5fb..54aa90042484 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -66,7 +66,7 @@ static struct { int default_ticks; unsigned long inuse; unsigned gpio; - int gstate; + unsigned int gstate; } mtx1_wdt_device; static void mtx1_wdt_trigger(unsigned long unused) @@ -78,11 +78,8 @@ static void mtx1_wdt_trigger(unsigned long unused) ticks--; /* toggle wdt gpio */ - mtx1_wdt_device.gstate = ~mtx1_wdt_device.gstate; - if (mtx1_wdt_device.gstate) - gpio_direction_output(mtx1_wdt_device.gpio, 1); - else - gpio_direction_input(mtx1_wdt_device.gpio); + mtx1_wdt_device.gstate = !mtx1_wdt_device.gstate; + gpio_set_value(mtx1_wdt_device.gpio, mtx1_wdt_device.gstate); if (mtx1_wdt_device.queue && ticks) mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); @@ -105,7 +102,7 @@ static void mtx1_wdt_start(void) if (!mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 1; mtx1_wdt_device.gstate = 1; - gpio_direction_output(mtx1_wdt_device.gpio, 1); + gpio_set_value(mtx1_wdt_device.gpio, 1); mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); } mtx1_wdt_device.running++; @@ -120,7 +117,7 @@ static int mtx1_wdt_stop(void) if (mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 0; mtx1_wdt_device.gstate = 0; - gpio_direction_output(mtx1_wdt_device.gpio, 0); + gpio_set_value(mtx1_wdt_device.gpio, 0); } ticks = mtx1_wdt_device.default_ticks; spin_unlock_irqrestore(&mtx1_wdt_device.lock, flags); -- cgit v1.2.3 From db98f89a2807966c6e82601f5c57e1a9c214c91a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 15 Jun 2011 19:15:52 +0200 Subject: watchdog: mtx1-wdt: fix section mismatch Fix section mismatch and remove unused variable 'tmp'. Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtx-1_wdt.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 54aa90042484..0430e093b1a0 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -71,8 +71,6 @@ static struct { static void mtx1_wdt_trigger(unsigned long unused) { - u32 tmp; - spin_lock(&mtx1_wdt_device.lock); if (mtx1_wdt_device.running) ticks--; @@ -248,7 +246,7 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev) return 0; } -static struct platform_driver mtx1_wdt = { +static struct platform_driver mtx1_wdt_driver = { .probe = mtx1_wdt_probe, .remove = __devexit_p(mtx1_wdt_remove), .driver.name = "mtx1-wdt", @@ -257,12 +255,12 @@ static struct platform_driver mtx1_wdt = { static int __init mtx1_wdt_init(void) { - return platform_driver_register(&mtx1_wdt); + return platform_driver_register(&mtx1_wdt_driver); } static void __exit mtx1_wdt_exit(void) { - platform_driver_unregister(&mtx1_wdt); + platform_driver_unregister(&mtx1_wdt_driver); } module_init(mtx1_wdt_init); -- cgit v1.2.3 From e376fd664b1547e29e264e3cfb97553a1be9054b Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 26 May 2011 11:12:53 +0200 Subject: watchdog: Intel SCU Watchdog: Fix build and remove duplicate code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to build the Intel SCU Watchdog fails for me with gcc 4.6.0 - $ gcc --version | head -n 1 gcc (GCC) 4.6.0 20110513 (prerelease) like this : CC drivers/watchdog/intel_scu_watchdog.o In file included from drivers/watchdog/intel_scu_watchdog.c:49:0: /home/jj/src/linux-2.6/arch/x86/include/asm/apb_timer.h: In function ‘apbt_time_init’: /home/jj/src/linux-2.6/arch/x86/include/asm/apb_timer.h:65:42: warning: ‘return’ with a value, in function returning void [enabled by default] drivers/watchdog/intel_scu_watchdog.c: In function ‘intel_scu_watchdog_init’: drivers/watchdog/intel_scu_watchdog.c:468:2: error: implicit declaration of function ‘sfi_get_mtmr’ [-Werror=implicit-function-declaration] drivers/watchdog/intel_scu_watchdog.c:468:32: warning: assignment makes pointer from integer without a cast [enabled by default] cc1: some warnings being treated as errors make[1]: *** [drivers/watchdog/intel_scu_watchdog.o] Error 1 make: *** [drivers/watchdog/intel_scu_watchdog.o] Error 2 Additionally, linux/types.h is needlessly being included twice in drivers/watchdog/intel_scu_watchdog.c Signed-off-by: Jesper Juhl Signed-off-by: Wim Van Sebroeck --- arch/x86/include/asm/apb_timer.h | 2 +- drivers/watchdog/Kconfig | 3 +-- drivers/watchdog/intel_scu_watchdog.c | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h index 2fefa501d3ba..af60d8a2e288 100644 --- a/arch/x86/include/asm/apb_timer.h +++ b/arch/x86/include/asm/apb_timer.h @@ -62,7 +62,7 @@ extern int sfi_mtimer_num; #else /* CONFIG_APB_TIMER */ static inline unsigned long apbt_quick_calibrate(void) {return 0; } -static inline void apbt_time_init(void) {return 0; } +static inline void apbt_time_init(void) { } #endif #endif /* ASM_X86_APBT_H */ diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 022f9eb0b7bf..9536d386bb38 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -535,8 +535,7 @@ config I6300ESB_WDT config INTEL_SCU_WATCHDOG bool "Intel SCU Watchdog for Mobile Platforms" - depends on WATCHDOG - depends on INTEL_SCU_IPC + depends on X86_MRST ---help--- Hardware driver for the watchdog time built into the Intel SCU for Intel Mobile Platforms. diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c index 919bdd16136f..ba4386066a42 100644 --- a/drivers/watchdog/intel_scu_watchdog.c +++ b/drivers/watchdog/intel_scu_watchdog.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From ae2a00607463ceb647ada550d7f34ba33177ef38 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 27 Jun 2011 22:37:16 +0800 Subject: watchdog: gef_wdt: fix MODULE_ALIAS Remove the space between "platform:" prefix and the driver name. Signed-off-by: Axel Lin Acked-by: Martyn Welch Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/gef_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 29a7cd4b90c8..b146082bd85a 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -329,4 +329,4 @@ MODULE_AUTHOR("Martyn Welch "); MODULE_DESCRIPTION("GE watchdog driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -MODULE_ALIAS("platform: gef_wdt"); +MODULE_ALIAS("platform:gef_wdt"); -- cgit v1.2.3 From f0ca89b031d327b80b612a0608d31b8e13e6dc33 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 21 Jun 2011 20:51:34 +0200 Subject: ALSA: HDA: Add a new Conexant codec ID (506c) Conexant ID 506c was found on Acer Aspire 3830TG. As users report no playback, sending to stable should be safe. Cc: stable@kernel.org BugLink: https://bugs.launchpad.net/bugs/783582 Reported-by: andROOM Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 694b9daf691f..4158949ea078 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -4389,6 +4389,8 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = { .patch = patch_cxt5066 }, { .id = 0x14f15069, .name = "CX20585", .patch = patch_cxt5066 }, + { .id = 0x14f1506c, .name = "CX20588", + .patch = patch_cxt5066 }, { .id = 0x14f1506e, .name = "CX20590", .patch = patch_cxt5066 }, { .id = 0x14f15097, .name = "CX20631", @@ -4417,6 +4419,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15066"); MODULE_ALIAS("snd-hda-codec-id:14f15067"); MODULE_ALIAS("snd-hda-codec-id:14f15068"); MODULE_ALIAS("snd-hda-codec-id:14f15069"); +MODULE_ALIAS("snd-hda-codec-id:14f1506c"); MODULE_ALIAS("snd-hda-codec-id:14f1506e"); MODULE_ALIAS("snd-hda-codec-id:14f15097"); MODULE_ALIAS("snd-hda-codec-id:14f15098"); -- cgit v1.2.3 From 9966db22caf8f74c0e6d84a569e6d7d56332e127 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 21 Jun 2011 21:01:52 +0200 Subject: ALSA: HDA: Add model=auto quirk for Acer Aspire 3830TG Since we're not using the new auto parser as a fallback yet, add it manually as a quirk. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4158949ea078..7bbc5f237a5e 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3074,6 +3074,7 @@ static const char * const cxt5066_models[CXT5066_MODELS] = { }; static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT5066_AUTO), SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), -- cgit v1.2.3 From 0cfae7c9378cf77434f6be89b5fb65d8f9a5031f Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Tue, 28 Jun 2011 16:59:14 +0200 Subject: ALSA: atmel - update author email for ABDAC, AC97C and AT73C213 This patch updates the email address of the sound drivers supported by me to an email account I will use on a more regular basis in the future. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Takashi Iwai --- sound/atmel/abdac.c | 2 +- sound/atmel/ac97c.c | 2 +- sound/spi/at73c213.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index 6e2409181895..bfee60c4d4c0 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c @@ -599,4 +599,4 @@ module_exit(atmel_abdac_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)"); -MODULE_AUTHOR("Hans-Christian Egtvedt "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index b310702c646e..ac35222ad0dd 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -1199,4 +1199,4 @@ module_exit(atmel_ac97c_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Driver for Atmel AC97 controller"); -MODULE_AUTHOR("Hans-Christian Egtvedt "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index 337a00241a1f..4dd051bdf4fd 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -1124,6 +1124,6 @@ static void __exit at73c213_exit(void) } module_exit(at73c213_exit); -MODULE_AUTHOR("Hans-Christian Egtvedt "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 5ee0a58d8ca443e80ed8712c86c9938360b79cac Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 27 Jun 2011 15:38:05 -0400 Subject: iwlagn: use PCI_DMA_* for pci_* operations "iwlagn: map command buffers BIDI" uses the DMA_* enumerations for DMA directions, even though the pci_* DMA API is still in use. That patch was undoubtedly developed on top of "iwlagn: don't use the PCI wrappers for DMA operation", which is due in the next release. Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-tx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 47074315903e..137dba95b1ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -126,7 +126,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) } static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, - struct iwl_tfd *tfd, enum dma_data_direction dma_dir) + struct iwl_tfd *tfd, int dma_dir) { struct pci_dev *dev = priv->pci_dev; int i; @@ -168,7 +168,7 @@ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) int index = txq->q.read_ptr; iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index], - DMA_TO_DEVICE); + PCI_DMA_TODEVICE); /* free SKB */ if (txq->txb) { @@ -312,7 +312,7 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) if (txq->meta[i].flags & CMD_MAPPED) { iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i], - DMA_BIDIRECTIONAL); + PCI_DMA_BIDIRECTIONAL); txq->meta[i].flags = 0; } @@ -694,11 +694,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) continue; phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i], - cmd->len[i], DMA_BIDIRECTIONAL); + cmd->len[i], PCI_DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) { iwlagn_unmap_tfd(priv, out_meta, &txq->tfds[q->write_ptr], - DMA_BIDIRECTIONAL); + PCI_DMA_BIDIRECTIONAL); idx = -ENOMEM; goto out; } @@ -802,7 +802,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; - iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); + iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], PCI_DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { -- cgit v1.2.3 From 1d1221f375c94ef961ba8574ac4f85c8870ddd51 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 24 Jun 2011 16:08:38 +0400 Subject: proc: restrict access to /proc/PID/io /proc/PID/io may be used for gathering private information. E.g. for openssh and vsftpd daemons wchars/rchars may be used to learn the precise password length. Restrict it to processes being able to ptrace the target process. ptrace_may_access() is needed to prevent keeping open file descriptor of "io" file, executing setuid binary and gathering io information of the setuid'ed process. Signed-off-by: Vasiliy Kulikov Signed-off-by: Linus Torvalds --- fs/proc/base.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 8a84210ca080..fc5bc2767692 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2708,6 +2708,9 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole) struct task_io_accounting acct = task->ioac; unsigned long flags; + if (!ptrace_may_access(task, PTRACE_MODE_READ)) + return -EACCES; + if (whole && lock_task_sighand(task, &flags)) { struct task_struct *t = task; @@ -2839,7 +2842,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), #endif #ifdef CONFIG_TASK_IO_ACCOUNTING - INF("io", S_IRUGO, proc_tgid_io_accounting), + INF("io", S_IRUSR, proc_tgid_io_accounting), #endif #ifdef CONFIG_HARDWALL INF("hardwall", S_IRUGO, proc_pid_hardwall), @@ -3181,7 +3184,7 @@ static const struct pid_entry tid_base_stuff[] = { REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), #endif #ifdef CONFIG_TASK_IO_ACCOUNTING - INF("io", S_IRUGO, proc_tid_io_accounting), + INF("io", S_IRUSR, proc_tid_io_accounting), #endif #ifdef CONFIG_HARDWALL INF("hardwall", S_IRUGO, proc_pid_hardwall), -- cgit v1.2.3 From 25732821cb965f00475922ca46e84f78e4bada95 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 24 Jun 2011 14:31:47 -0700 Subject: drm/i915: forcewake fix after reset The failure is as follows: 1. Userspace gets forcewake lock, lock count >=1 2. GPU hang/reset occurs (forcewake bit is reset) 3. count is now incorrect The failure can only occur when using the forcewake userspace lock. This has the unfortunate consequence of messing up the driver as well as userspace, unless userspace closes the debugfs file, the kernel will never end up waking the GT since the refcount will be > 1. The solution is to try to recover the correct forcewake state based on the refcount. There is a period of time where userspace reads/writes may occur after the reset, before the GT has been forcewaked. The interface was never designed to be a perfect solution for userspace reads/writes, and the kernel portion is fixed by this patch. Suggested-by: Chris Wilson Signed-off-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0defd4270594..609358faaa90 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -579,6 +579,9 @@ int i915_reset(struct drm_device *dev, u8 flags) } else switch (INTEL_INFO(dev)->gen) { case 6: ret = gen6_do_reset(dev, flags); + /* If reset with a user forcewake, try to restore */ + if (atomic_read(&dev_priv->forcewake_count)) + __gen6_gt_force_wake_get(dev_priv); break; case 5: ret = ironlake_do_reset(dev, flags); -- cgit v1.2.3 From f01c22fd59aa10a3738ede20fd4b9b6fd1e2eac3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jun 2011 11:48:51 +0100 Subject: drm/i915: Use chipset-specific irq installers Konstantin Belousov pointed out that 4697995b98417 replaced the generic i915_driver_irq_*install() functions with chipset specific routines accessible only through driver->irq_*install(). So update the sanity check in i915_request_wait() to match. Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c6389de53161..e81dbe57c773 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2080,8 +2080,8 @@ i915_wait_request(struct intel_ring_buffer *ring, if (!ier) { DRM_ERROR("something (likely vbetool) disabled " "interrupts, re-enabling\n"); - i915_driver_irq_preinstall(ring->dev); - i915_driver_irq_postinstall(ring->dev); + ring->dev->driver->irq_preinstall(ring->dev); + ring->dev->driver->irq_postinstall(ring->dev); } trace_i915_gem_request_wait_begin(ring, seqno); -- cgit v1.2.3 From aeb0aea143e958d5218162d73b1ed4d6ff0ed7c4 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Tue, 28 Jun 2011 17:01:14 +0200 Subject: watchdog: update author email for at32ap700x_wdt This patch updates the email address of the at32ap700x_wdt driver supported by me to an email account I will use on a more regular basis in the future. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/at32ap700x_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index 750bc5281d79..4ca5d40304b2 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -448,7 +448,7 @@ static void __exit at32_wdt_exit(void) } module_exit(at32_wdt_exit); -MODULE_AUTHOR("Hans-Christian Egtvedt "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From 937c190ccdd29855828529fc2b4b3e5f1282ff23 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 27 Jun 2011 19:55:30 +0000 Subject: powerpc/pseries: remove duplicate SCSI_BNX2_ISCSI in pseries_defconfig Remove duplicate assignment of SCSI_BNX2_ISCSI in pseries_defconfig introduced by: 37e0c21e powerpc/pseries: Enable iSCSI support for a number of cards causes warning: arch/powerpc/configs/pseries_defconfig:151:warning: override: reassigning to symbol SCSI_BNX2_ISCSI Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/configs/pseries_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index c9f212b5f3de..80bc5de7ee1d 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -148,7 +148,6 @@ CONFIG_SCSI_SAS_ATTRS=m CONFIG_SCSI_CXGB3_ISCSI=m CONFIG_SCSI_CXGB4_ISCSI=m CONFIG_SCSI_BNX2_ISCSI=m -CONFIG_SCSI_BNX2_ISCSI=m CONFIG_BE2ISCSI=m CONFIG_SCSI_IBMVSCSI=y CONFIG_SCSI_IBMVFC=m -- cgit v1.2.3 From 9a8f99fab02db296815d7f0ae8ba8ce169df0063 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Sat, 4 Jun 2011 05:35:47 +0000 Subject: powerpc/rtas-rtc: remove sideeffects of printk_ratelimit Don't use printk_ratelimit() as an additional condition for returning on an error. Because when the ratelimit is reached, printk_ratelimit will return 0 and e.g. in rtas_get_boot_time won't check for an error condition. Signed-off-by: Christian Dietrich Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/rtas-rtc.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 77578c093dda..c57c19358a26 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -29,9 +30,10 @@ unsigned long __init rtas_get_boot_time(void) } } while (wait_time && (get_tb() < max_wait_tb)); - if (error != 0 && printk_ratelimit()) { - printk(KERN_WARNING "error: reading the clock failed (%d)\n", - error); + if (error != 0) { + printk_ratelimited(KERN_WARNING + "error: reading the clock failed (%d)\n", + error); return 0; } @@ -55,19 +57,21 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm) wait_time = rtas_busy_delay_time(error); if (wait_time) { - if (in_interrupt() && printk_ratelimit()) { + if (in_interrupt()) { memset(rtc_tm, 0, sizeof(struct rtc_time)); - printk(KERN_WARNING "error: reading clock" - " would delay interrupt\n"); + printk_ratelimited(KERN_WARNING + "error: reading clock " + "would delay interrupt\n"); return; /* delay not allowed */ } msleep(wait_time); } } while (wait_time && (get_tb() < max_wait_tb)); - if (error != 0 && printk_ratelimit()) { - printk(KERN_WARNING "error: reading the clock failed (%d)\n", - error); + if (error != 0) { + printk_ratelimited(KERN_WARNING + "error: reading the clock failed (%d)\n", + error); return; } @@ -99,9 +103,10 @@ int rtas_set_rtc_time(struct rtc_time *tm) } } while (wait_time && (get_tb() < max_wait_tb)); - if (error != 0 && printk_ratelimit()) - printk(KERN_WARNING "error: setting the clock failed (%d)\n", - error); + if (error != 0) + printk_ratelimited(KERN_WARNING + "error: setting the clock failed (%d)\n", + error); return 0; } -- cgit v1.2.3 From 76462232c21dc011462522387ddad0598a4f11e4 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Sat, 4 Jun 2011 05:36:54 +0000 Subject: arch/powerpc: use printk_ratelimited instead of printk_ratelimit Since printk_ratelimit() shouldn't be used anymore (see comment in include/linux/printk.h), replace it with printk_ratelimited. Signed-off-by: Christian Dietrich Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/signal_32.c | 57 ++++++++++++++++++++++------------------- arch/powerpc/kernel/signal_64.c | 17 ++++++------ arch/powerpc/kernel/traps.c | 22 ++++++++-------- arch/powerpc/mm/fault.c | 10 ++++---- arch/powerpc/sysdev/mpic.c | 11 ++++---- 5 files changed, 60 insertions(+), 57 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index b96a3a010c26..78b76dc54dfb 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include #include @@ -892,11 +893,12 @@ badframe: printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (show_unhandled_signals && printk_ratelimit()) - printk(KERN_INFO "%s[%d]: bad frame in handle_rt_signal32: " - "%p nip %08lx lr %08lx\n", - current->comm, current->pid, - addr, regs->nip, regs->link); + if (show_unhandled_signals) + printk_ratelimited(KERN_INFO + "%s[%d]: bad frame in handle_rt_signal32: " + "%p nip %08lx lr %08lx\n", + current->comm, current->pid, + addr, regs->nip, regs->link); force_sigsegv(sig, current); return 0; @@ -1058,11 +1060,12 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, return 0; bad: - if (show_unhandled_signals && printk_ratelimit()) - printk(KERN_INFO "%s[%d]: bad frame in sys_rt_sigreturn: " - "%p nip %08lx lr %08lx\n", - current->comm, current->pid, - rt_sf, regs->nip, regs->link); + if (show_unhandled_signals) + printk_ratelimited(KERN_INFO + "%s[%d]: bad frame in sys_rt_sigreturn: " + "%p nip %08lx lr %08lx\n", + current->comm, current->pid, + rt_sf, regs->nip, regs->link); force_sig(SIGSEGV, current); return 0; @@ -1149,12 +1152,12 @@ int sys_debug_setcontext(struct ucontext __user *ctx, * We kill the task with a SIGSEGV in this situation. */ if (do_setcontext(ctx, regs, 1)) { - if (show_unhandled_signals && printk_ratelimit()) - printk(KERN_INFO "%s[%d]: bad frame in " - "sys_debug_setcontext: %p nip %08lx " - "lr %08lx\n", - current->comm, current->pid, - ctx, regs->nip, regs->link); + if (show_unhandled_signals) + printk_ratelimited(KERN_INFO "%s[%d]: bad frame in " + "sys_debug_setcontext: %p nip %08lx " + "lr %08lx\n", + current->comm, current->pid, + ctx, regs->nip, regs->link); force_sig(SIGSEGV, current); goto out; @@ -1236,11 +1239,12 @@ badframe: printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (show_unhandled_signals && printk_ratelimit()) - printk(KERN_INFO "%s[%d]: bad frame in handle_signal32: " - "%p nip %08lx lr %08lx\n", - current->comm, current->pid, - frame, regs->nip, regs->link); + if (show_unhandled_signals) + printk_ratelimited(KERN_INFO + "%s[%d]: bad frame in handle_signal32: " + "%p nip %08lx lr %08lx\n", + current->comm, current->pid, + frame, regs->nip, regs->link); force_sigsegv(sig, current); return 0; @@ -1288,11 +1292,12 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, return 0; badframe: - if (show_unhandled_signals && printk_ratelimit()) - printk(KERN_INFO "%s[%d]: bad frame in sys_sigreturn: " - "%p nip %08lx lr %08lx\n", - current->comm, current->pid, - addr, regs->nip, regs->link); + if (show_unhandled_signals) + printk_ratelimited(KERN_INFO + "%s[%d]: bad frame in sys_sigreturn: " + "%p nip %08lx lr %08lx\n", + current->comm, current->pid, + addr, regs->nip, regs->link); force_sig(SIGSEGV, current); return 0; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index da989fff19cc..e91c736cc842 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -380,10 +381,10 @@ badframe: printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", regs, uc, &uc->uc_mcontext); #endif - if (show_unhandled_signals && printk_ratelimit()) - printk(regs->msr & MSR_64BIT ? fmt64 : fmt32, - current->comm, current->pid, "rt_sigreturn", - (long)uc, regs->nip, regs->link); + if (show_unhandled_signals) + printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, + current->comm, current->pid, "rt_sigreturn", + (long)uc, regs->nip, regs->link); force_sig(SIGSEGV, current); return 0; @@ -468,10 +469,10 @@ badframe: printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (show_unhandled_signals && printk_ratelimit()) - printk(regs->msr & MSR_64BIT ? fmt64 : fmt32, - current->comm, current->pid, "setup_rt_frame", - (long)frame, regs->nip, regs->link); + if (show_unhandled_signals) + printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, + current->comm, current->pid, "setup_rt_frame", + (long)frame, regs->nip, regs->link); force_sigsegv(signr, current); return 0; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6414a0d5ba65..1a0141426cda 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -197,12 +198,11 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) if (die("Exception in kernel mode", regs, signr)) return; } else if (show_unhandled_signals && - unhandled_signal(current, signr) && - printk_ratelimit()) { - printk(regs->msr & MSR_64BIT ? fmt64 : fmt32, - current->comm, current->pid, signr, - addr, regs->nip, regs->link, code); - } + unhandled_signal(current, signr)) { + printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, + current->comm, current->pid, signr, + addr, regs->nip, regs->link, code); + } memset(&info, 0, sizeof(info)); info.si_signo = signr; @@ -1342,9 +1342,8 @@ void altivec_assist_exception(struct pt_regs *regs) } else { /* didn't recognize the instruction */ /* XXX quick hack for now: set the non-Java bit in the VSCR */ - if (printk_ratelimit()) - printk(KERN_ERR "Unrecognized altivec instruction " - "in %s at %lx\n", current->comm, regs->nip); + printk_ratelimited(KERN_ERR "Unrecognized altivec instruction " + "in %s at %lx\n", current->comm, regs->nip); current->thread.vscr.u[3] |= 0x10000; } } @@ -1548,9 +1547,8 @@ u32 ppc_warn_emulated; void ppc_warn_emulated_print(const char *type) { - if (printk_ratelimit()) - pr_warning("%s used emulated %s instruction\n", current->comm, - type); + pr_warn_ratelimited("%s used emulated %s instruction\n", current->comm, + type); } static int __init ppc_warn_emulated_init(void) diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 54f4fb994e99..ad35f66c69e8 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -346,11 +347,10 @@ bad_area_nosemaphore: return 0; } - if (is_exec && (error_code & DSISR_PROTFAULT) - && printk_ratelimit()) - printk(KERN_CRIT "kernel tried to execute NX-protected" - " page (%lx) - exploit attempt? (uid: %d)\n", - address, current_uid()); + if (is_exec && (error_code & DSISR_PROTFAULT)) + printk_ratelimited(KERN_CRIT "kernel tried to execute NX-protected" + " page (%lx) - exploit attempt? (uid: %d)\n", + address, current_uid()); return SIGSEGV; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 3a8de5bb628a..58d7a534f877 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -1648,9 +1649,8 @@ static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg) return NO_IRQ; } if (unlikely(mpic->protected && test_bit(src, mpic->protected))) { - if (printk_ratelimit()) - printk(KERN_WARNING "%s: Got protected source %d !\n", - mpic->name, (int)src); + printk_ratelimited(KERN_WARNING "%s: Got protected source %d !\n", + mpic->name, (int)src); mpic_eoi(mpic); return NO_IRQ; } @@ -1688,9 +1688,8 @@ unsigned int mpic_get_coreint_irq(void) return NO_IRQ; } if (unlikely(mpic->protected && test_bit(src, mpic->protected))) { - if (printk_ratelimit()) - printk(KERN_WARNING "%s: Got protected source %d !\n", - mpic->name, (int)src); + printk_ratelimited(KERN_WARNING "%s: Got protected source %d !\n", + mpic->name, (int)src); return NO_IRQ; } -- cgit v1.2.3 From f5b2d0ef631bb0647ae8ed1752d2127b8fb6da70 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 29 Jun 2011 14:26:07 +0800 Subject: ALSA: HDMI - fix ELD monitor name length I noticed that the last character of the ELD monitor name is lost, this fixes the issue. This fix should be confirming to the HDA spec, and works together with the DRM part of the ELD patch. The HDA spec does not mention that Monitor_Name_String is an '\0' ending string, and it allows NML to be 1, which is only valid when MNL does not count the possible ending '\0'. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_eld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index b05f7be9dc1b..e3e853153d14 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -294,7 +294,7 @@ static int hdmi_update_eld(struct hdmi_eld *e, snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl); goto out_fail; } else - strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl); + strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); for (i = 0; i < e->sad_count; i++) { if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { -- cgit v1.2.3 From cb16c348760ad2bc79b67b20aefac05529569ed7 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 19 Jun 2011 19:21:11 +0300 Subject: KVM: x86 emulator: fix %rip-relative addressing with immediate source operand %rip-relative addressing is relative to the first byte of the next instruction, so we need to add %rip only after we've fetched any immediate bytes. Based on original patch by Li Xin . Signed-off-by: Avi Kivity Acked-by: Li Xin Signed-off-by: Marcelo Tosatti --- arch/x86/kvm/emulate.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 6df88c7885c0..adc98675cda0 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3372,7 +3372,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) int def_op_bytes, def_ad_bytes, goffset, simd_prefix; bool op_prefix = false; struct opcode opcode; - struct operand memop = { .type = OP_NONE }; + struct operand memop = { .type = OP_NONE }, *memopp = NULL; c->eip = ctxt->eip; c->fetch.start = c->eip; @@ -3547,9 +3547,6 @@ done_prefixes: if (memop.type == OP_MEM && c->ad_bytes != 8) memop.addr.mem.ea = (u32)memop.addr.mem.ea; - if (memop.type == OP_MEM && c->rip_relative) - memop.addr.mem.ea += c->eip; - /* * Decode and fetch the source operand: register, memory * or immediate. @@ -3571,6 +3568,7 @@ done_prefixes: c->op_bytes; srcmem_common: c->src = memop; + memopp = &c->src; break; case SrcImmU16: rc = decode_imm(ctxt, &c->src, 2, false); @@ -3667,6 +3665,7 @@ done_prefixes: case DstMem: case DstMem64: c->dst = memop; + memopp = &c->dst; if ((c->d & DstMask) == DstMem64) c->dst.bytes = 8; else @@ -3700,10 +3699,13 @@ done_prefixes: /* Special instructions do their own operand decoding. */ default: c->dst.type = OP_NONE; /* Disable writeback. */ - return 0; + break; } done: + if (memopp && memopp->type == OP_MEM && c->rip_relative) + memopp->addr.mem.ea += c->eip; + return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK; } -- cgit v1.2.3 From b00c2c79d9ceac49d8b3ba3b097e5df33f802d9a Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 29 Jun 2011 04:23:47 +0000 Subject: sh: fix the INTC vector for IRQ and IRL in setup-sh7757 Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index 717a76b399b1..fad2da4c97cf 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -1089,13 +1089,13 @@ static DECLARE_INTC_DESC(intc_desc, "sh7757", vectors, groups, /* Support for external interrupt pins in IRQ mode */ static struct intc_vect vectors_irq0123[] __initdata = { - INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280), - INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300), + INTC_VECT(IRQ0, 0x200), INTC_VECT(IRQ1, 0x240), + INTC_VECT(IRQ2, 0x280), INTC_VECT(IRQ3, 0x2c0), }; static struct intc_vect vectors_irq4567[] __initdata = { - INTC_VECT(IRQ4, 0x340), INTC_VECT(IRQ5, 0x380), - INTC_VECT(IRQ6, 0x3c0), INTC_VECT(IRQ7, 0x200), + INTC_VECT(IRQ4, 0x300), INTC_VECT(IRQ5, 0x340), + INTC_VECT(IRQ6, 0x380), INTC_VECT(IRQ7, 0x3c0), }; static struct intc_sense_reg sense_registers[] __initdata = { @@ -1129,14 +1129,14 @@ static struct intc_vect vectors_irl0123[] __initdata = { }; static struct intc_vect vectors_irl4567[] __initdata = { - INTC_VECT(IRL4_LLLL, 0xb00), INTC_VECT(IRL4_LLLH, 0xb20), - INTC_VECT(IRL4_LLHL, 0xb40), INTC_VECT(IRL4_LLHH, 0xb60), - INTC_VECT(IRL4_LHLL, 0xb80), INTC_VECT(IRL4_LHLH, 0xba0), - INTC_VECT(IRL4_LHHL, 0xbc0), INTC_VECT(IRL4_LHHH, 0xbe0), - INTC_VECT(IRL4_HLLL, 0xc00), INTC_VECT(IRL4_HLLH, 0xc20), - INTC_VECT(IRL4_HLHL, 0xc40), INTC_VECT(IRL4_HLHH, 0xc60), - INTC_VECT(IRL4_HHLL, 0xc80), INTC_VECT(IRL4_HHLH, 0xca0), - INTC_VECT(IRL4_HHHL, 0xcc0), + INTC_VECT(IRL4_LLLL, 0x200), INTC_VECT(IRL4_LLLH, 0x220), + INTC_VECT(IRL4_LLHL, 0x240), INTC_VECT(IRL4_LLHH, 0x260), + INTC_VECT(IRL4_LHLL, 0x280), INTC_VECT(IRL4_LHLH, 0x2a0), + INTC_VECT(IRL4_LHHL, 0x2c0), INTC_VECT(IRL4_LHHH, 0x2e0), + INTC_VECT(IRL4_HLLL, 0x300), INTC_VECT(IRL4_HLLH, 0x320), + INTC_VECT(IRL4_HLHL, 0x340), INTC_VECT(IRL4_HLHH, 0x360), + INTC_VECT(IRL4_HHLL, 0x380), INTC_VECT(IRL4_HHLH, 0x3a0), + INTC_VECT(IRL4_HHHL, 0x3c0), }; static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7757-irl0123", vectors_irl0123, -- cgit v1.2.3 From 6afba9e7fca5ad6a701c13760639faa0906fe487 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 29 Jun 2011 04:23:42 +0000 Subject: sh: fix the value of sh_dmae_slave_config in setup-sh7757 Fix the value of chcr for SCIF[2-4]_RX and RIIC[0-9]_RX and the value of mid_rid for some RIIC. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index fad2da4c97cf..e915deafac89 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -183,7 +183,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = { { .slave_id = SHDMA_SLAVE_SCIF2_RX, .addr = 0x1f4b0014, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x22, }, @@ -197,7 +197,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = { { .slave_id = SHDMA_SLAVE_SCIF3_RX, .addr = 0x1f4c0014, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x2a, }, @@ -211,7 +211,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = { { .slave_id = SHDMA_SLAVE_SCIF4_RX, .addr = 0x1f4d0014, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x42, }, @@ -228,7 +228,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { { .slave_id = SHDMA_SLAVE_RIIC0_RX, .addr = 0x1e500013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x22, }, @@ -242,7 +242,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { { .slave_id = SHDMA_SLAVE_RIIC1_RX, .addr = 0x1e510013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x2a, }, @@ -256,7 +256,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { { .slave_id = SHDMA_SLAVE_RIIC2_RX, .addr = 0x1e520013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0xa2, }, @@ -265,12 +265,12 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { .addr = 0x1e530012, .chcr = SM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), - .mid_rid = 0xab, + .mid_rid = 0xa9, }, { .slave_id = SHDMA_SLAVE_RIIC3_RX, .addr = 0x1e530013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0xaf, }, @@ -279,14 +279,14 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { .addr = 0x1e540012, .chcr = SM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), - .mid_rid = 0xc1, + .mid_rid = 0xc5, }, { .slave_id = SHDMA_SLAVE_RIIC4_RX, .addr = 0x1e540013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), - .mid_rid = 0xc2, + .mid_rid = 0xc6, }, }; @@ -301,7 +301,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { { .slave_id = SHDMA_SLAVE_RIIC5_RX, .addr = 0x1e550013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x22, }, @@ -315,7 +315,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { { .slave_id = SHDMA_SLAVE_RIIC6_RX, .addr = 0x1e560013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x2a, }, @@ -329,7 +329,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { { .slave_id = SHDMA_SLAVE_RIIC7_RX, .addr = 0x1e570013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x42, }, @@ -343,7 +343,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { { .slave_id = SHDMA_SLAVE_RIIC8_RX, .addr = 0x1e580013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x46, }, @@ -357,7 +357,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { { .slave_id = SHDMA_SLAVE_RIIC9_RX, .addr = 0x1e590013, - .chcr = SM_INC | 0x800 | 0x40000000 | + .chcr = DM_INC | 0x800 | 0x40000000 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x52, }, -- cgit v1.2.3 From 9b640f2e154268cb516efcaf9c434f2e73c6783e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 29 Jun 2011 11:36:10 +0200 Subject: i2c-taos-evm: Fix log messages * Print all error and information messages even when debugging is disabled. * Don't use adapter device to log messages before it is ready. Signed-off-by: Jean Delvare Cc: stable@kernel.org --- drivers/i2c/busses/i2c-taos-evm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index dd39c1eb03ed..26c352a09298 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -234,7 +234,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) if (taos->state != TAOS_STATE_IDLE) { err = -ENODEV; - dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, " + dev_err(&serio->dev, "TAOS EVM reset failed (state=%d, " "pos=%d)\n", taos->state, taos->pos); goto exit_close; } @@ -255,7 +255,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) msecs_to_jiffies(250)); if (taos->state != TAOS_STATE_IDLE) { err = -ENODEV; - dev_err(&adapter->dev, "Echo off failed " + dev_err(&serio->dev, "TAOS EVM echo off failed " "(state=%d)\n", taos->state); goto exit_close; } @@ -263,7 +263,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) err = i2c_add_adapter(adapter); if (err) goto exit_close; - dev_dbg(&serio->dev, "Connected to TAOS EVM\n"); + dev_info(&serio->dev, "Connected to TAOS EVM\n"); taos->client = taos_instantiate_device(adapter); return 0; @@ -288,7 +288,7 @@ static void taos_disconnect(struct serio *serio) serio_set_drvdata(serio, NULL); kfree(taos); - dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n"); + dev_info(&serio->dev, "Disconnected from TAOS EVM\n"); } static struct serio_device_id taos_serio_ids[] = { -- cgit v1.2.3 From cd823db8b1161ef0d756514d280715a576d65cc3 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Wed, 29 Jun 2011 11:36:11 +0200 Subject: i2c/pca954x: Initialize the mux to disconnected state pca954x power-on default is channel 0 connected. If multiple pca954x muxes are connected to the same physical I2C bus, the parent bus will see channel 0 devices behind both muxes by default. This is bad. Scenario: -- pca954x @ 0x70 -- ch 0 (I2C-bus-101) -- EEPROM @ 0x50 | I2C-bus-1 --- | -- pca954x @ 0x71 -- ch 0 (I2C-bus-111) -- EEPROM @ 0x50 1. Load I2C bus driver: creates I2C-bus-1 2. Load pca954x driver: creates virtual I2C-bus-101 and I2C-bus-111 3. Load eeprom driver 4. Try to read EEPROM @ 0x50 on I2C-bus-101. The transaction will also bleed onto I2C-bus-111 because pca954x @ 0x71 channel 0 is connected by default. Fix: Initialize pca954x to disconnected state in pca954x_probe() Signed-off-by: Petri Gynther Signed-off-by: Jean Delvare Cc: stable@kernel.org --- drivers/i2c/muxes/pca954x.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c index 54e1ce73534b..6f8953664636 100644 --- a/drivers/i2c/muxes/pca954x.c +++ b/drivers/i2c/muxes/pca954x.c @@ -201,10 +201,11 @@ static int pca954x_probe(struct i2c_client *client, i2c_set_clientdata(client, data); - /* Read the mux register at addr to verify - * that the mux is in fact present. + /* Write the mux register at addr to verify + * that the mux is in fact present. This also + * initializes the mux to disconnected state. */ - if (i2c_smbus_read_byte(client) < 0) { + if (i2c_smbus_write_byte(client, 0) < 0) { dev_warn(&client->dev, "probe failed\n"); goto exit_free; } -- cgit v1.2.3 From ed6e4ef836d425bc35e33bf20fcec95e68203afa Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sat, 18 Jun 2011 07:53:59 +0000 Subject: netfilter: Fix ip_route_me_harder triggering ip_rt_bug Avoid creating input routes with ip_route_me_harder. It does not work for locally generated packets. Instead, restrict sockets to provide valid saddr for output route (or unicast saddr for transparent proxy). For other traffic allow saddr to be unicast or local but if callers forget to check saddr type use 0 for the output route. The resulting handling should be: - REJECT TCP: - in INPUT we can provide addr_type = RTN_LOCAL but better allow rejecting traffic delivered with local route (no IP address => use RTN_UNSPEC to allow also RTN_UNICAST). - FORWARD: RTN_UNSPEC => allow RTN_LOCAL/RTN_UNICAST saddr, add fix to ignore RTN_BROADCAST and RTN_MULTICAST - OUTPUT: RTN_UNSPEC - NAT, mangle, ip_queue, nf_ip_reroute: RTN_UNSPEC in LOCAL_OUT - IPVS: - use RTN_LOCAL in LOCAL_OUT and FORWARD after SNAT to restrict saddr to be local Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller --- net/ipv4/netfilter.c | 60 +++++++++++++++-------------------------- net/ipv4/netfilter/ipt_REJECT.c | 14 +++------- 2 files changed, 26 insertions(+), 48 deletions(-) diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 4614babdc45f..2e97e3ec1eb7 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -17,51 +17,35 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) const struct iphdr *iph = ip_hdr(skb); struct rtable *rt; struct flowi4 fl4 = {}; - unsigned long orefdst; + __be32 saddr = iph->saddr; + __u8 flags = 0; unsigned int hh_len; - unsigned int type; - type = inet_addr_type(net, iph->saddr); - if (skb->sk && inet_sk(skb->sk)->transparent) - type = RTN_LOCAL; - if (addr_type == RTN_UNSPEC) - addr_type = type; + if (!skb->sk && addr_type != RTN_LOCAL) { + if (addr_type == RTN_UNSPEC) + addr_type = inet_addr_type(net, saddr); + if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST) + flags |= FLOWI_FLAG_ANYSRC; + else + saddr = 0; + } /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook. */ - if (addr_type == RTN_LOCAL) { - fl4.daddr = iph->daddr; - if (type == RTN_LOCAL) - fl4.saddr = iph->saddr; - fl4.flowi4_tos = RT_TOS(iph->tos); - fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; - fl4.flowi4_mark = skb->mark; - fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; - rt = ip_route_output_key(net, &fl4); - if (IS_ERR(rt)) - return -1; - - /* Drop old route. */ - skb_dst_drop(skb); - skb_dst_set(skb, &rt->dst); - } else { - /* non-local src, find valid iif to satisfy - * rp-filter when calling ip_route_input. */ - fl4.daddr = iph->saddr; - rt = ip_route_output_key(net, &fl4); - if (IS_ERR(rt)) - return -1; + fl4.daddr = iph->daddr; + fl4.saddr = saddr; + fl4.flowi4_tos = RT_TOS(iph->tos); + fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; + fl4.flowi4_mark = skb->mark; + fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : flags; + rt = ip_route_output_key(net, &fl4); + if (IS_ERR(rt)) + return -1; - orefdst = skb->_skb_refdst; - if (ip_route_input(skb, iph->daddr, iph->saddr, - RT_TOS(iph->tos), rt->dst.dev) != 0) { - dst_release(&rt->dst); - return -1; - } - dst_release(&rt->dst); - refdst_drop(orefdst); - } + /* Drop old route. */ + skb_dst_drop(skb); + skb_dst_set(skb, &rt->dst); if (skb_dst(skb)->error) return -1; diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 1ff79e557f96..51f13f8ec724 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -40,7 +40,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) struct iphdr *niph; const struct tcphdr *oth; struct tcphdr _otcph, *tcph; - unsigned int addr_type; /* IP header checks: fragment. */ if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) @@ -55,6 +54,9 @@ static void send_reset(struct sk_buff *oldskb, int hook) if (oth->rst) return; + if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) + return; + /* Check checksum */ if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) return; @@ -101,19 +103,11 @@ static void send_reset(struct sk_buff *oldskb, int hook) nskb->csum_start = (unsigned char *)tcph - nskb->head; nskb->csum_offset = offsetof(struct tcphdr, check); - addr_type = RTN_UNSPEC; - if (hook != NF_INET_FORWARD -#ifdef CONFIG_BRIDGE_NETFILTER - || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED) -#endif - ) - addr_type = RTN_LOCAL; - /* ip_route_me_harder expects skb->dst to be set */ skb_dst_set_noref(nskb, skb_dst(oldskb)); nskb->protocol = htons(ETH_P_IP); - if (ip_route_me_harder(nskb, addr_type)) + if (ip_route_me_harder(nskb, RTN_UNSPEC)) goto free_nskb; niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); -- cgit v1.2.3 From 7ab24bfdf9a9a9f87ac8e5ad9a25f80b5b947be7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 29 Jun 2011 05:48:41 -0700 Subject: net+crypto: Use vmalloc for zlib inflate buffers. They are 64K and result in order-4 allocations, even with SLUB. Therefore, just like we always have for the deflate buffers, use vmalloc. Reported-by: Martin Jackson Acked-by: Herbert Xu Signed-off-by: David S. Miller --- crypto/deflate.c | 7 +++---- crypto/zlib.c | 7 +++---- drivers/net/bnx2x/bnx2x_main.c | 6 +++--- drivers/net/ppp_deflate.c | 5 ++--- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/crypto/deflate.c b/crypto/deflate.c index b5ccae29be74..b0165ecad0c5 100644 --- a/crypto/deflate.c +++ b/crypto/deflate.c @@ -32,7 +32,6 @@ #include #include #include -#include #define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION #define DEFLATE_DEF_WINBITS 11 @@ -73,7 +72,7 @@ static int deflate_decomp_init(struct deflate_ctx *ctx) int ret = 0; struct z_stream_s *stream = &ctx->decomp_stream; - stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); + stream->workspace = vzalloc(zlib_inflate_workspacesize()); if (!stream->workspace) { ret = -ENOMEM; goto out; @@ -86,7 +85,7 @@ static int deflate_decomp_init(struct deflate_ctx *ctx) out: return ret; out_free: - kfree(stream->workspace); + vfree(stream->workspace); goto out; } @@ -99,7 +98,7 @@ static void deflate_comp_exit(struct deflate_ctx *ctx) static void deflate_decomp_exit(struct deflate_ctx *ctx) { zlib_inflateEnd(&ctx->decomp_stream); - kfree(ctx->decomp_stream.workspace); + vfree(ctx->decomp_stream.workspace); } static int deflate_init(struct crypto_tfm *tfm) diff --git a/crypto/zlib.c b/crypto/zlib.c index d11d761a5e41..06b62e5cdcc7 100644 --- a/crypto/zlib.c +++ b/crypto/zlib.c @@ -29,7 +29,6 @@ #include #include #include -#include #include @@ -60,7 +59,7 @@ static void zlib_decomp_exit(struct zlib_ctx *ctx) if (stream->workspace) { zlib_inflateEnd(stream); - kfree(stream->workspace); + vfree(stream->workspace); stream->workspace = NULL; } } @@ -228,13 +227,13 @@ static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params, ? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS]) : DEF_WBITS; - stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); + stream->workspace = vzalloc(zlib_inflate_workspacesize()); if (!stream->workspace) return -ENOMEM; ret = zlib_inflateInit2(stream, ctx->decomp_windowBits); if (ret != Z_OK) { - kfree(stream->workspace); + vfree(stream->workspace); stream->workspace = NULL; return -EINVAL; } diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 4b70311a11ef..74be989f51c5 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -49,6 +49,7 @@ #include #include #include +#include #define BNX2X_MAIN #include "bnx2x.h" @@ -4537,8 +4538,7 @@ static int bnx2x_gunzip_init(struct bnx2x *bp) if (bp->strm == NULL) goto gunzip_nomem2; - bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), - GFP_KERNEL); + bp->strm->workspace = vmalloc(zlib_inflate_workspacesize()); if (bp->strm->workspace == NULL) goto gunzip_nomem3; @@ -4562,7 +4562,7 @@ gunzip_nomem1: static void bnx2x_gunzip_end(struct bnx2x *bp) { if (bp->strm) { - kfree(bp->strm->workspace); + vfree(bp->strm->workspace); kfree(bp->strm); bp->strm = NULL; } diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c index 31e9407a0739..1dbdf82a6dfd 100644 --- a/drivers/net/ppp_deflate.c +++ b/drivers/net/ppp_deflate.c @@ -305,7 +305,7 @@ static void z_decomp_free(void *arg) if (state) { zlib_inflateEnd(&state->strm); - kfree(state->strm.workspace); + vfree(state->strm.workspace); kfree(state); } } @@ -345,8 +345,7 @@ static void *z_decomp_alloc(unsigned char *options, int opt_len) state->w_size = w_size; state->strm.next_out = NULL; - state->strm.workspace = kmalloc(zlib_inflate_workspacesize(), - GFP_KERNEL|__GFP_REPEAT); + state->strm.workspace = vmalloc(zlib_inflate_workspacesize()); if (state->strm.workspace == NULL) goto out_free; -- cgit v1.2.3 From 55caa9241ece1c07a930e3d05a624061adcf2653 Mon Sep 17 00:00:00 2001 From: Yinglin Luan Date: Sat, 25 Jun 2011 18:12:12 +0000 Subject: rionet: fix NULL pointer dereference in rionet_remove Function rionet_remove initializes local variable 'ndev' to NULL and do nothing changes before the call to unregister_netdev(ndev), this could cause a NULL pointer dereference. Reported-by: Jesper Juhl Signed-off-by: Yinglin Luan Signed-off-by: David S. Miller --- drivers/net/rionet.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 77c5092a6a40..5d3436d47edd 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -378,7 +378,7 @@ static int rionet_close(struct net_device *ndev) static void rionet_remove(struct rio_dev *rdev) { - struct net_device *ndev = NULL; + struct net_device *ndev = rio_get_drvdata(rdev); struct rionet_peer *peer, *tmp; free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ? @@ -433,22 +433,12 @@ static const struct net_device_ops rionet_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int rionet_setup_netdev(struct rio_mport *mport) +static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) { int rc = 0; - struct net_device *ndev = NULL; struct rionet_private *rnet; u16 device_id; - /* Allocate our net_device structure */ - ndev = alloc_etherdev(sizeof(struct rionet_private)); - if (ndev == NULL) { - printk(KERN_INFO "%s: could not allocate ethernet device.\n", - DRV_NAME); - rc = -ENOMEM; - goto out; - } - rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL, mport->sys_size ? __fls(sizeof(void *)) + 4 : 0); if (!rionet_active) { @@ -504,11 +494,21 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) int rc = -ENODEV; u32 lpef, lsrc_ops, ldst_ops; struct rionet_peer *peer; + struct net_device *ndev = NULL; /* If local device is not rionet capable, give up quickly */ if (!rionet_capable) goto out; + /* Allocate our net_device structure */ + ndev = alloc_etherdev(sizeof(struct rionet_private)); + if (ndev == NULL) { + printk(KERN_INFO "%s: could not allocate ethernet device.\n", + DRV_NAME); + rc = -ENOMEM; + goto out; + } + /* * First time through, make sure local device is rionet * capable, setup netdev, and set flags so this is skipped @@ -529,7 +529,7 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) goto out; } - rc = rionet_setup_netdev(rdev->net->hport); + rc = rionet_setup_netdev(rdev->net->hport, ndev); rionet_check = 1; } @@ -546,6 +546,8 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) list_add_tail(&peer->node, &rionet_peers); } + rio_set_drvdata(rdev, ndev); + out: return rc; } -- cgit v1.2.3 From a30d5155a4f80af3cbe1fe0366e9f0c6fdbfd8dd Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sun, 26 Jun 2011 21:39:51 +0000 Subject: net/can: activate bit-timing calculation and netlink based drivers by default The two options "CAN bit-timing calculation" and "Platform CAN drivers with Netlink support" have a "default Y". In order to activate them by default, change to "default y". Signed-off-by: Marc Kleine-Budde Acked-by: Wolfgang Grandegger Acked-by: Kurt Van Dijck Signed-off-by: David S. Miller --- drivers/net/can/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 1d699e3df547..754df5ef1729 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -36,7 +36,7 @@ config CAN_SLCAN config CAN_DEV tristate "Platform CAN drivers with Netlink support" depends on CAN - default Y + default y ---help--- Enables the common framework for platform CAN drivers with Netlink support. This is the standard library for CAN drivers. @@ -45,7 +45,7 @@ config CAN_DEV config CAN_CALC_BITTIMING bool "CAN bit-timing calculation" depends on CAN_DEV - default Y + default y ---help--- If enabled, CAN bit-timing parameters will be calculated for the bit-rate specified via Netlink argument "bitrate" when the device -- cgit v1.2.3 From 1a8690aa50a00670f254282a92caf1401bd30528 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 27 Jun 2011 08:24:07 +0000 Subject: MAINTAINERS: drop Michael from bfin_mac driver We want people to just use the list now rather than hitting up people who are no longer responsible for it. Signed-off-by: Mike Frysinger Acked-by: Michael Hennerich Signed-off-by: David S. Miller --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 05aaf9221ad7..1d22afeaaa26 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1422,7 +1422,6 @@ S: Supported F: arch/blackfin/ BLACKFIN EMAC DRIVER -M: Michael Hennerich L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported -- cgit v1.2.3 From 16adf5d07987d93675945f3cecf0e33706566005 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 17 Jun 2011 20:02:10 -0400 Subject: usbnet: Remove over-broad module alias from zaurus. This module and a bunch of dependancies are getting loaded on several of laptops I have (probably picking up the mobile broadband device), that have nothing to do with zaurus. Matching by class without any vendor/device pair isn't the right thing to do here, as it will prevent any other driver from correctly binding to it. (Or in the absense of a driver, will just waste time & memory by unnecessarily loading modules) Signed-off-by: Dave Jones Signed-off-by: David S. Miller --- drivers/net/usb/zaurus.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index 241756e0e86f..1a2234c20514 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c @@ -331,17 +331,7 @@ static const struct usb_device_id products [] = { ZAURUS_MASTER_INTERFACE, .driver_info = ZAURUS_PXA_INFO, }, - - -/* At least some of the newest PXA units have very different lies about - * their standards support: they claim to be cell phones offering - * direct access to their radios! (No, they don't conform to CDC MDLM.) - */ { - USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &bogus_mdlm_info, -}, { /* Motorola MOTOMAGX phones */ USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), -- cgit v1.2.3 From 140fe3b1ab9c082182ef13359fab4ddba95c24c3 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 21 Jun 2011 10:35:55 +0800 Subject: jump_label: Fix jump_label update for modules The jump labels entries for modules do not stop at __stop__jump_table, but after mod->jump_entries + mod_num_jump_entries. By checking the wrong end point, module trace events never get enabled. Cc: Ingo Molnar Acked-by: Jason Baron Tested-by: Avi Kivity Tested-by: Johannes Berg Signed-off-by: Xiao Guangrong Link: http://lkml.kernel.org/r/4E00038B.2060404@cn.fujitsu.com Signed-off-by: Steven Rostedt --- kernel/jump_label.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index fa27e750dbc0..a8ce45097f3d 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -375,15 +375,19 @@ int jump_label_text_reserved(void *start, void *end) static void jump_label_update(struct jump_label_key *key, int enable) { - struct jump_entry *entry = key->entries; - - /* if there are no users, entry can be NULL */ - if (entry) - __jump_label_update(key, entry, __stop___jump_table, enable); + struct jump_entry *entry = key->entries, *stop = __stop___jump_table; #ifdef CONFIG_MODULES + struct module *mod = __module_address((jump_label_t)key); + __jump_label_mod_update(key, enable); + + if (mod) + stop = mod->jump_entries + mod->num_jump_entries; #endif + /* if there are no users, entry can be NULL */ + if (entry) + __jump_label_update(key, entry, stop, enable); } #endif -- cgit v1.2.3 From e999dc50404d401150a5429b6459473a691fd1a0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 13 Jun 2011 12:14:07 +0100 Subject: ASoC: Fix Blackfin I2S _pointer() implementation return in bounds values The Blackfin DMA controller can report one frame beyond the end of the buffer in the wraparound case but ALSA requires that the pointer always be in the buffer. Do the wraparound to handle this. A similar bug is likely to apply to the other Blackfin PCM drivers but the code is less obvious to inspection and I don't have a user to test. Reported-by: Kieran O'Leary Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/blackfin/bf5xx-i2s-pcm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index b5101efd1c87..f1fd95bb6416 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c @@ -138,11 +138,20 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) pr_debug("%s enter\n", __func__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { diff = sport_curr_offset_tx(sport); - frames = bytes_to_frames(substream->runtime, diff); } else { diff = sport_curr_offset_rx(sport); - frames = bytes_to_frames(substream->runtime, diff); } + + /* + * TX at least can report one frame beyond the end of the + * buffer if we hit the wraparound case - clamp to within the + * buffer as the ALSA APIs require. + */ + if (diff == snd_pcm_lib_buffer_bytes(substream)) + diff = 0; + + frames = bytes_to_frames(substream->runtime, diff); + return frames; } -- cgit v1.2.3 From 38553564dc1052640515ed86be3ccb76cda6eee7 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 3 Jun 2011 08:23:20 -0500 Subject: [SCSI] ibmvfc: Fix Virtual I/O failover hang If a Virtual I/O server fails in a dual virtual I/O server multipath configuration, ensure we delete all remote ports so that path failover can occur. For a single path configuration, the remote ports will go into devloss state. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index b7650613b8c2..bdfa223a7dbb 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -4306,8 +4306,8 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) spin_lock_irqsave(vhost->host->host_lock, flags); if (rc == H_CLOSED) vio_enable_interrupts(to_vio_dev(vhost->dev)); - else if (rc || (rc = ibmvfc_send_crq_init(vhost)) || - (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) { + if (rc || (rc = ibmvfc_send_crq_init(vhost)) || + (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) { ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc); } -- cgit v1.2.3 From c2dd32e02648d77466f320d6edd157b5080e7c99 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Fri, 3 Jun 2011 09:57:29 -0500 Subject: [SCSI] hpsa: fix dma unmap error in hpsa_passthru_ioctl Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index c6c0434d8034..a75122d1c710 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2580,7 +2580,8 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp) c->SG[0].Ext = 0; /* we are not chaining*/ } hpsa_scsi_do_simple_cmd_core(h, c); - hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL); + if (iocommand.buf_size > 0) + hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL); check_ioctl_unit_attention(h, c); /* Copy the error information out */ -- cgit v1.2.3 From db111e18ec19bbadbf44a60f73bf2ff5991dc915 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Fri, 3 Jun 2011 09:57:34 -0500 Subject: [SCSI] hpsa: fix potential overrun while memcpy'ing sense data This memcpy: memcpy(cmd->sense_buffer, ei->SenseInfo, ei->SenseLen > SCSI_SENSE_BUFFERSIZE ? SCSI_SENSE_BUFFERSIZE : ei->SenseLen); The ei->SenseLen field is filled in by the Smart Array. For requests to logical drives, it will not exceed 32 bytes, so should be ok, but for physical requests it depends on the target device, not the Smart Array. It's conceivable that this could exceed the 32 byte size of ei->SenseInfo. In that case, the memcpy would read past the end of ei->SenseInfo, copying data from the next command, as if it were sense data, or, if it happened to be the very last command in the block of allocated commands, could fall off the end of the allocated area and crash. I'm not aware of anyone ever encountering this behavior, but it could conceivably happen. This bug was found by Coverity. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index a75122d1c710..6bba23a26303 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1037,6 +1037,7 @@ static void complete_scsi_command(struct CommandList *cp) unsigned char sense_key; unsigned char asc; /* additional sense code */ unsigned char ascq; /* additional sense code qualifier */ + unsigned long sense_data_size; ei = cp->err_info; cmd = (struct scsi_cmnd *) cp->scsi_cmd; @@ -1051,10 +1052,14 @@ static void complete_scsi_command(struct CommandList *cp) cmd->result |= ei->ScsiStatus; /* copy the sense data whether we need to or not. */ - memcpy(cmd->sense_buffer, ei->SenseInfo, - ei->SenseLen > SCSI_SENSE_BUFFERSIZE ? - SCSI_SENSE_BUFFERSIZE : - ei->SenseLen); + if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo)) + sense_data_size = SCSI_SENSE_BUFFERSIZE; + else + sense_data_size = sizeof(ei->SenseInfo); + if (ei->SenseLen < sense_data_size) + sense_data_size = ei->SenseLen; + + memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size); scsi_set_resid(cmd, ei->ResidualCnt); if (ei->CommandStatus == 0) { -- cgit v1.2.3 From 49743170556e13156a64f8f20fa412805771b4e1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 29 Jun 2011 10:10:07 -0700 Subject: ahci: change 'masking port_map' printk to KERN_WARNING level It's not so much an error as a warning about normal Marvell crazines. So don't use KERN_ERR that ends up spamming the console even in quiet mode, it's not _that_ critical. Explained by Jeff: "Long explanation, it's a mess: Marvell took standard AHCI, and bastardized it to include a weird mode whereby PATA devices appear inside the AHCI DMA and interrupt infrastructure you're familiar with. So, PATA devices appear via pata_marvell driver, using basic legacy IDE programming interface. But SATA devices, which might also be attached to this chip, either work in under-performing mode or simply don't work at all (e.g. newer 6 Gbps devices or port multiplier attachments, NCQ, ...) On the other hand, 'ahci' driver loads and works with the chip's attached SATA devices quite beautifully, but is completely unable to drive any attached PATA devices, due to the Marvell-specific PATA-under-AHCI interface. The "masking port_map 0x7 -> 0x3" message is the ahci driver "hiding" the PATA port(s) from itself, making sure it will only drive the SATA ports it knows how to drive." Acked-by: Jeff Garzik Signed-off-by: Linus Torvalds --- drivers/ata/libahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index d38c40fe4ddb..41223c7f0206 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -452,7 +452,7 @@ void ahci_save_initial_config(struct device *dev, } if (mask_port_map) { - dev_printk(KERN_ERR, dev, "masking port_map 0x%x -> 0x%x\n", + dev_printk(KERN_WARNING, dev, "masking port_map 0x%x -> 0x%x\n", port_map, port_map & mask_port_map); port_map &= mask_port_map; -- cgit v1.2.3 From d70bed1947772f34d66ada3bd923bfc12ea2452b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Jun 2011 00:30:34 -0700 Subject: drm/i915: Hold struct_mutex during i915_save_state/i915_restore_state Lots of register access in these functions, some of which requires the struct mutex. These functions now hold the struct mutex across the calls to i915_save_display and i915_restore_display, and so the internal mutex calls in those functions have been removed. To ensure that no-one else was calling them (and hence violating the new required locking invarient), those functions have been made static. gen6_enable_rps locks the struct mutex, and so i915_restore_state unlocks the mutex around calls to that function. Reviewed-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_suspend.c | 19 +++++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eddabf68e97a..1c8bfb1300d7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -997,8 +997,6 @@ extern unsigned int i915_enable_fbc; extern int i915_suspend(struct drm_device *dev, pm_message_t state); extern int i915_resume(struct drm_device *dev); -extern void i915_save_display(struct drm_device *dev); -extern void i915_restore_display(struct drm_device *dev); extern int i915_master_create(struct drm_device *dev, struct drm_master *master); extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master); diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index e8152d23d5b6..5257cfc34c35 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -597,7 +597,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) return; } -void i915_save_display(struct drm_device *dev) +static void i915_save_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -678,7 +678,6 @@ void i915_save_display(struct drm_device *dev) } /* VGA state */ - mutex_lock(&dev->struct_mutex); dev_priv->saveVGA0 = I915_READ(VGA0); dev_priv->saveVGA1 = I915_READ(VGA1); dev_priv->saveVGA_PD = I915_READ(VGA_PD); @@ -688,10 +687,9 @@ void i915_save_display(struct drm_device *dev) dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); i915_save_vga(dev); - mutex_unlock(&dev->struct_mutex); } -void i915_restore_display(struct drm_device *dev) +static void i915_restore_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -783,7 +781,6 @@ void i915_restore_display(struct drm_device *dev) else I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); - mutex_lock(&dev->struct_mutex); I915_WRITE(VGA0, dev_priv->saveVGA0); I915_WRITE(VGA1, dev_priv->saveVGA1); I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); @@ -791,7 +788,6 @@ void i915_restore_display(struct drm_device *dev) udelay(150); i915_restore_vga(dev); - mutex_unlock(&dev->struct_mutex); } int i915_save_state(struct drm_device *dev) @@ -801,6 +797,8 @@ int i915_save_state(struct drm_device *dev) pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); + mutex_lock(&dev->struct_mutex); + /* Hardware status page */ dev_priv->saveHWS = I915_READ(HWS_PGA); @@ -840,6 +838,8 @@ int i915_save_state(struct drm_device *dev) for (i = 0; i < 3; i++) dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); + mutex_unlock(&dev->struct_mutex); + return 0; } @@ -850,6 +850,8 @@ int i915_restore_state(struct drm_device *dev) pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); + mutex_lock(&dev->struct_mutex); + /* Hardware status page */ I915_WRITE(HWS_PGA, dev_priv->saveHWS); @@ -867,6 +869,7 @@ int i915_restore_state(struct drm_device *dev) I915_WRITE(IER, dev_priv->saveIER); I915_WRITE(IMR, dev_priv->saveIMR); } + mutex_unlock(&dev->struct_mutex); intel_init_clock_gating(dev); @@ -878,6 +881,8 @@ int i915_restore_state(struct drm_device *dev) if (IS_GEN6(dev)) gen6_enable_rps(dev_priv); + mutex_lock(&dev->struct_mutex); + /* Cache mode state */ I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); @@ -891,6 +896,8 @@ int i915_restore_state(struct drm_device *dev) for (i = 0; i < 3; i++) I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); + mutex_unlock(&dev->struct_mutex); + intel_i2c_reset(dev); return 0; -- cgit v1.2.3 From c31eb8e926835582cd186b33a7a864880a4c0c79 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 28 Jun 2011 18:21:19 +0530 Subject: ath9k: Fix suspend/resume when no interface is UP When no interface has been brought up, the chip's power state continued as AWAKE. So during resume, the chip never been powered up. Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index b8cbfc707213..3bad0b2cf9a3 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -278,6 +278,12 @@ static int ath_pci_suspend(struct device *device) ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); + /* The device has to be moved to FULLSLEEP forcibly. + * Otherwise the chip never moved to full sleep, + * when no interface is up. + */ + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); + return 0; } -- cgit v1.2.3 From a0b8de350be458b33248e48b2174d9af8a4c4798 Mon Sep 17 00:00:00 2001 From: "Eugene A. Shatokhin" Date: Tue, 28 Jun 2011 23:04:51 -0400 Subject: ath5k: fix memory leak when fewer than N_PD_CURVES are in use We would free the proper number of curves, but in the wrong slots, due to a missing level of indirection through the pdgain_idx table. It's simpler just to try to free all four slots, so do that. Cc: stable@kernel.org Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 1fef84f87c78..392771f93759 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -691,14 +691,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) if (!chinfo[pier].pd_curves) continue; - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) { struct ath5k_pdgain_info *pd = &chinfo[pier].pd_curves[pdg]; - if (pd != NULL) { - kfree(pd->pd_step); - kfree(pd->pd_pwr); - } + kfree(pd->pd_step); + kfree(pd->pd_pwr); } kfree(chinfo[pier].pd_curves); -- cgit v1.2.3 From dc501fbc4389f6c15a8da14684b5926e0d9553da Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 29 Jun 2011 11:41:51 -0700 Subject: drm/i915: Don't call describe_obj on NULL pointers Reported-by: Pavel Roskin Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38777 Cc: Chris Wilson Signed-off-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_debugfs.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4d46441cbe2d..0a893f7400fa 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1207,13 +1207,17 @@ static int i915_context_status(struct seq_file *m, void *unused) if (ret) return ret; - seq_printf(m, "power context "); - describe_obj(m, dev_priv->pwrctx); - seq_printf(m, "\n"); + if (dev_priv->pwrctx) { + seq_printf(m, "power context "); + describe_obj(m, dev_priv->pwrctx); + seq_printf(m, "\n"); + } - seq_printf(m, "render context "); - describe_obj(m, dev_priv->renderctx); - seq_printf(m, "\n"); + if (dev_priv->renderctx) { + seq_printf(m, "render context "); + describe_obj(m, dev_priv->renderctx); + seq_printf(m, "\n"); + } mutex_unlock(&dev->mode_config.mutex); -- cgit v1.2.3 From a18b989a5c12ca82ed37f94279273ddbc073758a Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Thu, 26 May 2011 13:30:34 +1000 Subject: crypto: caam - fix operator precedence in shared descriptor allocation setkey allocates 16 bytes (CAAM_CMD_SZ * DESC_AEAD_SHARED_TEXT_LEN) shy of what is needed to store the shared descriptor, resulting in memory corruption. Fix this. Signed-off-by: Kim Phillips Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index d0e65d6ddc77..676d957c22b0 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -238,9 +238,9 @@ static int build_sh_desc_ipsec(struct caam_ctx *ctx) /* build shared descriptor for this session */ sh_desc = kmalloc(CAAM_CMD_SZ * DESC_AEAD_SHARED_TEXT_LEN + - keys_fit_inline ? - ctx->split_key_pad_len + ctx->enckeylen : - CAAM_PTR_SZ * 2, GFP_DMA | GFP_KERNEL); + (keys_fit_inline ? + ctx->split_key_pad_len + ctx->enckeylen : + CAAM_PTR_SZ * 2), GFP_DMA | GFP_KERNEL); if (!sh_desc) { dev_err(jrdev, "could not allocate shared descriptor\n"); return -ENOMEM; -- cgit v1.2.3 From b271a988eb9c3944c50fb62c21ac61860090d3ba Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 24 Jun 2011 13:15:38 +0000 Subject: drm/radeon/kms: increase rom size for atrm method The vbios rom is >64k on a lot of modern asics. Increase the fetch size for atrm to make sure we don't miss part of a larger rom. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_bios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 1aba85cad1a8..3fc5fa1aefd0 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -104,7 +104,7 @@ static bool radeon_read_bios(struct radeon_device *rdev) static bool radeon_atrm_get_bios(struct radeon_device *rdev) { int ret; - int size = 64 * 1024; + int size = 256 * 1024; int i; if (!radeon_atrm_supported(rdev->pdev)) -- cgit v1.2.3 From 79d2427338e8da362678de32a1c8af1dc8a9810a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jun 2011 11:27:47 +0100 Subject: drm/i915/overlay: Fix unpinning along init error paths As pointed out by Dan Carpenter, it was seemingly possible to hit an error whilst mapping the buffer for the regs (except the only likely error returns should not happen during init) and so leak a pin count on the bo. To handle this we would need to reacquire the struct mutex, so for simplicity rearrange for the lock to be held for the entire function. For extra pedagogy, test that we only call init once. Signed-off-by: Chris Wilson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_overlay.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 56a8e2aea19c..9e2959bc91cd 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1409,6 +1409,11 @@ void intel_setup_overlay(struct drm_device *dev) overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); if (!overlay) return; + + mutex_lock(&dev->struct_mutex); + if (WARN_ON(dev_priv->overlay)) + goto out_free; + overlay->dev = dev; reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); @@ -1416,8 +1421,6 @@ void intel_setup_overlay(struct drm_device *dev) goto out_free; overlay->reg_bo = reg_bo; - mutex_lock(&dev->struct_mutex); - if (OVERLAY_NEEDS_PHYSICAL(dev)) { ret = i915_gem_attach_phys_object(dev, reg_bo, I915_GEM_PHYS_OVERLAY_REGS, @@ -1442,8 +1445,6 @@ void intel_setup_overlay(struct drm_device *dev) } } - mutex_unlock(&dev->struct_mutex); - /* init all values */ overlay->color_key = 0x0101fe; overlay->brightness = -19; @@ -1452,7 +1453,7 @@ void intel_setup_overlay(struct drm_device *dev) regs = intel_overlay_map_regs(overlay); if (!regs) - goto out_free_bo; + goto out_unpin_bo; memset(regs, 0, sizeof(struct overlay_registers)); update_polyphase_filter(regs); @@ -1461,15 +1462,17 @@ void intel_setup_overlay(struct drm_device *dev) intel_overlay_unmap_regs(overlay, regs); dev_priv->overlay = overlay; + mutex_unlock(&dev->struct_mutex); DRM_INFO("initialized overlay support\n"); return; out_unpin_bo: - i915_gem_object_unpin(reg_bo); + if (!OVERLAY_NEEDS_PHYSICAL(dev)) + i915_gem_object_unpin(reg_bo); out_free_bo: drm_gem_object_unreference(®_bo->base); - mutex_unlock(&dev->struct_mutex); out_free: + mutex_unlock(&dev->struct_mutex); kfree(overlay); return; } -- cgit v1.2.3 From f71d4af4cd475aced6d9ec9730b03885ac80b833 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 28 Jun 2011 13:00:41 -0700 Subject: drm/i915: move IRQ function table init to i915_irq.c This lets us make the various IRQ functions static and helps avoid problems like the one fixed in "drm/i915: Use chipset-specific irq installers" where one of the exported functions was called rather than the chipset specific version. This also fixes a UMS-mode bug -- the correct irq functions for IRL and later chips were only getting loaded in the KMS path. Signed-off-by: Jesse Barnes Reviewed-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_dma.c | 31 +--------------- drivers/gpu/drm/i915/i915_drv.c | 8 ----- drivers/gpu/drm/i915/i915_drv.h | 30 +--------------- drivers/gpu/drm/i915/i915_irq.c | 78 ++++++++++++++++++++++++++++++----------- 4 files changed, 60 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2b79588541e7..e1787022d6c8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1266,30 +1266,6 @@ static int i915_load_modeset_init(struct drm_device *dev) intel_modeset_gem_init(dev); - if (IS_IVYBRIDGE(dev)) { - /* Share pre & uninstall handlers with ILK/SNB */ - dev->driver->irq_handler = ivybridge_irq_handler; - dev->driver->irq_preinstall = ironlake_irq_preinstall; - dev->driver->irq_postinstall = ivybridge_irq_postinstall; - dev->driver->irq_uninstall = ironlake_irq_uninstall; - dev->driver->enable_vblank = ivybridge_enable_vblank; - dev->driver->disable_vblank = ivybridge_disable_vblank; - } else if (HAS_PCH_SPLIT(dev)) { - dev->driver->irq_handler = ironlake_irq_handler; - dev->driver->irq_preinstall = ironlake_irq_preinstall; - dev->driver->irq_postinstall = ironlake_irq_postinstall; - dev->driver->irq_uninstall = ironlake_irq_uninstall; - dev->driver->enable_vblank = ironlake_enable_vblank; - dev->driver->disable_vblank = ironlake_disable_vblank; - } else { - dev->driver->irq_preinstall = i915_driver_irq_preinstall; - dev->driver->irq_postinstall = i915_driver_irq_postinstall; - dev->driver->irq_uninstall = i915_driver_irq_uninstall; - dev->driver->irq_handler = i915_driver_irq_handler; - dev->driver->enable_vblank = i915_enable_vblank; - dev->driver->disable_vblank = i915_disable_vblank; - } - ret = drm_irq_install(dev); if (ret) goto cleanup_gem; @@ -2017,12 +1993,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) /* enable GEM by default */ dev_priv->has_gem = 1; - dev->driver->get_vblank_counter = i915_get_vblank_counter; - dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ - if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { - dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ - dev->driver->get_vblank_counter = gm45_get_vblank_counter; - } + intel_irq_init(dev); /* Try to make sure MCHBAR is enabled before poking at it */ intel_setup_mchbar(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 609358faaa90..013d304455b9 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -765,14 +765,6 @@ static struct drm_driver driver = { .resume = i915_resume, .device_is_agp = i915_driver_device_is_agp, - .enable_vblank = i915_enable_vblank, - .disable_vblank = i915_disable_vblank, - .get_vblank_timestamp = i915_get_vblank_timestamp, - .get_scanout_position = i915_get_crtc_scanoutpos, - .irq_preinstall = i915_driver_irq_preinstall, - .irq_postinstall = i915_driver_irq_postinstall, - .irq_uninstall = i915_driver_irq_uninstall, - .irq_handler = i915_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, .master_create = i915_master_create, .master_destroy = i915_master_destroy, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1c8bfb1300d7..f245c588ae95 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1031,33 +1031,12 @@ extern int i915_irq_emit(struct drm_device *dev, void *data, extern int i915_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); -extern void i915_driver_irq_preinstall(struct drm_device * dev); -extern int i915_driver_irq_postinstall(struct drm_device *dev); -extern void i915_driver_irq_uninstall(struct drm_device * dev); - -extern irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS); -extern void ironlake_irq_preinstall(struct drm_device *dev); -extern int ironlake_irq_postinstall(struct drm_device *dev); -extern void ironlake_irq_uninstall(struct drm_device *dev); - -extern irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS); -extern void ivybridge_irq_preinstall(struct drm_device *dev); -extern int ivybridge_irq_postinstall(struct drm_device *dev); -extern void ivybridge_irq_uninstall(struct drm_device *dev); +extern void intel_irq_init(struct drm_device *dev); extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int i915_enable_vblank(struct drm_device *dev, int crtc); -extern void i915_disable_vblank(struct drm_device *dev, int crtc); -extern int ironlake_enable_vblank(struct drm_device *dev, int crtc); -extern void ironlake_disable_vblank(struct drm_device *dev, int crtc); -extern int ivybridge_enable_vblank(struct drm_device *dev, int crtc); -extern void ivybridge_disable_vblank(struct drm_device *dev, int crtc); -extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); -extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -1068,13 +1047,6 @@ void i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); void intel_enable_asle (struct drm_device *dev); -int i915_get_vblank_timestamp(struct drm_device *dev, int crtc, - int *max_error, - struct timeval *vblank_time, - unsigned flags); - -int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, - int *vpos, int *hpos); #ifdef CONFIG_DEBUG_FS extern void i915_destroy_error_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ae2b49969b99..226d8b296e69 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -152,7 +152,7 @@ i915_pipe_enabled(struct drm_device *dev, int pipe) /* Called from drm generic code, passed a 'crtc', which * we use as a pipe index */ -u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) +static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long high_frame; @@ -184,7 +184,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) return (high1 << 8) | low; } -u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) +static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int reg = PIPE_FRMCOUNT_GM45(pipe); @@ -198,7 +198,7 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) return I915_READ(reg); } -int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, +static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, int *vpos, int *hpos) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -264,7 +264,7 @@ int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, return ret; } -int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, +static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, int *max_error, struct timeval *vblank_time, unsigned flags) @@ -462,7 +462,7 @@ static void pch_irq_handler(struct drm_device *dev) DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); } -irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -550,7 +550,7 @@ done: return ret; } -irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1209,7 +1209,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) } } -irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1454,7 +1454,7 @@ int i915_irq_wait(struct drm_device *dev, void *data, /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ -int i915_enable_vblank(struct drm_device *dev, int pipe) +static int i915_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1478,7 +1478,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) return 0; } -int ironlake_enable_vblank(struct drm_device *dev, int pipe) +static int ironlake_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1494,7 +1494,7 @@ int ironlake_enable_vblank(struct drm_device *dev, int pipe) return 0; } -int ivybridge_enable_vblank(struct drm_device *dev, int pipe) +static int ivybridge_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1513,7 +1513,7 @@ int ivybridge_enable_vblank(struct drm_device *dev, int pipe) /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ -void i915_disable_vblank(struct drm_device *dev, int pipe) +static void i915_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1529,7 +1529,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -void ironlake_disable_vblank(struct drm_device *dev, int pipe) +static void ironlake_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1540,7 +1540,7 @@ void ironlake_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -void ivybridge_disable_vblank(struct drm_device *dev, int pipe) +static void ivybridge_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; @@ -1728,7 +1728,7 @@ repeat: /* drm_dma.h hooks */ -void ironlake_irq_preinstall(struct drm_device *dev) +static void ironlake_irq_preinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1769,7 +1769,7 @@ void ironlake_irq_preinstall(struct drm_device *dev) POSTING_READ(SDEIER); } -int ironlake_irq_postinstall(struct drm_device *dev) +static int ironlake_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; /* enable kind of interrupts always enabled */ @@ -1841,7 +1841,7 @@ int ironlake_irq_postinstall(struct drm_device *dev) return 0; } -int ivybridge_irq_postinstall(struct drm_device *dev) +static int ivybridge_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; /* enable kind of interrupts always enabled */ @@ -1891,7 +1891,7 @@ int ivybridge_irq_postinstall(struct drm_device *dev) return 0; } -void i915_driver_irq_preinstall(struct drm_device * dev) +static void i915_driver_irq_preinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; @@ -1918,7 +1918,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev) * Must be called after intel_modeset_init or hotplug interrupts won't be * enabled correctly. */ -int i915_driver_irq_postinstall(struct drm_device *dev) +static int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; @@ -1994,7 +1994,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) return 0; } -void ironlake_irq_uninstall(struct drm_device *dev) +static void ironlake_irq_uninstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -2014,7 +2014,7 @@ void ironlake_irq_uninstall(struct drm_device *dev) I915_WRITE(GTIIR, I915_READ(GTIIR)); } -void i915_driver_irq_uninstall(struct drm_device * dev) +static void i915_driver_irq_uninstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; @@ -2040,3 +2040,41 @@ void i915_driver_irq_uninstall(struct drm_device * dev) I915_READ(PIPESTAT(pipe)) & 0x8000ffff); I915_WRITE(IIR, I915_READ(IIR)); } + +void intel_irq_init(struct drm_device *dev) +{ + dev->driver->get_vblank_counter = i915_get_vblank_counter; + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ + if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { + dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ + dev->driver->get_vblank_counter = gm45_get_vblank_counter; + } + + + dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; + dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; + + if (IS_IVYBRIDGE(dev)) { + /* Share pre & uninstall handlers with ILK/SNB */ + dev->driver->irq_handler = ivybridge_irq_handler; + dev->driver->irq_preinstall = ironlake_irq_preinstall; + dev->driver->irq_postinstall = ivybridge_irq_postinstall; + dev->driver->irq_uninstall = ironlake_irq_uninstall; + dev->driver->enable_vblank = ivybridge_enable_vblank; + dev->driver->disable_vblank = ivybridge_disable_vblank; + } else if (HAS_PCH_SPLIT(dev)) { + dev->driver->irq_handler = ironlake_irq_handler; + dev->driver->irq_preinstall = ironlake_irq_preinstall; + dev->driver->irq_postinstall = ironlake_irq_postinstall; + dev->driver->irq_uninstall = ironlake_irq_uninstall; + dev->driver->enable_vblank = ironlake_enable_vblank; + dev->driver->disable_vblank = ironlake_disable_vblank; + } else { + dev->driver->irq_preinstall = i915_driver_irq_preinstall; + dev->driver->irq_postinstall = i915_driver_irq_postinstall; + dev->driver->irq_uninstall = i915_driver_irq_uninstall; + dev->driver->irq_handler = i915_driver_irq_handler; + dev->driver->enable_vblank = i915_enable_vblank; + dev->driver->disable_vblank = i915_disable_vblank; + } +} -- cgit v1.2.3 From 4d4d6fbb7c3125f17a4864215191e54b975cfb4f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 29 Jun 2011 10:13:04 +0000 Subject: ARM: mach-shmobile: make a struct in board-ap4evb.c static struct soc_camera_link imx074_link in board-ap4evb.c doesn't have to be global. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ap4evb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index f6b687f61c28..803bc6edfca4 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -913,7 +913,7 @@ static struct i2c_board_info imx074_info = { I2C_BOARD_INFO("imx074", 0x1a), }; -struct soc_camera_link imx074_link = { +static struct soc_camera_link imx074_link = { .bus_id = 0, .board_info = &imx074_info, .i2c_adapter_id = 0, -- cgit v1.2.3 From 7b61ca5d94baf2c31971871fa875750f90fce098 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 30 Jun 2011 15:04:38 +0900 Subject: sh: Fix up unmet dependency warnings with USB EHCI/OHCI selects. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index df89ba5e104b..bbdeb48bbf8e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -348,7 +348,7 @@ config CPU_SUBTYPE_SH7720 select SYS_SUPPORTS_CMT select ARCH_WANT_OPTIONAL_GPIOLIB select USB_ARCH_HAS_OHCI - select USB_OHCI_SH + select USB_OHCI_SH if USB_OHCI_HCD help Select SH7720 if you have a SH3-DSP SH7720 CPU. @@ -358,7 +358,7 @@ config CPU_SUBTYPE_SH7721 select CPU_HAS_DSP select SYS_SUPPORTS_CMT select USB_ARCH_HAS_OHCI - select USB_OHCI_SH + select USB_OHCI_SH if USB_OHCI_HCD help Select SH7721 if you have a SH3-DSP SH7721 CPU. @@ -442,7 +442,7 @@ config CPU_SUBTYPE_SH7763 bool "Support SH7763 processor" select CPU_SH4A select USB_ARCH_HAS_OHCI - select USB_OHCI_SH + select USB_OHCI_SH if USB_OHCI_HCD help Select SH7763 if you have a SH4A SH7763(R5S77631) CPU. @@ -470,9 +470,9 @@ config CPU_SUBTYPE_SH7786 select GENERIC_CLOCKEVENTS_BROADCAST if SMP select ARCH_WANT_OPTIONAL_GPIOLIB select USB_ARCH_HAS_OHCI - select USB_OHCI_SH + select USB_OHCI_SH if USB_OHCI_HCD select USB_ARCH_HAS_EHCI - select USB_EHCI_SH + select USB_EHCI_SH if USB_EHCI_HCD config CPU_SUBTYPE_SHX3 bool "Support SH-X3 processor" -- cgit v1.2.3 From 9ab3a15d95809a5d4feecda58b3749c53590e1b2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 30 Jun 2011 15:10:06 +0900 Subject: sh: use printk_ratelimited instead of printk_ratelimit Follows the powerpc change, for much the same rationale. Signed-off-by: Paul Mundt --- arch/sh/kernel/irq.c | 6 +++--- arch/sh/mm/alignment.c | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 91971103b62b..a3ee91971129 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -268,9 +269,8 @@ void migrate_irqs(void) unsigned int newcpu = cpumask_any_and(data->affinity, cpu_online_mask); if (newcpu >= nr_cpu_ids) { - if (printk_ratelimit()) - printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n", - irq, cpu); + pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n", + irq, cpu); cpumask_setall(data->affinity); newcpu = cpumask_any_and(data->affinity, diff --git a/arch/sh/mm/alignment.c b/arch/sh/mm/alignment.c index b2595b8548ee..620fa7ff9eec 100644 --- a/arch/sh/mm/alignment.c +++ b/arch/sh/mm/alignment.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -95,13 +96,13 @@ int set_unalign_ctl(struct task_struct *tsk, unsigned int val) void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn, struct pt_regs *regs) { - if (user_mode(regs) && (se_usermode & UM_WARN) && printk_ratelimit()) - pr_notice("Fixing up unaligned userspace access " + if (user_mode(regs) && (se_usermode & UM_WARN)) + pr_notice_ratelimited("Fixing up unaligned userspace access " "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", tsk->comm, task_pid_nr(tsk), (void *)instruction_pointer(regs), insn); - else if (se_kernmode_warn && printk_ratelimit()) - pr_notice("Fixing up unaligned kernel access " + else if (se_kernmode_warn) + pr_notice_ratelimited("Fixing up unaligned kernel access " "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", tsk->comm, task_pid_nr(tsk), (void *)instruction_pointer(regs), insn); -- cgit v1.2.3 From e336f61fe238ade68eca7850d64fd6c194bdc998 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Tue, 28 Jun 2011 08:43:29 +0200 Subject: MAINTAINERS: update AVR32 and AT32AP maintainers This alters the maintenance of the AVR32 architecture and the AT32AP machine code to be shared between Haavard Skinnemoen and me. The status is also changed to maintained, as we no longer are being paid to look after this architecture. Signed-off-by: Hans-Christian Egtvedt Acked-by: Haavard Skinnemoen --- MAINTAINERS | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f0358cd91de3..782f11e31705 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1345,16 +1345,18 @@ F: drivers/auxdisplay/ F: include/linux/cfag12864b.h AVR32 ARCHITECTURE -M: Hans-Christian Egtvedt +M: Haavard Skinnemoen +M: Hans-Christian Egtvedt W: http://www.atmel.com/products/AVR32/ W: http://avr32linux.org/ W: http://avrfreaks.net/ -S: Supported +S: Maintained F: arch/avr32/ AVR32/AT32AP MACHINE SUPPORT -M: Hans-Christian Egtvedt -S: Supported +M: Haavard Skinnemoen +M: Hans-Christian Egtvedt +S: Maintained F: arch/avr32/mach-at32ap/ AX.25 NETWORK LAYER -- cgit v1.2.3 From 0cfdd247d1779d5ffc8f685b172a526ecdc6773f Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 25 May 2011 11:14:35 +0200 Subject: drbd: Use the correct max_bio_size when creating resync requests Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_worker.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 4d76b06b6b20..4d3e6f6213ba 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -536,12 +536,7 @@ static int w_make_resync_request(struct drbd_conf *mdev, return 1; } - /* starting with drbd 8.3.8, we can handle multi-bio EEs, - * if it should be necessary */ - max_bio_size = - mdev->agreed_pro_version < 94 ? queue_max_hw_sectors(mdev->rq_queue) << 9 : - mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_BIO_SIZE; - + max_bio_size = queue_max_hw_sectors(mdev->rq_queue) << 9; number = drbd_rs_number_requests(mdev); if (number == 0) goto requeue; -- cgit v1.2.3 From 829c60878626be290a4c248e8f1b86a0d5cbd38b Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Fri, 3 Jun 2011 21:18:13 +0200 Subject: drbd: add missing spinlock to bitmap receive During bitmap exchange, when using the RLE bitmap compression scheme, we have a code path that can set the whole bitmap at once. To avoid holding spin_lock_irq() for too long, we used to lock out other bitmap modifications during bitmap exchange by other means, and then, knowing we have exclusive access to the bitmap, modify it without the spinlock, and with IRQs enabled. Since we now allow local IO to continue, potentially setting additional bits during the bitmap receive phase, this is no longer true, and we get uncoordinated updates of bitmap members, causing bm_set to no longer accurately reflect the total number of set bits. To actually see this, you'd need to have a large bitmap, use RLE bitmap compression, and have busy IO during sync handshake and bitmap exchange. Fix this by taking the spin_lock_irq() in this code path as well, but calling cond_resched_lock() after each page worth of bits processed. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index f440a02dfdb1..1e89a74ddb17 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -112,9 +112,6 @@ struct drbd_bitmap { struct task_struct *bm_task; }; -static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, - unsigned long e, int val, const enum km_type km); - #define bm_print_lock_info(m) __bm_print_lock_info(m, __func__) static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func) { @@ -1256,7 +1253,7 @@ unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_f * expected to be called for only a few bits (e - s about BITS_PER_LONG). * Must hold bitmap lock already. */ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, - unsigned long e, int val, const enum km_type km) + unsigned long e, int val) { struct drbd_bitmap *b = mdev->bitmap; unsigned long *p_addr = NULL; @@ -1274,14 +1271,14 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, unsigned int page_nr = bm_bit_to_page_idx(b, bitnr); if (page_nr != last_page_nr) { if (p_addr) - __bm_unmap(p_addr, km); + __bm_unmap(p_addr, KM_IRQ1); if (c < 0) bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]); else if (c > 0) bm_set_page_need_writeout(b->bm_pages[last_page_nr]); changed_total += c; c = 0; - p_addr = __bm_map_pidx(b, page_nr, km); + p_addr = __bm_map_pidx(b, page_nr, KM_IRQ1); last_page_nr = page_nr; } if (val) @@ -1290,7 +1287,7 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, c -= (0 != __test_and_clear_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr)); } if (p_addr) - __bm_unmap(p_addr, km); + __bm_unmap(p_addr, KM_IRQ1); if (c < 0) bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]); else if (c > 0) @@ -1318,7 +1315,7 @@ static int bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, if ((val ? BM_DONT_SET : BM_DONT_CLEAR) & b->bm_flags) bm_print_lock_info(mdev); - c = __bm_change_bits_to(mdev, s, e, val, KM_IRQ1); + c = __bm_change_bits_to(mdev, s, e, val); spin_unlock_irqrestore(&b->bm_lock, flags); return c; @@ -1343,16 +1340,17 @@ static inline void bm_set_full_words_within_one_page(struct drbd_bitmap *b, { int i; int bits; - unsigned long *paddr = kmap_atomic(b->bm_pages[page_nr], KM_USER0); + unsigned long *paddr = kmap_atomic(b->bm_pages[page_nr], KM_IRQ1); for (i = first_word; i < last_word; i++) { bits = hweight_long(paddr[i]); paddr[i] = ~0UL; b->bm_set += BITS_PER_LONG - bits; } - kunmap_atomic(paddr, KM_USER0); + kunmap_atomic(paddr, KM_IRQ1); } -/* Same thing as drbd_bm_set_bits, but without taking the spin_lock_irqsave. +/* Same thing as drbd_bm_set_bits, + * but more efficient for a large bit range. * You must first drbd_bm_lock(). * Can be called to set the whole bitmap in one go. * Sets bits from s to e _inclusive_. */ @@ -1366,6 +1364,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi * Do not use memset, because we must account for changes, * so we need to loop over the words with hweight() anyways. */ + struct drbd_bitmap *b = mdev->bitmap; unsigned long sl = ALIGN(s,BITS_PER_LONG); unsigned long el = (e+1) & ~((unsigned long)BITS_PER_LONG-1); int first_page; @@ -1376,15 +1375,19 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi if (e - s <= 3*BITS_PER_LONG) { /* don't bother; el and sl may even be wrong. */ - __bm_change_bits_to(mdev, s, e, 1, KM_USER0); + spin_lock_irq(&b->bm_lock); + __bm_change_bits_to(mdev, s, e, 1); + spin_unlock_irq(&b->bm_lock); return; } /* difference is large enough that we can trust sl and el */ + spin_lock_irq(&b->bm_lock); + /* bits filling the current long */ if (sl) - __bm_change_bits_to(mdev, s, sl-1, 1, KM_USER0); + __bm_change_bits_to(mdev, s, sl-1, 1); first_page = sl >> (3 + PAGE_SHIFT); last_page = el >> (3 + PAGE_SHIFT); @@ -1397,7 +1400,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi /* first and full pages, unless first page == last page */ for (page_nr = first_page; page_nr < last_page; page_nr++) { bm_set_full_words_within_one_page(mdev->bitmap, page_nr, first_word, last_word); - cond_resched(); + cond_resched_lock(&b->bm_lock); first_word = 0; } @@ -1411,7 +1414,8 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi * it would trigger an assert in __bm_change_bits_to() */ if (el <= e) - __bm_change_bits_to(mdev, el, e, 1, KM_USER0); + __bm_change_bits_to(mdev, el, e, 1); + spin_unlock_irq(&b->bm_lock); } /* returns bit state -- cgit v1.2.3 From 8ccee20e3ef4e12dbf02a18f17d386569b1f73ee Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Mon, 6 Jun 2011 11:31:42 +0200 Subject: drbd: don't cond_resched_lock with IRQs disabled The last commit, drbd: add missing spinlock to bitmap receive, introduced a cond_resched_lock(), where the lock in question is taken with irqs disabled. As we must not schedule with IRQs disabled, and cond_resched_lock_irq() does not exist, yet, we re-aquire the spin_lock_irq() for each bitmap page processed in turn. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 1e89a74ddb17..61f4fae9f67e 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -1400,8 +1400,10 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi /* first and full pages, unless first page == last page */ for (page_nr = first_page; page_nr < last_page; page_nr++) { bm_set_full_words_within_one_page(mdev->bitmap, page_nr, first_word, last_word); - cond_resched_lock(&b->bm_lock); + spin_unlock_irq(&b->bm_lock); + cond_resched(); first_word = 0; + spin_lock_irq(&b->bm_lock); } /* last page (respectively only page, for first page == last page) */ -- cgit v1.2.3 From 5a8b424276f7ba50c51e7caf485b2be23739e5b8 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 14 Jun 2011 14:18:23 +0200 Subject: drbd: account bitmap IO during resync as resync-(related-)-io If we have a good resync rate, we will frequently update the on-disk bitmap, which, if not accounted for as resync io, may let an otherwise idle device appear to be "busy", and cause us to throttle resync. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 61f4fae9f67e..7b976296b564 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -991,6 +991,9 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must bio_endio(bio, -EIO); } else { submit_bio(rw, bio); + /* this should not count as user activity and cause the + * resync to throttle -- see drbd_rs_should_slow_down(). */ + atomic_add(len >> 9, &mdev->rs_sect_ev); } } -- cgit v1.2.3 From cb6518cbef5e3e36b7ae90fcab610a52ea7e9fc0 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Mon, 20 Jun 2011 14:44:45 +0200 Subject: drbd: when receive times out on meta socket, also check last receive time on data socket If we have an asymetrically congested network, we may send P_PING, but due to congestion, the corresponding P_PING_ACK would time out, and we would drop a (congested, but otherwise) healthy connection ("PingAck did not arrive in time.") Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 25d32c5aa50a..43beaca53179 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -4602,6 +4602,11 @@ int drbd_asender(struct drbd_thread *thi) dev_err(DEV, "meta connection shut down by peer.\n"); goto reconnect; } else if (rv == -EAGAIN) { + /* If the data socket received something meanwhile, + * that is good enough: peer is still alive. */ + if (time_after(mdev->last_received, + jiffies - mdev->meta.socket->sk->sk_rcvtimeo)) + continue; if (ping_timeout_active) { dev_err(DEV, "PingAck did not arrive in time.\n"); goto reconnect; @@ -4637,6 +4642,7 @@ int drbd_asender(struct drbd_thread *thi) goto reconnect; } if (received == expect) { + mdev->last_received = jiffies; D_ASSERT(cmd != NULL); if (!cmd->process(mdev, h)) goto reconnect; -- cgit v1.2.3 From 15b493d11fcce3c5547e3d7fb6d90e11ffe12777 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 28 Jun 2011 09:48:48 +0200 Subject: drbd: fix limit define, we support 1 PiByte now Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- include/linux/drbd_limits.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h index 246f576c981d..447c36752385 100644 --- a/include/linux/drbd_limits.h +++ b/include/linux/drbd_limits.h @@ -117,10 +117,10 @@ /* drbdsetup XY resize -d Z * you are free to reduce the device size to nothing, if you want to. * the upper limit with 64bit kernel, enough ram and flexible meta data - * is 16 TB, currently. */ + * is 1 PiB, currently. */ /* DRBD_MAX_SECTORS */ #define DRBD_DISK_SIZE_SECT_MIN 0 -#define DRBD_DISK_SIZE_SECT_MAX (16 * (2LLU << 30)) +#define DRBD_DISK_SIZE_SECT_MAX (1 * (2LLU << 40)) #define DRBD_DISK_SIZE_SECT_DEF 0 /* = disabled = no user size... */ #define DRBD_ON_IO_ERROR_DEF EP_PASS_ON -- cgit v1.2.3 From 86e1e98e5c6b4edab97e2b058466ef553cfd878e Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 28 Jun 2011 13:22:48 +0200 Subject: drbd: we should write meta data updates with FLUSH FUA We used to write these with BIO_RW_BARRIER aka REQ_HARDBARRIER (unless disabled in the configuration). The correct semantic now would be to write with FLUSH/FUA. For example, with activity log transactions, FUA alone is not enough, we need the corresponding bitmap update (and all related application updates) on stable storage as well. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_actlog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 09ef9a878ef0..cf0e63dd97da 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -79,7 +79,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev, md_io.error = 0; if ((rw & WRITE) && !test_bit(MD_NO_FUA, &mdev->flags)) - rw |= REQ_FUA; + rw |= REQ_FUA | REQ_FLUSH; rw |= REQ_SYNC; bio = bio_alloc(GFP_NOIO, 1); -- cgit v1.2.3 From 71276410e17653cfacfa238a363475cde9e18fb3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 30 Jun 2011 12:31:23 +0200 Subject: ALSA: cs5535 - Fix invalid big-endian conversions Fix the wrongly converted short values: sound/pci/cs5535audio/cs5535audio_pcm.c:152: warning: large integer implicitly truncated to unsigned type sound/pci/cs5535audio/cs5535audio_pcm.c:160: warning: large integer implicitly truncated to unsigned type Signed-off-by: Takashi Iwai --- sound/pci/cs5535audio/cs5535audio_pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index f16bc8aad6ed..e083122ca55a 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -149,7 +149,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[i]; desc->addr = cpu_to_le32(addr); desc->size = cpu_to_le32(period_bytes); - desc->ctlreserved = cpu_to_le32(PRD_EOP); + desc->ctlreserved = cpu_to_le16(PRD_EOP); desc_addr += sizeof(struct cs5535audio_dma_desc); addr += period_bytes; } @@ -157,7 +157,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, lastdesc = &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[periods]; lastdesc->addr = cpu_to_le32((u32) dma->desc_buf.addr); lastdesc->size = 0; - lastdesc->ctlreserved = cpu_to_le32(PRD_JMP); + lastdesc->ctlreserved = cpu_to_le16(PRD_JMP); jmpprd_addr = cpu_to_le32(lastdesc->addr + (sizeof(struct cs5535audio_dma_desc)*periods)); -- cgit v1.2.3 From 286bed0f0c447b6660e72093d7e778784fdd9ee6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 30 Jun 2011 12:45:36 +0200 Subject: ALSA: hdspm - Fix compile warnings with PPC The char can be unsigned on some architectures. Since the code checks the negative values, they should be declared as signed char explicitly. sound/pci/rme9652/hdspm.c:5449: warning: comparison is always false due to limited range of data type sound/pci/rme9652/hdspm.c:5462: warning: comparison is always false due to limited range of data type Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 3f08afc0f0d3..c8e402fc3782 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -896,11 +896,11 @@ struct hdspm { unsigned char max_channels_in; unsigned char max_channels_out; - char *channel_map_in; - char *channel_map_out; + signed char *channel_map_in; + signed char *channel_map_out; - char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; - char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; + signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; + signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; char **port_names_in; char **port_names_out; -- cgit v1.2.3 From 50176ddefa4a942419cb693dd2d8345bfdcde67c Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Tue, 31 May 2011 16:35:50 -0500 Subject: hfsplus: add missing call to bio_put() hfsplus leaks bio objects by failing to call bio_put() on the bios it allocates. Add the missing call to fix the leak. Signed-off-by: Seth Forshee Cc: # .38.x, .39.x Signed-off-by: Christoph Hellwig --- fs/hfsplus/wrapper.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 3031d81f5f0f..4ac88ff79aa6 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -36,6 +36,7 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, { DECLARE_COMPLETION_ONSTACK(wait); struct bio *bio; + int ret = 0; bio = bio_alloc(GFP_NOIO, 1); bio->bi_sector = sector; @@ -54,8 +55,10 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, wait_for_completion(&wait); if (!bio_flagged(bio, BIO_UPTODATE)) - return -EIO; - return 0; + ret = -EIO; + + bio_put(bio); + return ret; } static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) -- cgit v1.2.3 From 032016a56a1e9c83646435b32e4416d499e1f1ce Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Fri, 24 Jun 2011 01:15:02 +0400 Subject: hfsplus: Fix double iput of the same inode in hfsplus_fill_super() There is a misprint in resource deallocation code on error path in hfsplus_fill_super(): the sbi->alloc_file inode is iput twice, while the root inode in not iput at all. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Christoph Hellwig --- fs/hfsplus/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index b49b55584c84..84a47b709f51 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -500,7 +500,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) out_put_hidden_dir: iput(sbi->hidden_dir); out_put_root: - iput(sbi->alloc_file); + iput(root); out_put_alloc_file: iput(sbi->alloc_file); out_close_cat_tree: -- cgit v1.2.3 From 32dd11942aeb47f91209a446d6b10063c5b69389 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 30 Jun 2011 09:12:40 -0400 Subject: xen/mmu: Fix for linker errors when CONFIG_SMP is not defined. Simple enough - we use an extern defined symbol which is not defined when CONFIG_SMP is not defined. This fixes the linker dying. CC: stable@kernel.org Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 673e968df3cf..0ccccb67a993 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1232,7 +1232,11 @@ static void xen_flush_tlb_others(const struct cpumask *cpus, { struct { struct mmuext_op op; +#ifdef CONFIG_SMP DECLARE_BITMAP(mask, num_processors); +#else + DECLARE_BITMAP(mask, NR_CPUS); +#endif } *args; struct multicall_space mcs; -- cgit v1.2.3 From 4f3c7a18d9e8a287d31f828a259d713fe4859471 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 30 Jun 2011 15:08:04 +0200 Subject: ALSA: sb16 - Fix build errors on MIPS and others with 13bit ioctl size One of ioctl definition in sound/sb16_csp.h contains the data size over 8kB, and this causes build errors on architectures like MIPS, which define _IOC_SIZEBITS=13. For avoiding this build errors but keeping the compatibility, manually expand with _IOC() instead of using _IOW() for the problematic ioctl. Signed-off-by: Takashi Iwai --- include/sound/sb16_csp.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h index 736eac71d053..af1b49e982df 100644 --- a/include/sound/sb16_csp.h +++ b/include/sound/sb16_csp.h @@ -99,7 +99,14 @@ struct snd_sb_csp_info { /* get CSP information */ #define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info) /* load microcode to CSP */ -#define SNDRV_SB_CSP_IOCTL_LOAD_CODE _IOW('H', 0x11, struct snd_sb_csp_microcode) +/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits) + * defined for some architectures like MIPS, and it leads to build errors. + * (x86 and co have 14-bit size, thus it's valid, though.) + * As a workaround for skipping the size-limit check, here we don't use the + * normal _IOW() macro but _IOC() with the manual argument. + */ +#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \ + _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode)) /* unload microcode from CSP */ #define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12) /* start CSP */ -- cgit v1.2.3 From 155a16f21923bc2f04161ac92acca986371ef27b Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 30 Jun 2011 09:18:27 -0400 Subject: xen/pci: Use the INT_SRC_OVR IRQ (instead of GSI) to preset the ACPI SCI IRQ. In the past we would use the GSI value to preset the ACPI SCI IRQ which worked great as GSI == IRQ: ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level) While that is most often seen, there are some oddities: ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level) which means that GSI 20 (or pin 20) is to be overriden for IRQ 9. Our code that presets the interrupt for ACPI SCI however would use the GSI 20 instead of IRQ 9 ending up with: xen: sci override: global_irq=20 trigger=0 polarity=1 xen: registering gsi 20 triggering 0 polarity 1 xen: --> pirq=20 -> irq=20 xen: acpi sci 20 .. snip.. calling acpi_init+0x0/0xbc @ 1 ACPI: SCI (IRQ9) allocation failed ACPI Exception: AE_NOT_ACQUIRED, Unable to install System Control Interrupt handler (20110413/evevent-119) ACPI: Unable to start the ACPI Interpreter as the ACPI interpreter made a call to 'acpi_gsi_to_irq' which got nine. It used that value to request an IRQ (request_irq) and since that was not present it failed. The fix is to recognize that for interrupts that are overriden (in our case we only care about the ACPI SCI) we should use the IRQ number to present the IRQ instead of the using GSI. End result is that we get: xen: sci override: global_irq=20 trigger=0 polarity=1 xen: registering gsi 20 triggering 0 polarity 1 xen: --> pirq=20 -> irq=9 (gsi=9) xen: acpi sci 9 which fixes the ACPI interpreter failing on startup. CC: stable@kernel.org Reported-by: Liwei Tested-by: Liwei [http://lists.xensource.com/archives/html/xen-devel/2011-06/msg01727.html] Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/pci/xen.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 8214724ce54d..fe008309ffec 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -333,6 +333,7 @@ static int xen_register_pirq(u32 gsi, int triggering) struct physdev_map_pirq map_irq; int shareable = 0; char *name; + bool gsi_override = false; if (!xen_pv_domain()) return -1; @@ -349,11 +350,32 @@ static int xen_register_pirq(u32 gsi, int triggering) if (pirq < 0) goto out; - irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name); + /* Before we bind the GSI to a Linux IRQ, check whether + * we need to override it with bus_irq (IRQ) value. Usually for + * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so: + * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level) + * but there are oddballs where the IRQ != GSI: + * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level) + * which ends up being: gsi_to_irq[9] == 20 + * (which is what acpi_gsi_to_irq ends up calling when starting the + * the ACPI interpreter and keels over since IRQ 9 has not been + * setup as we had setup IRQ 20 for it). + */ + if (gsi == acpi_sci_override_gsi) { + /* Check whether the GSI != IRQ */ + acpi_gsi_to_irq(gsi, &irq); + if (irq != gsi) + /* Bugger, we MUST have that IRQ. */ + gsi_override = true; + } + if (gsi_override) + irq = xen_bind_pirq_gsi_to_irq(irq, pirq, shareable, name); + else + irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name); if (irq < 0) goto out; - printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d\n", pirq, irq); + printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi); map_irq.domid = DOMID_SELF; map_irq.type = MAP_PIRQ_TYPE_GSI; -- cgit v1.2.3 From daf54f1f363a61c618662ef66d4bf09d2b090941 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 30 Jun 2011 08:59:55 -0400 Subject: drm/radeon/kms: Fix chremap setup on RV770 CE CE variant requires a different chremap setup. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=35472 Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/rv770.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 6f508ffd1035..8bb347d23ca6 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -575,6 +575,12 @@ static void rv770_program_channel_remap(struct radeon_device *rdev) else tcp_chan_steer = 0x00fac688; + /* RV770 CE has special chremap setup */ + if (rdev->pdev->device == 0x944e) { + tcp_chan_steer = 0x00b08b08; + mc_shared_chremap = 0x00b08b08; + } + WREG32(TCP_CHAN_STEER, tcp_chan_steer); WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); } -- cgit v1.2.3 From 724d4c03066cec0e23b44344ad384fb4ebb7419d Mon Sep 17 00:00:00 2001 From: Henrik Ahlgren Date: Fri, 1 Jul 2011 01:48:35 +0300 Subject: CREDITS: Fix typo David Brownell's CREDITS entry should have N: (name) instead of M: (email). Signed-off-by: Henrik Ahlgren Signed-off-by: Linus Torvalds --- CREDITS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CREDITS b/CREDITS index d78359f5f64d..1deb331d96ed 100644 --- a/CREDITS +++ b/CREDITS @@ -518,7 +518,7 @@ N: Zach Brown E: zab@zabbo.net D: maestro pci sound -M: David Brownell +N: David Brownell D: Kernel engineer, mentor, and friend. Maintained USB EHCI and D: gadget layers, SPI subsystem, GPIO subsystem, and more than a few D: device drivers. His encouragement also helped many engineers get -- cgit v1.2.3 From a52a82fc3a397261ecbcbd441498be58997379c8 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 1 Jun 2011 12:57:37 -0300 Subject: [media] media: vb2: add __GFP_NOWARN to dma-sg allocator Add __GFP_NOWARN parameter to videobuf2 dma-sg allocator to prevent kernel warning and stack dump if there is not enough memory available. Videobuf2 and drivers should correctly handle no memory case, so there is no need for stack dump and extensive log. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-dma-sg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/videobuf2-dma-sg.c b/drivers/media/video/videobuf2-dma-sg.c index b2d9485aac75..10a20d9509d9 100644 --- a/drivers/media/video/videobuf2-dma-sg.c +++ b/drivers/media/video/videobuf2-dma-sg.c @@ -62,7 +62,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size) goto fail_pages_array_alloc; for (i = 0; i < buf->sg_desc.num_pages; ++i) { - buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO); + buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); if (NULL == buf->pages[i]) goto fail_pages_alloc; sg_set_page(&buf->sg_desc.sglist[i], -- cgit v1.2.3 From bf7b73efb7f52abf56b512546c3bbc35001dd696 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 8 Jun 2011 06:15:05 -0300 Subject: [media] Revert "[media] v4l2: vb2: one more fix for REQBUFS()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 31901a078af29c33c736dcbf815656920e904632. Queue should be reinitialized on each REQBUFS() call even if the memory access method and buffer count have not been changed. The user might have changed the format and if we go the short path introduced in that commit, the memory buffer will not be reallocated to fit with new format. The previous patch was just over-engineered optimization, which just introduced a bug to videobuf2. Reported-by: Uwe Kleine-König Signed-off-by: Marek Szyprowski CC: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 6ba1461d51ef..6489aa26e788 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -492,13 +492,6 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) return -EINVAL; } - /* - * If the same number of buffers and memory access method is requested - * then return immediately. - */ - if (q->memory == req->memory && req->count == q->num_buffers) - return 0; - if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) { /* * We already have buffers allocated, so first check if they -- cgit v1.2.3 From afdea8bac5e80362459940e18e705d792e677a57 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 10 Jun 2011 08:58:42 -0300 Subject: [media] media: vb2: reset queued_count value during queue reinitialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit queued_count variable was left untouched during the queue reinitialization in __vb2_queue_cancel, what might lead to mismatch between the real number of queued buffers and queued_count variable. Reported-by: Uwe Kleine-König Signed-off-by: Marek Szyprowski CC: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 6489aa26e788..84f03b25aedb 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -1189,6 +1189,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q) * has not already dequeued before initiating cancel. */ INIT_LIST_HEAD(&q->done_list); + atomic_set(&q->queued_count, 0); wake_up_all(&q->done_wq); /* -- cgit v1.2.3 From 66072d4fa7cb644f1f064e290f8fddfbd8ccd478 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 28 Jun 2011 08:29:02 -0300 Subject: [media] media: vb2: fix allocation failure check __vb2_queue_alloc function returns the number of successfully allocated buffers. There is no point in checking if the returned value is negative. If this function returns 0, videobuf2 should just return -ENOMEM to userspace, because no driver can work without memory buffers. Reported-by: Jonathan Corbet Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park CC: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 84f03b25aedb..3015e6000946 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -532,9 +532,9 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) /* Finally, allocate buffers and video memory */ ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes, plane_sizes); - if (ret < 0) { - dprintk(1, "Memory allocation failed with error: %d\n", ret); - return ret; + if (ret == 0) { + dprintk(1, "Memory allocation failed\n"); + return -ENOMEM; } /* -- cgit v1.2.3 From ca4186f06fecbf2b692a42cdea54b7ef23b2496c Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Wed, 1 Jun 2011 13:39:46 -0300 Subject: [media] media: omap3isp: fix a potential NULL deref Fix a potential NULL pointer dereference by skipping registration of external entities in case none are provided. This is useful at least when testing mere memory-to-memory scenarios. Signed-off-by: Ohad Ben-Cohen Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap3isp/isp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c index c9fd04ee70a8..94b6ed89e195 100644 --- a/drivers/media/video/omap3isp/isp.c +++ b/drivers/media/video/omap3isp/isp.c @@ -1748,7 +1748,7 @@ static int isp_register_entities(struct isp_device *isp) goto done; /* Register external entities */ - for (subdevs = pdata->subdevs; subdevs->subdevs; ++subdevs) { + for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) { struct v4l2_subdev *sensor; struct media_entity *input; unsigned int flags; -- cgit v1.2.3 From c064b8eac8da5d494fd221f14219c4f39502deb2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 15 Jun 2011 05:20:34 -0300 Subject: [media] v4l: Don't access media entity after is has been destroyed Entities associated with video device nodes are unregistered in video_unregister_device(). This destroys the entity even though it can still be accessed through open video device nodes. Move the media_device_unregister_entity() call from video_unregister_device() to v4l2_device_release() to ensure that the entity isn't unregistered until the last reference to the video device is released. Also remove the media_entity_get()/put() calls from v4l2-dev.c. Those functions were designed for subdevs, to avoid a parent module from being removed while still accessible through board code. They're not currently needed for video device nodes, and will oops when a hotpluggable device is disconnected during streaming, as media_entity_put() called in v4l2_device_release() tries to access entity->parent->dev->driver which is set to NULL when the device is disconnected. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 39 +++++++-------------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 19d5ae293780..06f14008b346 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -167,6 +167,12 @@ static void v4l2_device_release(struct device *cd) mutex_unlock(&videodev_lock); +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev && + vdev->vfl_type != VFL_TYPE_SUBDEV) + media_device_unregister_entity(&vdev->entity); +#endif + /* Release video_device and perform other cleanups as needed. */ vdev->release(vdev); @@ -389,9 +395,6 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) static int v4l2_open(struct inode *inode, struct file *filp) { struct video_device *vdev; -#if defined(CONFIG_MEDIA_CONTROLLER) - struct media_entity *entity = NULL; -#endif int ret = 0; /* Check if the video device is available */ @@ -405,17 +408,6 @@ static int v4l2_open(struct inode *inode, struct file *filp) /* and increase the device refcount */ video_get(vdev); mutex_unlock(&videodev_lock); -#if defined(CONFIG_MEDIA_CONTROLLER) - if (vdev->v4l2_dev && vdev->v4l2_dev->mdev && - vdev->vfl_type != VFL_TYPE_SUBDEV) { - entity = media_entity_get(&vdev->entity); - if (!entity) { - ret = -EBUSY; - video_put(vdev); - return ret; - } - } -#endif if (vdev->fops->open) { if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { ret = -ERESTARTSYS; @@ -431,14 +423,8 @@ static int v4l2_open(struct inode *inode, struct file *filp) err: /* decrease the refcount in case of an error */ - if (ret) { -#if defined(CONFIG_MEDIA_CONTROLLER) - if (vdev->v4l2_dev && vdev->v4l2_dev->mdev && - vdev->vfl_type != VFL_TYPE_SUBDEV) - media_entity_put(entity); -#endif + if (ret) video_put(vdev); - } return ret; } @@ -455,11 +441,6 @@ static int v4l2_release(struct inode *inode, struct file *filp) if (vdev->lock) mutex_unlock(vdev->lock); } -#if defined(CONFIG_MEDIA_CONTROLLER) - if (vdev->v4l2_dev && vdev->v4l2_dev->mdev && - vdev->vfl_type != VFL_TYPE_SUBDEV) - media_entity_put(&vdev->entity); -#endif /* decrease the refcount unconditionally since the release() return value is ignored. */ video_put(vdev); @@ -754,12 +735,6 @@ void video_unregister_device(struct video_device *vdev) if (!vdev || !video_is_registered(vdev)) return; -#if defined(CONFIG_MEDIA_CONTROLLER) - if (vdev->v4l2_dev && vdev->v4l2_dev->mdev && - vdev->vfl_type != VFL_TYPE_SUBDEV) - media_device_unregister_entity(&vdev->entity); -#endif - mutex_lock(&videodev_lock); /* This must be in a critical section to prevent a race with v4l2_open. * Once this bit has been cleared video_get may never be called again. -- cgit v1.2.3 From a96aa5342d575980e5b572cde88036f3a878ebee Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Jun 2011 18:17:48 -0300 Subject: [media] uvcvideo: Ignore entities for terminals with no supported format If a streaming interface has no supported format, the driver won't create a video device for the associated terminal. Fix an oops by ignoring that terminal when creating links between entities. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_entity.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c index c3ab0c813be2..48fea373c25a 100644 --- a/drivers/media/video/uvc/uvc_entity.c +++ b/drivers/media/video/uvc/uvc_entity.c @@ -27,14 +27,20 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, struct uvc_entity *entity) { const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; - struct uvc_entity *remote; + struct media_entity *sink; unsigned int i; - u8 remote_pad; - int ret = 0; + int ret; + + sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) + ? (entity->vdev ? &entity->vdev->entity : NULL) + : &entity->subdev.entity; + if (sink == NULL) + return 0; for (i = 0; i < entity->num_pads; ++i) { struct media_entity *source; - struct media_entity *sink; + struct uvc_entity *remote; + u8 remote_pad; if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) continue; @@ -43,10 +49,11 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, if (remote == NULL) return -EINVAL; - source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) - ? &remote->vdev->entity : &remote->subdev.entity; - sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) - ? &entity->vdev->entity : &entity->subdev.entity; + source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING) + ? (remote->vdev ? &remote->vdev->entity : NULL) + : &remote->subdev.entity; + if (source == NULL) + continue; remote_pad = remote->num_pads - 1; ret = media_entity_create_link(source, remote_pad, @@ -55,11 +62,10 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, return ret; } - if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) - ret = v4l2_device_register_subdev(&chain->dev->vdev, - &entity->subdev); + if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) + return 0; - return ret; + return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev); } static struct v4l2_subdev_ops uvc_subdev_ops = { @@ -84,9 +90,11 @@ static int uvc_mc_init_entity(struct uvc_entity *entity) ret = media_entity_init(&entity->subdev.entity, entity->num_pads, entity->pads, 0); - } else + } else if (entity->vdev != NULL) { ret = media_entity_init(&entity->vdev->entity, entity->num_pads, entity->pads, 0); + } else + ret = 0; return ret; } -- cgit v1.2.3 From 8ca2c80b170c47eeb55f0c2a0f2b8edf85f35d49 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Tue, 24 May 2011 12:22:03 -0300 Subject: [media] uvcvideo: Remove buffers from the queues when freeing When freeing memory for the video buffers also remove them from the irq & main queues. This fixes an oops when doing the following: open ("/dev/video", ..) VIDIOC_REQBUFS VIDIOC_QBUF VIDIOC_REQBUFS close () As the second VIDIOC_REQBUFS will cause the list entries of the buffers to be cleared while they still hang around on the main and irc queues Signed-off-by: Sjoerd Simons Acked-by: Laurent Pinchart Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_queue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 109a06384a8f..f90ce9fce539 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -104,6 +104,8 @@ static int __uvc_free_buffers(struct uvc_video_queue *queue) } if (queue->count) { + uvc_queue_cancel(queue, 0); + INIT_LIST_HEAD(&queue->mainqueue); vfree(queue->mem); queue->count = 0; } -- cgit v1.2.3 From aa122d424b14b4a4c5ba302e668366717e9cac7b Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Mon, 30 May 2011 15:02:00 -0300 Subject: [media] uvcvideo: Disable the queue when failing to start When failing to start the camera we should disable the queue again, to rollback into the same initial state. Otherwise re-trying will always hit -EBUSY Signed-off-by: Sjoerd Simons Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index fc766b9f24c5..49994793cc77 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -1255,8 +1255,10 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable) /* Commit the streaming parameters. */ ret = uvc_commit_video(stream, &stream->ctrl); - if (ret < 0) + if (ret < 0) { + uvc_queue_enable(&stream->queue, 0); return ret; + } return uvc_init_video(stream, GFP_KERNEL); } -- cgit v1.2.3 From cd62287e364c0d15d517c6ced4e4808b54711475 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Sat, 4 Jun 2011 15:03:20 +0200 Subject: sched, cgroups: Fix MIN_SHARES on 64-bit boxen Commit c8b28116 ("sched: Increase SCHED_LOAD_SCALE resolution") intended to have no user-visible effect, but allows setting cpu.shares to < MIN_SHARES, which the user then sees. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra Cc: Nikhil Rao Link: http://lkml.kernel.org/r/1307192600.8618.3.camel@marge.simson.net Signed-off-by: Ingo Molnar --- kernel/sched.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 3f2e502d609b..9769c756ad66 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -292,8 +292,8 @@ static DEFINE_SPINLOCK(task_group_lock); * (The default weight is 1024 - so there's no practical * limitation from this.) */ -#define MIN_SHARES 2 -#define MAX_SHARES (1UL << (18 + SCHED_LOAD_RESOLUTION)) +#define MIN_SHARES (1UL << 1) +#define MAX_SHARES (1UL << 18) static int root_task_group_load = ROOT_TASK_GROUP_LOAD; #endif @@ -8450,10 +8450,7 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares) if (!tg->se[0]) return -EINVAL; - if (shares < MIN_SHARES) - shares = MIN_SHARES; - else if (shares > MAX_SHARES) - shares = MAX_SHARES; + shares = clamp(shares, scale_load(MIN_SHARES), scale_load(MAX_SHARES)); mutex_lock(&shares_mutex); if (tg->shares == shares) -- cgit v1.2.3 From a26474e8649643e82d71e3a386d5c4bcc0b207ef Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 28 Jun 2011 11:41:07 +0200 Subject: x86-32, NUMA: Fix boot regression caused by NUMA init unification on highmem machines During 32/64 NUMA init unification, commit 797390d855 ("x86-32, NUMA: use sparse_memory_present_with_active_regions()") made 32bit mm init call memory_present() automatically from active_regions instead of leaving it to each NUMA init path. This commit description is inaccurate - memory_present() calls aren't the same for flat and numaq. After the commit, memory_present() is only called for the intersection of e820 and NUMA layout. Before, on flatmem, memory_present() would be called from 0 to max_pfn. After, it would be called only on the areas that e820 indicates to be populated. This is how x86_64 works and should be okay as memmap is allowed to contain holes; however, x86_32 DISCONTIGMEM is missing early_pfn_valid(), which makes memmap_init_zone() assume that memmap doesn't contain any hole. This leads to the following oops if e820 map contains holes as it often does on machine with near or more 4GiB of memory by calling pfn_to_page() on a pfn which isn't mapped to a NUMA node, a reported by Conny Seidel: BUG: unable to handle kernel paging request at 000012b0 IP: [] memmap_init_zone+0x6c/0xf2 *pdpt =3D 0000000000000000 *pde =3D f000eef3f000ee00 Oops: 0000 [#1] SMP last sysfs file: Modules linked in: Pid: 0, comm: swapper Not tainted 2.6.39-rc5-00164-g797390d #1 To Be Filled By O.E.M. To Be Filled By O.E.M./E350M1 EIP: 0060:[] EFLAGS: 00010012 CPU: 0 EIP is at memmap_init_zone+0x6c/0xf2 EAX: 00000000 EBX: 000a8000 ECX: 000a7fff EDX: f2c00b80 ESI: 000a8000 EDI: f2c00800 EBP: c19ffe54 ESP: c19ffe34 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 Process swapper (pid: 0, ti=3Dc19fe000 task=3Dc1a07f60 task.ti=3Dc19fe000) Stack: 00000002 00000000 0023f000 00000000 10000000 00000a00 f2c00000 f2c00b58 c19ffeb0 c1a80f24 000375fe 00000000 f2c00800 00000800 00000100 00000030 c1abb768 0000003c 00000000 00000000 00000004 00207a02 f2c00800 000375fe Call Trace: [] free_area_init_node+0x358/0x385 [] free_area_init_nodes+0x420/0x487 [] paging_init+0x114/0x11b [] setup_arch+0xb37/0xc0a [] start_kernel+0x76/0x316 [] i386_start_kernel+0xa8/0xb0 This patch fixes the bug by defining early_pfn_valid() to be the same as pfn_valid() when DISCONTIGMEM. Reported-bisected-and-tested-by: Conny Seidel Signed-off-by: Tejun Heo Cc: hans.rosenfeld@amd.com Cc: Christoph Lameter Cc: Conny Seidel Link: http://lkml.kernel.org/r/20110628094107.GB3386@htj.dyndns.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mmzone_32.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h index 224e8c5eb307..ffa037f28d39 100644 --- a/arch/x86/include/asm/mmzone_32.h +++ b/arch/x86/include/asm/mmzone_32.h @@ -57,6 +57,8 @@ static inline int pfn_valid(int pfn) return 0; } +#define early_pfn_valid(pfn) pfn_valid((pfn)) + #endif /* CONFIG_DISCONTIGMEM */ #ifdef CONFIG_NEED_MULTIPLE_NODES -- cgit v1.2.3 From ee1b3ea9e6171d7a842527a44873f9f51e6f239b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 21 Jun 2011 07:18:26 -0400 Subject: cifs: set socket send and receive timeouts before attempting connect Benjamin S. reported that he was unable to suspend his machine while it had a cifs share mounted. The freezer caused this to spew when he tried it: -----------------------[snip]------------------ PM: Syncing filesystems ... done. Freezing user space processes ... (elapsed 0.01 seconds) done. Freezing remaining freezable tasks ... Freezing of tasks failed after 20.01 seconds (1 tasks refusing to freeze, wq_busy=0): cifsd S ffff880127f7b1b0 0 1821 2 0x00800000 ffff880127f7b1b0 0000000000000046 ffff88005fe008a8 ffff8800ffffffff ffff880127cee6b0 0000000000011100 ffff880127737fd8 0000000000004000 ffff880127737fd8 0000000000011100 ffff880127f7b1b0 ffff880127736010 Call Trace: [] ? sk_reset_timer+0xf/0x19 [] ? tcp_connect+0x43c/0x445 [] ? tcp_v4_connect+0x40d/0x47f [] ? schedule_timeout+0x21/0x1ad [] ? _raw_spin_lock_bh+0x9/0x1f [] ? release_sock+0x19/0xef [] ? inet_stream_connect+0x14c/0x24a [] ? autoremove_wake_function+0x0/0x2a [] ? ipv4_connect+0x39c/0x3b5 [cifs] [] ? cifs_reconnect+0x1fc/0x28a [cifs] [] ? cifs_demultiplex_thread+0x397/0xb9f [cifs] [] ? perf_event_exit_task+0xb9/0x1bf [] ? cifs_demultiplex_thread+0x0/0xb9f [cifs] [] ? cifs_demultiplex_thread+0x0/0xb9f [cifs] [] ? kthread+0x7a/0x82 [] ? kernel_thread_helper+0x4/0x10 [] ? kthread+0x0/0x82 [] ? kernel_thread_helper+0x0/0x10 Restarting tasks ... done. -----------------------[snip]------------------ We do attempt to perform a try_to_freeze in cifs_reconnect, but the connection attempt itself seems to be taking longer than 20s to time out. The connect timeout is governed by the socket send and receive timeouts, so we can shorten that period by setting those timeouts before attempting the connect instead of after. Adam Williamson tested the patch and said that it seems to have fixed suspending on his laptop when a cifs share is mounted. Reported-by: Benjamin S Tested-by: Adam Williamson Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 7f540df52527..c8cb83ef6f6f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2474,14 +2474,6 @@ generic_ip_connect(struct TCP_Server_Info *server) if (rc < 0) return rc; - rc = socket->ops->connect(socket, saddr, slen, 0); - if (rc < 0) { - cFYI(1, "Error %d connecting to server", rc); - sock_release(socket); - server->ssocket = NULL; - return rc; - } - /* * Eventually check for other socket options to change from * the default. sock_setsockopt not used because it expects @@ -2510,6 +2502,14 @@ generic_ip_connect(struct TCP_Server_Info *server) socket->sk->sk_sndbuf, socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); + rc = socket->ops->connect(socket, saddr, slen, 0); + if (rc < 0) { + cFYI(1, "Error %d connecting to server", rc); + sock_release(socket); + server->ssocket = NULL; + return rc; + } + if (sport == htons(RFC1001_PORT)) rc = ip_rfc1001_connect(server); -- cgit v1.2.3 From e8bb10b82f3d9fff79751ee392c1c499e3d68365 Mon Sep 17 00:00:00 2001 From: Vladimir Pantelic Date: Tue, 26 Apr 2011 04:28:11 -0300 Subject: [media] OMAP_VOUTLIB: Fix wrong resizer calculation The omap_vout_new_crop() function has possible bug, uses uninitialized variable "crop.width/height" which is actually output of the function. Instead we should be using "try_crop.width/height" to calculate the resizer value. Signed-off-by: Vladimir Pantelic Signed-off-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap/omap_voutlib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c index 2aa6a76c5e59..8ae74817a110 100644 --- a/drivers/media/video/omap/omap_voutlib.c +++ b/drivers/media/video/omap/omap_voutlib.c @@ -193,7 +193,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix, return -EINVAL; if (cpu_is_omap24xx()) { - if (crop->height != win->w.height) { + if (try_crop.height != win->w.height) { /* If we're resizing vertically, we can't support a * crop width wider than 768 pixels. */ @@ -202,7 +202,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix, } } /* vertical resizing */ - vresize = (1024 * crop->height) / win->w.height; + vresize = (1024 * try_crop.height) / win->w.height; if (cpu_is_omap24xx() && (vresize > 2048)) vresize = 2048; else if (cpu_is_omap34xx() && (vresize > 4096)) @@ -221,7 +221,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix, try_crop.height = 2; } /* horizontal resizing */ - hresize = (1024 * crop->width) / win->w.width; + hresize = (1024 * try_crop.width) / win->w.width; if (cpu_is_omap24xx() && (hresize > 2048)) hresize = 2048; else if (cpu_is_omap34xx() && (hresize > 4096)) -- cgit v1.2.3 From 8f3a307b9afd8c2ebde46ef317df4df3813301a7 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 16 Jun 2011 15:32:07 -0300 Subject: [media] OMAP_VOUT: Change hardcoded device node number to -1 With addition of media-controller framework, now we have various device nodes (/dev/videoX) getting created, so hardcoding minor number in video_register_device() is not recommended. So let V4L2 framework choose free minor number for the device. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap/omap_vout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 4ada9be1d430..eb16607358d0 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -2391,7 +2391,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev) /* Register the Video device with V4L2 */ vfd = vout->vfd; - if (video_register_device(vfd, VFL_TYPE_GRABBER, k + 1) < 0) { + if (video_register_device(vfd, VFL_TYPE_GRABBER, -1) < 0) { dev_err(&pdev->dev, ": Could not register " "Video for Linux device\n"); vfd->minor = -1; -- cgit v1.2.3 From 383e4f69879d11c86ebdd38b3356f6d0690fb4cc Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 14 Apr 2011 13:42:34 -0300 Subject: [media] omap_vout: Added check in reqbuf & mmap for buf_size allocation The usecase where, user allocates small size of buffer through bootargs (video1_bufsize/video2_bufsize) and later from application tries to set the format which requires larger buffer size, driver doesn't check for insufficient buffer size and allows application to map extra buffer. This leads to kernel crash, when user application tries to access memory beyond the allocation size. Added check in both mmap and reqbuf call back function, and return error if the size of the buffer allocated by user through bootargs is less than the S_FMT size. Signed-off-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap/omap_vout.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index eb16607358d0..4d07c5844402 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -982,6 +982,14 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, startindex = (vout->vid == OMAP_VIDEO1) ? video1_numbuffers : video2_numbuffers; + /* Check the size of the buffer */ + if (*size > vout->buffer_size) { + v4l2_err(&vout->vid_dev->v4l2_dev, + "buffer allocation mismatch [%u] [%u]\n", + *size, vout->buffer_size); + return -ENOMEM; + } + for (i = startindex; i < *count; i++) { vout->buffer_size = *size; @@ -1228,6 +1236,14 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma) (vma->vm_pgoff << PAGE_SHIFT)); return -EINVAL; } + /* Check the size of the buffer */ + if (size > vout->buffer_size) { + v4l2_err(&vout->vid_dev->v4l2_dev, + "insufficient memory [%lu] [%u]\n", + size, vout->buffer_size); + return -ENOMEM; + } + q->bufs[i]->baddr = vma->vm_start; vma->vm_flags |= VM_RESERVED; -- cgit v1.2.3 From 258c05637d6b6df2478a2808a3d2350c3c6782d6 Mon Sep 17 00:00:00 2001 From: Andre Bartke Date: Fri, 10 Jun 2011 07:57:54 -0300 Subject: [media] V4L: mx1-camera: fix uninitialized variable mx1_camera_add_device() can return an uninitialized value of ret. Signed-off-by: Andre Bartke [g.liakhovetski@gmx.de: modified the fix to remove "ret" completely] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mx1_camera.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index bc0c23a1009c..63f8a0cc33d8 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -444,12 +444,9 @@ static int mx1_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx1_camera_dev *pcdev = ici->priv; - int ret; - if (pcdev->icd) { - ret = -EBUSY; - goto ebusy; - } + if (pcdev->icd) + return -EBUSY; dev_info(icd->dev.parent, "MX1 Camera driver attached to camera %d\n", icd->devnum); @@ -458,8 +455,7 @@ static int mx1_camera_add_device(struct soc_camera_device *icd) pcdev->icd = icd; -ebusy: - return ret; + return 0; } static void mx1_camera_remove_device(struct soc_camera_device *icd) -- cgit v1.2.3 From 35d136c8dab034ee14aa00d6082229b4b74607da Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 7 Jun 2011 18:45:17 -0300 Subject: [media] ite-cir: 8709 needs to use pnp resource 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to the intrepid testing and debugging of Matthijs van Drunen, it was uncovered that at least some variants of the ITE8709 need to use pnp resource 2, rather than 0, for things to function properly. Resource 0 has a length of only 1, and if you try to bypass the pnp_port_len check and use it anyway (with either a length of 1 or 2), the system in question's trackpad ceased to function. The circa lirc 0.8.7 lirc_ite8709 driver used resource 2, but the value was (amusingly) changed to 0 by way of a patch from ITE themselves, so I don't know if there may be variants where 0 actually *is* correct, but at least in this case and in the original lirc_ite8709 driver author's case, it sure looks like 2 is the right value. This fix should probably be applied to all stable kernels with the ite-cir driver, lest we nuke more people's trackpads. Tested-by: Matthijs van Drunen CC: Juan Jesús García de Soria CC: stable@kernel.org Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ite-cir.c | 12 +++++++++--- drivers/media/rc/ite-cir.h | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index e716b931cf7e..ecd3d0280768 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1347,6 +1347,7 @@ static const struct ite_dev_params ite_dev_descs[] = { { /* 0: ITE8704 */ .model = "ITE8704 CIR transceiver", .io_region_size = IT87_IOREG_LENGTH, + .io_rsrc_no = 0, .hw_tx_capable = true, .sample_period = (u32) (1000000000ULL / 115200), .tx_carrier_freq = 38000, @@ -1371,6 +1372,7 @@ static const struct ite_dev_params ite_dev_descs[] = { { /* 1: ITE8713 */ .model = "ITE8713 CIR transceiver", .io_region_size = IT87_IOREG_LENGTH, + .io_rsrc_no = 0, .hw_tx_capable = true, .sample_period = (u32) (1000000000ULL / 115200), .tx_carrier_freq = 38000, @@ -1395,6 +1397,7 @@ static const struct ite_dev_params ite_dev_descs[] = { { /* 2: ITE8708 */ .model = "ITE8708 CIR transceiver", .io_region_size = IT8708_IOREG_LENGTH, + .io_rsrc_no = 0, .hw_tx_capable = true, .sample_period = (u32) (1000000000ULL / 115200), .tx_carrier_freq = 38000, @@ -1420,6 +1423,7 @@ static const struct ite_dev_params ite_dev_descs[] = { { /* 3: ITE8709 */ .model = "ITE8709 CIR transceiver", .io_region_size = IT8709_IOREG_LENGTH, + .io_rsrc_no = 2, .hw_tx_capable = true, .sample_period = (u32) (1000000000ULL / 115200), .tx_carrier_freq = 38000, @@ -1461,6 +1465,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id struct rc_dev *rdev = NULL; int ret = -ENOMEM; int model_no; + int io_rsrc_no; ite_dbg("%s called", __func__); @@ -1490,10 +1495,11 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id /* get the description for the device */ dev_desc = &ite_dev_descs[model_no]; + io_rsrc_no = dev_desc->io_rsrc_no; /* validate pnp resources */ - if (!pnp_port_valid(pdev, 0) || - pnp_port_len(pdev, 0) != dev_desc->io_region_size) { + if (!pnp_port_valid(pdev, io_rsrc_no) || + pnp_port_len(pdev, io_rsrc_no) != dev_desc->io_region_size) { dev_err(&pdev->dev, "IR PNP Port not valid!\n"); goto failure; } @@ -1504,7 +1510,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id } /* store resource values */ - itdev->cir_addr = pnp_port_start(pdev, 0); + itdev->cir_addr = pnp_port_start(pdev, io_rsrc_no); itdev->cir_irq = pnp_irq(pdev, 0); /* initialize spinlocks */ diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h index 16a19f5fd718..aa899a0b9750 100644 --- a/drivers/media/rc/ite-cir.h +++ b/drivers/media/rc/ite-cir.h @@ -57,6 +57,9 @@ struct ite_dev_params { /* size of the I/O region */ int io_region_size; + /* IR pnp I/O resource number */ + int io_rsrc_no; + /* true if the hardware supports transmission */ bool hw_tx_capable; -- cgit v1.2.3 From 1ba9268c2bfeebfd70193145685e12faeae92882 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Wed, 8 Jun 2011 15:00:01 -0300 Subject: [media] keymaps: fix table for pinnacle pctv hd devices Both consumers of RC_MAP_PINNACLE_PCTV_HD send along full RC-5 scancodes, so this update makes this keymap actually *have* full scancodes, heisted from rc-dib0700-rc5.c. This should fix out of the box remote functionality for the Pinnacle PCTV HD 800i (cx88 pci card) and PCTV HD Pro 801e (em28xx usb stick). CC: stable@kernel.org Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c | 58 ++++++++++++-------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c index bb10ffe086b4..8d558ae63456 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c @@ -15,43 +15,39 @@ /* Pinnacle PCTV HD 800i mini remote */ static struct rc_map_table pinnacle_pctv_hd[] = { - - { 0x0f, KEY_1 }, - { 0x15, KEY_2 }, - { 0x10, KEY_3 }, - { 0x18, KEY_4 }, - { 0x1b, KEY_5 }, - { 0x1e, KEY_6 }, - { 0x11, KEY_7 }, - { 0x21, KEY_8 }, - { 0x12, KEY_9 }, - { 0x27, KEY_0 }, - - { 0x24, KEY_ZOOM }, - { 0x2a, KEY_SUBTITLE }, - - { 0x00, KEY_MUTE }, - { 0x01, KEY_ENTER }, /* Pinnacle Logo */ - { 0x39, KEY_POWER }, - - { 0x03, KEY_VOLUMEUP }, - { 0x09, KEY_VOLUMEDOWN }, - { 0x06, KEY_CHANNELUP }, - { 0x0c, KEY_CHANNELDOWN }, - - { 0x2d, KEY_REWIND }, - { 0x30, KEY_PLAYPAUSE }, - { 0x33, KEY_FASTFORWARD }, - { 0x3c, KEY_STOP }, - { 0x36, KEY_RECORD }, - { 0x3f, KEY_EPG }, /* Labeled "?" */ + /* Key codes for the tiny Pinnacle remote*/ + { 0x0700, KEY_MUTE }, + { 0x0701, KEY_MENU }, /* Pinnacle logo */ + { 0x0739, KEY_POWER }, + { 0x0703, KEY_VOLUMEUP }, + { 0x0709, KEY_VOLUMEDOWN }, + { 0x0706, KEY_CHANNELUP }, + { 0x070c, KEY_CHANNELDOWN }, + { 0x070f, KEY_1 }, + { 0x0715, KEY_2 }, + { 0x0710, KEY_3 }, + { 0x0718, KEY_4 }, + { 0x071b, KEY_5 }, + { 0x071e, KEY_6 }, + { 0x0711, KEY_7 }, + { 0x0721, KEY_8 }, + { 0x0712, KEY_9 }, + { 0x0727, KEY_0 }, + { 0x0724, KEY_ZOOM }, /* 'Square' key */ + { 0x072a, KEY_SUBTITLE }, /* 'T' key */ + { 0x072d, KEY_REWIND }, + { 0x0730, KEY_PLAYPAUSE }, + { 0x0733, KEY_FASTFORWARD }, + { 0x0736, KEY_RECORD }, + { 0x073c, KEY_STOP }, + { 0x073f, KEY_HELP }, /* '?' key */ }; static struct rc_map_list pinnacle_pctv_hd_map = { .map = { .scan = pinnacle_pctv_hd, .size = ARRAY_SIZE(pinnacle_pctv_hd), - .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_RC5, .name = RC_MAP_PINNACLE_PCTV_HD, } }; -- cgit v1.2.3 From 6a8c97ac92461ec57e36b10572e78d4221e8faa8 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Wed, 8 Jun 2011 18:56:56 -0300 Subject: [media] lirc_zilog: fix spinning rx thread We were calling schedule_timeout with the rx thread's task state still at TASK_RUNNING, which it shouldn't be. Make sure we call set_current_state(TASK_INTERRUPTIBLE) *before* schedule_timeout, and we're all good here. I believe this problem was mistakenly introduced in commit 5bd6b0464b68d429bc8a3fe6595d19c39dfc4d95, and I'm not sure how I missed it before, as I swear I tested the patchset that was included in, but alas, stuff happens... Acked-by: Andy Walls CC: stable@kernel.org Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/lirc/lirc_zilog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c index dd6a57c3c3a3..4e051f6b52db 100644 --- a/drivers/staging/lirc/lirc_zilog.c +++ b/drivers/staging/lirc/lirc_zilog.c @@ -475,14 +475,14 @@ static int lirc_thread(void *arg) dprintk("poll thread started\n"); while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + /* if device not opened, we can sleep half a second */ if (atomic_read(&ir->open_count) == 0) { schedule_timeout(HZ/2); continue; } - set_current_state(TASK_INTERRUPTIBLE); - /* * This is ~113*2 + 24 + jitter (2*repeat gap + code length). * We use this interval as the chip resets every time you poll -- cgit v1.2.3 From c4b0afee3c1730cf9b0f6ad21729928d23d3918e Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 13 Jun 2011 15:32:26 -0300 Subject: [media] [staging] lirc_serial: allocate irq at init time There's really no good reason not to just grab the desired IRQ at driver init time, instead of every time the lirc device node is accessed. This also improves the speed and reliability with which a serial transmitter can operate, as back-to-back transmission attempts (i.e., channel change to a multi-digit channel) don't have to spend time acquiring and then releasing the IRQ for every digit, sometimes multiple times, if lircd has been told to use the min_repeat parameter. CC: devel@driverdev.osuosl.org Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/lirc/lirc_serial.c | 44 ++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c index 4a3cca03224a..805df913bb6e 100644 --- a/drivers/staging/lirc/lirc_serial.c +++ b/drivers/staging/lirc/lirc_serial.c @@ -838,7 +838,23 @@ static int hardware_init_port(void) static int init_port(void) { - int i, nlow, nhigh; + int i, nlow, nhigh, result; + + result = request_irq(irq, irq_handler, + IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0), + LIRC_DRIVER_NAME, (void *)&hardware); + + switch (result) { + case -EBUSY: + printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); + return -EBUSY; + case -EINVAL: + printk(KERN_ERR LIRC_DRIVER_NAME + ": Bad irq number or handler\n"); + return -EINVAL; + default: + break; + }; /* Reserve io region. */ /* @@ -893,34 +909,17 @@ static int init_port(void) printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " "%s receiver\n", sense ? "low" : "high"); + dprintk("Interrupt %d, port %04x obtained\n", irq, io); return 0; } static int set_use_inc(void *data) { - int result; unsigned long flags; /* initialize timestamp */ do_gettimeofday(&lasttv); - result = request_irq(irq, irq_handler, - IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0), - LIRC_DRIVER_NAME, (void *)&hardware); - - switch (result) { - case -EBUSY: - printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); - return -EBUSY; - case -EINVAL: - printk(KERN_ERR LIRC_DRIVER_NAME - ": Bad irq number or handler\n"); - return -EINVAL; - default: - dprintk("Interrupt %d, port %04x obtained\n", irq, io); - break; - } - spin_lock_irqsave(&hardware[type].lock, flags); /* Set DLAB 0. */ @@ -945,10 +944,6 @@ static void set_use_dec(void *data) soutp(UART_IER, sinp(UART_IER) & (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); spin_unlock_irqrestore(&hardware[type].lock, flags); - - free_irq(irq, (void *)&hardware); - - dprintk("freed IRQ %d\n", irq); } static ssize_t lirc_write(struct file *file, const char *buf, @@ -1256,6 +1251,9 @@ exit_serial_exit: static void __exit lirc_serial_exit_module(void) { lirc_serial_exit(); + + free_irq(irq, (void *)&hardware); + if (iommap != 0) release_mem_region(iommap, 8 << ioshift); else -- cgit v1.2.3 From 3f5c4c73322e4d6f3d40b697dac3073d2adffe41 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 16 Jun 2011 16:18:37 -0300 Subject: [media] rc: fix ghost keypresses with certain hw With hardware that has to use ir_raw_event_store_edge to collect IR sample durations, we were not doing an event reset unless IR_MAX_DURATION had passed. That's around 4 seconds. So if someone presses up, then down, with less than 4 seconds in between, they'd get the initial up, then up and down upon pressing down. To fix this, I've lowered the "send a reset event" logic's threshold to the input device's REP_DELAY (defaults to 500ms), and with an saa7134-based GPIO-driven IR receiver in a Hauppauge HVR-1150, I get *much* better behavior out of the remote now. Special thanks to Devin for providing the hardware to investigate this issue. CC: stable@kernel.org CC: Devin Heitmueller Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-raw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 11c19d8d0ee0..423ed45d6c55 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -114,18 +114,20 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) s64 delta; /* ns */ DEFINE_IR_RAW_EVENT(ev); int rc = 0; + int delay; if (!dev->raw) return -EINVAL; now = ktime_get(); delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event)); + delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]); /* Check for a long duration since last event or if we're * being called for the first time, note that delta can't * possibly be negative. */ - if (delta > IR_MAX_DURATION || !dev->raw->last_type) + if (delta > delay || !dev->raw->last_type) type |= IR_START_EVENT; else ev.duration = delta; -- cgit v1.2.3 From 9800b5b619cd9a013a6f0c7d5da0dbbc17a5af30 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 16 Jun 2011 17:30:48 -0300 Subject: [media] saa7134: fix raw IR timeout value The comment says "wait 15ms", but the code says jiffies_to_msecs(15) instead of msecs_to_jiffies(15). Fix that. Tested, works fine with both rc5 and rc6 decode, in-kernel and via lirc userspace, with an HVR-1150. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ff6c0e97563e..d4ee24bf6928 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -963,7 +963,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) * to work with other protocols. */ if (!ir->active) { - timeout = jiffies + jiffies_to_msecs(15); + timeout = jiffies + msecs_to_jiffies(15); mod_timer(&ir->timer, timeout); ir->active = true; } -- cgit v1.2.3 From 842071c9ea021a42256386cb0cbe3735af33c4db Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 20 Jun 2011 00:04:05 -0300 Subject: [media] imon: auto-config ffdc 7e device Another device with the 0xffdc device id, this one with 0x7e in the config byte. Its an iMON VFD + RC6 IR, in a CoolerMaster 260 case. Reported-by: Filip Streibl Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/imon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 7136582a8573..ba480325851b 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1751,6 +1751,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx) break; /* iMON VFD, MCE IR */ case 0x46: + case 0x7e: case 0x9e: dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR"); detected_display_type = IMON_DISPLAY_TYPE_VFD; -- cgit v1.2.3 From 372b4249243d1e7c12a0f2b67e7badc608fcff45 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 20 Jun 2011 00:07:13 -0300 Subject: [media] imon: allow either proto on unknown 0xffdc While 0xffdc devices have their IR protocol hard-coded into the firmware of the device, we have no known way of telling what it is if we don't have the device's config byte already in the driver. Unknown devices default to the imon native protocol, but might actually be rc6, so we should set the driver up such that the user can load the rc6 keytable from userspace and still have a working device ahead of its config byte being added to the driver. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/imon.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index ba480325851b..6bc35eeb653b 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1767,6 +1767,9 @@ static void imon_get_ffdc_type(struct imon_context *ictx) dev_info(ictx->dev, "Unknown 0xffdc device, " "defaulting to VFD and iMON IR"); detected_display_type = IMON_DISPLAY_TYPE_VFD; + /* We don't know which one it is, allow user to set the + * RC6 one from userspace if OTHER wasn't correct. */ + allowed_protos |= RC_TYPE_RC6; break; } -- cgit v1.2.3 From 98c32bcded0e249fd48726930ae9f393e0e318b4 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 23 Jun 2011 10:40:55 -0300 Subject: [media] rc: call input_sync after scancode reports Due to commit cdda911c34006f1089f3c87b1a1f31ab3a4722f2, evdev only becomes readable when the buffer contains an EV_SYN/SYN_REPORT event. If we get a repeat or a scancode we don't have a mapping for, we never call input_sync, and thus those events don't get reported in a timely fashion. For example, take an mceusb transceiver with a default rc6 keymap. Press buttons on an rc5 remote while monitoring with ir-keytable, and you'll see nothing. Now press a button on the rc6 remote matching the keymap. You'll suddenly get the rc5 key scancodes, the rc6 scancode and the rc6 key spit out all at the same time. Pressing and holding a button on a remote we do have a keymap for also works rather unreliably right now, due to repeat events also happening without a call to input_sync (we bail from ir_do_keydown before getting to the point where it calls input_sync). Easy fix though, just add two strategically placed input_sync calls right after our input_event calls for EV_MSC, and all is well again. Technically, we probably should have been doing this all along, its just that it never caused any functional difference until the referenced change went into the input layer. input_sync once per IR signal. There was another hidden bug in the code where we were calling input_report_key using last_keycode instead of our just discovered keycode, which manifested with the reordering of calling input_report_key and setting last_keycode. Reported-by: Stephan Raue CC: Stephan Raue CC: Mauro Carvalho Chehab CC: Jeff Brown Acked-by: Dmitry Torokhov Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-main.c | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index f57cd5677ac2..3186ac7c2c10 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -522,18 +522,20 @@ EXPORT_SYMBOL_GPL(rc_g_keycode_from_table); /** * ir_do_keyup() - internal function to signal the release of a keypress * @dev: the struct rc_dev descriptor of the device + * @sync: whether or not to call input_sync * * This function is used internally to release a keypress, it must be * called with keylock held. */ -static void ir_do_keyup(struct rc_dev *dev) +static void ir_do_keyup(struct rc_dev *dev, bool sync) { if (!dev->keypressed) return; IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode); input_report_key(dev->input_dev, dev->last_keycode, 0); - input_sync(dev->input_dev); + if (sync) + input_sync(dev->input_dev); dev->keypressed = false; } @@ -549,7 +551,7 @@ void rc_keyup(struct rc_dev *dev) unsigned long flags; spin_lock_irqsave(&dev->keylock, flags); - ir_do_keyup(dev); + ir_do_keyup(dev, true); spin_unlock_irqrestore(&dev->keylock, flags); } EXPORT_SYMBOL_GPL(rc_keyup); @@ -578,7 +580,7 @@ static void ir_timer_keyup(unsigned long cookie) */ spin_lock_irqsave(&dev->keylock, flags); if (time_is_before_eq_jiffies(dev->keyup_jiffies)) - ir_do_keyup(dev); + ir_do_keyup(dev, true); spin_unlock_irqrestore(&dev->keylock, flags); } @@ -597,6 +599,7 @@ void rc_repeat(struct rc_dev *dev) spin_lock_irqsave(&dev->keylock, flags); input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode); + input_sync(dev->input_dev); if (!dev->keypressed) goto out; @@ -622,29 +625,28 @@ EXPORT_SYMBOL_GPL(rc_repeat); static void ir_do_keydown(struct rc_dev *dev, int scancode, u32 keycode, u8 toggle) { - input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); - - /* Repeat event? */ - if (dev->keypressed && - dev->last_scancode == scancode && - dev->last_toggle == toggle) - return; + bool new_event = !dev->keypressed || + dev->last_scancode != scancode || + dev->last_toggle != toggle; - /* Release old keypress */ - ir_do_keyup(dev); + if (new_event && dev->keypressed) + ir_do_keyup(dev, false); - dev->last_scancode = scancode; - dev->last_toggle = toggle; - dev->last_keycode = keycode; + input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); - if (keycode == KEY_RESERVED) - return; + if (new_event && keycode != KEY_RESERVED) { + /* Register a keypress */ + dev->keypressed = true; + dev->last_scancode = scancode; + dev->last_toggle = toggle; + dev->last_keycode = keycode; + + IR_dprintk(1, "%s: key down event, " + "key 0x%04x, scancode 0x%04x\n", + dev->input_name, keycode, scancode); + input_report_key(dev->input_dev, keycode, 1); + } - /* Register a keypress */ - dev->keypressed = true; - IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", - dev->input_name, keycode, scancode); - input_report_key(dev->input_dev, dev->last_keycode, 1); input_sync(dev->input_dev); } -- cgit v1.2.3 From 0466dcbeda72e6a2753cd7e81f0a190054bd2233 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 1 Jul 2011 12:46:56 +0200 Subject: Update version number references in README When 3.0 is released I believe the README should reflect the new numbering. Signed-off-by: Jesper Juhl Signed-off-by: Linus Torvalds --- README | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README b/README index 8510017a3576..0d5a7ddbe3ee 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ - Linux kernel release 2.6.xx + Linux kernel release 3.x -These are the release notes for Linux version 2.6. Read them carefully, +These are the release notes for Linux version 3. Read them carefully, as they tell you what this is all about, explain how to install the kernel, and what to do if something goes wrong. @@ -62,10 +62,10 @@ INSTALLING the kernel source: directory where you have permissions (eg. your home directory) and unpack it: - gzip -cd linux-2.6.XX.tar.gz | tar xvf - + gzip -cd linux-3.X.tar.gz | tar xvf - or - bzip2 -dc linux-2.6.XX.tar.bz2 | tar xvf - + bzip2 -dc linux-3.X.tar.bz2 | tar xvf - Replace "XX" with the version number of the latest kernel. @@ -75,15 +75,15 @@ INSTALLING the kernel source: files. They should match the library, and not get messed up by whatever the kernel-du-jour happens to be. - - You can also upgrade between 2.6.xx releases by patching. Patches are + - You can also upgrade between 3.x releases by patching. Patches are distributed in the traditional gzip and the newer bzip2 format. To install by patching, get all the newer patch files, enter the - top level directory of the kernel source (linux-2.6.xx) and execute: + top level directory of the kernel source (linux-3.x) and execute: - gzip -cd ../patch-2.6.xx.gz | patch -p1 + gzip -cd ../patch-3.x.gz | patch -p1 or - bzip2 -dc ../patch-2.6.xx.bz2 | patch -p1 + bzip2 -dc ../patch-3.x.bz2 | patch -p1 (repeat xx for all versions bigger than the version of your current source tree, _in_order_) and you should be ok. You may want to remove @@ -91,9 +91,9 @@ INSTALLING the kernel source: failed patches (xxx# or xxx.rej). If there are, either you or me has made a mistake. - Unlike patches for the 2.6.x kernels, patches for the 2.6.x.y kernels + Unlike patches for the 3.x kernels, patches for the 3.x.y kernels (also known as the -stable kernels) are not incremental but instead apply - directly to the base 2.6.x kernel. Please read + directly to the base 3.x kernel. Please read Documentation/applying-patches.txt for more information. Alternatively, the script patch-kernel can be used to automate this @@ -107,14 +107,14 @@ INSTALLING the kernel source: an alternative directory can be specified as the second argument. - If you are upgrading between releases using the stable series patches - (for example, patch-2.6.xx.y), note that these "dot-releases" are - not incremental and must be applied to the 2.6.xx base tree. For - example, if your base kernel is 2.6.12 and you want to apply the - 2.6.12.3 patch, you do not and indeed must not first apply the - 2.6.12.1 and 2.6.12.2 patches. Similarly, if you are running kernel - version 2.6.12.2 and want to jump to 2.6.12.3, you must first - reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying - the 2.6.12.3 patch. + (for example, patch-3.x.y), note that these "dot-releases" are + not incremental and must be applied to the 3.x base tree. For + example, if your base kernel is 3.0 and you want to apply the + 3.0.3 patch, you do not and indeed must not first apply the + 3.0.1 and 3.0.2 patches. Similarly, if you are running kernel + version 3.0.2 and want to jump to 3.0.3, you must first + reverse the 3.0.2 patch (that is, patch -R) _before_ applying + the 3.0.3 patch. You can read more on this in Documentation/applying-patches.txt - Make sure you have no stale .o files and dependencies lying around: @@ -126,7 +126,7 @@ INSTALLING the kernel source: SOFTWARE REQUIREMENTS - Compiling and running the 2.6.xx kernels requires up-to-date + Compiling and running the 3.x kernels requires up-to-date versions of various software packages. Consult Documentation/Changes for the minimum version numbers required and how to get updates for these packages. Beware that using @@ -142,11 +142,11 @@ BUILD directory for the kernel: Using the option "make O=output/dir" allow you to specify an alternate place for the output files (including .config). Example: - kernel source code: /usr/src/linux-2.6.N + kernel source code: /usr/src/linux-3.N build directory: /home/name/build/kernel To configure and build the kernel use: - cd /usr/src/linux-2.6.N + cd /usr/src/linux-3.N make O=/home/name/build/kernel menuconfig make O=/home/name/build/kernel sudo make O=/home/name/build/kernel modules_install install -- cgit v1.2.3 From 2b1ecb7337592a7bf0989efac46a5b52daab769e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 1 Jul 2011 11:08:56 -0700 Subject: drm/i915: apply HWSTAM writes to Ivy Bridge as well In an attempt to fix 38862 and 38863. Signed-off-by: Jesse Barnes Tested-by: Kenneth Graunke Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 226d8b296e69..3b03f85ea627 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1740,7 +1740,7 @@ static void ironlake_irq_preinstall(struct drm_device *dev) INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); I915_WRITE(HWSTAM, 0xeffe); - if (IS_GEN6(dev)) { + if (IS_GEN6(dev) || IS_GEN7(dev)) { /* Workaround stalls observed on Sandy Bridge GPUs by * making the blitter command streamer generate a * write to the Hardware Status Page for -- cgit v1.2.3 From 8208441be21eb3df448e171c4e5cf92756f287da Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 1 Jul 2011 13:18:28 -0400 Subject: drm/radeon/kms: use correct reg on fusion when reading back mem config Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 12d2fdc52414..e8a5ffb0124d 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2248,7 +2248,10 @@ int evergreen_mc_init(struct radeon_device *rdev) /* Get VRAM informations */ rdev->mc.vram_is_ddr = true; - tmp = RREG32(MC_ARB_RAMCFG); + if (rdev->flags & RADEON_IS_IGP) + tmp = RREG32(FUS_MC_ARB_RAMCFG); + else + tmp = RREG32(MC_ARB_RAMCFG); if (tmp & CHANSIZE_OVERRIDE) { chansize = 16; } else if (tmp & CHANSIZE_MASK) { -- cgit v1.2.3 From 2498c41e1b6aaa1929d13cae9ff1cb6226887078 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 1 Jul 2011 12:58:54 -0400 Subject: drm/radeon/kms: fix typo in cayman reg offset Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/nid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 9736746da2d6..4672869cdb26 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -320,7 +320,7 @@ #define CGTS_USER_TCC_DISABLE 0x914C #define TCC_DISABLE_MASK 0xFFFF0000 #define TCC_DISABLE_SHIFT 16 -#define CGTS_SM_CTRL_REG 0x915C +#define CGTS_SM_CTRL_REG 0x9150 #define OVERRIDE (1 << 21) #define TA_CNTL_AUX 0x9508 -- cgit v1.2.3 From 6002525170df5f72c92ab946b6ebf1656aaec74d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 1 Jul 2011 18:00:51 +1000 Subject: Revert "drm/nvc0: recognise 0xdX chipsets as NV_C0" Oh boy. That was a bad gamble. PDISP has changed. This reverts commit cdf81a235f11c8a55023c6b181d21d519a8a5967. Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_state.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 144f79a350ae..731acea865b5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -371,7 +371,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->vram.flags_valid = nv50_vram_flags_valid; break; case 0xC0: - case 0xD0: engine->instmem.init = nvc0_instmem_init; engine->instmem.takedown = nvc0_instmem_takedown; engine->instmem.suspend = nvc0_instmem_suspend; @@ -923,7 +922,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev_priv->card_type = NV_50; break; case 0xc0: - case 0xd0: dev_priv->card_type = NV_C0; break; default: -- cgit v1.2.3 From 3140d5b2664309253ba465a14c89fe4f59c0359b Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Sat, 25 Jun 2011 23:37:29 +0200 Subject: USB: fsl_udc_core: fix build breakage when building for ARM arch Commit 09ba0def (USB: fsl_udc_core: prepare for SoCs with BE registers and descriptors) introduced build breakage on ARM arch. Fix it by setting accessors using a static inline function which is a nop when compiling the driver for ARM arch. Commit 2ea6698 (USB: fsl_udc_core: support device mode of MPC5121E DR USB Controller) caused another breakage on ARM by using flush_dcache_range(). Don't use it, convert to the DMA API usage instead. USB2.0CV Halt Endpoint Test succeeds on PPC. Tested both on ARM i.MX31 and mpc5121 PPC, also with CONFIG_DMA_API_DEBUG enabled. Signed-off-by: Anatolij Gustschin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_udc_core.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 2cd9a60c7f3a..4e4833168087 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -46,7 +46,6 @@ #include #include #include -#include #include "fsl_usb2_udc.h" @@ -118,6 +117,17 @@ static void (*_fsl_writel)(u32 v, unsigned __iomem *p); #define fsl_readl(p) (*_fsl_readl)((p)) #define fsl_writel(v, p) (*_fsl_writel)((v), (p)) +static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) +{ + if (pdata->big_endian_mmio) { + _fsl_readl = _fsl_readl_be; + _fsl_writel = _fsl_writel_be; + } else { + _fsl_readl = _fsl_readl_le; + _fsl_writel = _fsl_writel_le; + } +} + static inline u32 cpu_to_hc32(const u32 x) { return udc_controller->pdata->big_endian_desc @@ -132,6 +142,8 @@ static inline u32 hc32_to_cpu(const u32 x) : le32_to_cpu((__force __le32)x); } #else /* !CONFIG_PPC32 */ +static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) {} + #define fsl_readl(addr) readl(addr) #define fsl_writel(val32, addr) writel(val32, addr) #define cpu_to_hc32(x) cpu_to_le32(x) @@ -1277,6 +1289,11 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) req->req.complete = NULL; req->dtd_count = 0; + req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, + req->req.buf, req->req.length, + ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + req->mapped = 1; + if (fsl_req_to_dtd(req) == 0) fsl_queue_td(ep, req); else @@ -1348,9 +1365,6 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, /* Fill in the reqest structure */ *((u16 *) req->req.buf) = cpu_to_le16(tmp); - /* flush cache for the req buffer */ - flush_dcache_range((u32)req->req.buf, (u32)req->req.buf + 8); - req->ep = ep; req->req.length = 2; req->req.status = -EINPROGRESS; @@ -1358,6 +1372,11 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, req->req.complete = NULL; req->dtd_count = 0; + req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, + req->req.buf, req->req.length, + ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + req->mapped = 1; + /* prime the data phase */ if ((fsl_req_to_dtd(req) == 0)) fsl_queue_td(ep, req); @@ -2354,7 +2373,6 @@ static int __init struct_udc_setup(struct fsl_udc *udc, struct fsl_req, req); /* allocate a small amount of memory to get valid address */ udc->status_req->req.buf = kmalloc(8, GFP_KERNEL); - udc->status_req->req.dma = virt_to_phys(udc->status_req->req.buf); udc->resume_state = USB_STATE_NOTATTACHED; udc->usb_state = USB_STATE_POWERED; @@ -2470,13 +2488,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) } /* Set accessors only after pdata->init() ! */ - if (pdata->big_endian_mmio) { - _fsl_readl = _fsl_readl_be; - _fsl_writel = _fsl_writel_be; - } else { - _fsl_readl = _fsl_readl_le; - _fsl_writel = _fsl_writel_le; - } + fsl_set_accessors(pdata); #ifndef CONFIG_ARCH_MXC if (pdata->have_sysif_regs) -- cgit v1.2.3 From e534c5b831c8b8e9f5edee5c8a37753c808b80dc Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 1 Jul 2011 16:43:02 -0400 Subject: USB: fix regression occurring during device removal This patch (as1476) fixes a regression introduced by fccf4e86200b8f5edd9a65da26f150e32ba79808 (USB: Free bandwidth when usb_disable_device is called). usb_disconnect() grabs the bandwidth_mutex before calling usb_disable_device(), which calls down indirectly to usb_set_interface(), which tries to acquire the bandwidth_mutex. The fix causes usb_set_interface() to return early when it is called for an interface that has already been unregistered, which is what happens in usb_disable_device(). Signed-off-by: Alan Stern Tested-by: Sarah Sharp Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 64c7ab4702df..e0719b4ee189 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1286,6 +1286,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) interface); return -EINVAL; } + if (iface->unregistering) + return -ENODEV; alt = usb_altnum_to_altsetting(iface, alternate); if (!alt) { -- cgit v1.2.3 From 7f2c0662e5cfd05f12ca49109e8f787bf2d87b66 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 25 Jun 2011 12:42:14 -0700 Subject: hwmon: (pmbus) Drop check for PMBus revision register in probe function Some PMBus devices do not support the PMBus revision register, so don't check if it exists. Signed-off-by: Guenter Roeck Reviewed-by: Robert Coulson Cc: stable.kernel.org # 2.6.39 --- drivers/hwmon/pmbus_core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus_core.c index 354770ed3186..744672c1f26d 100644 --- a/drivers/hwmon/pmbus_core.c +++ b/drivers/hwmon/pmbus_core.c @@ -1430,14 +1430,9 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, i2c_set_clientdata(client, data); mutex_init(&data->update_lock); - /* - * Bail out if status register or PMBus revision register - * does not exist. - */ - if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0 - || i2c_smbus_read_byte_data(client, PMBUS_REVISION) < 0) { - dev_err(&client->dev, - "Status or revision register not found\n"); + /* Bail out if PMBus status register does not exist. */ + if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0) { + dev_err(&client->dev, "PMBus status register not found\n"); ret = -ENODEV; goto out_data; } -- cgit v1.2.3 From 3b33ca41227a54a78446fb0d7a6fdb9862f563db Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 30 Jun 2011 02:30:03 -0700 Subject: hwmon: (adm1275) Free allocated memory if probe function fails Probe function did not free allocated memory if it failed. Fix it. Signed-off-by: Guenter Roeck Reviewed-by: Robert Coulson --- drivers/hwmon/adm1275.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/adm1275.c b/drivers/hwmon/adm1275.c index c2ee2048ab91..b9b7caf4a1d2 100644 --- a/drivers/hwmon/adm1275.c +++ b/drivers/hwmon/adm1275.c @@ -32,6 +32,7 @@ static int adm1275_probe(struct i2c_client *client, const struct i2c_device_id *id) { int config; + int ret; struct pmbus_driver_info *info; if (!i2c_check_functionality(client->adapter, @@ -43,8 +44,10 @@ static int adm1275_probe(struct i2c_client *client, return -ENOMEM; config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); - if (config < 0) - return config; + if (config < 0) { + ret = config; + goto err_mem; + } info->pages = 1; info->direct[PSC_VOLTAGE_IN] = true; @@ -76,7 +79,14 @@ static int adm1275_probe(struct i2c_client *client, else info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; - return pmbus_do_probe(client, id, info); + ret = pmbus_do_probe(client, id, info); + if (ret) + goto err_mem; + return 0; + +err_mem: + kfree(info); + return ret; } static int adm1275_remove(struct i2c_client *client) -- cgit v1.2.3 From 81ae68142a0483b3791cba99eab268859858f508 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 30 Jun 2011 06:54:05 -0700 Subject: hwmon: (pmbus) Improve fan detection Some PMBus devices return no error when reading fan speed registers, but don't really support fans. Strengthen fan detection by also checking if fan configuration registers exist. Signed-off-by: Guenter Roeck Reviewed-by: Robert Coulson Cc: stable.kernel.org # 2.6.39 --- drivers/hwmon/pmbus.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/pmbus.c b/drivers/hwmon/pmbus.c index 98e2e28899e2..b0ea00b75f17 100644 --- a/drivers/hwmon/pmbus.c +++ b/drivers/hwmon/pmbus.c @@ -47,12 +47,14 @@ static void pmbus_find_sensor_groups(struct i2c_client *client, if (info->func[0] && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) info->func[0] |= PMBUS_HAVE_STATUS_INPUT; - if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { info->func[0] |= PMBUS_HAVE_FAN12; if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) info->func[0] |= PMBUS_HAVE_STATUS_FAN12; } - if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { info->func[0] |= PMBUS_HAVE_FAN34; if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) info->func[0] |= PMBUS_HAVE_STATUS_FAN34; -- cgit v1.2.3 From 0e502ec889d33bfcb348e420d7e105bc61c45eb4 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 30 Jun 2011 06:57:41 -0700 Subject: hwmon: (pmbus) Auto-detect temp2 and temp3 registers/attributes Additional temperature attribute support is easy to detect, so do it. Signed-off-by: Guenter Roeck Reviewed-by: Robert Coulson Cc: stable.kernel.org # 2.6.39 --- drivers/hwmon/pmbus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/pmbus.c b/drivers/hwmon/pmbus.c index b0ea00b75f17..931d940923ae 100644 --- a/drivers/hwmon/pmbus.c +++ b/drivers/hwmon/pmbus.c @@ -65,6 +65,10 @@ static void pmbus_find_sensor_groups(struct i2c_client *client, PMBUS_STATUS_TEMPERATURE)) info->func[0] |= PMBUS_HAVE_STATUS_TEMP; } + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; /* Sensors detected on all pages */ for (page = 0; page < info->pages; page++) { -- cgit v1.2.3 From 6e4e2f811bade330126d4029c88c831784a7efd9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 1 Jul 2011 17:30:00 -0700 Subject: 6pack,mkiss: fix lock inconsistency Lockdep found a locking inconsistency in the mkiss_close function: > kernel: [ INFO: inconsistent lock state ] > kernel: 2.6.39.1 #3 > kernel: --------------------------------- > kernel: inconsistent {IN-SOFTIRQ-R} -> {SOFTIRQ-ON-W} usage. > kernel: ax25ipd/2813 [HC0[0]:SC0[0]:HE1:SE1] takes: > kernel: (disc_data_lock){+++?.-}, at: [] mkiss_close+0x1b/0x90 [mkiss] > kernel: {IN-SOFTIRQ-R} state was registered at: The message hints that disc_data_lock is aquired with softirqs disabled, but does not itself disable softirqs, which can in rare circumstances lead to a deadlock. The same problem is present in the 6pack driver, this patch fixes both by using write_lock_bh instead of write_lock. Reported-by: Bernard F6BVP Tested-by: Bernard F6BVP Signed-off-by: Arnd Bergmann Acked-by: Ralf Baechle Cc: stable@kernel.org Signed-off-by: David S. Miller --- drivers/net/hamradio/6pack.c | 4 ++-- drivers/net/hamradio/mkiss.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 3e5d0b6b6516..0d283781bc5e 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -692,10 +692,10 @@ static void sixpack_close(struct tty_struct *tty) { struct sixpack *sp; - write_lock(&disc_data_lock); + write_lock_bh(&disc_data_lock); sp = tty->disc_data; tty->disc_data = NULL; - write_unlock(&disc_data_lock); + write_unlock_bh(&disc_data_lock); if (!sp) return; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 4c628393c8b1..bc02968cee16 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -813,10 +813,10 @@ static void mkiss_close(struct tty_struct *tty) { struct mkiss *ax; - write_lock(&disc_data_lock); + write_lock_bh(&disc_data_lock); ax = tty->disc_data; tty->disc_data = NULL; - write_unlock(&disc_data_lock); + write_unlock_bh(&disc_data_lock); if (!ax) return; -- cgit v1.2.3 From 11d53b4990226247a950e2b1ccfa4cf93bfbc822 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 24 Jun 2011 15:23:34 -0700 Subject: ipv6: Don't change dst->flags using assignments. This blows away any flags already set in the entry. Signed-off-by: David S. Miller --- net/ipv6/route.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index de2b1decd786..c2af4da074b0 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1062,14 +1062,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); rt->dst.output = ip6_output; -#if 0 /* there's no chance to use these for ndisc */ - rt->dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST - ? DST_HOST - : 0; - ipv6_addr_copy(&rt->rt6i_dst.addr, addr); - rt->rt6i_dst.plen = 128; -#endif - spin_lock_bh(&icmp6_dst_lock); rt->dst.next = icmp6_dst_gc_list; icmp6_dst_gc_list = &rt->dst; @@ -1244,7 +1236,7 @@ int ip6_route_add(struct fib6_config *cfg) ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); rt->rt6i_dst.plen = cfg->fc_dst_len; if (rt->rt6i_dst.plen == 128) - rt->dst.flags = DST_HOST; + rt->dst.flags |= DST_HOST; #ifdef CONFIG_IPV6_SUBTREES ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); @@ -2025,7 +2017,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, in6_dev_hold(idev); - rt->dst.flags = DST_HOST; + rt->dst.flags |= DST_HOST; rt->dst.input = ip6_input; rt->dst.output = ip6_output; rt->rt6i_idev = idev; -- cgit v1.2.3 From 957c665f37007de93ccbe45902a23143724170d0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 24 Jun 2011 15:25:00 -0700 Subject: ipv6: Don't put artificial limit on routing table size. IPV6, unlike IPV4, doesn't have a routing cache. Routing table entries, as well as clones made in response to route lookup requests, all live in the same table. And all of these things are together collected in the destination cache table for ipv6. This means that routing table entries count against the garbage collection limits, even though such entries cannot ever be reclaimed and are added explicitly by the administrator (rather than being created in response to lookups). Therefore it makes no sense to count ipv6 routing table entries against the GC limits. Add a DST_NOCOUNT destination cache entry flag, and skip the counting if it is set. Use this flag bit in ipv6 when adding routing table entries. Signed-off-by: David S. Miller --- include/net/dst.h | 1 + net/core/dst.c | 6 ++++-- net/ipv6/route.c | 13 +++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 7d15d238b6ec..e12ddfb9eb16 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -77,6 +77,7 @@ struct dst_entry { #define DST_NOPOLICY 0x0004 #define DST_NOHASH 0x0008 #define DST_NOCACHE 0x0010 +#define DST_NOCOUNT 0x0020 union { struct dst_entry *next; struct rtable __rcu *rt_next; diff --git a/net/core/dst.c b/net/core/dst.c index 9ccca038444f..6135f3671692 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -190,7 +190,8 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, dst->lastuse = jiffies; dst->flags = flags; dst->next = NULL; - dst_entries_add(ops, 1); + if (!(flags & DST_NOCOUNT)) + dst_entries_add(ops, 1); return dst; } EXPORT_SYMBOL(dst_alloc); @@ -243,7 +244,8 @@ again: neigh_release(neigh); } - dst_entries_add(dst->ops, -1); + if (!(dst->flags & DST_NOCOUNT)) + dst_entries_add(dst->ops, -1); if (dst->ops->destroy) dst->ops->destroy(dst); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c2af4da074b0..0ef1f086feb8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -228,9 +228,10 @@ static struct rt6_info ip6_blk_hole_entry_template = { /* allocate dst with ip6_dst_ops */ static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, - struct net_device *dev) + struct net_device *dev, + int flags) { - struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, 0); + struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); @@ -1042,7 +1043,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, if (unlikely(idev == NULL)) return NULL; - rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev); + rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); if (unlikely(rt == NULL)) { in6_dev_put(idev); goto out; @@ -1206,7 +1207,7 @@ int ip6_route_add(struct fib6_config *cfg) goto out; } - rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL); + rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT); if (rt == NULL) { err = -ENOMEM; @@ -1726,7 +1727,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) { struct net *net = dev_net(ort->rt6i_dev); struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, - ort->dst.dev); + ort->dst.dev, 0); if (rt) { rt->dst.input = ort->dst.input; @@ -2005,7 +2006,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, { struct net *net = dev_net(idev->dev); struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, - net->loopback_dev); + net->loopback_dev, 0); struct neighbour *neigh; if (rt == NULL) { -- cgit v1.2.3 From 12fdb4d3babcde43834c54dee22a69bb73adbae7 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 29 Jun 2011 23:18:20 +0000 Subject: xfrm: Remove family arg from xfrm_bundle_ok The family arg is not used any more, so remove it. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/xfrm/xfrm_policy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 9bec2e8a838c..5ce74a385525 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -50,7 +50,7 @@ static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); static void xfrm_init_pmtu(struct dst_entry *dst); static int stale_bundle(struct dst_entry *dst); -static int xfrm_bundle_ok(struct xfrm_dst *xdst, int family); +static int xfrm_bundle_ok(struct xfrm_dst *xdst); static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, @@ -2241,7 +2241,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) static int stale_bundle(struct dst_entry *dst) { - return !xfrm_bundle_ok((struct xfrm_dst *)dst, AF_UNSPEC); + return !xfrm_bundle_ok((struct xfrm_dst *)dst); } void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) @@ -2313,7 +2313,7 @@ static void xfrm_init_pmtu(struct dst_entry *dst) * still valid. */ -static int xfrm_bundle_ok(struct xfrm_dst *first, int family) +static int xfrm_bundle_ok(struct xfrm_dst *first) { struct dst_entry *dst = &first->u.dst; struct xfrm_dst *last; -- cgit v1.2.3 From c146066ab80267c3305de5dda6a4083f06df9265 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 29 Jun 2011 23:19:32 +0000 Subject: ipv4: Don't use ufo handling on later transformed packets We might call ip_ufo_append_data() for packets that will be IPsec transformed later. This function should be used just for real udp packets. So we check for rt->dst.header_len which is only nonzero on IPsec handling and call ip_ufo_append_data() just if rt->dst.header_len is zero. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4a7e16b5d3f3..84f26e8e6c60 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -828,7 +828,7 @@ static int __ip_append_data(struct sock *sk, cork->length += length; if (((length > mtu) || (skb && skb_is_gso(skb))) && (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO)) { + (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { err = ip_ufo_append_data(sk, queue, getfrag, from, length, hh_len, fragheaderlen, transhdrlen, mtu, flags); -- cgit v1.2.3 From b00897b881f775040653955fda99dcf7c167b382 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 29 Jun 2011 23:20:41 +0000 Subject: xfrm4: Don't call icmp_send on local error Calling icmp_send() on a local message size error leads to an incorrect update of the path mtu. So use ip_local_error() instead to notify the socket about the error. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/xfrm4_output.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 2d51840e53a1..327a617d594c 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -32,7 +32,12 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) dst = skb_dst(skb); mtu = dst_mtu(dst); if (skb->len > mtu) { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + if (skb->sk) + ip_local_error(skb->sk, EMSGSIZE, ip_hdr(skb)->daddr, + inet_sk(skb->sk)->inet_dport, mtu); + else + icmp_send(skb, ICMP_DEST_UNREACH, + ICMP_FRAG_NEEDED, htonl(mtu)); ret = -EMSGSIZE; } out: -- cgit v1.2.3 From da92b393e0bfc8e6d056885453201b0e7d8190dd Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Thu, 30 Jun 2011 10:02:05 +0000 Subject: qlge:Fix crash caused by mailbox execution on wedged chip. When we are in a recover process from a chip fatal error, driver should skip over execution of mailbox commands during resetting chip. Signed-off-by: Jitendra Kalsaria Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 1 + drivers/net/qlge/qlge_main.c | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index d32850715f5c..b2c86124a120 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -1996,6 +1996,7 @@ enum { QL_LB_LINK_UP = 10, QL_FRC_COREDUMP = 11, QL_EEH_FATAL = 12, + QL_ASIC_RECOVERY = 14, /* We are in ascic recovery. */ }; /* link_status bit definitions */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 930ae45457bb..4fbefcf989a0 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2152,6 +2152,10 @@ void ql_queue_asic_error(struct ql_adapter *qdev) * thread */ clear_bit(QL_ADAPTER_UP, &qdev->flags); + /* Set asic recovery bit to indicate reset process that we are + * in fatal error recovery process rather than normal close + */ + set_bit(QL_ASIC_RECOVERY, &qdev->flags); queue_delayed_work(qdev->workqueue, &qdev->asic_reset_work, 0); } @@ -3818,11 +3822,17 @@ static int ql_adapter_reset(struct ql_adapter *qdev) end_jiffies = jiffies + max((unsigned long)1, usecs_to_jiffies(30)); - /* Stop management traffic. */ - ql_mb_set_mgmnt_traffic_ctl(qdev, MB_SET_MPI_TFK_STOP); + /* Check if bit is set then skip the mailbox command and + * clear the bit, else we are in normal reset process. + */ + if (!test_bit(QL_ASIC_RECOVERY, &qdev->flags)) { + /* Stop management traffic. */ + ql_mb_set_mgmnt_traffic_ctl(qdev, MB_SET_MPI_TFK_STOP); - /* Wait for the NIC and MGMNT FIFOs to empty. */ - ql_wait_fifo_empty(qdev); + /* Wait for the NIC and MGMNT FIFOs to empty. */ + ql_wait_fifo_empty(qdev); + } else + clear_bit(QL_ASIC_RECOVERY, &qdev->flags); ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); -- cgit v1.2.3 From 5069ee555eb41192e7a5003ba3b1f91880cfec06 Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Thu, 30 Jun 2011 10:02:06 +0000 Subject: qlge: Fix printk priority so chip fatal errors are always reported. Precedence of the printk should be at higher level so chip fatal errors are always reported. Signed-off-by: Jitendra Kalsaria Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 4fbefcf989a0..6b4ff970972b 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2170,23 +2170,20 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev, return; case CAM_LOOKUP_ERR_EVENT: - netif_err(qdev, link, qdev->ndev, - "Multiple CAM hits lookup occurred.\n"); - netif_err(qdev, drv, qdev->ndev, - "This event shouldn't occur.\n"); + netdev_err(qdev->ndev, "Multiple CAM hits lookup occurred.\n"); + netdev_err(qdev->ndev, "This event shouldn't occur.\n"); ql_queue_asic_error(qdev); return; case SOFT_ECC_ERROR_EVENT: - netif_err(qdev, rx_err, qdev->ndev, - "Soft ECC error detected.\n"); + netdev_err(qdev->ndev, "Soft ECC error detected.\n"); ql_queue_asic_error(qdev); break; case PCI_ERR_ANON_BUF_RD: - netif_err(qdev, rx_err, qdev->ndev, - "PCI error occurred when reading anonymous buffers from rx_ring %d.\n", - ib_ae_rsp->q_id); + netdev_err(qdev->ndev, "PCI error occurred when reading " + "anonymous buffers from rx_ring %d.\n", + ib_ae_rsp->q_id); ql_queue_asic_error(qdev); break; @@ -2441,11 +2438,10 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) */ if (var & STS_FE) { ql_queue_asic_error(qdev); - netif_err(qdev, intr, qdev->ndev, - "Got fatal error, STS = %x.\n", var); + netdev_err(qdev->ndev, "Got fatal error, STS = %x.\n", var); var = ql_read32(qdev, ERR_STS); - netif_err(qdev, intr, qdev->ndev, - "Resetting chip. Error Status Register = 0x%x\n", var); + netdev_err(qdev->ndev, "Resetting chip. " + "Error Status Register = 0x%x\n", var); return IRQ_HANDLED; } -- cgit v1.2.3 From b4e4fe848c25af645a069bb2f21ba6456246e5de Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Thu, 30 Jun 2011 10:02:07 +0000 Subject: qlge:Version change to v1.00.00.29 Signed-off-by: Jitendra Kalsaria Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index b2c86124a120..ca306fd5f588 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -16,7 +16,7 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "v1.00.00.27.00.00-01" +#define DRV_VERSION "v1.00.00.29.00.00-01" #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ -- cgit v1.2.3 From 5f77898de17ff983ff0e2988b73a6bdf4b6f9f8b Mon Sep 17 00:00:00 2001 From: Shyam Iyer Date: Tue, 28 Jun 2011 08:58:05 +0000 Subject: Fix call trace when interrupts are disabled while sleeping function kzalloc is called request_threaded irq will call kzalloc that can sleep. Initializing the flags variable outside of spin_lock_irqsave/restore in bnad_mbox_irq_alloc will avoid call traces like below. Jun 27 08:15:24 home-t710 kernel: [11735.634550] Brocade 10G Ethernet driver Jun 27 08:15:24 home-t710 kernel: [11735.634590] bnad_pci_probe : (0xffff880427f3d000, 0xffffffffa020f3e0) PCI Func : (2) Jun 27 08:15:24 home-t710 kernel: [11735.637677] bna 0000:82:00.2: PCI INT A -> GSI 66 (level, low) -> IRQ 66 Jun 27 08:15:24 home-t710 kernel: [11735.638290] bar0 mapped to ffffc90014980000, len 262144 Jun 27 08:15:24 home-t710 kernel: [11735.638732] BUG: sleeping function called from invalid context at mm/slub.c:847 Jun 27 08:15:24 home-t710 kernel: [11735.638736] in_atomic(): 0, irqs_disabled(): 1, pid: 11243, name: insmod Jun 27 08:15:24 home-t710 kernel: [11735.638740] Pid: 11243, comm: insmod Not tainted 3.0.0-rc4+ #6 Jun 27 08:15:24 home-t710 kernel: [11735.638743] Call Trace: Jun 27 08:15:24 home-t710 kernel: [11735.638755] [] __might_sleep+0xeb/0xf0 Jun 27 08:15:24 home-t710 kernel: [11735.638766] [] ? netif_wake_queue+0x3d/0x3d [bna] Jun 27 08:15:24 home-t710 kernel: [11735.638773] [] kmem_cache_alloc_trace+0x43/0xd8 Jun 27 08:15:24 home-t710 kernel: [11735.638782] [] ? netif_wake_queue+0x3d/0x3d [bna] Jun 27 08:15:24 home-t710 kernel: [11735.638787] [] request_threaded_irq+0xa1/0x113 Jun 27 08:15:24 home-t710 kernel: [11735.638798] [] bnad_pci_probe+0x612/0x8e5 [bna] Jun 27 08:15:24 home-t710 kernel: [11735.638807] [] ? netif_wake_queue+0x3d/0x3d [bna] Jun 27 08:15:24 home-t710 kernel: [11735.638816] [] ? _raw_spin_unlock_irqrestore+0x17/0x19 Jun 27 08:15:24 home-t710 kernel: [11735.638822] [] local_pci_probe+0x44/0x75 Jun 27 08:15:24 home-t710 kernel: [11735.638826] [] pci_device_probe+0xd0/0xff Jun 27 08:15:24 home-t710 kernel: [11735.638832] [] driver_probe_device+0x131/0x213 Jun 27 08:15:24 home-t710 kernel: [11735.638836] [] __driver_attach+0x5a/0x7e Jun 27 08:15:24 home-t710 kernel: [11735.638840] [] ? driver_probe_device+0x213/0x213 Jun 27 08:15:24 home-t710 kernel: [11735.638844] [] bus_for_each_dev+0x53/0x89 Jun 27 08:15:24 home-t710 kernel: [11735.638848] [] driver_attach+0x1e/0x20 Jun 27 08:15:24 home-t710 kernel: [11735.638852] [] bus_add_driver+0xd1/0x224 Jun 27 08:15:24 home-t710 kernel: [11735.638858] [] ? 0xffffffffa01b7fff Jun 27 08:15:24 home-t710 kernel: [11735.638862] [] driver_register+0x98/0x105 Jun 27 08:15:24 home-t710 kernel: [11735.638866] [] ? 0xffffffffa01b7fff Jun 27 08:15:24 home-t710 kernel: [11735.638871] [] __pci_register_driver+0x56/0xc1 Jun 27 08:15:24 home-t710 kernel: [11735.638875] [] ? 0xffffffffa01b7fff Jun 27 08:15:24 home-t710 kernel: [11735.638884] [] bnad_module_init+0x40/0x60 [bna] Jun 27 08:15:24 home-t710 kernel: [11735.638892] [] do_one_initcall+0x7f/0x136 Jun 27 08:15:24 home-t710 kernel: [11735.638899] [] sys_init_module+0x88/0x1d0 Jun 27 08:15:24 home-t710 kernel: [11735.638906] [] system_call_fastpath+0x16/0x1b Jun 27 08:15:24 home-t710 kernel: [11735.639642] bnad_pci_probe : (0xffff880427f3e000, 0xffffffffa020f3e0) PCI Func : (3) Jun 27 08:15:24 home-t710 kernel: [11735.639665] bna 0000:82:00.3: PCI INT A -> GSI 66 (level, low) -> IRQ 66 Jun 27 08:15:24 home-t710 kernel: [11735.639735] bar0 mapped to ffffc90014400000, len 262144 Signed-off-by: Shyam Iyer Acked-by: Rasesh Mody Signed-off-by: David S. Miller --- drivers/net/bna/bnad.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c index 7d25a97d33f6..44e219c910da 100644 --- a/drivers/net/bna/bnad.c +++ b/drivers/net/bna/bnad.c @@ -1111,7 +1111,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad, struct bna_intr_info *intr_info) { int err = 0; - unsigned long flags; + unsigned long irq_flags = 0, flags; u32 irq; irq_handler_t irq_handler; @@ -1125,18 +1125,17 @@ bnad_mbox_irq_alloc(struct bnad *bnad, if (bnad->cfg_flags & BNAD_CF_MSIX) { irq_handler = (irq_handler_t)bnad_msix_mbox_handler; irq = bnad->msix_table[bnad->msix_num - 1].vector; - flags = 0; intr_info->intr_type = BNA_INTR_T_MSIX; intr_info->idl[0].vector = bnad->msix_num - 1; } else { irq_handler = (irq_handler_t)bnad_isr; irq = bnad->pcidev->irq; - flags = IRQF_SHARED; + irq_flags = IRQF_SHARED; intr_info->intr_type = BNA_INTR_T_INTX; /* intr_info->idl.vector = 0 ? */ } spin_unlock_irqrestore(&bnad->bna_lock, flags); - + flags = irq_flags; sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME); /* -- cgit v1.2.3 From 5efb54cc3fc104585cda81c44676f05115bd9ddd Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 30 Jun 2011 15:07:31 -0700 Subject: PM: Documentation: fix typo: pm_runtime_idle_sync() doesn't exist. Replace reference to pm_runtime_idle_sync() in the driver core with pm_runtime_put_sync() which is used in the code. Signed-off-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- Documentation/power/runtime_pm.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 22accb3eb40e..518d9be4c731 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -506,7 +506,7 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has -finished, so the PM core uses pm_runtime_idle_sync() to invoke the +finished, so the PM core uses pm_runtime_put_sync() to invoke the subsystem-level idle callback for the device at that time. The user space can effectively disallow the driver of the device to power manage -- cgit v1.2.3 From f5da24dbed213d103f00aa9ef26e010b50d2db24 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 2 Jul 2011 14:27:11 +0200 Subject: PM / Runtime: Update documentation regarding driver removal Commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a (PM / Runtime: Rework runtime PM handling during driver removal) forgot to update the documentation in Documentation/power/runtime_pm.txt to match the new code in drivers/base/dd.c. Update that documentation to match the code it describes. Signed-off-by: Rafael J. Wysocki Reviewed-by: Kevin Hilman --- Documentation/power/runtime_pm.txt | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 518d9be4c731..b24875b1ced5 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -501,13 +501,29 @@ helper functions described in Section 4. In that case, pm_runtime_resume() should be used. Of course, for this purpose the device's run-time PM has to be enabled earlier by calling pm_runtime_enable(). -If the device bus type's or driver's ->probe() or ->remove() callback runs +If the device bus type's or driver's ->probe() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is -incremented by the core before executing ->probe() and ->remove(). Still, it -may be desirable to suspend the device as soon as ->probe() or ->remove() has -finished, so the PM core uses pm_runtime_put_sync() to invoke the -subsystem-level idle callback for the device at that time. +incremented by the driver core before executing ->probe(). Still, it may be +desirable to suspend the device as soon as ->probe() has finished, so the driver +core uses pm_runtime_put_sync() to invoke the subsystem-level idle callback for +the device at that time. + +Moreover, the driver core prevents runtime PM callbacks from racing with the bus +notifier callback in __device_release_driver(), which is necessary, because the +notifier is used by some subsystems to carry out operations affecting the +runtime PM functionality. It does so by calling pm_runtime_get_sync() before +driver_sysfs_remove() and the BUS_NOTIFY_UNBIND_DRIVER notifications. This +resumes the device if it's in the suspended state and prevents it from +being suspended again while those routines are being executed. + +To allow bus types and drivers to put devices into the suspended state by +calling pm_runtime_suspend() from their ->remove() routines, the driver core +executes pm_runtime_put_sync() after running the BUS_NOTIFY_UNBIND_DRIVER +notifications in __device_release_driver(). This requires bus types and +drivers to make their ->remove() callbacks avoid races with runtime PM directly, +but also it allows of more flexibility in the handling of devices during the +removal of their drivers. The user space can effectively disallow the driver of the device to power manage it at run time by changing the value of its /sys/devices/.../power/control -- cgit v1.2.3 From 6f231dda68080759f1aed3769896e94c73099f0f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 2 Jul 2011 22:56:22 -0700 Subject: isci: Intel(R) C600 Series Chipset Storage Control Unit Driver Support for the up to 2x4-port 6Gb/s SAS controllers embedded in the chipset. This is a snapshot of the first publicly available version of the driver, commit 4c1db2d0 in the 'historical' branch. git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git historical Signed-off-by: Maciej Trela Signed-off-by: Dave Jiang Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/Kconfig | 34 + drivers/scsi/Makefile | 1 + drivers/scsi/isci/Makefile | 30 + drivers/scsi/isci/core/intel_ata.h | 554 +++ drivers/scsi/isci/core/intel_sas.h | 948 +++++ drivers/scsi/isci/core/intel_sat.h | 95 + drivers/scsi/isci/core/intel_sata.h | 280 ++ drivers/scsi/isci/core/intel_scsi.h | 474 +++ drivers/scsi/isci/core/sati_device.h | 156 + drivers/scsi/isci/core/sati_translator_sequence.h | 304 ++ drivers/scsi/isci/core/sati_types.h | 145 + drivers/scsi/isci/core/sci_base_controller.h | 306 ++ .../isci/core/sci_base_memory_descriptor_list.c | 159 + .../isci/core/sci_base_memory_descriptor_list.h | 155 + drivers/scsi/isci/core/sci_base_phy.h | 205 + drivers/scsi/isci/core/sci_base_port.h | 203 + drivers/scsi/isci/core/sci_base_remote_device.h | 277 ++ drivers/scsi/isci/core/sci_base_request.h | 195 + drivers/scsi/isci/core/sci_base_state.h | 90 + drivers/scsi/isci/core/sci_base_state_machine.c | 182 + drivers/scsi/isci/core/sci_base_state_machine.h | 139 + drivers/scsi/isci/core/sci_controller.h | 100 + drivers/scsi/isci/core/sci_controller_constants.h | 215 + .../scsi/isci/core/sci_memory_descriptor_list.h | 169 + drivers/scsi/isci/core/sci_object.h | 99 + drivers/scsi/isci/core/sci_pool.h | 199 + drivers/scsi/isci/core/sci_status.h | 409 ++ drivers/scsi/isci/core/sci_types.h | 88 + drivers/scsi/isci/core/sci_util.c | 70 + drivers/scsi/isci/core/sci_util.h | 138 + drivers/scsi/isci/core/scic_config_parameters.h | 347 ++ drivers/scsi/isci/core/scic_controller.h | 586 +++ drivers/scsi/isci/core/scic_io_request.h | 512 +++ drivers/scsi/isci/core/scic_phy.h | 303 ++ drivers/scsi/isci/core/scic_port.h | 213 + drivers/scsi/isci/core/scic_remote_device.h | 295 ++ drivers/scsi/isci/core/scic_sds_controller.c | 4147 ++++++++++++++++++++ drivers/scsi/isci/core/scic_sds_controller.h | 706 ++++ .../scsi/isci/core/scic_sds_controller_registers.h | 463 +++ drivers/scsi/isci/core/scic_sds_pci.h | 95 + drivers/scsi/isci/core/scic_sds_phy.c | 2807 +++++++++++++ drivers/scsi/isci/core/scic_sds_phy.h | 491 +++ drivers/scsi/isci/core/scic_sds_phy_registers.h | 187 + drivers/scsi/isci/core/scic_sds_port.c | 2757 +++++++++++++ drivers/scsi/isci/core/scic_sds_port.h | 514 +++ .../isci/core/scic_sds_port_configuration_agent.c | 851 ++++ .../isci/core/scic_sds_port_configuration_agent.h | 108 + drivers/scsi/isci/core/scic_sds_port_registers.h | 223 ++ drivers/scsi/isci/core/scic_sds_remote_device.c | 2252 +++++++++++ drivers/scsi/isci/core/scic_sds_remote_device.h | 602 +++ .../scsi/isci/core/scic_sds_remote_node_context.c | 1244 ++++++ .../scsi/isci/core/scic_sds_remote_node_context.h | 342 ++ .../scsi/isci/core/scic_sds_remote_node_table.c | 600 +++ .../scsi/isci/core/scic_sds_remote_node_table.h | 196 + drivers/scsi/isci/core/scic_sds_request.c | 2179 ++++++++++ drivers/scsi/isci/core/scic_sds_request.h | 484 +++ .../scsi/isci/core/scic_sds_smp_remote_device.c | 410 ++ drivers/scsi/isci/core/scic_sds_smp_request.c | 669 ++++ drivers/scsi/isci/core/scic_sds_smp_request.h | 70 + drivers/scsi/isci/core/scic_sds_ssp_request.c | 340 ++ .../scsi/isci/core/scic_sds_stp_packet_request.c | 838 ++++ .../scsi/isci/core/scic_sds_stp_packet_request.h | 154 + drivers/scsi/isci/core/scic_sds_stp_pio_request.h | 116 + .../scsi/isci/core/scic_sds_stp_remote_device.c | 975 +++++ drivers/scsi/isci/core/scic_sds_stp_request.c | 2004 ++++++++++ drivers/scsi/isci/core/scic_sds_stp_request.h | 221 ++ .../isci/core/scic_sds_unsolicited_frame_control.c | 379 ++ .../isci/core/scic_sds_unsolicited_frame_control.h | 286 ++ drivers/scsi/isci/core/scic_task_request.h | 148 + drivers/scsi/isci/core/scic_user_callback.h | 740 ++++ drivers/scsi/isci/core/scu_completion_codes.h | 280 ++ drivers/scsi/isci/core/scu_constants.h | 151 + drivers/scsi/isci/core/scu_event_codes.h | 336 ++ drivers/scsi/isci/core/scu_registers.h | 1824 +++++++++ drivers/scsi/isci/core/scu_remote_node_context.h | 230 ++ drivers/scsi/isci/core/scu_task_context.h | 943 +++++ drivers/scsi/isci/core/scu_unsolicited_frame.h | 117 + drivers/scsi/isci/core/scu_viit_data.h | 179 + drivers/scsi/isci/deprecated.c | 491 +++ drivers/scsi/isci/events.c | 619 +++ drivers/scsi/isci/firmware/Makefile | 19 + drivers/scsi/isci/firmware/README | 36 + drivers/scsi/isci/firmware/create_fw.c | 177 + drivers/scsi/isci/host.c | 781 ++++ drivers/scsi/isci/host.h | 283 ++ drivers/scsi/isci/init.c | 613 +++ drivers/scsi/isci/isci.h | 138 + drivers/scsi/isci/phy.c | 179 + drivers/scsi/isci/phy.h | 104 + drivers/scsi/isci/port.c | 484 +++ drivers/scsi/isci/port.h | 153 + drivers/scsi/isci/remote_device.c | 698 ++++ drivers/scsi/isci/remote_device.h | 154 + drivers/scsi/isci/request.c | 1472 +++++++ drivers/scsi/isci/request.h | 429 ++ drivers/scsi/isci/sata.c | 356 ++ drivers/scsi/isci/sata.h | 83 + drivers/scsi/isci/sci_environment.h | 112 + drivers/scsi/isci/task.c | 1691 ++++++++ drivers/scsi/isci/task.h | 368 ++ drivers/scsi/isci/timers.c | 319 ++ drivers/scsi/isci/timers.h | 126 + firmware/Makefile | 1 + firmware/isci/isci_firmware.bin.ihex | 11 + 104 files changed, 51230 insertions(+) create mode 100644 drivers/scsi/isci/Makefile create mode 100644 drivers/scsi/isci/core/intel_ata.h create mode 100644 drivers/scsi/isci/core/intel_sas.h create mode 100644 drivers/scsi/isci/core/intel_sat.h create mode 100644 drivers/scsi/isci/core/intel_sata.h create mode 100644 drivers/scsi/isci/core/intel_scsi.h create mode 100644 drivers/scsi/isci/core/sati_device.h create mode 100644 drivers/scsi/isci/core/sati_translator_sequence.h create mode 100644 drivers/scsi/isci/core/sati_types.h create mode 100644 drivers/scsi/isci/core/sci_base_controller.h create mode 100644 drivers/scsi/isci/core/sci_base_memory_descriptor_list.c create mode 100644 drivers/scsi/isci/core/sci_base_memory_descriptor_list.h create mode 100644 drivers/scsi/isci/core/sci_base_phy.h create mode 100644 drivers/scsi/isci/core/sci_base_port.h create mode 100644 drivers/scsi/isci/core/sci_base_remote_device.h create mode 100644 drivers/scsi/isci/core/sci_base_request.h create mode 100644 drivers/scsi/isci/core/sci_base_state.h create mode 100644 drivers/scsi/isci/core/sci_base_state_machine.c create mode 100644 drivers/scsi/isci/core/sci_base_state_machine.h create mode 100644 drivers/scsi/isci/core/sci_controller.h create mode 100644 drivers/scsi/isci/core/sci_controller_constants.h create mode 100644 drivers/scsi/isci/core/sci_memory_descriptor_list.h create mode 100644 drivers/scsi/isci/core/sci_object.h create mode 100644 drivers/scsi/isci/core/sci_pool.h create mode 100644 drivers/scsi/isci/core/sci_status.h create mode 100644 drivers/scsi/isci/core/sci_types.h create mode 100644 drivers/scsi/isci/core/sci_util.c create mode 100644 drivers/scsi/isci/core/sci_util.h create mode 100644 drivers/scsi/isci/core/scic_config_parameters.h create mode 100644 drivers/scsi/isci/core/scic_controller.h create mode 100644 drivers/scsi/isci/core/scic_io_request.h create mode 100644 drivers/scsi/isci/core/scic_phy.h create mode 100644 drivers/scsi/isci/core/scic_port.h create mode 100644 drivers/scsi/isci/core/scic_remote_device.h create mode 100644 drivers/scsi/isci/core/scic_sds_controller.c create mode 100644 drivers/scsi/isci/core/scic_sds_controller.h create mode 100644 drivers/scsi/isci/core/scic_sds_controller_registers.h create mode 100644 drivers/scsi/isci/core/scic_sds_pci.h create mode 100644 drivers/scsi/isci/core/scic_sds_phy.c create mode 100644 drivers/scsi/isci/core/scic_sds_phy.h create mode 100644 drivers/scsi/isci/core/scic_sds_phy_registers.h create mode 100644 drivers/scsi/isci/core/scic_sds_port.c create mode 100644 drivers/scsi/isci/core/scic_sds_port.h create mode 100644 drivers/scsi/isci/core/scic_sds_port_configuration_agent.c create mode 100644 drivers/scsi/isci/core/scic_sds_port_configuration_agent.h create mode 100644 drivers/scsi/isci/core/scic_sds_port_registers.h create mode 100644 drivers/scsi/isci/core/scic_sds_remote_device.c create mode 100644 drivers/scsi/isci/core/scic_sds_remote_device.h create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_context.c create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_context.h create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_table.c create mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_table.h create mode 100644 drivers/scsi/isci/core/scic_sds_request.c create mode 100644 drivers/scsi/isci/core/scic_sds_request.h create mode 100644 drivers/scsi/isci/core/scic_sds_smp_remote_device.c create mode 100644 drivers/scsi/isci/core/scic_sds_smp_request.c create mode 100644 drivers/scsi/isci/core/scic_sds_smp_request.h create mode 100644 drivers/scsi/isci/core/scic_sds_ssp_request.c create mode 100644 drivers/scsi/isci/core/scic_sds_stp_packet_request.c create mode 100644 drivers/scsi/isci/core/scic_sds_stp_packet_request.h create mode 100644 drivers/scsi/isci/core/scic_sds_stp_pio_request.h create mode 100644 drivers/scsi/isci/core/scic_sds_stp_remote_device.c create mode 100644 drivers/scsi/isci/core/scic_sds_stp_request.c create mode 100644 drivers/scsi/isci/core/scic_sds_stp_request.h create mode 100644 drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c create mode 100644 drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h create mode 100644 drivers/scsi/isci/core/scic_task_request.h create mode 100644 drivers/scsi/isci/core/scic_user_callback.h create mode 100644 drivers/scsi/isci/core/scu_completion_codes.h create mode 100644 drivers/scsi/isci/core/scu_constants.h create mode 100644 drivers/scsi/isci/core/scu_event_codes.h create mode 100644 drivers/scsi/isci/core/scu_registers.h create mode 100644 drivers/scsi/isci/core/scu_remote_node_context.h create mode 100644 drivers/scsi/isci/core/scu_task_context.h create mode 100644 drivers/scsi/isci/core/scu_unsolicited_frame.h create mode 100644 drivers/scsi/isci/core/scu_viit_data.h create mode 100644 drivers/scsi/isci/deprecated.c create mode 100644 drivers/scsi/isci/events.c create mode 100644 drivers/scsi/isci/firmware/Makefile create mode 100644 drivers/scsi/isci/firmware/README create mode 100644 drivers/scsi/isci/firmware/create_fw.c create mode 100644 drivers/scsi/isci/host.c create mode 100644 drivers/scsi/isci/host.h create mode 100644 drivers/scsi/isci/init.c create mode 100644 drivers/scsi/isci/isci.h create mode 100644 drivers/scsi/isci/phy.c create mode 100644 drivers/scsi/isci/phy.h create mode 100644 drivers/scsi/isci/port.c create mode 100644 drivers/scsi/isci/port.h create mode 100644 drivers/scsi/isci/remote_device.c create mode 100644 drivers/scsi/isci/remote_device.h create mode 100644 drivers/scsi/isci/request.c create mode 100644 drivers/scsi/isci/request.h create mode 100644 drivers/scsi/isci/sata.c create mode 100644 drivers/scsi/isci/sata.h create mode 100644 drivers/scsi/isci/sci_environment.h create mode 100644 drivers/scsi/isci/task.c create mode 100644 drivers/scsi/isci/task.h create mode 100644 drivers/scsi/isci/timers.c create mode 100644 drivers/scsi/isci/timers.h create mode 100644 firmware/isci/isci_firmware.bin.ihex diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 4a1f029c4fe9..3aa664fa892e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -830,6 +830,40 @@ config SCSI_GDTH To compile this driver as a module, choose M here: the module will be called gdth. +config SCSI_ISCI + tristate "Intel(R) C600 Series Chipset SAS Controller" + depends on PCI && SCSI + # little endian host assumptions + depends on X86 + # (temporary): dma api misuse + depends on !DMAR + # (temporary): known alpha quality driver + depends on EXPERIMENTAL + select SCSI_SAS_LIBSAS + ---help--- + This driver supports the 6Gb/s SAS capabilities of the storage + control unit found in the Intel(R) C600 series chipset. + + The experimental tag will be removed after the driver exits alpha + +choice + prompt "Default Silicon Revision" + depends on SCSI_ISCI + default PBG_HBA_A2 + # temporary A-step silicon is pre-production + +config PBG_HBA_BETA + bool "B0" + +config PBG_HBA_A2 + bool "A2" + +config PBG_HBA_A0 + bool "A0" + +endchoice + + config SCSI_GENERIC_NCR5380 tristate "Generic NCR5380/53c400 SCSI PIO support" depends on ISA && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 7ad0b8a79ae8..3c08f5352b2d 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_SCSI_AACRAID) += aacraid/ obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/ obj-$(CONFIG_SCSI_PM8001) += pm8001/ +obj-$(CONFIG_SCSI_ISCI) += isci/ obj-$(CONFIG_SCSI_IPS) += ips.o obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile new file mode 100644 index 000000000000..34f7af3525f4 --- /dev/null +++ b/drivers/scsi/isci/Makefile @@ -0,0 +1,30 @@ +#TODO kill SCIC_SDS_4_ENABLED it is always true for this +#generation of silicon +EXTRA_CFLAGS += -DSCIC_SDS_4_ENABLED + +#temporary until atapi support ready +EXTRA_CFLAGS += -DDISABLE_ATAPI + +EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/ +obj-$(CONFIG_SCSI_ISCI) += isci.o +isci-objs := init.o phy.o request.o sata.o \ + remote_device.o port.o timers.o deprecated.o \ + host.o task.o events.o \ + core/scic_sds_controller.o \ + core/scic_sds_remote_device.o \ + core/scic_sds_request.o \ + core/scic_sds_stp_request.o \ + core/scic_sds_stp_packet_request.o \ + core/scic_sds_stp_remote_device.o \ + core/scic_sds_port.o \ + core/scic_sds_port_configuration_agent.o \ + core/scic_sds_phy.o \ + core/scic_sds_ssp_request.o \ + core/scic_sds_remote_node_context.o \ + core/scic_sds_smp_request.o \ + core/scic_sds_smp_remote_device.o \ + core/scic_sds_remote_node_table.o \ + core/scic_sds_unsolicited_frame_control.o \ + core/sci_base_memory_descriptor_list.o \ + core/sci_base_state_machine.o \ + core/sci_util.o diff --git a/drivers/scsi/isci/core/intel_ata.h b/drivers/scsi/isci/core/intel_ata.h new file mode 100644 index 000000000000..48b297e50bd0 --- /dev/null +++ b/drivers/scsi/isci/core/intel_ata.h @@ -0,0 +1,554 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file defines all of the ATA related constants, enumerations, and types. + * Please note that this file does not necessarily contain an exhaustive + * list of all constants, commands, sub-commands, etc. + * + * + */ + +#ifndef _ATA_H_ +#define _ATA_H_ + +#include + +/** + * + * + * ATA_COMMAND_CODES These constants depict the various ATA command codes + * defined in the ATA/ATAPI specification. + */ +#define ATA_IDENTIFY_DEVICE 0xEC +#define ATA_CHECK_POWER_MODE 0xE5 +#define ATA_STANDBY 0xE2 +#define ATA_STANDBY_IMMED 0xE0 +#define ATA_IDLE_IMMED 0xE1 +#define ATA_IDLE 0xE3 +#define ATA_FLUSH_CACHE 0xE7 +#define ATA_FLUSH_CACHE_EXT 0xEA +#define ATA_READ_DMA_EXT 0x25 +#define ATA_READ_DMA 0xC8 +#define ATA_READ_SECTORS_EXT 0x24 +#define ATA_READ_SECTORS 0x20 +#define ATA_WRITE_DMA_EXT 0x35 +#define ATA_WRITE_DMA 0xCA +#define ATA_WRITE_SECTORS_EXT 0x34 +#define ATA_WRITE_SECTORS 0x30 +#define ATA_WRITE_UNCORRECTABLE 0x45 +#define ATA_READ_VERIFY_SECTORS 0x40 +#define ATA_READ_VERIFY_SECTORS_EXT 0x42 +#define ATA_READ_BUFFER 0xE4 +#define ATA_WRITE_BUFFER 0xE8 +#define ATA_EXECUTE_DEVICE_DIAG 0x90 +#define ATA_SET_FEATURES 0xEF +#define ATA_SMART 0xB0 +#define ATA_PACKET_IDENTIFY 0xA1 +#define ATA_PACKET 0xA0 +#define ATA_READ_FPDMA 0x60 +#define ATA_WRITE_FPDMA 0x61 +#define ATA_READ_LOG_EXT 0x2F +#define ATA_NOP 0x00 +#define ATA_DEVICE_RESET 0x08 +#define ATA_MEDIA_EJECT 0xED + +/** + * + * + * ATA_SMART_SUB_COMMAND_CODES These constants define the ATA SMART command + * sub-codes that can be executed. + */ +#define ATA_SMART_SUB_CMD_ENABLE 0xD8 +#define ATA_SMART_SUB_CMD_DISABLE 0xD9 +#define ATA_SMART_SUB_CMD_RETURN_STATUS 0xDA +#define ATA_SMART_SUB_CMD_READ_LOG 0xD5 + +/** + * + * + * ATA_SET_FEATURES_SUB_COMMAND_CODES These constants define the ATA SET + * FEATURES command sub-codes that can be executed. + */ +#define ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE 0x02 +#define ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE 0x82 +#define ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD 0x55 +#define ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD 0xAA +#define ATA_SET_FEATURES_SUB_CMD_SET_TRANSFER_MODE 0x3 + +/** + * + * + * ATA_READ_LOG_EXT_PAGE_CODES This is a list of log page codes available for + * use. + */ +#define ATA_LOG_PAGE_NCQ_ERROR 0x10 +#define ATA_LOG_PAGE_SMART_SELF_TEST 0x06 +#define ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST 0x07 + +/** + * + * + * ATA_LOG_PAGE_NCQ_ERROR_CONSTANTS These constants define standard values for + * use when requesting the NCQ error log page. + */ +#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR 0 +#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR_COUNT 1 + +/** + * + * + * ATA_STATUS_REGISTER_BITS The following are status register bit definitions + * per ATA/ATAPI-7. + */ +#define ATA_STATUS_REG_BSY_BIT 0x80 +#define ATA_STATUS_REG_DEVICE_FAULT_BIT 0x20 +#define ATA_STATUS_REG_ERROR_BIT 0x01 + +/** + * + * + * ATA_ERROR_REGISTER_BITS The following are error register bit definitions per + * ATA/ATAPI-7. + */ +#define ATA_ERROR_REG_NO_MEDIA_BIT 0x02 +#define ATA_ERROR_REG_ABORT_BIT 0x04 +#define ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT 0x08 +#define ATA_ERROR_REG_ID_NOT_FOUND_BIT 0x10 +#define ATA_ERROR_REG_MEDIA_CHANGE_BIT 0x20 +#define ATA_ERROR_REG_UNCORRECTABLE_BIT 0x40 +#define ATA_ERROR_REG_WRITE_PROTECTED_BIT 0x40 +#define ATA_ERROR_REG_ICRC_BIT 0x80 + +/** + * + * + * ATA_CONTROL_REGISTER_BITS The following are control register bit definitions + * per ATA/ATAPI-7 + */ +#define ATA_CONTROL_REG_INTERRUPT_ENABLE_BIT 0x02 +#define ATA_CONTROL_REG_SOFT_RESET_BIT 0x04 +#define ATA_CONTROL_REG_HIGH_ORDER_BYTE_BIT 0x80 + +/** + * + * + * ATA_DEVICE_HEAD_REGISTER_BITS The following are device/head register bit + * definitions per ATA/ATAPI-7. + */ +#define ATA_DEV_HEAD_REG_LBA_MODE_ENABLE 0x40 +#define ATA_DEV_HEAD_REG_FUA_ENABLE 0x80 + +/** + * + * + * ATA_IDENTIFY_DEVICE_FIELD_LENGTHS The following constants define the number + * of bytes contained in various fields found in the IDENTIFY DEVICE data + * structure. + */ +#define ATA_IDENTIFY_SERIAL_NUMBER_LEN 20 +#define ATA_IDENTIFY_MODEL_NUMBER_LEN 40 +#define ATA_IDENTIFY_FW_REVISION_LEN 8 +#define ATA_IDENTIFY_48_LBA_LEN 8 +#define ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN 30 +#define ATA_IDENTIFY_WWN_LEN 8 + +/** + * + * + * ATA_IDENTIFY_DEVICE_FIELD_MASKS The following constants define bit masks + * utilized to determine if a feature is supported/enabled or if a bit is + * simply set inside of the IDENTIFY DEVICE data structre. + */ +#define ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE 0x0080 +#define ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE 0x0100 +#define ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE 0x2000 +#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE 0x0001 +#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE 0x0400 +#define ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE 0x0100 +#define ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE 0x0001 +#define ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE 0x0100 +#define ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE 0x001F +#define ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE 0x0100 +#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK 0x000F +#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE 0x2000 +#define ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT 0x0004 +#define ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED 0x0002 + +/** + * + * + * ATAPI_IDENTIFY_DEVICE_FIELD_MASKS These constants define the various bit + * definitions for the fields in the PACKET IDENTIFY DEVICE data structure. + */ +#define ATAPI_IDENTIFY_16BYTE_CMD_PCKT_ENABLE 0x01 + +/** + * + * + * ATA_PACKET_FEATURE_BITS These constants define the various bit definitions + * for the ATA PACKET feature register. + */ +#define ATA_PACKET_FEATURE_DMA 0x01 +#define ATA_PACKET_FEATURE_OVL 0x02 +#define ATA_PACKET_FEATURE_DMADIR 0x04 + +/** + * + * + * ATA_Device_Power_Mode_Values These constants define the power mode values + * returned by ATA_Check_Power_Mode + */ +#define ATA_STANDBY_POWER_MODE 0x00 +#define ATA_IDLE_POWER_MODE 0x80 +#define ATA_ACTIVE_POWER_MODE 0xFF + +/** + * + * + * ATA_WRITE_UNCORRECTIABLE feature field values These constants define the + * Write Uncorrectable feature values used with the SATI translation. + */ +#define ATA_WRITE_UNCORRECTABLE_PSUEDO 0x55 +#define ATA_WRITE_UNCORRECTABLE_FLAGGED 0xAA + + + +/** + * struct ATA_IDENTIFY_DEVICE - This structure depicts the ATA IDENTIFY DEVICE + * data format. + * + * + */ +struct ata_identify_device_data { + u16 general_config_bits; /* word 00 */ + u16 obsolete0; /* word 01 (num cylinders) */ + u16 vendor_specific_config_bits; /* word 02 */ + u16 obsolete1; /* word 03 (num heads) */ + u16 retired1[2]; /* words 04-05 */ + u16 obsolete2; /* word 06 (sectors / track) */ + u16 reserved_for_compact_flash1[2]; /* words 07-08 */ + u16 retired0; /* word 09 */ + u8 serial_number[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; /* word 10-19 */ + u16 retired2[2]; /* words 20-21 */ + u16 obsolete4; /* word 22 */ + u8 firmware_revision[ATA_IDENTIFY_FW_REVISION_LEN]; /* words 23-26 */ + u8 model_number[ATA_IDENTIFY_MODEL_NUMBER_LEN]; /* words 27-46 */ + u16 max_sectors_per_multiple; /* word 47 */ + u16 reserved0; /* word 48 */ + u16 capabilities1; /* word 49 */ + u16 capabilities2; /* word 50 */ + u16 obsolete5[2]; /* words 51-52 */ + u16 validity_bits; /* word 53 */ + u16 obsolete6[5]; /* + * words 54-58 Used to be: + * current cylinders, + * current heads, + * current sectors/Track, + * current capacity */ + u16 current_max_sectors_per_multiple; /* word 59 */ + u8 total_num_sectors[4]; /* words 60-61 */ + u16 obsolete7; /* word 62 */ + u16 multi_word_dma_mode; /* word 63 */ + u16 pio_modes_supported; /* word 64 */ + u16 min_multiword_dma_transfer_cycle; /* word 65 */ + u16 rec_min_multiword_dma_transfer_cycle; /* word 66 */ + u16 min_pio_transfer_no_flow_ctrl; /* word 67 */ + u16 min_pio_transfer_with_flow_ctrl; /* word 68 */ + u16 reserved1[2]; /* words 69-70 */ + u16 reserved2[4]; /* words 71-74 */ + u16 queue_depth; /* word 75 */ + u16 serial_ata_capabilities; /* word 76 */ + u16 serial_ata_reserved; /* word 77 */ + u16 serial_ata_features_supported; /* word 78 */ + u16 serial_ata_features_enabled; /* word 79 */ + u16 major_version_number; /* word 80 */ + u16 minor_version_number; /* word 81 */ + u16 command_set_supported0; /* word 82 */ + u16 command_set_supported1; /* word 83 */ + u16 command_set_supported_extention; /* word 84 */ + u16 command_set_enabled0; /* word 85 */ + u16 command_set_enabled1; /* word 86 */ + u16 command_set_default; /* word 87 */ + u16 ultra_dma_mode; /* word 88 */ + u16 security_erase_completion_time; /* word 89 */ + u16 enhanced_security_erase_time; /* word 90 */ + u16 current_power_mgmt_value; /* word 91 */ + u16 master_password_revision; /* word 92 */ + u16 hardware_reset_result; /* word 93 */ + u16 current_acoustic_management_value; /* word 94 */ + u16 stream_min_request_size; /* word 95 */ + u16 stream_transfer_time; /* word 96 */ + u16 stream_access_latency; /* word 97 */ + u16 stream_performance_granularity[2]; /* words 98-99 */ + u8 max_48bit_lba[ATA_IDENTIFY_48_LBA_LEN]; /* words 100-103 */ + u16 streaming_transfer_time; /* word 104 */ + u16 reserved3; /* word 105 */ + u16 physical_logical_sector_info; /* word 106 */ + u16 acoustic_test_interseek_delay; /* word 107 */ + u8 world_wide_name[ATA_IDENTIFY_WWN_LEN]; /* words 108-111 */ + u8 reserved_for_wwn_extention[ATA_IDENTIFY_WWN_LEN]; /* words 112-115 */ + u16 reserved4; /* word 116 */ + u8 words_per_logical_sector[4]; /* words 117-118 */ + u16 command_set_supported2; /* word 119 */ + u16 reserved5[7]; /* words 120-126 */ + u16 removable_media_status; /* word 127 */ + u16 security_status; /* word 128 */ + u16 vendor_specific1[31]; /* words 129-159 */ + u16 cfa_power_mode1; /* word 160 */ + u16 reserved_for_compact_flash2[7]; /* words 161-167 */ + u16 device_nominal_form_factor; /* word 168 */ + u16 reserved_for_compact_flash3[7]; /* words 169-175 */ + u16 current_media_serial_number[ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN]; /* words 176-205 */ + u16 reserved6[3]; /* words 206-208 */ + u16 logical_sector_alignment; /* words 209 */ + u16 reserved7[7]; /* words 210-216 */ + u16 nominal_media_rotation_rate; /* word 217 */ + u16 reserved8[37]; /* words 218-254 */ + u16 integrity_word; /* word 255 */ + +}; + +#define ATA_IDENTIFY_DEVICE_GET_OFFSET(field_name) \ + ((unsigned long)&(((struct ata_identify_device_data *)0)->field_name)) +#define ATA_IDENTIFY_DEVICE_WCE_ENABLE 0x20 +#define ATA_IDENTIFY_DEVICE_RA_ENABLE 0x40 + +/** + * struct ATAPI_IDENTIFY_PACKET_DATA - The following structure depicts the + * ATA-ATAPI 7 version of the IDENTIFY PACKET DEVICE data structure. + * + * + */ +struct atapi_identify_packet_device { + u16 generalConfigBits; /* word 00 */ + u16 reserved0; /* word 01 (num cylinders) */ + u16 uniqueConfigBits; /* word 02 */ + u16 reserved1[7]; /* words 03 - 09 */ + u8 serialNumber[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; /* word 10-19 */ + u16 reserved2[3]; /* words 20-22 */ + u8 firmwareRevision[ATA_IDENTIFY_FW_REVISION_LEN]; /* words 23-26 */ + u8 modelNumber[ATA_IDENTIFY_MODEL_NUMBER_LEN]; /* words 27-46 */ + u16 reserved4[2]; /* words 47-48 */ + u16 capabilities1; /* word 49 */ + u16 capabilities2; /* word 50 */ + u16 obsolete0[2]; /* words 51-52 */ + u16 validityBits; /* word 53 */ + u16 reserved[8]; /* words 54-61 */ + + u16 DMADIRBitRequired; /* word 62, page2 */ + u16 multiWordDmaMode; /* word 63 */ + u16 pioModesSupported; /* word 64 */ + u16 minMultiwordDmaTransferCycle; /* word 65 */ + u16 recMinMultiwordDmaTransferCycle; /* word 66 */ + u16 minPioTransferNoFlowCtrl; /* word 67 */ + u16 minPioTransferWithFlowCtrl; /* word 68 */ + u16 reserved6[2]; /* words 69-70 */ + u16 nsFromPACKETReceiptToBusRelease; /* word 71 */ + u16 nsFromSERVICEReceiptToBSYreset; /* wore 72 */ + u16 reserved7[2]; /* words 73-74 */ + u16 queueDepth; /* word 75 */ + u16 serialAtaCapabilities; /* word 76 */ + u16 serialAtaReserved; /* word 77 */ + u16 serialAtaFeaturesSupported; /* word 78 */ + u16 serialAtaFeaturesEnabled; /* word 79 */ + + u16 majorVersionNumber; /* word 80, page3 */ + u16 minorVersionNumber; /* word 81 */ + u16 commandSetSupported0; /* word 82 */ + u16 commandSetSupported1; /* word 83 */ + + u16 commandSetSupportedExtention; /* word 84, page4 */ + u16 commandSetEnabled0; /* word 85 */ + u16 commandSetEnabled1; /* word 86 */ + u16 commandSetDefault; /* word 87 */ + + u16 ultraDmaMode; /* word 88, page5 */ + u16 reserved8[4]; /* words 89 - 92 */ + + u16 hardwareResetResult; /* word 93, page6 */ + u16 currentAcousticManagementValue; /* word 94 */ + u16 reserved9[30]; /* words 95-124 */ + u16 ATAPIByteCount0Behavior; /* word 125 */ + u16 obsolete1; /* word 126 */ + u16 removableMediaStatus; /* word 127, */ + + u16 securityStatus; /* word 128, page7 */ + u16 vendorSpecific1[31]; /* words 129-159 */ + u16 reservedForCompactFlash[16]; /* words 160-175 */ + u16 reserved10[79]; /* words 176-254 */ + u16 integrityWord; /* word 255 */ +}; + +/** + * struct ata_extended_smart_self_test_log - The following structure depicts + * the ATA-8 version of the Extended SMART self test log page descriptor + * entry. + * + * + */ +union ata_descriptor_entry { + struct DESCRIPTOR_ENTRY { + u8 lba_field; + u8 status_byte; + u8 time_stamp_low; + u8 time_stamp_high; + u8 checkpoint_byte; + u8 failing_lba_low; + u8 failing_lba_mid; + u8 failing_lba_high; + u8 failing_lba_low_ext; + u8 failing_lba_mid_ext; + u8 failing_lba_high_ext; + + u8 vendor_specific1; + u8 vendor_specific2; + u8 vendor_specific3; + u8 vendor_specific4; + u8 vendor_specific5; + u8 vendor_specific6; + u8 vendor_specific7; + u8 vendor_specific8; + u8 vendor_specific9; + u8 vendor_specific10; + u8 vendor_specific11; + u8 vendor_specific12; + u8 vendor_specific13; + u8 vendor_specific14; + u8 vendor_specific15; + } DESCRIPTOR_ENTRY; + + u8 descriptor_entry[26]; + +}; + +/** + * struct ata_extended_smart_self_test_log - The following structure depicts + * the ATA-8 version of the SMART self test log page descriptor entry. + * + * + */ +union ata_smart_descriptor_entry { + struct SMART_DESCRIPTOR_ENTRY { + u8 lba_field; + u8 status_byte; + u8 time_stamp_low; + u8 time_stamp_high; + u8 checkpoint_byte; + u8 failing_lba_low; + u8 failing_lba_mid; + u8 failing_lba_high; + u8 failing_lba_low_ext; + + u8 vendor_specific1; + u8 vendor_specific2; + u8 vendor_specific3; + u8 vendor_specific4; + u8 vendor_specific5; + u8 vendor_specific6; + u8 vendor_specific7; + u8 vendor_specific8; + u8 vendor_specific9; + u8 vendor_specific10; + u8 vendor_specific11; + u8 vendor_specific12; + u8 vendor_specific13; + u8 vendor_specific14; + u8 vendor_specific15; + } SMART_DESCRIPTOR_ENTRY; + + u8 smart_descriptor_entry[24]; + +}; + +/** + * struct ata_extended_smart_self_test_log - The following structure depicts + * the ATA-8 version of the Extended SMART self test log page. + * + * + */ +struct ata_extended_smart_self_test_log { + u8 self_test_log_data_structure_revision_number; /* byte 0 */ + u8 reserved0; /* byte 1 */ + u8 self_test_descriptor_index[2]; /* byte 2-3 */ + + union ata_descriptor_entry descriptor_entrys[19]; /* bytes 4-497 */ + + u8 vendor_specific[2]; /* byte 498-499 */ + u8 reserved1[11]; /* byte 500-510 */ + u8 data_structure_checksum; /* byte 511 */ + +}; + +/** + * struct ata_extended_smart_self_test_log - The following structure depicts + * the ATA-8 version of the SMART self test log page. + * + * + */ +struct ata_smart_self_test_log { + u8 self_test_log_data_structure_revision_number[2]; /* bytes 0-1 */ + + union ata_smart_descriptor_entry descriptor_entrys[21]; /* bytes 2-505 */ + + u8 vendor_specific[2]; /* byte 506-507 */ + u8 self_test_index; /* byte 508 */ + u8 reserved1[2]; /* byte 509-510 */ + u8 data_structure_checksum; /* byte 511 */ + +}; + +#endif /* _ATA_H_ */ + diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h new file mode 100644 index 000000000000..eb9686ea35f1 --- /dev/null +++ b/drivers/scsi/isci/core/intel_sas.h @@ -0,0 +1,948 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _INTEL_SAS_H_ +#define _INTEL_SAS_H_ + +/** + * This file contains all of the definitions relating to structures, constants, + * etc. defined by the SAS specification. + * + * + */ + +#include "intel_sata.h" +#include "intel_scsi.h" + +/** + * struct sci_sas_address - This structure depicts how a SAS address is + * represented by SCI. + * + * + */ +struct sci_sas_address { + /** + * This member contains the higher 32-bits of the SAS address. + */ + u32 high; + + /** + * This member contains the lower 32-bits of the SAS address. + */ + u32 low; + +}; + +/** + * struct sci_sas_identify_address_frame_protocols - This structure depicts the + * contents of bytes 2 and 3 in the SAS IDENTIFY ADDRESS FRAME (IAF). + * + * For specific information on each of these individual fields please reference + * the SAS specification Link layer section on address frames. + */ +struct sci_sas_identify_address_frame_protocols { + union { + struct { + u16 restricted1:1; + u16 smp_initiator:1; + u16 stp_initiator:1; + u16 ssp_initiator:1; + u16 reserved3:4; + u16 restricted2:1; + u16 smp_target:1; + u16 stp_target:1; + u16 ssp_target:1; + u16 reserved4:4; + } bits; + + u16 all; + } u; + +}; + +/** + * struct sci_sas_identify_address_frame - This structure depicts the contents + * of the SAS IDENTIFY ADDRESS FRAME (IAF). + * + * For specific information on each of these individual fields please reference + * the SAS specification Link layer section on address frames. + */ +struct sci_sas_identify_address_frame { + u16 address_frame_type:4; + u16 device_type:3; + u16 reserved1:1; + u16 reason:4; + u16 reserved2:4; + + struct sci_sas_identify_address_frame_protocols protocols; + + struct sci_sas_address device_name; + struct sci_sas_address sas_address; + + u32 phy_identifier:8; + u32 break_reply_capable:1; + u32 requested_in_zpsds:1; + u32 in_zpsds_persistent:1; + u32 reserved5:21; + + u32 reserved6[4]; + +}; + +/** + * struct sas_capabilities - This structure depicts the various SAS + * capabilities supported by the directly attached target device. For + * specific information on each of these individual fields please reference + * the SAS specification Phy layer section on speed negotiation windows. + * + * + */ +struct sas_capabilities { + union { +#if defined (SCIC_SDS_4_ENABLED) + struct { + /** + * The SAS specification indicates the start bit shall always be set to + * 1. This implementation will have the start bit set to 0 if the + * PHY CAPABILITIES were either not received or speed negotiation failed. + */ + u32 start:1; + u32 tx_ssc_type:1; + u32 reserved1:2; + u32 requested_logical_link_rate:4; + + u32 gen1_without_ssc_supported:1; + u32 gen1_with_ssc_supported:1; + u32 gen2_without_ssc_supported:1; + u32 gen2_with_ssc_supported:1; + u32 gen3_without_ssc_supported:1; + u32 gen3_with_ssc_supported:1; + u32 reserved2:17; + u32 parity:1; + } bits; +#endif /* (SCIC_SDS_4_ENABLED) */ + + u32 all; + } u; + +}; + +/** + * enum _SCI_SAS_LINK_RATE - This enumeration depicts the SAS specification + * defined link speeds. + * + * + */ +enum sci_sas_link_rate { + SCI_SAS_NO_LINK_RATE = 0, + SCI_SATA_SPINUP_HOLD = 0x3, + SCI_SAS_150_GB = 0x8, + SCI_SAS_300_GB = 0x9, + SCI_SAS_600_GB = 0xA +}; + +/** + * enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS + * specification defined task attribute values for a command information + * unit. + * + * + */ +enum sci_sas_task_attribute { + SCI_SAS_SIMPLE_ATTRIBUTE = 0, + SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE = 1, + SCI_SAS_ORDERED_ATTRIBUTE = 2, + SCI_SAS_ACA_ATTRIBUTE = 4, +}; + +/** + * enum _SCI_SAS_TASK_MGMT_FUNCTION - This enumeration depicts the SAM/SAS + * specification defined task management functions. + * + * This HARD_RESET function listed here is not actually defined as a task + * management function in the industry standard. + */ +enum sci_sas_task_mgmt_function { + SCI_SAS_ABORT_TASK = SCSI_TASK_REQUEST_ABORT_TASK, + SCI_SAS_ABORT_TASK_SET = SCSI_TASK_REQUEST_ABORT_TASK_SET, + SCI_SAS_CLEAR_TASK_SET = SCSI_TASK_REQUEST_CLEAR_TASK_SET, + SCI_SAS_LOGICAL_UNIT_RESET = SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET, + SCI_SAS_I_T_NEXUS_RESET = SCSI_TASK_REQUEST_I_T_NEXUS_RESET, + SCI_SAS_CLEAR_ACA = SCSI_TASK_REQUEST_CLEAR_ACA, + SCI_SAS_QUERY_TASK = SCSI_TASK_REQUEST_QUERY_TASK, + SCI_SAS_QUERY_TASK_SET = SCSI_TASK_REQUEST_QUERY_TASK_SET, + SCI_SAS_QUERY_ASYNCHRONOUS_EVENT = SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION, + SCI_SAS_HARD_RESET = 0xFF +}; + + +/** + * enum _SCI_SAS_FRAME_TYPE - This enumeration depicts the SAS specification + * defined SSP frame types. + * + * + */ +enum sci_sas_frame_type { + SCI_SAS_DATA_FRAME = 0x01, + SCI_SAS_XFER_RDY_FRAME = 0x05, + SCI_SAS_COMMAND_FRAME = 0x06, + SCI_SAS_RESPONSE_FRAME = 0x07, + SCI_SAS_TASK_FRAME = 0x16 +}; + +/** + * struct sci_ssp_command_iu - This structure depicts the contents of the SSP + * COMMAND INFORMATION UNIT. For specific information on each of these + * individual fields please reference the SAS specification SSP transport + * layer section. + * + * + */ +struct sci_ssp_command_iu { + u32 lun_upper; + u32 lun_lower; + + u32 additional_cdb_length:6; + u32 reserved0:2; + u32 reserved1:8; + u32 enable_first_burst:1; + u32 task_priority:4; + u32 task_attribute:3; + u32 reserved2:8; + + u32 cdb[4]; + +}; + +/** + * struct sci_ssp_task_iu - This structure depicts the contents of the SSP TASK + * INFORMATION UNIT. For specific information on each of these individual + * fields please reference the SAS specification SSP transport layer section. + * + * + */ +struct sci_ssp_task_iu { + u32 lun_upper; + u32 lun_lower; + + u32 reserved0:8; + u32 task_function:8; + u32 reserved1:8; + u32 reserved2:8; + + u32 reserved3:16; + u32 task_tag:16; + + u32 reserved4[3]; + +}; + +#define SSP_RESPONSE_IU_MAX_DATA 64 + +#define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK (0x03) + + +#define sci_ssp_get_sense_data_length(sense_data_length_buffer) \ + SCIC_BUILD_DWORD(sense_data_length_buffer) + +#define sci_ssp_get_response_data_length(response_data_length_buffer) \ + SCIC_BUILD_DWORD(response_data_length_buffer) + +/** + * struct sci_ssp_response_iu - This structure depicts the contents of the SSP + * RESPONSE INFORMATION UNIT. For specific information on each of these + * individual fields please reference the SAS specification SSP transport + * layer section. + * + * + */ +struct sci_ssp_response_iu { + u8 reserved0[8]; + + u8 retry_delay_timer[2]; + u8 data_present; + u8 status; + + u8 reserved1[4]; + u8 sense_data_length[4]; + u8 response_data_length[4]; + + u32 data[SSP_RESPONSE_IU_MAX_DATA]; + +}; + +/** + * enum _SCI_SAS_DATA_PRESENT_TYPE - This enumeration depicts the SAS + * specification defined SSP data present types in struct sci_ssp_response_iu. + * + * + */ +enum sci_ssp_response_iu_data_present_type { + SCI_SSP_RESPONSE_IU_NO_DATA = 0x00, + SCI_SSP_RESPONSE_IU_RESPONSE_DATA = 0x01, + SCI_SSP_RESPONSE_IU_SENSE_DATA = 0x02 +}; + +/** + * struct sci_ssp_frame_header - This structure depicts the contents of an SSP + * frame header. For specific information on the individual fields please + * reference the SAS specification transport layer SSP frame format. + * + * + */ +struct sci_ssp_frame_header { + /* Word 0 */ + u32 hashed_destination_address:24; + u32 frame_type:8; + + /* Word 1 */ + u32 hashed_source_address:24; + u32 reserved1_0:8; + + /* Word 2 */ + u32 reserved2_2:6; + u32 fill_bytes:2; + u32 reserved2_1:3; + u32 tlr_control:2; + u32 retry_data_frames:1; + u32 retransmit:1; + u32 changing_data_pointer:1; + u32 reserved2_0:16; + + /* Word 3 */ + u32 uiResv4; + + /* Word 4 */ + u16 target_port_transfer_tag; + u16 tag; + + /* Word 5 */ + u32 data_offset; + +}; + +/** + * struct smp_request_header - This structure defines the contents of an SMP + * Request header. + * + * For specific information on each of these individual fields please reference + * the SAS specification. + */ +struct smp_request_header { + u8 smp_frame_type; /* byte 0 */ + u8 function; /* byte 1 */ + u8 allocated_response_length; /* byte 2 */ + u8 request_length; /* byte 3 */ +}; + +/** + * struct smp_response_header - This structure depicts the contents of the SAS + * SMP DISCOVER RESPONSE frame. For specific information on each of these + * individual fields please reference the SAS specification Link layer + * section on address frames. + * + * + */ +struct smp_response_header { + u8 smp_frame_type; /* byte 0 */ + u8 function; /* byte 1 */ + u8 function_result; /* byte 2 */ + u8 response_length; /* byte 3 */ +}; + +/** + * struct smp_request_general - This structure defines the contents of an SMP + * Request that is comprised of the struct smp_request_header and a CRC. + * + * For specific information on each of these individual fields please reference + * the SAS specification. + */ +struct smp_request_general { + u32 crc; /* bytes 4-7 */ + +}; + +/** + * struct smp_request_phy_identifier - This structure defines the contents of + * an SMP Request that is comprised of the struct smp_request_header and a phy + * identifier. Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA. + * + * For specific information on each of these individual fields please reference + * the SAS specification. + */ +struct smp_request_phy_identifier { + u32 reserved_byte4_7; /* bytes 4-7 */ + + u32 ignore_zone_group:1; /* byte 8 */ + u32 reserved_byte8:7; + + u32 phy_identifier:8; /* byte 9 */ + u32 reserved_byte10:8; /* byte 10 */ + u32 reserved_byte11:8; /* byte 11 */ + +}; + +/** + * struct smp_request_configure_route_information - This structure defines the + * contents of an SMP Configure Route Information request. + * + * For specific information on each of these individual fields please reference + * the SAS specification. + */ +struct smp_request_configure_route_information { + u32 expected_expander_change_count:16; /* bytes 4-5 */ + u32 expander_route_index_high:8; + u32 expander_route_index:8; /* bytes 6-7 */ + + u32 reserved_byte8:8; /* bytes 8 */ + u32 phy_identifier:8; /* bytes 9 */ + u32 reserved_byte_10_11:16; /* bytes 10-11 */ + + u32 reserved_byte_12_bit_0_6:7; + u32 disable_route_entry:1; /* byte 12 */ + u32 reserved_byte_13_15:24; /* bytes 13-15 */ + + u32 routed_sas_address[2]; /* bytes 16-23 */ + u8 reserved_byte_24_39[16]; /* bytes 24-39 */ + +}; + +/** + * struct smp_request_phy_control - This structure defines the contents of an + * SMP Phy Controler request. + * + * For specific information on each of these individual fields please reference + * the SAS specification. + */ +struct smp_request_phy_control { + u16 expected_expander_change_count; /* byte 4-5 */ + + u16 reserved_byte_6_7; /* byte 6-7 */ + u8 reserved_byte_8; /* byte 8 */ + + u8 phy_identifier; /* byte 9 */ + u8 phy_operation; /* byte 10 */ + + u8 update_partial_pathway_timeout_value:1; + u8 reserved_byte_11_bit_1_7:7; /* byte 11 */ + + u8 reserved_byte_12_23[12]; /* byte 12-23 */ + + u8 attached_device_name[8]; /* byte 24-31 */ + + u8 reserved_byte_32_bit_3_0:4; /* byte 32 */ + u8 programmed_minimum_physical_link_rate:4; + + u8 reserved_byte_33_bit_3_0:4; /* byte 33 */ + u8 programmed_maximum_physical_link_rate:4; + + u16 reserved_byte_34_35; /* byte 34-35 */ + + u8 partial_pathway_timeout_value:4; + u8 reserved_byte_36_bit_4_7:4; /* byte 36 */ + + u16 reserved_byte_37_38; /* byte 37-38 */ + u8 reserved_byte_39; /* byte 39 */ + +}; + +/** + * struct smp_request_vendor_specific - This structure depicts the vendor + * specific space for SMP request. + * + * + */ + #define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016 +struct smp_request_vendor_specific { + u8 request_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH]; +}; + +/** + * struct smp_request - This structure simply unionizes the existing request + * structures into a common request type. + * + * + */ +struct smp_request { + struct smp_request_header header; + + union { /* bytes 4-N */ + struct smp_request_general report_general; + struct smp_request_phy_identifier discover; + struct smp_request_general report_manufacturer_information; + struct smp_request_phy_identifier report_phy_sata; + struct smp_request_phy_control phy_control; + struct smp_request_phy_identifier report_phy_error_log; + struct smp_request_phy_identifier report_route_information; + struct smp_request_configure_route_information configure_route_information; + struct smp_request_vendor_specific vendor_specific_request; + } request; + +}; + + +/** + * struct smp_response_report_general - This structure depicts the SMP Report + * General for expander devices. It adheres to the SAS-2.1 specification. + * + * For specific information on each of these individual fields please reference + * the SAS specification Application layer section on SMP. + */ +struct smp_response_report_general { + u16 expander_change_count; /* byte 4-5 */ + u16 expander_route_indexes; /* byte 6-7 */ + + u32 reserved_byte8:7; /* byte 8 bit 0-6 */ + u32 long_response:1; /* byte 8 bit 7 */ + + u32 number_of_phys:8; /* byte 9 */ + + u32 configurable_route_table:1; /* byte 10 */ + u32 configuring:1; + u32 configures_others:1; + u32 open_reject_retry_supported:1; + u32 stp_continue_awt:1; + u32 self_configuring:1; + u32 zone_configuring:1; + u32 table_to_table_supported:1; + + u32 reserved_byte11:8; /* byte 11 */ + + u32 enclosure_logical_identifier_high; /* byte 12-15 */ + u32 enclosure_logical_identifier_low; /* byte 16-19 */ + + u32 reserved_byte20_23; + u32 reserved_byte24_27; + +}; + +struct smp_response_report_general_long { + struct smp_response_report_general sas1_1; + + struct { + u16 reserved1; + u16 stp_bus_inactivity_time_limit; + u16 stp_max_connect_time_limit; + u16 stp_smp_i_t_nexus_loss_time; + + u32 zoning_enabled:1; + u32 zoning_supported:1; + u32 physicaL_presence_asserted:1; + u32 zone_locked:1; + u32 reserved2:1; + u32 num_zone_groups:3; + u32 saving_zoning_enabled_supported:3; + u32 saving_zone_perms_table_supported:1; + u32 saving_zone_phy_info_supported:1; + u32 saving_zone_manager_password_supported:1; + u32 saving:1; + u32 reserved3:1; + u32 max_number_routed_sas_addresses:16; + + struct sci_sas_address active_zone_manager_sas_address; + + u16 zone_lock_inactivity_time_limit; + u16 reserved4; + + u8 reserved5; + u8 first_enclosure_connector_element_index; + u8 number_of_enclosure_connector_element_indices; + u8 reserved6; + + u32 reserved7:7; + u32 reduced_functionality:1; + u32 time_to_reduce_functionality:8; + u32 initial_time_to_reduce_functionality:8; + u8 max_reduced_functionality_time; + + u16 last_self_config_status_descriptor_index; + u16 max_number_of_stored_self_config_status_descriptors; + + u16 last_phy_event_list_descriptor_index; + u16 max_number_of_stored_phy_event_list_descriptors; + } sas2; + +}; + +/** + * struct smp_response_report_manufacturer_information - This structure depicts + * the SMP report manufacturer information for expander devices. It adheres + * to the SAS-2.1 specification. + * + * For specific information on each of these individual fields please reference + * the SAS specification Application layer section on SMP. + */ +struct smp_response_report_manufacturer_information { + u32 expander_change_count:16; /* bytes 4-5 */ + u32 reserved1:16; + + u32 sas1_1_format:1; + u32 reserved2:31; + + u8 vendor_id[8]; + u8 product_id[16]; + u8 product_revision_level[4]; + u8 component_vendor_id[8]; + u8 component_id[2]; + u8 component_revision_level; + u8 reserved3; + u8 vendor_specific[8]; + +}; + +#define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52 +#define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE 116 + +/** + * struct smp_discover_response_protocols - This structure depicts the discover + * response where the supported protocols by the remote phy are specified. + * + * For specific information on each of these individual fields please reference + * the SAS specification Link layer section on address frames. + */ +struct smp_discover_response_protocols { + union { + struct { + u16 attached_sata_host:1; + u16 attached_smp_initiator:1; + u16 attached_stp_initiator:1; + u16 attached_ssp_initiator:1; + u16 reserved3:4; + u16 attached_sata_device:1; + u16 attached_smp_target:1; + u16 attached_stp_target:1; + u16 attached_ssp_target:1; + u16 reserved4:3; + u16 attached_sata_port_selector:1; + } bits; + + u16 all; + } u; + +}; + +/** + * struct SMP_RESPONSE_DISCOVER_FORMAT - This structure defines the SMP phy + * discover response format. It handles both SAS1.1 and SAS 2 definitions. + * The unions indicate locations where the SAS specification versions differ + * from one another. + * + * + */ +struct smp_response_discover { + + union { + struct { + u8 reserved[2]; + } sas1_1; + + struct { + u16 expander_change_count; + } sas2; + + } u1; + + u8 reserved1[3]; + u8 phy_identifier; + u8 reserved2[2]; + + union { + struct { + u16 reserved1:4; + u16 attached_device_type:3; + u16 reserved2:1; + u16 negotiated_physical_link_rate:4; + u16 reserved3:4; + } sas1_1; + + struct { + u16 attached_reason:4; + u16 attached_device_type:3; + u16 reserved2:1; + u16 negotiated_logical_link_rate:4; + u16 reserved3:4; + } sas2; + + } u2; + + struct smp_discover_response_protocols protocols; + struct sci_sas_address sas_address; + struct sci_sas_address attached_sas_address; + + u8 attached_phy_identifier; + + union { + struct { + u8 reserved; + } sas1_1; + + struct { + u8 attached_break_reply_capable:1; + u8 attached_requested_inside_zpsds:1; + u8 attached_inside_zpsds_persistent:1; + u8 reserved1:5; + } sas2; + + } u3; + + u8 reserved_for_identify[6]; + + u32 hardware_min_physical_link_rate:4; + u32 programmed_min_physical_link_rate:4; + u32 hardware_max_physical_link_rate:4; + u32 programmed_max_physical_link_rate:4; + u32 phy_change_count:8; + u32 partial_pathway_timeout_value:4; + u32 reserved5:3; + u32 virtual_phy:1; + + u32 routing_attribute:4; + u32 reserved6:4; + u32 connector_type:7; + u32 reserved7:1; + u32 connector_element_index:8; + u32 connector_physical_link:8; + + u16 reserved8; + u16 vendor_specific; + + union { + struct { + /** + * In the SAS 1.1 specification this structure ends after 52 bytes. + * As a result, the contents of this field should never have a + * real value. It is undefined. + */ + u8 undefined[SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE + - SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE]; + } sas1_1; + + struct { + struct sci_sas_address attached_device_name; + + u32 zoning_enabled:1; + u32 inside_zpsds:1; + u32 zone_group_persistent:1; + u32 reserved1:1; + u32 requested_inside_zpsds:1; + u32 inside_zpsds_persistent:1; + u32 requested_inside_zpsds_changed_by_expander:1; + u32 reserved2:1; + u32 reserved_for_zoning_fields:16; + u32 zone_group:8; + + u8 self_configuration_status; + u8 self_configuration_levels_completed; + u16 reserved_for_self_config_fields; + + struct sci_sas_address self_configuration_sas_address; + + u32 programmed_phy_capabilities; + u32 current_phy_capabilities; + u32 attached_phy_capabilities; + + u32 reserved3; + + u32 reserved4:16; + u32 negotiated_physical_link_rate:4; + u32 reason:4; + u32 hardware_muxing_supported:1; + u32 negotiated_ssc:1; + u32 reserved5:6; + + u32 default_zoning_enabled:1; + u32 reserved6:1; + u32 default_zone_group_persistent:1; + u32 reserved7:1; + u32 default_requested_inside_zpsds:1; + u32 default_inside_zpsds_persistent:1; + u32 reserved8:2; + u32 reserved9:16; + u32 default_zone_group:8; + + u32 saved_zoning_enabled:1; + u32 reserved10:1; + u32 saved_zone_group_persistent:1; + u32 reserved11:1; + u32 saved_requested_inside_zpsds:1; + u32 saved_inside_zpsds_persistent:1; + u32 reserved12:18; + u32 saved_zone_group:8; + + u32 reserved14:2; + u32 shadow_zone_group_persistent:1; + u32 reserved15:1; + u32 shadow_requested_inside_zpsds:1; + u32 shadow_inside_zpsds_persistent:1; + u32 reserved16:18; + u32 shadow_zone_group:8; + + u8 device_slot_number; + u8 device_slot_group_number; + u8 device_slot_group_output_connector[6]; + } sas2; + + } u4; + +}; + +/** + * struct smp_response_report_phy_sata - This structure depicts the contents of + * the SAS SMP REPORT PHY SATA frame. For specific information on each of + * these individual fields please reference the SAS specification Link layer + * section on address frames. + * + * + */ +struct smp_response_report_phy_sata { + u32 ignored_byte_4_7; /* bytes 4-7 */ + + u32 affiliations_valid:1; + u32 affiliations_supported:1; + u32 reserved_byte11:6; /* byte 11 */ + u32 ignored_byte10:8; /* byte 10 */ + u32 phy_identifier:8; /* byte 9 */ + u32 reserved_byte_8:8; /* byte 8 */ + + u32 reserved_12_15; + u32 stp_sas_address[2]; + u8 device_to_host_fis[20]; + u32 reserved_44_47; + u32 affiliated_stp_initiator_sas_address[2]; + +}; + +struct smp_response_vendor_specific { + u8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH]; +}; + +union smp_response_body { + struct smp_response_report_general report_general; + struct smp_response_report_manufacturer_information report_manufacturer_information; + struct smp_response_discover discover; + struct smp_response_report_phy_sata report_phy_sata; + struct smp_response_vendor_specific vendor_specific_response; +}; + +/** + * struct smp_response - This structure simply unionizes the existing response + * structures into a common response type. + * + * + */ +struct smp_response { + struct smp_response_header header; + + union smp_response_body response; + +}; + +/* SMP Request Functions */ +#define SMP_FUNCTION_REPORT_GENERAL 0x00 +#define SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION 0x01 +#define SMP_FUNCTION_DISCOVER 0x10 +#define SMP_FUNCTION_REPORT_PHY_ERROR_LOG 0x11 +#define SMP_FUNCTION_REPORT_PHY_SATA 0x12 +#define SMP_FUNCTION_REPORT_ROUTE_INFORMATION 0X13 +#define SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION 0X90 +#define SMP_FUNCTION_PHY_CONTROL 0x91 +#define SMP_FUNCTION_PHY_TEST 0x92 + +#define SMP_FRAME_TYPE_REQUEST 0x40 +#define SMP_FRAME_TYPE_RESPONSE 0x41 + +#define PHY_OPERATION_NOP 0x00 +#define PHY_OPERATION_LINK_RESET 0x01 +#define PHY_OPERATION_HARD_RESET 0x02 +#define PHY_OPERATION_DISABLE 0x03 +#define PHY_OPERATION_CLEAR_ERROR_LOG 0x05 +#define PHY_OPERATION_CLEAR_AFFILIATION 0x06 + +#define NPLR_PHY_ENABLED_UNK_LINK_RATE 0x00 +#define NPLR_PHY_DISABLED 0x01 +#define NPLR_PHY_ENABLED_SPD_NEG_FAILED 0x02 +#define NPLR_PHY_ENABLED_SATA_HOLD 0x03 +#define NPLR_PHY_ENABLED_1_5G 0x08 +#define NPLR_PHY_ENABLED_3_0G 0x09 + +/* SMP Function Result values. */ +#define SMP_RESULT_FUNCTION_ACCEPTED 0x00 +#define SMP_RESULT_UNKNOWN_FUNCTION 0x01 +#define SMP_RESULT_FUNCTION_FAILED 0x02 +#define SMP_RESULT_INVALID_REQUEST_FRAME_LEN 0x03 +#define SMP_RESULT_INAVALID_EXPANDER_CHANGE_COUNT 0x04 +#define SMP_RESULT_BUSY 0x05 +#define SMP_RESULT_INCOMPLETE_DESCRIPTOR_LIST 0x06 +#define SMP_RESULT_PHY_DOES_NOT_EXIST 0x10 +#define SMP_RESULT_INDEX_DOES_NOT_EXIST 0x11 +#define SMP_RESULT_PHY_DOES_NOT_SUPPORT_SATA 0x12 +#define SMP_RESULT_UNKNOWN_PHY_OPERATION 0x13 +#define SMP_RESULT_UNKNOWN_PHY_TEST_FUNCTION 0x14 +#define SMP_RESULT_PHY_TEST_IN_PROGRESS 0x15 +#define SMP_RESULT_PHY_VACANT 0x16 + +/* Attached Device Types */ +#define SMP_NO_DEVICE_ATTACHED 0 +#define SMP_END_DEVICE_ONLY 1 +#define SMP_EDGE_EXPANDER_DEVICE 2 +#define SMP_FANOUT_EXPANDER_DEVICE 3 + +/* Expander phy routine attribute */ +#define DIRECT_ROUTING_ATTRIBUTE 0 +#define SUBTRACTIVE_ROUTING_ATTRIBUTE 1 +#define TABLE_ROUTING_ATTRIBUTE 2 + +#endif /* _INTEL_SAS_H_ */ + diff --git a/drivers/scsi/isci/core/intel_sat.h b/drivers/scsi/isci/core/intel_sat.h new file mode 100644 index 000000000000..c4d78ed35cf1 --- /dev/null +++ b/drivers/scsi/isci/core/intel_sat.h @@ -0,0 +1,95 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SAT_H_ +#define _SAT_H_ + +/** + * This file contains constants and constructs defined in the SCSI to ATA + * Translation (SAT) T10 standard. For more information please refer to + * www.t10.org. + * + * + */ + +/** + * + * + * SAT_PROTOCOLS These constants indicate the various protocol values that can + * be supported in a SAT translator. + */ +#define SAT_PROTOCOL_ATA_HARD_RESET 0 +#define SAT_PROTOCOL_SOFT_RESET 1 +#define SAT_PROTOCOL_NON_DATA 3 +#define SAT_PROTOCOL_PIO_DATA_IN 4 +#define SAT_PROTOCOL_PIO_DATA_OUT 5 +#define SAT_PROTOCOL_DMA 6 +#define SAT_PROTOCOL_DMA_QUEUED 7 +#define SAT_PROTOCOL_DEVICE_DIAGNOSTIC 8 +#define SAT_PROTOCOL_DEVICE_RESET 9 +#define SAT_PROTOCOL_UDMA_DATA_IN 10 +#define SAT_PROTOCOL_UDMA_DATA_OUT 11 +#define SAT_PROTOCOL_FPDMA 12 +#define SAT_PROTOCOL_RETURN_RESPONSE_INFO 15 + +#define SAT_PROTOCOL_PACKET 0x10 +#define SAT_PROTOCOL_PACKET_NON_DATA (SAT_PROTOCOL_PACKET | 0x0) +#define SAT_PROTOCOL_PACKET_DMA_DATA_IN (SAT_PROTOCOL_PACKET | 0x1) +#define SAT_PROTOCOL_PACKET_DMA_DATA_OUT (SAT_PROTOCOL_PACKET | 0x2) +#define SAT_PROTOCOL_PACKET_PIO_DATA_IN (SAT_PROTOCOL_PACKET | 0x3) +#define SAT_PROTOCOL_PACKET_PIO_DATA_OUT (SAT_PROTOCOL_PACKET | 0x4) + +#endif /* _SAT_H_ */ + diff --git a/drivers/scsi/isci/core/intel_sata.h b/drivers/scsi/isci/core/intel_sata.h new file mode 100644 index 000000000000..47390d54064d --- /dev/null +++ b/drivers/scsi/isci/core/intel_sata.h @@ -0,0 +1,280 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SATA_H_ +#define _SATA_H_ + +#include + +/** + * This file defines all of the SATA releated constants, enumerations, and + * types. Please note that this file does not necessarily contain an + * exhaustive list of all contants and commands. + * + * + */ + +/** + * + * + * SATA FIS Types These constants depict the various SATA FIS types devined in + * the serial ATA specification. + */ +#define SATA_FIS_TYPE_REGH2D 0x27 +#define SATA_FIS_TYPE_REGD2H 0x34 +#define SATA_FIS_TYPE_SETDEVBITS 0xA1 +#define SATA_FIS_TYPE_DMA_ACTIVATE 0x39 +#define SATA_FIS_TYPE_DMA_SETUP 0x41 +#define SATA_FIS_TYPE_BIST_ACTIVATE 0x58 +#define SATA_FIS_TYPE_PIO_SETUP 0x5F +#define SATA_FIS_TYPE_DATA 0x46 + +#define SATA_REGISTER_FIS_SIZE 0x20 + +/** + * struct sata_fis_header - This is the common definition for a SATA FIS Header + * word. A different header word is defined for any FIS type that does not + * use the standard header. + * + * + */ +struct sata_fis_header { + u32 fis_type:8; /* word 0 */ + u32 pm_port:4; + u32 reserved:1; + u32 direction_flag:1; /* direction */ + u32 interrupt_flag:1; + u32 command_flag:1; /* command, auto_activate, or notification */ + u32 status:8; + u32 error:8; +}; + + +/** + * struct sata_fis_reg_h2d - This is the definition for a SATA Host to Device + * Register FIS. + * + * + */ +struct sata_fis_reg_h2d { + u32 fis_type:8; /* word 0 */ + u32 pm_port:4; + u32 reserved0:3; + u32 command_flag:1; + u32 command:8; + u32 features:8; + u32 lba_low:8; /* word 1 */ + u32 lba_mid:8; + u32 lba_high:8; + u32 device:8; + u32 lba_low_exp:8; /* word 2 */ + u32 lba_mid_exp:8; + u32 lba_high_exp:8; + u32 features_exp:8; + u32 sector_count:8; /* word 3 */ + u32 sector_count_exp:8; + u32 reserved1:8; + u32 control:8; + u32 reserved2; /* word 4 */ +}; + +/** + * struct sata_fis_reg_d2h - SATA Device To Host FIS + * + * + */ +struct sata_fis_reg_d2h { + u32 fis_type:8; /* word 0 */ + u32 pm_port:4; + u32 reserved0:2; + u32 irq:1; + u32 reserved1:1; + u32 status:8; + u32 error:8; + u8 lba_low; /* word 1 */ + u8 lba_mid; + u8 lba_high; + u8 device; + u8 lba_low_exp; /* word 2 */ + u8 lba_mid_exp; + u8 lba_high_exp; + u8 reserved; + u8 sector_count; /* word 3 */ + u8 sector_count_exp; + u16 reserved2; + u32 reserved3; +}; + +/** + * + * + * Status field bit definitions + */ +#define SATA_FIS_STATUS_DEVBITS_MASK (0x77) + +/** + * struct sata_fis_set_dev_bits - SATA Set Device Bits FIS + * + * + */ +struct sata_fis_set_dev_bits { + u32 fis_type:8; /* word 0 */ + u32 pm_port:4; + u32 reserved0:2; + u32 irq:1; + u32 notification:1; + u32 status_low:4; + u32 status_high:4; + u32 error:8; + u32 s_active; /* word 1 */ +}; + +/** + * struct sata_fis_dma_activate - SATA DMA Activate FIS + * + * + */ +struct sata_fis_dma_activate { + u32 fis_type:8; /* word 0 */ + u32 pm_port:4; + u32 reserved0:24; +}; + +/** + * + * + * The lower 5 bits in the DMA Buffer ID Low field of the DMA Setup are used to + * communicate the command tag. + */ +#define SATA_DMA_SETUP_TAG_ENABLE 0x1F + +#define SATA_DMA_SETUP_AUTO_ACT_ENABLE 0x80 + +/** + * struct sata_fis_dma_setup - SATA DMA Setup FIS + * + * + */ +struct sata_fis_dma_setup { + u32 fis_type:8; /* word 0 */ + u32 pm_port:4; + u32 reserved_00:1; + u32 direction:1; + u32 irq:1; + u32 auto_activate:1; + u32 reserved_01:16; + u32 dma_buffer_id_low; /* word 1 */ + u32 dma_buffer_id_high; /* word 2 */ + u32 reserved0; /* word 3 */ + u32 dma_buffer_offset; /* word 4 */ + u32 dma_transfer_count; /* word 5 */ + u32 reserved1; /* word 6 */ +}; + +/** + * struct sata_fis_bist_activate - SATA BIST Activate FIS + * + * + */ +struct sata_fis_bist_activate { + u32 fis_type:8; /* word 0 */ + u32 reserved0:8; + u32 pattern_definition:8; + u32 reserved1:8; + u32 data1; /* word 1 */ + u32 data2; /* word 1 */ +}; + +/* + * SATA PIO Setup FIS + */ +struct sata_fis_pio_setup { + u32 fis_type:8; /* word 0 */ + u32 pm_port:4; + u32 reserved_00:1; + u32 direction:1; + u32 irq:1; + u32 reserved_01:1; + u32 status:8; + u32 error:8; + u32 lba_low:8; /* word 1 */ + u32 lba_mid:8; + u32 lba_high:8; + u32 device:8; + u32 lba_low_exp:8; /* word 2 */ + u32 lba_mid_exp:8; + u32 lba_high_exp:8; + u32 reserved:8; + u32 sector_count:8; /* word 3 */ + u32 sector_count_exp:8; + u32 reserved1:8; + u32 ending_status:8; + u32 transfter_count:16; /* word 4 */ + u32 reserved3:16; +}; + +/** + * struct sata_fis_data - SATA Data FIS + * + * + */ +struct sata_fis_data { + u32 fis_type:8; /* word 0 */ + u32 pm_port:4; + u32 reserved0:24; + u8 data[4]; /* word 1 */ +}; + +#endif /* _SATA_H_ */ diff --git a/drivers/scsi/isci/core/intel_scsi.h b/drivers/scsi/isci/core/intel_scsi.h new file mode 100644 index 000000000000..1e45d3c98127 --- /dev/null +++ b/drivers/scsi/isci/core/intel_scsi.h @@ -0,0 +1,474 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file defines all of the SCSI related constants, enumerations, and + * types. Please note that this file does not necessarily contain an + * exhaustive list of all constants, commands, sub-commands, etc. + * + * + */ + +#ifndef _SCSI_H__ +#define _SCSI_H__ + + +/* + * ****************************************************************************** + * * C O N S T A N T S A N D M A C R O S + * ****************************************************************************** */ + +/** + * enum _SCSI_TASK_MGMT_REQUEST_CODES - This enumberation contains the + * constants to be used for SCSI task management request codes. SAM does + * not specify any particular values for these codes so constants used here + * are the same as those specified in SAS. + * + * + */ +enum scsi_task_mgmt_request_codes { + SCSI_TASK_REQUEST_ABORT_TASK = 0x01, + SCSI_TASK_REQUEST_ABORT_TASK_SET = 0x02, + SCSI_TASK_REQUEST_CLEAR_TASK_SET = 0x04, + SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET = 0x08, + SCSI_TASK_REQUEST_I_T_NEXUS_RESET = 0x10, + SCSI_TASK_REQUEST_CLEAR_ACA = 0x40, + SCSI_TASK_REQUEST_QUERY_TASK = 0x80, + SCSI_TASK_REQUEST_QUERY_TASK_SET = 0x81, + SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION = 0x82, + +}; + +/** + * enum _SCSI_TASK_MGMT_RESPONSE_CODES - This enumeration contains all of the + * SCSI task management response codes. + * + * + */ +enum scsi_task_mgmt_response_codes { + SCSI_TASK_MGMT_FUNC_COMPLETE = 0, + SCSI_INVALID_FRAME = 2, + SCSI_TASK_MGMT_FUNC_NOT_SUPPORTED = 4, + SCSI_TASK_MGMT_FUNC_FAILED = 5, + SCSI_TASK_MGMT_FUNC_SUCCEEDED = 8, + SCSI_INVALID_LUN = 9 +}; + +/** + * enum _SCSI_SENSE_RESPONSE_CODE - this enumeration depicts the types of sense + * data responses as per SPC-3. + * + * + */ +enum scsi_sense_response_code { + SCSI_FIXED_CURRENT_RESPONSE_CODE = 0x70, + SCSI_FIXED_DEFERRED_RESPONSE_CODE = 0x71, + SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE = 0x72, + SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE = 0x73 + +}; + +/* + * This constant represents the valid bit located in byte 0 of a FIXED + * format sense data. */ +#define SCSI_FIXED_SENSE_DATA_VALID_BIT 0x80 + +#define SCSI_FIXED_SENSE_DATA_BASE_LENGTH 18 + +/* This value is used in the DATAPRES field of the SCSI Response IU. */ +#define SCSI_RESPONSE_DATA_PRES_SENSE_DATA 0x02 + +/** + * + * + * SCSI_SENSE_KEYS These constants delineate all of the SCSI protocol sense key + * constants + */ +#define SCSI_SENSE_NO_SENSE 0x00 +#define SCSI_SENSE_RECOVERED_ERROR 0x01 +#define SCSI_SENSE_NOT_READY 0x02 +#define SCSI_SENSE_MEDIUM_ERROR 0x03 +#define SCSI_SENSE_HARDWARE_ERROR 0x04 +#define SCSI_SENSE_ILLEGAL_REQUEST 0x05 +#define SCSI_SENSE_UNIT_ATTENTION 0x06 +#define SCSI_SENSE_DATA_PROTECT 0x07 +#define SCSI_SENSE_BLANK_CHECK 0x08 +#define SCSI_SENSE_VENDOR_SPECIFIC 0x09 +#define SCSI_SENSE_COPY_ABORTED 0x0A +#define SCSI_SENSE_ABORTED_COMMAND 0x0B +#define SCSI_SENSE_VOLUME_OVERFLOW 0x0D +#define SCSI_SENSE_MISCOMPARE 0x0E + +/** + * + * + * SCSI_ADDITIONAL_SENSE_CODES These constants delineate all of the SCSI + * protocol additional sense code constants. + */ +#define SCSI_ASC_NO_ADDITIONAL_SENSE 0x00 +#define SCSI_ASC_INITIALIZING_COMMAND_REQUIRED 0x04 +#define SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS 0x04 +#define SCSI_ASC_LUN_FORMAT_IN_PROGRESS 0x04 +#define SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION 0x05 +#define SCSI_ASC_UNRECOVERED_READ_ERROR 0x11 +#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20 +#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21 +#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24 +#define SCSI_ASC_INVALID_FIELD_IN_PARM_LIST 0x26 +#define SCSI_ASC_WRITE_PROTECTED 0x27 +#define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28 +#define SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED 0x39 +#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A +#define SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44 +#define SCSI_ASC_IU_CRC_ERROR_DETECTED 0x47 +#define SCSI_ASC_MEDIUM_REMOVAL_REQUEST 0x5A +#define SCSI_ASC_COMMAND_SEQUENCE_ERROR 0x2C +#define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED 0x53 +#define SCSI_ASC_HARDWARE_IMPENDING_FAILURE 0x5D +#define SCSI_ASC_POWER_STATE_CHANGE 0x5E +#define SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT 0x40 +#define SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED 0x67 + +/** + * + * + * SCSI_ADDITIONAL_SENSE_CODE_QUALIFIERS This enumeration contains all of the + * used SCSI protocol additional sense code qualifier constants. + */ +#define SCSI_ASCQ_NO_ADDITIONAL_SENSE 0x00 +#define SCSI_ASCQ_INVALID_FIELD_IN_CDB 0x00 +#define SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 0x00 +#define SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION 0x00 +#define SCSI_ASCQ_INTERNAL_TARGET_FAILURE 0x00 +#define SCSI_ASCQ_LBA_OUT_OF_RANGE 0x00 +#define SCSI_ASCQ_MEDIUM_NOT_PRESENT 0x00 +#define SCSI_ASCQ_NOT_READY_TO_READY_CHANGE 0x00 +#define SCSI_ASCQ_WRITE_PROTECTED 0x00 +#define SCSI_ASCQ_UNRECOVERED_READ_ERROR 0x00 +#define SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED 0x00 +#define SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE 0x00 +#define SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST 0x01 +#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 +#define SCSI_ASCQ_IU_CRC_ERROR_DETECTED 0x03 +#define SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS 0x04 +#define SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS 0x09 +#define SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE 0x10 +#define SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND 0x03 +#define SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND 0x04 +#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE 0x42 +#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY 0x43 +#define SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED 0x0B +#define SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 0x04 + + + +/** + * + * + * SCSI_STATUS_CODES These constants define all of the used SCSI status values. + */ +#define SCSI_STATUS_GOOD 0x00 +#define SCSI_STATUS_CHECK_CONDITION 0x02 +#define SCSI_STATUS_CONDITION_MET 0x04 +#define SCSI_STATUS_BUSY 0x08 +#define SCSI_STATUS_TASKFULL 0x28 +#define SCSI_STATUS_ACA 0x30 +#define SCSI_STATUS_ABORT 0x40 + +/** + * + * + * SCSI_OPERATION_CODES These constants delineate all of the SCSI + * command/operation codes. + */ +#define SCSI_INQUIRY 0x12 +#define SCSI_READ_CAPACITY_10 0x25 +#define SCSI_SERVICE_ACTION_IN_16 0x9E +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_START_STOP_UNIT 0x1B +#define SCSI_SYNCHRONIZE_CACHE_10 0x35 +#define SCSI_SYNCHRONIZE_CACHE_16 0x91 +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_REPORT_LUNS 0xA0 +#define SCSI_REASSIGN_BLOCKS 0x07 +#define SCSI_READ_6 0x08 +#define SCSI_READ_10 0x28 +#define SCSI_READ_12 0xA8 +#define SCSI_READ_16 0x88 +#define SCSI_WRITE_6 0x0A +#define SCSI_WRITE_10 0x2A +#define SCSI_WRITE_12 0xAA +#define SCSI_WRITE_16 0x8A +#define SCSI_VERIFY_10 0x2F +#define SCSI_VERIFY_12 0xAF +#define SCSI_VERIFY_16 0x8F +#define SCSI_SEEK_6 0x01 +#define SCSI_SEEK_10 0x02 +#define SCSI_WRITE_VERIFY 0x2E +#define SCSI_FORMAT_UNIT 0x04 +#define SCSI_READ_BUFFER 0x3C +#define SCSI_WRITE_BUFFER 0x3B +#define SCSI_SEND_DIAGNOSTIC 0x1D +#define SCSI_RECEIVE_DIAGNOSTIC 0x1C +#define SCSI_MODE_SENSE_6 0x1A +#define SCSI_MODE_SENSE_10 0x5A +#define SCSI_MODE_SELECT_6 0x15 +#define SCSI_MODE_SELECT_10 0x55 +#define SCSI_MAINTENANCE_IN 0xA3 +#define SCSI_LOG_SENSE 0x4D +#define SCSI_LOG_SELECT 0x4C +#define SCSI_RESERVE_6 0x16 +#define SCSI_RESERVE_10 0x56 +#define SCSI_RELEASE_6 0x17 +#define SCSI_RELEASE_10 0x57 +#define SCSI_ATA_PASSTHRU_12 0xA1 +#define SCSI_ATA_PASSTHRU_16 0x85 +#define SCSI_WRITE_LONG_10 0x3F +#define SCSI_WRITE_LONG_16 0x9F +#define SCSI_PERSISTENT_RESERVE_IN 0x5E +#define SCSI_PERSISTENT_RESERVE_OUT 0x5F + +/** + * + * + * SCSI_SERVICE_ACTION_IN_CODES Service action in operations. + */ +#define SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16 0x10 + +#define SCSI_SERVICE_ACTION_MASK 0x1f + +/** + * + * + * SCSI_MAINTENANCE_IN_SERVICE_ACTION_CODES MAINTENANCE IN service action codes. + */ +#define SCSI_REPORT_TASK_MGMT 0x0D +#define SCSI_REPORT_OP_CODES 0x0C + +/** + * + * + * SCSI_MODE_PAGE_CONTROLS These constants delineate all of the used SCSI Mode + * Page control values. + */ +#define SCSI_MODE_SENSE_PC_CURRENT 0x0 +#define SCSI_MODE_SENSE_PC_CHANGEABLE 0x1 +#define SCSI_MODE_SENSE_PC_DEFAULT 0x2 +#define SCSI_MODE_SENSE_PC_SAVED 0x3 + +#define SCSI_MODE_SENSE_PC_SHIFT 0x06 +#define SCSI_MODE_SENSE_PAGE_CODE_ENABLE 0x3F +#define SCSI_MODE_SENSE_DBD_ENABLE 0x08 +#define SCSI_MODE_SENSE_LLBAA_ENABLE 0x10 + +/** + * + * + * SCSI_MODE_PAGE_CODES These constants delineate all of the used SCSI Mode + * Page codes. + */ +#define SCSI_MODE_PAGE_READ_WRITE_ERROR 0x01 +#define SCSI_MODE_PAGE_DISCONNECT_RECONNECT 0x02 +#define SCSI_MODE_PAGE_CACHING 0x08 +#define SCSI_MODE_PAGE_CONTROL 0x0A +#define SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT 0x19 +#define SCSI_MODE_PAGE_POWER_CONDITION 0x1A +#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL 0x1C +#define SCSI_MODE_PAGE_ALL_PAGES 0x3F + +#define SCSI_MODE_SENSE_ALL_SUB_PAGES_CODE 0xFF +#define SCSI_MODE_SENSE_NO_SUB_PAGES_CODE 0x0 +#define SCSI_MODE_SENSE_PROTOCOL_PORT_NUM_SUBPAGES 0x1 +#define SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT 0x04 +#define SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT 0x20 +#define SCSI_MODE_PAGE_DEXCPT_ENABLE 0x08 +#define SCSI_MODE_SENSE_HEADER_FUA_ENABLE 0x10 +#define SCSI_MODE_PAGE_POWER_CONDITION_STANDBY 0x1 +#define SCSI_MODE_PAGE_POWER_CONDITION_IDLE 0x2 + +#define SCSI_MODE_SENSE_6_HEADER_LENGTH 4 +#define SCSI_MODE_SENSE_10_HEADER_LENGTH 8 +#define SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH 8 +#define SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH 16 + +#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE 0x08 +#define SCSI_MODE_PAGE_19_SAS_ID 0x6 +#define SCSI_MODE_PAGE_19_SUB1_PAGE_NUM 0x1 +#define SCSI_MODE_PAGE_19_SUB1_PC 0x59 + +#define SCSI_MODE_HEADER_MEDIUM_TYPE_SBC 0x00 + +/* Mode Select constrains related masks value */ +#define SCSI_MODE_SELECT_PF_BIT 0x1 +#define SCSI_MODE_SELECT_PF_MASK 0x10 +#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE 0x6 +#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK 0x0F +#define SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK 0x40 +#define SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK 0x80 +#define SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK 0x40 +#define SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK 0x1F +#define SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS 0xC1 +#define SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST 0x84 +#define SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC 0xF1 +#define SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER 0xF0 +#define SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP 0x38 +#define SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO 0x47 + + +#define SCSI_CONTROL_BYTE_NACA_BIT_ENABLE 0x04 +#define SCSI_MOVE_FUA_BIT_ENABLE 0x08 +#define SCSI_READ_CAPACITY_PMI_BIT_ENABLE 0x01 +#define SCSI_READ_CAPACITY_10_DATA_LENGTH 8 +#define SCSI_READ_CAPACITY_16_DATA_LENGTH 32 + +/* Inquiry constants */ +#define SCSI_INQUIRY_EVPD_ENABLE 0x01 +#define SCSI_INQUIRY_PAGE_CODE_OFFSET 0x02 +#define SCSI_INQUIRY_SUPPORTED_PAGES_PAGE 0x00 +#define SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE 0x80 +#define SCSI_INQUIRY_DEVICE_ID_PAGE 0x83 +#define SCSI_INQUIRY_ATA_INFORMATION_PAGE 0x89 +#define SCSI_INQUIRY_BLOCK_DEVICE_PAGE 0xB1 +#define SCSI_INQUIRY_BLOCK_DEVICE_LENGTH 0x3C +#define SCSI_INQUIRY_STANDARD_ALLOCATION_LENGTH 0x24 /* 36 */ + +#define SCSI_REQUEST_SENSE_ALLOCATION_LENGTH 0xFC /* 252 */ + +/** Defines the log page codes that are use in gathing Smart data + */ +#define SCSI_LOG_PAGE_SUPPORTED_PAGES 0x00 +#define SCSI_LOG_PAGE_INFORMATION_EXCEPTION 0x2F +#define SCSI_LOG_PAGE_SELF_TEST 0x10 + +/** + * + * + * SCSI_INQUIRY_VPD The following are constants used with vital product data + * inquiry pages. Values are already shifted into the proper nibble location. + */ +#define SCSI_PIV_ENABLE 0x80 +#define SCSI_LUN_ASSOCIATION 0x00 +#define SCSI_TARGET_PORT_ASSOCIATION 0x10 + +#define SCSI_VEN_UNIQUE_IDENTIFIER_TYPE 0x00 +#define SCSI_NAA_IDENTIFIER_TYPE 0x03 + +#define SCSI_T10_IDENTIFIER_TYPE 0x01 +#define SCSI_BINARY_CODE_SET 0x01 +#define SCSI_ASCII_CODE_SET 0x02 +#define SCSI_FC_PROTOCOL_IDENTIFIER 0x00 +#define SCSI_SAS_PROTOCOL_IDENTIFIER 0x60 + +#define SCSI_VERIFY_BYTCHK_ENABLED 0x02 + +#define SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED 0x02 +/** + * + * + * SCSI_START_STOP_UNIT_POWER_CONDITION_CODES The following are SCSI Start Stop + * Unit command Power Condition codes. + */ +#define SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID 0x0 +#define SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE 0x1 +#define SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE 0x2 +#define SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY 0x3 +#define SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL 0x7 +#define SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL 0xB + +#define SCSI_START_STOP_UNIT_IMMED_MASK 0x1 +#define SCSI_START_STOP_UNIT_IMMED_SHIFT 0 + +#define SCSI_START_STOP_UNIT_START_BIT_MASK 0x1 +#define SCSI_START_STOP_UNIT_START_BIT_SHIFT 0 + +#define SCSI_START_STOP_UNIT_LOEJ_BIT_MASK 0x2 +#define SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT 1 + +#define SCSI_START_STOP_UNIT_NO_FLUSH_MASK 0x4 +#define SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT 2 + +#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK 0xF +#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT 0 + +#define SCSI_START_STOP_UNIT_POWER_CONDITION_MASK 0xF0 +#define SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT 4 + +#define SCSI_LOG_SENSE_PC_FIELD_MASK 0xC0 +#define SCSI_LOG_SENSE_PC_FIELD_SHIFT 6 + +#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK 0x3F +#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT 0 + +/** + * + * + * MRIE - Method of reporting informational exceptions codes + */ +#define NO_REPORTING_INFO_EXCEPTION_CONDITION 0x0 +#define ASYNCHRONOUS_EVENT_REPORTING 0x1 +#define ESTABLISH_UNIT_ATTENTION_CONDITION 0x2 +#define CONDITIONALLY_GENERATE_RECOVERED_ERROR 0x3 +#define UNCONDITIONALLY_GENERATE_RECOVERED_ERROR 0x4 +#define GENERATE_NO_SENSE 0x5 +#define REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6 + +#define SCSI_INFORMATION_EXCEPTION_DEXCPT_BIT 0x08 + +/* Reassign Blocks masks */ +#define SCSI_REASSIGN_BLOCKS_LONGLBA_BIT 0x02 +#define SCSI_REASSIGN_BLOCKS_LONGLIST_BIT 0x01 + +#endif /* _SCSI_H_ */ + diff --git a/drivers/scsi/isci/core/sati_device.h b/drivers/scsi/isci/core/sati_device.h new file mode 100644 index 000000000000..4d1cfde12cae --- /dev/null +++ b/drivers/scsi/isci/core/sati_device.h @@ -0,0 +1,156 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SATI_DEVICE_H_ +#define _SATI_DEVICE_H_ + +/** + * This file contains all of the defintions for the SATI remote device object. + * Some translations require information to be remembered on a per device + * basis. This information is stored in the object defined in this file. + * + * + */ + +#include "sati_types.h" +#include "intel_ata.h" + +/** + * enum _SATI_DEVICE_STATE - This enumeration depicts the various states + * possible for the a translation remote device object. + * + * + */ +enum sati_device_state { + SATI_DEVICE_STATE_OPERATIONAL, + SATI_DEVICE_STATE_STOPPED, + SATI_DEVICE_STATE_STANDBY, + SATI_DEVICE_STATE_IDLE, + SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED, + SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS, + SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS, + SATI_DEVICE_STATE_SEQUENCE_INCOMPLETE, + SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION + +}; + +/** + * + * + * SATI_DEVICE_CAPABILITIES These constants define the various capabilities + * that a remote device may support for which there is an impact on translation. + */ +#define SATI_DEVICE_CAP_UDMA_ENABLE 0x00000001 +#define SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE 0x00000002 +#define SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE 0x00000004 +#define SATI_DEVICE_CAP_48BIT_ENABLE 0x00000008 +#define SATI_DEVICE_CAP_DMA_FUA_ENABLE 0x00000010 +#define SATI_DEVICE_CAP_SMART_SUPPORT 0x00000020 +#define SATI_DEVICE_CAP_REMOVABLE_MEDIA 0x00000040 +#define SATI_DEVICE_CAP_SMART_ENABLE 0x00000080 +#define SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE 0x00000100 +#define SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR 0x00000200 +#define SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT 0x00000400 + + +/** + * struct sati_device - The SATI_DEVICE structure define the state of the + * remote device with respect to translation. + * + * + */ +struct sati_device { + /** + * This field simply dictates the state of the SATI device. + */ + enum sati_device_state state; + + /** + * This field indicates features supported by the remote device that + * impact translation execution. + */ + u16 capabilities; + + /** + * This field indicates the depth of the native command queue supported + * by the device. + */ + u8 ncq_depth; + + /** + * This field stores the additional sense code for a unit attention + * condition. + */ + u8 unit_attention_asc; + + /** + * This field indicates the additional sense code qualifier for a unit + * attention condition. + */ + u8 unit_attention_ascq; + +}; + +void sati_device_construct( + struct sati_device *device, + bool is_ncq_enabled, + u8 max_ncq_depth); + +void sati_device_update_capabilities( + struct sati_device *device, + struct ata_identify_device_data *identify); + +#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */ + diff --git a/drivers/scsi/isci/core/sati_translator_sequence.h b/drivers/scsi/isci/core/sati_translator_sequence.h new file mode 100644 index 000000000000..592570d50ebd --- /dev/null +++ b/drivers/scsi/isci/core/sati_translator_sequence.h @@ -0,0 +1,304 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SATI_TRANSLATOR_SEQUENCE_H_ +#define _SATI_TRANSLATOR_SEQUENCE_H_ + +/** + * This file contains all of the defintions for the SATI translator sequence. + * A translator sequence is simply a defintion for the various sequences of + * commands that occur in this translator. + * + * + */ + +#include "sati_device.h" + +/** + * enum _SATI_TRANSLATOR_SEQUENCE_TYPE - This enumeration defines the possible + * sequence types for the translator. + * + * + */ +enum sati_translator_sequence_type { + /* SCSI Primary Command (SPC) sequences. */ + SATI_SEQUENCE_REPORT_LUNS, + SATI_SEQUENCE_TEST_UNIT_READY, + SATI_SEQUENCE_INQUIRY_STANDARD, + SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES, + SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER, + SATI_SEQUENCE_INQUIRY_DEVICE_ID, + SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE, + SATI_SEQUENCE_MODE_SENSE_6_CACHING, + SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL, + SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR, + SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT, + SATI_SEQUENCE_MODE_SENSE_6_CONTROL, + SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES, + SATI_SEQUENCE_MODE_SENSE_10_CACHING, + SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL, + SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR, + SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT, + SATI_SEQUENCE_MODE_SENSE_10_CONTROL, + SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES, + SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING, + SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION, + SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL, + + /* Log Sense Sequences */ + SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE, + SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE, + SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE, + SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE, + + /* SCSI Block Command (SBC) sequences. */ + + SATI_SEQUENCE_READ_6, + SATI_SEQUENCE_READ_10, + SATI_SEQUENCE_READ_12, + SATI_SEQUENCE_READ_16, + + SATI_SEQUENCE_READ_CAPACITY_10, + SATI_SEQUENCE_READ_CAPACITY_16, + + SATI_SEQUENCE_SYNCHRONIZE_CACHE, + + SATI_SEQUENCE_VERIFY_10, + SATI_SEQUENCE_VERIFY_12, + SATI_SEQUENCE_VERIFY_16, + + SATI_SEQUENCE_WRITE_6, + SATI_SEQUENCE_WRITE_10, + SATI_SEQUENCE_WRITE_12, + SATI_SEQUENCE_WRITE_16, + + SATI_SEQUENCE_START_STOP_UNIT, + + SATI_SEQUENCE_REASSIGN_BLOCKS, + + /* SCSI Task Requests sequences */ + + SATI_SEQUENCE_LUN_RESET, + + SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS, + SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE, + + SATI_SEQUENCE_WRITE_LONG + +}; + +#define SATI_SEQUENCE_TYPE_READ_MIN SATI_SEQUENCE_READ_6 +#define SATI_SEQUENCE_TYPE_READ_MAX SATI_SEQUENCE_READ_16 + +/** + * + * + * SATI_SEQUENCE_STATES These constants depict the various state values + * associated with a translation sequence. + */ +#define SATI_SEQUENCE_STATE_INITIAL 0 +#define SATI_SEQUENCE_STATE_TRANSLATE_DATA 1 +#define SATI_SEQUENCE_STATE_AWAIT_RESPONSE 2 +#define SATI_SEQUENCE_STATE_FINAL 3 +#define SATI_SEQUENCE_STATE_INCOMPLETE 4 + +/** + * + * + * SATI_DATA_DIRECTIONS These constants depict the various types of data + * directions for a translation sequence. Data can flow in/out (read/write) or + * no data at all. + */ +#define SATI_DATA_DIRECTION_NONE 0 +#define SATI_DATA_DIRECTION_IN 1 +#define SATI_DATA_DIRECTION_OUT 2 + +/** + * struct SATI_MODE_SELECT_PROCESSING_STATE - This structure contains all of + * the current processing states for processing mode select 6 and 10 + * commands' parameter fields. + * + * + */ +typedef struct SATI_MODE_SELECT_PROCESSING_STATE { + u8 *mode_pages; + u32 mode_page_offset; + u32 mode_pages_size; + u32 size_of_data_processed; + u32 total_ata_command_sent; + u32 ata_command_sent_for_cmp; /* cmp: current mode page */ + bool current_mode_page_processed; + +} SATI_MODE_SELECT_PROCESSING_STATE_T; + + +enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS { + SATI_REASSIGN_BLOCKS_READY_TO_SEND, + SATI_REASSIGN_BLOCKS_COMMAND_FAIL, + SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS, +}; + +/** + * struct sati_reassign_blocks_processing_state - This structure contains all + * of the current processing states for processing reassign block command's + * parameter fields. + * + * + */ +struct sati_reassign_blocks_processing_state { + u32 lba_offset; + u32 block_lists_size; + u8 lba_size; + u32 size_of_data_processed; + u32 ata_command_sent_for_current_lba; + bool current_lba_processed; + enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS ata_command_status; + +}; + +#define SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH 12 + +/** + * struct sati_atapi_data - The SATI_ATAPI_DATA structure is for sati atapi IO + * specific data. + * + * + */ +struct sati_atapi_data { + u8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH]; +}; + +/** + * struct sati_translator_sequence - This structure contains all of the + * translation information associated with a particular request. + * + * + */ +struct sati_translator_sequence { + /** + * This field contains the sequence type determined by the SATI. + */ + u8 type; + + /** + * This field indicates the current state for the sequence. + */ + u8 state; + + /** + * This field indicates the data direction (none, read, or write) for + * the translated request. + */ + u8 data_direction; + + /** + * This field contains the SATA/ATA protocol to be utilized during + * the IO transfer. + */ + u8 protocol; + + /** + * This field is utilized for sequences requiring data translation. + * It specifies the amount of data requested by the caller from the + * operation. It's necessary, because at times the user requests less + * data than is available. Thus, we need to avoid overrunning the + * buffer. + */ + u32 allocation_length; + + /** + * This field specifies the amount of data that will actually be + * transfered across the wire for this ATA request. + */ + u32 ata_transfer_length; + + /** + * This field specifies the amount of data bytes that have been + * set in a translation sequence. It will be incremented every time + * a data byte has been set by a sati translation. + */ + u16 number_data_bytes_set; + + /** + * This field indicates whether or not the sense response has been set + * by the translation sequence. + */ + bool is_sense_response_set; + + /** + * This field specifies the remote device context for which this + * translator sequence is destined. + */ + struct sati_device *device; + + /** + * This field is utilized to provide the translator with memory space + * required for translations that utilize multiple requests. + */ + union { + u32 translated_command; + u32 move_sector_count; + u32 scratch; + struct sati_reassign_blocks_processing_state reassign_blocks_process_state; + SATI_MODE_SELECT_PROCESSING_STATE_T process_state; + struct sati_atapi_data sati_atapi_data; + } command_specific_data; + +}; + + + +#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */ + diff --git a/drivers/scsi/isci/core/sati_types.h b/drivers/scsi/isci/core/sati_types.h new file mode 100644 index 000000000000..b6159e06c280 --- /dev/null +++ b/drivers/scsi/isci/core/sati_types.h @@ -0,0 +1,145 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SATI_TYPES_H_ +#define _SATI_TYPES_H_ + +/** + * This file contains various type definitions to be utilized with SCSI to ATA + * Translation Implementation. + * + * + */ + +/** + * enum _SATI_STATUS - This enumeration defines the possible return values from + * the SATI translation methods. + * + * + */ +enum sati_status { + /** + * This indicates that the translation was supported and occurred + * without error. + */ + SATI_SUCCESS, + + /** + * This indicates that the translation was supported, occurred without + * error, and no additional translation is necessary. This is done in + * conditions where the SCSI command doesn't require any interaction with + * the remote device. + */ + SATI_COMPLETE, + + /** + * This indicated everything SATI_COMPLETE does in addition to the response data + * not using all the memory allocated by the OS. + */ + SATI_COMPLETE_IO_DONE_EARLY, + + /** + * This indicates that translator sequence has finished some specific + * command in the sequence, but additional commands are necessary. + */ + SATI_SEQUENCE_INCOMPLETE, + + /** + * This indicates a general failure has occurred for which no further + * specification information is available. + */ + SATI_FAILURE, + + /** + * This indicates that the result of the IO request indicates a + * failure. The caller should reference the corresponding response + * data for further details. + */ + SATI_FAILURE_CHECK_RESPONSE_DATA, + + /** + * This status indicates that the supplied sequence type doesn't map + * to an existing definition. + */ + SATI_FAILURE_INVALID_SEQUENCE_TYPE, + + /** + * This status indicates that the supplied sequence state doesn't match + * the operation being requested by the user. + */ + SATI_FAILURE_INVALID_STATE + +}; + +#if (!defined(DISABLE_SATI_MODE_SENSE) \ + || !defined(DISABLE_SATI_MODE_SELECT) \ + || !defined(DISABLE_SATI_REQUEST_SENSE)) \ + +#if !defined(ENABLE_SATI_MODE_PAGES) +/** + * + * + * This macro enables the common mode page data structures and code. Currently, + * MODE SENSE, MODE SELECT, and REQUEST SENSE all make reference to this common + * code. As a result, enable the common mode page code if any of these 3 are + * being translated. + */ +#define ENABLE_SATI_MODE_PAGES +#endif /* !defined(ENABLE_SATI_MODE_PAGES) */ + +#endif /* MODE_SENSE/SELECT/REQUEST_SENSE */ + +#endif /* _SATI_TYPES_H_ */ + diff --git a/drivers/scsi/isci/core/sci_base_controller.h b/drivers/scsi/isci/core/sci_base_controller.h new file mode 100644 index 000000000000..36c53406ea5a --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_controller.h @@ -0,0 +1,306 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_CONTROLLER_H_ +#define _SCI_BASE_CONTROLLER_H_ + +#include "intel_sas.h" +#include "sci_controller_constants.h" +#include "sci_base_state.h" +#include "sci_base_memory_descriptor_list.h" +#include "sci_base_state_machine.h" +#include "sci_object.h" + +struct sci_base_memory_descriptor_list; + +/** + * enum sci_base_controller_states - This enumeration depicts all the states + * for the common controller state machine. + * + * + */ +enum sci_base_controller_states { + /** + * Simply the initial state for the base controller state machine. + */ + SCI_BASE_CONTROLLER_STATE_INITIAL = 0, + + /** + * This state indicates that the controller is reset. The memory for + * the controller is in it's initial state, but the controller requires + * initialization. + * This state is entered from the INITIAL state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_CONTROLLER_STATE_RESET, + + /** + * This state is typically an action state that indicates the controller + * is in the process of initialization. In this state no new IO operations + * are permitted. + * This state is entered from the RESET state. + */ + SCI_BASE_CONTROLLER_STATE_INITIALIZING, + + /** + * This state indicates that the controller has been successfully + * initialized. In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + */ + SCI_BASE_CONTROLLER_STATE_INITIALIZED, + + /** + * This state indicates the the controller is in the process of becoming + * ready (i.e. starting). In this state no new IO operations are permitted. + * This state is entered from the INITIALIZED state. + */ + SCI_BASE_CONTROLLER_STATE_STARTING, + + /** + * This state indicates the controller is now ready. Thus, the user + * is able to perform IO operations on the controller. + * This state is entered from the STARTING state. + */ + SCI_BASE_CONTROLLER_STATE_READY, + + /** + * This state is typically an action state that indicates the controller + * is in the process of resetting. Thus, the user is unable to perform + * IO operations on the controller. A reset is considered destructive in + * most cases. + * This state is entered from the READY state. + * This state is entered from the FAILED state. + * This state is entered from the STOPPED state. + */ + SCI_BASE_CONTROLLER_STATE_RESETTING, + + /** + * This state indicates that the controller is in the process of stopping. + * In this state no new IO operations are permitted, but existing IO + * operations are allowed to complete. + * This state is entered from the READY state. + */ + SCI_BASE_CONTROLLER_STATE_STOPPING, + + /** + * This state indicates that the controller has successfully been stopped. + * In this state no new IO operations are permitted. + * This state is entered from the STOPPING state. + */ + SCI_BASE_CONTROLLER_STATE_STOPPED, + + /** + * This state indicates that the controller could not successfully be + * initialized. In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + * This state is entered from the STARTING state. + * This state is entered from the STOPPING state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_CONTROLLER_STATE_FAILED, + + SCI_BASE_CONTROLLER_MAX_STATES + +}; + +/** + * struct sci_base_controller - The base controller object abstracts the fields + * common to all SCI controller objects. + * + * + */ +struct sci_base_controller { + /** + * The field specifies that the parent object for the base controller + * is the base object itself. + */ + struct sci_base_object parent; + + /** + * This field points to the memory descriptor list associated with this + * controller. The MDL indicates the memory requirements necessary for + * this controller object. + */ + struct sci_base_memory_descriptor_list mdl; + + /** + * This field contains the information for the base controller state + * machine. + */ + struct sci_base_state_machine state_machine; +}; + +/* Forward declarations */ +struct sci_base_remote_device; +struct sci_base_request; + +typedef enum sci_status +(*sci_base_controller_handler_t)(struct sci_base_controller *); + +typedef enum sci_status +(*sci_base_controller_timed_handler_t)(struct sci_base_controller *, u32); + +typedef enum sci_status +(*sci_base_controller_request_handler_t)(struct sci_base_controller *, + struct sci_base_remote_device *, + struct sci_base_request *); + +typedef enum sci_status +(*sci_base_controller_start_request_handler_t)(struct sci_base_controller *, + struct sci_base_remote_device *, + struct sci_base_request *, u16); + +/** + * struct sci_base_controller_state_handler - This structure contains all of + * the state handler methods common to base controller state machines. + * Handler methods provide the ability to change the behavior for user + * requests or transitions depending on the state the machine is in. + * + * + */ +struct sci_base_controller_state_handler { + /** + * The start_handler specifies the method invoked when a user attempts to + * start a controller. + */ + sci_base_controller_timed_handler_t start; + + /** + * The stop_handler specifies the method invoked when a user attempts to + * stop a controller. + */ + sci_base_controller_timed_handler_t stop; + + /** + * The reset_handler specifies the method invoked when a user attempts to + * reset a controller. + */ + sci_base_controller_handler_t reset; + + /** + * The initialize_handler specifies the method invoked when a user + * attempts to initialize a controller. + */ + sci_base_controller_handler_t initialize; + + /** + * The start_io_handler specifies the method invoked when a user + * attempts to start an IO request for a controller. + */ + sci_base_controller_start_request_handler_t start_io; + + /** + * The complete_io_handler specifies the method invoked when a user + * attempts to complete an IO request for a controller. + */ + sci_base_controller_request_handler_t complete_io; + + /** + * The continue_io_handler specifies the method invoked when a user + * attempts to continue an IO request for a controller. + */ + sci_base_controller_request_handler_t continue_io; + + /** + * The start_task_handler specifies the method invoked when a user + * attempts to start a task management request for a controller. + */ + sci_base_controller_start_request_handler_t start_task; + + /** + * The complete_task_handler specifies the method invoked when a user + * attempts to complete a task management request for a controller. + */ + sci_base_controller_request_handler_t complete_task; + +}; + +/** + * sci_base_controller_construct() - Construct the base controller + * @this_controller: This parameter specifies the base controller to be + * constructed. + * @state_table: This parameter specifies the table of state definitions to be + * utilized for the controller state machine. + * @mde_array: This parameter specifies the array of memory descriptor entries + * to be managed by this list. + * @mde_array_length: This parameter specifies the size of the array of entries. + * @next_mdl: This parameter specifies a subsequent MDL object to be managed by + * this MDL object. + * @oem_parameters: This parameter specifies the original equipment + * manufacturer parameters to be utilized by this controller object. + * + */ +static inline void sci_base_controller_construct( + struct sci_base_controller *scic_base, + const struct sci_base_state *state_table, + struct sci_physical_memory_descriptor *mdes, + u32 mde_count, + struct sci_base_memory_descriptor_list *next_mdl) +{ + scic_base->parent.private = NULL; + + sci_base_state_machine_construct( + &scic_base->state_machine, + &scic_base->parent, + state_table, + SCI_BASE_CONTROLLER_STATE_INITIAL + ); + + sci_base_mdl_construct(&scic_base->mdl, mdes, mde_count, next_mdl); + + sci_base_state_machine_start(&scic_base->state_machine); +} + +#endif /* _SCI_BASE_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c new file mode 100644 index 000000000000..86ae6a855399 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c @@ -0,0 +1,159 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the base implementation for the memory descriptor list. + * This is currently comprised of MDL iterator methods. + * + * + */ + +#include "sci_environment.h" +#include "sci_base_memory_descriptor_list.h" + +/* + * ****************************************************************************** + * * P U B L I C M E T H O D S + * ****************************************************************************** */ + +void sci_mdl_first_entry( + struct sci_base_memory_descriptor_list *base_mdl) +{ + base_mdl->next_index = 0; + + /* + * If this MDL is managing another MDL, then recursively rewind that MDL + * object as well. */ + if (base_mdl->next_mdl != SCI_INVALID_HANDLE) + sci_mdl_first_entry(base_mdl->next_mdl); +} + + +void sci_mdl_next_entry( + struct sci_base_memory_descriptor_list *base_mdl) +{ + /* + * If there is at least one more entry left in the array, then change + * the next pointer to it. */ + if (base_mdl->next_index < base_mdl->length) + base_mdl->next_index++; + else if (base_mdl->next_index == base_mdl->length) { + /* + * This MDL has exhausted it's set of entries. If this MDL is managing + * another MDL, then start iterating through that MDL. */ + if (base_mdl->next_mdl != SCI_INVALID_HANDLE) + sci_mdl_next_entry(base_mdl->next_mdl); + } +} + + +struct sci_physical_memory_descriptor *sci_mdl_get_current_entry( + struct sci_base_memory_descriptor_list *base_mdl) +{ + if (base_mdl->next_index < base_mdl->length) + return &base_mdl->mde_array[base_mdl->next_index]; + else if (base_mdl->next_index == base_mdl->length) { + /* + * This MDL has exhausted it's set of entries. If this MDL is managing + * another MDL, then return it's current entry. */ + if (base_mdl->next_mdl != SCI_INVALID_HANDLE) + return sci_mdl_get_current_entry(base_mdl->next_mdl); + } + + return NULL; +} + +/* + * ****************************************************************************** + * * P R O T E C T E D M E T H O D S + * ****************************************************************************** */ + +void sci_base_mdl_construct( + struct sci_base_memory_descriptor_list *mdl, + struct sci_physical_memory_descriptor *mde_array, + u32 mde_array_length, + struct sci_base_memory_descriptor_list *next_mdl) +{ + mdl->length = mde_array_length; + mdl->mde_array = mde_array; + mdl->next_index = 0; + mdl->next_mdl = next_mdl; +} + +/* --------------------------------------------------------------------------- */ + +bool sci_base_mde_is_valid( + struct sci_physical_memory_descriptor *mde, + u32 alignment, + u32 size, + u16 attributes) +{ + /* Only need the lower 32 bits to ensure alignment is met. */ + u32 physical_address = lower_32_bits(mde->physical_address); + + if ( + ((((unsigned long)mde->virtual_address) & (alignment - 1)) != 0) + || ((physical_address & (alignment - 1)) != 0) + || (mde->constant_memory_alignment != alignment) + || (mde->constant_memory_size != size) + || (mde->virtual_address == NULL) + || (mde->constant_memory_attributes != attributes) + ) { + return false; + } + + return true; +} + diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h new file mode 100644 index 000000000000..257d6e368b4a --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h @@ -0,0 +1,155 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ +#define _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ + +/** + * This file contains the protected interface structures, constants and + * interface methods for the struct sci_base_memory_descriptor_list object. + * + * + */ + + +#include "sci_types.h" +#include "sci_memory_descriptor_list.h" + + +/** + * struct sci_base_memory_descriptor_list - This structure contains all of the + * fields necessary to implement a simple stack for managing the list of + * available controller indices. + * + * + */ +struct sci_base_memory_descriptor_list { + /** + * This field indicates the length of the memory descriptor entry array. + */ + u32 length; + + /** + * This field is utilized to provide iterator pattern functionality. + * It indicates the index of the next memory descriptor in the iteration. + */ + u32 next_index; + + /** + * This field will point to the list of memory descriptors. + */ + struct sci_physical_memory_descriptor *mde_array; + + /** + * This field simply allows a user to chain memory descriptor lists + * together if desired. This field will be initialized to + * SCI_INVALID_HANDLE. + */ + struct sci_base_memory_descriptor_list *next_mdl; + +}; + +/** + * sci_base_mdl_construct() - This method is invoked to construct an memory + * descriptor list. It initializes the fields of the MDL. + * @mdl: This parameter specifies the memory descriptor list to be constructed. + * @mde_array: This parameter specifies the array of memory descriptor entries + * to be managed by this list. + * @mde_array_length: This parameter specifies the size of the array of entries. + * @next_mdl: This parameter specifies a subsequent MDL object to be managed by + * this MDL object. + * + * none. + */ +void sci_base_mdl_construct( + struct sci_base_memory_descriptor_list *mdl, + struct sci_physical_memory_descriptor *mde_array, + u32 mde_array_length, + struct sci_base_memory_descriptor_list *next_mdl); + +/** + * sci_base_mde_construct() - + * + * This macro constructs an memory descriptor entry with the given alignment + * and size + */ +#define sci_base_mde_construct(mde, alignment, size, attributes) \ + { \ + (mde)->constant_memory_alignment = (alignment); \ + (mde)->constant_memory_size = (size); \ + (mde)->constant_memory_attributes = (attributes); \ + } + +/** + * sci_base_mde_is_valid() - This method validates that the memory descriptor + * is correctly filled out by the SCI User + * @mde: This parameter is the mde entry to validate + * @alignment: This parameter specifies the expected alignment of the memory + * for the mde. + * @size: This parameter specifies the memory size expected for the mde its + * value should not have been changed by the SCI User. + * @attributes: This parameter specifies the attributes for the memory + * descriptor provided. + * + * bool This method returns an indication as to whether the supplied MDE is + * valid or not. true The MDE is valid. false The MDE is not valid. + */ +bool sci_base_mde_is_valid( + struct sci_physical_memory_descriptor *mde, + u32 alignment, + u32 size, + u16 attributes); + +#endif /* _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_phy.h b/drivers/scsi/isci/core/sci_base_phy.h new file mode 100644 index 000000000000..6c0d9bbbc95f --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_phy.h @@ -0,0 +1,205 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_PHY_H_ +#define _SCI_BASE_PHY_H_ + +/** + * This file contains all of the structures, constants, and methods common to + * all phy object definitions. + * + * + */ + +#include "sci_base_state_machine.h" + +/** + * enum sci_base_phy_states - This enumeration depicts the standard states + * common to all phy state machine implementations. + * + * + */ +enum sci_base_phy_states { + /** + * Simply the initial state for the base domain state machine. + */ + SCI_BASE_PHY_STATE_INITIAL, + + /** + * This state indicates that the phy has successfully been stopped. + * In this state no new IO operations are permitted on this phy. + * This state is entered from the INITIAL state. + * This state is entered from the STARTING state. + * This state is entered from the READY state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PHY_STATE_STOPPED, + + /** + * This state indicates that the phy is in the process of becomming + * ready. In this state no new IO operations are permitted on this phy. + * This state is entered from the STOPPED state. + * This state is entered from the READY state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PHY_STATE_STARTING, + + /** + * This state indicates the the phy is now ready. Thus, the user + * is able to perform IO operations utilizing this phy as long as it + * is currently part of a valid port. + * This state is entered from the STARTING state. + */ + SCI_BASE_PHY_STATE_READY, + + /** + * This state indicates that the phy is in the process of being reset. + * In this state no new IO operations are permitted on this phy. + * This state is entered from the READY state. + */ + SCI_BASE_PHY_STATE_RESETTING, + + /** + * Simply the final state for the base phy state machine. + */ + SCI_BASE_PHY_STATE_FINAL, + + SCI_BASE_PHY_MAX_STATES + +}; + +/** + * struct sci_base_phy - This structure defines all of the fields common to PHY + * objects. + * + * + */ +struct sci_base_phy { + /** + * This field depicts the parent object (struct sci_base_object) for the phy. + */ + struct sci_base_object parent; + + /** + * This field contains the information for the base phy state machine. + */ + struct sci_base_state_machine state_machine; +}; + +typedef enum sci_status (*SCI_BASE_PHY_HANDLER_T)( + struct sci_base_phy * + ); + +/** + * struct sci_base_phy_state_handler - This structure contains all of the state + * handler methods common to base phy state machines. Handler methods + * provide the ability to change the behavior for user requests or + * transitions depending on the state the machine is in. + * + * + */ +struct sci_base_phy_state_handler { + /** + * The start_handler specifies the method invoked when there is an + * attempt to start a phy. + */ + SCI_BASE_PHY_HANDLER_T start_handler; + + /** + * The stop_handler specifies the method invoked when there is an + * attempt to stop a phy. + */ + SCI_BASE_PHY_HANDLER_T stop_handler; + + /** + * The reset_handler specifies the method invoked when there is an + * attempt to reset a phy. + */ + SCI_BASE_PHY_HANDLER_T reset_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a phy. + */ + SCI_BASE_PHY_HANDLER_T destruct_handler; + +}; + +/** + * sci_base_phy_construct() - Construct the base phy + * @this_phy: This parameter specifies the base phy to be constructed. + * @state_table: This parameter specifies the table of state definitions to be + * utilized for the phy state machine. + * + */ +static inline void sci_base_phy_construct( + struct sci_base_phy *base_phy, + const struct sci_base_state *state_table) +{ + base_phy->parent.private = NULL; + sci_base_state_machine_construct( + &base_phy->state_machine, + &base_phy->parent, + state_table, + SCI_BASE_PHY_STATE_INITIAL + ); + + sci_base_state_machine_start( + &base_phy->state_machine + ); +} + + +#endif /* _SCI_BASE_PHY_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_port.h b/drivers/scsi/isci/core/sci_base_port.h new file mode 100644 index 000000000000..4e2031d195f0 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_port.h @@ -0,0 +1,203 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_PORT_H_ +#define _SCI_BASE_PORT_H_ + +#include "sci_base_state_machine.h" +#include "sci_object.h" + +/** + * enum sci_base_port_states - This enumeration depicts all the states for the + * common port state machine. + * + * + */ +enum sci_base_port_states { + /** + * This state indicates that the port has successfully been stopped. + * In this state no new IO operations are permitted. + * This state is entered from the STOPPING state. + */ + SCI_BASE_PORT_STATE_STOPPED, + + /** + * This state indicates that the port is in the process of stopping. + * In this state no new IO operations are permitted, but existing IO + * operations are allowed to complete. + * This state is entered from the READY state. + */ + SCI_BASE_PORT_STATE_STOPPING, + + /** + * This state indicates the port is now ready. Thus, the user is + * able to perform IO operations on this port. + * This state is entered from the STARTING state. + */ + SCI_BASE_PORT_STATE_READY, + + /** + * This state indicates the port is in the process of performing a hard + * reset. Thus, the user is unable to perform IO operations on this + * port. + * This state is entered from the READY state. + */ + SCI_BASE_PORT_STATE_RESETTING, + + /** + * This state indicates the port has failed a reset request. This state + * is entered when a port reset request times out. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PORT_STATE_FAILED, + + SCI_BASE_PORT_MAX_STATES + +}; + +/** + * struct sci_base_port - The base port object abstracts the fields common to + * all SCI port objects. + * + * + */ +struct sci_base_port { + /** + * The field specifies that the parent object for the base controller + * is the base object itself. + */ + struct sci_base_object parent; + + /** + * This field contains the information for the base port state machine. + */ + struct sci_base_state_machine state_machine; +}; + +struct sci_base_phy; + +typedef enum sci_status (*SCI_BASE_PORT_HANDLER_T)( + struct sci_base_port * + ); + +typedef enum sci_status (*SCI_BASE_PORT_PHY_HANDLER_T)( + struct sci_base_port *, + struct sci_base_phy * + ); + +typedef enum sci_status (*SCI_BASE_PORT_RESET_HANDLER_T)( + struct sci_base_port *, + u32 timeout + ); + +/** + * struct sci_base_port_state_handler - This structure contains all of the + * state handler methods common to base port state machines. Handler + * methods provide the ability to change the behavior for user requests or + * transitions depending on the state the machine is in. + * + * + */ +struct sci_base_port_state_handler { + /** + * The start_handler specifies the method invoked when a user attempts to + * start a port. + */ + SCI_BASE_PORT_HANDLER_T start_handler; + + /** + * The stop_handler specifies the method invoked when a user attempts to + * stop a port. + */ + SCI_BASE_PORT_HANDLER_T stop_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a port. + */ + SCI_BASE_PORT_HANDLER_T destruct_handler; + + /** + * The reset_handler specifies the method invoked when a user attempts to + * hard reset a port. + */ + SCI_BASE_PORT_RESET_HANDLER_T reset_handler; + + /** + * The add_phy_handler specifies the method invoked when a user attempts to + * add another phy into the port. + */ + SCI_BASE_PORT_PHY_HANDLER_T add_phy_handler; + + /** + * The remove_phy_handler specifies the method invoked when a user + * attempts to remove a phy from the port. + */ + SCI_BASE_PORT_PHY_HANDLER_T remove_phy_handler; + +}; + +/** + * sci_base_port_construct() - Construct the base port object + * @this_port: This parameter specifies the base port to be constructed. + * @state_table: This parameter specifies the table of state definitions to be + * utilized for the domain state machine. + * + */ +void sci_base_port_construct( + struct sci_base_port *this_port, + const struct sci_base_state *state_table); + +#endif /* _SCI_BASE_PORT_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_remote_device.h b/drivers/scsi/isci/core/sci_base_remote_device.h new file mode 100644 index 000000000000..fe6614b8ef5b --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_remote_device.h @@ -0,0 +1,277 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_REMOTE_DEVICE_H_ +#define _SCI_BASE_REMOTE_DEVICE_H_ + +/** + * This file contains all of the structures, constants, and methods common to + * all remote device object definitions. + * + * + */ + +#include "sci_base_state_machine.h" + +struct sci_base_request; + +/** + * enum sci_base_remote_device_states - This enumeration depicts all the states + * for the common remote device state machine. + * + * + */ +enum sci_base_remote_device_states { + /** + * Simply the initial state for the base remote device state machine. + */ + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL, + + /** + * This state indicates that the remote device has successfully been + * stopped. In this state no new IO operations are permitted. + * This state is entered from the INITIAL state. + * This state is entered from the STOPPING state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED, + + /** + * This state indicates the the remote device is in the process of + * becoming ready (i.e. starting). In this state no new IO operations + * are permitted. + * This state is entered from the STOPPED state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STARTING, + + /** + * This state indicates the remote device is now ready. Thus, the user + * is able to perform IO operations on the remote device. + * This state is entered from the STARTING state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_READY, + + /** + * This state indicates that the remote device is in the process of + * stopping. In this state no new IO operations are permitted, but + * existing IO operations are allowed to complete. + * This state is entered from the READY state. + * This state is entered from the FAILED state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, + + /** + * This state indicates that the remote device has failed. + * In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + * This state is entered from the READY state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_FAILED, + + /** + * This state indicates the device is being reset. + * In this state no new IO operations are permitted. + * This state is entered from the READY state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, + + /** + * Simply the final state for the base remote device state machine. + */ + SCI_BASE_REMOTE_DEVICE_STATE_FINAL, + + SCI_BASE_REMOTE_DEVICE_MAX_STATES + +}; + +/** + * struct sci_base_remote_device - The base remote device object abstracts the + * fields common to all SCI remote device objects. + * + * + */ +struct sci_base_remote_device { + /** + * The field specifies that the parent object for the base remote + * device is the base object itself. + */ + struct sci_base_object parent; + + /** + * This field contains the information for the base remote device state + * machine. + */ + struct sci_base_state_machine state_machine; +}; + + +typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HANDLER_T)( + struct sci_base_remote_device * + ); + +typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T)( + struct sci_base_remote_device *, + struct sci_base_request * + ); + +typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T)( + struct sci_base_remote_device *, + struct sci_base_request *, + void *, + enum sci_io_status + ); + +/** + * struct sci_base_remote_device_state_handler - This structure contains all of + * the state handler methods common to base remote device state machines. + * Handler methods provide the ability to change the behavior for user + * requests or transitions depending on the state the machine is in. + * + * + */ +struct sci_base_remote_device_state_handler { + /** + * The start_handler specifies the method invoked when a user attempts to + * start a remote device. + */ + SCI_BASE_REMOTE_DEVICE_HANDLER_T start_handler; + + /** + * The stop_handler specifies the method invoked when a user attempts to + * stop a remote device. + */ + SCI_BASE_REMOTE_DEVICE_HANDLER_T stop_handler; + + /** + * The fail_handler specifies the method invoked when a remote device + * failure has occurred. A failure may be due to an inability to + * initialize/configure the device. + */ + SCI_BASE_REMOTE_DEVICE_HANDLER_T fail_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a remote device. + */ + SCI_BASE_REMOTE_DEVICE_HANDLER_T destruct_handler; + + /** + * The reset handler specifies the method invloked when requesting to reset a + * remote device. + */ + SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_handler; + + /** + * The reset complete handler specifies the method invloked when reporting + * that a reset has completed to the remote device. + */ + SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_complete_handler; + + /** + * The start_io_handler specifies the method invoked when a user + * attempts to start an IO request for a remote device. + */ + SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_io_handler; + + /** + * The complete_io_handler specifies the method invoked when a user + * attempts to complete an IO request for a remote device. + */ + SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_io_handler; + + /** + * The continue_io_handler specifies the method invoked when a user + * attempts to continue an IO request for a remote device. + */ + SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T continue_io_handler; + + /** + * The start_task_handler specifies the method invoked when a user + * attempts to start a task management request for a remote device. + */ + SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_task_handler; + + /** + * The complete_task_handler specifies the method invoked when a user + * attempts to complete a task management request for a remote device. + */ + SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_task_handler; + +}; + +/** + * sci_base_remote_device_construct() - Construct the base remote device + * @this_remote_device: This parameter specifies the base remote device to be + * constructed. + * @state_table: This parameter specifies the table of state definitions to be + * utilized for the remote device state machine. + * + */ +static inline void sci_base_remote_device_construct( + struct sci_base_remote_device *base_dev, + const struct sci_base_state *state_table) +{ + base_dev->parent.private = NULL; + sci_base_state_machine_construct( + &base_dev->state_machine, + &base_dev->parent, + state_table, + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL + ); + + sci_base_state_machine_start( + &base_dev->state_machine + ); +} +#endif /* _SCI_BASE_REMOTE_DEVICE_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_request.h b/drivers/scsi/isci/core/sci_base_request.h new file mode 100644 index 000000000000..d1b2195b228a --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_request.h @@ -0,0 +1,195 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_REQUST_H_ +#define _SCI_BASE_REQUST_H_ + +/** + * This file contains all of the constants, types, and method declarations for + * the SCI base IO and task request objects. + * + * + */ + +#include "sci_base_state_machine.h" + +/** + * enum sci_base_request_states - This enumeration depicts all the states for + * the common request state machine. + * + * + */ +enum sci_base_request_states { + /** + * Simply the initial state for the base request state machine. + */ + SCI_BASE_REQUEST_STATE_INITIAL, + + /** + * This state indicates that the request has been constructed. This state + * is entered from the INITIAL state. + */ + SCI_BASE_REQUEST_STATE_CONSTRUCTED, + + /** + * This state indicates that the request has been started. This state is + * entered from the CONSTRUCTED state. + */ + SCI_BASE_REQUEST_STATE_STARTED, + + /** + * This state indicates that the request has completed. + * This state is entered from the STARTED state. This state is entered from + * the ABORTING state. + */ + SCI_BASE_REQUEST_STATE_COMPLETED, + + /** + * This state indicates that the request is in the process of being + * terminated/aborted. + * This state is entered from the CONSTRUCTED state. + * This state is entered from the STARTED state. + */ + SCI_BASE_REQUEST_STATE_ABORTING, + + /** + * Simply the final state for the base request state machine. + */ + SCI_BASE_REQUEST_STATE_FINAL, +}; + +/** + * struct sci_base_request - The base request object abstracts the fields + * common to all SCI IO and task request objects. + * + * + */ +struct sci_base_request { + /** + * The field specifies that the parent object for the base request is the + * base object itself. + */ + struct sci_base_object parent; + + /** + * This field contains the information for the base request state machine. + */ + struct sci_base_state_machine state_machine; +}; + +typedef enum sci_status (*SCI_BASE_REQUEST_HANDLER_T)( + struct sci_base_request *this_request + ); + +/** + * struct sci_base_request_state_handler - This structure contains all of the + * state handler methods common to base IO and task request state machines. + * Handler methods provide the ability to change the behavior for user + * requests or transitions depending on the state the machine is in. + * + * + */ +struct sci_base_request_state_handler { + /** + * The start_handler specifies the method invoked when a user attempts to + * start a request. + */ + SCI_BASE_REQUEST_HANDLER_T start_handler; + + /** + * The abort_handler specifies the method invoked when a user attempts to + * abort a request. + */ + SCI_BASE_REQUEST_HANDLER_T abort_handler; + + /** + * The complete_handler specifies the method invoked when a user attempts to + * complete a request. + */ + SCI_BASE_REQUEST_HANDLER_T complete_handler; + + /** + * The destruct_handler specifies the method invoked when a user attempts to + * destruct a request. + */ + SCI_BASE_REQUEST_HANDLER_T destruct_handler; + +}; + +/** + * sci_base_request_construct() - Construct the base request. + * @this_request: This parameter specifies the base request to be constructed. + * @state_table: This parameter specifies the table of state definitions to be + * utilized for the request state machine. + * + */ +static inline void sci_base_request_construct( + struct sci_base_request *base_req, + const struct sci_base_state *my_state_table) +{ + base_req->parent.private = NULL; + sci_base_state_machine_construct( + &base_req->state_machine, + &base_req->parent, + my_state_table, + SCI_BASE_REQUEST_STATE_INITIAL + ); + + sci_base_state_machine_start( + &base_req->state_machine + ); +} + +#endif /* _SCI_BASE_REQUST_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_state.h b/drivers/scsi/isci/core/sci_base_state.h new file mode 100644 index 000000000000..d6b9c1a951b1 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_state.h @@ -0,0 +1,90 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_STATE_H_ +#define _SCI_BASE_STATE_H_ + +#include "sci_object.h" + +typedef void (*SCI_BASE_STATE_HANDLER_T)( + void + ); + +typedef void (*SCI_STATE_TRANSITION_T)( + struct sci_base_object *base_object + ); + +/** + * struct sci_base_state - The base state object abstracts the fields common to + * all state objects defined in SCI. + * + * + */ +struct sci_base_state { + /** + * This field is a function pointer that defines the method to be + * invoked when the state is entered. + */ + SCI_STATE_TRANSITION_T enter_state; + + /** + * This field is a function pointer that defines the method to be + * invoked when the state is exited. + */ + SCI_STATE_TRANSITION_T exit_state; + +}; + +#endif /* _SCI_BASE_STATE_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_state_machine.c b/drivers/scsi/isci/core/sci_base_state_machine.c new file mode 100644 index 000000000000..5b1e8da55fe6 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_state_machine.c @@ -0,0 +1,182 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains all of the functionality common to all state machine + * object implementations. + * + * + */ + +#include "sci_base_state_machine.h" + +static void sci_state_machine_exit_state(struct sci_base_state_machine *sm) +{ + u32 state = sm->current_state_id; + SCI_STATE_TRANSITION_T exit = sm->state_table[state].exit_state; + + if (exit) + exit(sm->state_machine_owner); +} + +static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) +{ + u32 state = sm->current_state_id; + SCI_STATE_TRANSITION_T enter = sm->state_table[state].enter_state; + + if (enter) + enter(sm->state_machine_owner); +} + +/* + * ****************************************************************************** + * * P R O T E C T E D M E T H O D S + * ****************************************************************************** */ + +/** + * This method will set the initial state and state table for the state + * machine. The caller should follow this request with the initialize + * request to cause the state machine to start. + * @sm: This parameter provides the state machine object to be + * constructed. + * @state_machine_owner: This parameter indicates the object that is owns the + * state machine being constructed. + * @state_table: This parameter specifies the table of state objects that is + * managed by this state machine. + * @initial_state: This parameter specifies the value of the initial state for + * this state machine. + * + */ +void sci_base_state_machine_construct(struct sci_base_state_machine *sm, + struct sci_base_object *owner, + const struct sci_base_state *state_table, + u32 initial_state) +{ + sm->state_machine_owner = owner; + sm->initial_state_id = initial_state; + sm->previous_state_id = initial_state; + sm->current_state_id = initial_state; + sm->state_table = state_table; +} + +/** + * This method will cause the state machine to enter the initial state. + * @sm: This parameter specifies the state machine that is to + * be started. + * + * sci_base_state_machine_construct() for how to set the initial state none + */ +void sci_base_state_machine_start(struct sci_base_state_machine *sm) +{ + sm->current_state_id = sm->initial_state_id; +#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) + sci_base_subject_notify(&sm->parent); +#endif + sci_state_machine_enter_state(sm); +} + +/** + * This method will cause the state machine to exit it's current state only. + * @sm: This parameter specifies the state machine that is to + * be stopped. + * + */ +void sci_base_state_machine_stop( + struct sci_base_state_machine *sm) +{ + sci_state_machine_exit_state(sm); +#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) + sci_base_subject_notify(&sm->parent); +#endif +} + +/** + * This method performs an update to the current state of the state machine. + * @sm: This parameter specifies the state machine for which + * the caller wishes to perform a state change. + * @next_state: This parameter specifies the new state for the state machine. + * + */ +void sci_base_state_machine_change_state( + struct sci_base_state_machine *sm, + u32 next_state) +{ + sci_state_machine_exit_state(sm); + + sm->previous_state_id = sm->current_state_id; + sm->current_state_id = next_state; + +#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) + /* Notify of the state change prior to entering the state. */ + sci_base_subject_notify(&sm->parent); +#endif + + sci_state_machine_enter_state(sm); +} + +/** + * This method simply returns the current state of the state machine to the + * caller. + * @sm: This parameter specifies the state machine for which to + * retrieve the current state. + * + * This method returns a u32 value indicating the current state for the + * supplied state machine. + */ +u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm) +{ + return sm->current_state_id; +} + diff --git a/drivers/scsi/isci/core/sci_base_state_machine.h b/drivers/scsi/isci/core/sci_base_state_machine.h new file mode 100644 index 000000000000..cee38bd3d127 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_state_machine.h @@ -0,0 +1,139 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_STATE_MACHINE_H_ +#define _SCI_BASE_STATE_MACHINE_H_ + +/** + * This file contains all structures, constants, or method declarations common + * to all state machines defined in SCI. + * + * + */ + + +#include "sci_base_state.h" + + +/** + * SET_STATE_HANDLER() - + * + * This macro simply provides simplified retrieval of an objects state handler. + */ +#define SET_STATE_HANDLER(object, table, state) \ + (object)->state_handlers = &(table)[(state)] + +/** + * struct sci_base_state_machine - This structure defines the fields common to + * all state machines. + * + * + */ +struct sci_base_state_machine { + /** + * This field points to the start of the state machine's state table. + */ + const struct sci_base_state *state_table; + + /** + * This field points to the object to which this state machine is + * associated. It serves as a cookie to be provided to the state + * enter/exit methods. + */ + struct sci_base_object *state_machine_owner; + + /** + * This field simply indicates the state value for the state machine's + * initial state. + */ + u32 initial_state_id; + + /** + * This field indicates the current state of the state machine. + */ + u32 current_state_id; + + /** + * This field indicates the previous state of the state machine. + */ + u32 previous_state_id; + +}; + +/* + * ****************************************************************************** + * * P R O T E C T E D M E T H O D S + * ****************************************************************************** */ + +void sci_base_state_machine_construct( + struct sci_base_state_machine *this_state_machine, + struct sci_base_object *state_machine_owner, + const struct sci_base_state *state_table, + u32 initial_state); + +void sci_base_state_machine_start( + struct sci_base_state_machine *this_state_machine); + +void sci_base_state_machine_stop( + struct sci_base_state_machine *this_state_machine); + +void sci_base_state_machine_change_state( + struct sci_base_state_machine *this_state_machine, + u32 next_state); + +u32 sci_base_state_machine_get_state( + struct sci_base_state_machine *this_state_machine); + +#endif /* _SCI_BASE_STATE_MACHINE_H_ */ diff --git a/drivers/scsi/isci/core/sci_controller.h b/drivers/scsi/isci/core/sci_controller.h new file mode 100644 index 000000000000..26c3548cbf7a --- /dev/null +++ b/drivers/scsi/isci/core/sci_controller.h @@ -0,0 +1,100 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_CONTROLLER_H_ +#define _SCI_CONTROLLER_H_ + +/** + * This file contains all of the interface methods that can be called by an SCI + * user on all SCI controller objects. + * + * + */ + + +#include "sci_types.h" + +struct sci_base_memory_descriptor_list; +struct scic_sds_controller; + +#define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF + +/** + * sci_controller_get_memory_descriptor_list_handle() - This method simply + * returns a handle for the memory descriptor list associated with the + * supplied controller. The descriptor list provides DMA safe/capable + * memory requirements for this controller. + * @controller: This parameter specifies the controller for which to retrieve + * the DMA safe memory descriptor list. + * + * The user must adhere to the alignment requirements specified in memory + * descriptor. In situations where the operating environment does not offer + * memory allocation utilities supporting alignment, then it is the + * responsibility of the user to manually align the memory buffer for SCI. + * Thus, the user may have to allocate a larger buffer to meet the alignment. + * Additionally, the user will need to remember the actual memory allocation + * addresses in order to ensure the memory can be properly freed when necessary + * to do so. This method will return a valid handle, but the MDL may not be + * accurate until after the user has invoked the associated + * sci_controller_initialize() routine. A pointer to a physical memory + * descriptor array. + */ +struct sci_base_memory_descriptor_list * + sci_controller_get_memory_descriptor_list_handle( + struct scic_sds_controller *controller); + + +#endif /* _SCI_CONTROLLER_H_ */ + diff --git a/drivers/scsi/isci/core/sci_controller_constants.h b/drivers/scsi/isci/core/sci_controller_constants.h new file mode 100644 index 000000000000..06c34c7bdd5f --- /dev/null +++ b/drivers/scsi/isci/core/sci_controller_constants.h @@ -0,0 +1,215 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_CONTROLLER_CONSTANTS_H_ +#define _SCI_CONTROLLER_CONSTANTS_H_ + +/** + * This file contains constant values that change based on the type of core or + * framework being managed. These constants are exported in order to + * provide the user with information as to the bounds (i.e. how many) of + * specific objects. + * + * + */ + + +#ifdef SCIC_SDS_4_ENABLED + +#ifndef SCI_MAX_PHYS +/** + * + * + * This constant defines the maximum number of phy objects that can be + * supported for the SCU Driver Standard (SDS) library. This is tied directly + * to silicon capabilities. + */ +#define SCI_MAX_PHYS (4) +#endif + +#ifndef SCI_MAX_PORTS +/** + * + * + * This constant defines the maximum number of port objects that can be + * supported for the SCU Driver Standard (SDS) library. This is tied directly + * to silicon capabilities. + */ +#define SCI_MAX_PORTS SCI_MAX_PHYS +#endif + +#ifndef SCI_MIN_SMP_PHYS +/** + * + * + * This constant defines the minimum number of SMP phy objects that can be + * supported for a single expander level. This was determined by using 36 + * physical phys and room for 2 virtual phys. + */ +#define SCI_MIN_SMP_PHYS (38) +#endif + +#ifndef SCI_MAX_SMP_PHYS +/** + * + * + * This constant defines the maximum number of SMP phy objects that can be + * supported for the SCU Driver Standard (SDS) library. This number can be + * increased if required. + */ +#define SCI_MAX_SMP_PHYS (384) +#endif + +#ifndef SCI_MAX_REMOTE_DEVICES +/** + * + * + * This constant defines the maximum number of remote device objects that can + * be supported for the SCU Driver Standard (SDS) library. This is tied + * directly to silicon capabilities. + */ +#define SCI_MAX_REMOTE_DEVICES (256) +#endif + +#ifndef SCI_MIN_REMOTE_DEVICES +/** + * + * + * This constant defines the minimum number of remote device objects that can + * be supported for the SCU Driver Standard (SDS) library. This # can be + * configured for minimum memory environments to any value less than + * SCI_MAX_REMOTE_DEVICES + */ +#define SCI_MIN_REMOTE_DEVICES (16) +#endif + +#ifndef SCI_MAX_IO_REQUESTS +/** + * + * + * This constant defines the maximum number of IO request objects that can be + * supported for the SCU Driver Standard (SDS) library. This is tied directly + * to silicon capabilities. + */ +#define SCI_MAX_IO_REQUESTS (256) +#endif + +#ifndef SCI_MIN_IO_REQUESTS +/** + * + * + * This constant defines the minimum number of IO request objects that can be + * supported for the SCU Driver Standard (SDS) library. This # can be + * configured for minimum memory environments to any value less than + * SCI_MAX_IO_REQUESTS. + */ +#define SCI_MIN_IO_REQUESTS (1) +#endif + +#ifndef SCI_MAX_MSIX_MESSAGES +/** + * + * + * This constant defines the maximum number of MSI-X interrupt vectors/messages + * supported for an SCU hardware controller instance. + */ +#define SCI_MAX_MSIX_MESSAGES (2) +#endif + +#ifndef SCI_MAX_SCATTER_GATHER_ELEMENTS +/** + * + * + * This constant defines the maximum number of Scatter-Gather Elements to be + * used by any SCI component. + */ +#define SCI_MAX_SCATTER_GATHER_ELEMENTS 130 +#endif + +#ifndef SCI_MIN_SCATTER_GATHER_ELEMENTS +/** + * + * + * This constant defines the minimum number of Scatter-Gather Elements to be + * used by any SCI component. + */ +#define SCI_MIN_SCATTER_GATHER_ELEMENTS 1 +#endif + +#else /* SCIC_SDS_4_ENABLED */ + +#error "SCI Core configuration left unspecified (e.g. SCIC_SDS_4_ENABLED)" + +#endif /* SCIC_SDS_4_ENABLED */ + +/** + * + * + * This constant defines the maximum number of controllers that can occur in a + * single silicon package. + */ +#define SCI_MAX_CONTROLLERS 2 + +/** + * + * + * The maximum number of supported domain objects is currently tied to the + * maximum number of support port objects. + */ +#define SCI_MAX_DOMAINS SCI_MAX_PORTS + + +#endif /* _SCI_CONTROLLER_CONSTANTS_H_ */ + diff --git a/drivers/scsi/isci/core/sci_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_memory_descriptor_list.h new file mode 100644 index 000000000000..44de1c18d2c8 --- /dev/null +++ b/drivers/scsi/isci/core/sci_memory_descriptor_list.h @@ -0,0 +1,169 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_MEMORY_DESCRIPTOR_LIST_H_ +#define _SCI_MEMORY_DESCRIPTOR_LIST_H_ + +/** + * This file contains all of the basic data types utilized by an SCI user or + * implementor. + * + * + */ + + +#include "sci_types.h" + +struct sci_base_memory_descriptor_list; + +/** + * + * + * SCI_MDE_ATTRIBUTES These constants depict memory attributes for the Memory + * Descriptor Entries (MDEs) contained in the MDL. + */ +#define SCI_MDE_ATTRIBUTE_CACHEABLE 0x0001 +#define SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS 0x0002 + +/** + * struct sci_physical_memory_descriptor - This structure defines a description + * of a memory location for the SCI implementation. + * + * + */ +struct sci_physical_memory_descriptor { + /** + * This field contains the virtual address associated with this descriptor + * element. This field shall be zero when the descriptor is retrieved from + * the SCI implementation. The user shall set this field prior + * sci_controller_start() + */ + void *virtual_address; + + /** + * This field contains the physical address associated with this desciptor + * element. This field shall be zero when the descriptor is retrieved from + * the SCI implementation. The user shall set this field prior + * sci_controller_start() + */ + dma_addr_t physical_address; + + /** + * This field contains the size requirement for this memory descriptor. + * A value of zero for this field indicates the end of the descriptor + * list. The value should be treated as read only for an SCI user. + */ + u32 constant_memory_size; + + /** + * This field contains the alignment requirement for this memory + * descriptor. A value of zero for this field indicates the end of the + * descriptor list. All other values indicate the number of bytes to + * achieve the necessary alignment. The value should be treated as + * read only for an SCI user. + */ + u32 constant_memory_alignment; + + /** + * This field contains an indication regarding the desired memory + * attributes for this memory descriptor entry. + * Notes: + * - If the cacheable attribute is set, the user can allocate + * memory that is backed by cache for better performance. It + * is not required that the memory be backed by cache. + * - If the physically contiguous attribute is set, then the + * entire memory must be physically contiguous across all + * page boundaries. + */ + u16 constant_memory_attributes; + +}; + +/** + * sci_mdl_first_entry() - This method simply rewinds the MDL iterator back to + * the first memory descriptor entry in the list. + * @mdl: This parameter specifies the memory descriptor list that is to be + * rewound. + * + */ +void sci_mdl_first_entry( + struct sci_base_memory_descriptor_list *mdl); + +/** + * sci_mdl_next_entry() - This method simply updates the "current" pointer to + * the next sequential memory descriptor. + * @mdl: This parameter specifies the memory descriptor list for which to + * return the next memory descriptor entry in the list. + * + * none. + */ +void sci_mdl_next_entry( + struct sci_base_memory_descriptor_list *mdl); + +/** + * sci_mdl_get_current_entry() - This method simply returns the current memory + * descriptor entry. + * @mdl: This parameter specifies the memory descriptor list for which to + * return the current memory descriptor entry. + * + * This method returns a pointer to the current physical memory descriptor in + * the MDL. NULL This value is returned if there are no descriptors in the list. + */ +struct sci_physical_memory_descriptor *sci_mdl_get_current_entry( + struct sci_base_memory_descriptor_list *mdl); + + +#endif /* _SCI_MEMORY_DESCRIPTOR_LIST_H_ */ + diff --git a/drivers/scsi/isci/core/sci_object.h b/drivers/scsi/isci/core/sci_object.h new file mode 100644 index 000000000000..930694264f1a --- /dev/null +++ b/drivers/scsi/isci/core/sci_object.h @@ -0,0 +1,99 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_OBJECT_H_ +#define _SCI_OBJECT_H_ + +/** + * This file contains all of the method and constants associated with the SCI + * base object. The SCI base object is the class from which all other + * objects derive in the Storage Controller Interface. + * + * + */ + + +#include "sci_types.h" +#include "sci_status.h" + +/** + * struct sci_base_object - all core objects must include this as their + * first member to permit the casting below + * + * TODO: unwind this assumption, convert these routines and callers to pass a struct + * sci_base_object pointer without casting, or convert 'private' to the + * expected type per-object + * + */ +struct sci_base_object { + void *private; +}; + +static inline void *sci_object_get_association(void *obj) +{ + struct sci_base_object *base = obj; + + return base->private; +} + +static inline void sci_object_set_association(void *obj, void *private) +{ + struct sci_base_object *base = obj; + + base->private = private; +} + +#endif /* _SCI_OBJECT_H_ */ + diff --git a/drivers/scsi/isci/core/sci_pool.h b/drivers/scsi/isci/core/sci_pool.h new file mode 100644 index 000000000000..c0d2ea32529b --- /dev/null +++ b/drivers/scsi/isci/core/sci_pool.h @@ -0,0 +1,199 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the interface to the pool class. This class allows two + * different two different priority tasks to insert and remove items from + * the free pool. The user of the pool is expected to evaluate the pool + * condition empty before a get operation and pool condition full before a + * put operation. Methods Provided: - sci_pool_create() - + * sci_pool_initialize() - sci_pool_empty() - sci_pool_full() - + * sci_pool_get() - sci_pool_put() + * + * + */ + +#ifndef _SCI_POOL_H_ +#define _SCI_POOL_H_ + +/** + * SCI_POOL_INCREMENT() - + * + * Private operation for the pool + */ +#define SCI_POOL_INCREMENT(this_pool, index) \ + (((index) + 1) == (this_pool).size ? 0 : (index) + 1) + +/** + * SCI_POOL_CREATE() - + * + * This creates a pool structure of pool_name. The members in the pool are of + * type with number of elements equal to size. + */ +#define SCI_POOL_CREATE(pool_name, type, pool_size) \ + struct \ + { \ + u32 size; \ + u32 get; \ + u32 put; \ + type array[(pool_size) + 1]; \ + } pool_name + + +/** + * sci_pool_empty() - + * + * This macro evaluates the pool and returns true if the pool is empty. If the + * pool is empty the user should not perform any get operation on the pool. + */ +#define sci_pool_empty(this_pool) \ + ((this_pool).get == (this_pool).put) + +/** + * sci_pool_full() - + * + * This macro evaluates the pool and returns true if the pool is full. If the + * pool is full the user should not perform any put operation. + */ +#define sci_pool_full(this_pool) \ + (SCI_POOL_INCREMENT(this_pool, (this_pool).put) == (this_pool).get) + +/** + * sci_pool_size() - + * + * This macro returns the size of the pool created. The internal size of the + * pool is actually 1 larger then necessary in order to ensure get and put + * pointers can be written simultaneously by different users. As a result, + * this macro subtracts 1 from the internal size + */ +#define sci_pool_size(this_pool) \ + ((this_pool).size - 1) + +/** + * sci_pool_count() - + * + * This macro indicates the number of elements currently contained in the pool. + */ +#define sci_pool_count(this_pool) \ + (\ + sci_pool_empty((this_pool)) \ + ? 0 \ + : (\ + sci_pool_full((this_pool)) \ + ? sci_pool_size((this_pool)) \ + : (\ + (this_pool).get > (this_pool).put \ + ? ((this_pool).size - (this_pool).get + (this_pool).put) \ + : ((this_pool).put - (this_pool).get) \ + ) \ + ) \ + ) + +/** + * sci_pool_initialize() - + * + * This macro initializes the pool to an empty condition. + */ +#define sci_pool_initialize(this_pool) \ + { \ + (this_pool).size = (sizeof((this_pool).array) / sizeof((this_pool).array[0])); \ + (this_pool).get = 0; \ + (this_pool).put = 0; \ + } + +/** + * sci_pool_get() - + * + * This macro will get the next free element from the pool. This should only be + * called if the pool is not empty. + */ +#define sci_pool_get(this_pool, my_value) \ + { \ + (my_value) = (this_pool).array[(this_pool).get]; \ + (this_pool).get = SCI_POOL_INCREMENT((this_pool), (this_pool).get); \ + } + +/** + * sci_pool_put() - + * + * This macro will put the value into the pool. This should only be called if + * the pool is not full. + */ +#define sci_pool_put(this_pool, the_value) \ + { \ + (this_pool).array[(this_pool).put] = (the_value); \ + (this_pool).put = SCI_POOL_INCREMENT((this_pool), (this_pool).put); \ + } + +/** + * sci_pool_erase() - + * + * This macro will search the pool and remove any elements in the pool matching + * the supplied value. This method can only be utilized on pools + */ +#define sci_pool_erase(this_pool, type, the_value) \ + { \ + type tmp_value; \ + u32 index; \ + u32 element_count = sci_pool_count((this_pool)); \ + \ + for (index = 0; index < element_count; index++) { \ + sci_pool_get((this_pool), tmp_value); \ + if (tmp_value != (the_value)) \ + sci_pool_put((this_pool), tmp_value); \ + } \ + } + +#endif /* _SCI_POOL_H_ */ diff --git a/drivers/scsi/isci/core/sci_status.h b/drivers/scsi/isci/core/sci_status.h new file mode 100644 index 000000000000..72b61081c28d --- /dev/null +++ b/drivers/scsi/isci/core/sci_status.h @@ -0,0 +1,409 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_STATUS_H_ +#define _SCI_STATUS_H_ + +/** + * This file contains all of the return status codes utilized across the + * various sub-components in SCI. + * + * + */ + + +/** + * enum _SCI_STATUS - This is the general return status enumeration for non-IO, + * non-task management related SCI interface methods. + * + * + */ +enum sci_status { + /** + * This member indicates successful completion. + */ + SCI_SUCCESS = 0, + + /** + * This value indicates that the calling method completed successfully, + * but that the IO may have completed before having it's start method + * invoked. This occurs during SAT translation for requests that do + * not require an IO to the target or for any other requests that may + * be completed without having to submit IO. + */ + SCI_SUCCESS_IO_COMPLETE_BEFORE_START, + + /** + * This Value indicates that the SCU hardware returned an early response + * because the io request specified more data than is returned by the + * target device (mode pages, inquiry data, etc.). The completion routine + * will handle this case to get the actual number of bytes transferred. + */ + SCI_SUCCESS_IO_DONE_EARLY, + + /** + * This member indicates that the object for which a state change is + * being requested is already in said state. + */ + SCI_WARNING_ALREADY_IN_STATE, + + /** + * This member indicates interrupt coalescence timer may cause SAS + * specification compliance issues (i.e. SMP target mode response + * frames must be returned within 1.9 milliseconds). + */ + SCI_WARNING_TIMER_CONFLICT, + + /** + * This field indicates a sequence of action is not completed yet. Mostly, + * this status is used when multiple ATA commands are needed in a SATI translation. + */ + SCI_WARNING_SEQUENCE_INCOMPLETE, + + /** + * This member indicates that there was a general failure. + */ + SCI_FAILURE, + + /** + * This member indicates that the SCI implementation is unable to complete + * an operation due to a critical flaw the prevents any further operation + * (i.e. an invalid pointer). + */ + SCI_FATAL_ERROR, + + /** + * This member indicates the calling function failed, because the state + * of the controller is in a state that prevents successful completion. + */ + SCI_FAILURE_INVALID_STATE, + + /** + * This member indicates the calling function failed, because there is + * insufficient resources/memory to complete the request. + */ + SCI_FAILURE_INSUFFICIENT_RESOURCES, + + /** + * This member indicates the calling function failed, because the + * controller object required for the operation can't be located. + */ + SCI_FAILURE_CONTROLLER_NOT_FOUND, + + /** + * This member indicates the calling function failed, because the + * discovered controller type is not supported by the library. + */ + SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE, + + /** + * This member indicates the calling function failed, because the + * requested initialization data version isn't supported. + */ + SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION, + + /** + * This member indicates the calling function failed, because the + * requested configuration of SAS Phys into SAS Ports is not supported. + */ + SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION, + + /** + * This member indicates the calling function failed, because the + * requested protocol is not supported by the remote device, port, + * or controller. + */ + SCI_FAILURE_UNSUPPORTED_PROTOCOL, + + /** + * This member indicates the calling function failed, because the + * requested information type is not supported by the SCI implementation. + */ + SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE, + + /** + * This member indicates the calling function failed, because the + * device already exists. + */ + SCI_FAILURE_DEVICE_EXISTS, + + /** + * This member indicates the calling function failed, because adding + * a phy to the object is not possible. + */ + SCI_FAILURE_ADDING_PHY_UNSUPPORTED, + + /** + * This member indicates the calling function failed, because the + * requested information type is not supported by the SCI implementation. + */ + SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD, + + /** + * This member indicates the calling function failed, because the SCI + * implementation does not support the supplied time limit. + */ + SCI_FAILURE_UNSUPPORTED_TIME_LIMIT, + + /** + * This member indicates the calling method failed, because the SCI + * implementation does not contain the specified Phy. + */ + SCI_FAILURE_INVALID_PHY, + + /** + * This member indicates the calling method failed, because the SCI + * implementation does not contain the specified Port. + */ + SCI_FAILURE_INVALID_PORT, + + /** + * This member indicates the calling method was partly successful + * The port was reset but not all phys in port are operational + */ + SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS, + + /** + * This member indicates that calling method failed + * The port reset did not complete because none of the phys are operational + */ + SCI_FAILURE_RESET_PORT_FAILURE, + + /** + * This member indicates the calling method failed, because the SCI + * implementation does not contain the specified remote device. + */ + SCI_FAILURE_INVALID_REMOTE_DEVICE, + + /** + * This member indicates the calling method failed, because the remote + * device is in a bad state and requires a reset. + */ + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, + + /** + * This member indicates the calling method failed, because the SCI + * implementation does not contain or support the specified IO tag. + */ + SCI_FAILURE_INVALID_IO_TAG, + + /** + * This member indicates that the operation failed and the user should + * check the response data associated with the IO. + */ + SCI_FAILURE_IO_RESPONSE_VALID, + + /** + * This member indicates that the operation failed, the failure is + * controller implementation specific, and the response data associated + * with the request is not valid. You can query for the controller + * specific error information via scic_controller_get_request_status() + */ + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, + + /** + * This member indicated that the operation failed because the + * user requested this IO to be terminated. + */ + SCI_FAILURE_IO_TERMINATED, + + /** + * This member indicates that the operation failed and the associated + * request requires a SCSI abort task to be sent to the target. + */ + SCI_FAILURE_IO_REQUIRES_SCSI_ABORT, + + /** + * This member indicates that the operation failed because the supplied + * device could not be located. + */ + SCI_FAILURE_DEVICE_NOT_FOUND, + + /** + * This member indicates that the operation failed because the + * objects association is required and is not correctly set. + */ + SCI_FAILURE_INVALID_ASSOCIATION, + + /** + * This member indicates that the operation failed, because a timeout + * occurred. + */ + SCI_FAILURE_TIMEOUT, + + /** + * This member indicates that the operation failed, because the user + * specified a value that is either invalid or not supported. + */ + SCI_FAILURE_INVALID_PARAMETER_VALUE, + + /** + * This value indicates that the operation failed, because the number + * of messages (MSI-X) is not supported. + */ + SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT, + + /** + * This value indicates that the method failed due to a lack of + * available NCQ tags. + */ + SCI_FAILURE_NO_NCQ_TAG_AVAILABLE, + + /** + * This value indicates that a protocol violation has occurred on the + * link. + */ + SCI_FAILURE_PROTOCOL_VIOLATION, + + /** + * This value indicates a failure condition that retry may help to clear. + */ + SCI_FAILURE_RETRY_REQUIRED, + + /** + * This field indicates the retry limit was reached when a retry is attempted + */ + SCI_FAILURE_RETRY_LIMIT_REACHED, + + /** + * This member indicates the calling method was partly successful. + * Mostly, this status is used when a LUN_RESET issued to an expander attached + * STP device in READY NCQ substate needs to have RNC suspended/resumed + * before posting TC. + */ + SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS, + + /** + * This field indicates an illegal phy connection based on the routing attribute + * of both expander phy attached to each other. + */ + SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION, + + /** + * This field indicates a CONFIG ROUTE INFO command has a response with function result + * INDEX DOES NOT EXIST, usually means exceeding max route index. + */ + SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX, + + /** + * This value indicates that an unsupported PCI device ID has been + * specified. This indicates that attempts to invoke + * scic_library_allocate_controller() will fail. + */ + SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID + +}; + +/** + * enum _SCI_IO_STATUS - This enumeration depicts all of the possible IO + * completion status values. Each value in this enumeration maps directly + * to a value in the enum sci_status enumeration. Please refer to that + * enumeration for detailed comments concerning what the status represents. + * + * Add the API to retrieve the SCU status from the core. Check to see that the + * following status are properly handled: - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL + * - SCI_IO_FAILURE_INVALID_IO_TAG + */ +enum sci_io_status { + SCI_IO_SUCCESS = SCI_SUCCESS, + SCI_IO_FAILURE = SCI_FAILURE, + SCI_IO_SUCCESS_COMPLETE_BEFORE_START = SCI_SUCCESS_IO_COMPLETE_BEFORE_START, + SCI_IO_SUCCESS_IO_DONE_EARLY = SCI_SUCCESS_IO_DONE_EARLY, + SCI_IO_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE, + SCI_IO_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES, + SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL, + SCI_IO_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID, + SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, + SCI_IO_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED, + SCI_IO_FAILURE_REQUIRES_SCSI_ABORT = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT, + SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE, + SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE, + SCI_IO_FAILURE_PROTOCOL_VIOLATION = SCI_FAILURE_PROTOCOL_VIOLATION, + + SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, + + SCI_IO_FAILURE_RETRY_REQUIRED = SCI_FAILURE_RETRY_REQUIRED, + SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED, + SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE +}; + +/** + * enum _SCI_TASK_STATUS - This enumeration depicts all of the possible task + * completion status values. Each value in this enumeration maps directly + * to a value in the enum sci_status enumeration. Please refer to that + * enumeration for detailed comments concerning what the status represents. + * + * Check to see that the following status are properly handled: + */ +enum sci_task_status { + SCI_TASK_SUCCESS = SCI_SUCCESS, + SCI_TASK_FAILURE = SCI_FAILURE, + SCI_TASK_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE, + SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES, + SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL, + SCI_TASK_FAILURE_INVALID_TAG = SCI_FAILURE_INVALID_IO_TAG, + SCI_TASK_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID, + SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, + SCI_TASK_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED, + SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE, + + SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, + SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS + +}; + + +#endif /* _SCI_STATUS_H_ */ + diff --git a/drivers/scsi/isci/core/sci_types.h b/drivers/scsi/isci/core/sci_types.h new file mode 100644 index 000000000000..431735d1a589 --- /dev/null +++ b/drivers/scsi/isci/core/sci_types.h @@ -0,0 +1,88 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_TYPES_H_ +#define _SCI_TYPES_H_ + +#include + +#define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ + ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) + +#define SCI_INVALID_HANDLE 0x0 + +/** + * The SCI_LIBRARY_HANDLE_T will be utilized by SCI users as an opaque handle + * for the SCI Library object. + * + * SCI_LIBRARY_HANDLE_T + */ +typedef void *SCI_LIBRARY_HANDLE_T; + + +typedef enum { + SCI_IO_REQUEST_DATA_IN = 0, /* Read operation */ + SCI_IO_REQUEST_DATA_OUT, /* Write operation */ + SCI_IO_REQUEST_NO_DATA +} SCI_IO_REQUEST_DATA_DIRECTION; + + +enum sci_controller_mode { + SCI_MODE_SPEED, /* Optimized for performance */ + SCI_MODE_SIZE /* Optimized for memory use */ +}; + +#endif /* _SCI_TYPES_H_ */ + diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c new file mode 100644 index 000000000000..5cdd96f29a9e --- /dev/null +++ b/drivers/scsi/isci/core/sci_util.c @@ -0,0 +1,70 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sci_util.h" + +void scic_word_copy_with_swap( + u32 *destination, + u32 *source, + u32 word_count) +{ + while (word_count--) { + *destination = SCIC_SWAP_DWORD(*source); + + source++; + destination++; + } +} + diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h new file mode 100644 index 000000000000..67e2badf8ea8 --- /dev/null +++ b/drivers/scsi/isci/core/sci_util.h @@ -0,0 +1,138 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_UTIL_H_ +#define _SCI_UTIL_H_ + +#include "sci_types.h" + +/** + * SCIC_SWAP_DWORD() - + * + * Normal byte swap macro + */ +#define SCIC_SWAP_DWORD(x) \ + (\ + (((x) >> 24) & 0x000000FF) \ + | (((x) >> 8) & 0x0000FF00) \ + | (((x) << 8) & 0x00FF0000) \ + | (((x) << 24) & 0xFF000000) \ + ) + +#define SCIC_BUILD_DWORD(char_buffer) \ + (\ + ((char_buffer)[0] << 24) \ + | ((char_buffer)[1] << 16) \ + | ((char_buffer)[2] << 8) \ + | ((char_buffer)[3]) \ + ) + +#define SCI_FIELD_OFFSET(type, field) ((unsigned long)&(((type *)0)->field)) + +/** + * sci_physical_address_add() - + * + * This macro simply performs addition on an dma_addr_t type. The + * lower u32 value is "clipped" or "wrapped" back through 0. When this occurs + * the upper 32-bits are incremented by 1. + */ +#define sci_physical_address_add(physical_address, value) \ + { \ + u32 lower = lower_32_bits((physical_address)); \ + u32 upper = upper_32_bits((physical_address)); \ + \ + if (lower + (value) < lower) \ + upper += 1; \ + \ + lower += (value); \ + sci_cb_make_physical_address(physical_address, upper, lower); \ + } + +/** + * sci_physical_address_subtract() - + * + * This macro simply performs subtraction on an dma_addr_t type. The + * lower u32 value is "clipped" or "wrapped" back through 0. When this occurs + * the upper 32-bits are decremented by 1. + */ +#define sci_physical_address_subtract(physical_address, value) \ + { \ + u32 lower = lower_32_bits((physical_address)); \ + u32 upper = upper_32_bits((physical_address)); \ + \ + if (lower - (value) > lower) \ + upper -= 1; \ + \ + lower -= (value); \ + sci_cb_make_physical_address(physical_address, upper, lower); \ + } + +/** + * scic_word_copy_with_swap() - Copy the data from source to destination and + * swap the bytes during the copy. + * @destination: This parameter specifies the destination address to which the + * data is to be copied. + * @source: This parameter specifies the source address from which data is to + * be copied. + * @word_count: This parameter specifies the number of 32-bit words to copy and + * byte swap. + * + */ +void scic_word_copy_with_swap( + u32 *destination, + u32 *source, + u32 word_count); + +#endif /* _SCI_UTIL_H_ */ diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h new file mode 100644 index 000000000000..4c16a50a0658 --- /dev/null +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -0,0 +1,347 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_USER_PARAMETERS_H_ +#define _SCIC_SDS_USER_PARAMETERS_H_ + +/** + * This file contains all of the structure definitions and interface methods + * that can be called by a SCIC user on the SCU Driver Standard + * (struct scic_sds_user_parameters) user parameter block. + * + * + */ + + +#include "sci_types.h" +#include "sci_status.h" +#include "intel_sas.h" +#include "sci_controller_constants.h" + +struct scic_sds_controller; + +/** + * + * + * SCIC_SDS_PARM_PHY_SPEED These constants define the speeds utilized for a + * phy/port. + */ +#define SCIC_SDS_PARM_NO_SPEED 0 + +/** + * + * + * This value of 1 indicates generation 1 (i.e. 1.5 Gb/s). + */ +#define SCIC_SDS_PARM_GEN1_SPEED 1 + +/** + * + * + * This value of 2 indicates generation 2 (i.e. 3.0 Gb/s). + */ +#define SCIC_SDS_PARM_GEN2_SPEED 2 + +/** + * + * + * This value of 3 indicates generation 3 (i.e. 6.0 Gb/s). + */ +#define SCIC_SDS_PARM_GEN3_SPEED 3 + +/** + * + * + * For range checks, the max speed generation + */ +#define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED + +/** + * struct scic_sds_user_parameters - This structure delineates the various user + * parameters that can be changed by the core user. + * + * + */ +struct scic_sds_user_parameters { + struct { + /** + * This field specifies the NOTIFY (ENABLE SPIN UP) primitive + * insertion frequency for this phy index. + */ + u32 notify_enable_spin_up_insertion_frequency; + + /** + * This method specifies the number of transmitted DWORDs within which + * to transmit a single ALIGN primitive. This value applies regardless + * of what type of device is attached or connection state. A value of + * 0 indicates that no ALIGN primitives will be inserted. + */ + u16 align_insertion_frequency; + + /** + * This method specifies the number of transmitted DWORDs within which + * to transmit 2 ALIGN primitives. This applies for SAS connections + * only. A minimum value of 3 is required for this field. + */ + u16 in_connection_align_insertion_frequency; + + /** + * This field indicates the maximum speed generation to be utilized + * by phys in the supplied port. + * - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s). + * - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s). + * - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s). + */ + u8 max_speed_generation; + + } phys[SCI_MAX_PHYS]; + + /** + * This field specifies the maximum number of direct attached devices + * that can have power supplied to them simultaneously. + */ + u8 max_number_concurrent_device_spin_up; + + /** + * This field specifies the number of seconds to allow a phy to consume + * power before yielding to another phy. + * + */ + u8 phy_spin_up_delay_interval; + + /** + * These timer values specifies how long a link will remain open with no + * activity in increments of a microsecond, it can be in increments of + * 100 microseconds if the upper most bit is set. + * + */ + u16 stp_inactivity_timeout; + u16 ssp_inactivity_timeout; + + /** + * These timer values specifies how long a link will remain open in increments + * of 100 microseconds. + * + */ + u16 stp_max_occupancy_timeout; + u16 ssp_max_occupancy_timeout; + + /** + * This timer value specifies how long a link will remain open with no + * outbound traffic in increments of a microsecond. + * + */ + u8 no_outbound_task_timeout; + +}; + +/** + * This structure/union specifies the various different user parameter sets + * available. Each type is specific to a hardware controller version. + * + * union scic_user_parameters + */ +union scic_user_parameters { + /** + * This field specifies the user parameters specific to the + * Storage Controller Unit (SCU) Driver Standard (SDS) version + * 1. + */ + struct scic_sds_user_parameters sds1; + +}; + + +/** + * + * + * SCIC_SDS_OEM_PHY_MASK These constants define the valid values for phy_mask + */ + +/** + * + * + * This is the min value assignable to a port's phy mask + */ +#define SCIC_SDS_PARM_PHY_MASK_MIN 0x0 + +/** + * + * + * This is the max value assignable to a port's phy mask + */ +#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF + +/** + * struct scic_sds_oem_parameters - This structure delineates the various OEM + * parameters that must be set the core user. + * + * + */ +struct scic_sds_oem_parameters { + struct { + /** + * This field indicates whether Spread Spectrum Clocking (SSC) + * should be enabled or disabled. + */ + bool do_enable_ssc; + + } controller; + + struct { + /** + * This field specifies the phys to be contained inside a port. + * The bit position in the mask specifies the index of the phy + * to be contained in the port. Multiple bits (i.e. phys) + * can be contained in a single port. + */ + u8 phy_mask; + + } ports[SCI_MAX_PORTS]; + + struct { + /** + * This field specifies the SAS address to be transmitted on + * for this phy index. + */ + struct sci_sas_address sas_address; + + } phys[SCI_MAX_PHYS]; + +}; + +/** + * This structure/union specifies the various different OEM parameter sets + * available. Each type is specific to a hardware controller version. + * + * union scic_oem_parameters + */ +union scic_oem_parameters { + /** + * This field specifies the OEM parameters specific to the + * Storage Controller Unit (SCU) Driver Standard (SDS) version + * 1. + */ + struct scic_sds_oem_parameters sds1; + +}; + +/** + * scic_user_parameters_set() - This method allows the user to attempt to + * change the user parameters utilized by the controller. + * @controller: This parameter specifies the controller on which to set the + * user parameters. + * @user_parameters: This parameter specifies the USER_PARAMETERS object + * containing the potential new values. + * + * Indicate if the update of the user parameters was successful. SCI_SUCCESS + * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE + * This value is returned if the attempt to change the user parameter failed, + * because changing one of the parameters is not currently allowed. + * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user + * supplied an invalid interrupt coalescence time, spin up delay interval, etc. + */ +enum sci_status scic_user_parameters_set( + struct scic_sds_controller *controller, + union scic_user_parameters *user_parameters); + +/** + * scic_user_parameters_get() - This method allows the user to retrieve the + * user parameters utilized by the controller. + * @controller: This parameter specifies the controller on which to set the + * user parameters. + * @user_parameters: This parameter specifies the USER_PARAMETERS object into + * which the framework shall save it's parameters. + * + */ +void scic_user_parameters_get( + struct scic_sds_controller *controller, + union scic_user_parameters *user_parameters); + +/** + * scic_oem_parameters_set() - This method allows the user to attempt to change + * the OEM parameters utilized by the controller. + * @controller: This parameter specifies the controller on which to set the + * user parameters. + * @oem_parameters: This parameter specifies the OEM parameters object + * containing the potential new values. + * + * Indicate if the update of the user parameters was successful. SCI_SUCCESS + * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE + * This value is returned if the attempt to change the user parameter failed, + * because changing one of the parameters is not currently allowed. + * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user + * supplied an unsupported value for one of the OEM parameters. + */ +enum sci_status scic_oem_parameters_set( + struct scic_sds_controller *controller, + union scic_oem_parameters *oem_parameters); + +/** + * scic_oem_parameters_get() - This method allows the user to retreive the OEM + * parameters utilized by the controller. + * @controller: This parameter specifies the controller on which to set the + * user parameters. + * @oem_parameters: This parameter specifies the OEM parameters object in which + * to write the core's OEM parameters. + * + */ +void scic_oem_parameters_get( + struct scic_sds_controller *controller, + union scic_oem_parameters *oem_parameters); + + +#endif /* _SCIC_SDS_USER_PARAMETERS_H_ */ + diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h new file mode 100644 index 000000000000..756b14fcd9a4 --- /dev/null +++ b/drivers/scsi/isci/core/scic_controller.h @@ -0,0 +1,586 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_CONTROLLER_H_ +#define _SCIC_CONTROLLER_H_ + +/** + * This file contains all of the interface methods that can be called by an + * SCIC user on a controller object. + * + * + */ + + +#include "sci_types.h" +#include "sci_status.h" +#include "sci_controller.h" +#include "scic_config_parameters.h" + +struct scic_sds_request; +struct scic_sds_phy; +struct scic_sds_port; +struct scic_sds_remote_device; + +/** + * enum _SCIC_INTERRUPT_TYPE - This enumeration depicts the various types of + * interrupts that are potentially supported by a SCI Core implementation. + * + * + */ +enum scic_interrupt_type { + SCIC_LEGACY_LINE_INTERRUPT_TYPE, + SCIC_MSIX_INTERRUPT_TYPE, + + /** + * This enumeration value indicates the use of polling. + */ + SCIC_NO_INTERRUPTS + +}; + +/** + * This method is called by the SCI user in order to have the SCI + * implementation handle the interrupt. This method performs minimal + * processing to allow for streamlined interrupt time usage. + * + * SCIC_CONTROLLER_INTERRUPT_HANDLER true: returned if there is an interrupt to + * process and it was processed. false: returned if no interrupt was processed. + */ +typedef bool (*SCIC_CONTROLLER_INTERRUPT_HANDLER)( + struct scic_sds_controller *controller + ); + +/** + * This method is called by the SCI user to process completions generated as a + * result of a previously handled interrupt. This method will result in the + * completion of IO requests and handling of other controller generated + * events. This method should be called some time after the interrupt + * handler. + * + * Most, if not all, of the user callback APIs are invoked from within this + * API. As a result, the user should be cognizent of the operating level at + * which they invoke this API. + */ +typedef void (*SCIC_CONTROLLER_COMPLETION_HANDLER)( + struct scic_sds_controller *controller + ); + +/** + * struct scic_controller_handler_methods - This structure contains an + * interrupt handler and completion handler function pointers. + * + * + */ +struct scic_controller_handler_methods { + SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler; + SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler; + +}; + +/** + * scic_controller_construct() - This method will attempt to construct a + * controller object utilizing the supplied parameter information. + * @c: This parameter specifies the controller to be constructed. + * @scu_base: mapped base address of the scu registers + * @smu_base: mapped base address of the smu registers + * + * Indicate if the controller was successfully constructed or if it failed in + * some way. SCI_SUCCESS This value is returned if the controller was + * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned + * if the interrupt coalescence timer may cause SAS compliance issues for SMP + * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE + * This value is returned if the controller does not support the supplied type. + * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the + * controller does not support the supplied initialization data version. + */ +enum sci_status scic_controller_construct(struct scic_sds_controller *c, + void __iomem *scu_base, + void __iomem *smu_base); + +/** + * scic_controller_enable_interrupts() - This method will enable all controller + * interrupts. + * @controller: This parameter specifies the controller for which to enable + * interrupts. + * + */ +void scic_controller_enable_interrupts( + struct scic_sds_controller *controller); + +/** + * scic_controller_disable_interrupts() - This method will disable all + * controller interrupts. + * @controller: This parameter specifies the controller for which to disable + * interrupts. + * + */ +void scic_controller_disable_interrupts( + struct scic_sds_controller *controller); + +/** + * scic_controller_get_handler_methods() - This method will return provide + * function pointers for the interrupt handler and completion handler. The + * interrupt handler is expected to be invoked at interrupt time. The + * completion handler is scheduled to run as a result of the interrupt + * handler. The completion handler performs the bulk work for processing + * silicon events. + * @interrupt_type: This parameter informs the core which type of + * interrupt/completion methods are being requested. These are the types: + * SCIC_LEGACY_LINE_INTERRUPT_TYPE, SCIC_MSIX_INTERRUPT_TYPE, + * SCIC_NO_INTERRUPTS (POLLING) + * @message_count: This parameter informs the core the number of MSI-X messages + * to be utilized. This parameter must be 0 when requesting legacy line + * based handlers. + * @handler_methods: The caller provides a pointer to a buffer of type + * struct scic_controller_handler_methods. The size depends on the combination of + * the interrupt_type and message_count input parameters: + * SCIC_LEGACY_LINE_INTERRUPT_TYPE: - size = + * sizeof(struct scic_controller_handler_methods) SCIC_MSIX_INTERRUPT_TYPE: + * sizeof(struct scic_controller_handler_methods) + * @handler_methods: SCIC fills out the caller's buffer with the appropriate + * interrupt and completion handlers based on the info provided in the + * interrupt_type and message_count input parameters. For + * SCIC_LEGACY_LINE_INTERRUPT_TYPE, the buffer receives a single + * struct scic_controller_handler_methods element regardless that the + * message_count parameter is zero. For SCIC_MSIX_INTERRUPT_TYPE, the buffer + * receives an array of elements of type struct scic_controller_handler_methods + * where the array size is equivalent to the message_count parameter. The + * array is zero-relative where entry zero corresponds to message-vector + * zero, entry one corresponds to message-vector one, and so forth. + * + * Indicate if the handler retrieval operation was successful. SCI_SUCCESS This + * value is returned if retrieval succeeded. + * SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT This value is returned if the user + * supplied an unsupported number of MSI-X messages. For legacy line interrupts + * the only valid value is 0. + */ +enum sci_status scic_controller_get_handler_methods( + enum scic_interrupt_type interrupt_type, + u16 message_count, + struct scic_controller_handler_methods *handler_methods); + +/** + * scic_controller_initialize() - This method will initialize the controller + * hardware managed by the supplied core controller object. This method + * will bring the physical controller hardware out of reset and enable the + * core to determine the capabilities of the hardware being managed. Thus, + * the core controller can determine it's exact physical (DMA capable) + * memory requirements. + * @controller: This parameter specifies the controller to be initialized. + * + * The SCI Core user must have called scic_controller_construct() on the + * supplied controller object previously. Indicate if the controller was + * successfully initialized or if it failed in some way. SCI_SUCCESS This value + * is returned if the controller hardware was successfully initialized. + */ +enum sci_status scic_controller_initialize( + struct scic_sds_controller *controller); + +/** + * scic_controller_get_suggested_start_timeout() - This method returns the + * suggested scic_controller_start() timeout amount. The user is free to + * use any timeout value, but this method provides the suggested minimum + * start timeout value. The returned value is based upon empirical + * information determined as a result of interoperability testing. + * @controller: the handle to the controller object for which to return the + * suggested start timeout. + * + * This method returns the number of milliseconds for the suggested start + * operation timeout. + */ +u32 scic_controller_get_suggested_start_timeout( + struct scic_sds_controller *controller); + +/** + * scic_controller_start() - This method will start the supplied core + * controller. This method will start the staggered spin up operation. The + * SCI User completion callback is called when the following conditions are + * met: -# the return status of this method is SCI_SUCCESS. -# after all of + * the phys have successfully started or been given the opportunity to start. + * @controller: the handle to the controller object to start. + * @timeout: This parameter specifies the number of milliseconds in which the + * start operation should complete. + * + * The SCI Core user must have filled in the physical memory descriptor + * structure via the sci_controller_get_memory_descriptor_list() method. The + * SCI Core user must have invoked the scic_controller_initialize() method + * prior to invoking this method. The controller must be in the INITIALIZED or + * STARTED state. Indicate if the controller start method succeeded or failed + * in some way. SCI_SUCCESS if the start operation succeeded. + * SCI_WARNING_ALREADY_IN_STATE if the controller is already in the STARTED + * state. SCI_FAILURE_INVALID_STATE if the controller is not either in the + * INITIALIZED or STARTED states. SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if + * there are inconsistent or invalid values in the supplied + * struct sci_physical_memory_descriptor array. + */ +enum sci_status scic_controller_start( + struct scic_sds_controller *controller, + u32 timeout); + +/** + * scic_controller_stop() - This method will stop an individual controller + * object.This method will invoke the associated user callback upon + * completion. The completion callback is called when the following + * conditions are met: -# the method return status is SCI_SUCCESS. -# the + * controller has been quiesced. This method will ensure that all IO + * requests are quiesced, phys are stopped, and all additional operation by + * the hardware is halted. + * @controller: the handle to the controller object to stop. + * @timeout: This parameter specifies the number of milliseconds in which the + * stop operation should complete. + * + * The controller must be in the STARTED or STOPPED state. Indicate if the + * controller stop method succeeded or failed in some way. SCI_SUCCESS if the + * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the + * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the + * controller is not either in the STARTED or STOPPED states. + */ +enum sci_status scic_controller_stop( + struct scic_sds_controller *controller, + u32 timeout); + +/** + * scic_controller_reset() - This method will reset the supplied core + * controller regardless of the state of said controller. This operation is + * considered destructive. In other words, all current operations are wiped + * out. No IO completions for outstanding devices occur. Outstanding IO + * requests are not aborted or completed at the actual remote device. + * @controller: the handle to the controller object to reset. + * + * Indicate if the controller reset method succeeded or failed in some way. + * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if + * the controller reset operation is unable to complete. + */ +enum sci_status scic_controller_reset( + struct scic_sds_controller *controller); + +/** + * scic_controller_start_io() - This method is called by the SCI user to + * send/start an IO request. If the method invocation is successful, then + * the IO request has been queued to the hardware for processing. + * @controller: the handle to the controller object for which to start an IO + * request. + * @remote_device: the handle to the remote device object for which to start an + * IO request. + * @io_request: the handle to the io request object to start. + * @io_tag: This parameter specifies a previously allocated IO tag that the + * user desires to be utilized for this request. This parameter is optional. + * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value + * for this parameter. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a + * result, it is expected the user will have set the NCQ tag field in the host + * to device register FIS prior to calling this method. There is also a + * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking + * the scic_controller_start_io() method. scic_controller_allocate_tag() for + * more information on allocating a tag. Indicate if the controller + * successfully started the IO request. SCI_IO_SUCCESS if the IO request was + * successfully started. Determine the failure situations and return values. + */ +enum sci_io_status scic_controller_start_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *io_request, + u16 io_tag); + + +/** + * scic_controller_start_task() - This method is called by the SCIC user to + * send/start a framework task management request. + * @controller: the handle to the controller object for which to start the task + * management request. + * @remote_device: the handle to the remote device object for which to start + * the task management request. + * @task_request: the handle to the task request object to start. + * @io_tag: This parameter specifies a previously allocated IO tag that the + * user desires to be utilized for this request. Note this not the io_tag + * of the request being managed. It is to be utilized for the task request + * itself. This parameter is optional. The user is allowed to supply + * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - The user must synchronize this task with completion + * queue processing. If they are not synchronized then it is possible for the + * io requests that are being managed by the task request can complete before + * starting the task request. scic_controller_allocate_tag() for more + * information on allocating a tag. Indicate if the controller successfully + * started the IO request. SCI_TASK_SUCCESS if the task request was + * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is + * returned if there is/are task(s) outstanding that require termination or + * completion before this request can succeed. + */ +enum sci_task_status scic_controller_start_task( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *task_request, + u16 io_tag); + +/** + * scic_controller_complete_task() - This method will perform core specific + * completion operations for task management request. After this method is + * invoked, the user should consider the task request as invalid until it is + * properly reused (i.e. re-constructed). + * @controller: The handle to the controller object for which to complete the + * task management request. + * @remote_device: The handle to the remote device object for which to complete + * the task management request. + * @task_request: the handle to the task management request object to complete. + * + * Indicate if the controller successfully completed the task management + * request. SCI_SUCCESS if the completion process was successful. + */ +enum sci_status scic_controller_complete_task( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *task_request); + + +/** + * scic_controller_terminate_request() - This method is called by the SCI Core + * user to terminate an ongoing (i.e. started) core IO request. This does + * not abort the IO request at the target, but rather removes the IO request + * from the host controller. + * @controller: the handle to the controller object for which to terminate a + * request. + * @remote_device: the handle to the remote device object for which to + * terminate a request. + * @request: the handle to the io or task management request object to + * terminate. + * + * Indicate if the controller successfully began the terminate process for the + * IO request. SCI_SUCCESS if the terminate process was successfully started + * for the request. Determine the failure situations and return values. + */ +enum sci_status scic_controller_terminate_request( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *request); + +/** + * scic_controller_complete_io() - This method will perform core specific + * completion operations for an IO request. After this method is invoked, + * the user should consider the IO request as invalid until it is properly + * reused (i.e. re-constructed). + * @controller: The handle to the controller object for which to complete the + * IO request. + * @remote_device: The handle to the remote device object for which to complete + * the IO request. + * @io_request: the handle to the io request object to complete. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI + * Core user, using the scic_controller_allocate_io_tag() method, then it is + * the responsibility of the caller to invoke the scic_controller_free_io_tag() + * method to free the tag (i.e. this method will not free the IO tag). Indicate + * if the controller successfully completed the IO request. SCI_SUCCESS if the + * completion process was successful. + */ +enum sci_status scic_controller_complete_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *io_request); + + +/** + * scic_controller_get_port_handle() - This method simply provides the user + * with a unique handle for a given SAS/SATA core port index. + * @controller: This parameter represents the handle to the controller object + * from which to retrieve a port (SAS or SATA) handle. + * @port_index: This parameter specifies the port index in the controller for + * which to retrieve the port handle. 0 <= port_index < maximum number of + * phys. + * @port_handle: This parameter specifies the retrieved port handle to be + * provided to the caller. + * + * Indicate if the retrieval of the port handle was successful. SCI_SUCCESS + * This value is returned if the retrieval was successful. + * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port id is + * not in the supported range. + */ +enum sci_status scic_controller_get_port_handle( + struct scic_sds_controller *controller, + u8 port_index, + struct scic_sds_port **port_handle); + +/** + * scic_controller_get_phy_handle() - This method simply provides the user with + * a unique handle for a given SAS/SATA phy index/identifier. + * @controller: This parameter represents the handle to the controller object + * from which to retrieve a phy (SAS or SATA) handle. + * @phy_index: This parameter specifies the phy index in the controller for + * which to retrieve the phy handle. 0 <= phy_index < maximum number of phys. + * @phy_handle: This parameter specifies the retrieved phy handle to be + * provided to the caller. + * + * Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This + * value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY + * This value is returned if the supplied phy id is not in the supported range. + */ +enum sci_status scic_controller_get_phy_handle( + struct scic_sds_controller *controller, + u8 phy_index, + struct scic_sds_phy **phy_handle); + +/** + * scic_controller_allocate_io_tag() - This method will allocate a tag from the + * pool of free IO tags. Direct allocation of IO tags by the SCI Core user + * is optional. The scic_controller_start_io() method will allocate an IO + * tag if this method is not utilized and the tag is not supplied to the IO + * construct routine. Direct allocation of IO tags may provide additional + * performance improvements in environments capable of supporting this usage + * model. Additionally, direct allocation of IO tags also provides + * additional flexibility to the SCI Core user. Specifically, the user may + * retain IO tags across the lives of multiple IO requests. + * @controller: the handle to the controller object for which to allocate the + * tag. + * + * IO tags are a protected resource. It is incumbent upon the SCI Core user to + * ensure that each of the methods that may allocate or free available IO tags + * are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). An unsigned integer representing an available IO tag. + * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no + * currently available tags to be allocated. All return other values indicate a + * legitimate tag. + */ +u16 scic_controller_allocate_io_tag( + struct scic_sds_controller *controller); + +/** + * scic_controller_free_io_tag() - This method will free an IO tag to the pool + * of free IO tags. This method provides the SCI Core user more flexibility + * with regards to IO tags. The user may desire to keep an IO tag after an + * IO request has completed, because they plan on re-using the tag for a + * subsequent IO request. This method is only legal if the tag was + * allocated via scic_controller_allocate_io_tag(). + * @controller: This parameter specifies the handle to the controller object + * for which to free/return the tag. + * @io_tag: This parameter represents the tag to be freed to the pool of + * available tags. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI + * Core user, using the scic_controller_allocate_io_tag() method, then it is + * the responsibility of the caller to invoke this method to free the tag. This + * method returns an indication of whether the tag was successfully put back + * (freed) to the pool of available tags. SCI_SUCCESS This return value + * indicates the tag was successfully placed into the pool of available IO + * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag + * is not a valid IO tag value. + */ +enum sci_status scic_controller_free_io_tag( + struct scic_sds_controller *controller, + u16 io_tag); + + + + +/** + * scic_controller_set_mode() - This method allows the user to configure the + * SCI core into either a performance mode or a memory savings mode. + * @controller: This parameter represents the handle to the controller object + * for which to update the operating mode. + * @mode: This parameter specifies the new mode for the controller. + * + * Indicate if the user successfully change the operating mode of the + * controller. SCI_SUCCESS The user successfully updated the mode. + */ +enum sci_status scic_controller_set_mode( + struct scic_sds_controller *controller, + enum sci_controller_mode mode); + + +/** + * scic_controller_set_interrupt_coalescence() - This method allows the user to + * configure the interrupt coalescence. + * @controller: This parameter represents the handle to the controller object + * for which its interrupt coalesce register is overridden. + * @coalesce_number: Used to control the number of entries in the Completion + * Queue before an interrupt is generated. If the number of entries exceed + * this number, an interrupt will be generated. The valid range of the input + * is [0, 256]. A setting of 0 results in coalescing being disabled. + * @coalesce_timeout: Timeout value in microseconds. The valid range of the + * input is [0, 2700000] . A setting of 0 is allowed and results in no + * interrupt coalescing timeout. + * + * Indicate if the user successfully set the interrupt coalesce parameters. + * SCI_SUCCESS The user successfully updated the interrutp coalescence. + * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range. + */ +enum sci_status scic_controller_set_interrupt_coalescence( + struct scic_sds_controller *controller, + u32 coalesce_number, + u32 coalesce_timeout); + +struct device; +struct scic_sds_controller *scic_controller_alloc(struct device *dev); + + +#endif /* _SCIC_CONTROLLER_H_ */ + diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h new file mode 100644 index 000000000000..7378f335066c --- /dev/null +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -0,0 +1,512 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_IO_REQUEST_H_ +#define _SCIC_IO_REQUEST_H_ + +/** + * This file contains the structures and interface methods that can be + * referenced and used by the SCI user for the SCI IO request object. + * + * Determine the failure situations and return values. + */ + + +#include "sci_types.h" +#include "sci_status.h" +#include "intel_sas.h" + +struct scic_sds_request; +struct scic_sds_remote_device; +struct scic_sds_controller; + +/** + * struct scic_io_parameters - This structure contains additional optional + * parameters for SSP IO requests. These parameters are utilized with the + * scic_io_request_construct_advanced_ssp() method. + * + * Add Block-guard/DIF, TLR + */ +struct scic_io_parameters { + /** + * This sub-structure contains SCSI specific features (for use with SSP + * IO requests). + */ + struct { + /** + * Data Integrity Format (DIF) is also known as protection information + * or block-guard. This sub-structure contains DIF specific feature + * information for SSP IO requests. + */ + struct { + void *placeholder; + } dif; + + /** + * Transport Layer Retries (TLR) is an SSP protocol specific feature. + * This sub-structure contains Transport Layer Retries (TLR) specific + * feature information for SSP IO requests. + */ + struct { + void *placeholder; + } tlr; + + } scsi; + +}; + +/** + * struct scic_passthru_request_callbacks - This structure contains the pointer + * to the callback functions for constructing the passthrough request common + * to SSP, SMP and STP. This structure must be set by the win sci layer + * before the passthrough build is called + * + * + */ +struct scic_passthru_request_callbacks { + /** + * Function pointer to get the phy identifier for passthrough request. + */ + u32 (*scic_cb_passthru_get_phy_identifier)(void *, u8 *); + /** + * Function pointer to get the port identifier for passthrough request. + */ + u32 (*scic_cb_passthru_get_port_identifier)(void *, u8 *); + /** + * Function pointer to get the connection rate for passthrough request. + */ + u32 (*scic_cb_passthru_get_connection_rate)(void *, void *); + /** + * Function pointer to get the destination sas address for passthrough request. + */ + void (*scic_cb_passthru_get_destination_sas_address)(void *, u8 **); + /** + * Function pointer to get the transfer length for passthrough request. + */ + u32 (*scic_cb_passthru_get_transfer_length)(void *); + /** + * Function pointer to get the data direction for passthrough request. + */ + u32 (*scic_cb_passthru_get_data_direction)(void *); + +}; + +/** + * struct scic_ssp_passthru_request_callbacks - This structure contains the + * pointer to the callback functions for constructing the passthrough + * request specific to SSP. This structure must be set by the win sci layer + * before the passthrough build is called + * + * + */ +struct scic_ssp_passthru_request_callbacks { + /** + * Common callbacks for all Passthru requests + */ + struct scic_passthru_request_callbacks common_callbacks; + /** + * Function pointer to get the lun for passthrough request. + */ + void (*scic_cb_ssp_passthru_get_lun)(void *, u8 **); + /** + * Function pointer to get the cdb + */ + void (*scic_cb_ssp_passthru_get_cdb)(void *, u32 *, u8 **, u32 *, u8 **); + /** + * Function pointer to get the task attribute for passthrough request. + */ + u32 (*scic_cb_ssp_passthru_get_task_attribute)(void *); +}; + +/** + * struct scic_stp_passthru_request_callbacks - This structure contains the + * pointer to the callback functions for constructing the passthrough + * request specific to STP. This structure must be set by the win sci layer + * before the passthrough build is called + * + * + */ +struct scic_stp_passthru_request_callbacks { + /** + * Common callbacks for all Passthru requests + */ + struct scic_passthru_request_callbacks common_callbacks; + /** + * Function pointer to get the protocol for passthrough request. + */ + u8 (*scic_cb_stp_passthru_get_protocol)(void *); + /** + * Function pointer to get the resgister fis + */ + void (*scic_cb_stp_passthru_get_register_fis)(void *, u8 **); + /** + * Function pointer to get the MULTIPLE_COUNT (bits 5,6,7 in Byte 1 in the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) + */ + u8 (*scic_cb_stp_passthru_get_multiplecount)(void *); + /** + * Function pointer to get the EXTEND (bit 0 in Byte 1 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) + */ + u8 (*scic_cb_stp_passthru_get_extend)(void *); + /** + * Function pointer to get the CK_COND (bit 5 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) + */ + u8 (*scic_cb_stp_passthru_get_ckcond)(void *); + /** + * Function pointer to get the T_DIR (bit 3 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) + */ + u8 (*scic_cb_stp_passthru_get_tdir)(void *); + /** + * Function pointer to get the BYTE_BLOCK (bit 2 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) + */ + u8 (*scic_cb_stp_passthru_get_byteblock)(void *); + /** + * Function pointer to get the T_LENGTH (bits 0,1 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) + */ + u8 (*scic_cb_stp_passthru_get_tlength)(void *); + +}; + +/** + * struct scic_smp_passthru_request_callbacks - This structure contains the + * pointer to the callback functions for constructing the passthrough + * request specific to SMP. This structure must be set by the win sci layer + * before the passthrough build is called + * + * + */ +struct scic_smp_passthru_request_callbacks { + /** + * Common callbacks for all Passthru requests + */ + struct scic_passthru_request_callbacks common_callbacks; + + /** + * Function pointer to get the length of the smp request and its length + */ + u32 (*scic_cb_smp_passthru_get_request)(void *, u8 **); + /** + * Function pointer to get the frame type of the smp request + */ + u8 (*scic_cb_smp_passthru_get_frame_type)(void *); + /** + * Function pointer to get the function in the the smp request + */ + u8 (*scic_cb_smp_passthru_get_function)(void *); + + /** + * Function pointer to get the "allocated response length" in the the smp request + */ + u8 (*scic_cb_smp_passthru_get_allocated_response_length)(void *); + +}; + +/** + * This enumeration specifies the transport protocol utilized for the request. + * + * + */ +typedef enum { + /** + * This enumeration constant indicates that no protocol has yet been + * set. + */ + SCIC_NO_PROTOCOL, + + /** + * This enumeration constant indicates that the protocol utilized + * is the Serial Management Protocol. + */ + SCIC_SMP_PROTOCOL, + + /** + * This enumeration constant indicates that the protocol utilized + * is the Serial SCSI Protocol. + */ + SCIC_SSP_PROTOCOL, + + /** + * This enumeration constant indicates that the protocol utilized + * is the Serial-ATA Tunneling Protocol. + */ + SCIC_STP_PROTOCOL + +} SCIC_TRANSPORT_PROTOCOL; + + +/** + * scic_io_request_get_object_size() - This method simply returns the size + * required to build an SCI based IO request object. + * + * Return the size of the SCI IO request object. + */ +u32 scic_io_request_get_object_size( + void); + +/** + * scic_io_request_construct() - This method is called by the SCI user to + * construct all SCI Core IO requests. Memory initialization and + * functionality common to all IO request types is performed in this method. + * @scic_controller: the handle to the core controller object for which to + * build an IO request. + * @scic_remote_device: the handle to the core remote device object for which + * to build an IO request. + * @io_tag: This parameter specifies the IO tag to be associated with this + * request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the + * request is built internally. The request will be copied into the actual + * controller request memory when the IO tag is allocated internally during + * the scic_controller_start_io() method. + * @user_io_request_object: This parameter specifies the user IO request to be + * utilized during IO construction. This IO pointer will become the + * associated object for the core IO request object. + * @scic_io_request_memory: This parameter specifies the memory location to be + * utilized when building the core request. + * @new_scic_io_request_handle: This parameter specifies a pointer to the + * handle the core will expect in further interactions with the core IO + * request object. + * + * The SCI core implementation will create an association between the user IO + * request object and the core IO request object. Indicate if the controller + * successfully built the IO request. SCI_SUCCESS This value is returned if the + * IO request was successfully built. + */ +enum sci_status scic_io_request_construct( + struct scic_sds_controller *scic_controller, + struct scic_sds_remote_device *scic_remote_device, + u16 io_tag, + void *user_io_request_object, + void *scic_io_request_memory, + struct scic_sds_request **new_scic_io_request_handle); + +/** + * scic_io_request_construct_basic_ssp() - This method is called by the SCI + * user to build an SSP IO request. + * @scic_io_request: This parameter specifies the handle to the io request + * object to be built. + * + * - The user must have previously called scic_io_request_construct() on the + * supplied IO request. Indicate if the controller successfully built the IO + * request. SCI_SUCCESS This value is returned if the IO request was + * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned + * if the remote_device does not support the SSP protocol. + * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not + * properly set the association between the SCIC IO request and the user's IO + * request. Please refer to the sci_object_set_association() routine for more + * information. + */ +enum sci_status scic_io_request_construct_basic_ssp( + struct scic_sds_request *scic_io_request); + + + + + +/** + * scic_io_request_construct_basic_sata() - This method is called by the SCI + * Core user to build an STP IO request. + * @scic_io_request: This parameter specifies the handle to the io request + * object to be built. + * + * - The user must have previously called scic_io_request_construct() on the + * supplied IO request. Indicate if the controller successfully built the IO + * request. SCI_SUCCESS This value is returned if the IO request was + * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned + * if the remote_device does not support the STP protocol. + * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not + * properly set the association between the SCIC IO request and the user's IO + * request. Please refer to the sci_object_set_association() routine for more + * information. + */ +enum sci_status scic_io_request_construct_basic_sata( + struct scic_sds_request *scic_io_request); + + + + +/** + * scic_io_request_construct_smp() - This method is called by the SCI user to + * build an SMP IO request. + * @scic_io_request: This parameter specifies the handle to the io request + * object to be built. + * + * - The user must have previously called scic_io_request_construct() on the + * supplied IO request. Indicate if the controller successfully built the IO + * request. SCI_SUCCESS This value is returned if the IO request was + * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned + * if the remote_device does not support the SMP protocol. + * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not + * properly set the association between the SCIC IO request and the user's IO + * request. Please refer to the sci_object_set_association() routine for more + * information. + */ +enum sci_status scic_io_request_construct_smp( + struct scic_sds_request *scic_io_request); + + + +/** + * scic_request_get_controller_status() - This method returns the controller + * specific IO/Task request status. These status values are unique to the + * specific controller being managed by the SCIC. + * @io_request: the handle to the IO or task management request object for + * which to retrieve the status. + * + * This method returns a value indicating the controller specific request + * status. + */ +u32 scic_request_get_controller_status( + struct scic_sds_request *io_request); + + + +/** + * scic_io_request_get_command_iu_address() - This method will return the + * address to the command information unit. + * @scic_io_request: This parameter specifies the handle to the io request + * object to be built. + * + * The address of the SSP/SMP command information unit. + */ +void *scic_io_request_get_command_iu_address( + struct scic_sds_request *scic_io_request); + +/** + * scic_io_request_get_response_iu_address() - This method will return the + * address to the response information unit. For an SSP request this buffer + * is only valid if the IO request is completed with the status + * SCI_FAILURE_IO_RESPONSE_VALID. + * @scic_io_request: This parameter specifies the handle to the io request + * object to be built. + * + * The address of the SSP/SMP response information unit. + */ +void *scic_io_request_get_response_iu_address( + struct scic_sds_request *scic_io_request); + +/** + * scic_io_request_get_io_tag() - This method will return the IO tag utilized + * by the IO request. + * @scic_io_request: This parameter specifies the handle to the io request + * object for which to return the IO tag. + * + * An unsigned integer representing the IO tag being utilized. + * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if the IO does not + * currently have an IO tag allocated to it. All return other values indicate a + * legitimate tag. + */ +u16 scic_io_request_get_io_tag( + struct scic_sds_request *scic_io_request); + + +/** + * scic_stp_io_request_set_ncq_tag() - This method will assign an NCQ tag to + * the io request object. The caller of this function must make sure that + * only valid NCQ tags are assigned to the io request object. + * @scic_io_request: This parameter specifies the handle to the io request + * object to which to assign the ncq tag. + * @ncq_tag: This parameter specifies the NCQ tag to be utilized for the + * supplied core IO request. It is up to the user to make sure that this is + * a valid NCQ tag. + * + * none This function is only valid for SATA NCQ requests. + */ +void scic_stp_io_request_set_ncq_tag( + struct scic_sds_request *scic_io_request, + u16 ncq_tag); + +/** + * scic_stp_io_request_get_h2d_reg_address() - This method will return the + * address of the host to device register fis region for the io request + * object. + * @scic_io_request: This parameter specifies the handle to the io request + * object from which to get the host to device register fis buffer. + * + * The address of the host to device register fis buffer in the io request + * object. This function is only valid for SATA requests. + */ +void *scic_stp_io_request_get_h2d_reg_address( + struct scic_sds_request *scic_io_request); + +/** + * scic_stp_io_request_get_d2h_reg_address() - This method will return the + * address of the device to host register fis region for the io request + * object. + * @scic_io_request: This parameter specifies teh handle to the io request + * object from which to get the device to host register fis buffer. + * + * The address fo the device to host register fis ending the io request. This + * function is only valid for SATA requests. + */ +void *scic_stp_io_request_get_d2h_reg_address( + struct scic_sds_request *scic_io_request); + + +/** + * scic_io_request_get_number_of_bytes_transferred() - This method will return + * the number of bytes transferred from the SCU + * @scic_io_request: This parameter specifies the handle to the io request + * whose data length was not eqaul to the data length specified in the + * request. When the driver gets an early io completion status from the + * hardware, this routine should be called to get the actual number of bytes + * transferred + * + * The return is the number of bytes transferred when the data legth is not + * equal to the specified length in the io request + */ +u32 scic_io_request_get_number_of_bytes_transferred( + struct scic_sds_request *scic_io_request); + + +#endif /* _SCIC_IO_REQUEST_H_ */ + diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h new file mode 100644 index 000000000000..25a6140fa9e4 --- /dev/null +++ b/drivers/scsi/isci/core/scic_phy.h @@ -0,0 +1,303 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_PHY_H_ +#define _SCIC_PHY_H_ + +/** + * This file contains all of the interface methods that can be called by an + * SCIC user on a phy (SAS or SATA) object. + * + * + */ + + +#include "sci_types.h" +#include "sci_status.h" + +#include "intel_sata.h" +#include "intel_sas.h" + +struct scic_sds_phy; +struct scic_sds_port; + +/** + * struct scic_phy_properties - This structure defines the properties common to + * all phys that can be retrieved. + * + * + */ +struct scic_phy_properties { + /** + * This field specifies the port that currently contains the + * supplied phy. This field may be set to SCI_INVALID_HANDLE + * if the phy is not currently contained in a port. + */ + struct scic_sds_port *owning_port; + + /** + * This field specifies the link rate at which the phy is + * currently operating. + */ + enum sci_sas_link_rate negotiated_link_rate; + + /** + * This field indicates the protocols supported by the phy. + */ + struct sci_sas_identify_address_frame_protocols protocols; + + /** + * This field specifies the index of the phy in relation to other + * phys within the controller. This index is zero relative. + */ + u8 index; + +}; + +/** + * struct scic_sas_phy_properties - This structure defines the properties, + * specific to a SAS phy, that can be retrieved. + * + * + */ +struct scic_sas_phy_properties { + /** + * This field delineates the Identify Address Frame received + * from the remote end point. + */ + struct sci_sas_identify_address_frame received_iaf; + + /** + * This field delineates the Phy capabilities structure received + * from the remote end point. + */ + struct sas_capabilities received_capabilities; + +}; + +/** + * struct scic_sata_phy_properties - This structure defines the properties, + * specific to a SATA phy, that can be retrieved. + * + * + */ +struct scic_sata_phy_properties { + /** + * This field delineates the signature FIS received from the + * attached target. + */ + struct sata_fis_reg_d2h signature_fis; + + /** + * This field specifies to the user if a port selector is connected + * on the specified phy. + */ + bool is_port_selector_present; + +}; + +/** + * enum scic_phy_counter_id - This enumeration depicts the various pieces of + * optional information that can be retrieved for a specific phy. + * + * + */ +enum scic_phy_counter_id { + /** + * This PHY information field tracks the number of frames received. + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME, + + /** + * This PHY information field tracks the number of frames transmitted. + */ + SCIC_PHY_COUNTER_TRANSMITTED_FRAME, + + /** + * This PHY information field tracks the number of DWORDs received. + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME_WORD, + + /** + * This PHY information field tracks the number of DWORDs transmitted. + */ + SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD, + + /** + * This PHY information field tracks the number of times DWORD + * synchronization was lost. + */ + SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR, + + /** + * This PHY information field tracks the number of received DWORDs with + * running disparity errors. + */ + SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR, + + /** + * This PHY information field tracks the number of received frames with a + * CRC error (not including short or truncated frames). + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR, + + /** + * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT) + * primitives received. + */ + SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT, + + /** + * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT) + * primitives transmitted. + */ + SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT, + + /** + * This PHY information field tracks the number of times the inactivity + * timer for connections on the phy has been utilized. + */ + SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED, + + /** + * This PHY information field tracks the number of DONE (CREDIT TIMEOUT) + * primitives received. + */ + SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT, + + /** + * This PHY information field tracks the number of DONE (CREDIT TIMEOUT) + * primitives transmitted. + */ + SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT, + + /** + * This PHY information field tracks the number of CREDIT BLOCKED + * primitives received. + * @note Depending on remote device implementation, credit blocks + * may occur regularly. + */ + SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED, + + /** + * This PHY information field contains the number of short frames + * received. A short frame is simply a frame smaller then what is + * allowed by either the SAS or SATA specification. + */ + SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME, + + /** + * This PHY information field contains the number of frames received after + * credit has been exhausted. + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT, + + /** + * This PHY information field contains the number of frames received after + * a DONE has been received. + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE, + + /** + * This PHY information field contains the number of times the phy + * failed to achieve DWORD synchronization during speed negotiation. + */ + SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR +}; + + +/** + * scic_sas_phy_get_properties() - This method will enable the user to retrieve + * information specific to a SAS phy, such as: the received identify address + * frame, received phy capabilities, etc. + * @phy: this parameter specifies the phy for which to retrieve properties. + * @properties: This parameter specifies the properties structure into which to + * copy the requested information. + * + * This method returns an indication as to whether the SAS phy properties were + * successfully retrieved. SCI_SUCCESS This value is returned if the SAS + * properties are successfully retrieved. SCI_FAILURE This value is returned if + * the SAS properties are not successfully retrieved (e.g. It's not a SAS Phy). + */ +enum sci_status scic_sas_phy_get_properties( + struct scic_sds_phy *phy, + struct scic_sas_phy_properties *properties); + +/** + * scic_sata_phy_get_properties() - This method will enable the user to + * retrieve information specific to a SATA phy, such as: the received + * signature FIS, if a port selector is present, etc. + * @phy: this parameter specifies the phy for which to retrieve properties. + * @properties: This parameter specifies the properties structure into which to + * copy the requested information. + * + * This method returns an indication as to whether the SATA phy properties were + * successfully retrieved. SCI_SUCCESS This value is returned if the SATA + * properties are successfully retrieved. SCI_FAILURE This value is returned if + * the SATA properties are not successfully retrieved (e.g. It's not a SATA + * Phy). + */ +enum sci_status scic_sata_phy_get_properties( + struct scic_sds_phy *phy, + struct scic_sata_phy_properties *properties); + + + + + + + +#endif /* _SCIC_PHY_H_ */ + diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h new file mode 100644 index 000000000000..34d22c04aa56 --- /dev/null +++ b/drivers/scsi/isci/core/scic_port.h @@ -0,0 +1,213 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_PORT_H_ +#define _SCIC_PORT_H_ + +/** + * This file contains all of the interface methods that can be called by an SCI + * Core user on a SAS or SATA port. + * + * + */ + + +#include "sci_types.h" +#include "sci_status.h" +#include "intel_sas.h" + +struct scic_sds_port; + +enum SCIC_PORT_NOT_READY_REASON_CODE { + SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, + SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, + SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, + SCIC_PORT_NOT_READY_RECONFIGURING, + + SCIC_PORT_NOT_READY_REASON_CODE_MAX +}; + +/** + * struct scic_port_end_point_properties - This structure defines the + * properties that can be retrieved for each end-point local or remote + * (attached) port in the controller. + * + * + */ +struct scic_port_end_point_properties { + /** + * This field indicates the SAS address for the associated end + * point in the port. + */ + struct sci_sas_address sas_address; + + /** + * This field indicates the protocols supported by the associated + * end-point in the port. + */ + struct sci_sas_identify_address_frame_protocols protocols; + +}; + +/** + * struct scic_port_properties - This structure defines the properties that can + * be retrieved for each port in the controller. + * + * + */ +struct scic_port_properties { + /** + * This field specifies the logical index of the port (0 relative). + */ + u32 index; + + /** + * This field indicates the local end-point properties for port. + */ + struct scic_port_end_point_properties local; + + /** + * This field indicates the remote (attached) end-point properties + * for the port. + */ + struct scic_port_end_point_properties remote; + + /** + * This field specifies the phys contained inside the port. + */ + u32 phy_mask; + +}; + +/** + * scic_port_get_properties() - This method simply returns the properties + * regarding the port, such as: physical index, protocols, sas address, etc. + * @port: this parameter specifies the port for which to retrieve the physical + * index. + * @properties: This parameter specifies the properties structure into which to + * copy the requested information. + * + * Indicate if the user specified a valid port. SCI_SUCCESS This value is + * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This + * value is returned if the specified port is not valid. When this value is + * returned, no data is copied to the properties output parameter. + */ +enum sci_status scic_port_get_properties( + struct scic_sds_port *port, + struct scic_port_properties *properties); + + + +/** + * scic_port_start() - This method will make the port ready for operation. + * Prior to calling the start method IO operation is not possible. + * @port: This parameter specifies the port to be started. + * + * Indicate if the port was successfully started. SCI_SUCCESS This value is + * returned if the port was successfully started. SCI_WARNING_ALREADY_IN_STATE + * This value is returned if the port is in the process of starting. + * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port is not + * valid. SCI_FAILURE_INVALID_STATE This value is returned if a start operation + * can't be completed due to the state of port. + */ +enum sci_status scic_port_start( + struct scic_sds_port *port); + +/** + * scic_port_stop() - This method will make the port no longer ready for + * operation. After invoking this method IO operation is not possible. + * @port: This parameter specifies the port to be stopped. + * + * Indicate if the port was successfully stopped. SCI_SUCCESS This value is + * returned if the port was successfully stopped. SCI_WARNING_ALREADY_IN_STATE + * This value is returned if the port is already stopped or in the process of + * stopping. SCI_FAILURE_INVALID_PORT This value is returned if the supplied + * port is not valid. SCI_FAILURE_INVALID_STATE This value is returned if a + * stop operation can't be completed due to the state of port. + */ +enum sci_status scic_port_stop( + struct scic_sds_port *port); + +/** + * scic_port_hard_reset() - This method will request the SCI implementation to + * perform a HARD RESET on the SAS Port. If/When the HARD RESET completes + * the SCI user will be notified via an SCI OS callback indicating a direct + * attached device was found. + * @port: a handle corresponding to the SAS port to be hard reset. + * @reset_timeout: This parameter specifies the number of milliseconds in which + * the port reset operation should complete. + * + * The SCI User callback in SCIC_USER_CALLBACKS_T will only be called once for + * each phy in the SAS Port at completion of the hard reset sequence. Return a + * status indicating whether the hard reset started successfully. SCI_SUCCESS + * This value is returned if the hard reset operation started successfully. + */ +enum sci_status scic_port_hard_reset( + struct scic_sds_port *port, + u32 reset_timeout); + +/** + * scic_port_enable_broadcast_change_notification() - This API method enables + * the broadcast change notification from underneath hardware. + * @port: The port upon which broadcast change notifications (BCN) are to be + * enabled. + * + */ +void scic_port_enable_broadcast_change_notification( + struct scic_sds_port *port); + + +#endif /* _SCIC_PORT_H_ */ + diff --git a/drivers/scsi/isci/core/scic_remote_device.h b/drivers/scsi/isci/core/scic_remote_device.h new file mode 100644 index 000000000000..e8c04592763e --- /dev/null +++ b/drivers/scsi/isci/core/scic_remote_device.h @@ -0,0 +1,295 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_REMOTE_DEVICE_H_ +#define _SCIC_REMOTE_DEVICE_H_ + +/** + * This file contains all of the interface methods that can be called by an + * SCIC user on the device object. + * + * + */ + + +#include "sci_types.h" +#include "sci_status.h" +#include "intel_sas.h" + +struct scic_sds_port; +struct scic_sds_remote_device; + +/** + * + * + * + */ +enum scic_remote_device_not_ready_reason_code { + SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED, + SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED, + SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED, + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED, + SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED, + + SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX + +}; + +/** + * scic_remote_device_get_object_size() - This method simply returns the + * maximum memory space needed to store a remote device object. + * + * a positive integer value indicating the size (in bytes) of the remote device + * object. + */ +u32 scic_remote_device_get_object_size( + void); + +struct scic_sds_port; +struct scic_sds_remote_device; +/** + * scic_remote_device_construct() - This method will perform the construction + * common to all remote device objects. + * @sci_port: SAS/SATA port through which this device is accessed. + * @sci_dev: remote device to construct + * + * It isn't necessary to call scic_remote_device_destruct() for device objects + * that have only called this method for construction. Once subsequent + * construction methods have been invoked (e.g. + * scic_remote_device_da_construct()), then destruction should occur. none + */ +void scic_remote_device_construct(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev); + +/** + * scic_remote_device_da_construct() - This method will construct a + * SCIC_REMOTE_DEVICE object for a direct attached (da) device. The + * information (e.g. IAF, Signature FIS, etc.) necessary to build the device + * is known to the SCI Core since it is contained in the scic_phy object. + * @remote_device: This parameter specifies the remote device to be destructed. + * + * The user must have previously called scic_remote_device_construct() Remote + * device objects are a limited resource. As such, they must be protected. + * Thus calls to construct and destruct are mutually exclusive and + * non-reentrant. Indicate if the remote device was successfully constructed. + * SCI_SUCCESS Returned if the device was successfully constructed. + * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been + * constructed. If it's an additional phy for the target, then call + * scic_remote_device_da_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned + * if the supplied parameters necessitate creation of a remote device for which + * the protocol is not supported by the underlying controller hardware. + * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core + * controller associated with the supplied parameters is unable to support + * additional remote devices. + */ +enum sci_status scic_remote_device_da_construct( + struct scic_sds_remote_device *remote_device); + +/** + * scic_remote_device_ea_construct() - This method will construct an + * SCIC_REMOTE_DEVICE object for an expander attached (ea) device from an + * SMP Discover Response. + * @remote_device: This parameter specifies the remote device to be destructed. + * @discover_response: This parameter specifies the SMP Discovery Response to + * be used in device creation. + * + * The user must have previously called scic_remote_device_construct() Remote + * device objects are a limited resource. As such, they must be protected. + * Thus calls to construct and destruct are mutually exclusive and + * non-reentrant. Indicate if the remote device was successfully constructed. + * SCI_SUCCESS Returned if the device was successfully constructed. + * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been + * constructed. If it's an additional phy for the target, then call + * scic_ea_remote_device_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned + * if the supplied parameters necessitate creation of a remote device for which + * the protocol is not supported by the underlying controller hardware. + * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core + * controller associated with the supplied parameters is unable to support + * additional remote devices. + */ +enum sci_status scic_remote_device_ea_construct( + struct scic_sds_remote_device *remote_device, + struct smp_response_discover *discover_response); + +/** + * scic_remote_device_destruct() - This method is utilized to free up a core's + * remote device object. + * @remote_device: This parameter specifies the remote device to be destructed. + * + * Remote device objects are a limited resource. As such, they must be + * protected. Thus calls to construct and destruct are mutually exclusive and + * non-reentrant. The return value shall indicate if the device was + * successfully destructed or if some failure occurred. enum sci_status This value + * is returned if the device is successfully destructed. + * SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied + * device isn't valid (e.g. it's already been destoryed, the handle isn't + * valid, etc.). + */ +enum sci_status scic_remote_device_destruct( + struct scic_sds_remote_device *remote_device); + + + + + +/** + * scic_remote_device_start() - This method will start the supplied remote + * device. This method enables normal IO requests to flow through to the + * remote device. + * @remote_device: This parameter specifies the device to be started. + * @timeout: This parameter specifies the number of milliseconds in which the + * start operation should complete. + * + * An indication of whether the device was successfully started. SCI_SUCCESS + * This value is returned if the device was successfully started. + * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start + * the device when there have been no phys added to it. + */ +enum sci_status scic_remote_device_start( + struct scic_sds_remote_device *remote_device, + u32 timeout); + +/** + * scic_remote_device_stop() - This method will stop both transmission and + * reception of link activity for the supplied remote device. This method + * disables normal IO requests from flowing through to the remote device. + * @remote_device: This parameter specifies the device to be stopped. + * @timeout: This parameter specifies the number of milliseconds in which the + * stop operation should complete. + * + * An indication of whether the device was successfully stopped. SCI_SUCCESS + * This value is returned if the transmission and reception for the device was + * successfully stopped. + */ +enum sci_status scic_remote_device_stop( + struct scic_sds_remote_device *remote_device, + u32 timeout); + +/** + * scic_remote_device_reset() - This method will reset the device making it + * ready for operation. This method must be called anytime the device is + * reset either through a SMP phy control or a port hard reset request. + * @remote_device: This parameter specifies the device to be reset. + * + * This method does not actually cause the device hardware to be reset. This + * method resets the software object so that it will be operational after a + * device hardware reset completes. An indication of whether the device reset + * was accepted. SCI_SUCCESS This value is returned if the device reset is + * started. + */ +enum sci_status scic_remote_device_reset( + struct scic_sds_remote_device *remote_device); + +/** + * scic_remote_device_reset_complete() - This method informs the device object + * that the reset operation is complete and the device can resume operation + * again. + * @remote_device: This parameter specifies the device which is to be informed + * of the reset complete operation. + * + * An indication that the device is resuming operation. SCI_SUCCESS the device + * is resuming operation. + */ +enum sci_status scic_remote_device_reset_complete( + struct scic_sds_remote_device *remote_device); + + + +/** + * scic_remote_device_get_connection_rate() - This method simply returns the + * link rate at which communications to the remote device occur. + * @remote_device: This parameter specifies the device for which to get the + * connection rate. + * + * Return the link rate at which we transfer for the supplied remote device. + */ +enum sci_sas_link_rate scic_remote_device_get_connection_rate( + struct scic_sds_remote_device *remote_device); + +/** + * scic_remote_device_get_protocols() - This method will indicate which + * protocols are supported by this remote device. + * @remote_device: This parameter specifies the device for which to return the + * protocol. + * @protocols: This parameter specifies the output values, from the remote + * device object, which indicate the protocols supported by the supplied + * remote_device. + * + * The type of protocols supported by this device. The values are returned as + * part of a bit mask in order to allow for multi-protocol support. + */ +void scic_remote_device_get_protocols( + struct scic_sds_remote_device *remote_device, + struct smp_discover_response_protocols *protocols); + + +#if !defined(DISABLE_ATAPI) +/** + * scic_remote_device_is_atapi() - + * @this_device: The device whose type is to be decided. + * + * This method first decide whether a device is a stp target, then decode the + * signature fis of a DA STP device to tell whether it is a standard end disk + * or an ATAPI device. bool Indicate a device is ATAPI device or not. + */ +bool scic_remote_device_is_atapi( + struct scic_sds_remote_device *device_handle); +#else /* !defined(DISABLE_ATAPI) */ +#define scic_remote_device_is_atapi(device_handle) false +#endif /* !defined(DISABLE_ATAPI) */ + + +#endif /* _SCIC_REMOTE_DEVICE_H_ */ + diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c new file mode 100644 index 000000000000..35f7796df661 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -0,0 +1,4147 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "scic_controller.h" +#include "scic_phy.h" +#include "scic_port.h" +#include "scic_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_controller_registers.h" +#include "scic_sds_pci.h" +#include "scic_sds_phy.h" +#include "scic_sds_port_configuration_agent.h" +#include "scic_sds_port.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_request.h" +#include "scic_user_callback.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_completion_codes.h" +#include "scu_constants.h" +#include "scu_event_codes.h" +#include "scu_remote_node_context.h" +#include "scu_task_context.h" +#include "scu_unsolicited_frame.h" + +#define SCU_CONTEXT_RAM_INIT_STALL_TIME 200 + +/** + * smu_dcc_get_max_ports() - + * + * This macro returns the maximum number of logical ports supported by the + * hardware. The caller passes in the value read from the device context + * capacity register and this macro will mash and shift the value appropriately. + */ +#define smu_dcc_get_max_ports(dcc_value) \ + (\ + (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \ + ) + +/** + * smu_dcc_get_max_task_context() - + * + * This macro returns the maximum number of task contexts supported by the + * hardware. The caller passes in the value read from the device context + * capacity register and this macro will mash and shift the value appropriately. + */ +#define smu_dcc_get_max_task_context(dcc_value) \ + (\ + (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \ + ) + +/** + * smu_dcc_get_max_remote_node_context() - + * + * This macro returns the maximum number of remote node contexts supported by + * the hardware. The caller passes in the value read from the device context + * capacity register and this macro will mash and shift the value appropriately. + */ +#define smu_dcc_get_max_remote_node_context(dcc_value) \ + (\ + (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \ + ) + + +static void scic_sds_controller_power_control_timer_handler( + void *controller); +#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3 +#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3 + +/** + * + * + * The number of milliseconds to wait for a phy to start. + */ +#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100 + +/** + * + * + * The number of milliseconds to wait while a given phy is consuming power + * before allowing another set of phys to consume power. Ultimately, this will + * be specified by OEM parameter. + */ +#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500 + +/** + * COMPLETION_QUEUE_CYCLE_BIT() - + * + * This macro will return the cycle bit of the completion queue entry + */ +#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000) + +/** + * NORMALIZE_GET_POINTER() - + * + * This macro will normalize the completion queue get pointer so its value can + * be used as an index into an array + */ +#define NORMALIZE_GET_POINTER(x) \ + ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK) + +/** + * NORMALIZE_PUT_POINTER() - + * + * This macro will normalize the completion queue put pointer so its value can + * be used as an array inde + */ +#define NORMALIZE_PUT_POINTER(x) \ + ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK) + + +/** + * NORMALIZE_GET_POINTER_CYCLE_BIT() - + * + * This macro will normalize the completion queue cycle pointer so it matches + * the completion queue cycle bit + */ +#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \ + ((SMU_CQGR_CYCLE_BIT & (x)) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT)) + +/** + * NORMALIZE_EVENT_POINTER() - + * + * This macro will normalize the completion queue event entry so its value can + * be used as an index. + */ +#define NORMALIZE_EVENT_POINTER(x) \ + (\ + ((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK) \ + >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \ + ) + +/** + * INCREMENT_COMPLETION_QUEUE_GET() - + * + * This macro will increment the controllers completion queue index value and + * possibly toggle the cycle bit if the completion queue index wraps back to 0. + */ +#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \ + INCREMENT_QUEUE_GET(\ + (index), \ + (cycle), \ + (controller)->completion_queue_entries, \ + SMU_CQGR_CYCLE_BIT \ + ) + +/** + * INCREMENT_EVENT_QUEUE_GET() - + * + * This macro will increment the controllers event queue index value and + * possibly toggle the event cycle bit if the event queue index wraps back to 0. + */ +#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \ + INCREMENT_QUEUE_GET(\ + (index), \ + (cycle), \ + (controller)->completion_event_entries, \ + SMU_CQGR_EVENT_CYCLE_BIT \ + ) + +struct sci_base_memory_descriptor_list * +sci_controller_get_memory_descriptor_list_handle(struct scic_sds_controller *scic) +{ + return &scic->parent.mdl; +} + +/* + * ****************************************************************************- + * * SCIC SDS Controller Initialization Methods + * ****************************************************************************- */ + +/** + * This timer is used to start another phy after we have given up on the + * previous phy to transition to the ready state. + * + * + */ +static void scic_sds_controller_phy_startup_timeout_handler( + void *controller) +{ + enum sci_status status; + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + this_controller->phy_startup_timer_pending = false; + + status = SCI_FAILURE; + + while (status != SCI_SUCCESS) { + status = scic_sds_controller_start_next_phy(this_controller); + } +} + +/** + * + * + * This method initializes the phy startup operations for controller start. + */ +void scic_sds_controller_initialize_phy_startup( + struct scic_sds_controller *this_controller) +{ + this_controller->phy_startup_timer = scic_cb_timer_create( + this_controller, + scic_sds_controller_phy_startup_timeout_handler, + this_controller + ); + + this_controller->next_phy_to_start = 0; + this_controller->phy_startup_timer_pending = false; +} + +/** + * + * + * This method initializes the power control operations for the controller + * object. + */ +void scic_sds_controller_initialize_power_control( + struct scic_sds_controller *this_controller) +{ + this_controller->power_control.timer = scic_cb_timer_create( + this_controller, + scic_sds_controller_power_control_timer_handler, + this_controller + ); + + memset( + this_controller->power_control.requesters, + 0, + sizeof(this_controller->power_control.requesters) + ); + + this_controller->power_control.phys_waiting = 0; +} + +/* --------------------------------------------------------------------------- */ + +#define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT (32) +#define SCU_TASK_CONTEXT_ALIGNMENT (256) +#define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64) +#define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT (1024) +#define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT (64) + +/* --------------------------------------------------------------------------- */ + +/** + * This method builds the memory descriptor table for this controller. + * @this_controller: This parameter specifies the controller object for which + * to build the memory table. + * + */ +static void scic_sds_controller_build_memory_descriptor_table( + struct scic_sds_controller *this_controller) +{ + sci_base_mde_construct( + &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE], + SCU_COMPLETION_RAM_ALIGNMENT, + (sizeof(u32) * this_controller->completion_queue_entries), + (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS) + ); + + sci_base_mde_construct( + &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT], + SCU_REMOTE_NODE_CONTEXT_ALIGNMENT, + this_controller->remote_node_entries * sizeof(union scu_remote_node_context), + SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS + ); + + sci_base_mde_construct( + &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT], + SCU_TASK_CONTEXT_ALIGNMENT, + this_controller->task_context_entries * sizeof(struct scu_task_context), + SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS + ); + + /* + * The UF buffer address table size must be programmed to a power + * of 2. Find the first power of 2 that is equal to or greater then + * the number of unsolicited frame buffers to be utilized. */ + scic_sds_unsolicited_frame_control_set_address_table_count( + &this_controller->uf_control + ); + + sci_base_mde_construct( + &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER], + SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT, + scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control), + SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS + ); +} + +/** + * This method validates the driver supplied memory descriptor table. + * @this_controller: + * + * enum sci_status + */ +enum sci_status scic_sds_controller_validate_memory_descriptor_table( + struct scic_sds_controller *this_controller) +{ + bool mde_list_valid; + + mde_list_valid = sci_base_mde_is_valid( + &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE], + SCU_COMPLETION_RAM_ALIGNMENT, + (sizeof(u32) * this_controller->completion_queue_entries), + (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS) + ); + + if (mde_list_valid == false) + return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; + + mde_list_valid = sci_base_mde_is_valid( + &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT], + SCU_REMOTE_NODE_CONTEXT_ALIGNMENT, + this_controller->remote_node_entries * sizeof(union scu_remote_node_context), + SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS + ); + + if (mde_list_valid == false) + return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; + + mde_list_valid = sci_base_mde_is_valid( + &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT], + SCU_TASK_CONTEXT_ALIGNMENT, + this_controller->task_context_entries * sizeof(struct scu_task_context), + SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS + ); + + if (mde_list_valid == false) + return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; + + mde_list_valid = sci_base_mde_is_valid( + &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER], + SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT, + scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control), + SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS + ); + + if (mde_list_valid == false) + return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; + + return SCI_SUCCESS; +} + +/** + * This method initializes the controller with the physical memory addresses + * that are used to communicate with the driver. + * @this_controller: + * + */ +void scic_sds_controller_ram_initialization( + struct scic_sds_controller *this_controller) +{ + struct sci_physical_memory_descriptor *mde; + + /* + * The completion queue is actually placed in cacheable memory + * Therefore it no longer comes out of memory in the MDL. */ + mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE]; + this_controller->completion_queue = (u32 *)mde->virtual_address; + SMU_CQBAR_WRITE(this_controller, mde->physical_address); + + /* + * Program the location of the Remote Node Context table + * into the SCU. */ + mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT]; + this_controller->remote_node_context_table = (union scu_remote_node_context *) + mde->virtual_address; + SMU_RNCBAR_WRITE(this_controller, mde->physical_address); + + /* Program the location of the Task Context table into the SCU. */ + mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT]; + this_controller->task_context_table = (struct scu_task_context *) + mde->virtual_address; + SMU_HTTBAR_WRITE(this_controller, mde->physical_address); + + mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER]; + scic_sds_unsolicited_frame_control_construct( + &this_controller->uf_control, mde, this_controller + ); + + /* + * Inform the silicon as to the location of the UF headers and + * address table. */ + SCU_UFHBAR_WRITE( + this_controller, + this_controller->uf_control.headers.physical_address); + SCU_PUFATHAR_WRITE( + this_controller, + this_controller->uf_control.address_table.physical_address); +} + +/** + * This method initializes the task context data for the controller. + * @this_controller: + * + */ +void scic_sds_controller_assign_task_entries( + struct scic_sds_controller *this_controller) +{ + u32 task_assignment; + + /* + * Assign all the TCs to function 0 + * TODO: Do we actually need to read this register to write it back? */ + task_assignment = SMU_TCA_READ(this_controller, 0); + + task_assignment = + ( + task_assignment + | (SMU_TCA_GEN_VAL(STARTING, 0)) + | (SMU_TCA_GEN_VAL(ENDING, this_controller->task_context_entries - 1)) + | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE)) + ); + + SMU_TCA_WRITE(this_controller, 0, task_assignment); +} + +/** + * This method initializes the hardware completion queue. + * + * + */ +void scic_sds_controller_initialize_completion_queue( + struct scic_sds_controller *this_controller) +{ + u32 index; + u32 completion_queue_control_value; + u32 completion_queue_get_value; + u32 completion_queue_put_value; + + this_controller->completion_queue_get = 0; + + completion_queue_control_value = ( + SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1) + | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1) + ); + + SMU_CQC_WRITE(this_controller, completion_queue_control_value); + + /* Set the completion queue get pointer and enable the queue */ + completion_queue_get_value = ( + (SMU_CQGR_GEN_VAL(POINTER, 0)) + | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0)) + | (SMU_CQGR_GEN_BIT(ENABLE)) + | (SMU_CQGR_GEN_BIT(EVENT_ENABLE)) + ); + + SMU_CQGR_WRITE(this_controller, completion_queue_get_value); + + /* Set the completion queue put pointer */ + completion_queue_put_value = ( + (SMU_CQPR_GEN_VAL(POINTER, 0)) + | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0)) + ); + + SMU_CQPR_WRITE(this_controller, completion_queue_put_value); + + /* Initialize the cycle bit of the completion queue entries */ + for (index = 0; index < this_controller->completion_queue_entries; index++) { + /* + * If get.cycle_bit != completion_queue.cycle_bit + * its not a valid completion queue entry + * so at system start all entries are invalid */ + this_controller->completion_queue[index] = 0x80000000; + } +} + +/** + * This method initializes the hardware unsolicited frame queue. + * + * + */ +void scic_sds_controller_initialize_unsolicited_frame_queue( + struct scic_sds_controller *this_controller) +{ + u32 frame_queue_control_value; + u32 frame_queue_get_value; + u32 frame_queue_put_value; + + /* Write the queue size */ + frame_queue_control_value = + SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count); + + SCU_UFQC_WRITE(this_controller, frame_queue_control_value); + + /* Setup the get pointer for the unsolicited frame queue */ + frame_queue_get_value = ( + SCU_UFQGP_GEN_VAL(POINTER, 0) + | SCU_UFQGP_GEN_BIT(ENABLE_BIT) + ); + + SCU_UFQGP_WRITE(this_controller, frame_queue_get_value); + + /* Setup the put pointer for the unsolicited frame queue */ + frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0); + + SCU_UFQPP_WRITE(this_controller, frame_queue_put_value); +} + +/** + * This method enables the hardware port task scheduler. + * + * + */ +void scic_sds_controller_enable_port_task_scheduler( + struct scic_sds_controller *this_controller) +{ + u32 port_task_scheduler_value; + + port_task_scheduler_value = SCU_PTSGCR_READ(this_controller); + + port_task_scheduler_value |= + (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE)); + + SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value); +} + +/* --------------------------------------------------------------------------- */ + +/** + * + * + * This macro is used to delay between writes to the AFE registers during AFE + * initialization. + */ +#define AFE_REGISTER_WRITE_DELAY 10 + +static bool is_a0(void) +{ + return isci_si_rev == ISCI_SI_REVA0; +} + +static bool is_a2(void) +{ + return isci_si_rev == ISCI_SI_REVA2; +} + +static bool is_b0(void) +{ + return isci_si_rev > ISCI_SI_REVA2; +} + +/* Initialize the AFE for this phy index. We need to read the AFE setup from + * the OEM parameters none + */ +void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) +{ + u32 afe_status; + u32 phy_id; + + /* Clear DFX Status registers */ + scu_afe_register_write(scic, afe_dfx_master_control0, 0x0081000f); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + /* Configure bias currents to normal */ + if (is_a0()) + scu_afe_register_write(scic, afe_bias_control, 0x00005500); + else + scu_afe_register_write(scic, afe_bias_control, 0x00005A00); + + + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + /* Enable PLL */ + if (is_b0()) + scu_afe_register_write(scic, afe_pll_control0, 0x80040A08); + else + scu_afe_register_write(scic, afe_pll_control0, 0x80040908); + + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + /* Wait for the PLL to lock */ + do { + afe_status = scu_afe_register_read( + scic, afe_common_block_status); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + } while ((afe_status & 0x00001000) == 0); + + if (is_b0()) { + /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ + scu_afe_register_write(scic, afe_pmsn_master_control0, 0x7bcc96ad); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + } + + for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { + if (is_b0()) { + /* Configure transmitter SSC parameters */ + scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + } else { + /* + * All defaults, except the Receive Word Alignament/Comma Detect + * Enable....(0xe800) */ + scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004512); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + scu_afe_txreg_write(scic, phy_id, afe_xcvr_control1, 0x0050100F); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + } + + /* + * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) + * & increase TX int & ext bias 20%....(0xe85c) */ + if (is_a0()) + scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003D4); + else if (is_a2()) + scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003F0); + else { + /* Power down TX and RX (PWRDNTX and PWRDNRX) */ + scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d7); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + /* + * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) + * & increase TX int & ext bias 20%....(0xe85c) */ + scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d4); + } + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + if (is_a0() || is_a2()) { + /* Enable TX equalization (0xe824) */ + scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + } + + /* + * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On), + * RDD=0x0(RX Detect Enabled) ....(0xe800) */ + scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004100); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + /* Leave DFE/FFE on */ + if (is_a0()) + scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F09983F); + else if (is_a2()) + scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F); + else { + scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + /* Enable TX equalization (0xe824) */ + scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000); + } + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, 0x000E7C03); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control1, 0x000E7C03); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control2, 0x000E7C03); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + + scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control3, 0x000E7C03); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + } + + /* Transfer control to the PEs */ + scu_afe_register_write(scic, afe_dfx_master_control0, 0x00010f00); + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); +} + +/* + * ****************************************************************************- + * * SCIC SDS Controller Internal Start/Stop Routines + * ****************************************************************************- */ + + +/** + * This method will attempt to transition into the ready state for the + * controller and indicate that the controller start operation has completed + * if all criteria are met. + * @this_controller: This parameter indicates the controller object for which + * to transition to ready. + * @status: This parameter indicates the status value to be pass into the call + * to scic_cb_controller_start_complete(). + * + * none. + */ +static void scic_sds_controller_transition_to_ready( + struct scic_sds_controller *this_controller, + enum sci_status status) +{ + if (this_controller->parent.state_machine.current_state_id + == SCI_BASE_CONTROLLER_STATE_STARTING) { + /* + * We move into the ready state, because some of the phys/ports + * may be up and operational. */ + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(this_controller), + SCI_BASE_CONTROLLER_STATE_READY + ); + + scic_cb_controller_start_complete(this_controller, status); + } +} + +/** + * This method is the general timeout handler for the controller. It will take + * the correct timetout action based on the current controller state + */ +void scic_sds_controller_timeout_handler( + struct scic_sds_controller *scic) +{ + enum sci_base_controller_states current_state; + + current_state = sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine(scic)); + + if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING) { + scic_sds_controller_transition_to_ready( + scic, SCI_FAILURE_TIMEOUT); + } else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING) { + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_FAILED); + scic_cb_controller_stop_complete(scic, SCI_FAILURE_TIMEOUT); + } else /* / @todo Now what do we want to do in this case? */ + dev_err(scic_to_dev(scic), + "%s: Controller timer fired when controller was not " + "in a state being timed.\n", + __func__); +} + +/** + * scic_sds_controller_get_port_configuration_mode + * @this_controller: This is the controller to use to determine if we are using + * manual or automatic port configuration. + * + * SCIC_PORT_CONFIGURATION_MODE + */ +enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode( + struct scic_sds_controller *this_controller) +{ + u32 index; + enum SCIC_PORT_CONFIGURATION_MODE mode; + + mode = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; + + for (index = 0; index < SCI_MAX_PORTS; index++) { + if (this_controller->oem_parameters.sds1.ports[index].phy_mask != 0) { + mode = SCIC_PORT_MANUAL_CONFIGURATION_MODE; + break; + } + } + + return mode; +} + +enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) +{ + u32 index; + enum sci_status port_status; + enum sci_status status = SCI_SUCCESS; + + for (index = 0; index < scic->logical_port_entries; index++) { + port_status = scic_port_stop(&scic->port_table[index]); + + if ((port_status != SCI_SUCCESS) && + (port_status != SCI_FAILURE_INVALID_STATE)) { + status = SCI_FAILURE; + + dev_warn(scic_to_dev(scic), + "%s: Controller stop operation failed to " + "stop port %d because of status %d.\n", + __func__, + scic->port_table[index].logical_port_index, + port_status); + } + } + + return status; +} + +/** + * + * + * + */ +static void scic_sds_controller_phy_timer_start( + struct scic_sds_controller *this_controller) +{ + scic_cb_timer_start( + this_controller, + this_controller->phy_startup_timer, + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT + ); + + this_controller->phy_startup_timer_pending = true; +} + +/** + * + * + * + */ +void scic_sds_controller_phy_timer_stop( + struct scic_sds_controller *this_controller) +{ + scic_cb_timer_stop( + this_controller, + this_controller->phy_startup_timer + ); + + this_controller->phy_startup_timer_pending = false; +} + +/** + * This method is called internally by the controller object to start the next + * phy on the controller. If all the phys have been starte, then this + * method will attempt to transition the controller to the READY state and + * inform the user (scic_cb_controller_start_complete()). + * @this_controller: This parameter specifies the controller object for which + * to start the next phy. + * + * enum sci_status + */ +enum sci_status scic_sds_controller_start_next_phy( + struct scic_sds_controller *this_controller) +{ + enum sci_status status; + + status = SCI_SUCCESS; + + if (this_controller->phy_startup_timer_pending == false) { + if (this_controller->next_phy_to_start == SCI_MAX_PHYS) { + bool is_controller_start_complete = true; + struct scic_sds_phy *the_phy; + u8 index; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + the_phy = &this_controller->phy_table[index]; + + if (scic_sds_phy_get_port(the_phy) != SCI_INVALID_HANDLE) { + /** + * The controller start operation is complete if and only + * if: + * - all links have been given an opportunity to start + * - have no indication of a connected device + * - have an indication of a connected device and it has + * finished the link training process. + */ + if ( + ( + (the_phy->is_in_link_training == false) + && (the_phy->parent.state_machine.current_state_id + == SCI_BASE_PHY_STATE_INITIAL) + ) + || ( + (the_phy->is_in_link_training == false) + && (the_phy->parent.state_machine.current_state_id + == SCI_BASE_PHY_STATE_STOPPED) + ) + || ( + (the_phy->is_in_link_training == true) + && (the_phy->parent.state_machine.current_state_id + == SCI_BASE_PHY_STATE_STARTING) + ) + ) { + is_controller_start_complete = false; + break; + } + } + } + + /* + * The controller has successfully finished the start process. + * Inform the SCI Core user and transition to the READY state. */ + if (is_controller_start_complete == true) { + scic_sds_controller_transition_to_ready( + this_controller, SCI_SUCCESS + ); + scic_sds_controller_phy_timer_stop(this_controller); + } + } else { + struct scic_sds_phy *the_phy; + + the_phy = &this_controller->phy_table[this_controller->next_phy_to_start]; + + if ( + scic_sds_controller_get_port_configuration_mode(this_controller) + == SCIC_PORT_MANUAL_CONFIGURATION_MODE + ) { + if (scic_sds_phy_get_port(the_phy) == SCI_INVALID_HANDLE) { + this_controller->next_phy_to_start++; + + /* + * Caution recursion ahead be forwarned + * + * The PHY was never added to a PORT in MPC mode so start the next phy in sequence + * This phy will never go link up and will not draw power the OEM parameters either + * configured the phy incorrectly for the PORT or it was never assigned to a PORT */ + return scic_sds_controller_start_next_phy(this_controller); + } + } + + status = scic_sds_phy_start(the_phy); + + if (status == SCI_SUCCESS) { + scic_sds_controller_phy_timer_start(this_controller); + } else { + dev_warn(scic_to_dev(this_controller), + "%s: Controller stop operation failed " + "to stop phy %d because of status " + "%d.\n", + __func__, + this_controller->phy_table[this_controller->next_phy_to_start].phy_index, + status); + } + + this_controller->next_phy_to_start++; + } + } + + return status; +} + +/** + * + * @this_controller: + * + * enum sci_status + */ +enum sci_status scic_sds_controller_stop_phys( + struct scic_sds_controller *this_controller) +{ + u32 index; + enum sci_status status; + enum sci_status phy_status; + + status = SCI_SUCCESS; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + phy_status = scic_sds_phy_stop(&this_controller->phy_table[index]); + + if ( + (phy_status != SCI_SUCCESS) + && (phy_status != SCI_FAILURE_INVALID_STATE) + ) { + status = SCI_FAILURE; + + dev_warn(scic_to_dev(this_controller), + "%s: Controller stop operation failed to stop " + "phy %d because of status %d.\n", + __func__, + this_controller->phy_table[index].phy_index, phy_status); + } + } + + return status; +} + +/** + * + * @this_controller: + * + * enum sci_status + */ +enum sci_status scic_sds_controller_stop_devices( + struct scic_sds_controller *this_controller) +{ + u32 index; + enum sci_status status; + enum sci_status device_status; + + status = SCI_SUCCESS; + + for (index = 0; index < this_controller->remote_node_entries; index++) { + if (this_controller->device_table[index] != SCI_INVALID_HANDLE) { + /* / @todo What timeout value do we want to provide to this request? */ + device_status = scic_remote_device_stop(this_controller->device_table[index], 0); + + if ((device_status != SCI_SUCCESS) && + (device_status != SCI_FAILURE_INVALID_STATE)) { + dev_warn(scic_to_dev(this_controller), + "%s: Controller stop operation failed " + "to stop device 0x%p because of " + "status %d.\n", + __func__, + this_controller->device_table[index], device_status); + } + } + } + + return status; +} + +/* + * ****************************************************************************- + * * SCIC SDS Controller Power Control (Staggered Spinup) + * ****************************************************************************- */ + +/** + * + * + * This method starts the power control timer for this controller object. + */ +static void scic_sds_controller_power_control_timer_start( + struct scic_sds_controller *this_controller) +{ + scic_cb_timer_start( + this_controller, this_controller->power_control.timer, + SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL + ); + + this_controller->power_control.timer_started = true; +} + +/** + * + * + * + */ +static void scic_sds_controller_power_control_timer_handler( + void *controller) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + if (this_controller->power_control.phys_waiting == 0) { + this_controller->power_control.timer_started = false; + } else { + struct scic_sds_phy *the_phy = NULL; + u8 i; + + for (i = 0; + (i < SCI_MAX_PHYS) + && (this_controller->power_control.phys_waiting != 0); + i++) { + if (this_controller->power_control.requesters[i] != NULL) { + the_phy = this_controller->power_control.requesters[i]; + this_controller->power_control.requesters[i] = NULL; + this_controller->power_control.phys_waiting--; + break; + } + } + + /* + * It doesn't matter if the power list is empty, we need to start the + * timer in case another phy becomes ready. */ + scic_sds_controller_power_control_timer_start(this_controller); + + scic_sds_phy_consume_power_handler(the_phy); + } +} + +/** + * This method inserts the phy in the stagger spinup control queue. + * @this_controller: + * + * + */ +void scic_sds_controller_power_control_queue_insert( + struct scic_sds_controller *this_controller, + struct scic_sds_phy *the_phy) +{ + BUG_ON(the_phy == NULL); + + if ( + (this_controller->power_control.timer_started) + && (this_controller->power_control.requesters[the_phy->phy_index] == NULL) + ) { + this_controller->power_control.requesters[the_phy->phy_index] = the_phy; + this_controller->power_control.phys_waiting++; + } else { + scic_sds_controller_power_control_timer_start(this_controller); + scic_sds_phy_consume_power_handler(the_phy); + } +} + +/** + * This method removes the phy from the stagger spinup control queue. + * @this_controller: + * + * + */ +void scic_sds_controller_power_control_queue_remove( + struct scic_sds_controller *this_controller, + struct scic_sds_phy *the_phy) +{ + BUG_ON(the_phy == NULL); + + if (this_controller->power_control.requesters[the_phy->phy_index] != NULL) { + this_controller->power_control.phys_waiting--; + } + + this_controller->power_control.requesters[the_phy->phy_index] = NULL; +} + +/* + * ****************************************************************************- + * * SCIC SDS Controller Completion Routines + * ****************************************************************************- */ + +/** + * This method returns a true value if the completion queue has entries that + * can be processed + * @this_controller: + * + * bool true if the completion queue has entries to process false if the + * completion queue has no entries to process + */ +static bool scic_sds_controller_completion_queue_has_entries( + struct scic_sds_controller *this_controller) +{ + u32 get_value = this_controller->completion_queue_get; + u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK; + + if ( + NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) + == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index]) + ) { + return true; + } + + return false; +} + +/* --------------------------------------------------------------------------- */ + +/** + * This method processes a task completion notification. This is called from + * within the controller completion handler. + * @this_controller: + * @completion_entry: + * + */ +static void scic_sds_controller_task_completion( + struct scic_sds_controller *this_controller, + u32 completion_entry) +{ + u32 index; + struct scic_sds_request *io_request; + + index = SCU_GET_COMPLETION_INDEX(completion_entry); + io_request = this_controller->io_request_table[index]; + + /* Make sure that we really want to process this IO request */ + if ( + (io_request != SCI_INVALID_HANDLE) + && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) + && ( + scic_sds_io_tag_get_sequence(io_request->io_tag) + == this_controller->io_request_sequence[index] + ) + ) { + /* Yep this is a valid io request pass it along to the io request handler */ + scic_sds_io_request_tc_completion(io_request, completion_entry); + } +} + +/** + * This method processes an SDMA completion event. This is called from within + * the controller completion handler. + * @this_controller: + * @completion_entry: + * + */ +static void scic_sds_controller_sdma_completion( + struct scic_sds_controller *this_controller, + u32 completion_entry) +{ + u32 index; + struct scic_sds_request *io_request; + struct scic_sds_remote_device *device; + + index = SCU_GET_COMPLETION_INDEX(completion_entry); + + switch (scu_get_command_request_type(completion_entry)) { + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: + io_request = this_controller->io_request_table[index]; + dev_warn(scic_to_dev(this_controller), + "%s: SCIC SDS Completion type SDMA %x for io request " + "%p\n", + __func__, + completion_entry, + io_request); + /* @todo For a post TC operation we need to fail the IO + * request + */ + break; + + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC: + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC: + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: + device = this_controller->device_table[index]; + dev_warn(scic_to_dev(this_controller), + "%s: SCIC SDS Completion type SDMA %x for remote " + "device %p\n", + __func__, + completion_entry, + device); + /* @todo For a port RNC operation we need to fail the + * device + */ + break; + + default: + dev_warn(scic_to_dev(this_controller), + "%s: SCIC SDS Completion unknown SDMA completion " + "type %x\n", + __func__, + completion_entry); + break; + + } +} + +/** + * + * @this_controller: + * @completion_entry: + * + * This method processes an unsolicited frame message. This is called from + * within the controller completion handler. none + */ +static void scic_sds_controller_unsolicited_frame( + struct scic_sds_controller *this_controller, + u32 completion_entry) +{ + u32 index; + u32 frame_index; + + struct scu_unsolicited_frame_header *frame_header; + struct scic_sds_phy *phy; + struct scic_sds_remote_device *device; + + enum sci_status result = SCI_FAILURE; + + frame_index = SCU_GET_FRAME_INDEX(completion_entry); + + frame_header + = this_controller->uf_control.buffers.array[frame_index].header; + this_controller->uf_control.buffers.array[frame_index].state + = UNSOLICITED_FRAME_IN_USE; + + if (SCU_GET_FRAME_ERROR(completion_entry)) { + /* + * / @todo If the IAF frame or SIGNATURE FIS frame has an error will + * / this cause a problem? We expect the phy initialization will + * / fail if there is an error in the frame. */ + scic_sds_controller_release_frame(this_controller, frame_index); + return; + } + + if (frame_header->is_address_frame) { + index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + phy = &this_controller->phy_table[index]; + if (phy != NULL) { + result = scic_sds_phy_frame_handler(phy, frame_index); + } + } else { + + index = SCU_GET_COMPLETION_INDEX(completion_entry); + + if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + /* + * This is a signature fis or a frame from a direct attached SATA + * device that has not yet been created. In either case forwared + * the frame to the PE and let it take care of the frame data. */ + index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + phy = &this_controller->phy_table[index]; + result = scic_sds_phy_frame_handler(phy, frame_index); + } else { + if (index < this_controller->remote_node_entries) + device = this_controller->device_table[index]; + else + device = NULL; + + if (device != NULL) + result = scic_sds_remote_device_frame_handler(device, frame_index); + else + scic_sds_controller_release_frame(this_controller, frame_index); + } + } + + if (result != SCI_SUCCESS) { + /* + * / @todo Is there any reason to report some additional error message + * / when we get this failure notifiction? */ + } +} + +/** + * This method processes an event completion entry. This is called from within + * the controller completion handler. + * @this_controller: + * @completion_entry: + * + */ +static void scic_sds_controller_event_completion( + struct scic_sds_controller *this_controller, + u32 completion_entry) +{ + u32 index; + struct scic_sds_request *io_request; + struct scic_sds_remote_device *device; + struct scic_sds_phy *phy; + + index = SCU_GET_COMPLETION_INDEX(completion_entry); + + switch (scu_get_event_type(completion_entry)) { + case SCU_EVENT_TYPE_SMU_COMMAND_ERROR: + /* / @todo The driver did something wrong and we need to fix the condtion. */ + dev_err(scic_to_dev(this_controller), + "%s: SCIC Controller 0x%p received SMU command error " + "0x%x\n", + __func__, + this_controller, + completion_entry); + break; + + case SCU_EVENT_TYPE_SMU_PCQ_ERROR: + case SCU_EVENT_TYPE_SMU_ERROR: + case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR: + /* + * / @todo This is a hardware failure and its likely that we want to + * / reset the controller. */ + dev_err(scic_to_dev(this_controller), + "%s: SCIC Controller 0x%p received fatal controller " + "event 0x%x\n", + __func__, + this_controller, + completion_entry); + break; + + case SCU_EVENT_TYPE_TRANSPORT_ERROR: + io_request = this_controller->io_request_table[index]; + scic_sds_io_request_event_handler(io_request, completion_entry); + break; + + case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: + switch (scu_get_event_specifier(completion_entry)) { + case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: + case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: + io_request = this_controller->io_request_table[index]; + if (io_request != SCI_INVALID_HANDLE) + scic_sds_io_request_event_handler(io_request, completion_entry); + else + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller 0x%p received " + "event 0x%x for io request object " + "that doesnt exist.\n", + __func__, + this_controller, + completion_entry); + + break; + + case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: + device = this_controller->device_table[index]; + if (device != SCI_INVALID_HANDLE) + scic_sds_remote_device_event_handler(device, completion_entry); + else + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller 0x%p received " + "event 0x%x for remote device object " + "that doesnt exist.\n", + __func__, + this_controller, + completion_entry); + + break; + } + break; + + case SCU_EVENT_TYPE_BROADCAST_CHANGE: + /* + * direct the broadcast change event to the phy first and then let + * the phy redirect the broadcast change to the port object */ + case SCU_EVENT_TYPE_ERR_CNT_EVENT: + /* + * direct error counter event to the phy object since that is where + * we get the event notification. This is a type 4 event. */ + case SCU_EVENT_TYPE_OSSP_EVENT: + index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + phy = &this_controller->phy_table[index]; + scic_sds_phy_event_handler(phy, completion_entry); + break; + + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + case SCU_EVENT_TYPE_RNC_OPS_MISC: + if (index < this_controller->remote_node_entries) { + device = this_controller->device_table[index]; + + if (device != NULL) + scic_sds_remote_device_event_handler(device, completion_entry); + } else + dev_err(scic_to_dev(this_controller), + "%s: SCIC Controller 0x%p received event 0x%x " + "for remote device object 0x%0x that doesnt " + "exist.\n", + __func__, + this_controller, + completion_entry, + index); + + break; + + default: + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller received unknown event code %x\n", + __func__, + completion_entry); + break; + } +} + +/** + * This method is a private routine for processing the completion queue entries. + * @this_controller: + * + */ +static void scic_sds_controller_process_completions( + struct scic_sds_controller *this_controller) +{ + u32 completion_count = 0; + u32 completion_entry; + u32 get_index; + u32 get_cycle; + u32 event_index; + u32 event_cycle; + + dev_dbg(scic_to_dev(this_controller), + "%s: completion queue begining get:0x%08x\n", + __func__, + this_controller->completion_queue_get); + + /* Get the component parts of the completion queue */ + get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get); + get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get; + + event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get); + event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get; + + while ( + NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) + == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index]) + ) { + completion_count++; + + completion_entry = this_controller->completion_queue[get_index]; + INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle); + + dev_dbg(scic_to_dev(this_controller), + "%s: completion queue entry:0x%08x\n", + __func__, + completion_entry); + + switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { + case SCU_COMPLETION_TYPE_TASK: + scic_sds_controller_task_completion(this_controller, completion_entry); + break; + + case SCU_COMPLETION_TYPE_SDMA: + scic_sds_controller_sdma_completion(this_controller, completion_entry); + break; + + case SCU_COMPLETION_TYPE_UFI: + scic_sds_controller_unsolicited_frame(this_controller, completion_entry); + break; + + case SCU_COMPLETION_TYPE_EVENT: + INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); + scic_sds_controller_event_completion(this_controller, completion_entry); + break; + + case SCU_COMPLETION_TYPE_NOTIFY: + /* + * Presently we do the same thing with a notify event that we do with the + * other event codes. */ + INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); + scic_sds_controller_event_completion(this_controller, completion_entry); + break; + + default: + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller received unknown " + "completion type %x\n", + __func__, + completion_entry); + break; + } + } + + /* Update the get register if we completed one or more entries */ + if (completion_count > 0) { + this_controller->completion_queue_get = + SMU_CQGR_GEN_BIT(ENABLE) + | SMU_CQGR_GEN_BIT(EVENT_ENABLE) + | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) + | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); + + SMU_CQGR_WRITE(this_controller, + this_controller->completion_queue_get); + } + + dev_dbg(scic_to_dev(this_controller), + "%s: completion queue ending get:0x%08x\n", + __func__, + this_controller->completion_queue_get); + +} + +/** + * This method is a private routine for processing the completion queue entries. + * @this_controller: + * + */ +static void scic_sds_controller_transitioned_process_completions( + struct scic_sds_controller *this_controller) +{ + u32 completion_count = 0; + u32 completion_entry; + u32 get_index; + u32 get_cycle; + u32 event_index; + u32 event_cycle; + + dev_dbg(scic_to_dev(this_controller), + "%s: completion queue begining get:0x%08x\n", + __func__, + this_controller->completion_queue_get); + + /* Get the component parts of the completion queue */ + get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get); + get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get; + + event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get); + event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get; + + while ( + NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) + == COMPLETION_QUEUE_CYCLE_BIT( + this_controller->completion_queue[get_index]) + ) { + completion_count++; + + completion_entry = this_controller->completion_queue[get_index]; + INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle); + + dev_dbg(scic_to_dev(this_controller), + "%s: completion queue entry:0x%08x\n", + __func__, + completion_entry); + + switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { + case SCU_COMPLETION_TYPE_TASK: + scic_sds_controller_task_completion(this_controller, completion_entry); + break; + + case SCU_COMPLETION_TYPE_NOTIFY: + case SCU_COMPLETION_TYPE_EVENT: + /* + * Presently we do the same thing with a notify event that we + * do with the other event codes. */ + INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); + /* Fall-through */ + + case SCU_COMPLETION_TYPE_SDMA: + case SCU_COMPLETION_TYPE_UFI: + default: + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller ignoring completion type " + "%x\n", + __func__, + completion_entry); + break; + } + } + + /* Update the get register if we completed one or more entries */ + if (completion_count > 0) { + this_controller->completion_queue_get = + SMU_CQGR_GEN_BIT(ENABLE) + | SMU_CQGR_GEN_BIT(EVENT_ENABLE) + | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) + | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); + + SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get); + } + + dev_dbg(scic_to_dev(this_controller), + "%s: completion queue ending get:0x%08x\n", + __func__, + this_controller->completion_queue_get); +} + +/* + * ****************************************************************************- + * * SCIC SDS Controller Interrupt and Completion functions + * ****************************************************************************- */ + +/** + * This method provides standard (common) processing of interrupts for polling + * and legacy based interrupts. + * @controller: + * @interrupt_status: + * + * This method returns a boolean (bool) indication as to whether an completions + * are pending to be processed. true if an interrupt is to be processed false + * if no interrupt was pending + */ +static bool scic_sds_controller_standard_interrupt_handler( + struct scic_sds_controller *this_controller, + u32 interrupt_status) +{ + bool is_completion_needed = false; + + if ((interrupt_status & SMU_ISR_QUEUE_ERROR) || + ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && + (!scic_sds_controller_completion_queue_has_entries( + this_controller)))) { + /* + * We have a fatal error on the read of the completion queue bar + * OR + * We have a fatal error there is nothing in the completion queue + * but we have a report from the hardware that the queue is full + * / @todo how do we request the a controller reset */ + is_completion_needed = true; + this_controller->encountered_fatal_error = true; + } + + if (scic_sds_controller_completion_queue_has_entries(this_controller)) { + is_completion_needed = true; + } + + return is_completion_needed; +} + +/** + * This is the method provided to handle polling for interrupts for the + * controller object. + * + * bool true if an interrupt is to be processed false if no interrupt was + * pending + */ +static bool scic_sds_controller_polling_interrupt_handler( + struct scic_sds_controller *scic) +{ + u32 interrupt_status; + + /* + * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the + * hardware indicates nothing is pending. Since we are not being + * called from a real interrupt, we don't want to confuse the hardware + * by servicing the completion queue before the hardware indicates it + * is ready. We'll simply wait for another polling interval and check + * again. + */ + interrupt_status = SMU_ISR_READ(scic); + if ((interrupt_status & + (SMU_ISR_COMPLETION | + SMU_ISR_QUEUE_ERROR | + SMU_ISR_QUEUE_SUSPEND)) == 0) { + return false; + } + + return scic_sds_controller_standard_interrupt_handler( + scic, interrupt_status); +} + +/** + * This is the method provided to handle completions when interrupt polling is + * in use. + */ +static void scic_sds_controller_polling_completion_handler( + struct scic_sds_controller *scic) +{ + if (scic->encountered_fatal_error == true) { + dev_err(scic_to_dev(scic), + "%s: SCIC Controller has encountered a fatal error.\n", + __func__); + + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_FAILED); + } else if (scic_sds_controller_completion_queue_has_entries(scic)) { + if (scic->restrict_completions == false) + scic_sds_controller_process_completions(scic); + else + scic_sds_controller_transitioned_process_completions( + scic); + } + + /* + * The interrupt handler does not adjust the CQ's + * get pointer. So, SCU's INTx pin stays asserted during the + * interrupt handler even though it tries to clear the interrupt + * source. Therefore, the completion handler must ensure that the + * interrupt source is cleared. Otherwise, we get a spurious + * interrupt for which the interrupt handler will not issue a + * corresponding completion event. Also, we unmask interrupts. + */ + SMU_ISR_WRITE( + scic, + (u32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND) + ); +} + +/** + * This is the method provided to handle legacy interrupts for the controller + * object. + * + * bool true if an interrupt is processed false if no interrupt was processed + */ +static bool scic_sds_controller_legacy_interrupt_handler( + struct scic_sds_controller *scic) +{ + u32 interrupt_status; + bool is_completion_needed; + + interrupt_status = SMU_ISR_READ(scic); + is_completion_needed = scic_sds_controller_standard_interrupt_handler( + scic, interrupt_status); + + return is_completion_needed; +} + + +/** + * This is the method provided to handle legacy completions it is expected that + * the SCI User will call this completion handler anytime the interrupt + * handler reports that it has handled an interrupt. + */ +static void scic_sds_controller_legacy_completion_handler( + struct scic_sds_controller *scic) +{ + scic_sds_controller_polling_completion_handler(scic); + SMU_IMR_WRITE(scic, 0x00000000); +} + +/** + * This is the method provided to handle an MSIX interrupt message when there + * is just a single MSIX message being provided by the hardware. This mode + * of operation is single vector mode. + * + * bool true if an interrupt is processed false if no interrupt was processed + */ +static bool scic_sds_controller_single_vector_interrupt_handler( + struct scic_sds_controller *scic) +{ + u32 interrupt_status; + + /* + * Mask the interrupts + * There is a race in the hardware that could cause us not to be notified + * of an interrupt completion if we do not take this step. We will unmask + * the interrupts in the completion routine. */ + SMU_IMR_WRITE(scic, 0xFFFFFFFF); + + interrupt_status = SMU_ISR_READ(scic); + interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); + + if ((interrupt_status == 0) && + scic_sds_controller_completion_queue_has_entries(scic)) { + /* + * There is at least one completion queue entry to process so we can + * return a success and ignore for now the case of an error interrupt */ + SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); + return true; + } + + if (interrupt_status != 0) { + /* + * There is an error interrupt pending so let it through and handle + * in the callback */ + return true; + } + + /* + * Clear any offending interrupts since we could not find any to handle + * and unmask them all */ + SMU_ISR_WRITE(scic, 0x00000000); + SMU_IMR_WRITE(scic, 0x00000000); + + return false; +} + +/** + * This is the method provided to handle completions for a single MSIX message. + */ +static void scic_sds_controller_single_vector_completion_handler( + struct scic_sds_controller *scic) +{ + u32 interrupt_status; + + interrupt_status = SMU_ISR_READ(scic); + interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); + + if (interrupt_status & SMU_ISR_QUEUE_ERROR) { + dev_err(scic_to_dev(scic), + "%s: SCIC Controller has encountered a fatal error.\n", + __func__); + + /* + * We have a fatal condition and must reset the controller + * Leave the interrupt mask in place and get the controller reset */ + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_FAILED); + return; + } + + if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && + !scic_sds_controller_completion_queue_has_entries(scic)) { + dev_err(scic_to_dev(scic), + "%s: SCIC Controller has encountered a fatal error.\n", + __func__); + + /* + * We have a fatal condtion and must reset the controller + * Leave the interrupt mask in place and get the controller reset */ + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_FAILED); + return; + } + + if (scic_sds_controller_completion_queue_has_entries(scic)) { + scic_sds_controller_process_completions(scic); + + /* + * We dont care which interrupt got us to processing the completion queu + * so clear them both. */ + SMU_ISR_WRITE( + scic, + (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)); + } + + SMU_IMR_WRITE(scic, 0x00000000); +} + +/** + * This is the method provided to handle a MSIX message for a normal completion. + * + * bool true if an interrupt is processed false if no interrupt was processed + */ +static bool scic_sds_controller_normal_vector_interrupt_handler( + struct scic_sds_controller *scic) +{ + if (scic_sds_controller_completion_queue_has_entries(scic)) { + return true; + } else { + /* + * we have a spurious interrupt it could be that we have already + * emptied the completion queue from a previous interrupt */ + SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); + + /* + * There is a race in the hardware that could cause us not to be notified + * of an interrupt completion if we do not take this step. We will mask + * then unmask the interrupts so if there is another interrupt pending + * the clearing of the interrupt source we get the next interrupt message. */ + SMU_IMR_WRITE(scic, 0xFF000000); + SMU_IMR_WRITE(scic, 0x00000000); + } + + return false; +} + +/** + * This is the method provided to handle the completions for a normal MSIX + * message. + */ +static void scic_sds_controller_normal_vector_completion_handler( + struct scic_sds_controller *scic) +{ + /* Empty out the completion queue */ + if (scic_sds_controller_completion_queue_has_entries(scic)) + scic_sds_controller_process_completions(scic); + + /* Clear the interrupt and enable all interrupts again */ + SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); + /* Could we write the value of SMU_ISR_COMPLETION? */ + SMU_IMR_WRITE(scic, 0xFF000000); + SMU_IMR_WRITE(scic, 0x00000000); +} + +/** + * This is the method provided to handle the error MSIX message interrupt. + * This is the normal operating mode for the hardware if MSIX is enabled. + * + * bool true if an interrupt is processed false if no interrupt was processed + */ +static bool scic_sds_controller_error_vector_interrupt_handler( + struct scic_sds_controller *scic) +{ + u32 interrupt_status; + + interrupt_status = SMU_ISR_READ(scic); + interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); + + if (interrupt_status != 0) { + /* + * There is an error interrupt pending so let it through and handle + * in the callback */ + return true; + } + + /* + * There is a race in the hardware that could cause us not to be notified + * of an interrupt completion if we do not take this step. We will mask + * then unmask the error interrupts so if there was another interrupt + * pending we will be notified. + * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */ + SMU_IMR_WRITE(scic, 0x000000FF); + SMU_IMR_WRITE(scic, 0x00000000); + + return false; +} + +/** + * This is the method provided to handle the error completions when the + * hardware is using two MSIX messages. + */ +static void scic_sds_controller_error_vector_completion_handler( + struct scic_sds_controller *scic) +{ + u32 interrupt_status; + + interrupt_status = SMU_ISR_READ(scic); + + if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && + scic_sds_controller_completion_queue_has_entries(scic)) { + + scic_sds_controller_process_completions(scic); + SMU_ISR_WRITE(scic, SMU_ISR_QUEUE_SUSPEND); + + } else { + dev_err(scic_to_dev(scic), + "%s: SCIC Controller reports CRC error on completion " + "ISR %x\n", + __func__, + interrupt_status); + + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_FAILED); + + return; + } + + /* + * If we dont process any completions I am not sure that we want to do this. + * We are in the middle of a hardware fault and should probably be reset. */ + SMU_IMR_WRITE(scic, 0x00000000); +} + + +/* + * ****************************************************************************- + * * SCIC SDS Controller External Methods + * ****************************************************************************- */ + +/** + * This method returns the sizeof the SCIC SDS Controller Object + */ +u32 scic_sds_controller_get_object_size(void) +{ + return sizeof(struct scic_sds_controller); +} + + +void scic_sds_controller_link_up( + struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + scic_sds_controller_phy_handler_t link_up; + u32 state; + + state = scic->parent.state_machine.current_state_id; + link_up = scic_sds_controller_state_handler_table[state].link_up; + + if (link_up) + link_up(scic, sci_port, sci_phy); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller linkup event from phy %d in " + "unexpected state %d\n", + __func__, + sci_phy->phy_index, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + scic))); +} + + +void scic_sds_controller_link_down( + struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + u32 state; + scic_sds_controller_phy_handler_t link_down; + + state = scic->parent.state_machine.current_state_id; + link_down = scic_sds_controller_state_handler_table[state].link_down; + + if (link_down) + link_down(scic, sci_port, sci_phy); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller linkdown event from phy %d in " + "unexpected state %d\n", + __func__, + sci_phy->phy_index, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + scic))); +} + +/** + * This method will write to the SCU PCP register the request value. The method + * is used to suspend/resume ports, devices, and phys. + * @this_controller: + * + * + */ +void scic_sds_controller_post_request( + struct scic_sds_controller *this_controller, + u32 request) +{ + dev_dbg(scic_to_dev(this_controller), + "%s: SCIC Controller 0x%p post request 0x%08x\n", + __func__, + this_controller, + request); + + SMU_PCP_WRITE(this_controller, request); +} + +/** + * This method will copy the soft copy of the task context into the physical + * memory accessible by the controller. + * @this_controller: This parameter specifies the controller for which to copy + * the task context. + * @this_request: This parameter specifies the request for which the task + * context is being copied. + * + * After this call is made the SCIC_SDS_IO_REQUEST object will always point to + * the physical memory version of the task context. Thus, all subsequent + * updates to the task context are performed in the TC table (i.e. DMAable + * memory). none + */ +void scic_sds_controller_copy_task_context( + struct scic_sds_controller *this_controller, + struct scic_sds_request *this_request) +{ + struct scu_task_context *task_context_buffer; + + task_context_buffer = scic_sds_controller_get_task_context_buffer( + this_controller, this_request->io_tag + ); + + memcpy( + task_context_buffer, + this_request->task_context_buffer, + SCI_FIELD_OFFSET(struct scu_task_context, sgl_snapshot_ac) + ); + + /* + * Now that the soft copy of the TC has been copied into the TC + * table accessible by the silicon. Thus, any further changes to + * the TC (e.g. TC termination) occur in the appropriate location. */ + this_request->task_context_buffer = task_context_buffer; +} + +/** + * This method returns the task context buffer for the given io tag. + * @this_controller: + * @io_tag: + * + * struct scu_task_context* + */ +struct scu_task_context *scic_sds_controller_get_task_context_buffer( + struct scic_sds_controller *this_controller, + u16 io_tag + ) { + u16 task_index = scic_sds_io_tag_get_index(io_tag); + + if (task_index < this_controller->task_context_entries) { + return &this_controller->task_context_table[task_index]; + } + + return NULL; +} + +/** + * This method returnst the sequence value from the io tag value + * @this_controller: + * @io_tag: + * + * u16 + */ + +/** + * This method returns the IO request associated with the tag value + * @this_controller: + * @io_tag: + * + * SCIC_SDS_IO_REQUEST_T* NULL if there is no valid IO request at the tag value + */ +struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( + struct scic_sds_controller *this_controller, + u16 io_tag + ) { + u16 task_index; + u16 task_sequence; + + task_index = scic_sds_io_tag_get_index(io_tag); + + if (task_index < this_controller->task_context_entries) { + if (this_controller->io_request_table[task_index] != SCI_INVALID_HANDLE) { + task_sequence = scic_sds_io_tag_get_sequence(io_tag); + + if (task_sequence == this_controller->io_request_sequence[task_index]) { + return this_controller->io_request_table[task_index]; + } + } + } + + return SCI_INVALID_HANDLE; +} + +/** + * This method allocates remote node index and the reserves the remote node + * context space for use. This method can fail if there are no more remote + * node index available. + * @this_controller: This is the controller object which contains the set of + * free remote node ids + * @the_devce: This is the device object which is requesting the a remote node + * id + * @node_id: This is the remote node id that is assinged to the device if one + * is available + * + * enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote + * node index available. + */ +enum sci_status scic_sds_controller_allocate_remote_node_context( + struct scic_sds_controller *this_controller, + struct scic_sds_remote_device *the_device, + u16 *node_id) +{ + u16 node_index; + u32 remote_node_count = scic_sds_remote_device_node_count(the_device); + + node_index = scic_sds_remote_node_table_allocate_remote_node( + &this_controller->available_remote_nodes, remote_node_count + ); + + if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + this_controller->device_table[node_index] = the_device; + + *node_id = node_index; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INSUFFICIENT_RESOURCES; +} + +/** + * This method frees the remote node index back to the available pool. Once + * this is done the remote node context buffer is no longer valid and can + * not be used. + * @this_controller: + * @the_device: + * @node_id: + * + */ +void scic_sds_controller_free_remote_node_context( + struct scic_sds_controller *this_controller, + struct scic_sds_remote_device *the_device, + u16 node_id) +{ + u32 remote_node_count = scic_sds_remote_device_node_count(the_device); + + if (this_controller->device_table[node_id] == the_device) { + this_controller->device_table[node_id] = SCI_INVALID_HANDLE; + + scic_sds_remote_node_table_release_remote_node_index( + &this_controller->available_remote_nodes, remote_node_count, node_id + ); + } +} + +/** + * This method returns the union scu_remote_node_context for the specified remote + * node id. + * @this_controller: + * @node_id: + * + * union scu_remote_node_context* + */ +union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( + struct scic_sds_controller *this_controller, + u16 node_id + ) { + if ( + (node_id < this_controller->remote_node_entries) + && (this_controller->device_table[node_id] != SCI_INVALID_HANDLE) + ) { + return &this_controller->remote_node_context_table[node_id]; + } + + return NULL; +} + +/** + * + * @resposne_buffer: This is the buffer into which the D2H register FIS will be + * constructed. + * @frame_header: This is the frame header returned by the hardware. + * @frame_buffer: This is the frame buffer returned by the hardware. + * + * This method will combind the frame header and frame buffer to create a SATA + * D2H register FIS none + */ +void scic_sds_controller_copy_sata_response( + void *response_buffer, + void *frame_header, + void *frame_buffer) +{ + memcpy( + response_buffer, + frame_header, + sizeof(u32) + ); + + memcpy( + (char *)((char *)response_buffer + sizeof(u32)), + frame_buffer, + sizeof(struct sata_fis_reg_d2h) - sizeof(u32) + ); +} + +/** + * This method releases the frame once this is done the frame is available for + * re-use by the hardware. The data contained in the frame header and frame + * buffer is no longer valid. The UF queue get pointer is only updated if UF + * control indicates this is appropriate. + * @this_controller: + * @frame_index: + * + */ +void scic_sds_controller_release_frame( + struct scic_sds_controller *this_controller, + u32 frame_index) +{ + if (scic_sds_unsolicited_frame_control_release_frame( + &this_controller->uf_control, frame_index) == true) + SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get); +} + +/** + * This method sets user parameters and OEM parameters to default values. + * Users can override these values utilizing the scic_user_parameters_set() + * and scic_oem_parameters_set() methods. + * @controller: This parameter specifies the controller for which to set the + * configuration parameters to their default values. + * + */ +static void scic_sds_controller_set_default_config_parameters( + struct scic_sds_controller *this_controller) +{ + u16 index; + + /* Default to no SSC operation. */ + this_controller->oem_parameters.sds1.controller.do_enable_ssc = false; + + /* Initialize all of the port parameter information to narrow ports. */ + for (index = 0; index < SCI_MAX_PORTS; index++) { + this_controller->oem_parameters.sds1.ports[index].phy_mask = 0; + } + + /* Initialize all of the phy parameter information. */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + /* + * Default to 3G (i.e. Gen 2) for now. User can override if + * they choose. */ + this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2; + + /* + * Previous Vitesse based expanders had a arbitration issue that + * is worked around by having the upper 32-bits of SAS address + * with a value greater then the Vitesse company identifier. + * Hence, usage of 0x5FCFFFFF. */ + this_controller->oem_parameters.sds1.phys[index].sas_address.low + = 0x00000001; + this_controller->oem_parameters.sds1.phys[index].sas_address.high + = 0x5FCFFFFF; + } + + this_controller->user_parameters.sds1.stp_inactivity_timeout = 5; + this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5; + this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5; + this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20; + this_controller->user_parameters.sds1.no_outbound_task_timeout = 5; + +} + + +enum sci_status scic_controller_construct(struct scic_sds_controller *controller, + void __iomem *scu_base, + void __iomem *smu_base) +{ + u8 index; + + sci_base_controller_construct( + &controller->parent, + scic_sds_controller_state_table, + controller->memory_descriptors, + ARRAY_SIZE(controller->memory_descriptors), + NULL + ); + + controller->scu_registers = scu_base; + controller->smu_registers = smu_base; + + scic_sds_port_configuration_agent_construct(&controller->port_agent); + + /* Construct the ports for this controller */ + for (index = 0; index < SCI_MAX_PORTS; index++) + scic_sds_port_construct(&controller->port_table[index], + index, controller); + scic_sds_port_construct(&controller->port_table[index], + SCIC_SDS_DUMMY_PORT, controller); + + /* Construct the phys for this controller */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + /* Add all the PHYs to the dummy port */ + scic_sds_phy_construct( + &controller->phy_table[index], + &controller->port_table[SCI_MAX_PORTS], + index + ); + } + + controller->invalid_phy_mask = 0; + + /* Set the default maximum values */ + controller->completion_event_entries = SCU_EVENT_COUNT; + controller->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; + controller->remote_node_entries = SCI_MAX_REMOTE_DEVICES; + controller->logical_port_entries = SCI_MAX_PORTS; + controller->task_context_entries = SCU_IO_REQUEST_COUNT; + controller->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT; + controller->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT; + + /* Initialize the User and OEM parameters to default values. */ + scic_sds_controller_set_default_config_parameters(controller); + + return SCI_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_initialize( + struct scic_sds_controller *scic) +{ + enum sci_status status = SCI_FAILURE_INVALID_STATE; + sci_base_controller_handler_t initialize; + u32 state; + + state = scic->parent.state_machine.current_state_id; + initialize = scic_sds_controller_state_handler_table[state].base.initialize; + + if (initialize) + status = initialize(&scic->parent); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller initialize operation requested " + "in invalid state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + scic))); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +u32 scic_controller_get_suggested_start_timeout( + struct scic_sds_controller *sc) +{ + /* Validate the user supplied parameters. */ + if (sc == SCI_INVALID_HANDLE) + return 0; + + /* + * The suggested minimum timeout value for a controller start operation: + * + * Signature FIS Timeout + * + Phy Start Timeout + * + Number of Phy Spin Up Intervals + * --------------------------------- + * Number of milliseconds for the controller start operation. + * + * NOTE: The number of phy spin up intervals will be equivalent + * to the number of phys divided by the number phys allowed + * per interval - 1 (once OEM parameters are supported). + * Currently we assume only 1 phy per interval. */ + + return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT + + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT + + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL)); +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_start( + struct scic_sds_controller *scic, + u32 timeout) +{ + enum sci_status status = SCI_FAILURE_INVALID_STATE; + sci_base_controller_timed_handler_t start; + u32 state; + + state = scic->parent.state_machine.current_state_id; + start = scic_sds_controller_state_handler_table[state].base.start; + + if (start) + status = start(&scic->parent, timeout); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller start operation requested in " + "invalid state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + scic))); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_stop( + struct scic_sds_controller *scic, + u32 timeout) +{ + enum sci_status status = SCI_FAILURE_INVALID_STATE; + sci_base_controller_timed_handler_t stop; + u32 state; + + state = scic->parent.state_machine.current_state_id; + stop = scic_sds_controller_state_handler_table[state].base.stop; + + if (stop) + status = stop(&scic->parent, timeout); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller stop operation requested in " + "invalid state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + scic))); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_reset( + struct scic_sds_controller *scic) +{ + enum sci_status status = SCI_FAILURE_INVALID_STATE; + sci_base_controller_handler_t reset; + u32 state; + + state = scic->parent.state_machine.current_state_id; + reset = scic_sds_controller_state_handler_table[state].base.reset; + + if (reset) + status = reset(&scic->parent); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller reset operation requested in " + "invalid state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + scic))); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_get_handler_methods( + enum scic_interrupt_type interrupt_type, + u16 message_count, + struct scic_controller_handler_methods *handler_methods) +{ + enum sci_status status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT; + + switch (interrupt_type) { + case SCIC_LEGACY_LINE_INTERRUPT_TYPE: + if (message_count == 0) { + handler_methods[0].interrupt_handler + = scic_sds_controller_legacy_interrupt_handler; + handler_methods[0].completion_handler + = scic_sds_controller_legacy_completion_handler; + + status = SCI_SUCCESS; + } + break; + + case SCIC_MSIX_INTERRUPT_TYPE: + if (message_count == 1) { + handler_methods[0].interrupt_handler + = scic_sds_controller_single_vector_interrupt_handler; + handler_methods[0].completion_handler + = scic_sds_controller_single_vector_completion_handler; + + status = SCI_SUCCESS; + } else if (message_count == 2) { + handler_methods[0].interrupt_handler + = scic_sds_controller_normal_vector_interrupt_handler; + handler_methods[0].completion_handler + = scic_sds_controller_normal_vector_completion_handler; + + handler_methods[1].interrupt_handler + = scic_sds_controller_error_vector_interrupt_handler; + handler_methods[1].completion_handler + = scic_sds_controller_error_vector_completion_handler; + + status = SCI_SUCCESS; + } + break; + + case SCIC_NO_INTERRUPTS: + if (message_count == 0) { + + handler_methods[0].interrupt_handler + = scic_sds_controller_polling_interrupt_handler; + handler_methods[0].completion_handler + = scic_sds_controller_polling_completion_handler; + + status = SCI_SUCCESS; + } + break; + + default: + status = SCI_FAILURE_INVALID_PARAMETER_VALUE; + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +enum sci_io_status scic_controller_start_io( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *io_request, + u16 io_tag) +{ + u32 state; + sci_base_controller_start_request_handler_t start_io; + + state = scic->parent.state_machine.current_state_id; + start_io = scic_sds_controller_state_handler_table[state].base.start_io; + + return start_io(&scic->parent, + (struct sci_base_remote_device *) remote_device, + (struct sci_base_request *)io_request, io_tag); +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_terminate_request( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *request) +{ + sci_base_controller_request_handler_t terminate_request; + u32 state; + + state = scic->parent.state_machine.current_state_id; + terminate_request = scic_sds_controller_state_handler_table[state].terminate_request; + + return terminate_request(&scic->parent, + (struct sci_base_remote_device *)remote_device, + (struct sci_base_request *)request); +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_complete_io( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *io_request) +{ + u32 state; + sci_base_controller_request_handler_t complete_io; + + state = scic->parent.state_machine.current_state_id; + complete_io = scic_sds_controller_state_handler_table[state].base.complete_io; + + return complete_io(&scic->parent, + (struct sci_base_remote_device *)remote_device, + (struct sci_base_request *)io_request); +} + +/* --------------------------------------------------------------------------- */ + + +enum sci_task_status scic_controller_start_task( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *task_request, + u16 task_tag) +{ + u32 state; + sci_base_controller_start_request_handler_t start_task; + enum sci_task_status status = SCI_TASK_FAILURE_INVALID_STATE; + + state = scic->parent.state_machine.current_state_id; + start_task = scic_sds_controller_state_handler_table[state].base.start_task; + + if (start_task) + status = start_task(&scic->parent, + (struct sci_base_remote_device *)remote_device, + (struct sci_base_request *)task_request, + task_tag); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller starting task from invalid " + "state\n", + __func__); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_complete_task( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *task_request) +{ + u32 state; + sci_base_controller_request_handler_t complete_task; + enum sci_status status = SCI_FAILURE_INVALID_STATE; + + state = scic->parent.state_machine.current_state_id; + complete_task = scic_sds_controller_state_handler_table[state].base.complete_task; + + if (complete_task) + status = complete_task(&scic->parent, + (struct sci_base_remote_device *)remote_device, + (struct sci_base_request *)task_request); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller completing task from invalid " + "state\n", + __func__); + + return status; +} + + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_get_port_handle( + struct scic_sds_controller *scic, + u8 port_index, + struct scic_sds_port **port_handle) +{ + if (port_index < scic->logical_port_entries) { + *port_handle = &scic->port_table[port_index]; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_PORT; +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_get_phy_handle( + struct scic_sds_controller *scic, + u8 phy_index, + struct scic_sds_phy **phy_handle) +{ + if (phy_index < ARRAY_SIZE(scic->phy_table)) { + *phy_handle = &scic->phy_table[phy_index]; + + return SCI_SUCCESS; + } + + dev_err(scic_to_dev(scic), + "%s: Controller:0x%p PhyId:0x%x invalid phy index\n", + __func__, scic, phy_index); + + return SCI_FAILURE_INVALID_PHY; +} + +/* --------------------------------------------------------------------------- */ + +u16 scic_controller_allocate_io_tag( + struct scic_sds_controller *scic) +{ + u16 task_context; + u16 sequence_count; + + if (!sci_pool_empty(scic->tci_pool)) { + sci_pool_get(scic->tci_pool, task_context); + + sequence_count = scic->io_request_sequence[task_context]; + + return scic_sds_io_tag_construct(sequence_count, task_context); + } + + return SCI_CONTROLLER_INVALID_IO_TAG; +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_free_io_tag( + struct scic_sds_controller *scic, + u16 io_tag) +{ + u16 sequence; + u16 index; + + BUG_ON(io_tag == SCI_CONTROLLER_INVALID_IO_TAG); + + sequence = scic_sds_io_tag_get_sequence(io_tag); + index = scic_sds_io_tag_get_index(io_tag); + + if (!sci_pool_full(scic->tci_pool)) { + if (sequence == scic->io_request_sequence[index]) { + scic_sds_io_sequence_increment( + scic->io_request_sequence[index]); + + sci_pool_put(scic->tci_pool, index); + + return SCI_SUCCESS; + } + } + + return SCI_FAILURE_INVALID_IO_TAG; +} + +/* --------------------------------------------------------------------------- */ + +void scic_controller_enable_interrupts( + struct scic_sds_controller *scic) +{ + BUG_ON(scic->smu_registers == NULL); + SMU_IMR_WRITE(scic, 0x00000000); +} + +/* --------------------------------------------------------------------------- */ + +void scic_controller_disable_interrupts( + struct scic_sds_controller *scic) +{ + BUG_ON(scic->smu_registers == NULL); + SMU_IMR_WRITE(scic, 0xffffffff); +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_controller_set_mode( + struct scic_sds_controller *scic, + enum sci_controller_mode operating_mode) +{ + enum sci_status status = SCI_SUCCESS; + + if ((scic->parent.state_machine.current_state_id == + SCI_BASE_CONTROLLER_STATE_INITIALIZING) || + (scic->parent.state_machine.current_state_id == + SCI_BASE_CONTROLLER_STATE_INITIALIZED)) { + switch (operating_mode) { + case SCI_MODE_SPEED: + scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; + scic->task_context_entries = SCU_IO_REQUEST_COUNT; + scic->uf_control.buffers.count = + SCU_UNSOLICITED_FRAME_COUNT; + scic->completion_event_entries = SCU_EVENT_COUNT; + scic->completion_queue_entries = + SCU_COMPLETION_QUEUE_COUNT; + scic_sds_controller_build_memory_descriptor_table(scic); + break; + + case SCI_MODE_SIZE: + scic->remote_node_entries = SCI_MIN_REMOTE_DEVICES; + scic->task_context_entries = SCI_MIN_IO_REQUESTS; + scic->uf_control.buffers.count = + SCU_MIN_UNSOLICITED_FRAMES; + scic->completion_event_entries = SCU_MIN_EVENTS; + scic->completion_queue_entries = + SCU_MIN_COMPLETION_QUEUE_ENTRIES; + scic_sds_controller_build_memory_descriptor_table(scic); + break; + + default: + status = SCI_FAILURE_INVALID_PARAMETER_VALUE; + break; + } + } else + status = SCI_FAILURE_INVALID_STATE; + + return status; +} + +/** + * scic_sds_controller_reset_hardware() - + * + * This method will reset the controller hardware. + */ +void scic_sds_controller_reset_hardware( + struct scic_sds_controller *scic) +{ + /* Disable interrupts so we dont take any spurious interrupts */ + scic_controller_disable_interrupts(scic); + + /* Reset the SCU */ + SMU_SMUSRCR_WRITE(scic, 0xFFFFFFFF); + + /* Delay for 1ms to before clearing the CQP and UFQPR. */ + scic_cb_stall_execution(1000); + + /* The write to the CQGR clears the CQP */ + SMU_CQGR_WRITE(scic, 0x00000000); + + /* The write to the UFQGP clears the UFQPR */ + SCU_UFQGP_WRITE(scic, 0x00000000); +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_user_parameters_set( + struct scic_sds_controller *scic, + union scic_user_parameters *scic_parms) +{ + if ( + (scic->parent.state_machine.current_state_id + == SCI_BASE_CONTROLLER_STATE_RESET) + || (scic->parent.state_machine.current_state_id + == SCI_BASE_CONTROLLER_STATE_INITIALIZING) + || (scic->parent.state_machine.current_state_id + == SCI_BASE_CONTROLLER_STATE_INITIALIZED) + ) { + u16 index; + + /* + * Validate the user parameters. If they are not legal, then + * return a failure. */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (! + (scic_parms->sds1.phys[index].max_speed_generation + <= SCIC_SDS_PARM_MAX_SPEED + && scic_parms->sds1.phys[index].max_speed_generation + > SCIC_SDS_PARM_NO_SPEED + ) + ) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } + + memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms)); + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_STATE; +} + +/* --------------------------------------------------------------------------- */ + +void scic_user_parameters_get( + struct scic_sds_controller *scic, + union scic_user_parameters *scic_parms) +{ + memcpy(scic_parms, (&scic->user_parameters), sizeof(*scic_parms)); +} + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_oem_parameters_set( + struct scic_sds_controller *scic, + union scic_oem_parameters *scic_parms) +{ + if ( + (scic->parent.state_machine.current_state_id + == SCI_BASE_CONTROLLER_STATE_RESET) + || (scic->parent.state_machine.current_state_id + == SCI_BASE_CONTROLLER_STATE_INITIALIZING) + || (scic->parent.state_machine.current_state_id + == SCI_BASE_CONTROLLER_STATE_INITIALIZED) + ) { + u16 index; + + /* + * Validate the oem parameters. If they are not legal, then + * return a failure. */ + for (index = 0; index < SCI_MAX_PORTS; index++) { + if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) { + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } + } + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if ( + scic_parms->sds1.phys[index].sas_address.high == 0 + && scic_parms->sds1.phys[index].sas_address.low == 0 + ) { + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } + } + + memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms)); + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_STATE; +} + +/* --------------------------------------------------------------------------- */ + +void scic_oem_parameters_get( + struct scic_sds_controller *scic, + union scic_oem_parameters *scic_parms) +{ + memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms)); +} + +/* --------------------------------------------------------------------------- */ + + +#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853 +#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280 +#define INTERRUPT_COALESCE_TIMEOUT_MAX_US 2700000 +#define INTERRUPT_COALESCE_NUMBER_MAX 256 +#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 7 +#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28 + +enum sci_status scic_controller_set_interrupt_coalescence( + struct scic_sds_controller *scic_controller, + u32 coalesce_number, + u32 coalesce_timeout) +{ + u8 timeout_encode = 0; + u32 min = 0; + u32 max = 0; + + /* Check if the input parameters fall in the range. */ + if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + + /* + * Defined encoding for interrupt coalescing timeout: + * Value Min Max Units + * ----- --- --- ----- + * 0 - - Disabled + * 1 13.3 20.0 ns + * 2 26.7 40.0 + * 3 53.3 80.0 + * 4 106.7 160.0 + * 5 213.3 320.0 + * 6 426.7 640.0 + * 7 853.3 1280.0 + * 8 1.7 2.6 us + * 9 3.4 5.1 + * 10 6.8 10.2 + * 11 13.7 20.5 + * 12 27.3 41.0 + * 13 54.6 81.9 + * 14 109.2 163.8 + * 15 218.5 327.7 + * 16 436.9 655.4 + * 17 873.8 1310.7 + * 18 1.7 2.6 ms + * 19 3.5 5.2 + * 20 7.0 10.5 + * 21 14.0 21.0 + * 22 28.0 41.9 + * 23 55.9 83.9 + * 24 111.8 167.8 + * 25 223.7 335.5 + * 26 447.4 671.1 + * 27 894.8 1342.2 + * 28 1.8 2.7 s + * Others Undefined */ + + /* + * Use the table above to decide the encode of interrupt coalescing timeout + * value for register writing. */ + if (coalesce_timeout == 0) + timeout_encode = 0; + else{ + /* make the timeout value in unit of (10 ns). */ + coalesce_timeout = coalesce_timeout * 100; + min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10; + max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10; + + /* get the encode of timeout for register writing. */ + for (timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN; + timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX; + timeout_encode++) { + if (min <= coalesce_timeout && max > coalesce_timeout) + break; + else if (coalesce_timeout >= max && coalesce_timeout < min * 2 + && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US * 100) { + if ((coalesce_timeout - max) < (2 * min - coalesce_timeout)) + break; + else{ + timeout_encode++; + break; + } + } else { + max = max * 2; + min = min * 2; + } + } + + if (timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX + 1) + /* the value is out of range. */ + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } + + SMU_ICC_WRITE( + scic_controller, + (SMU_ICC_GEN_VAL(NUMBER, coalesce_number) | + SMU_ICC_GEN_VAL(TIMER, timeout_encode)) + ); + + scic_controller->interrupt_coalesce_number = (u16)coalesce_number; + scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100; + + return SCI_SUCCESS; +} + + +struct scic_sds_controller *scic_controller_alloc(struct device *dev) +{ + return devm_kzalloc(dev, sizeof(struct scic_sds_controller), GFP_KERNEL); +} + +/* + * ***************************************************************************** + * * DEFAULT STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which, if it was used, would + * be cast to a struct scic_sds_remote_device. + * @io_request: This is the struct sci_base_request which, if it was used, would be + * cast to a SCIC_SDS_IO_REQUEST. + * @io_tag: This is the IO tag to be assigned to the IO request or + * SCI_CONTROLLER_INVALID_IO_TAG. + * + * This method is called when the struct scic_sds_controller default start io/task + * handler is in place. - Issue a warning message enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_controller_default_start_operation_handler( + struct sci_base_controller *controller, + struct sci_base_remote_device *remote_device, + struct sci_base_request *io_request, + u16 io_tag) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller requested to start an io/task from " + "invalid state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + this_controller))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which, if it was used, would + * be cast to a struct scic_sds_remote_device. + * @io_request: This is the struct sci_base_request which, if it was used, would be + * cast to a SCIC_SDS_IO_REQUEST. + * + * This method is called when the struct scic_sds_controller default request handler + * is in place. - Issue a warning message enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_controller_default_request_handler( + struct sci_base_controller *controller, + struct sci_base_remote_device *remote_device, + struct sci_base_request *io_request) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller request operation from invalid state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + this_controller))); + + return SCI_FAILURE_INVALID_STATE; +} + +/* + * ***************************************************************************** + * * GENERAL (COMMON) STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @controller: The struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * + * This method is called when the struct scic_sds_controller is in the ready state + * reset handler is in place. - Transition to + * SCI_BASE_CONTROLLER_STATE_RESETTING enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_controller_general_reset_handler( + struct sci_base_controller *controller) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + /* + * The reset operation is not a graceful cleanup just perform the state + * transition. */ + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(this_controller), + SCI_BASE_CONTROLLER_STATE_RESETTING + ); + + return SCI_SUCCESS; +} + +/* + * ***************************************************************************** + * * RESET STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @controller: This is the struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * + * This method is the struct scic_sds_controller initialize handler for the reset + * state. - Currently this function does nothing enum sci_status SCI_FAILURE This + * function is not yet implemented and is a valid request from the reset state. + */ +static enum sci_status scic_sds_controller_reset_state_initialize_handler( + struct sci_base_controller *controller) +{ + u32 index; + enum sci_status result = SCI_SUCCESS; + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(this_controller), + SCI_BASE_CONTROLLER_STATE_INITIALIZING + ); + + this_controller->timeout_timer = scic_cb_timer_create( + this_controller, + (void (*)(void *))scic_sds_controller_timeout_handler, + (void (*)(void *))controller); + + scic_sds_controller_initialize_phy_startup(this_controller); + + scic_sds_controller_initialize_power_control(this_controller); + + /* + * There is nothing to do here for B0 since we do not have to + * program the AFE registers. + * / @todo The AFE settings are supposed to be correct for the B0 but + * / presently they seem to be wrong. */ + scic_sds_controller_afe_initialization(this_controller); + + if (SCI_SUCCESS == result) { + u32 status; + u32 terminate_loop; + + /* Take the hardware out of reset */ + SMU_SMUSRCR_WRITE(this_controller, 0x00000000); + + /* + * / @todo Provide meaningfull error code for hardware failure + * result = SCI_FAILURE_CONTROLLER_HARDWARE; */ + result = SCI_FAILURE; + terminate_loop = 100; + + while (terminate_loop-- && (result != SCI_SUCCESS)) { + /* Loop until the hardware reports success */ + scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME); + status = SMU_SMUCSR_READ(this_controller); + + if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) { + result = SCI_SUCCESS; + } + } + } + + if (result == SCI_SUCCESS) { + u32 max_supported_ports; + u32 max_supported_devices; + u32 max_supported_io_requests; + u32 device_context_capacity; + + /* + * Determine what are the actaul device capacities that the + * hardware will support */ + device_context_capacity = SMU_DCC_READ(this_controller); + + max_supported_ports = + smu_dcc_get_max_ports(device_context_capacity); + max_supported_devices = + smu_dcc_get_max_remote_node_context(device_context_capacity); + max_supported_io_requests = + smu_dcc_get_max_task_context(device_context_capacity); + + /* Make all PEs that are unassigned match up with the logical ports */ + for (index = 0; index < max_supported_ports; index++) { + scu_register_write( + this_controller, + this_controller->scu_registers->peg0.ptsg.protocol_engine[index], + index + ); + } + + /* Record the smaller of the two capacity values */ + this_controller->logical_port_entries = + min(max_supported_ports, this_controller->logical_port_entries); + + this_controller->task_context_entries = + min(max_supported_io_requests, this_controller->task_context_entries); + + this_controller->remote_node_entries = + min(max_supported_devices, this_controller->remote_node_entries); + + /* + * Now that we have the correct hardware reported minimum values + * build the MDL for the controller. Default to a performance + * configuration. */ + scic_controller_set_mode(this_controller, SCI_MODE_SPEED); + } + + /* Initialize hardware PCI Relaxed ordering in DMA engines */ + if (result == SCI_SUCCESS) { + u32 dma_configuration; + + /* Configure the payload DMA */ + dma_configuration = SCU_PDMACR_READ(this_controller); + dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); + SCU_PDMACR_WRITE(this_controller, dma_configuration); + + /* Configure the control DMA */ + dma_configuration = SCU_CDMACR_READ(this_controller); + dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); + SCU_CDMACR_WRITE(this_controller, dma_configuration); + } + + /* + * Initialize the PHYs before the PORTs because the PHY registers + * are accessed during the port initialization. */ + if (result == SCI_SUCCESS) { + /* Initialize the phys */ + for (index = 0; + (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS); + index++) { + result = scic_sds_phy_initialize( + &this_controller->phy_table[index], + &this_controller->scu_registers->peg0.pe[index].ll + ); + } + } + + if (result == SCI_SUCCESS) { + /* Initialize the logical ports */ + for (index = 0; + (index < this_controller->logical_port_entries) + && (result == SCI_SUCCESS); + index++) { + result = scic_sds_port_initialize( + &this_controller->port_table[index], + &this_controller->scu_registers->peg0.pe[index].tl, + &this_controller->scu_registers->peg0.ptsg.port[index], + &this_controller->scu_registers->peg0.ptsg.protocol_engine, + &this_controller->scu_registers->peg0.viit[index] + ); + } + } + + if (SCI_SUCCESS == result) { + result = scic_sds_port_configuration_agent_initialize( + this_controller, + &this_controller->port_agent + ); + } + + /* Advance the controller state machine */ + if (result == SCI_SUCCESS) { + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(this_controller), + SCI_BASE_CONTROLLER_STATE_INITIALIZED + ); + } else { + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(this_controller), + SCI_BASE_CONTROLLER_STATE_FAILED + ); + } + + return result; +} + +/* + * ***************************************************************************** + * * INITIALIZED STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @controller: This is the struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @timeout: This is the allowed time for the controller object to reach the + * started state. + * + * This method is the struct scic_sds_controller start handler for the initialized + * state. - Validate we have a good memory descriptor table - Initialze the + * physical memory before programming the hardware - Program the SCU hardware + * with the physical memory addresses passed in the memory descriptor table. - + * Initialzie the TCi pool - Initialize the RNi pool - Initialize the + * completion queue - Initialize the unsolicited frame data - Take the SCU port + * task scheduler out of reset - Start the first phy object. - Transition to + * SCI_BASE_CONTROLLER_STATE_STARTING. enum sci_status SCI_SUCCESS if all of the + * controller start operations complete + * SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the memory + * descriptor fields is invalid. + */ +static enum sci_status scic_sds_controller_initialized_state_start_handler( + struct sci_base_controller *controller, + u32 timeout) +{ + u16 index; + enum sci_status result; + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + /* Make sure that the SCI User filled in the memory descriptor table correctly */ + result = scic_sds_controller_validate_memory_descriptor_table(this_controller); + + if (result == SCI_SUCCESS) { + /* The memory descriptor list looks good so program the hardware */ + scic_sds_controller_ram_initialization(this_controller); + } + + if (SCI_SUCCESS == result) { + /* Build the TCi free pool */ + sci_pool_initialize(this_controller->tci_pool); + for (index = 0; index < this_controller->task_context_entries; index++) { + sci_pool_put(this_controller->tci_pool, index); + } + + /* Build the RNi free pool */ + scic_sds_remote_node_table_initialize( + &this_controller->available_remote_nodes, + this_controller->remote_node_entries + ); + } + + if (SCI_SUCCESS == result) { + /* + * Before anything else lets make sure we will not be interrupted + * by the hardware. */ + scic_controller_disable_interrupts(this_controller); + + /* Enable the port task scheduler */ + scic_sds_controller_enable_port_task_scheduler(this_controller); + + /* Assign all the task entries to this controller physical function */ + scic_sds_controller_assign_task_entries(this_controller); + + /* Now initialze the completion queue */ + scic_sds_controller_initialize_completion_queue(this_controller); + + /* Initialize the unsolicited frame queue for use */ + scic_sds_controller_initialize_unsolicited_frame_queue(this_controller); + } + + if (SCI_SUCCESS == result) { + scic_sds_controller_start_next_phy(this_controller); + + scic_cb_timer_start(this_controller, + this_controller->timeout_timer, + timeout); + + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(this_controller), + SCI_BASE_CONTROLLER_STATE_STARTING + ); + } + + return result; +} + +/* + * ***************************************************************************** + * * INITIALIZED STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @controller: This is struct scic_sds_controller which receives the link up + * notification. + * @port: This is struct scic_sds_port with which the phy is associated. + * @phy: This is the struct scic_sds_phy which has gone link up. + * + * This method is called when the struct scic_sds_controller is in the starting state + * link up handler is called. This method will perform the following: - Stop + * the phy timer - Start the next phy - Report the link up condition to the + * port object none + */ +static void scic_sds_controller_starting_state_link_up_handler( + struct scic_sds_controller *this_controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + scic_sds_controller_phy_timer_stop(this_controller); + + this_controller->port_agent.link_up_handler( + this_controller, &this_controller->port_agent, port, phy + ); + /* scic_sds_port_link_up(port, phy); */ + + scic_sds_controller_start_next_phy(this_controller); +} + +/** + * + * @controller: This is struct scic_sds_controller which receives the link down + * notification. + * @port: This is struct scic_sds_port with which the phy is associated. + * @phy: This is the struct scic_sds_phy which has gone link down. + * + * This method is called when the struct scic_sds_controller is in the starting state + * link down handler is called. - Report the link down condition to the port + * object none + */ +static void scic_sds_controller_starting_state_link_down_handler( + struct scic_sds_controller *this_controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + this_controller->port_agent.link_down_handler( + this_controller, &this_controller->port_agent, port, phy + ); + /* scic_sds_port_link_down(port, phy); */ +} + +/* + * ***************************************************************************** + * * READY STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @controller: The struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @timeout: The timeout for when the stop operation should report a failure. + * + * This method is called when the struct scic_sds_controller is in the ready state + * stop handler is called. - Start the timeout timer - Transition to + * SCI_BASE_CONTROLLER_STATE_STOPPING. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_controller_ready_state_stop_handler( + struct sci_base_controller *controller, + u32 timeout) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + scic_cb_timer_start(this_controller, + this_controller->timeout_timer, + timeout); + + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(this_controller), + SCI_BASE_CONTROLLER_STATE_STOPPING + ); + + return SCI_SUCCESS; +} + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device object. + * @io_request: This is the struct sci_base_request which is cast to a + * SCIC_SDS_IO_REQUEST object. + * @io_tag: This is the IO tag to be assigned to the IO request or + * SCI_CONTROLLER_INVALID_IO_TAG. + * + * This method is called when the struct scic_sds_controller is in the ready state and + * the start io handler is called. - Start the io request on the remote device + * - if successful - assign the io_request to the io_request_table - post the + * request to the hardware enum sci_status SCI_SUCCESS if the start io operation + * succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be + * allocated for the io request. SCI_FAILURE_INVALID_STATE if one or more + * objects are not in a valid state to accept io requests. How does the io_tag + * parameter get assigned to the io request? + */ +static enum sci_status scic_sds_controller_ready_state_start_io_handler( + struct sci_base_controller *controller, + struct sci_base_remote_device *remote_device, + struct sci_base_request *io_request, + u16 io_tag) +{ + enum sci_status status; + + struct scic_sds_controller *this_controller; + struct scic_sds_request *the_request; + struct scic_sds_remote_device *the_device; + + this_controller = (struct scic_sds_controller *)controller; + the_request = (struct scic_sds_request *)io_request; + the_device = (struct scic_sds_remote_device *)remote_device; + + status = scic_sds_remote_device_start_io(this_controller, the_device, the_request); + + if (status == SCI_SUCCESS) { + this_controller->io_request_table[ + scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + + scic_sds_controller_post_request( + this_controller, + scic_sds_request_get_post_context(the_request) + ); + } + + return status; +} + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device object. + * @io_request: This is the struct sci_base_request which is cast to a + * SCIC_SDS_IO_REQUEST object. + * + * This method is called when the struct scic_sds_controller is in the ready state and + * the complete io handler is called. - Complete the io request on the remote + * device - if successful - remove the io_request to the io_request_table + * enum sci_status SCI_SUCCESS if the start io operation succeeds + * SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid state to + * accept io requests. + */ +static enum sci_status scic_sds_controller_ready_state_complete_io_handler( + struct sci_base_controller *controller, + struct sci_base_remote_device *remote_device, + struct sci_base_request *io_request) +{ + u16 index; + enum sci_status status; + struct scic_sds_controller *this_controller; + struct scic_sds_request *the_request; + struct scic_sds_remote_device *the_device; + + this_controller = (struct scic_sds_controller *)controller; + the_request = (struct scic_sds_request *)io_request; + the_device = (struct scic_sds_remote_device *)remote_device; + + status = scic_sds_remote_device_complete_io( + this_controller, the_device, the_request); + + if (status == SCI_SUCCESS) { + index = scic_sds_io_tag_get_index(the_request->io_tag); + this_controller->io_request_table[index] = SCI_INVALID_HANDLE; + } + + return status; +} + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device object. + * @io_request: This is the struct sci_base_request which is cast to a + * SCIC_SDS_IO_REQUEST object. + * + * This method is called when the struct scic_sds_controller is in the ready state and + * the continue io handler is called. enum sci_status + */ +static enum sci_status scic_sds_controller_ready_state_continue_io_handler( + struct sci_base_controller *controller, + struct sci_base_remote_device *remote_device, + struct sci_base_request *io_request) +{ + struct scic_sds_controller *this_controller; + struct scic_sds_request *the_request; + + the_request = (struct scic_sds_request *)io_request; + this_controller = (struct scic_sds_controller *)controller; + + this_controller->io_request_table[ + scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + + scic_sds_controller_post_request( + this_controller, + scic_sds_request_get_post_context(the_request) + ); + + return SCI_SUCCESS; +} + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device object. + * @io_request: This is the struct sci_base_request which is cast to a + * SCIC_SDS_IO_REQUEST object. + * @task_tag: This is the task tag to be assigned to the task request or + * SCI_CONTROLLER_INVALID_IO_TAG. + * + * This method is called when the struct scic_sds_controller is in the ready state and + * the start task handler is called. - The remote device is requested to start + * the task request - if successful - assign the task to the io_request_table - + * post the request to the SCU hardware enum sci_status SCI_SUCCESS if the start io + * operation succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could + * not be allocated for the io request. SCI_FAILURE_INVALID_STATE if one or + * more objects are not in a valid state to accept io requests. How does the io + * tag get assigned in this code path? + */ +static enum sci_status scic_sds_controller_ready_state_start_task_handler( + struct sci_base_controller *controller, + struct sci_base_remote_device *remote_device, + struct sci_base_request *io_request, + u16 task_tag) +{ + struct scic_sds_controller *this_controller = (struct scic_sds_controller *) + controller; + struct scic_sds_request *the_request = (struct scic_sds_request *) + io_request; + struct scic_sds_remote_device *the_device = (struct scic_sds_remote_device *) + remote_device; + enum sci_status status; + + status = scic_sds_remote_device_start_task( + this_controller, the_device, the_request + ); + + if (status == SCI_SUCCESS) { + this_controller->io_request_table[ + scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + + scic_sds_controller_post_request( + this_controller, + scic_sds_request_get_post_context(the_request) + ); + } else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS) { + this_controller->io_request_table[ + scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + + /* + * We will let framework know this task request started successfully, + * although core is still woring on starting the request (to post tc when + * RNC is resumed.) */ + status = SCI_SUCCESS; + } + return status; +} + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device object. + * @io_request: This is the struct sci_base_request which is cast to a + * SCIC_SDS_IO_REQUEST object. + * + * This method is called when the struct scic_sds_controller is in the ready state and + * the terminate request handler is called. - call the io request terminate + * function - if successful - post the terminate request to the SCU hardware + * enum sci_status SCI_SUCCESS if the start io operation succeeds + * SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid state to + * accept io requests. + */ +static enum sci_status scic_sds_controller_ready_state_terminate_request_handler( + struct sci_base_controller *controller, + struct sci_base_remote_device *remote_device, + struct sci_base_request *io_request) +{ + struct scic_sds_controller *this_controller = (struct scic_sds_controller *) + controller; + struct scic_sds_request *the_request = (struct scic_sds_request *) + io_request; + enum sci_status status; + + status = scic_sds_io_request_terminate(the_request); + if (status == SCI_SUCCESS) { + /* + * Utilize the original post context command and or in the POST_TC_ABORT + * request sub-type. */ + scic_sds_controller_post_request( + this_controller, + scic_sds_request_get_post_context(the_request) + | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT + ); + } + + return status; +} + +/** + * + * @controller: This is struct scic_sds_controller which receives the link up + * notification. + * @port: This is struct scic_sds_port with which the phy is associated. + * @phy: This is the struct scic_sds_phy which has gone link up. + * + * This method is called when the struct scic_sds_controller is in the starting state + * link up handler is called. This method will perform the following: - Stop + * the phy timer - Start the next phy - Report the link up condition to the + * port object none + */ +static void scic_sds_controller_ready_state_link_up_handler( + struct scic_sds_controller *this_controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + this_controller->port_agent.link_up_handler( + this_controller, &this_controller->port_agent, port, phy + ); +} + +/** + * + * @controller: This is struct scic_sds_controller which receives the link down + * notification. + * @port: This is struct scic_sds_port with which the phy is associated. + * @phy: This is the struct scic_sds_phy which has gone link down. + * + * This method is called when the struct scic_sds_controller is in the starting state + * link down handler is called. - Report the link down condition to the port + * object none + */ +static void scic_sds_controller_ready_state_link_down_handler( + struct scic_sds_controller *this_controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + this_controller->port_agent.link_down_handler( + this_controller, &this_controller->port_agent, port, phy + ); +} + +/* + * ***************************************************************************** + * * STOPPING STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device object. + * @io_request: This is the struct sci_base_request which is cast to a + * SCIC_SDS_IO_REQUEST object. + * + * This method is called when the struct scic_sds_controller is in a stopping state + * and the complete io handler is called. - This function is not yet + * implemented enum sci_status SCI_FAILURE + */ +static enum sci_status scic_sds_controller_stopping_state_complete_io_handler( + struct sci_base_controller *controller, + struct sci_base_remote_device *remote_device, + struct sci_base_request *io_request) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)controller; + + /* / @todo Implement this function */ + return SCI_FAILURE; +} + +/** + * + * @controller: This is struct sci_base_controller object which is cast into a + * struct scic_sds_controller object. + * @remote_device: This is struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device object. + * @io_request: This is the struct sci_base_request which is cast to a + * SCIC_SDS_IO_REQUEST object. + * + * This method is called when the struct scic_sds_controller is in a stopping state + * and the complete task handler is called. - This function is not yet + * implemented enum sci_status SCI_FAILURE + */ + +/* + * ***************************************************************************** + * * STOPPED STATE HANDLERS + * ***************************************************************************** */ + +/* + * ***************************************************************************** + * * FAILED STATE HANDLERS + * ***************************************************************************** */ + +const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[] = { + [SCI_BASE_CONTROLLER_STATE_INITIAL] = { + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_default_request_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + }, + [SCI_BASE_CONTROLLER_STATE_RESET] = { + .base.initialize = scic_sds_controller_reset_state_initialize_handler, + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_default_request_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + }, + [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = { + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_default_request_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + }, + [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = { + .base.start = scic_sds_controller_initialized_state_start_handler, + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_default_request_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + }, + [SCI_BASE_CONTROLLER_STATE_STARTING] = { + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_default_request_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + .link_up = scic_sds_controller_starting_state_link_up_handler, + .link_down = scic_sds_controller_starting_state_link_down_handler + }, + [SCI_BASE_CONTROLLER_STATE_READY] = { + .base.stop = scic_sds_controller_ready_state_stop_handler, + .base.reset = scic_sds_controller_general_reset_handler, + .base.start_io = scic_sds_controller_ready_state_start_io_handler, + .base.complete_io = scic_sds_controller_ready_state_complete_io_handler, + .base.continue_io = scic_sds_controller_ready_state_continue_io_handler, + .base.start_task = scic_sds_controller_ready_state_start_task_handler, + .base.complete_task = scic_sds_controller_ready_state_complete_io_handler, + .terminate_request = scic_sds_controller_ready_state_terminate_request_handler, + .link_up = scic_sds_controller_ready_state_link_up_handler, + .link_down = scic_sds_controller_ready_state_link_down_handler + }, + [SCI_BASE_CONTROLLER_STATE_RESETTING] = { + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_default_request_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + }, + [SCI_BASE_CONTROLLER_STATE_STOPPING] = { + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_stopping_state_complete_io_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + }, + [SCI_BASE_CONTROLLER_STATE_STOPPED] = { + .base.reset = scic_sds_controller_general_reset_handler, + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_default_request_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + }, + [SCI_BASE_CONTROLLER_STATE_FAILED] = { + .base.reset = scic_sds_controller_general_reset_handler, + .base.start_io = scic_sds_controller_default_start_operation_handler, + .base.complete_io = scic_sds_controller_default_request_handler, + .base.continue_io = scic_sds_controller_default_request_handler, + .terminate_request = scic_sds_controller_default_request_handler, + }, +}; + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * object. + * + * This method implements the actions taken by the struct scic_sds_controller on entry + * to the SCI_BASE_CONTROLLER_STATE_INITIAL. - Set the state handlers to the + * controllers initial state. none This function should initialze the + * controller object. + */ +static void scic_sds_controller_initial_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)object; + + sci_base_state_machine_change_state( + &this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * object. + * + * This method implements the actions taken by the struct scic_sds_controller on exit + * from the SCI_BASE_CONTROLLER_STATE_STARTING. - This function stops the + * controller starting timeout timer. none + */ +static void scic_sds_controller_starting_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_controller *scic = (struct scic_sds_controller *)object; + + scic_cb_timer_stop(scic, scic->timeout_timer); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * object. + * + * This method implements the actions taken by the struct scic_sds_controller on entry + * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the + * controllers ready state. none + */ +static void scic_sds_controller_ready_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)object; + + /* set the default interrupt coalescence number and timeout value. */ + scic_controller_set_interrupt_coalescence( + this_controller, 0x10, 250); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * object. + * + * This method implements the actions taken by the struct scic_sds_controller on exit + * from the SCI_BASE_CONTROLLER_STATE_READY. - This function does nothing. none + */ +static void scic_sds_controller_ready_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)object; + + /* disable interrupt coalescence. */ + scic_controller_set_interrupt_coalescence(this_controller, 0, 0); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * object. + * + * This method implements the actions taken by the struct scic_sds_controller on entry + * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the + * controllers ready state. - Stop the phys on this controller - Stop the ports + * on this controller - Stop all of the remote devices on this controller none + */ +static void scic_sds_controller_stopping_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)object; + + /* Stop all of the components for this controller */ + scic_sds_controller_stop_phys(this_controller); + scic_sds_controller_stop_ports(this_controller); + scic_sds_controller_stop_devices(this_controller); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * object. + * + * This method implements the actions taken by the struct scic_sds_controller on exit + * from the SCI_BASE_CONTROLLER_STATE_STOPPING. - This function stops the + * controller stopping timeout timer. none + */ +static void scic_sds_controller_stopping_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)object; + + scic_cb_timer_stop(this_controller, this_controller->timeout_timer); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * object. + * + * This method implements the actions taken by the struct scic_sds_controller on entry + * to the SCI_BASE_CONTROLLER_STATE_RESETTING. - Set the state handlers to the + * controllers resetting state. - Write to the SCU hardware reset register to + * force a reset - Transition to the SCI_BASE_CONTROLLER_STATE_RESET none + */ +static void scic_sds_controller_resetting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_controller *this_controller; + + this_controller = (struct scic_sds_controller *)object; + + scic_sds_controller_reset_hardware(this_controller); + + sci_base_state_machine_change_state( + scic_sds_controller_get_base_state_machine(this_controller), + SCI_BASE_CONTROLLER_STATE_RESET + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_controller_state_table[] = { + [SCI_BASE_CONTROLLER_STATE_INITIAL] = { + .enter_state = scic_sds_controller_initial_state_enter, + }, + [SCI_BASE_CONTROLLER_STATE_RESET] = {}, + [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {}, + [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {}, + [SCI_BASE_CONTROLLER_STATE_STARTING] = { + .exit_state = scic_sds_controller_starting_state_exit, + }, + [SCI_BASE_CONTROLLER_STATE_READY] = { + .enter_state = scic_sds_controller_ready_state_enter, + .exit_state = scic_sds_controller_ready_state_exit, + }, + [SCI_BASE_CONTROLLER_STATE_RESETTING] = { + .enter_state = scic_sds_controller_resetting_state_enter, + }, + [SCI_BASE_CONTROLLER_STATE_STOPPING] = { + .enter_state = scic_sds_controller_stopping_state_enter, + .exit_state = scic_sds_controller_stopping_state_exit, + }, + [SCI_BASE_CONTROLLER_STATE_STOPPED] = {}, + [SCI_BASE_CONTROLLER_STATE_FAILED] = {} +}; + diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h new file mode 100644 index 000000000000..afa45f9874a4 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -0,0 +1,706 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_CONTROLLER_H_ +#define _SCIC_SDS_CONTROLLER_H_ + +/** + * This file contains the structures, constants and prototypes used for the + * core controller object. + * + * + */ + +#include "sci_pool.h" +#include "sci_controller_constants.h" +#include "sci_memory_descriptor_list.h" +#include "sci_base_controller.h" +#include "scic_config_parameters.h" +#include "scic_sds_port.h" +#include "scic_sds_phy.h" +#include "scic_sds_remote_node_table.h" +#include "scu_registers.h" +#include "scu_constants.h" +#include "scu_remote_node_context.h" +#include "scu_task_context.h" +#include "scu_unsolicited_frame.h" +#include "scic_sds_unsolicited_frame_control.h" +#include "scic_sds_port_configuration_agent.h" +#include "scic_sds_pci.h" + +struct scic_sds_remote_device; +struct scic_sds_request; +struct scic_sds_controller; + + +#define SCU_COMPLETION_RAM_ALIGNMENT (64) + +/** + * enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS - + * + * This enumeration depects the types of MDEs that are going to be created for + * the controller object. + */ +enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS { + /** + * Completion queue MDE entry + */ + SCU_MDE_COMPLETION_QUEUE, + + /** + * Remote node context MDE entry + */ + SCU_MDE_REMOTE_NODE_CONTEXT, + + /** + * Task context MDE entry + */ + SCU_MDE_TASK_CONTEXT, + + /** + * Unsolicited frame buffer MDE entrys this is the start of the unsolicited + * frame buffer entries. + */ + SCU_MDE_UF_BUFFER, + + SCU_MAX_MDES +}; + +/** + * + * + * Allowed PORT configuration modes APC Automatic PORT configuration mode is + * defined by the OEM configuration parameters providing no PHY_MASK parameters + * for any PORT. i.e. There are no phys assigned to any of the ports at start. + * MPC Manual PORT configuration mode is defined by the OEM configuration + * parameters providing a PHY_MASK value for any PORT. It is assumed that any + * PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned. + * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs + * being assigned is sufficient to declare manual PORT configuration. + */ +enum SCIC_PORT_CONFIGURATION_MODE { + SCIC_PORT_MANUAL_CONFIGURATION_MODE, + SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE +}; + +/** + * struct scic_power_control - + * + * This structure defines the fields for managing power control for direct + * attached disk devices. + */ +struct scic_power_control { + /** + * This field is set when the power control timer is running and cleared when + * it is not. + */ + bool timer_started; + + /** + * This field is the handle to the driver timer object. This timer is used to + * control when the directed attached disks can consume power. + */ + void *timer; + + /** + * This field is used to keep track of how many phys are put into the + * requesters field. + */ + u8 phys_waiting; + + /** + * This field is an array of phys that we are waiting on. The phys are direct + * mapped into requesters via struct scic_sds_phy.phy_index + */ + struct scic_sds_phy *requesters[SCI_MAX_PHYS]; + +}; + +/** + * struct scic_sds_controller - + * + * This structure represents the SCU contoller object. + */ +struct scic_sds_controller { + /** + * The struct sci_base_controller is the parent object for the struct scic_sds_controller + * object. + */ + struct sci_base_controller parent; + + /** + * This field is the driver timer object handler used to time the controller + * object start and stop requests. + */ + void *timeout_timer; + + /** + * This field contains the user parameters to be utilized for this + * core controller object. + */ + union scic_user_parameters user_parameters; + + /** + * This field contains the OEM parameters to be utilized for this + * core controller object. + */ + union scic_oem_parameters oem_parameters; + + /** + * This field contains the port configuration agent for this controller. + */ + struct scic_sds_port_configuration_agent port_agent; + + /** + * This field is the array of port objects that are controlled by this + * controller object. There is one dummy port object also contained within + * this controller object. + */ + struct scic_sds_port port_table[SCI_MAX_PORTS + 1]; + + /** + * This field is the array of phy objects that are controlled by this + * controller object. + */ + struct scic_sds_phy phy_table[SCI_MAX_PHYS]; + + /** + * This field is the array of device objects that are currently constructed + * for this controller object. This table is used as a fast lookup of device + * objects that need to handle device completion notifications from the + * hardware. The table is RNi based. + */ + struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; + + /** + * This field is the array of IO request objects that are currently active for + * this controller object. This table is used as a fast lookup of the io + * request object that need to handle completion queue notifications. The + * table is TCi based. + */ + struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS]; + + /** + * This field is the free RNi data structure + */ + struct scic_remote_node_table available_remote_nodes; + + /** + * This field is the TCi pool used to manage the task context index. + */ + SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS); + + /** + * This filed is the struct scic_power_control data used to controll when direct + * attached devices can consume power. + */ + struct scic_power_control power_control; + + /** + * This field is the array of sequence values for the IO Tag fields. Even + * though only 4 bits of the field is used for the sequence the sequence is 16 + * bits in size so the sequence can be bitwise or'd with the TCi to build the + * IO Tag value. + */ + u16 io_request_sequence[SCI_MAX_IO_REQUESTS]; + + /** + * This field in the array of sequence values for the RNi. These are used + * to control io request build to io request start operations. The sequence + * value is recorded into an io request when it is built and is checked on + * the io request start operation to make sure that there was not a device + * hot plug between the build and start operation. + */ + u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES]; + + /** + * This field is a pointer to the memory allocated by the driver for the task + * context table. This data is shared between the hardware and software. + */ + struct scu_task_context *task_context_table; + + /** + * This field is a pointer to the memory allocated by the driver for the + * remote node context table. This table is shared between the hardware and + * software. + */ + union scu_remote_node_context *remote_node_context_table; + + /** + * This field is the array of physical memory requiremets for this controller + * object. + */ + struct sci_physical_memory_descriptor memory_descriptors[SCU_MAX_MDES]; + + /** + * This field is a pointer to the completion queue. This memory is + * written to by the hardware and read by the software. + */ + u32 *completion_queue; + + /** + * This field is the software copy of the completion queue get pointer. The + * controller object writes this value to the hardware after processing the + * completion entries. + */ + u32 completion_queue_get; + + /** + * This field is the minimum of the number of hardware supported port entries + * and the software requested port entries. + */ + u32 logical_port_entries; + + /** + * This field is the minimum number of hardware supported completion queue + * entries and the software requested completion queue entries. + */ + u32 completion_queue_entries; + + /** + * This field is the minimum number of hardware supported event entries and + * the software requested event entries. + */ + u32 completion_event_entries; + + /** + * This field is the minimum number of devices supported by the hardware and + * the number of devices requested by the software. + */ + u32 remote_node_entries; + + /** + * This field is the minimum number of IO requests supported by the hardware + * and the number of IO requests requested by the software. + */ + u32 task_context_entries; + + /** + * This object contains all of the unsolicited frame specific + * data utilized by the core controller. + */ + struct scic_sds_unsolicited_frame_control uf_control; + + /** + * This field records the fact that the controller has encountered a fatal + * error and must be reset. + */ + bool encountered_fatal_error; + + /** + * This field specifies that the controller should ignore + * completion processing for non-fastpath events. This will + * cause the completions to be thrown away. + */ + bool restrict_completions; + + /* Phy Startup Data */ + /** + * This field is the driver timer handle for controller phy request startup. + * On controller start the controller will start each PHY individually in + * order of phy index. + */ + void *phy_startup_timer; + + /** + * This field is set when the phy_startup_timer is running and is cleared when + * the phy_startup_timer is stopped. + */ + bool phy_startup_timer_pending; + + /** + * This field is the index of the next phy start. It is initialized to 0 and + * increments for each phy index that is started. + */ + u32 next_phy_to_start; + + /** + * This field controlls the invalid link up notifications to the SCI_USER. If + * an invalid_link_up notification is reported a bit for the PHY index is set + * so further notifications are not made. Once the PHY object reports link up + * and is made part of a port then this bit for the PHY index is cleared. + */ + u8 invalid_phy_mask; + + /* + * This field saves the current interrupt coalescing number of the controller. + */ + u16 interrupt_coalesce_number; + + /* + * This field saves the current interrupt coalescing timeout value in microseconds. + */ + u32 interrupt_coalesce_timeout; + + /** + * This field is a pointer to the memory mapped register space for the + * struct smu_registers. + */ + struct smu_registers __iomem *smu_registers; + + /** + * This field is a pointer to the memory mapped register space for the + * struct scu_registers. + */ + struct scu_registers __iomem *scu_registers; + +}; + +typedef void (*scic_sds_controller_phy_handler_t)(struct scic_sds_controller *, + struct scic_sds_port *, + struct scic_sds_phy *); +/** + * struct scic_sds_controller_state_handler - + * + * This structure contains the SDS core specific definition for the state + * handlers. + */ +struct scic_sds_controller_state_handler { + struct sci_base_controller_state_handler base; + + sci_base_controller_request_handler_t terminate_request; + scic_sds_controller_phy_handler_t link_up; + scic_sds_controller_phy_handler_t link_down; +}; + +extern const struct scic_sds_controller_state_handler + scic_sds_controller_state_handler_table[]; +extern const struct sci_base_state scic_sds_controller_state_table[]; + +/** + * INCREMENT_QUEUE_GET() - + * + * This macro will increment the specified index to and if the index wraps to 0 + * it will toggel the cycle bit. + */ +#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \ + { \ + if ((index) + 1 == entry_count) { \ + (index) = 0; \ + (cycle) = (cycle) ^ (bit_toggle); \ + } else { \ + index = index + 1; \ + } \ + } + +/** + * scic_sds_controller_get_base_state_machine() - + * + * This is a helper macro that gets the base state machine for the controller + * object + */ +#define scic_sds_controller_get_base_state_machine(this_controller) \ + (&(this_controller)->parent.state_machine) + +/** + * scic_sds_controller_get_port_configuration_agent() - + * + * This is a helper macro to get the port configuration agent from the + * controller object. + */ +#define scic_sds_controller_get_port_configuration_agent(controller) \ + (&(controller)->port_agent) + +/** + * smu_register_write() - + * + * This macro writes to the smu_register for this controller + */ +#define smu_register_write(controller, reg, value) \ + scic_sds_pci_write_smu_dword((controller), &(reg), (value)) + +/** + * smu_register_read() - + * + * This macro reads the smu_register for this controller + */ +#define smu_register_read(controller, reg) \ + scic_sds_pci_read_smu_dword((controller), &(reg)) + +/** + * scu_register_write() - + * + * This mcaro writes the scu_register for this controller + */ +#define scu_register_write(controller, reg, value) \ + scic_sds_pci_write_scu_dword((controller), &(reg), (value)) + +/** + * scu_register_read() - + * + * This macro reads the scu_register for this controller + */ +#define scu_register_read(controller, reg) \ + scic_sds_pci_read_scu_dword((controller), &(reg)) + +/** + * scic_sds_controller_get_protocol_engine_group() - + * + * This macro returns the protocol engine group for this controller object. + * Presently we only support protocol engine group 0 so just return that + */ +#define scic_sds_controller_get_protocol_engine_group(controller) 0 + +/** + * scic_sds_io_tag_construct() - + * + * This macro constructs an IO tag from the sequence and index values. + */ +#define scic_sds_io_tag_construct(sequence, task_index) \ + ((sequence) << 12 | (task_index)) + +/** + * scic_sds_io_tag_get_sequence() - + * + * This macro returns the IO sequence from the IO tag value. + */ +#define scic_sds_io_tag_get_sequence(io_tag) \ + (((io_tag) & 0xF000) >> 12) + +/** + * scic_sds_io_tag_get_index() - + * + * This macro returns the TCi from the io tag value + */ +#define scic_sds_io_tag_get_index(io_tag) \ + ((io_tag) & 0x0FFF) + +/** + * scic_sds_io_sequence_increment() - + * + * This is a helper macro to increment the io sequence count. We may find in + * the future that it will be faster to store the sequence count in such a way + * as we dont perform the shift operation to build io tag values so therefore + * need a way to incrment them correctly + */ +#define scic_sds_io_sequence_increment(value) \ + ((value) = (((value) + 1) & 0x000F)) + +#define scic_sds_remote_device_node_count(device) \ + (\ + (\ + (device)->target_protocols.u.bits.attached_stp_target \ + && ((device)->is_direct_attached != true) \ + ) \ + ? SCU_STP_REMOTE_NODE_COUNT : SCU_SSP_REMOTE_NODE_COUNT \ + ) + +/** + * scic_sds_controller_set_invalid_phy() - + * + * This macro will set the bit in the invalid phy mask for this controller + * object. This is used to control messages reported for invalid link up + * notifications. + */ +#define scic_sds_controller_set_invalid_phy(controller, phy) \ + ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index)) + +/** + * scic_sds_controller_clear_invalid_phy() - + * + * This macro will clear the bit in the invalid phy mask for this controller + * object. This is used to control messages reported for invalid link up + * notifications. + */ +#define scic_sds_controller_clear_invalid_phy(controller, phy) \ + ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) + +/* --------------------------------------------------------------------------- */ + +u32 scic_sds_controller_get_object_size(void); + +/* --------------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------------- */ + +enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode( + struct scic_sds_controller *this_controller); + +/* --------------------------------------------------------------------------- */ + +void scic_sds_controller_post_request( + struct scic_sds_controller *this_controller, + u32 request); + +/* --------------------------------------------------------------------------- */ + +void scic_sds_controller_release_frame( + struct scic_sds_controller *this_controller, + u32 frame_index); + +void scic_sds_controller_copy_sata_response( + void *response_buffer, + void *frame_header, + void *frame_buffer); + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_sds_controller_allocate_remote_node_context( + struct scic_sds_controller *this_controller, + struct scic_sds_remote_device *the_device, + u16 *node_id); + +void scic_sds_controller_free_remote_node_context( + struct scic_sds_controller *this_controller, + struct scic_sds_remote_device *the_device, + u16 node_id); + +union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( + struct scic_sds_controller *this_controller, + u16 node_id); + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( + struct scic_sds_controller *this_controller, + u16 io_tag); + + +struct scu_task_context *scic_sds_controller_get_task_context_buffer( + struct scic_sds_controller *this_controller, + u16 io_tag); + +/* + * ***************************************************************************** + * * CORE CONTROLLER POWER CONTROL METHODS + * ***************************************************************************** */ + + +void scic_sds_controller_power_control_queue_insert( + struct scic_sds_controller *this_controller, + struct scic_sds_phy *the_phy); + +void scic_sds_controller_power_control_queue_remove( + struct scic_sds_controller *this_controller, + struct scic_sds_phy *the_phy); + +/* + * ***************************************************************************** + * * CORE CONTROLLER PHY MESSAGE PROCESSING + * ***************************************************************************** */ + +void scic_sds_controller_link_up( + struct scic_sds_controller *this_controller, + struct scic_sds_port *the_port, + struct scic_sds_phy *the_phy); + +void scic_sds_controller_link_down( + struct scic_sds_controller *this_controller, + struct scic_sds_port *the_port, + struct scic_sds_phy *the_phy); + +/* + * ***************************************************************************** + * * CORE CONTROLLER PRIVATE METHODS + * ***************************************************************************** */ + +enum sci_status scic_sds_controller_validate_memory_descriptor_table( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_ram_initialization( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_assign_task_entries( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_afe_initialization( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_enable_port_task_scheduler( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_initialize_completion_queue( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_initialize_unsolicited_frame_queue( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_phy_timer_stop( + struct scic_sds_controller *this_controller); + +enum sci_status scic_sds_controller_start_next_phy( + struct scic_sds_controller *this_controller); + +enum sci_status scic_sds_controller_stop_phys( + struct scic_sds_controller *this_controller); + +enum sci_status scic_sds_controller_stop_ports( + struct scic_sds_controller *this_controller); + +enum sci_status scic_sds_controller_stop_devices( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_copy_task_context( + struct scic_sds_controller *this_controller, + struct scic_sds_request *this_request); + +void scic_sds_controller_timeout_handler( + struct scic_sds_controller *controller); + +void scic_sds_controller_initialize_power_control( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_register_setup( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_reset_hardware( + struct scic_sds_controller *this_controller); + + +void scic_sds_controller_initialize_phy_startup( + struct scic_sds_controller *this_controller); + +#endif /* _SCIC_SDS_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_controller_registers.h b/drivers/scsi/isci/core/scic_sds_controller_registers.h new file mode 100644 index 000000000000..b7bec92ee59c --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_controller_registers.h @@ -0,0 +1,463 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_CONTROLLER_REGISTERS_H_ +#define _SCIC_SDS_CONTROLLER_REGISTERS_H_ + +/** + * This file contains macros used to perform the register reads/writes to the + * SCU hardware. + * + * + */ + +#include "scu_registers.h" +#include "scic_sds_controller.h" + +/** + * scic_sds_controller_smu_register_read() - + * + * SMU_REGISTER_ACCESS_MACROS + */ +#define scic_sds_controller_smu_register_read(controller, reg) \ + smu_register_read(\ + (controller), \ + (controller)->smu_registers->reg \ + ) + +#define scic_sds_controller_smu_register_write(controller, reg, value) \ + smu_register_write(\ + (controller), \ + (controller)->smu_registers->reg, \ + (value) \ + ) + +/** + * scu_afe_register_write() - + * + * AFE_REGISTER_ACCESS_MACROS + */ +#define scu_afe_register_write(controller, reg, value) \ + scu_register_write(\ + (controller), \ + (controller)->scu_registers->afe.reg, \ + (value) \ + ) + +#define scu_afe_txreg_write(controller, phy, reg, value) \ + scu_register_write(\ + (controller), \ + (controller)->scu_registers->afe.scu_afe_xcvr[phy].reg,\ + (value) \ + ) + +#define scu_afe_register_read(controller, reg) \ + scu_register_read(\ + (controller), \ + (controller)->scu_registers->afe.reg \ + ) + +/** + * scu_controller_viit_register_write() - + * + * VIIT_REGISTER_ACCESS_MACROS + */ +#define scu_controller_viit_register_write(controller, index, reg, value) \ + scu_register_write(\ + (controller), \ + (controller)->scu_registers->peg0.viit[index].reg, \ + value \ + ) + +/* + * ***************************************************************************** + * * SMU REGISTERS + * ***************************************************************************** */ + +/** + * SMU_PCP_WRITE() - + * + * struct smu_registers + */ +#define SMU_PCP_WRITE(controller, value) \ + scic_sds_controller_smu_register_write(\ + controller, post_context_port, value \ + ) + +#define SMU_TCR_READ(controller, value) \ + scic_sds_controller_smu_register_read(\ + controller, task_context_range \ + ) + +#define SMU_TCR_WRITE(controller, value) \ + scic_sds_controller_smu_register_write(\ + controller, task_context_range, value \ + ) + +#define SMU_HTTBAR_WRITE(controller, address) \ + { \ + scic_sds_controller_smu_register_write(\ + controller, \ + host_task_table_lower, \ + lower_32_bits(address) \ + ); \ + scic_sds_controller_smu_register_write(\ + controller, \ + host_task_table_upper, \ + upper_32_bits(address) \ + ); \ + } + +#define SMU_CQBAR_WRITE(controller, address) \ + { \ + scic_sds_controller_smu_register_write(\ + controller, \ + completion_queue_lower, \ + lower_32_bits(address) \ + ); \ + scic_sds_controller_smu_register_write(\ + controller, \ + completion_queue_upper, \ + upper_32_bits(address) \ + ); \ + } + +#define SMU_CQGR_WRITE(controller, value) \ + scic_sds_controller_smu_register_write(\ + controller, completion_queue_get, value \ + ) + +#define SMU_CQGR_READ(controller, value) \ + scic_sds_controller_smu_register_read(\ + controller, completion_queue_get \ + ) + +#define SMU_CQPR_WRITE(controller, value) \ + scic_sds_controller_smu_register_write(\ + controller, completion_queue_put, value \ + ) + +#define SMU_RNCBAR_WRITE(controller, address) \ + { \ + scic_sds_controller_smu_register_write(\ + controller, \ + remote_node_context_lower, \ + lower_32_bits(address) \ + ); \ + scic_sds_controller_smu_register_write(\ + controller, \ + remote_node_context_upper, \ + upper_32_bits(address) \ + ); \ + } + +#define SMU_AMR_READ(controller) \ + scic_sds_controller_smu_register_read(\ + controller, address_modifier \ + ) + +#define SMU_IMR_READ(controller) \ + scic_sds_controller_smu_register_read(\ + controller, interrupt_mask \ + ) + +#define SMU_IMR_WRITE(controller, mask) \ + scic_sds_controller_smu_register_write(\ + controller, interrupt_mask, mask \ + ) + +#define SMU_ISR_READ(controller) \ + scic_sds_controller_smu_register_read(\ + controller, interrupt_status \ + ) + +#define SMU_ISR_WRITE(controller, status) \ + scic_sds_controller_smu_register_write(\ + controller, interrupt_status, status \ + ) + +#define SMU_ICC_READ(controller) \ + scic_sds_controller_smu_register_read(\ + controller, interrupt_coalesce_control \ + ) + +#define SMU_ICC_WRITE(controller, value) \ + scic_sds_controller_smu_register_write(\ + controller, interrupt_coalesce_control, value \ + ) + +#define SMU_CQC_WRITE(controller, value) \ + scic_sds_controller_smu_register_write(\ + controller, completion_queue_control, value \ + ) + +#define SMU_SMUSRCR_WRITE(controller, value) \ + scic_sds_controller_smu_register_write(\ + controller, soft_reset_control, value \ + ) + +#define SMU_TCA_WRITE(controller, index, value) \ + scic_sds_controller_smu_register_write(\ + controller, task_context_assignment[index], value \ + ) + +#define SMU_TCA_READ(controller, index) \ + scic_sds_controller_smu_register_read(\ + controller, task_context_assignment[index] \ + ) + +#define SMU_DCC_READ(controller) \ + scic_sds_controller_smu_register_read(\ + controller, device_context_capacity \ + ) + +#define SMU_DFC_READ(controller) \ + scic_sds_controller_smu_register_read(\ + controller, device_function_capacity \ + ) + +#define SMU_SMUCSR_READ(controller) \ + scic_sds_controller_smu_register_read(\ + controller, control_status \ + ) + +#define SMU_CQPR_READ(controller) \ + scic_sds_controller_smu_register_read(\ + controller, completion_queue_put \ + ) + + +/** + * scic_sds_controller_scu_register_read() - + * + * SCU_REGISTER_ACCESS_MACROS + */ +#define scic_sds_controller_scu_register_read(controller, reg) \ + scu_register_read(\ + (controller), \ + (controller)->scu_registers->reg \ + ) + +#define scic_sds_controller_scu_register_write(controller, reg, value) \ + scu_register_write(\ + (controller), \ + (controller)->scu_registers->reg, \ + (value) \ + ) + + +/* + * **************************************************************************** + * * SCU SDMA REGISTERS + * **************************************************************************** */ + +/** + * scu_sdma_register_read() - + * + * SCU_SDMA_REGISTER_ACCESS_MACROS + */ +#define scu_sdma_register_read(controller, reg) \ + scu_register_read(\ + (controller), \ + (controller)->scu_registers->sdma.reg \ + ) + +#define scu_sdma_register_write(controller, reg, value) \ + scu_register_write(\ + (controller), \ + (controller)->scu_registers->sdma.reg, \ + (value) \ + ) + +/** + * SCU_PUFATHAR_WRITE() - + * + * struct scu_sdma_registers + */ +#define SCU_PUFATHAR_WRITE(controller, address) \ + { \ + scu_sdma_register_write(\ + controller, \ + uf_address_table_lower, \ + lower_32_bits(address) \ + ); \ + scu_sdma_register_write(\ + controller, \ + uf_address_table_upper, \ + upper_32_bits(address) \ + ); \ + } + +#define SCU_UFHBAR_WRITE(controller, address) \ + { \ + scu_sdma_register_write(\ + controller, \ + uf_header_base_address_lower, \ + lower_32_bits(address) \ + ); \ + scu_sdma_register_write(\ + controller, \ + uf_header_base_address_upper, \ + upper_32_bits(address) \ + ); \ + } + +#define SCU_UFQC_READ(controller) \ + scu_sdma_register_read(\ + controller, \ + unsolicited_frame_queue_control \ + ) + +#define SCU_UFQC_WRITE(controller, value) \ + scu_sdma_register_write(\ + controller, \ + unsolicited_frame_queue_control, \ + value \ + ) + +#define SCU_UFQPP_READ(controller) \ + scu_sdma_register_read(\ + controller, \ + unsolicited_frame_put_pointer \ + ) + +#define SCU_UFQPP_WRITE(controller, value) \ + scu_sdma_register_write(\ + controller, \ + unsolicited_frame_put_pointer, \ + value \ + ) + +#define SCU_UFQGP_WRITE(controller, value) \ + scu_sdma_register_write(\ + controller, \ + unsolicited_frame_get_pointer, \ + value \ + ) + +#define SCU_PDMACR_READ(controller) \ + scu_sdma_register_read(\ + controller, \ + pdma_configuration \ + ) + +#define SCU_PDMACR_WRITE(controller, value) \ + scu_sdma_register_write(\ + controller, \ + pdma_configuration, \ + value \ + ) + +#define SCU_CDMACR_READ(controller) \ + scu_sdma_register_read(\ + controller, \ + cdma_configuration \ + ) + +#define SCU_CDMACR_WRITE(controller, value) \ + scu_sdma_register_write(\ + controller, \ + cdma_configuration, \ + value \ + ) + +/* + * ***************************************************************************** + * * SCU Port Task Scheduler Group Registers + * ***************************************************************************** */ + +/** + * scu_ptsg_register_read() - + * + * SCU_PTSG_REGISTER_ACCESS_MACROS + */ +#define scu_ptsg_register_read(controller, reg) \ + scu_register_read(\ + (controller), \ + (controller)->scu_registers->peg0.ptsg.reg \ + ) + +#define scu_ptsg_register_write(controller, reg, value) \ + scu_register_write(\ + (controller), \ + (controller)->scu_registers->peg0.ptsg.reg, \ + (value) \ + ) + +/** + * SCU_PTSGCR_READ() - + * + * SCU_PTSG_REGISTERS + */ +#define SCU_PTSGCR_READ(controller) \ + scu_ptsg_register_read(\ + (controller), \ + control \ + ) + +#define SCU_PTSGCR_WRITE(controller, value) \ + scu_ptsg_register_write(\ + (controller), \ + control, \ + value \ + ) + +#define SCU_PTSGRTC_READ(controller) \ + scu_ptsg_register_read(\ + contoller, \ + real_time_clock \ + ) + +#endif /* _SCIC_SDS_CONTROLLER_REGISTERS_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_pci.h b/drivers/scsi/isci/core/scic_sds_pci.h new file mode 100644 index 000000000000..21326777acc6 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_pci.h @@ -0,0 +1,95 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_PCI_H_ +#define _SCIC_SDS_PCI_H_ + +/** + * This file contains the prototypes/macros utilized in writing out PCI data + * for the SCI core. + * + * + */ + +#include +#include "sci_types.h" + +struct scic_sds_controller; + +void scic_sds_pci_bar_initialization(struct scic_sds_controller *scic); + +/* for debug we separate scu and smu accesses and require a controller */ +static inline u32 scic_sds_pci_read_smu_dword(struct scic_sds_controller *scic, void __iomem *addr) +{ + return readl(addr); +} + +static inline void scic_sds_pci_write_smu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value) +{ + writel(value, addr); +} + +static inline u32 scic_sds_pci_read_scu_dword(struct scic_sds_controller *scic, void __iomem *addr) +{ + return readl(addr); +} + +static inline void scic_sds_pci_write_scu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value) +{ + writel(value, addr); +} + + +#endif /* _SCIC_SDS_PCI_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c new file mode 100644 index 000000000000..7d012b571b5b --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -0,0 +1,2807 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "intel_ata.h" +#include "intel_sata.h" +#include "sci_base_state.h" +#include "sci_base_state_machine.h" +#include "scic_phy.h" +#include "scic_sds_controller.h" +#include "scic_sds_phy.h" +#include "scic_sds_phy_registers.h" +#include "scic_sds_port.h" +#include "scic_user_callback.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_event_codes.h" + +#define SCIC_SDS_PHY_MIN_TIMER_COUNT (SCI_MAX_PHYS) +#define SCIC_SDS_PHY_MAX_TIMER_COUNT (SCI_MAX_PHYS) + +/* Maximum arbitration wait time in micro-seconds */ +#define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) + +/* + * ***************************************************************************** + * * SCIC SDS PHY Internal Methods + * ***************************************************************************** */ + +/** + * This method will initialize the phy link layer registers + * @this_phy: + * @link_layer_registers: + * + * enum sci_status + */ +static enum sci_status scic_sds_phy_link_layer_initialization( + struct scic_sds_phy *this_phy, + struct scu_link_layer_registers *link_layer_registers) +{ + u32 phy_configuration; + struct sas_capabilities phy_capabilities; + u32 parity_check = 0; + u32 parity_count = 0; + u32 link_layer_control; + + this_phy->link_layer_registers = link_layer_registers; + + /* Set our IDENTIFY frame data */ + #define SCI_END_DEVICE 0x01 + + SCU_SAS_TIID_WRITE( + this_phy, + (SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) + | SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) + | SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) + | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) + | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE)) + ); + + /* Write the device SAS Address */ + SCU_SAS_TIDNH_WRITE(this_phy, 0xFEDCBA98); + SCU_SAS_TIDNL_WRITE(this_phy, this_phy->phy_index); + + /* Write the source SAS Address */ + SCU_SAS_TISSAH_WRITE( + this_phy, + this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[ + this_phy->phy_index].sas_address.high + ); + SCU_SAS_TISSAL_WRITE( + this_phy, + this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[ + this_phy->phy_index].sas_address.low + ); + + /* Clear and Set the PHY Identifier */ + SCU_SAS_TIPID_WRITE(this_phy, 0x00000000); + SCU_SAS_TIPID_WRITE(this_phy, SCU_SAS_TIPID_GEN_VALUE(ID, this_phy->phy_index)); + + /* Change the initial state of the phy configuration register */ + phy_configuration = SCU_SAS_PCFG_READ(this_phy); + + /* Hold OOB state machine in reset */ + phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + SCU_SAS_PCFG_WRITE(this_phy, phy_configuration); + + /* Configure the SNW capabilities */ + phy_capabilities.u.all = 0; + phy_capabilities.u.bits.start = 1; + phy_capabilities.u.bits.gen3_without_ssc_supported = 1; + phy_capabilities.u.bits.gen2_without_ssc_supported = 1; + phy_capabilities.u.bits.gen1_without_ssc_supported = 1; + if (this_phy->owning_port->owning_controller->oem_parameters.sds1. + controller.do_enable_ssc == true) { + phy_capabilities.u.bits.gen3_with_ssc_supported = 1; + phy_capabilities.u.bits.gen2_with_ssc_supported = 1; + phy_capabilities.u.bits.gen1_with_ssc_supported = 1; + } + + /* + * The SAS specification indicates that the phy_capabilities that + * are transmitted shall have an even parity. Calculate the parity. */ + parity_check = phy_capabilities.u.all; + while (parity_check != 0) { + if (parity_check & 0x1) + parity_count++; + parity_check >>= 1; + } + + /* + * If parity indicates there are an odd number of bits set, then + * set the parity bit to 1 in the phy capabilities. */ + if ((parity_count % 2) != 0) + phy_capabilities.u.bits.parity = 1; + + SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all); + + /* Set the enable spinup period but disable the ability to send notify enable spinup */ + SCU_SAS_ENSPINUP_WRITE(this_phy, SCU_ENSPINUP_GEN_VAL(COUNT, 0x33)); + +#if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) || defined(CONFIG_PBG_HBA_BETA) + /* / @todo Provide a way to write this register correctly */ + scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421); +#else + /* / @todo Provide a way to write this register correctly */ + scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x0e739ce7); +#endif + + link_layer_control = SCU_SAS_LLCTL_GEN_VAL( + NO_OUTBOUND_TASK_TIMEOUT, + (u8)this_phy->owning_port->owning_controller-> + user_parameters.sds1.no_outbound_task_timeout + ); + +/* #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 */ +/* #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 */ +#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3 + + if (this_phy->owning_port->owning_controller->user_parameters.sds1. + phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED) { + link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( + MAX_LINK_RATE, COMPILED_MAX_LINK_RATE + ); + } else if (this_phy->owning_port->owning_controller->user_parameters.sds1. + phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED) { + link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( + MAX_LINK_RATE, + min( + SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2, + COMPILED_MAX_LINK_RATE) + ); + } else { + link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( + MAX_LINK_RATE, + min( + SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1, + COMPILED_MAX_LINK_RATE) + ); + } + + scu_link_layer_register_write( + this_phy, link_layer_control, link_layer_control + ); + + /* + * Program the max ARB time for the PHY to 700us so we inter-operate with + * the PMC expander which shuts down PHYs if the expander PHY generates too + * many breaks. This time value will guarantee that the initiator PHY will + * generate the break. */ +#if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) + scu_link_layer_register_write( + this_phy, + maximum_arbitration_wait_timer_timeout, + SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME + ); +#endif /* defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) */ + + /* + * Set the link layer hang detection to 500ms (0x1F4) from its default + * value of 128ms. Max value is 511 ms. */ + scu_link_layer_register_write( + this_phy, link_layer_hang_detection_timeout, 0x1F4 + ); + + /* We can exit the initial state to the stopped state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_STOPPED + ); + + return SCI_SUCCESS; +} + +/** + * This function will handle the sata SIGNATURE FIS timeout condition. It will + * restart the starting substate machine since we dont know what has actually + * happening. + */ +static void scic_sds_phy_sata_timeout(void *phy) +{ + struct scic_sds_phy *sci_phy = phy; + + dev_dbg(sciphy_to_dev(sci_phy), + "%s: SCIC SDS Phy 0x%p did not receive signature fis before " + "timeout.\n", + __func__, + sci_phy); + + sci_base_state_machine_stop( + scic_sds_phy_get_starting_substate_machine(sci_phy)); + + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(sci_phy), + SCI_BASE_PHY_STATE_STARTING + ); +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY External Methods + * ***************************************************************************** */ + +/** + * This method returns the object size for a phy object. + * + * u32 + */ + +/** + * This method returns the minimum number of timers required for a phy object. + * + * u32 + */ + +/** + * This method returns the maximum number of timers required for a phy object. + * + * u32 + */ + +#ifdef SCIC_DEBUG_ENABLED +/** + * scic_sds_phy_observe_state_change() - + * @our_observer: + * + * Debug code to record the state transitions in the phy + */ +void scic_sds_phy_observe_state_change( + struct sci_base_observer *our_observer, + struct sci_base_subject *the_subject) +{ + struct scic_sds_phy *this_phy; + struct sci_base_state_machine *the_state_machine; + + u8 transition_requestor; + u32 base_state_id; + u32 starting_substate_id; + + the_state_machine = (struct sci_base_state_machine *)the_subject; + this_phy = (struct scic_sds_phy *)the_state_machine->state_machine_owner; + + if (the_state_machine == &this_phy->parent.state_machine) { + transition_requestor = 0x01; + } else if (the_state_machine == &this_phy->starting_substate_machine) { + transition_requestor = 0x02; + } else { + transition_requestor = 0xFF; + } + + base_state_id = + sci_base_state_machine_get_state(&this_phy->parent.state_machine); + starting_substate_id = + sci_base_state_machine_get_state(&this_phy->starting_substate_machine); + + this_phy->state_record.state_transition_table[ + this_phy->state_record.index++] = ((transition_requestor << 24) + | ((u8)base_state_id << 8) + | ((u8)starting_substate_id)); + + this_phy->state_record.index = + this_phy->state_record.index & (MAX_STATE_TRANSITION_RECORD - 1); + +} +#endif /* SCIC_DEBUG_ENABLED */ + +#ifdef SCIC_DEBUG_ENABLED +/** + * scic_sds_phy_initialize_state_recording() - + * + * This method initializes the state record debug information for the phy + * object. The state machines for the phy object must be constructed before + * this function is called. + */ +void scic_sds_phy_initialize_state_recording( + struct scic_sds_phy *this_phy) +{ + this_phy->state_record.index = 0; + + sci_base_observer_initialize( + &this_phy->state_record.base_state_observer, + scic_sds_phy_observe_state_change, + &this_phy->parent.state_machine.parent + ); + + sci_base_observer_initialize( + &this_phy->state_record.starting_state_observer, + scic_sds_phy_observe_state_change, + &this_phy->starting_substate_machine.parent + ); +} +#endif /* SCIC_DEBUG_ENABLED */ + +/** + * This method will construct the struct scic_sds_phy object + * @this_phy: + * @owning_port: + * @phy_index: + * + */ +void scic_sds_phy_construct( + struct scic_sds_phy *this_phy, + struct scic_sds_port *owning_port, + u8 phy_index) +{ + /* + * Call the base constructor first + */ + sci_base_phy_construct( + &this_phy->parent, + scic_sds_phy_state_table + ); + + /* Copy the rest of the input data to our locals */ + this_phy->owning_port = owning_port; + this_phy->phy_index = phy_index; + this_phy->bcn_received_while_port_unassigned = false; + this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; + this_phy->link_layer_registers = NULL; + this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; + + /* Clear out the identification buffer data */ + memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type)); + + /* Initialize the the substate machines */ + sci_base_state_machine_construct( + &this_phy->starting_substate_machine, + &this_phy->parent.parent, + scic_sds_phy_starting_substates, + SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL + ); + + #ifdef SCIC_DEBUG_ENABLED + scic_sds_phy_initialize_state_recording(this_phy); + #endif /* SCIC_DEBUG_ENABLED */ +} + +/** + * This method returns the port currently containing this phy. If the phy is + * currently contained by the dummy port, then the phy is considered to not + * be part of a port. + * @this_phy: This parameter specifies the phy for which to retrieve the + * containing port. + * + * This method returns a handle to a port that contains the supplied phy. + * SCI_INVALID_HANDLE This value is returned if the phy is not part of a real + * port (i.e. it's contained in the dummy port). !SCI_INVALID_HANDLE All other + * values indicate a handle/pointer to the port containing the phy. + */ +struct scic_sds_port *scic_sds_phy_get_port( + struct scic_sds_phy *this_phy) +{ + if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT) + return SCI_INVALID_HANDLE; + + return this_phy->owning_port; +} + +/** + * This method will assign a port to the phy object. + * @out]: this_phy This parameter specifies the phy for which to assign a port + * object. + * + * + */ +void scic_sds_phy_set_port( + struct scic_sds_phy *this_phy, + struct scic_sds_port *the_port) +{ + this_phy->owning_port = the_port; + + if (this_phy->bcn_received_while_port_unassigned) { + this_phy->bcn_received_while_port_unassigned = false; + scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); + } +} + +/** + * This method will initialize the constructed phy + * @sci_phy: + * @link_layer_registers: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_initialize( + struct scic_sds_phy *sci_phy, + struct scu_link_layer_registers *link_layer_registers) +{ + /* Create the SIGNATURE FIS Timeout timer for this phy */ + sci_phy->sata_timeout_timer = scic_cb_timer_create( + scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_sata_timeout, + sci_phy + ); + + /* Perofrm the initialization of the PE hardware */ + scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers); + + /* + * There is nothing that needs to be done in this state just + * transition to the stopped state. */ + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(sci_phy), + SCI_BASE_PHY_STATE_STOPPED + ); + + return SCI_SUCCESS; +} + + +/** + * + * @this_phy: The phy object to be suspended. + * + * This function will perform the register reads/writes to suspend the SCU + * hardware protocol engine. none + */ +void scic_sds_phy_suspend( + struct scic_sds_phy *this_phy) +{ + u32 scu_sas_pcfg_value; + + scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); + + SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); +} + +/** + * + * @this_phy: The phy object to resume. + * + * This function will perform the register reads/writes required to resume the + * SCU hardware protocol engine. none + */ +void scic_sds_phy_resume( + struct scic_sds_phy *this_phy) +{ + u32 scu_sas_pcfg_value; + + scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + + scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); + + SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); +} + +/** + * This method returns the local sas address assigned to this phy. + * @this_phy: This parameter specifies the phy for which to retrieve the local + * SAS address. + * @sas_address: This parameter specifies the location into which to copy the + * local SAS address. + * + */ +void scic_sds_phy_get_sas_address( + struct scic_sds_phy *this_phy, + struct sci_sas_address *sas_address) +{ + sas_address->high = SCU_SAS_TISSAH_READ(this_phy); + sas_address->low = SCU_SAS_TISSAL_READ(this_phy); +} + +/** + * This method returns the remote end-point (i.e. attached) sas address + * assigned to this phy. + * @this_phy: This parameter specifies the phy for which to retrieve the remote + * end-point SAS address. + * @sas_address: This parameter specifies the location into which to copy the + * remote end-point SAS address. + * + */ +void scic_sds_phy_get_attached_sas_address( + struct scic_sds_phy *this_phy, + struct sci_sas_address *sas_address) +{ + sas_address->high + = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high; + sas_address->low + = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low; +} + +/** + * This method returns the supported protocols assigned to this phy + * @this_phy: + * + * + */ +void scic_sds_phy_get_protocols( + struct scic_sds_phy *this_phy, + struct sci_sas_identify_address_frame_protocols *protocols) +{ + protocols->u.all = (u16)(SCU_SAS_TIID_READ(this_phy) & 0x0000FFFF); +} + +/** + * + * @this_phy: The parameter is the phy object for which the attached phy + * protcols are to be returned. + * + * This method returns the supported protocols for the attached phy. If this + * is a SAS phy the protocols are returned from the identify address frame. If + * this is a SATA phy then protocols are made up and the target phy is an STP + * target phy. The caller will get the entire set of bits for the protocol + * value. + */ +void scic_sds_phy_get_attached_phy_protocols( + struct scic_sds_phy *this_phy, + struct sci_sas_identify_address_frame_protocols *protocols) +{ + protocols->u.all = 0; + + if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + protocols->u.all = + this_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all; + } else if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { + protocols->u.bits.stp_target = 1; + } +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY Handler Redirects + * ***************************************************************************** */ + +/** + * This method will attempt to start the phy object. This request is only valid + * when the phy is in the stopped state + * @this_phy: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_start( + struct scic_sds_phy *this_phy) +{ + return this_phy->state_handlers->parent.start_handler(&this_phy->parent); +} + +/** + * This method will attempt to stop the phy object. + * @this_phy: + * + * enum sci_status SCI_SUCCESS if the phy is going to stop SCI_INVALID_STATE if the + * phy is not in a valid state to stop + */ +enum sci_status scic_sds_phy_stop( + struct scic_sds_phy *this_phy) +{ + return this_phy->state_handlers->parent.stop_handler(&this_phy->parent); +} + +/** + * This method will attempt to reset the phy. This request is only valid when + * the phy is in an ready state + * @this_phy: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_reset( + struct scic_sds_phy *this_phy) +{ + return this_phy->state_handlers->parent.reset_handler( + &this_phy->parent + ); +} + +/** + * This method will process the event code received. + * @this_phy: + * @event_code: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + return this_phy->state_handlers->event_handler(this_phy, event_code); +} + +/** + * This method will process the frame index received. + * @this_phy: + * @frame_index: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_frame_handler( + struct scic_sds_phy *this_phy, + u32 frame_index) +{ + return this_phy->state_handlers->frame_handler(this_phy, frame_index); +} + +/** + * This method will give the phy permission to consume power + * @this_phy: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_consume_power_handler( + struct scic_sds_phy *this_phy) +{ + return this_phy->state_handlers->consume_power_handler(this_phy); +} + +/* + * ***************************************************************************** + * * SCIC PHY Public Methods + * ***************************************************************************** */ + + +enum sci_status scic_sas_phy_get_properties( + struct scic_sds_phy *sci_phy, + struct scic_sas_phy_properties *properties) +{ + if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + memcpy( + &properties->received_iaf, + &sci_phy->phy_type.sas.identify_address_frame_buffer, + sizeof(struct sci_sas_identify_address_frame) + ); + + properties->received_capabilities.u.all + = SCU_SAS_RECPHYCAP_READ(sci_phy); + + return SCI_SUCCESS; + } + + return SCI_FAILURE; +} + + +enum sci_status scic_sata_phy_get_properties( + struct scic_sds_phy *sci_phy, + struct scic_sata_phy_properties *properties) +{ + if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { + memcpy( + &properties->signature_fis, + &sci_phy->phy_type.sata.signature_fis_buffer, + sizeof(struct sata_fis_reg_d2h) + ); + + /* / @todo add support for port selectors. */ + properties->is_port_selector_present = false; + + return SCI_SUCCESS; + } + + return SCI_FAILURE; +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY HELPER FUNCTIONS + * ***************************************************************************** */ + + +/** + * + * @this_phy: The phy object that received SAS PHY DETECTED. + * + * This method continues the link training for the phy as if it were a SAS PHY + * instead of a SATA PHY. This is done because the completion queue had a SAS + * PHY DETECTED event when the state machine was expecting a SATA PHY event. + * none + */ +static void scic_sds_phy_start_sas_link_training( + struct scic_sds_phy *this_phy) +{ + u32 phy_control; + + phy_control = SCU_SAS_PCFG_READ(this_phy); + phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); + SCU_SAS_PCFG_WRITE(this_phy, phy_control); + + sci_base_state_machine_change_state( + &this_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN + ); + + this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; +} + +/** + * + * @this_phy: The phy object that received a SATA SPINUP HOLD event + * + * This method continues the link training for the phy as if it were a SATA PHY + * instead of a SAS PHY. This is done because the completion queue had a SATA + * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none + */ +static void scic_sds_phy_start_sata_link_training( + struct scic_sds_phy *this_phy) +{ + sci_base_state_machine_change_state( + &this_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER + ); + + this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; +} + +/** + * This method performs processing common to all protocols upon completion of + * link training. + * @this_phy: This parameter specifies the phy object for which link training + * has completed. + * @max_link_rate: This parameter specifies the maximum link rate to be + * associated with this phy. + * @next_state: This parameter specifies the next state for the phy's starting + * sub-state machine. + * + */ +static void scic_sds_phy_complete_link_training( + struct scic_sds_phy *this_phy, + enum sci_sas_link_rate max_link_rate, + u32 next_state) +{ + this_phy->max_negotiated_speed = max_link_rate; + + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), next_state + ); +} + +/** + * + * @this_phy: The struct scic_sds_phy object to restart. + * + * This method restarts the struct scic_sds_phy objects base state machine in the + * starting state from any starting substate. none + */ +static void scic_sds_phy_restart_starting_state( + struct scic_sds_phy *this_phy) +{ + /* Stop the current substate machine */ + sci_base_state_machine_stop( + scic_sds_phy_get_starting_substate_machine(this_phy) + ); + + /* Re-enter the base state machine starting state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_STARTING + ); +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY EVENT_HANDLERS + * ***************************************************************************** */ + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - + * decode the event - sas phy detected causes a state transition to the wait + * for speed event notification. - any other events log a warning message and + * set a failure status enum sci_status SCI_SUCCESS on any valid event notification + * SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + scic_sds_phy_start_sas_link_training(this_phy); + this_phy->is_in_link_training = true; + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + scic_sds_phy_start_sata_link_training(this_phy); + this_phy->is_in_link_training = true; + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - + * decode the event - sas phy detected returns us back to this state. - speed + * event detected causes a state transition to the wait for iaf. - identify + * timeout is an un-expected event and the state machine is restarted. - link + * failure events restart the starting state machine - any other events log a + * warning message and set a failure status enum sci_status SCI_SUCCESS on any valid + * event notification SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * Why is this being reported again by the controller? + * We would re-enter this state so just stay here */ + break; + + case SCU_EVENT_SAS_15: + case SCU_EVENT_SAS_15_SSC: + scic_sds_phy_complete_link_training( + this_phy, SCI_SAS_150_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + ); + break; + + case SCU_EVENT_SAS_30: + case SCU_EVENT_SAS_30_SSC: + scic_sds_phy_complete_link_training( + this_phy, SCI_SAS_300_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + ); + break; + + case SCU_EVENT_SAS_60: + case SCU_EVENT_SAS_60_SSC: + scic_sds_phy_complete_link_training( + this_phy, SCI_SAS_600_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + ); + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + /* + * We were doing SAS PHY link training and received a SATA PHY event + * continue OOB/SN as if this were a SATA PHY */ + scic_sds_phy_start_sata_link_training(this_phy); + break; + + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(this_phy); + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - + * decode the event - sas phy detected event backs up the state machine to the + * await speed notification. - identify timeout is an un-expected event and the + * state machine is restarted. - link failure events restart the starting state + * machine - any other events log a warning message and set a failure status + * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any + * unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + /* Backup the state machine */ + scic_sds_phy_start_sas_link_training(this_phy); + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + /* + * We were doing SAS PHY link training and received a SATA PHY event + * continue OOB/SN as if this were a SATA PHY */ + scic_sds_phy_start_sata_link_training(this_phy); + break; + + case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: + case SCU_EVENT_LINK_FAILURE: + case SCU_EVENT_HARD_RESET_RECEIVED: + /* Start the oob/sn state machine over again */ + scic_sds_phy_restart_starting_state(this_phy); + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER. - + * decode the event - link failure events restart the starting state machine - + * any other events log a warning message and set a failure status enum sci_status + * SCI_SUCCESS on a link failure event SCI_FAILURE on any unexpected event + * notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(this_phy); + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received unexpected " + "event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - + * decode the event - link failure events restart the starting state machine - + * sata spinup hold events are ignored since they are expected - any other + * events log a warning message and set a failure status enum sci_status SCI_SUCCESS + * on a link failure event SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(this_phy); + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + /* These events are received every 10ms and are expected while in this state */ + break; + + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. */ + scic_sds_phy_start_sas_link_training(this_phy); + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - + * decode the event - link failure events restart the starting state machine - + * sata spinup hold events are ignored since they are expected - sata phy + * detected event change to the wait speed event - any other events log a + * warning message and set a failure status enum sci_status SCI_SUCCESS on a link + * failure event SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(this_phy); + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + /* + * These events might be received since we dont know how many may be in + * the completion queue while waiting for power */ + break; + + case SCU_EVENT_SATA_PHY_DETECTED: + this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; + + /* We have received the SATA PHY notification change state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN + ); + break; + + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. */ + scic_sds_phy_start_sas_link_training(this_phy); + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. + * - decode the event - sata phy detected returns us back to this state. - + * speed event detected causes a state transition to the wait for signature. - + * link failure events restart the starting state machine - any other events + * log a warning message and set a failure status enum sci_status SCI_SUCCESS on any + * valid event notification SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SATA_PHY_DETECTED: + /* + * The hardware reports multiple SATA PHY detected events + * ignore the extras */ + break; + + case SCU_EVENT_SATA_15: + case SCU_EVENT_SATA_15_SSC: + scic_sds_phy_complete_link_training( + this_phy, + SCI_SAS_150_GB, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF + ); + break; + + case SCU_EVENT_SATA_30: + case SCU_EVENT_SATA_30_SSC: + scic_sds_phy_complete_link_training( + this_phy, + SCI_SAS_300_GB, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF + ); + break; + + case SCU_EVENT_SATA_60: + case SCU_EVENT_SATA_60_SSC: + scic_sds_phy_complete_link_training( + this_phy, + SCI_SAS_600_GB, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF + ); + break; + + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(this_phy); + break; + + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. */ + scic_sds_phy_start_sas_link_training(this_phy); + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - + * decode the event - sas phy detected event backs up the state machine to the + * await speed notification. - identify timeout is an un-expected event and the + * state machine is restarted. - link failure events restart the starting state + * machine - any other events log a warning message and set a failure status + * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any + * unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SATA_PHY_DETECTED: + /* Backup the state machine */ + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN + ); + break; + + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(this_phy); + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + + +/* + * ***************************************************************************** + * * SCIC SDS PHY FRAME_HANDLERS + * ***************************************************************************** */ + +/** + * + * @phy: This is struct scic_sds_phy object which is being requested to decode the + * frame data. + * @frame_index: This is the index of the unsolicited frame which was received + * for this phy. + * + * This method decodes the unsolicited frame when the struct scic_sds_phy is in the + * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Get the UF Header - If the UF + * is an IAF - Copy IAF data to local phy object IAF data buffer. - Change + * starting substate to wait power. - else - log warning message of unexpected + * unsolicted frame - release frame buffer enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler( + struct scic_sds_phy *this_phy, + u32 frame_index) +{ + enum sci_status result; + u32 *frame_words; + struct sci_sas_identify_address_frame *identify_frame; + + result = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_phy_get_controller(this_phy)->uf_control), + frame_index, + (void **)&frame_words); + + if (result != SCI_SUCCESS) { + return result; + } + + frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]); + identify_frame = (struct sci_sas_identify_address_frame *)frame_words; + + if (identify_frame->address_frame_type == 0) { + /* + * Byte swap the rest of the frame so we can make + * a copy of the buffer */ + frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]); + frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]); + frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]); + frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]); + frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]); + + memcpy( + &this_phy->phy_type.sas.identify_address_frame_buffer, + identify_frame, + sizeof(struct sci_sas_identify_address_frame) + ); + + if (identify_frame->protocols.u.bits.smp_target) { + /* + * We got the IAF for an expander PHY go to the final state since + * there are no power requirements for expander phys. */ + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL + ); + } else { + /* We got the IAF we can now go to the await spinup semaphore state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER + ); + } + + result = SCI_SUCCESS; + } else + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected frame id %x\n", + __func__, + frame_index); + + /* Regardless of the result release this frame since we are done with it */ + scic_sds_controller_release_frame( + scic_sds_phy_get_controller(this_phy), frame_index + ); + + return result; +} + +/** + * + * @phy: This is struct scic_sds_phy object which is being requested to decode the + * frame data. + * @frame_index: This is the index of the unsolicited frame which was received + * for this phy. + * + * This method decodes the unsolicited frame when the struct scic_sds_phy is in the + * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Get the UF Header - If + * the UF is an SIGNATURE FIS - Copy IAF data to local phy object SIGNATURE FIS + * data buffer. - else - log warning message of unexpected unsolicted frame - + * release frame buffer enum sci_status SCI_SUCCESS Must decode the SIGNATURE FIS + * data + */ +static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handler( + struct scic_sds_phy *this_phy, + u32 frame_index) +{ + enum sci_status result; + u32 *frame_words; + struct sata_fis_header *fis_frame_header; + u32 *fis_frame_data; + + result = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_phy_get_controller(this_phy)->uf_control), + frame_index, + (void **)&frame_words); + + if (result != SCI_SUCCESS) { + return result; + } + + fis_frame_header = (struct sata_fis_header *)frame_words; + + if ( + (fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H) + && !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT) + ) { + scic_sds_unsolicited_frame_control_get_buffer( + &(scic_sds_phy_get_controller(this_phy)->uf_control), + frame_index, + (void **)&fis_frame_data + ); + + scic_sds_controller_copy_sata_response( + &this_phy->phy_type.sata.signature_fis_buffer, + frame_words, + fis_frame_data + ); + + /* We got the IAF we can now go to the await spinup semaphore state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL + ); + + result = SCI_SUCCESS; + } else + dev_warn(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected frame id %x\n", + __func__, + frame_index); + + /* Regardless of the result release this frame since we are done with it */ + scic_sds_controller_release_frame( + scic_sds_phy_get_controller(this_phy), frame_index + ); + + return result; +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY POWER_HANDLERS + * ***************************************************************************** */ + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This method is called by the struct scic_sds_controller when the phy object is + * granted power. - The notify enable spinups are turned on for this phy object + * - The phy state machine is transitioned to the + * SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_power_handler( + struct scic_sds_phy *this_phy) +{ + u32 enable_spinup; + + enable_spinup = SCU_SAS_ENSPINUP_READ(this_phy); + enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); + SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup); + + /* Change state to the final state this substate machine has run to completion */ + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL + ); + + return SCI_SUCCESS; +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This method is called by the struct scic_sds_controller when the phy object is + * granted power. - The phy state machine is transitioned to the + * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_power_handler( + struct scic_sds_phy *this_phy) +{ + u32 scu_sas_pcfg_value; + + /* Release the spinup hold state and reset the OOB state machine */ + scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + scu_sas_pcfg_value &= + ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + + /* Now restart the OOB operation */ + scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); + SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + + /* Change state to the final state this substate machine has run to completion */ + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN + ); + + return SCI_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_phy_state_handler +scic_sds_phy_starting_substate_handler_table[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] = +{ + /* SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_default_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_starting_substate_await_ossp_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, + scic_sds_phy_starting_substate_await_iaf_uf_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_starting_substate_await_sas_power_event_handler, + scic_sds_phy_starting_substate_await_sas_power_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_starting_substate_await_sata_power_event_handler, + scic_sds_phy_starting_substate_await_sata_power_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_starting_substate_await_sata_phy_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_starting_substate_await_sata_speed_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_starting_substate_await_sig_fis_frame_handler, + scic_sds_phy_starting_substate_await_sig_fis_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_default_event_handler, + scic_sds_phy_default_consume_power_handler + } +}; + +/** + * scic_sds_phy_set_starting_substate_handlers() - + * + * This macro sets the starting substate handlers by state_id + */ +#define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \ + scic_sds_phy_set_state_handlers(\ + (phy), \ + &scic_sds_phy_starting_substate_handler_table[(state_id)] \ + ) + +/* + * **************************************************************************** + * * PHY STARTING SUBSTATE METHODS + * **************************************************************************** */ + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL. - The initial state + * handlers are put in place for the struct scic_sds_phy object. - The state is + * changed to the wait phy type event notification. none + */ +static void scic_sds_phy_starting_initial_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); + + /* This is just an temporary state go off to the starting state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_starting_substate_machine(this_phy), + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_ossp_en_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_iaf_uf_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Set the + * struct scic_sds_phy object state handlers for this state. - Add this phy object to + * the power control queue none + */ +static void scic_sds_phy_starting_await_sas_power_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER + ); + + scic_sds_controller_power_control_queue_insert( + scic_sds_phy_get_controller(this_phy), + this_phy + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Remove the + * struct scic_sds_phy object from the power control queue. none + */ +static void scic_sds_phy_starting_await_sas_power_substate_exit( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_controller_power_control_queue_remove( + scic_sds_phy_get_controller(this_phy), this_phy + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Set the + * struct scic_sds_phy object state handlers for this state. - Add this phy object to + * the power control queue none + */ +static void scic_sds_phy_starting_await_sata_power_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER + ); + + scic_sds_controller_power_control_queue_insert( + scic_sds_phy_get_controller(this_phy), + this_phy + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Remove the + * struct scic_sds_phy object from the power control queue. none + */ +static void scic_sds_phy_starting_await_sata_power_substate_exit( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_controller_power_control_queue_remove( + scic_sds_phy_get_controller(this_phy), + this_phy + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_sata_phy_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN + ); + + scic_cb_timer_start( + scic_sds_phy_get_controller(this_phy), + this_phy->sata_timeout_timer, + SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer + * that was started on entry to await sata phy event notification none + */ +static void scic_sds_phy_starting_await_sata_phy_substate_exit( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_cb_timer_stop( + scic_sds_phy_get_controller(this_phy), + this_phy->sata_timeout_timer + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_sata_speed_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN + ); + + scic_cb_timer_start( + scic_sds_phy_get_controller(this_phy), + this_phy->sata_timeout_timer, + SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer + * that was started on entry to await sata phy event notification none + */ +static void scic_sds_phy_starting_await_sata_speed_substate_exit( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_cb_timer_stop( + scic_sds_phy_get_controller(this_phy), + this_phy->sata_timeout_timer + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Set the + * struct scic_sds_phy object state handlers for this state. - Start the SIGNATURE FIS + * timeout timer none + */ +static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter( + struct sci_base_object *object) +{ + bool continue_to_ready_state; + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF + ); + + continue_to_ready_state = scic_sds_port_link_detected( + this_phy->owning_port, + this_phy + ); + + if (continue_to_ready_state) { + /* + * Clear the PE suspend condition so we can actually receive SIG FIS + * The hardware will not respond to the XRDY until the PE suspend + * condition is cleared. */ + scic_sds_phy_resume(this_phy); + + scic_cb_timer_start( + scic_sds_phy_get_controller(this_phy), + this_phy->sata_timeout_timer, + SCIC_SDS_SIGNATURE_FIS_TIMEOUT + ); + } else { + this_phy->is_in_link_training = false; + } +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Stop the SIGNATURE + * FIS timeout timer. none + */ +static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_cb_timer_stop( + scic_sds_phy_get_controller(this_phy), + this_phy->sata_timeout_timer + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. - Set the struct scic_sds_phy + * object state handlers for this state. - Change base state machine to the + * ready state. none + */ +static void scic_sds_phy_starting_final_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_starting_substate_handlers( + this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL + ); + + /* + * State machine has run to completion so exit out and change + * the base state machine to the ready state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_READY); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_phy_starting_substates[] = { + [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { + .enter_state = scic_sds_phy_starting_initial_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { + .enter_state = scic_sds_phy_starting_await_ossp_en_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { + .enter_state = scic_sds_phy_starting_await_sas_speed_en_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { + .enter_state = scic_sds_phy_starting_await_iaf_uf_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { + .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, + .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { + .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { + .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { + .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { + .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter, + .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { + .enter_state = scic_sds_phy_starting_final_substate_enter, + } +}; + +/* + * *************************************************************************** + * * DEFAULT HANDLERS + * *************************************************************************** */ + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This is the default method for phy a start request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_phy_default_start_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)phy; + + dev_warn(sciphy_to_dev(this_phy), + "%s: SCIC Phy 0x%p requested to start from invalid " + "state %d\n", + __func__, + this_phy, + sci_base_state_machine_get_state( + &this_phy->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; + +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This is the default method for phy a stop request. It will report a warning + * and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_phy_default_stop_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)phy; + + dev_warn(sciphy_to_dev(this_phy), + "%s: SCIC Phy 0x%p requested to stop from invalid " + "state %d\n", + __func__, + this_phy, + sci_base_state_machine_get_state( + &this_phy->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This is the default method for phy a reset request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_phy_default_reset_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)phy; + + dev_warn(sciphy_to_dev(this_phy), + "%s: SCIC Phy 0x%p requested to reset from invalid state " + "%d\n", + __func__, + this_phy, + sci_base_state_machine_get_state( + &this_phy->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This is the default method for phy a destruct request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_phy_default_destroy_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)phy; + + /* / @todo Implement something for the default */ + dev_warn(sciphy_to_dev(this_phy), + "%s: SCIC Phy 0x%p requested to destroy from invalid " + "state %d\n", + __func__, + this_phy, + sci_base_state_machine_get_state( + &this_phy->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * @frame_index: This is the frame index that was received from the SCU + * hardware. + * + * This is the default method for a phy frame handling request. It will report + * a warning, release the frame and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_phy_default_frame_handler( + struct scic_sds_phy *this_phy, + u32 frame_index) +{ + dev_warn(sciphy_to_dev(this_phy), + "%s: SCIC Phy 0x%p received unexpected frame data %d " + "while in state %d\n", + __func__, + this_phy, + frame_index, + sci_base_state_machine_get_state( + &this_phy->parent.state_machine)); + + scic_sds_controller_release_frame( + scic_sds_phy_get_controller(this_phy), frame_index); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * @event_code: This is the event code that was received from the SCU hardware. + * + * This is the default method for a phy event handler. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_phy_default_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + dev_warn(sciphy_to_dev(this_phy), + "%s: SCIC Phy 0x%p received unexpected event status %x " + "while in state %d\n", + __func__, + this_phy, + event_code, + sci_base_state_machine_get_state( + &this_phy->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This is the default method for a phy consume power handler. It will report + * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_phy_default_consume_power_handler( + struct scic_sds_phy *this_phy) +{ + dev_warn(sciphy_to_dev(this_phy), + "%s: SCIC Phy 0x%p given unexpected permission to consume " + "power while in state %d\n", + __func__, + this_phy, + sci_base_state_machine_get_state( + &this_phy->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/* + * ****************************************************************************** + * * PHY STOPPED STATE HANDLERS + * ****************************************************************************** */ + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This method takes the struct scic_sds_phy from a stopped state and attempts to + * start it. - The phy state machine is transitioned to the + * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_stopped_state_start_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)phy; + + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_STARTING + ); + + return SCI_SUCCESS; +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This method takes the struct scic_sds_phy from a stopped state and destroys it. - + * This function takes no action. Shouldnt this function transition the + * struct sci_base_phy::state_machine to the SCI_BASE_PHY_STATE_FINAL? enum sci_status + * SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_stopped_state_destroy_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)phy; + + /* / @todo what do we actually need to do here? */ + return SCI_SUCCESS; +} + +/* + * ****************************************************************************** + * * PHY STARTING STATE HANDLERS + * ****************************************************************************** */ + +/* All of these state handlers are mapped to the starting sub-state machine */ + +/* + * ****************************************************************************** + * * PHY READY STATE HANDLERS + * ****************************************************************************** */ + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This method takes the struct scic_sds_phy from a ready state and attempts to stop + * it. - The phy state machine is transitioned to the + * SCI_BASE_PHY_STATE_STOPPED. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_ready_state_stop_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)phy; + + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_STOPPED + ); + + return SCI_SUCCESS; +} + +/** + * + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This method takes the struct scic_sds_phy from a ready state and attempts to reset + * it. - The phy state machine is transitioned to the + * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_ready_state_reset_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)phy; + + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_RESETTING + ); + + return SCI_SUCCESS; +} + +/** + * + * @phy: This is the struct scic_sds_phy object which has received the event. + * + * This method request the struct scic_sds_phy handle the received event. The only + * event that we are interested in while in the ready state is the link failure + * event. - decoded event is a link failure - transition the struct scic_sds_phy back + * to the SCI_BASE_PHY_STATE_STARTING state. - any other event recived will + * report a warning message enum sci_status SCI_SUCCESS if the event received is a + * link failure SCI_FAILURE_INVALID_STATE for any other event received. + */ +static enum sci_status scic_sds_phy_ready_state_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + enum sci_status result = SCI_FAILURE; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_STARTING + ); + + result = SCI_SUCCESS; + break; + + case SCU_EVENT_BROADCAST_CHANGE: + /* Broadcast change received. Notify the port. */ + if (scic_sds_phy_get_port(this_phy) != SCI_INVALID_HANDLE) + scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); + else + this_phy->bcn_received_while_port_unassigned = true; + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%sP SCIC PHY 0x%p ready state machine received " + "unexpected event_code %x\n", + __func__, + this_phy, + event_code); + + result = SCI_FAILURE_INVALID_STATE; + break; + } + + return result; +} + +/* --------------------------------------------------------------------------- */ + +/** + * + * @this_phy: This is the struct scic_sds_phy object which is receiving the event. + * @event_code: This is the event code to be processed. + * + * This is the resetting state event handler. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_phy_resetting_state_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code) +{ + enum sci_status result = SCI_FAILURE; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_HARD_RESET_TRANSMITTED: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_STARTING + ); + + result = SCI_SUCCESS; + break; + + default: + dev_warn(sciphy_to_dev(this_phy), + "%s: SCIC PHY 0x%p resetting state machine received " + "unexpected event_code %x\n", + __func__, + this_phy, + event_code); + + result = SCI_FAILURE_INVALID_STATE; + break; + } + + return result; +} + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_phy_state_handler +scic_sds_phy_state_handler_table[SCI_BASE_PHY_MAX_STATES] = +{ + /* SCI_BASE_PHY_STATE_INITIAL */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_default_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCI_BASE_PHY_STATE_STOPPED */ + { + { + scic_sds_phy_stopped_state_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_stopped_state_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_default_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCI_BASE_PHY_STATE_STARTING */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_default_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCI_BASE_PHY_STATE_READY */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_ready_state_stop_handler, + scic_sds_phy_ready_state_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_ready_state_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCI_BASE_PHY_STATE_RESETTING */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_resetting_state_event_handler, + scic_sds_phy_default_consume_power_handler + }, + /* SCI_BASE_PHY_STATE_FINAL */ + { + { + scic_sds_phy_default_start_handler, + scic_sds_phy_default_stop_handler, + scic_sds_phy_default_reset_handler, + scic_sds_phy_default_destroy_handler + }, + scic_sds_phy_default_frame_handler, + scic_sds_phy_default_event_handler, + scic_sds_phy_default_consume_power_handler + } +}; + +/* + * **************************************************************************** + * * PHY STATE PRIVATE METHODS + * **************************************************************************** */ + +/** + * + * @this_phy: This is the struct scic_sds_phy object to stop. + * + * This method will stop the struct scic_sds_phy object. This does not reset the + * protocol engine it just suspends it and places it in a state where it will + * not cause the end device to power up. none + */ +static void scu_link_layer_stop_protocol_engine( + struct scic_sds_phy *this_phy) +{ + u32 scu_sas_pcfg_value; + u32 enable_spinup_value; + + /* Suspend the protocol engine and place it in a sata spinup hold state */ + scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + scu_sas_pcfg_value |= ( + SCU_SAS_PCFG_GEN_BIT(OOB_RESET) + | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) + | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) + ); + SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + + /* Disable the notify enable spinup primitives */ + enable_spinup_value = SCU_SAS_ENSPINUP_READ(this_phy); + enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE); + SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup_value); +} + +/** + * + * + * This method will start the OOB/SN state machine for this struct scic_sds_phy object. + */ +static void scu_link_layer_start_oob( + struct scic_sds_phy *this_phy) +{ + u32 scu_sas_pcfg_value; + + scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); + scu_sas_pcfg_value &= + ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); + + SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); +} + +/** + * + * + * This method will transmit a hard reset request on the specified phy. The SCU + * hardware requires that we reset the OOB state machine and set the hard reset + * bit in the phy configuration register. We then must start OOB over with the + * hard reset bit set. + */ +static void scu_link_layer_tx_hard_reset( + struct scic_sds_phy *this_phy) +{ + u32 phy_configuration_value; + + /* + * SAS Phys must wait for the HARD_RESET_TX event notification to transition + * to the starting state. */ + phy_configuration_value = SCU_SAS_PCFG_READ(this_phy); + phy_configuration_value |= + (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); + SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value); + + /* Now take the OOB state machine out of reset */ + phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); + phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value); +} + +/* + * **************************************************************************** + * * PHY BASE STATE METHODS + * **************************************************************************** */ + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state + * handlers for the phy object base state machine initial state. none + */ +static void scic_sds_phy_initial_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state + * handlers for the phy object base state machine initial state. - The SCU + * hardware is requested to stop the protocol engine. none + */ +static void scic_sds_phy_stopped_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + /* / @todo We need to get to the controller to place this PE in a reset state */ + + scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED); + + scu_link_layer_stop_protocol_engine(this_phy); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_STARTING. - This function sets the state + * handlers for the phy object base state machine starting state. - The SCU + * hardware is requested to start OOB/SN on this protocl engine. - The phy + * starting substate machine is started. - If the previous state was the ready + * state then the struct scic_sds_controller is informed that the phy has gone link + * down. none + */ +static void scic_sds_phy_starting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STARTING); + + scu_link_layer_stop_protocol_engine(this_phy); + scu_link_layer_start_oob(this_phy); + + /* We don't know what kind of phy we are going to be just yet */ + this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; + this_phy->bcn_received_while_port_unassigned = false; + + /* Change over to the starting substate machine to continue */ + sci_base_state_machine_start(&this_phy->starting_substate_machine); + + if (this_phy->parent.state_machine.previous_state_id + == SCI_BASE_PHY_STATE_READY) { + scic_sds_controller_link_down( + scic_sds_phy_get_controller(this_phy), + scic_sds_phy_get_port(this_phy), + this_phy + ); + } +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_READY. - This function sets the state + * handlers for the phy object base state machine ready state. - The SCU + * hardware protocol engine is resumed. - The struct scic_sds_controller is informed + * that the phy object has gone link up. none + */ +static void scic_sds_phy_ready_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_READY); + + scic_sds_controller_link_up( + scic_sds_phy_get_controller(this_phy), + scic_sds_phy_get_port(this_phy), + this_phy + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU hardware + * protocol engine represented by this struct scic_sds_phy object. none + */ +static void scic_sds_phy_ready_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_suspend(this_phy); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_RESETTING. - This function sets the state + * handlers for the phy object base state machine resetting state. none + */ +static void scic_sds_phy_resetting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_RESETTING); + + /* + * The phy is being reset, therefore deactivate it from the port. + * In the resetting state we don't notify the user regarding + * link up and link down notifications. */ + scic_sds_port_deactivate_phy(this_phy->owning_port, this_phy, false); + + if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + scu_link_layer_tx_hard_reset(this_phy); + } else { + /* + * The SCU does not need to have a descrete reset state so just go back to + * the starting state. */ + sci_base_state_machine_change_state( + &this_phy->parent.state_machine, + SCI_BASE_PHY_STATE_STARTING + ); + } +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_FINAL. - This function sets the state + * handlers for the phy object base state machine final state. none + */ +static void scic_sds_phy_final_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_phy *this_phy; + + this_phy = (struct scic_sds_phy *)object; + + scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_FINAL); + + /* Nothing to do here */ +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_phy_state_table[] = { + [SCI_BASE_PHY_STATE_INITIAL] = { + .enter_state = scic_sds_phy_initial_state_enter, + }, + [SCI_BASE_PHY_STATE_STOPPED] = { + .enter_state = scic_sds_phy_stopped_state_enter, + }, + [SCI_BASE_PHY_STATE_STARTING] = { + .enter_state = scic_sds_phy_starting_state_enter, + }, + [SCI_BASE_PHY_STATE_READY] = { + .enter_state = scic_sds_phy_ready_state_enter, + .exit_state = scic_sds_phy_ready_state_exit, + }, + [SCI_BASE_PHY_STATE_RESETTING] = { + .enter_state = scic_sds_phy_resetting_state_enter, + }, + [SCI_BASE_PHY_STATE_FINAL] = { + .enter_state = scic_sds_phy_final_state_enter, + }, +}; + diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h new file mode 100644 index 000000000000..d9691b30e457 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -0,0 +1,491 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_PHY_H_ +#define _SCIC_SDS_PHY_H_ + +/** + * This file contains the structures, constants and prototypes for the + * struct scic_sds_phy object. + * + * + */ + +#include "intel_sata.h" +#include "intel_sas.h" +#include "sci_base_phy.h" +#include "scu_registers.h" + +struct scic_sds_port; +/** + * + * + * This is the timeout value for the SATA phy to wait for a SIGNATURE FIS + * before restarting the starting state machine. Technically, the old parallel + * ATA specification required up to 30 seconds for a device to issue its + * signature FIS as a result of a soft reset. Now we see that devices respond + * generally within 15 seconds, but we'll use 25 for now. + */ +#define SCIC_SDS_SIGNATURE_FIS_TIMEOUT 25000 + +/** + * + * + * This is the timeout for the SATA OOB/SN because the hardware does not + * recognize a hot plug after OOB signal but before the SN signals. We need to + * make sure after a hotplug timeout if we have not received the speed event + * notification from the hardware that we restart the hardware OOB state + * machine. + */ +#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250 + +/** + * enum SCIC_SDS_PHY_STARTING_SUBSTATES - + * + * + */ +enum SCIC_SDS_PHY_STARTING_SUBSTATES { + /** + * Initial state + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL, + + /** + * Wait state for the hardware OSSP event type notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN, + + /** + * Wait state for the PHY speed notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN, + + /** + * Wait state for the IAF Unsolicited frame notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF, + + /** + * Wait state for the request to consume power + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER, + + /** + * Wait state for request to consume power + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, + + /** + * Wait state for the SATA PHY notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, + + /** + * Wait for the SATA PHY speed notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, + + /** + * Wait state for the SIGNATURE FIS unsolicited frame notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, + + /** + * Exit state for this state machine + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL, + + /** + * Maximum number of substates for the STARTING state machine + */ + SCIC_SDS_PHY_STARTING_MAX_SUBSTATES +}; + +struct scic_sds_port; +struct scic_sds_controller; + +#ifdef SCIC_DEBUG_ENABLED +#define MAX_STATE_TRANSITION_RECORD (256) + +/** + * + * + * Debug code to record the state transitions for the phy object + */ +struct scic_sds_phy_state_record { + struct sci_base_observer base_state_observer; + struct sci_base_observer starting_state_observer; + + u16 index; + + u32 state_transition_table[MAX_STATE_TRANSITION_RECORD]; + +}; +#endif /* SCIC_DEBUG_ENABLED */ + +/** + * This enumeration provides a named phy type for the state machine + * + * + */ +enum SCIC_SDS_PHY_PROTOCOL { + /** + * This is an unknown phy type since there is either nothing on the other + * end or we have not detected the phy type as yet. + */ + SCIC_SDS_PHY_PROTOCOL_UNKNOWN, + + /** + * This is a SAS PHY + */ + SCIC_SDS_PHY_PROTOCOL_SAS, + + /** + * This is a SATA PHY + */ + SCIC_SDS_PHY_PROTOCOL_SATA, + + SCIC_SDS_MAX_PHY_PROTOCOLS +}; + +/** + * struct scic_sds_phy - This structure contains or references all of the data + * necessary to represent the core phy object and SCU harware protocol + * engine. + * + * + */ +struct scic_sds_phy { + struct sci_base_phy parent; + + /** + * This field specifies the port object that owns/contains this phy. + */ + struct scic_sds_port *owning_port; + + /** + * This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s, + * or 6.0 Gb/s operation. + */ + enum sci_sas_link_rate max_negotiated_speed; + + /** + * This member specifies the protocol being utilized on this phy. This + * field contains a legitamite value once the PHY has link trained with + * a remote phy. + */ + enum SCIC_SDS_PHY_PROTOCOL protocol; + + /** + * This field specifies the index with which this phy is associated (0-3). + */ + u8 phy_index; + + /** + * This member indicates if this particular PHY has received a BCN while + * it had no port assignement. This BCN will be reported once the phy is + * assigned to a port. + */ + bool bcn_received_while_port_unassigned; + + /** + * This field indicates if this PHY is currently in the process of + * link training (i.e. it has started OOB, but has yet to perform + * IAF exchange/Signature FIS reception). + */ + bool is_in_link_training; + + union { + struct { + struct sci_sas_identify_address_frame identify_address_frame_buffer; + + } sas; + + struct { + struct sata_fis_reg_d2h signature_fis_buffer; + + } sata; + + } phy_type; + + /** + * This field contains a reference to the timer utilized in detecting + * when a signature FIS timeout has occurred. The signature FIS is the + * first FIS sent by an attached SATA device after OOB/SN. + */ + void *sata_timeout_timer; + + struct scic_sds_phy_state_handler *state_handlers; + + struct sci_base_state_machine starting_substate_machine; + + #ifdef SCIC_DEBUG_ENABLED + struct scic_sds_phy_state_record state_record; + #endif /* SCIC_DEBUG_ENABLED */ + + /** + * This field points to the link layer register set within the SCU. + */ + struct scu_link_layer_registers *link_layer_registers; + +}; + + +typedef enum sci_status (*SCIC_SDS_PHY_EVENT_HANDLER_T)(struct scic_sds_phy *, u32); +typedef enum sci_status (*SCIC_SDS_PHY_FRAME_HANDLER_T)(struct scic_sds_phy *, u32); +typedef enum sci_status (*SCIC_SDS_PHY_POWER_HANDLER_T)(struct scic_sds_phy *); + +/** + * struct scic_sds_phy_state_handler - + * + * + */ +struct scic_sds_phy_state_handler { + /** + * This is the struct sci_base_phy object state handlers. + */ + struct sci_base_phy_state_handler parent; + + /** + * The state handler for unsolicited frames received from the SCU hardware. + */ + SCIC_SDS_PHY_FRAME_HANDLER_T frame_handler; + + /** + * The state handler for events received from the SCU hardware. + */ + SCIC_SDS_PHY_EVENT_HANDLER_T event_handler; + + /** + * The state handler for staggered spinup. + */ + SCIC_SDS_PHY_POWER_HANDLER_T consume_power_handler; + +}; + +extern struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[]; +extern const struct sci_base_state scic_sds_phy_state_table[]; +extern const struct sci_base_state scic_sds_phy_starting_substates[]; +extern struct scic_sds_phy_state_handler + scic_sds_phy_starting_substate_handler_table[]; + + +/** + * scic_sds_phy_get_index() - + * + * This macro returns the phy index for the specified phy + */ +#define scic_sds_phy_get_index(phy) \ + ((phy)->phy_index) + +/** + * scic_sds_phy_get_controller() - This macro returns the controller for this + * phy + * + * + */ +#define scic_sds_phy_get_controller(phy) \ + (scic_sds_port_get_controller((phy)->owning_port)) + +/** + * scic_sds_phy_get_base_state_machine() - This macro returns the state machine + * for the base phy + * + * + */ +#define scic_sds_phy_get_base_state_machine(phy) \ + (&(phy)->parent.state_machine) + +/** + * scic_sds_phy_get_starting_substate_machine() - This macro returns the + * starting substate machine for this phy + * + * + */ +#define scic_sds_phy_get_starting_substate_machine(phy) \ + (&(phy)->starting_substate_machine) + +/** + * scic_sds_phy_set_state_handlers() - This macro sets the state handlers for + * this phy object + * + * + */ +#define scic_sds_phy_set_state_handlers(phy, handlers) \ + ((phy)->state_handlers = (handlers)) + +/** + * scic_sds_phy_set_base_state_handlers() - + * + * This macro set the base state handlers for the phy object. + */ +#define scic_sds_phy_set_base_state_handlers(phy, state_id) \ + scic_sds_phy_set_state_handlers(\ + (phy), \ + &scic_sds_phy_state_handler_table[(state_id)] \ + ) + +/** + * scic_sds_phy_is_ready() - + * + * This macro returns true if the current base state for this phy is + * SCI_BASE_PHY_STATE_READY + */ +#define scic_sds_phy_is_ready(phy) \ + (\ + SCI_BASE_PHY_STATE_READY \ + == sci_base_state_machine_get_state(\ + scic_sds_phy_get_base_state_machine(phy) \ + ) \ + ) + +/* --------------------------------------------------------------------------- */ + + + + +/* --------------------------------------------------------------------------- */ + +void scic_sds_phy_construct( + struct scic_sds_phy *this_phy, + struct scic_sds_port *owning_port, + u8 phy_index); + +struct scic_sds_port *scic_sds_phy_get_port( + struct scic_sds_phy *this_phy); + +void scic_sds_phy_set_port( + struct scic_sds_phy *this_phy, + struct scic_sds_port *owning_port); + +enum sci_status scic_sds_phy_initialize( + struct scic_sds_phy *this_phy, + struct scu_link_layer_registers *link_layer_registers); + +enum sci_status scic_sds_phy_start( + struct scic_sds_phy *this_phy); + +enum sci_status scic_sds_phy_stop( + struct scic_sds_phy *this_phy); + +enum sci_status scic_sds_phy_reset( + struct scic_sds_phy *this_phy); + +/* --------------------------------------------------------------------------- */ + +void scic_sds_phy_suspend( + struct scic_sds_phy *this_phy); + +void scic_sds_phy_resume( + struct scic_sds_phy *this_phy); + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_sds_phy_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code); + +enum sci_status scic_sds_phy_frame_handler( + struct scic_sds_phy *this_phy, + u32 frame_index); + +enum sci_status scic_sds_phy_consume_power_handler( + struct scic_sds_phy *this_phy); + +void scic_sds_phy_get_sas_address( + struct scic_sds_phy *this_phy, + struct sci_sas_address *sas_address); + +void scic_sds_phy_get_attached_sas_address( + struct scic_sds_phy *this_phy, + struct sci_sas_address *sas_address); + +void scic_sds_phy_get_protocols( + struct scic_sds_phy *this_phy, + struct sci_sas_identify_address_frame_protocols *protocols); + +void scic_sds_phy_get_attached_phy_protocols( + struct scic_sds_phy *this_phy, + struct sci_sas_identify_address_frame_protocols *protocols); + +/* + * ****************************************************************************- + * * SCIC SDS PHY Handler Methods + * ****************************************************************************- */ + +enum sci_status scic_sds_phy_default_start_handler( + struct sci_base_phy *phy); + +enum sci_status scic_sds_phy_default_stop_handler( + struct sci_base_phy *phy); + +enum sci_status scic_sds_phy_default_reset_handler( + struct sci_base_phy *phy); + +enum sci_status scic_sds_phy_default_destroy_handler( + struct sci_base_phy *phy); + +enum sci_status scic_sds_phy_default_frame_handler( + struct scic_sds_phy *phy, + u32 frame_index); + +enum sci_status scic_sds_phy_default_event_handler( + struct scic_sds_phy *phy, + u32 evnet_code); + +enum sci_status scic_sds_phy_default_consume_power_handler( + struct scic_sds_phy *phy); + +#endif /* _SCIC_SDS_PHY_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_phy_registers.h b/drivers/scsi/isci/core/scic_sds_phy_registers.h new file mode 100644 index 000000000000..7883819035da --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_phy_registers.h @@ -0,0 +1,187 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_PHY_REGISTERS_H_ +#define _SCIC_SDS_PHY_REGISTERS_H_ + +/** + * This file contains the macros used by the phy object to read/write to the + * SCU link layer registers. + * + * + */ + +#include "scic_sds_controller.h" + +/* + * ***************************************************************************** + * * SCU LINK LAYER REGISTER OPERATIONS + * ***************************************************************************** */ + +/** + * scu_link_layer_register_read() - + * + * THis macro requests the SCU register write for the specified link layer + * register. + */ +#define scu_link_layer_register_read(phy, reg) \ + scu_register_read(\ + scic_sds_phy_get_controller(phy), \ + (phy)->link_layer_registers->reg \ + ) + +/** + * scu_link_layer_register_write() - + * + * This macro requests the SCU register read for the specified link layer + * register. + */ +#define scu_link_layer_register_write(phy, reg, value) \ + scu_register_write(\ + scic_sds_phy_get_controller(phy), \ + (phy)->link_layer_registers->reg, \ + (value) \ + ) + +/* + * ***************************************************************************** + * * SCU LINK LAYER REGISTERS + * ***************************************************************************** */ + +/* / This macro reads from the SAS Identify Frame PHY Identifier register */ +#define SCU_SAS_TIPID_READ(phy) \ + scu_link_layer_register_read(phy, identify_frame_phy_id) + +/* / This macro writes to the SAS Identify Frame PHY Identifier register */ +#define SCU_SAS_TIPID_WRITE(phy, value) \ + scu_link_layer_register_write(phy, identify_frame_phy_id, value) + +/* / This macro reads from the SAS Identification register */ +#define SCU_SAS_TIID_READ(phy) \ + scu_link_layer_register_read(phy, transmit_identification) + +/* / This macro writes to the SAS Identification register */ +#define SCU_SAS_TIID_WRITE(phy, value) \ + scu_link_layer_register_write(phy, transmit_identification, value) + +/* / This macro reads the SAS Device Name High register */ +#define SCU_SAS_TIDNH_READ(phy) \ + scu_link_layer_register_read(phy, sas_device_name_high) + +/* / This macro writes the SAS Device Name High register */ +#define SCU_SAS_TIDNH_WRITE(phy, value) \ + scu_link_layer_register_write(phy, sas_device_name_high, value) + +/* / This macro reads the SAS Device Name Low register */ +#define SCU_SAS_TIDNL_READ(phy) \ + scu_link_layer_register_read(phy, sas_device_name_low) + +/* / This macro writes the SAS Device Name Low register */ +#define SCU_SAS_TIDNL_WRITE(phy, value) \ + scu_link_layer_register_write(phy, sas_device_name_low, value) + +/* / This macro reads the Source SAS Address High register */ +#define SCU_SAS_TISSAH_READ(phy) \ + scu_link_layer_register_read(phy, source_sas_address_high) + +/* / This macro writes the Source SAS Address High register */ +#define SCU_SAS_TISSAH_WRITE(phy, value) \ + scu_link_layer_register_write(phy, source_sas_address_high, value) + +/* / This macro reads the Source SAS Address Low register */ +#define SCU_SAS_TISSAL_READ(phy) \ + scu_link_layer_register_read(phy, source_sas_address_low) + +/* / This macro writes the Source SAS Address Low register */ +#define SCU_SAS_TISSAL_WRITE(phy, value) \ + scu_link_layer_register_write(phy, source_sas_address_low, value) + +/* / This macro reads the PHY Configuration register */ +#define SCU_SAS_PCFG_READ(phy) \ + scu_link_layer_register_read(phy, phy_configuration); + +/* / This macro writes the PHY Configuration register */ +#define SCU_SAS_PCFG_WRITE(phy, value) \ + scu_link_layer_register_write(phy, phy_configuration, value) + +/* / This macro reads the PHY Enable Spinup register */ +#define SCU_SAS_ENSPINUP_READ(phy) \ + scu_link_layer_register_read(phy, notify_enable_spinup_control) + +/* / This macro writes the PHY Enable Spinup register */ +#define SCU_SAS_ENSPINUP_WRITE(phy, value) \ + scu_link_layer_register_write(phy, notify_enable_spinup_control, value) + +/* / This macro reads the PHY Capacity register */ +#define SCU_SAS_PHYCAP_READ(phy) \ + scu_link_layer_register_read(phy, phy_capabilities) + +/* / This macro writes the PHY Capacity register */ +#define SCU_SAS_PHYCAP_WRITE(phy, value) \ + scu_link_layer_register_write(phy, phy_capabilities, value) + +/* / This macro reads the Recieved PHY Capacity register */ +#define SCU_SAS_RECPHYCAP_READ(phy) \ + scu_link_layer_register_read(phy, receive_phycap) + +/* / This macro reads the link layer control register */ +#define SCU_SAS_LLCTL_READ(phy) \ + scu_link_layer_register_read(phy, link_layer_control); + +/* / This macro writes the link layer control register */ +#define SCU_SAS_LLCTL_WRITE(phy, value) \ + scu_link_layer_register_write(phy, link_layer_control, value); + +#endif /* _SCIC_SDS_PHY_REGISTERS_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c new file mode 100644 index 000000000000..1af38505840c --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -0,0 +1,2757 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "intel_sas.h" +#include "sci_base_port.h" +#include "scic_controller.h" +#include "scic_phy.h" +#include "scic_port.h" +#include "scic_sds_controller.h" +#include "scic_sds_phy.h" +#include "scic_sds_phy_registers.h" +#include "scic_sds_port.h" +#include "scic_sds_port_registers.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_remote_node_context.h" +#include "scic_sds_request.h" +#include "scic_user_callback.h" +#include "sci_environment.h" + + +static void scic_sds_port_invalid_link_up( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy); +static void scic_sds_port_timeout_handler( + void *port); +#define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) +#define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) + +#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) + +void sci_base_port_construct( + struct sci_base_port *base_port, + const struct sci_base_state *state_table) +{ + base_port->parent.private = NULL; + sci_base_state_machine_construct( + &base_port->state_machine, + &base_port->parent, + state_table, + SCI_BASE_PORT_STATE_STOPPED + ); + + sci_base_state_machine_start( + &base_port->state_machine + ); +} + +/** + * + * @this_port: This is the port object to which the phy is being assigned. + * @phy_index: This is the phy index that is being assigned to the port. + * + * This method will return a true value if the specified phy can be assigned to + * this port The following is a list of phys for each port that are allowed: - + * Port 0 - 3 2 1 0 - Port 1 - 1 - Port 2 - 3 2 - Port 3 - 3 This method + * doesn't preclude all configurations. It merely ensures that a phy is part + * of the allowable set of phy identifiers for that port. For example, one + * could assign phy 3 to port 0 and no other phys. Please refer to + * scic_sds_port_is_phy_mask_valid() for information regarding whether the + * phy_mask for a port can be supported. bool true if this is a valid phy + * assignment for the port false if this is not a valid phy assignment for the + * port + */ +bool scic_sds_port_is_valid_phy_assignment( + struct scic_sds_port *this_port, + u32 phy_index) +{ + /* Initialize to invalid value. */ + u32 existing_phy_index = SCI_MAX_PHYS; + u32 index; + + if ((this_port->physical_port_index == 1) && (phy_index != 1)) { + return false; + } + + if (this_port->physical_port_index == 3 && phy_index != 3) { + return false; + } + + if ( + (this_port->physical_port_index == 2) + && ((phy_index == 0) || (phy_index == 1)) + ) { + return false; + } + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if ((this_port->phy_table[index] != NULL) + && (index != phy_index)) { + existing_phy_index = index; + } + } + + /* + * Ensure that all of the phys in the port are capable of + * operating at the same maximum link rate. */ + if ( + (existing_phy_index < SCI_MAX_PHYS) + && (this_port->owning_controller->user_parameters.sds1.phys[ + phy_index].max_speed_generation != + this_port->owning_controller->user_parameters.sds1.phys[ + existing_phy_index].max_speed_generation) + ) + return false; + + return true; +} + +/** + * This method requests a list (mask) of the phys contained in the supplied SAS + * port. + * @this_port: a handle corresponding to the SAS port for which to return the + * phy mask. + * + * Return a bit mask indicating which phys are a part of this port. Each bit + * corresponds to a phy identifier (e.g. bit 0 = phy id 0). + */ +u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) +{ + u32 index; + u32 mask; + + mask = 0; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (this_port->phy_table[index] != NULL) { + mask |= (1 << index); + } + } + + return mask; +} + +/** + * + * @this_port: This is the port object for which to determine if the phy mask + * can be supported. + * + * This method will return a true value if the port's phy mask can be supported + * by the SCU. The following is a list of valid PHY mask configurations for + * each port: - Port 0 - [[3 2] 1] 0 - Port 1 - [1] - Port 2 - [[3] 2] + * - Port 3 - [3] This method returns a boolean indication specifying if the + * phy mask can be supported. true if this is a valid phy assignment for the + * port false if this is not a valid phy assignment for the port + */ +bool scic_sds_port_is_phy_mask_valid( + struct scic_sds_port *this_port, + u32 phy_mask) +{ + if (this_port->physical_port_index == 0) { + if (((phy_mask & 0x0F) == 0x0F) + || ((phy_mask & 0x03) == 0x03) + || ((phy_mask & 0x01) == 0x01) + || (phy_mask == 0)) + return true; + } else if (this_port->physical_port_index == 1) { + if (((phy_mask & 0x02) == 0x02) + || (phy_mask == 0)) + return true; + } else if (this_port->physical_port_index == 2) { + if (((phy_mask & 0x0C) == 0x0C) + || ((phy_mask & 0x04) == 0x04) + || (phy_mask == 0)) + return true; + } else if (this_port->physical_port_index == 3) { + if (((phy_mask & 0x08) == 0x08) + || (phy_mask == 0)) + return true; + } + + return false; +} + +/** + * + * @this_port: This parameter specifies the port from which to return a + * connected phy. + * + * This method retrieves a currently active (i.e. connected) phy contained in + * the port. Currently, the lowest order phy that is connected is returned. + * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is + * returned if there are no currently active (i.e. connected to a remote end + * point) phys contained in the port. All other values specify a struct scic_sds_phy + * object that is active in the port. + */ +static struct scic_sds_phy *scic_sds_port_get_a_connected_phy( + struct scic_sds_port *this_port + ) { + u32 index; + struct scic_sds_phy *phy; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + /* + * Ensure that the phy is both part of the port and currently + * connected to the remote end-point. */ + phy = this_port->phy_table[index]; + if ( + (phy != NULL) + && scic_sds_port_active_phy(this_port, phy) + ) { + return phy; + } + } + + return NULL; +} + +/** + * scic_sds_port_set_phy() - + * @out]: port The port object to which the phy assignement is being made. + * @out]: phy The phy which is being assigned to the port. + * + * This method attempts to make the assignment of the phy to the port. If + * successful the phy is assigned to the ports phy table. bool true if the phy + * assignment can be made. false if the phy assignement can not be made. This + * is a functional test that only fails if the phy is currently assigned to a + * different port. + */ +enum sci_status scic_sds_port_set_phy( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + /* + * Check to see if we can add this phy to a port + * that means that the phy is not part of a port and that the port does + * not already have a phy assinged to the phy index. */ + if ( + (port->phy_table[phy->phy_index] == SCI_INVALID_HANDLE) + && (scic_sds_phy_get_port(phy) == SCI_INVALID_HANDLE) + && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index) + ) { + /* + * Phy is being added in the stopped state so we are in MPC mode + * make logical port index = physical port index */ + port->logical_port_index = port->physical_port_index; + port->phy_table[phy->phy_index] = phy; + scic_sds_phy_set_port(phy, port); + + return SCI_SUCCESS; + } + + return SCI_FAILURE; +} + +/** + * scic_sds_port_clear_phy() - + * @out]: port The port from which the phy is being cleared. + * @out]: phy The phy being cleared from the port. + * + * This method will clear the phy assigned to this port. This method fails if + * this phy is not currently assinged to this port. bool true if the phy is + * removed from the port. false if this phy is not assined to this port. + */ +enum sci_status scic_sds_port_clear_phy( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + /* Make sure that this phy is part of this port */ + if ( + (port->phy_table[phy->phy_index] == phy) + && (scic_sds_phy_get_port(phy) == port) + ) { + /* Yep it is assigned to this port so remove it */ + scic_sds_phy_set_port( + phy, + &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS] + ); + + port->phy_table[phy->phy_index] = SCI_INVALID_HANDLE; + + return SCI_SUCCESS; + } + + return SCI_FAILURE; +} + +/** + * scic_sds_port_add_phy() - + * @this_port: This parameter specifies the port in which the phy will be added. + * @the_phy: This parameter is the phy which is to be added to the port. + * + * This method will add a PHY to the selected port. This method returns an + * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status + * is failre to add the phy to the port. + */ +enum sci_status scic_sds_port_add_phy( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + return this_port->state_handlers->parent.add_phy_handler( + &this_port->parent, &the_phy->parent); +} + + +/** + * scic_sds_port_remove_phy() - + * @this_port: This parameter specifies the port in which the phy will be added. + * @the_phy: This parameter is the phy which is to be added to the port. + * + * This method will remove the PHY from the selected PORT. This method returns + * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other + * status is failre to add the phy to the port. + */ +enum sci_status scic_sds_port_remove_phy( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + return this_port->state_handlers->parent.remove_phy_handler( + &this_port->parent, &the_phy->parent); +} + +/** + * This method requests the SAS address for the supplied SAS port from the SCI + * implementation. + * @this_port: a handle corresponding to the SAS port for which to return the + * SAS address. + * @sas_address: This parameter specifies a pointer to a SAS address structure + * into which the core will copy the SAS address for the port. + * + */ +void scic_sds_port_get_sas_address( + struct scic_sds_port *this_port, + struct sci_sas_address *sas_address) +{ + u32 index; + + sas_address->high = 0; + sas_address->low = 0; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (this_port->phy_table[index] != NULL) { + scic_sds_phy_get_sas_address(this_port->phy_table[index], sas_address); + } + } +} + +/** + * This method will indicate which protocols are supported by this port. + * @this_port: a handle corresponding to the SAS port for which to return the + * supported protocols. + * @protocols: This parameter specifies a pointer to an IAF protocol field + * structure into which the core will copy the protocol values for the port. + * The values are returned as part of a bit mask in order to allow for + * multi-protocol support. + * + */ +static void scic_sds_port_get_protocols( + struct scic_sds_port *this_port, + struct sci_sas_identify_address_frame_protocols *protocols) +{ + u8 index; + + protocols->u.all = 0; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (this_port->phy_table[index] != NULL) { + scic_sds_phy_get_protocols(this_port->phy_table[index], protocols); + } + } +} + +/** + * This method requests the SAS address for the device directly attached to + * this SAS port. + * @this_port: a handle corresponding to the SAS port for which to return the + * SAS address. + * @sas_address: This parameter specifies a pointer to a SAS address structure + * into which the core will copy the SAS address for the device directly + * attached to the port. + * + */ +void scic_sds_port_get_attached_sas_address( + struct scic_sds_port *this_port, + struct sci_sas_address *sas_address) +{ + struct sci_sas_identify_address_frame_protocols protocols; + struct scic_sds_phy *phy; + + /* + * Ensure that the phy is both part of the port and currently + * connected to the remote end-point. */ + phy = scic_sds_port_get_a_connected_phy(this_port); + if (phy != NULL) { + scic_sds_phy_get_attached_phy_protocols(phy, &protocols); + + if (!protocols.u.bits.stp_target) { + scic_sds_phy_get_attached_sas_address(phy, sas_address); + } else { + scic_sds_phy_get_sas_address(phy, sas_address); + sas_address->low += phy->phy_index; + } + } else { + sas_address->high = 0; + sas_address->low = 0; + } +} + +/** + * This method will indicate which protocols are supported by this remote + * device. + * @this_port: a handle corresponding to the SAS port for which to return the + * supported protocols. + * @protocols: This parameter specifies a pointer to an IAF protocol field + * structure into which the core will copy the protocol values for the port. + * The values are returned as part of a bit mask in order to allow for + * multi-protocol support. + * + */ +void scic_sds_port_get_attached_protocols( + struct scic_sds_port *this_port, + struct sci_sas_identify_address_frame_protocols *protocols) +{ + struct scic_sds_phy *phy; + + /* + * Ensure that the phy is both part of the port and currently + * connected to the remote end-point. */ + phy = scic_sds_port_get_a_connected_phy(this_port); + if (phy != NULL) + scic_sds_phy_get_attached_phy_protocols(phy, protocols); + else + protocols->u.all = 0; +} + +/** + * This method returns the amount of memory requred for a port object. + * + * u32 + */ + +/** + * This method returns the minimum number of timers required for all port + * objects. + * + * u32 + */ + +/** + * This method returns the maximum number of timers required for all port + * objects. + * + * u32 + */ + +/** + * + * @this_port: + * @port_index: + * + * + */ +void scic_sds_port_construct( + struct scic_sds_port *this_port, + u8 port_index, + struct scic_sds_controller *owning_controller) +{ + u32 index; + + sci_base_port_construct( + &this_port->parent, + scic_sds_port_state_table + ); + + sci_base_state_machine_construct( + scic_sds_port_get_ready_substate_machine(this_port), + &this_port->parent.parent, + scic_sds_port_ready_substate_table, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING + ); + + this_port->logical_port_index = SCIC_SDS_DUMMY_PORT; + this_port->physical_port_index = port_index; + this_port->active_phy_mask = 0; + + this_port->owning_controller = owning_controller; + + this_port->started_request_count = 0; + this_port->assigned_device_count = 0; + + this_port->timer_handle = SCI_INVALID_HANDLE; + + this_port->transport_layer_registers = NULL; + this_port->port_task_scheduler_registers = NULL; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + this_port->phy_table[index] = NULL; + } +} + +/** + * This method performs initialization of the supplied port. Initialization + * includes: - state machine initialization - member variable initialization + * - configuring the phy_mask + * @this_port: + * @transport_layer_registers: + * @port_task_scheduler_registers: + * @port_configuration_regsiter: + * + * enum sci_status SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned + * if the phy being added to the port + */ +enum sci_status scic_sds_port_initialize( + struct scic_sds_port *this_port, + void *transport_layer_registers, + void *port_task_scheduler_registers, + void *port_configuration_regsiter, + void *viit_registers) +{ + u32 tl_control; + + this_port->transport_layer_registers = transport_layer_registers; + this_port->port_task_scheduler_registers = port_task_scheduler_registers; + this_port->port_pe_configuration_register = port_configuration_regsiter; + this_port->viit_registers = viit_registers; + + scic_sds_port_set_direct_attached_device_id( + this_port, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX + ); + + /* + * Hardware team recommends that we enable the STP prefetch + * for all ports */ + tl_control = SCU_TLCR_READ(this_port); + tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); + SCU_TLCR_WRITE(this_port, tl_control); + + /* + * If this is not the dummy port make the assignment of + * the timer and start the state machine */ + if (this_port->physical_port_index != SCI_MAX_PORTS) { + /* / @todo should we create the timer at create time? */ + this_port->timer_handle = scic_cb_timer_create( + scic_sds_port_get_controller(this_port), + scic_sds_port_timeout_handler, + this_port + ); + + } else { + /* + * Force the dummy port into a condition where it rejects all requests + * as its in an invalid state for any operation. + * / @todo should we set a set of specical handlers for the dummy port? */ + scic_sds_port_set_base_state_handlers( + this_port, SCI_BASE_PORT_STATE_STOPPED + ); + } + + return SCI_SUCCESS; +} + +/** + * + * @this_port: This is the struct scic_sds_port object for which has a phy that has + * gone link up. + * @the_phy: This is the struct scic_sds_phy object that has gone link up. + * @do_notify_user: This parameter specifies whether to inform the user (via + * scic_cb_port_link_up()) as to the fact that a new phy as become ready. + * + * This method is the a general link up handler for the struct scic_sds_port object. + * This function will determine if this struct scic_sds_phy can be assigned to this + * struct scic_sds_port object. If the struct scic_sds_phy object can is not a valid PHY for + * this port then the function will notify the SCIC_USER. A PHY can only be + * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in + * the same port. none + */ +void scic_sds_port_general_link_up_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy, + bool do_notify_user) +{ + struct sci_sas_address port_sas_address; + struct sci_sas_address phy_sas_address; + + scic_sds_port_get_attached_sas_address(this_port, &port_sas_address); + scic_sds_phy_get_attached_sas_address(the_phy, &phy_sas_address); + + /* + * If the SAS address of the new phy matches the SAS address of + * other phys in the port OR this is the first phy in the port, + * then activate the phy and allow it to be used for operations + * in this port. */ + if ( + ( + (phy_sas_address.high == port_sas_address.high) + && (phy_sas_address.low == port_sas_address.low) + ) + || (this_port->active_phy_mask == 0) + ) { + scic_sds_port_activate_phy(this_port, the_phy, do_notify_user); + + if (this_port->parent.state_machine.current_state_id + == SCI_BASE_PORT_STATE_RESETTING) { + sci_base_state_machine_change_state( + &this_port->parent.state_machine, SCI_BASE_PORT_STATE_READY + ); + } + } else { + scic_sds_port_invalid_link_up(this_port, the_phy); + } +} + + +enum sci_status scic_port_start(struct scic_sds_port *port) +{ + return port->state_handlers->parent.start_handler(&port->parent); +} + + +enum sci_status scic_port_stop(struct scic_sds_port *port) +{ + return port->state_handlers->parent.stop_handler(&port->parent); +} + + +enum sci_status scic_port_get_properties( + struct scic_sds_port *port, + struct scic_port_properties *prop) +{ + if ((port == SCI_INVALID_HANDLE) || + (port->logical_port_index == SCIC_SDS_DUMMY_PORT)) + return SCI_FAILURE_INVALID_PORT; + + prop->index = port->logical_port_index; + prop->phy_mask = scic_sds_port_get_phys(port); + scic_sds_port_get_sas_address(port, &prop->local.sas_address); + scic_sds_port_get_protocols(port, &prop->local.protocols); + scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address); + scic_sds_port_get_attached_protocols(port, &prop->remote.protocols); + + return SCI_SUCCESS; +} + + +enum sci_status scic_port_hard_reset( + struct scic_sds_port *port, + u32 reset_timeout) +{ + return port->state_handlers->parent.reset_handler( + &port->parent, reset_timeout); +} + +/** + * + * @this_port: The port for which the direct attached device id is to be + * assigned. + * + * This method assigns the direct attached device ID for this port. + */ +void scic_sds_port_set_direct_attached_device_id( + struct scic_sds_port *this_port, + u32 device_id) +{ + u32 tl_control; + + SCU_STPTLDARNI_WRITE(this_port, device_id); + + /* + * The read should guarntee that the first write gets posted + * before the next write */ + tl_control = SCU_TLCR_READ(this_port); + tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); + SCU_TLCR_WRITE(this_port, tl_control); +} + + +/** + * + * @this_port: This is the port on which the phy should be enabled. + * @the_phy: This is the specific phy which to enable. + * @do_notify_user: This parameter specifies whether to inform the user (via + * scic_cb_port_link_up()) as to the fact that a new phy as become ready. + * + * This method will activate the phy in the port. Activation includes: - adding + * the phy to the port - enabling the Protocol Engine in the silicon. - + * notifying the user that the link is up. none + */ +void scic_sds_port_activate_phy( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy, + bool do_notify_user) +{ + struct scic_sds_controller *controller; + struct sci_sas_identify_address_frame_protocols protocols; + + controller = scic_sds_port_get_controller(this_port); + scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols); + + /* If this is sata port then the phy has already been resumed */ + if (!protocols.u.bits.stp_target) { + scic_sds_phy_resume(the_phy); + } + + this_port->active_phy_mask |= 1 << the_phy->phy_index; + + scic_sds_controller_clear_invalid_phy(controller, the_phy); + + if (do_notify_user == true) + scic_cb_port_link_up(this_port->owning_controller, this_port, the_phy); +} + +/** + * + * @this_port: This is the port on which the phy should be deactivated. + * @the_phy: This is the specific phy that is no longer active in the port. + * @do_notify_user: This parameter specifies whether to inform the user (via + * scic_cb_port_link_down()) as to the fact that a new phy as become ready. + * + * This method will deactivate the supplied phy in the port. none + */ +void scic_sds_port_deactivate_phy( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy, + bool do_notify_user) +{ + this_port->active_phy_mask &= ~(1 << the_phy->phy_index); + + the_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; + + /* Re-assign the phy back to the LP as if it were a narrow port */ + SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index); + + if (do_notify_user == true) + scic_cb_port_link_down(this_port->owning_controller, this_port, the_phy); +} + +/** + * + * @this_port: This is the port on which the phy should be disabled. + * @the_phy: This is the specific phy which to disabled. + * + * This method will disable the phy and report that the phy is not valid for + * this port object. None + */ +static void scic_sds_port_invalid_link_up( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + struct scic_sds_controller *controller = scic_sds_port_get_controller(this_port); + + /* + * Check to see if we have alreay reported this link as bad and if not go + * ahead and tell the SCI_USER that we have discovered an invalid link. */ + if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0) { + scic_sds_controller_set_invalid_phy(controller, the_phy); + + scic_cb_port_invalid_link_up(controller, this_port, the_phy); + } +} + +/** + * This method returns false if the port only has a single phy object assigned. + * If there are no phys or more than one phy then the method will return + * true. + * @this_port: The port for which the wide port condition is to be checked. + * + * bool true Is returned if this is a wide ported port. false Is returned if + * this is a narrow port. + */ +static bool scic_sds_port_is_wide(struct scic_sds_port *this_port) +{ + u32 index; + u32 phy_count = 0; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (this_port->phy_table[index] != NULL) { + phy_count++; + } + } + + return phy_count != 1; +} + +/** + * This method is called by the PHY object when the link is detected. if the + * port wants the PHY to continue on to the link up state then the port + * layer must return true. If the port object returns false the phy object + * must halt its attempt to go link up. + * @this_port: The port associated with the phy object. + * @the_phy: The phy object that is trying to go link up. + * + * true if the phy object can continue to the link up condition. true Is + * returned if this phy can continue to the ready state. false Is returned if + * can not continue on to the ready state. This notification is in place for + * wide ports and direct attached phys. Since there are no wide ported SATA + * devices this could become an invalid port configuration. + */ +bool scic_sds_port_link_detected( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + struct sci_sas_identify_address_frame_protocols protocols; + + scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols); + + if ( + (this_port->logical_port_index != SCIC_SDS_DUMMY_PORT) + && (protocols.u.bits.stp_target) + && scic_sds_port_is_wide(this_port) + ) { + scic_sds_port_invalid_link_up(this_port, the_phy); + + return false; + } + + return true; +} + +/** + * This method is the entry point for the phy to inform the port that it is now + * in a ready state + * @this_port: + * + * + */ +void scic_sds_port_link_up( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + the_phy->is_in_link_training = false; + + this_port->state_handlers->link_up_handler(this_port, the_phy); +} + +/** + * This method is the entry point for the phy to inform the port that it is no + * longer in a ready state + * @this_port: + * + * + */ +void scic_sds_port_link_down( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + this_port->state_handlers->link_down_handler(this_port, the_phy); +} + +/** + * This method is called to start an IO request on this port. + * @this_port: + * @the_device: + * @the_io_request: + * + * enum sci_status + */ +enum sci_status scic_sds_port_start_io( + struct scic_sds_port *this_port, + struct scic_sds_remote_device *the_device, + struct scic_sds_request *the_io_request) +{ + return this_port->state_handlers->start_io_handler( + this_port, the_device, the_io_request); +} + +/** + * This method is called to complete an IO request to the port. + * @this_port: + * @the_device: + * @the_io_request: + * + * enum sci_status + */ +enum sci_status scic_sds_port_complete_io( + struct scic_sds_port *this_port, + struct scic_sds_remote_device *the_device, + struct scic_sds_request *the_io_request) +{ + return this_port->state_handlers->complete_io_handler( + this_port, the_device, the_io_request); +} + +/** + * This method is provided to timeout requests for port operations. Mostly its + * for the port reset operation. + * + * + */ +static void scic_sds_port_timeout_handler(void *port) +{ + struct scic_sds_port *this_port = port; + u32 current_state; + + current_state = sci_base_state_machine_get_state( + &this_port->parent.state_machine); + + if (current_state == SCI_BASE_PORT_STATE_RESETTING) { + /* + * if the port is still in the resetting state then the timeout fired + * before the reset completed. */ + sci_base_state_machine_change_state( + &this_port->parent.state_machine, + SCI_BASE_PORT_STATE_FAILED + ); + } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { + /* + * if the port is stopped then the start request failed + * In this case stay in the stopped state. */ + dev_err(sciport_to_dev(this_port), + "%s: SCIC Port 0x%p failed to stop before tiemout.\n", + __func__, + this_port); + } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { + /* if the port is still stopping then the stop has not completed */ + scic_cb_port_stop_complete( + scic_sds_port_get_controller(this_port), + port, + SCI_FAILURE_TIMEOUT + ); + } else { + /* + * The port is in the ready state and we have a timer reporting a timeout + * this should not happen. */ + dev_err(sciport_to_dev(this_port), + "%s: SCIC Port 0x%p is processing a timeout operation " + "in state %d.\n", + __func__, + this_port, + current_state); + } +} + +/* --------------------------------------------------------------------------- */ + +#ifdef SCIC_DEBUG_ENABLED +void scic_sds_port_decrement_request_count(struct scic_sds_port *this_port) +{ + if (this_port->started_request_count == 0) + dev_warn(sciport_to_dev(this_port), + __func__, + "%s: SCIC Port object requested to decrement started " + "io count past zero.\n"); + else + this_port->started_request_count--; +} +#endif + +/** + * This function updates the hardwares VIIT entry for this port. + * + * + */ +void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port) +{ + struct sci_sas_address sas_address; + + scic_sds_port_get_sas_address(this_port, &sas_address); + + scu_port_viit_register_write( + this_port, initiator_sas_address_hi, sas_address.high); + + scu_port_viit_register_write( + this_port, initiator_sas_address_lo, sas_address.low); + + /* This value get cleared just in case its not already cleared */ + scu_port_viit_register_write( + this_port, reserved, 0); + + /* We are required to update the status register last */ + scu_port_viit_register_write( + this_port, status, ( + SCU_VIIT_ENTRY_ID_VIIT + | SCU_VIIT_IPPT_INITIATOR + | ((1 << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) + | SCU_VIIT_STATUS_ALL_VALID + ) + ); +} + +/** + * This method returns the maximum allowed speed for data transfers on this + * port. This maximum allowed speed evaluates to the maximum speed of the + * slowest phy in the port. + * @this_port: This parameter specifies the port for which to retrieve the + * maximum allowed speed. + * + * This method returns the maximum negotiated speed of the slowest phy in the + * port. + */ +enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( + struct scic_sds_port *this_port) +{ + u16 index = 0; + enum sci_sas_link_rate max_allowed_speed = SCI_SAS_600_GB; + struct scic_sds_phy *phy = NULL; + + /* + * Loop through all of the phys in this port and find the phy with the + * lowest maximum link rate. */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + phy = this_port->phy_table[index]; + if ( + (phy != NULL) + && (scic_sds_port_active_phy(this_port, phy) == true) + && (phy->max_negotiated_speed < max_allowed_speed) + ) + max_allowed_speed = phy->max_negotiated_speed; + } + + return max_allowed_speed; +} + + +/** + * This method passes the event to core user. + * @this_port: The port that a BCN happens. + * @this_phy: The phy that receives BCN. + * + */ +void scic_sds_port_broadcast_change_received( + struct scic_sds_port *this_port, + struct scic_sds_phy *this_phy) +{ + /* notify the user. */ + scic_cb_port_bc_change_primitive_received( + this_port->owning_controller, this_port, this_phy + ); +} + + +/** + * This API methhod enables the broadcast change notification from underneath + * hardware. + * @this_port: The port that a BCN had been disabled from. + * + */ +void scic_port_enable_broadcast_change_notification( + struct scic_sds_port *port) +{ + struct scic_sds_phy *phy; + u32 register_value; + u8 index; + + /* Loop through all of the phys to enable BCN. */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + phy = port->phy_table[index]; + if (phy != NULL) { + register_value = SCU_SAS_LLCTL_READ(phy); + + /* clear the bit by writing 1. */ + SCU_SAS_LLCTL_WRITE(phy, register_value); + } + } +} + +/* + * **************************************************************************** + * * READY SUBSTATE HANDLERS + * **************************************************************************** */ + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This method is the general ready state stop handler for the struct scic_sds_port + * object. This function will transition the ready substate machine to its + * final state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_ready_substate_stop_handler( + struct sci_base_port *port) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + + sci_base_state_machine_change_state( + &this_port->parent.state_machine, + SCI_BASE_PORT_STATE_STOPPING + ); + + return SCI_SUCCESS; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * @device: This is the struct sci_base_remote_device object which is not used in this + * function. + * @io_request: This is the struct sci_base_request object which is not used in this + * function. + * + * This method is the general ready substate complete io handler for the + * struct scic_sds_port object. This function decrments the outstanding request count + * for this port object. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_ready_substate_complete_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + + scic_sds_port_decrement_request_count(this_port); + + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_port_ready_substate_add_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; + enum sci_status status; + + status = scic_sds_port_set_phy(this_port, this_phy); + + if (status == SCI_SUCCESS) { + scic_sds_port_general_link_up_handler(this_port, this_phy, true); + + this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + + sci_base_state_machine_change_state( + &this_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + } + + return status; +} + + +static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; + enum sci_status status; + + status = scic_sds_port_clear_phy(this_port, this_phy); + + if (status == SCI_SUCCESS) { + scic_sds_port_deactivate_phy(this_port, this_phy, true); + + this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + + sci_base_state_machine_change_state( + &this_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + } + + return status; +} + +/* + * **************************************************************************** + * * READY SUBSTATE WAITING HANDLERS + * **************************************************************************** */ + +/** + * + * @this_port: This is the struct scic_sds_port object that which has a phy that has + * gone link up. + * @the_phy: This is the struct scic_sds_phy object that has gone link up. + * + * This method is the ready waiting substate link up handler for the + * struct scic_sds_port object. This methos will report the link up condition for + * this port and will transition to the ready operational substate. none + */ +static void scic_sds_port_ready_waiting_substate_link_up_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + /* + * Since this is the first phy going link up for the port we can just enable + * it and continue. */ + scic_sds_port_activate_phy(this_port, the_phy, true); + + sci_base_state_machine_change_state( + &this_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL + ); +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * @device: This is the struct sci_base_remote_device object which is not used in this + * request. + * @io_request: This is the struct sci_base_request object which is not used in this + * function. + * + * This method is the ready waiting substate start io handler for the + * struct scic_sds_port object. The port object can not accept new requests so the + * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + return SCI_FAILURE_INVALID_STATE; +} + +/* + * **************************************************************************** + * * READY SUBSTATE OPERATIONAL HANDLERS + * **************************************************************************** */ + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * @timeout: This is the timeout for the reset request to complete. + * + * This method will casue the port to reset. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_ready_operational_substate_reset_handler( + struct sci_base_port *port, + u32 timeout) +{ + enum sci_status status = SCI_FAILURE_INVALID_PHY; + u32 phy_index; + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + struct scic_sds_phy *selected_phy = SCI_INVALID_HANDLE; + + + /* Select a phy on which we can send the hard reset request. */ + for ( + phy_index = 0; + (phy_index < SCI_MAX_PHYS) + && (selected_phy == SCI_INVALID_HANDLE); + phy_index++ + ) { + selected_phy = this_port->phy_table[phy_index]; + + if ( + (selected_phy != SCI_INVALID_HANDLE) + && !scic_sds_port_active_phy(this_port, selected_phy) + ) { + /* We found a phy but it is not ready select different phy */ + selected_phy = SCI_INVALID_HANDLE; + } + } + + /* If we have a phy then go ahead and start the reset procedure */ + if (selected_phy != SCI_INVALID_HANDLE) { + status = scic_sds_phy_reset(selected_phy); + + if (status == SCI_SUCCESS) { + scic_cb_timer_start( + scic_sds_port_get_controller(this_port), + this_port->timer_handle, + timeout + ); + + this_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; + + sci_base_state_machine_change_state( + &this_port->parent.state_machine, + SCI_BASE_PORT_STATE_RESETTING + ); + } + } + + return status; +} + +/** + * scic_sds_port_ready_operational_substate_link_up_handler() - + * @this_port: This is the struct scic_sds_port object that which has a phy that has + * gone link up. + * @the_phy: This is the struct scic_sds_phy object that has gone link up. + * + * This method is the ready operational substate link up handler for the + * struct scic_sds_port object. This function notifies the SCI User that the phy has + * gone link up. none + */ +static void scic_sds_port_ready_operational_substate_link_up_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + scic_sds_port_general_link_up_handler(this_port, the_phy, true); +} + +/** + * scic_sds_port_ready_operational_substate_link_down_handler() - + * @this_port: This is the struct scic_sds_port object that which has a phy that has + * gone link down. + * @the_phy: This is the struct scic_sds_phy object that has gone link down. + * + * This method is the ready operational substate link down handler for the + * struct scic_sds_port object. This function notifies the SCI User that the phy has + * gone link down and if this is the last phy in the port the port will change + * state to the ready waiting substate. none + */ +static void scic_sds_port_ready_operational_substate_link_down_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy) +{ + scic_sds_port_deactivate_phy(this_port, the_phy, true); + + /* + * If there are no active phys left in the port, then transition + * the port to the WAITING state until such time as a phy goes + * link up. */ + if (this_port->active_phy_mask == 0) { + sci_base_state_machine_change_state( + scic_sds_port_get_ready_substate_machine(this_port), + SCIC_SDS_PORT_READY_SUBSTATE_WAITING + ); + } +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * @device: This is the struct sci_base_remote_device object which is not used in this + * function. + * @io_request: This is the struct sci_base_request object which is not used in this + * function. + * + * This method is the ready operational substate start io handler for the + * struct scic_sds_port object. This function incremetns the outstanding request + * count for this port object. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + + scic_sds_port_increment_request_count(this_port); + + return SCI_SUCCESS; +} + +/* + * **************************************************************************** + * * READY SUBSTATE OPERATIONAL HANDLERS + * **************************************************************************** */ + +/** + * scic_sds_port_ready_configuring_substate_add_phy_handler() - + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port add phy request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; + enum sci_status status; + + status = scic_sds_port_set_phy(this_port, this_phy); + + if (status == SCI_SUCCESS) { + scic_sds_port_general_link_up_handler(this_port, this_phy, true); + + /* + * Re-enter the configuring state since this may be the last phy in + * the port. */ + sci_base_state_machine_change_state( + &this_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + } + + return status; +} + +/** + * scic_sds_port_ready_configuring_substate_remove_phy_handler() - + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port remove phy request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; + enum sci_status status; + + status = scic_sds_port_clear_phy(this_port, this_phy); + + if (status == SCI_SUCCESS) { + scic_sds_port_deactivate_phy(this_port, this_phy, true); + + /* + * Re-enter the configuring state since this may be the last phy in + * the port. */ + sci_base_state_machine_change_state( + &this_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + } + + return status; +} + +/** + * scic_sds_port_ready_configuring_substate_complete_io_handler() - + * @port: This is the port that is being requested to complete the io request. + * @device: This is the device on which the io is completing. + * + * This method will decrement the outstanding request count for this port. If + * the request count goes to 0 then the port can be reprogrammed with its new + * phy data. + */ +static enum sci_status scic_sds_port_ready_configuring_substate_complete_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + scic_sds_port_decrement_request_count(port); + + if (port->started_request_count == 0) { + sci_base_state_machine_change_state( + &port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL + ); + } + + return SCI_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_port_state_handler +scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = +{ + /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */ + { + { + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_ready_substate_add_phy_handler, + scic_sds_port_default_remove_phy_handler + }, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_ready_waiting_substate_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_ready_waiting_substate_start_io_handler, + scic_sds_port_ready_substate_complete_io_handler, + }, + /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */ + { + { + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_ready_operational_substate_reset_handler, + scic_sds_port_ready_substate_add_phy_handler, + scic_sds_port_ready_substate_remove_phy_handler + }, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_ready_operational_substate_link_up_handler, + scic_sds_port_ready_operational_substate_link_down_handler, + scic_sds_port_ready_operational_substate_start_io_handler, + scic_sds_port_ready_substate_complete_io_handler + }, + /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */ + { + { + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_ready_configuring_substate_add_phy_handler, + scic_sds_port_ready_configuring_substate_remove_phy_handler + }, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_ready_configuring_substate_complete_io_handler + } +}; + + +/** + * scic_sds_port_set_ready_state_handlers() - + * + * This macro sets the port ready substate handlers. + */ +#define scic_sds_port_set_ready_state_handlers(port, state_id) \ + scic_sds_port_set_state_handlers(\ + port, &scic_sds_port_ready_substate_handler_table[(state_id)] \ + ) + +/* + * ****************************************************************************** + * * PORT STATE PRIVATE METHODS + * ****************************************************************************** */ + +/** + * + * @this_port: This is the struct scic_sds_port object to suspend. + * + * This method will susped the port task scheduler for this port object. none + */ +static void scic_sds_port_suspend_port_task_scheduler( + struct scic_sds_port *this_port) +{ + u32 pts_control_value; + u32 tl_control_value; + + pts_control_value = scu_port_task_scheduler_read(this_port, control); + tl_control_value = scu_transport_layer_read(this_port, control); + + pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND); + tl_control_value |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); + + scu_port_task_scheduler_write(this_port, control, pts_control_value); + scu_transport_layer_write(this_port, control, tl_control_value); +} + +/** + * + * @this_port: This is the struct scic_sds_port object to resume. + * + * This method will resume the port task scheduler for this port object. none + */ +static void scic_sds_port_resume_port_task_scheduler( + struct scic_sds_port *this_port) +{ + u32 pts_control_value; + + pts_control_value = scu_port_task_scheduler_read(this_port, control); + + pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND); + + scu_port_task_scheduler_write(this_port, control, pts_control_value); +} + +/* + * ****************************************************************************** + * * PORT READY SUBSTATE METHODS + * ****************************************************************************** */ + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the + * port for any ready phys. If there is at least one phy in a ready state then + * the port transitions to the ready operational substate. none + */ +static void scic_sds_port_ready_substate_waiting_enter( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)object; + + scic_sds_port_set_ready_state_handlers( + this_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING + ); + + scic_sds_port_suspend_port_task_scheduler(this_port); + + this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; + + if (this_port->active_phy_mask != 0) { + /* At least one of the phys on the port is ready */ + sci_base_state_machine_change_state( + &this_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL + ); + } +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets + * the state handlers for the port object, notifies the SCI User that the port + * is ready, and resumes port operations. none + */ +static void scic_sds_port_ready_substate_operational_enter( + struct sci_base_object *object) +{ + u32 index; + struct scic_sds_port *this_port = (struct scic_sds_port *)object; + + scic_sds_port_set_ready_state_handlers( + this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL + ); + + scic_cb_port_ready( + scic_sds_port_get_controller(this_port), this_port + ); + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (this_port->phy_table[index] != NULL) { + scic_sds_port_write_phy_assignment( + this_port, this_port->phy_table[index] + ); + } + } + + scic_sds_port_update_viit_entry(this_port); + + scic_sds_port_resume_port_task_scheduler(this_port); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports + * the port not ready and suspends the port task scheduler. none + */ +static void scic_sds_port_ready_substate_operational_exit( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)object; + + scic_cb_port_not_ready( + scic_sds_port_get_controller(this_port), + this_port, + this_port->not_ready_reason + ); +} + +/* + * ****************************************************************************** + * * PORT READY CONFIGURING METHODS + * ****************************************************************************** */ + +/** + * scic_sds_port_ready_substate_configuring_enter() - + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports + * the port not ready and suspends the port task scheduler. none + */ +static void scic_sds_port_ready_substate_configuring_enter( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)object; + + scic_sds_port_set_ready_state_handlers( + this_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + + if (this_port->active_phy_mask == 0) { + scic_cb_port_not_ready( + scic_sds_port_get_controller(this_port), + this_port, + SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS + ); + + sci_base_state_machine_change_state( + &this_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING + ); + } else if (this_port->started_request_count == 0) { + sci_base_state_machine_change_state( + &this_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL + ); + } +} + +static void scic_sds_port_ready_substate_configuring_exit( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)object; + + scic_sds_port_suspend_port_task_scheduler(this_port); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_port_ready_substate_table[] = { + [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { + .enter_state = scic_sds_port_ready_substate_waiting_enter, + }, + [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { + .enter_state = scic_sds_port_ready_substate_operational_enter, + .exit_state = scic_sds_port_ready_substate_operational_exit + }, + [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { + .enter_state = scic_sds_port_ready_substate_configuring_enter, + .exit_state = scic_sds_port_ready_substate_configuring_exit + }, +}; + +/* + * *************************************************************************** + * * DEFAULT HANDLERS + * *************************************************************************** */ + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for port a start request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_port_default_start_handler( + struct sci_base_port *port) +{ + struct scic_sds_port *sci_port = (struct scic_sds_port *)port; + + dev_warn(sciport_to_dev(sci_port), + "%s: SCIC Port 0x%p requested to start while in invalid " + "state %d\n", + __func__, + port, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine( + (struct scic_sds_port *)port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port stop request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_default_stop_handler( + struct sci_base_port *port) +{ + struct scic_sds_port *sci_port = (struct scic_sds_port *)port; + + dev_warn(sciport_to_dev(sci_port), + "%s: SCIC Port 0x%p requested to stop while in invalid " + "state %d\n", + __func__, + port, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine( + (struct scic_sds_port *)port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port destruct request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_port_default_destruct_handler( + struct sci_base_port *port) +{ + struct scic_sds_port *sci_port = (struct scic_sds_port *)port; + + dev_warn(sciport_to_dev(sci_port), + "%s: SCIC Port 0x%p requested to destruct while in invalid " + "state %d\n", + __func__, + port, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine( + (struct scic_sds_port *)port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * @timeout: This is the timeout for the reset request to complete. + * + * This is the default method for a port reset request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_port_default_reset_handler( + struct sci_base_port *port, + u32 timeout) +{ + struct scic_sds_port *sci_port = (struct scic_sds_port *)port; + + dev_warn(sciport_to_dev(sci_port), + "%s: SCIC Port 0x%p requested to reset while in invalid " + "state %d\n", + __func__, + port, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine( + (struct scic_sds_port *)port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port add phy request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_default_add_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy) +{ + struct scic_sds_port *sci_port = (struct scic_sds_port *)port; + + dev_warn(sciport_to_dev(sci_port), + "%s: SCIC Port 0x%p requested to add phy 0x%p while in " + "invalid state %d\n", + __func__, + port, + phy, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine( + (struct scic_sds_port *)port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port remove phy request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_port_default_remove_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy) +{ + struct scic_sds_port *sci_port = (struct scic_sds_port *)port; + + dev_warn(sciport_to_dev(sci_port), + "%s: SCIC Port 0x%p requested to remove phy 0x%p while in " + "invalid state %d\n", + __func__, + port, + phy, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine( + (struct scic_sds_port *)port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port unsolicited frame request. It will + * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even + * possible to receive an unsolicited frame directed to a port object? It + * seems possible if we implementing virtual functions but until then? + */ +enum sci_status scic_sds_port_default_frame_handler( + struct scic_sds_port *port, + u32 frame_index) +{ + dev_warn(sciport_to_dev(port), + "%s: SCIC Port 0x%p requested to process frame %d while in " + "invalid state %d\n", + __func__, + port, + frame_index, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine(port))); + + scic_sds_controller_release_frame( + scic_sds_port_get_controller(port), frame_index + ); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port event request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_port_default_event_handler( + struct scic_sds_port *port, + u32 event_code) +{ + dev_warn(sciport_to_dev(port), + "%s: SCIC Port 0x%p requested to process event 0x%x while " + "in invalid state %d\n", + __func__, + port, + event_code, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine( + (struct scic_sds_port *)port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port link up notification. It will report + * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +void scic_sds_port_default_link_up_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy) +{ + dev_warn(sciport_to_dev(this_port), + "%s: SCIC Port 0x%p received link_up notification from phy " + "0x%p while in invalid state %d\n", + __func__, + this_port, + phy, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine(this_port))); +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port link down notification. It will + * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +void scic_sds_port_default_link_down_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy) +{ + dev_warn(sciport_to_dev(this_port), + "%s: SCIC Port 0x%p received link down notification from " + "phy 0x%p while in invalid state %d\n", + __func__, + this_port, + phy, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine(this_port))); +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port start io request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_port_default_start_io_handler( + struct scic_sds_port *this_port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + dev_warn(sciport_to_dev(this_port), + "%s: SCIC Port 0x%p requested to start io request 0x%p " + "while in invalid state %d\n", + __func__, + this_port, + io_request, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine(this_port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port complete io request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_default_complete_io_handler( + struct scic_sds_port *this_port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + dev_warn(sciport_to_dev(this_port), + "%s: SCIC Port 0x%p requested to complete io request 0x%p " + "while in invalid state %d\n", + __func__, + this_port, + io_request, + sci_base_state_machine_get_state( + scic_sds_port_get_base_state_machine(this_port))); + + return SCI_FAILURE_INVALID_STATE; +} + +/* + * **************************************************************************** + * * GENERAL STATE HANDLERS + * **************************************************************************** */ + +/** + * + * @port: This is the struct scic_sds_port object on which the io request count will + * be decremented. + * @device: This is the struct scic_sds_remote_device object to which the io request + * is being directed. This parameter is not required to complete this + * operation. + * @io_request: This is the request that is being completed on this port + * object. This parameter is not required to complete this operation. + * + * This is a general complete io request handler for the struct scic_sds_port object. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_general_complete_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + + scic_sds_port_decrement_request_count(this_port); + + return SCI_SUCCESS; +} + +/* + * **************************************************************************** + * * STOPPED STATE HANDLERS + * **************************************************************************** */ + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This method takes the struct scic_sds_port from a stopped state and attempts to + * start it. To start a port it must have no assiged devices and it must have + * at least one phy assigned to it. If those conditions are met then the port + * can transition to the ready state. enum sci_status + * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This struct scic_sds_port object could + * not be started because the port configuration is not valid. SCI_SUCCESS the + * start request is successful and the struct scic_sds_port object has transitioned to + * the SCI_BASE_PORT_STATE_READY. + */ +static enum sci_status scic_sds_port_stopped_state_start_handler( + struct sci_base_port *port) +{ + u32 phy_mask; + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + + if (this_port->assigned_device_count > 0) { + /* + * / @todo This is a start failure operation because there are still + * / devices assigned to this port. There must be no devices + * / assigned to a port on a start operation. */ + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + phy_mask = scic_sds_port_get_phys(this_port); + + /* + * There are one or more phys assigned to this port. Make sure + * the port's phy mask is in fact legal and supported by the + * silicon. */ + if (scic_sds_port_is_phy_mask_valid(this_port, phy_mask) == true) { + sci_base_state_machine_change_state( + scic_sds_port_get_base_state_machine(this_port), + SCI_BASE_PORT_STATE_READY + ); + + return SCI_SUCCESS; + } + + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This method takes the struct scic_sds_port that is in a stopped state and handles a + * stop request. This function takes no action. enum sci_status SCI_SUCCESS the + * stop request is successful as the struct scic_sds_port object is already stopped. + */ +static enum sci_status scic_sds_port_stopped_state_stop_handler( + struct sci_base_port *port) +{ + /* We are already stopped so there is nothing to do here */ + return SCI_SUCCESS; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This method takes the struct scic_sds_port that is in a stopped state and handles + * the destruct request. The stopped state is the only state in which the + * struct scic_sds_port can be destroyed. This function causes the port object to + * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_stopped_state_destruct_handler( + struct sci_base_port *port) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + + sci_base_state_machine_stop(&this_port->parent.state_machine); + + return SCI_SUCCESS; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This method takes the struct scic_sds_port that is in a stopped state and handles + * the add phy request. In MPC mode the only time a phy can be added to a port + * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status + * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not + * be added to the port. SCI_SUCCESS if the phy is added to the port. + */ +static enum sci_status scic_sds_port_stopped_state_add_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; + struct sci_sas_address port_sas_address; + + /* Read the port assigned SAS Address if there is one */ + scic_sds_port_get_sas_address(this_port, &port_sas_address); + + if (port_sas_address.high != 0 && port_sas_address.low != 0) { + struct sci_sas_address phy_sas_address; + + /* + * Make sure that the PHY SAS Address matches the SAS Address + * for this port. */ + scic_sds_phy_get_sas_address(this_phy, &phy_sas_address); + + if ( + (port_sas_address.high != phy_sas_address.high) + || (port_sas_address.low != phy_sas_address.low) + ) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + } + + return scic_sds_port_set_phy(this_port, this_phy); +} + + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy + * object. + * + * This method takes the struct scic_sds_port that is in a stopped state and handles + * the remove phy request. In MPC mode the only time a phy can be removed from + * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status + * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not + * be added to the port. SCI_SUCCESS if the phy is added to the port. + */ +static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; + + return scic_sds_port_clear_phy(this_port, this_phy); +} + +/* + * **************************************************************************** + * * READY STATE HANDLERS + * **************************************************************************** */ + +/* + * **************************************************************************** + * * RESETTING STATE HANDLERS + * **************************************************************************** */ + +/* + * **************************************************************************** + * * STOPPING STATE HANDLERS + * **************************************************************************** */ + +/** + * + * @port: This is the struct scic_sds_port object on which the io request count will + * be decremented. + * @device: This is the struct scic_sds_remote_device object to which the io request + * is being directed. This parameter is not required to complete this + * operation. + * @io_request: This is the request that is being completed on this port + * object. This parameter is not required to complete this operation. + * + * This method takes the struct scic_sds_port that is in a stopping state and handles + * the complete io request. Should the request count reach 0 then the port + * object will transition to the stopped state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_stopping_state_complete_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + + scic_sds_port_decrement_request_count(this_port); + + if (this_port->started_request_count == 0) { + sci_base_state_machine_change_state( + scic_sds_port_get_base_state_machine(this_port), + SCI_BASE_PORT_STATE_STOPPED + ); + } + + return SCI_SUCCESS; +} + +/* + * **************************************************************************** + * * RESETTING STATE HANDLERS + * **************************************************************************** */ + +/** + * + * @port: This is the port object which is being requested to stop. + * + * This method will stop a failed port. This causes a transition to the + * stopping state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_reset_state_stop_handler( + struct sci_base_port *port) +{ + struct scic_sds_port *this_port = (struct scic_sds_port *)port; + + sci_base_state_machine_change_state( + &this_port->parent.state_machine, + SCI_BASE_PORT_STATE_STOPPING + ); + + return SCI_SUCCESS; +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This method will transition a failed port to its ready state. The port + * failed because a hard reset request timed out but at some time later one or + * more phys in the port became ready. enum sci_status SCI_SUCCESS + */ +static void scic_sds_port_reset_state_link_up_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy) +{ + /* + * / @todo We should make sure that the phy that has gone link up is the same + * / one on which we sent the reset. It is possible that the phy on + * / which we sent the reset is not the one that has gone link up and we + * / want to make sure that phy being reset comes back. Consider the + * / case where a reset is sent but before the hardware processes the + * / reset it get a link up on the port because of a hot plug event. + * / because of the reset request this phy will go link down almost + * / immediately. */ + + /* + * In the resetting state we don't notify the user regarding + * link up and link down notifications. */ + scic_sds_port_general_link_up_handler(this_port, phy, false); +} + +/** + * + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This method process link down notifications that occur during a port reset + * operation. Link downs can occur during the reset operation. enum sci_status + * SCI_SUCCESS + */ +static void scic_sds_port_reset_state_link_down_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy) +{ + /* + * In the resetting state we don't notify the user regarding + * link up and link down notifications. */ + scic_sds_port_deactivate_phy(this_port, phy, false); +} + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_port_state_handler +scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = +{ + /* SCI_BASE_PORT_STATE_STOPPED */ + { + { + scic_sds_port_stopped_state_start_handler, + scic_sds_port_stopped_state_stop_handler, + scic_sds_port_stopped_state_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_stopped_state_add_phy_handler, + scic_sds_port_stopped_state_remove_phy_handler + }, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_default_complete_io_handler + }, + /* SCI_BASE_PORT_STATE_STOPPING */ + { + { + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler + }, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_stopping_state_complete_io_handler + }, + /* SCI_BASE_PORT_STATE_READY */ + { + { + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler + }, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_general_complete_io_handler + }, + /* SCI_BASE_PORT_STATE_RESETTING */ + { + { + scic_sds_port_default_start_handler, + scic_sds_port_reset_state_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler + }, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_reset_state_link_up_handler, + scic_sds_port_reset_state_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_general_complete_io_handler + }, + /* SCI_BASE_PORT_STATE_FAILED */ + { + { + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler + }, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_general_complete_io_handler + } +}; + +/* + * ****************************************************************************** + * * PORT STATE PRIVATE METHODS + * ****************************************************************************** */ + +/** + * + * @this_port: This is the port object which to suspend. + * + * This method will enable the SCU Port Task Scheduler for this port object but + * will leave the port task scheduler in a suspended state. none + */ +static void scic_sds_port_enable_port_task_scheduler( + struct scic_sds_port *this_port) +{ + u32 pts_control_value; + + pts_control_value = scu_port_task_scheduler_read(this_port, control); + + pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND); + + scu_port_task_scheduler_write(this_port, control, pts_control_value); +} + +/** + * + * @this_port: This is the port object which to resume. + * + * This method will disable the SCU port task scheduler for this port object. + * none + */ +static void scic_sds_port_disable_port_task_scheduler( + struct scic_sds_port *this_port) +{ + u32 pts_control_value; + + pts_control_value = scu_port_task_scheduler_read(this_port, control); + + pts_control_value &= ~(SCU_PTSxCR_GEN_BIT(ENABLE) + | SCU_PTSxCR_GEN_BIT(SUSPEND)); + + scu_port_task_scheduler_write(this_port, control, pts_control_value); +} + +/* + * ****************************************************************************** + * * PORT STATE METHODS + * ****************************************************************************** */ + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped + * state handlers for the struct scic_sds_port object and disables the port task + * scheduler in the hardware. none + */ +static void scic_sds_port_stopped_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + scic_sds_port_set_base_state_handlers( + this_port, SCI_BASE_PORT_STATE_STOPPED + ); + + if ( + SCI_BASE_PORT_STATE_STOPPING + == this_port->parent.state_machine.previous_state_id + ) { + /* + * If we enter this state becasuse of a request to stop + * the port then we want to disable the hardwares port + * task scheduler. */ + scic_sds_port_disable_port_task_scheduler(this_port); + } +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware + * port task scheduler. none + */ +static void scic_sds_port_stopped_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + /* Enable and suspend the port task scheduler */ + scic_sds_port_enable_port_task_scheduler(this_port); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state + * handlers for the struct scic_sds_port object, reports the port object as not ready + * and starts the ready substate machine. none + */ +static void scic_sds_port_ready_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + /* Put the ready state handlers in place though they will not be there long */ + scic_sds_port_set_base_state_handlers( + this_port, SCI_BASE_PORT_STATE_READY + ); + + if ( + SCI_BASE_PORT_STATE_RESETTING + == this_port->parent.state_machine.previous_state_id + ) { + scic_cb_port_hard_reset_complete( + scic_sds_port_get_controller(this_port), + this_port, + SCI_SUCCESS + ); + } else { + /* Notify the caller that the port is not yet ready */ + scic_cb_port_not_ready( + scic_sds_port_get_controller(this_port), + this_port, + SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS + ); + } + + /* Start the ready substate machine */ + sci_base_state_machine_start( + scic_sds_port_get_ready_substate_machine(this_port) + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCI_BASE_STATE_READY. This function does nothing. none + */ +static void scic_sds_port_ready_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + sci_base_state_machine_stop(&this_port->ready_substate_machine); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting + * state handlers for the struct scic_sds_port object. none + */ +static void scic_sds_port_resetting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + scic_sds_port_set_base_state_handlers( + this_port, SCI_BASE_PORT_STATE_RESETTING + ); + + scic_sds_port_set_direct_attached_device_id( + this_port, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none + */ +static void scic_sds_port_resetting_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + scic_cb_timer_stop( + scic_sds_port_get_controller(this_port), + this_port->timer_handle + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping + * state handlers for the struct scic_sds_port object. none + */ +static void scic_sds_port_stopping_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + scic_sds_port_set_base_state_handlers( + this_port, SCI_BASE_PORT_STATE_STOPPING + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none + */ +static void scic_sds_port_stopping_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + scic_cb_timer_stop( + scic_sds_port_get_controller(this_port), + this_port->timer_handle + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping + * state handlers for the struct scic_sds_port object. none + */ +static void scic_sds_port_failed_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_port *this_port; + + this_port = (struct scic_sds_port *)object; + + scic_sds_port_set_base_state_handlers( + this_port, + SCI_BASE_PORT_STATE_FAILED + ); + + scic_cb_port_hard_reset_complete( + scic_sds_port_get_controller(this_port), + this_port, + SCI_FAILURE_TIMEOUT + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_port_state_table[] = { + [SCI_BASE_PORT_STATE_STOPPED] = { + .enter_state = scic_sds_port_stopped_state_enter, + .exit_state = scic_sds_port_stopped_state_exit + }, + [SCI_BASE_PORT_STATE_STOPPING] = { + .enter_state = scic_sds_port_stopping_state_enter, + .exit_state = scic_sds_port_stopping_state_exit + }, + [SCI_BASE_PORT_STATE_READY] = { + .enter_state = scic_sds_port_ready_state_enter, + .exit_state = scic_sds_port_ready_state_exit + }, + [SCI_BASE_PORT_STATE_RESETTING] = { + .enter_state = scic_sds_port_resetting_state_enter, + .exit_state = scic_sds_port_resetting_state_exit + }, + [SCI_BASE_PORT_STATE_FAILED] = { + .enter_state = scic_sds_port_failed_state_enter, + } +}; + diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h new file mode 100644 index 000000000000..bbb9de5228ed --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -0,0 +1,514 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_PORT_H_ +#define _SCIC_SDS_PORT_H_ + +/** + * This file contains the structures, constants and prototypes for the + * struct scic_sds_port object. + * + * + */ + +#include "sci_controller_constants.h" +#include "intel_sas.h" +#include "sci_base_port.h" +#include "sci_base_phy.h" +#include "scu_registers.h" + +#define SCIC_SDS_DUMMY_PORT 0xFF + +/** + * enum SCIC_SDS_PORT_READY_SUBSTATES - + * + * This enumeration depicts all of the states for the core port ready substate + * machine. + */ +enum SCIC_SDS_PORT_READY_SUBSTATES { + /** + * The substate where the port is started and ready but has no active phys. + */ + SCIC_SDS_PORT_READY_SUBSTATE_WAITING, + + /** + * The substate where the port is started and ready and there is at least one + * phy operational. + */ + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, + + /** + * The substate where the port is started and there was an add/remove phy + * event. This state is only used in Automatic Port Configuration Mode (APC) + */ + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, + + SCIC_SDS_PORT_READY_MAX_SUBSTATES +}; + +struct scic_sds_controller; +struct scic_sds_phy; +struct scic_sds_remote_device; +struct scic_sds_request; + +/** + * struct scic_sds_port - + * + * The core port object provides the the abstraction for an SCU port. + */ +struct scic_sds_port { + /** + * This field is the oommon base port object. + */ + struct sci_base_port parent; + + /** + * This field is the port index that is reported to the SCI USER. This allows + * the actual hardware physical port to change without the SCI USER getting a + * different answer for the get port index. + */ + u8 logical_port_index; + + /** + * This field is the port index used to program the SCU hardware. + */ + u8 physical_port_index; + + /** + * This field contains the active phy mask for the port. This mask is used in + * conjunction with the phy state to determine which phy to select for some + * port operations. + */ + u8 active_phy_mask; + + /** + * This field contains the count of the io requests started on this port + * object. It is used to control controller shutdown. + */ + u32 started_request_count; + + /** + * This field contains the number of devices assigned to this port. It is + * used to control port start requests. + */ + u32 assigned_device_count; + + /** + * This field contains the reason for the port not going ready. It is + * assigned in the state handlers and used in the state transition. + */ + u32 not_ready_reason; + + /** + * This field is the table of phys assigned to the port. + */ + struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; + + /** + * This field is a pointer back to the controller that owns this port object. + */ + struct scic_sds_controller *owning_controller; + + /** + * This field contains the port start/stop timer handle. + */ + void *timer_handle; + + /** + * This field points to the current set of state handlers for this port + * object. These state handlers are assigned at each enter state of the state + * machine. + */ + struct scic_sds_port_state_handler *state_handlers; + + /** + * This field is the ready substate machine for the port. + */ + struct sci_base_state_machine ready_substate_machine; + + /* / Memory mapped hardware register space */ + /** + * This field is the pointer to the transport layer register for the SCU + * hardware. + */ + struct scu_transport_layer_registers *transport_layer_registers; + + /** + * This field is the pointer to the port task scheduler registers for the SCU + * hardware. + */ + struct scu_port_task_scheduler_registers *port_task_scheduler_registers; + + /** + * This field is identical for all port objects and points to the port task + * scheduler group PE configuration registers. It is used to assign PEs to a + * port. + */ + SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register; + + /** + * This field is the VIIT register space for ths port object. + */ + struct scu_viit_entry *viit_registers; + +}; + + +typedef enum sci_status (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct scic_sds_port *, u32); + +typedef enum sci_status (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct scic_sds_port *, u32); + +typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct scic_sds_port *, struct scic_sds_phy *); + +typedef enum sci_status (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)( + struct scic_sds_port *, + struct scic_sds_remote_device *, + struct scic_sds_request *); + +struct scic_sds_port_state_handler { + struct sci_base_port_state_handler parent; + + SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler; + SCIC_SDS_PORT_EVENT_HANDLER_T event_handler; + + SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler; + SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler; + + SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler; + SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler; + +}; + +extern const struct sci_base_state scic_sds_port_state_table[]; +extern const struct sci_base_state scic_sds_port_ready_substate_table[]; + +extern struct scic_sds_port_state_handler scic_sds_port_state_handler_table[]; +extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[]; + +/** + * scic_sds_port_get_controller() - + * + * Helper macro to get the owning controller of this port + */ +#define scic_sds_port_get_controller(this_port) \ + ((this_port)->owning_controller) + +/** + * scic_sds_port_get_base_state_machine() - + * + * Helper macro to get the base state machine for this port + */ +#define scic_sds_port_get_base_state_machine(this_port) \ + (&(this_port)->parent.state_machine) + +/** + * scic_sds_port_set_base_state_handlers() - + * + * This macro will change the state handlers to those of the specified state id + */ +#define scic_sds_port_set_base_state_handlers(this_port, state_id) \ + scic_sds_port_set_state_handlers(\ + (this_port), &scic_sds_port_state_handler_table[(state_id)]) + +/** + * scic_sds_port_get_ready_substate_machine() - + * + * Helper macro to get the ready substate machine for this port + */ +#define scic_sds_port_get_ready_substate_machine(this_port) \ + (&(this_port)->ready_substate_machine) + +/** + * scic_sds_port_set_state_handlers() - + * + * Helper macro to set the port object state handlers + */ +#define scic_sds_port_set_state_handlers(this_port, handlers) \ + ((this_port)->state_handlers = (handlers)) + +/** + * scic_sds_port_get_index() - + * + * This macro returns the physical port index for this port object + */ +#define scic_sds_port_get_index(this_port) \ + ((this_port)->physical_port_index) + +/** + * scic_sds_port_increment_request_count() - + * + * Helper macro to increment the started request count + */ +#define scic_sds_port_increment_request_count(this_port) \ + ((this_port)->started_request_count++) + +#ifdef SCIC_DEBUG_ENABLED +/** + * scic_sds_port_decrement_request_count() - This method decrements the started + * io request count. The method will not decrment the started io request + * count below 0 and will log a debug message if this is attempted. + * + * + */ +void scic_sds_port_decrement_request_count( + struct scic_sds_port *this_port); +#else +/** + * scic_sds_port_decrement_request_count() - + * + * Helper macro to decrement the started io request count. The macro will not + * decrement the started io request count below 0. + */ +#define scic_sds_port_decrement_request_count(this_port) \ + (\ + (this_port)->started_request_count = (\ + ((this_port)->started_request_count == 0) ? \ + (this_port)->started_request_count : \ + ((this_port)->started_request_count - 1) \ + ) \ + ) +#endif + +/** + * scic_sds_port_write_phy_assignment() - + * + * Helper macro to write the phys port assignment + */ +#define scic_sds_port_write_phy_assignment(port, phy) \ + SCU_PCSPExCR_WRITE(\ + (port), \ + (phy)->phy_index, \ + (port)->physical_port_index \ + ) + +/** + * scic_sds_port_read_phy_assignment() - + * + * Helper macro to read the phys port assignment + */ +#define scic_sds_port_read_phy_assignment(port, phy) \ + SCU_PCSPExCR_READ(\ + (port), \ + (phy)->phy_index \ + ) + +#define scic_sds_port_active_phy(port, phy) \ + (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) + +/* --------------------------------------------------------------------------- */ + + + + +/* --------------------------------------------------------------------------- */ + +/* --------------------------------------------------------------------------- */ + +void scic_sds_port_construct( + struct scic_sds_port *this_port, + u8 port_index, + struct scic_sds_controller *owning_controller); + +enum sci_status scic_sds_port_initialize( + struct scic_sds_port *this_port, + void *transport_layer_registers, + void *port_task_scheduler_registers, + void *port_configuration_regsiter, + void *viit_registers); + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_sds_port_add_phy( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy); + +enum sci_status scic_sds_port_remove_phy( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy); + +void scic_sds_port_set_direct_attached_device_id( + struct scic_sds_port *this_port, + u32 device_id); + +void scic_sds_port_activate_phy( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy, + bool do_notify_user); + +void scic_sds_port_deactivate_phy( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy, + bool do_notify_user); + + + +void scic_sds_port_general_link_up_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *the_phy, + bool do_notify_user); + +bool scic_sds_port_link_detected( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy); + +void scic_sds_port_link_up( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy); + +void scic_sds_port_link_down( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy); + +/* --------------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_sds_port_start_io( + struct scic_sds_port *this_port, + struct scic_sds_remote_device *the_device, + struct scic_sds_request *the_io_request); + +enum sci_status scic_sds_port_complete_io( + struct scic_sds_port *this_port, + struct scic_sds_remote_device *the_device, + struct scic_sds_request *the_io_request); + +/* --------------------------------------------------------------------------- */ + +void scic_sds_port_update_viit_entry( + struct scic_sds_port *this_port); + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_sds_port_default_start_handler( + struct sci_base_port *port); + + +enum sci_status scic_sds_port_default_destruct_handler( + struct sci_base_port *port); + +enum sci_status scic_sds_port_default_reset_handler( + struct sci_base_port *port, + u32 timeout); + + +enum sci_status scic_sds_port_default_remove_phy_handler( + struct sci_base_port *port, + struct sci_base_phy *phy); + +enum sci_status scic_sds_port_default_frame_handler( + struct scic_sds_port *port, + u32 frame_index); + +enum sci_status scic_sds_port_default_event_handler( + struct scic_sds_port *port, + u32 event_code); + +void scic_sds_port_default_link_up_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy); + +void scic_sds_port_default_link_down_handler( + struct scic_sds_port *this_port, + struct scic_sds_phy *phy); + +enum sci_status scic_sds_port_default_start_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request); + + +enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( + struct scic_sds_port *this_port); + +void scic_sds_port_broadcast_change_received( + struct scic_sds_port *this_port, + struct scic_sds_phy *this_phy); + +bool scic_sds_port_is_valid_phy_assignment( + struct scic_sds_port *this_port, + u32 phy_index); + +bool scic_sds_port_is_phy_mask_valid( + struct scic_sds_port *this_port, + u32 phy_mask); + +u32 scic_sds_port_get_phys( + struct scic_sds_port *this_port); + +void scic_sds_port_get_sas_address( + struct scic_sds_port *this_port, + struct sci_sas_address *sas_address); + +void scic_sds_port_get_attached_sas_address( + struct scic_sds_port *this_port, + struct sci_sas_address *sas_address); + +void scic_sds_port_get_attached_protocols( + struct scic_sds_port *this_port, + struct sci_sas_identify_address_frame_protocols *protocols); + +enum sci_status scic_sds_port_set_phy( + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +enum sci_status scic_sds_port_clear_phy( + struct scic_sds_port *port, + struct scic_sds_phy *phy); + + + +#endif /* _SCIC_SDS_PORT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c new file mode 100644 index 000000000000..37d4469162a7 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -0,0 +1,851 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the implementation for the public and protected methods + * for the port configuration agent. + * + * + */ + +#include "sci_environment.h" +#include "scic_controller.h" +#include "scic_sds_controller.h" +#include "scic_sds_port_configuration_agent.h" + +#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) +#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) +#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100) + +enum SCIC_SDS_APC_ACTIVITY { + SCIC_SDS_APC_SKIP_PHY, + SCIC_SDS_APC_ADD_PHY, + SCIC_SDS_APC_START_TIMER, + + SCIC_SDS_APC_ACTIVITY_MAX +}; + +/* + * ****************************************************************************** + * General port configuration agent routines + * ****************************************************************************** */ + +/** + * + * @address_one: A SAS Address to be compared. + * @address_two: A SAS Address to be compared. + * + * Compare the two SAS Address and if SAS Address One is greater than SAS + * Address Two then return > 0 else if SAS Address One is less than SAS Address + * Two return < 0 Otherwise they are the same return 0 A signed value of x > 0 + * > y where x is returned for Address One > Address Two y is returned for + * Address One < Address Two 0 is returned ofr Address One = Address Two + */ +static s32 sci_sas_address_compare( + struct sci_sas_address address_one, + struct sci_sas_address address_two) +{ + if (address_one.high > address_two.high) { + return 1; + } else if (address_one.high < address_two.high) { + return -1; + } else if (address_one.low > address_two.low) { + return 1; + } else if (address_one.low < address_two.low) { + return -1; + } + + /* The two SAS Address must be identical */ + return 0; +} + +/** + * + * @controller: The controller object used for the port search. + * @phy: The phy object to match. + * + * This routine will find a matching port for the phy. This means that the + * port and phy both have the same broadcast sas address and same received sas + * address. The port address or the SCI_INVALID_HANDLE if there is no matching + * port. port address if the port can be found to match the phy. + * SCI_INVALID_HANDLE if there is no matching port for the phy. + */ +static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( + struct scic_sds_controller *controller, + struct scic_sds_phy *phy) +{ + u8 port_index; + struct scic_sds_port *port_handle; + struct sci_sas_address port_sas_address; + struct sci_sas_address port_attached_device_address; + struct sci_sas_address phy_sas_address; + struct sci_sas_address phy_attached_device_address; + + /* + * Since this phy can be a member of a wide port check to see if one or + * more phys match the sent and received SAS address as this phy in which + * case it should participate in the same port. */ + scic_sds_phy_get_sas_address(phy, &phy_sas_address); + scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); + + for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { + if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS) { + struct scic_sds_port *port = (struct scic_sds_port *)port_handle; + + scic_sds_port_get_sas_address(port, &port_sas_address); + scic_sds_port_get_attached_sas_address(port, &port_attached_device_address); + + if ( + (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0) + && (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) + ) { + return port; + } + } + } + + return SCI_INVALID_HANDLE; +} + +/** + * + * @controller: This is the controller object that contains the port agent + * @port_agent: This is the port configruation agent for the controller. + * + * This routine will validate the port configuration is correct for the SCU + * hardware. The SCU hardware allows for port configurations as follows. LP0 + * -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2, + * PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for + * this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION + * the port configuration is not valid for this port configuration agent. + */ +static enum sci_status scic_sds_port_configuration_agent_validate_ports( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent) +{ + struct sci_sas_address first_address; + struct sci_sas_address second_address; + + /* + * Sanity check the max ranges for all the phys the max index + * is always equal to the port range index */ + if ( + (port_agent->phy_valid_port_range[0].max_index != 0) + || (port_agent->phy_valid_port_range[1].max_index != 1) + || (port_agent->phy_valid_port_range[2].max_index != 2) + || (port_agent->phy_valid_port_range[3].max_index != 3) + ) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + /* + * This is a request to configure a single x4 port or at least attempt + * to make all the phys into a single port */ + if ( + (port_agent->phy_valid_port_range[0].min_index == 0) + && (port_agent->phy_valid_port_range[1].min_index == 0) + && (port_agent->phy_valid_port_range[2].min_index == 0) + && (port_agent->phy_valid_port_range[3].min_index == 0) + ) { + return SCI_SUCCESS; + } + + /* + * This is a degenerate case where phy 1 and phy 2 are assigned + * to the same port this is explicitly disallowed by the hardware + * unless they are part of the same x4 port and this condition was + * already checked above. */ + if (port_agent->phy_valid_port_range[2].min_index == 1) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + /* + * PE0 and PE3 can never have the same SAS Address unless they + * are part of the same x4 wide port and we have already checked + * for this condition. */ + scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address); + scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address); + + if (sci_sas_address_compare(first_address, second_address) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + /* + * PE0 and PE1 are configured into a 2x1 ports make sure that the + * SAS Address for PE0 and PE2 are different since they can not be + * part of the same port. */ + if ( + (port_agent->phy_valid_port_range[0].min_index == 0) + && (port_agent->phy_valid_port_range[1].min_index == 1) + ) { + scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address); + scic_sds_phy_get_sas_address(&controller->phy_table[2], &second_address); + + if (sci_sas_address_compare(first_address, second_address) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + } + + /* + * PE2 and PE3 are configured into a 2x1 ports make sure that the + * SAS Address for PE1 and PE3 are different since they can not be + * part of the same port. */ + if ( + (port_agent->phy_valid_port_range[2].min_index == 2) + && (port_agent->phy_valid_port_range[3].min_index == 3) + ) { + scic_sds_phy_get_sas_address(&controller->phy_table[1], &first_address); + scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address); + + if (sci_sas_address_compare(first_address, second_address) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + } + + return SCI_SUCCESS; +} + +/* + * ****************************************************************************** + * Manual port configuration agent routines + * ****************************************************************************** */ + +/** + * + * + * This routine will verify that all of the phys in the same port are using the + * same SAS address. + */ +static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent) +{ + u32 phy_mask; + u32 assigned_phy_mask; + struct sci_sas_address sas_address; + struct sci_sas_address phy_assigned_address; + u8 port_index; + u8 phy_index; + + assigned_phy_mask = 0; + sas_address.high = 0; + sas_address.low = 0; + + for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { + phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask; + + if (phy_mask != 0) { + /* + * Make sure that one or more of the phys were not already assinged to + * a different port. */ + if ((phy_mask & ~assigned_phy_mask) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + /* Find the starting phy index for this round through the loop */ + for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { + if ((1 << phy_index) & phy_mask) { + scic_sds_phy_get_sas_address( + &controller->phy_table[phy_index], &sas_address + ); + + /* + * The phy_index can be used as the starting point for the + * port range since the hardware starts all logical ports + * the same as the PE index. */ + port_agent->phy_valid_port_range[phy_index].min_index = port_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + + if (phy_index != port_index) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + break; + } + } + + /* + * See how many additional phys are being added to this logical port. + * Note: We have not moved the current phy_index so we will actually + * compare the startting phy with itself. + * This is expected and required to add the phy to the port. */ + while (phy_index < SCI_MAX_PHYS) { + if ((1 << phy_index) & phy_mask) { + scic_sds_phy_get_sas_address( + &controller->phy_table[phy_index], &phy_assigned_address + ); + + if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { + /* + * The phy mask specified that this phy is part of the same port + * as the starting phy and it is not so fail this configuration */ + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + port_agent->phy_valid_port_range[phy_index].min_index = port_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + + scic_sds_port_add_phy( + &controller->port_table[port_index], + &controller->phy_table[phy_index] + ); + + assigned_phy_mask |= (1 << phy_index); + } + + phy_index++; + } + } + } + + return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); +} + +/** + * + * + * This timer routine is used to allow the SCI User to rediscover or change + * device objects before a new series of link up notifications because a link + * down has allowed a better port configuration. + */ +static void scic_sds_mpc_agent_timeout_handler( + void *object) +{ + u8 index; + struct scic_sds_controller *controller = (struct scic_sds_controller *)object; + struct scic_sds_port_configuration_agent *port_agent = &controller->port_agent; + u16 configure_phy_mask; + + port_agent->timer_pending = false; + + /* Find the mask of phys that are reported read but as yet unconfigured into a port */ + configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (configure_phy_mask & (1 << index)) { + port_agent->link_up_handler( + controller, + port_agent, + scic_sds_phy_get_port(&controller->phy_table[index]), + &controller->phy_table[index] + ); + } + } +} + +/** + * + * @controller: This is the controller object that receives the link up + * notification. + * @port: This is the port object associated with the phy. If the is no + * associated port this is an SCI_INVALID_HANDLE. + * @phy: This is the phy object which has gone ready. + * + * This method handles the manual port configuration link up notifications. + * Since all ports and phys are associate at initialization time we just turn + * around and notifiy the port object that there is a link up. If this PHY is + * not associated with a port there is no action taken. Is it possible to get a + * link up notification from a phy that has no assocoated port? + */ +static void scic_sds_mpc_agent_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + /* + * If the port has an invalid handle then the phy was not assigned to + * a port. This is because the phy was not given the same SAS Address + * as the other PHYs in the port. */ + if (port != SCI_INVALID_HANDLE) { + port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); + + scic_sds_port_link_up(port, phy); + + if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0) { + port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy)); + } + } +} + +/** + * + * @controller: This is the controller object that receives the link down + * notification. + * @port: This is the port object associated with the phy. If the is no + * associated port this is an SCI_INVALID_HANDLE. The port is an invalid + * handle only if the phy was never port of this port. This happens when + * the phy is not broadcasting the same SAS address as the other phys in the + * assigned port. + * @phy: This is the phy object which has gone link down. + * + * This method handles the manual port configuration link down notifications. + * Since all ports and phys are associated at initialization time we just turn + * around and notifiy the port object of the link down event. If this PHY is + * not associated with a port there is no action taken. Is it possible to get a + * link down notification from a phy that has no assocoated port? + */ +static void scic_sds_mpc_agent_link_down( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + if (port != SCI_INVALID_HANDLE) { + /* + * If we can form a new port from the remainder of the phys then we want + * to start the timer to allow the SCI User to cleanup old devices and + * rediscover the port before rebuilding the port with the phys that + * remain in the ready state. */ + port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); + port_agent->phy_configured_mask &= ~(1 << scic_sds_phy_get_index(phy)); + + /* + * Check to see if there are more phys waiting to be configured into a port. + * If there are allow the SCI User to tear down this port, if necessary, and + * then reconstruc the port after the timeout. */ + if ( + (port_agent->phy_configured_mask == 0x0000) + && (port_agent->phy_ready_mask != 0x0000) + && !port_agent->timer_pending + ) { + port_agent->timer_pending = true; + + scic_cb_timer_start( + controller, + port_agent->timer, + SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT + ); + } + + scic_sds_port_link_down(port, phy); + } +} + +/* + * ****************************************************************************** + * Automatic port configuration agent routines + * ****************************************************************************** */ + +/** + * + * + * This routine will verify that the phys are assigned a valid SAS address for + * automatic port configuration mode. + */ +static enum sci_status scic_sds_apc_agent_validate_phy_configuration( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent) +{ + u8 phy_index; + u8 port_index; + struct sci_sas_address sas_address; + struct sci_sas_address phy_assigned_address; + + phy_index = 0; + + while (phy_index < SCI_MAX_PHYS) { + port_index = phy_index; + + /* Get the assigned SAS Address for the first PHY on the controller. */ + scic_sds_phy_get_sas_address( + &controller->phy_table[phy_index], &sas_address + ); + + while (++phy_index < SCI_MAX_PHYS) { + scic_sds_phy_get_sas_address( + &controller->phy_table[phy_index], &phy_assigned_address + ); + + /* Verify each of the SAS address are all the same for every PHY */ + if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) { + port_agent->phy_valid_port_range[phy_index].min_index = port_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + } else { + port_agent->phy_valid_port_range[phy_index].min_index = phy_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + break; + } + } + } + + return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); +} + +/** + * + * @controller: This is the controller that to which the port agent is assigned. + * @port_agent: This is the port agent that is requesting the timer start + * operation. + * @phy: This is the phy that has caused the timer operation to be scheduled. + * + * This routine will restart the automatic port configuration timeout timer for + * the next time period. This could be caused by either a link down event or a + * link up event where we can not yet tell to which port a phy belongs. + */ +static void scic_sds_apc_agent_start_timer( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_phy *phy, + u32 timeout) +{ + if (port_agent->timer_pending) { + scic_cb_timer_stop(controller, port_agent->timer); + } + + port_agent->timer_pending = true; + + scic_cb_timer_start(controller, port_agent->timer, timeout); +} + +/** + * + * @controller: This is the controller object that receives the link up + * notification. + * @phy: This is the phy object which has gone link up. + * + * This method handles the automatic port configuration for link up + * notifications. + */ +static void scic_sds_apc_agent_configure_ports( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_phy *phy, + bool start_timer) +{ + u8 port_index; + enum sci_status status; + struct scic_sds_port *port; + struct scic_sds_port *port_handle; + enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; + + port = scic_sds_port_configuration_agent_find_port(controller, phy); + + if (port != SCI_INVALID_HANDLE) { + if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) + apc_activity = SCIC_SDS_APC_ADD_PHY; + else + apc_activity = SCIC_SDS_APC_SKIP_PHY; + } else { + /* + * There is no matching Port for this PHY so lets search through the + * Ports and see if we can add the PHY to its own port or maybe start + * the timer and wait to see if a wider port can be made. + * + * Note the break when we reach the condition of the port id == phy id */ + for ( + port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index; + port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index; + port_index++ + ) { + scic_controller_get_port_handle(controller, port_index, &port_handle); + + port = (struct scic_sds_port *)port_handle; + + /* First we must make sure that this PHY can be added to this Port. */ + if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) { + /* + * Port contains a PHY with a greater PHY ID than the current + * PHY that has gone link up. This phy can not be part of any + * port so skip it and move on. */ + if (port->active_phy_mask > (1 << phy->phy_index)) { + apc_activity = SCIC_SDS_APC_SKIP_PHY; + break; + } + + /* + * We have reached the end of our Port list and have not found + * any reason why we should not either add the PHY to the port + * or wait for more phys to become active. */ + if (port->physical_port_index == phy->phy_index) { + /* + * The Port either has no active PHYs. + * Consider that if the port had any active PHYs we would have + * or active PHYs with + * a lower PHY Id than this PHY. */ + if (apc_activity != SCIC_SDS_APC_START_TIMER) { + apc_activity = SCIC_SDS_APC_ADD_PHY; + } + + break; + } + + /* + * The current Port has no active PHYs and this PHY could be part + * of this Port. Since we dont know as yet setup to start the + * timer and see if there is a better configuration. */ + if (port->active_phy_mask == 0) { + apc_activity = SCIC_SDS_APC_START_TIMER; + } + } else if (port->active_phy_mask != 0) { + /* + * The Port has an active phy and the current Phy can not + * participate in this port so skip the PHY and see if + * there is a better configuration. */ + apc_activity = SCIC_SDS_APC_SKIP_PHY; + } + } + } + + /* + * Check to see if the start timer operations should instead map to an + * add phy operation. This is caused because we have been waiting to + * add a phy to a port but could not becuase the automatic port + * configuration engine had a choice of possible ports for the phy. + * Since we have gone through a timeout we are going to restrict the + * choice to the smallest possible port. */ + if ( + (start_timer == false) + && (apc_activity == SCIC_SDS_APC_START_TIMER) + ) { + apc_activity = SCIC_SDS_APC_ADD_PHY; + } + + switch (apc_activity) { + case SCIC_SDS_APC_ADD_PHY: + status = scic_sds_port_add_phy(port, phy); + + if (status == SCI_SUCCESS) { + port_agent->phy_configured_mask |= (1 << phy->phy_index); + } + break; + + case SCIC_SDS_APC_START_TIMER: + scic_sds_apc_agent_start_timer( + controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION + ); + break; + + case SCIC_SDS_APC_SKIP_PHY: + default: + /* do nothing the PHY can not be made part of a port at this time. */ + break; + } +} + +/** + * + * @controller: This is the controller object that receives the link up + * notification. + * @port: This is the port object associated with the phy. If the is no + * associated port this is an SCI_INVALID_HANDLE. + * @phy: This is the phy object which has gone link up. + * + * This method handles the automatic port configuration for link up + * notifications. Is it possible to get a link down notification from a phy + * that has no assocoated port? + */ +static void scic_sds_apc_agent_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + BUG_ON(port != SCI_INVALID_HANDLE); + + port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); + + scic_sds_apc_agent_configure_ports(controller, port_agent, phy, true); +} + +/** + * + * @controller: This is the controller object that receives the link down + * notification. + * @port: This is the port object associated with the phy. If the is no + * associated port this is an SCI_INVALID_HANDLE. + * @phy: This is the phy object which has gone link down. + * + * This method handles the automatic port configuration link down + * notifications. not associated with a port there is no action taken. Is it + * possible to get a link down notification from a phy that has no assocoated + * port? + */ +static void scic_sds_apc_agent_link_down( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); + + if (port != SCI_INVALID_HANDLE) { + if (port_agent->phy_configured_mask & (1 << phy->phy_index)) { + enum sci_status status; + + status = scic_sds_port_remove_phy(port, phy); + + if (status == SCI_SUCCESS) { + port_agent->phy_configured_mask &= ~(1 << phy->phy_index); + } + } + } +} + +/** + * + * + * This routine will try to configure the phys into ports when the timer fires. + */ +static void scic_sds_apc_agent_timeout_handler( + void *object) +{ + u32 index; + struct scic_sds_port_configuration_agent *port_agent; + struct scic_sds_controller *controller = (struct scic_sds_controller *)object; + u16 configure_phy_mask; + + port_agent = scic_sds_controller_get_port_configuration_agent(controller); + + port_agent->timer_pending = false; + + configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; + + if (configure_phy_mask != 0x00) { + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (configure_phy_mask & (1 << index)) { + scic_sds_apc_agent_configure_ports( + controller, port_agent, &controller->phy_table[index], false + ); + } + } + } +} + +/* + * ****************************************************************************** + * Public port configuration agent routines + * ****************************************************************************** */ + +/** + * + * + * This method will construct the port configuration agent for operation. This + * call is universal for both manual port configuration and automatic port + * configuration modes. + */ +void scic_sds_port_configuration_agent_construct( + struct scic_sds_port_configuration_agent *port_agent) +{ + u32 index; + + port_agent->phy_configured_mask = 0x00; + port_agent->phy_ready_mask = 0x00; + + port_agent->link_up_handler = NULL; + port_agent->link_down_handler = NULL; + + port_agent->timer_pending = false; + port_agent->timer = NULL; + + for (index = 0; index < SCI_MAX_PORTS; index++) { + port_agent->phy_valid_port_range[index].min_index = 0; + port_agent->phy_valid_port_range[index].max_index = 0; + } +} + +/** + * + * @controller: This is the controller object for which the port agent is being + * initialized. + * + * This method will construct the port configuration agent for this controller. + */ +enum sci_status scic_sds_port_configuration_agent_initialize( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent) +{ + enum sci_status status = SCI_SUCCESS; + enum SCIC_PORT_CONFIGURATION_MODE mode; + + mode = scic_sds_controller_get_port_configuration_mode(controller); + + if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { + status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent); + + port_agent->link_up_handler = scic_sds_mpc_agent_link_up; + port_agent->link_down_handler = scic_sds_mpc_agent_link_down; + + port_agent->timer = scic_cb_timer_create( + controller, + scic_sds_mpc_agent_timeout_handler, + controller + ); + } else { + status = scic_sds_apc_agent_validate_phy_configuration(controller, port_agent); + + port_agent->link_up_handler = scic_sds_apc_agent_link_up; + port_agent->link_down_handler = scic_sds_apc_agent_link_down; + + port_agent->timer = scic_cb_timer_create( + controller, + scic_sds_apc_agent_timeout_handler, + controller + ); + } + + /* Make sure we have actually gotten a timer */ + if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) { + dev_err(scic_to_dev(controller), + "%s: Controller 0x%p automatic port configuration " + "agent could not get timer.\n", + __func__, + controller); + + status = SCI_FAILURE; + } + + return status; +} diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h new file mode 100644 index 000000000000..4146735ffc32 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h @@ -0,0 +1,108 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ +#define _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ + +/** + * This file contains the structures, constants and prototypes used for the + * core controller automatic port configuration engine. + * + * + */ + +#include "scic_sds_port.h" +#include "scic_sds_phy.h" + +struct scic_sds_controller; +struct scic_sds_port_configuration_agent; +struct scic_sds_port; +struct scic_sds_phy; + +typedef void (*SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T)( + struct scic_sds_controller *, + struct scic_sds_port_configuration_agent *, + struct scic_sds_port *, + struct scic_sds_phy * + ); + +struct SCIC_SDS_PORT_RANGE { + u8 min_index; + u8 max_index; +}; + +struct scic_sds_port_configuration_agent { + u16 phy_configured_mask; + u16 phy_ready_mask; + + struct SCIC_SDS_PORT_RANGE phy_valid_port_range[SCI_MAX_PHYS]; + + bool timer_pending; + + SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_up_handler; + SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_down_handler; + + void *timer; + +}; + +void scic_sds_port_configuration_agent_construct( + struct scic_sds_port_configuration_agent *port_agent); + +enum sci_status scic_sds_port_configuration_agent_initialize( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent); + +#endif /* _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port_registers.h b/drivers/scsi/isci/core/scic_sds_port_registers.h new file mode 100644 index 000000000000..cf8bc073b952 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port_registers.h @@ -0,0 +1,223 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_PORT_REGISTERS_H_ +#define _SCIC_SDS_PORT_REGISTERS_H_ + +/** + * This file contains a set of macros that assist in reading the SCU hardware + * registers. + * + * + */ + +/** + * scu_transport_layer_read() - + * + * Macro to read the transport layer register associated with this port object. + */ +#define scu_transport_layer_read(port, reg) \ + scu_register_read(\ + scic_sds_port_get_controller(port), \ + (port)->transport_layer_registers->reg \ + ) + +/** + * scu_transport_layer_write() - + * + * Macro to write the transport layer register associated with this port object. + */ +#define scu_transport_layer_write(port, reg, value) \ + scu_register_write(\ + scic_sds_port_get_controller(port), \ + (port)->transport_layer_registers->reg, \ + (value) \ + ) + +/** + * scu_port_task_scheduler_read() - + * + * Macro to read the port task scheduler register associated with this port + * object + */ +#define scu_port_task_scheduler_read(port, reg) \ + scu_register_read(\ + scic_sds_port_get_controller(port), \ + (port)->port_task_scheduler_registers->reg \ + ) + +/** + * scu_port_task_scheduler_write() - + * + * Macro to write the port task scheduler register associated with this port + * object + */ +#define scu_port_task_scheduler_write(port, reg, value) \ + scu_register_write(\ + scic_sds_port_get_controller(port), \ + (port)->port_task_scheduler_registers->reg, \ + (value) \ + ) + +#define scu_port_viit_register_write(port, reg, value) \ + scu_register_write(\ + scic_sds_port_get_controller(port), \ + (port)->viit_registers->reg, \ + (value) \ + ) + +/* + * **************************************************************************** + * * Transport Layer registers controlled by the port object + * **************************************************************************** */ + +/** + * SCU_TLCR_READ() - + * + * This macro reads the Transport layer control register + */ +#define SCU_TLCR_READ(port) \ + scu_transport_layer_read(port, control) + +/** + * SCU_TLCR_WRITE() - + * + * This macro writes the Transport layer control register + */ +#define SCU_TLCR_WRITE(port, value) \ + scu_transport_layer_write(port, control, value) + +/** + * SCU_TLADTR_READ() - + * + * This macro reads the Transport layer address translation register + */ +#define SCU_TLADTR_READ(port) \ + scu_transport_layer_read(port, address_translation) + +/** + * SCU_TLADTR_WRITE() - + * + * This macro writes the Transport layer address translation register + */ +#define SCU_TLADTR_WRITE(port) \ + scu_transport_layer_write(port, address_translation, value) + +/** + * SCU_STPTLDARNI_WRITE() - + * + * This macro writes the STP Transport Layer Direct Attached RNi register. + */ +#define SCU_STPTLDARNI_WRITE(port, index) \ + scu_transport_layer_write(port, stp_rni, index) + +/** + * SCU_STPTLDARNI_READ() - + * + * This macro reads the STP Transport Layer Direct Attached RNi register. + */ +#define SCU_STPTLDARNI_READ(port) \ + scu_transport_layer_read(port, stp_rni) + +/* + * **************************************************************************** + * * Port Task Scheduler registers controlled by the port object + * **************************************************************************** */ + +/** + * SCU_PTSxCR_READ() - + * + * Macro to read the port task scheduler control register + */ +#define SCU_PTSxCR_READ(port) \ + scu_port_task_scheduler_read(port, control) + +/** + * SCU_PTSxCR_WRITE() - + * + * Macro to write the port task scheduler control regsister + */ +#define SCU_PTSxCR_WRITE(port, value) \ + scu_port_task_scheduler_write(port, control, value) + +/* + * **************************************************************************** + * * Port PE Configuration registers + * **************************************************************************** */ + +/** + * SCU_PCSPExCR_WRITE() - + * + * Macro to write the PE Port Configuration Register + */ +#define SCU_PCSPExCR_WRITE(port, phy_id, value) \ + scu_register_write(\ + scic_sds_port_get_controller(port), \ + (port)->port_pe_configuration_register[phy_id], \ + (value) \ + ) + +/** + * SCU_PCSPExCR_READ() - + * + * Macro to read the PE Port Configuration Regsiter + */ +#define SCU_PCSPExCR_READ(port, phy_id) \ + scu_register_read(\ + scic_sds_port_get_controller(port), \ + (port)->port_pe_configuration_register[phy_id] \ + ) + +#endif /* _SCIC_SDS_PORT_REGISTERS_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c new file mode 100644 index 000000000000..21f03bc7d797 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -0,0 +1,2252 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the implementation of remote device methods. + * + * + */ + +#include "intel_sas.h" +#include "sci_util.h" +#include "sci_environment.h" +#include "scic_port.h" +#include "scic_phy.h" +#include "scic_remote_device.h" +#include "scic_sds_port.h" +#include "scic_sds_phy.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_request.h" +#include "scic_sds_controller.h" + +#define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT (1000) + +/* + * ***************************************************************************** + * * CORE REMOTE DEVICE PRIVATE METHODS + * ***************************************************************************** */ + +/* + * ***************************************************************************** + * * CORE REMOTE DEVICE PUBLIC METHODS + * ***************************************************************************** */ + +u32 scic_remote_device_get_object_size(void) +{ + return sizeof(struct scic_sds_remote_device) + + sizeof(struct scic_sds_remote_node_context); +} + +/* --------------------------------------------------------------------------- */ + +void scic_remote_device_construct(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev) +{ + sci_dev->owning_port = sci_port; + sci_dev->started_request_count = 0; + sci_dev->rnc = (struct scic_sds_remote_node_context *) &sci_dev[1]; + + sci_base_remote_device_construct( + &sci_dev->parent, + scic_sds_remote_device_state_table + ); + + scic_sds_remote_node_context_construct( + sci_dev, + sci_dev->rnc, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX + ); + + sci_object_set_association(sci_dev->rnc, sci_dev); +} + + +enum sci_status scic_remote_device_da_construct( + struct scic_sds_remote_device *sci_dev) +{ + enum sci_status status; + u16 remote_node_index; + struct sci_sas_identify_address_frame_protocols protocols; + + /* + * This information is request to determine how many remote node context + * entries will be needed to store the remote node. + */ + scic_sds_port_get_attached_protocols(sci_dev->owning_port, &protocols); + sci_dev->target_protocols.u.all = protocols.u.all; + sci_dev->is_direct_attached = true; +#if !defined(DISABLE_ATAPI) + sci_dev->is_atapi = scic_sds_remote_device_is_atapi(sci_dev); +#endif + + status = scic_sds_controller_allocate_remote_node_context( + sci_dev->owning_port->owning_controller, + sci_dev, + &remote_node_index); + + if (status == SCI_SUCCESS) { + scic_sds_remote_node_context_set_remote_node_index( + sci_dev->rnc, remote_node_index); + + scic_sds_port_get_attached_sas_address( + sci_dev->owning_port, &sci_dev->device_address); + + if (sci_dev->target_protocols.u.bits.attached_ssp_target) { + sci_dev->has_ready_substate_machine = false; + } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { + sci_dev->has_ready_substate_machine = true; + + sci_base_state_machine_construct( + &sci_dev->ready_substate_machine, + &sci_dev->parent.parent, + scic_sds_stp_remote_device_ready_substate_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { + sci_dev->has_ready_substate_machine = true; + + /* add the SMP ready substate machine construction here */ + sci_base_state_machine_construct( + &sci_dev->ready_substate_machine, + &sci_dev->parent.parent, + scic_sds_smp_remote_device_ready_substate_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } + + sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed( + sci_dev->owning_port); + + /* / @todo Should I assign the port width by reading all of the phys on the port? */ + sci_dev->device_port_width = 1; + } + + return status; +} + + +static void scic_sds_remote_device_get_info_from_smp_discover_response( + struct scic_sds_remote_device *this_device, + struct smp_response_discover *discover_response) +{ + /* decode discover_response to set sas_address to this_device. */ + this_device->device_address.high = + discover_response->attached_sas_address.high; + + this_device->device_address.low = + discover_response->attached_sas_address.low; + + this_device->target_protocols.u.all = discover_response->protocols.u.all; +} + + +enum sci_status scic_remote_device_ea_construct( + struct scic_sds_remote_device *sci_dev, + struct smp_response_discover *discover_response) +{ + enum sci_status status; + struct scic_sds_controller *the_controller; + + the_controller = scic_sds_port_get_controller(sci_dev->owning_port); + + scic_sds_remote_device_get_info_from_smp_discover_response( + sci_dev, discover_response); + + status = scic_sds_controller_allocate_remote_node_context( + the_controller, sci_dev, &sci_dev->rnc->remote_node_index); + + if (status == SCI_SUCCESS) { + if (sci_dev->target_protocols.u.bits.attached_ssp_target) { + sci_dev->has_ready_substate_machine = false; + } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { + sci_dev->has_ready_substate_machine = true; + + /* add the SMP ready substate machine construction here */ + sci_base_state_machine_construct( + &sci_dev->ready_substate_machine, + &sci_dev->parent.parent, + scic_sds_smp_remote_device_ready_substate_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { + sci_dev->has_ready_substate_machine = true; + + sci_base_state_machine_construct( + &sci_dev->ready_substate_machine, + &sci_dev->parent.parent, + scic_sds_stp_remote_device_ready_substate_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } + + /* + * For SAS-2 the physical link rate is actually a logical link + * rate that incorporates multiplexing. The SCU doesn't + * incorporate multiplexing and for the purposes of the + * connection the logical link rate is that same as the + * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay + * one another, so this code works for both situations. */ + sci_dev->connection_rate = min_t(u16, + scic_sds_port_get_max_allowed_speed(sci_dev->owning_port), + discover_response->u2.sas1_1.negotiated_physical_link_rate + ); + + /* / @todo Should I assign the port width by reading all of the phys on the port? */ + sci_dev->device_port_width = 1; + } + + return status; +} + +enum sci_status scic_remote_device_destruct( + struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->state_handlers->parent.destruct_handler(&sci_dev->parent); +} + + +enum sci_status scic_remote_device_start( + struct scic_sds_remote_device *sci_dev, + u32 timeout) +{ + return sci_dev->state_handlers->parent.start_handler(&sci_dev->parent); +} + + +enum sci_status scic_remote_device_stop( + struct scic_sds_remote_device *sci_dev, + u32 timeout) +{ + return sci_dev->state_handlers->parent.stop_handler(&sci_dev->parent); +} + + +enum sci_status scic_remote_device_reset( + struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->state_handlers->parent.reset_handler(&sci_dev->parent); +} + + +enum sci_status scic_remote_device_reset_complete( + struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->state_handlers->parent.reset_complete_handler(&sci_dev->parent); +} + + +enum sci_sas_link_rate scic_remote_device_get_connection_rate( + struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->connection_rate; +} + + +void scic_remote_device_get_protocols( + struct scic_sds_remote_device *sci_dev, + struct smp_discover_response_protocols *pr) +{ + pr->u.all = sci_dev->target_protocols.u.all; +} + +#if !defined(DISABLE_ATAPI) +bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->is_atapi; +} +#endif + + +/* + * ***************************************************************************** + * * SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS + * ***************************************************************************** */ + +/** + * + * + * Remote device timer requirements + */ +#define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0) +#define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES) + + +/** + * + * @this_device: The remote device for which the suspend is being requested. + * + * This method invokes the remote device suspend state handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_suspend( + struct scic_sds_remote_device *this_device, + u32 suspend_type) +{ + return this_device->state_handlers->suspend_handler(this_device, suspend_type); +} + +/** + * + * @this_device: The remote device for which the resume is being requested. + * + * This method invokes the remote device resume state handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_resume( + struct scic_sds_remote_device *this_device) +{ + return this_device->state_handlers->resume_handler(this_device); +} + +/** + * + * @this_device: The remote device for which the event handling is being + * requested. + * @frame_index: This is the frame index that is being processed. + * + * This method invokes the frame handler for the remote device state machine + * enum sci_status + */ +enum sci_status scic_sds_remote_device_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index) +{ + return this_device->state_handlers->frame_handler(this_device, frame_index); +} + +/** + * + * @this_device: The remote device for which the event handling is being + * requested. + * @event_code: This is the event code that is to be processed. + * + * This method invokes the remote device event handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_event_handler( + struct scic_sds_remote_device *this_device, + u32 event_code) +{ + return this_device->state_handlers->event_handler(this_device, event_code); +} + +/** + * + * @controller: The controller that is starting the io request. + * @this_device: The remote device for which the start io handling is being + * requested. + * @io_request: The io request that is being started. + * + * This method invokes the remote device start io handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_start_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *this_device, + struct scic_sds_request *io_request) +{ + return this_device->state_handlers->parent.start_io_handler( + &this_device->parent, &io_request->parent); +} + +/** + * + * @controller: The controller that is completing the io request. + * @this_device: The remote device for which the complete io handling is being + * requested. + * @io_request: The io request that is being completed. + * + * This method invokes the remote device complete io handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_complete_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *this_device, + struct scic_sds_request *io_request) +{ + return this_device->state_handlers->parent.complete_io_handler( + &this_device->parent, &io_request->parent); +} + +/** + * + * @controller: The controller that is starting the task request. + * @this_device: The remote device for which the start task handling is being + * requested. + * @io_request: The task request that is being started. + * + * This method invokes the remote device start task handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_start_task( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *this_device, + struct scic_sds_request *io_request) +{ + return this_device->state_handlers->parent.start_task_handler( + &this_device->parent, &io_request->parent); +} + +/** + * + * @controller: The controller that is completing the task request. + * @this_device: The remote device for which the complete task handling is + * being requested. + * @io_request: The task request that is being completed. + * + * This method invokes the remote device complete task handler. enum sci_status + */ + +/** + * + * @this_device: + * @request: + * + * This method takes the request and bulids an appropriate SCU context for the + * request and then requests the controller to post the request. none + */ +void scic_sds_remote_device_post_request( + struct scic_sds_remote_device *this_device, + u32 request) +{ + u32 context; + + context = scic_sds_remote_device_build_command_context(this_device, request); + + scic_sds_controller_post_request( + scic_sds_remote_device_get_controller(this_device), + context + ); +} + +#if !defined(DISABLE_ATAPI) +/** + * + * @this_device: The device to be checked. + * + * This method check the signature fis of a stp device to decide whether a + * device is atapi or not. true if a device is atapi device. False if a device + * is not atapi. + */ +bool scic_sds_remote_device_is_atapi( + struct scic_sds_remote_device *this_device) +{ + if (!this_device->target_protocols.u.bits.attached_stp_target) + return false; + else if (this_device->is_direct_attached) { + struct scic_sds_phy *phy; + struct scic_sata_phy_properties properties; + struct sata_fis_reg_d2h *signature_fis; + phy = scic_sds_port_get_a_connected_phy(this_device->owning_port); + scic_sata_phy_get_properties(phy, &properties); + + /* decode the signature fis. */ + signature_fis = &(properties.signature_fis); + + if ((signature_fis->sector_count == 0x01) + && (signature_fis->lba_low == 0x01) + && (signature_fis->lba_mid == 0x14) + && (signature_fis->lba_high == 0xEB) + && ((signature_fis->device & 0x5F) == 0x00) + ) { + /* An ATA device supporting the PACKET command set. */ + return true; + } else + return false; + } else { + /* Expander supported ATAPI device is not currently supported. */ + return false; + } +} +#endif +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the state handlers for the struct scic_sds_remote_device for the + * base state machine. + * + * + */ + +#include "sci_environment.h" +#include "scic_user_callback.h" +#include "scic_controller.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "scic_sds_request.h" +#include "scic_sds_remote_node_context.h" +#include "scu_event_codes.h" + +/* + * ***************************************************************************** + * * PROTECTED METHODS + * ***************************************************************************** */ + +/** + * + * @user_parameter: This is cast to a remote device object. + * + * This method is called once the remote node context is ready to be freed. + * The remote device can now report that its stop operation is complete. none + */ +static void scic_sds_cb_remote_device_rnc_destruct_complete( + void *user_parameter) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)user_parameter; + + BUG_ON(this_device->started_request_count != 0); + + sci_base_state_machine_change_state( + scic_sds_remote_device_get_base_state_machine(this_device), + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED + ); +} + +/** + * + * @user_parameter: This is cast to a remote device object. + * + * This method is called once the remote node context has transisitioned to a + * ready state. This is the indication that the remote device object can also + * transition to ready. none + */ +static void scic_sds_remote_device_resume_complete_handler( + void *user_parameter) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)user_parameter; + + if ( + sci_base_state_machine_get_state(&this_device->parent.state_machine) + != SCI_BASE_REMOTE_DEVICE_STATE_READY + ) { + sci_base_state_machine_change_state( + &this_device->parent.state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_READY + ); + } +} + +/** + * + * @device: This parameter specifies the device for which the request is being + * started. + * @request: This parameter specifies the request being started. + * @status: This parameter specifies the current start operation status. + * + * This method will perform the STP request start processing common to IO + * requests and task requests of all types. none + */ +void scic_sds_remote_device_start_request( + struct scic_sds_remote_device *this_device, + struct scic_sds_request *the_request, + enum sci_status status) +{ + /* We still have a fault in starting the io complete it on the port */ + if (status == SCI_SUCCESS) + scic_sds_remote_device_increment_request_count(this_device); + else{ + this_device->owning_port->state_handlers->complete_io_handler( + this_device->owning_port, this_device, the_request + ); + } +} + + +/** + * + * @request: This parameter specifies the request being continued. + * + * This method will continue to post tc for a STP request. This method usually + * serves as a callback when RNC gets resumed during a task management + * sequence. none + */ +void scic_sds_remote_device_continue_request( + struct scic_sds_remote_device *this_device) +{ + /* we need to check if this request is still valid to continue. */ + if (this_device->working_request != NULL) { + struct scic_sds_request *this_request = this_device->working_request; + struct scic_sds_controller *scic = this_request->owning_controller; + u32 state = scic->parent.state_machine.current_state_id; + sci_base_controller_request_handler_t continue_io; + + continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; + continue_io(&scic->parent, &this_request->target_device->parent, + &this_request->parent); + } +} + +/** + * + * @user_parameter: This is cast to a remote device object. + * + * This method is called once the remote node context has reached a suspended + * state. The remote device can now report that its suspend operation is + * complete. none + */ + +/** + * This method will terminate all of the IO requests in the controllers IO + * request table that were targeted for this device. + * @this_device: This parameter specifies the remote device for which to + * attempt to terminate all requests. + * + * This method returns an indication as to whether all requests were + * successfully terminated. If a single request fails to be terminated, then + * this method will return the failure. + */ +static enum sci_status scic_sds_remote_device_terminate_requests( + struct scic_sds_remote_device *this_device) +{ + enum sci_status status = SCI_SUCCESS; + enum sci_status terminate_status = SCI_SUCCESS; + struct scic_sds_request *the_request; + u32 index; + u32 request_count = this_device->started_request_count; + + for (index = 0; + (index < SCI_MAX_IO_REQUESTS) && (request_count > 0); + index++) { + the_request = this_device->owning_port->owning_controller->io_request_table[index]; + + if ((the_request != NULL) && (the_request->target_device == this_device)) { + terminate_status = scic_controller_terminate_request( + this_device->owning_port->owning_controller, + this_device, + the_request + ); + + if (terminate_status != SCI_SUCCESS) + status = terminate_status; + + request_count--; + } + } + + return status; +} + +/* + * ***************************************************************************** + * * DEFAULT STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * + * This method is the default start handler. It logs a warning and returns a + * failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_start_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to start while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + sds_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * + * This method is the default stop handler. It logs a warning and returns a + * failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_remote_device_default_stop_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to stop while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + sds_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * + * This method is the default fail handler. It logs a warning and returns a + * failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_fail_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to fail while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + sds_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * + * This method is the default destruct handler. It logs a warning and returns + * a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_destruct_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to destroy while in " + "wrong state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + sds_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * + * This method is the default reset handler. It logs a warning and returns a + * failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_reset_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to reset while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + sds_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * + * This method is the default reset complete handler. It logs a warning and + * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_reset_complete_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to complete reset while " + "in wrong state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + sds_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * + * This method is the default suspend handler. It logs a warning and returns a + * failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_suspend_handler( + struct scic_sds_remote_device *this_device, + u32 suspend_type) +{ + dev_warn(scirdev_to_dev(this_device), + "%s: SCIC Remote Device 0x%p requested to suspend %d while " + "in wrong state %d\n", + __func__, + this_device, + suspend_type, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + this_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * + * This method is the default resume handler. It logs a warning and returns a + * failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_resume_handler( + struct scic_sds_remote_device *this_device) +{ + dev_warn(scirdev_to_dev(this_device), + "%s: SCIC Remote Device requested to resume while in " + "wrong state %d\n", + __func__, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + this_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @event_code: The event code that the struct scic_sds_controller wants the device + * object to process. + * + * This method is the default event handler. It will call the RNC state + * machine handler for any RNC events otherwise it will log a warning and + * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_remote_device_core_event_handler( + struct scic_sds_remote_device *this_device, + u32 event_code, + bool is_ready_state) +{ + enum sci_status status; + + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_OPS_MISC: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code); + break; + case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: + + if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { + status = SCI_SUCCESS; + + /* Suspend the associated RNC */ + scic_sds_remote_node_context_suspend(this_device->rnc, + SCI_SOFTWARE_SUSPENSION, + NULL, NULL); + + dev_dbg(scirdev_to_dev(this_device), + "%s: device: %p event code: %x: %s\n", + __func__, this_device, event_code, + (is_ready_state) + ? "I_T_Nexus_Timeout event" + : "I_T_Nexus_Timeout event in wrong state"); + + break; + } + /* Else, fall through and treat as unhandled... */ + + default: + dev_dbg(scirdev_to_dev(this_device), + "%s: device: %p event code: %x: %s\n", + __func__, this_device, event_code, + (is_ready_state) + ? "unexpected event" + : "unexpected event in wrong state"); + status = SCI_FAILURE_INVALID_STATE; + break; + } + + return status; +} +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @event_code: The event code that the struct scic_sds_controller wants the device + * object to process. + * + * This method is the default event handler. It will call the RNC state + * machine handler for any RNC events otherwise it will log a warning and + * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_remote_device_default_event_handler( + struct scic_sds_remote_device *this_device, + u32 event_code) +{ + return scic_sds_remote_device_core_event_handler(this_device, + event_code, + false); +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @frame_index: The frame index for which the struct scic_sds_controller wants this + * device object to process. + * + * This method is the default unsolicited frame handler. It logs a warning, + * releases the frame and returns a failure. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index) +{ + dev_warn(scirdev_to_dev(this_device), + "%s: SCIC Remote Device requested to handle frame %x " + "while in wrong state %d\n", + __func__, + frame_index, + sci_base_state_machine_get_state( + &this_device->parent.state_machine)); + + /* Return the frame back to the controller */ + scic_sds_controller_release_frame( + scic_sds_remote_device_get_controller(this_device), frame_index + ); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST + * to start. + * + * This method is the default start io handler. It logs a warning and returns + * a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_start_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to start io request %p " + "while in wrong state %d\n", + __func__, + request, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + (struct scic_sds_remote_device *)device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST + * to complete. + * + * This method is the default complete io handler. It logs a warning and + * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_complete_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to complete io_request %p " + "while in wrong state %d\n", + __func__, + request, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + sds_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST + * to continue. + * + * This method is the default continue io handler. It logs a warning and + * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_continue_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + struct scic_sds_remote_device *sds_device = + (struct scic_sds_remote_device *)device; + + dev_warn(scirdev_to_dev(sds_device), + "%s: SCIC Remote Device requested to continue io request %p " + "while in wrong state %d\n", + __func__, + request, + sci_base_state_machine_get_state( + scic_sds_remote_device_get_base_state_machine( + sds_device))); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST + * to complete. + * + * This method is the default complete task handler. It logs a warning and + * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ + +/* + * ***************************************************************************** + * * NORMAL STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @device: The struct sci_base_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @frame_index: The frame index for which the struct scic_sds_controller wants this + * device object to process. + * + * This method is a general ssp frame handler. In most cases the device object + * needs to route the unsolicited frame processing to the io request object. + * This method decodes the tag for the io request object and routes the + * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_general_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index) +{ + enum sci_status result; + struct sci_ssp_frame_header *frame_header; + struct scic_sds_request *io_request; + + result = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_remote_device_get_controller(this_device)->uf_control), + frame_index, + (void **)&frame_header + ); + + if (SCI_SUCCESS == result) { + io_request = scic_sds_controller_get_io_request_from_tag( + scic_sds_remote_device_get_controller(this_device), frame_header->tag); + + if ((io_request == SCI_INVALID_HANDLE) + || (io_request->target_device != this_device)) { + /* + * We could not map this tag to a valid IO request + * Just toss the frame and continue */ + scic_sds_controller_release_frame( + scic_sds_remote_device_get_controller(this_device), frame_index + ); + } else { + /* The IO request is now in charge of releasing the frame */ + result = io_request->state_handlers->frame_handler( + io_request, frame_index); + } + } + + return result; +} + +/** + * + * @[in]: this_device This is the device object that is receiving the event. + * @[in]: event_code The event code to process. + * + * This is a common method for handling events reported to the remote device + * from the controller object. enum sci_status + */ +enum sci_status scic_sds_remote_device_general_event_handler( + struct scic_sds_remote_device *this_device, + u32 event_code) +{ + return scic_sds_remote_device_core_event_handler(this_device, + event_code, + true); +} + +/* + * ***************************************************************************** + * * STOPPED STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @device: + * + * This method takes the struct scic_sds_remote_device from a stopped state and + * attempts to start it. The RNC buffer for the device is constructed and the + * device state machine is transitioned to the + * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING. enum sci_status SCI_SUCCESS if there is + * an RNC buffer available to construct the remote device. + * SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer available in + * which to construct the remote device. + */ +static enum sci_status scic_sds_remote_device_stopped_state_start_handler( + struct sci_base_remote_device *device) +{ + enum sci_status status; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + + status = scic_sds_remote_node_context_resume( + this_device->rnc, + scic_sds_remote_device_resume_complete_handler, + this_device + ); + + if (status == SCI_SUCCESS) { + sci_base_state_machine_change_state( + scic_sds_remote_device_get_base_state_machine(this_device), + SCI_BASE_REMOTE_DEVICE_STATE_STARTING + ); + } + + return status; +} + +/** + * + * @this_device: The struct sci_base_remote_device which is cast into a + * struct scic_sds_remote_device. + * + * This method will stop a struct scic_sds_remote_device that is already in a stopped + * state. This is not considered an error since the device is already stopped. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( + struct sci_base_remote_device *this_device) +{ + return SCI_SUCCESS; +} + +/** + * + * @this_device: The struct sci_base_remote_device which is cast into a + * struct scic_sds_remote_device. + * + * This method will destruct a struct scic_sds_remote_device that is in a stopped + * state. This is the only state from which a destruct request will succeed. + * The RNi for this struct scic_sds_remote_device is returned to the free pool and the + * device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + + scic_sds_controller_free_remote_node_context( + scic_sds_remote_device_get_controller(this_device), + this_device, + this_device->rnc->remote_node_index + ); + + scic_sds_remote_node_context_set_remote_node_index( + this_device->rnc, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX + ); + + scic_sds_port_set_direct_attached_device_id( + this_device->owning_port, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX + ); + + sci_base_state_machine_change_state( + scic_sds_remote_device_get_base_state_machine(this_device), + SCI_BASE_REMOTE_DEVICE_STATE_FINAL + ); + + return SCI_SUCCESS; +} + +/* + * ***************************************************************************** + * * STARTING STATE HANDLERS + * ***************************************************************************** */ + +static enum sci_status scic_sds_remote_device_starting_state_stop_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + + /* + * This device has not yet started so there had better be no IO requests + */ + BUG_ON(this_device->started_request_count != 0); + + /* + * Destroy the remote node context + */ + scic_sds_remote_node_context_destruct( + this_device->rnc, + scic_sds_cb_remote_device_rnc_destruct_complete, + this_device + ); + + /* + * Transition to the stopping state and wait for the remote node to + * complete being posted and invalidated. + */ + sci_base_state_machine_change_state( + scic_sds_remote_device_get_base_state_machine(this_device), + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING + ); + + return SCI_SUCCESS; +} + +/* + * ***************************************************************************** + * * INITIALIZING STATE HANDLERS + * ***************************************************************************** */ + +/* There is nothing to do here for SSP devices */ + +/* + * ***************************************************************************** + * * READY STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @this_device: The struct scic_sds_remote_device object to be suspended. + * + * This method is the resume handler for the struct scic_sds_remote_device object. It + * will post an RNC resume to the SCU hardware. enum sci_status SCI_SUCCESS + */ + +/** + * + * @device: The struct sci_base_remote_device object which is cast to a + * struct scic_sds_remote_device object. + * + * This method is the default stop handler for the struct scic_sds_remote_device ready + * substate machine. It will stop the current substate machine and transition + * the base state machine to SCI_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status + * SCI_SUCCESS + */ +enum sci_status scic_sds_remote_device_ready_state_stop_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + enum sci_status status = SCI_SUCCESS; + + /* Request the parent state machine to transition to the stopping state */ + sci_base_state_machine_change_state( + scic_sds_remote_device_get_base_state_machine(this_device), + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING + ); + + if (this_device->started_request_count == 0) { + scic_sds_remote_node_context_destruct( + this_device->rnc, + scic_sds_cb_remote_device_rnc_destruct_complete, + this_device + ); + } else + status = scic_sds_remote_device_terminate_requests(this_device); + + return status; +} + +/** + * + * @device: The struct sci_base_remote_device object which is cast to a + * struct scic_sds_remote_device object. + * + * This is the ready state device reset handler enum sci_status + */ +enum sci_status scic_sds_remote_device_ready_state_reset_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + + /* Request the parent state machine to transition to the stopping state */ + sci_base_state_machine_change_state( + scic_sds_remote_device_get_base_state_machine(this_device), + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING + ); + + return SCI_SUCCESS; +} + +/** + * + * @device: The struct sci_base_remote_device object which is cast to a + * struct scic_sds_remote_device object. + * + * This is the default fail handler for the struct scic_sds_remote_device ready + * substate machine. It will stop the current ready substate and transition + * the remote device object to the SCI_BASE_REMOTE_DEVICE_STATE_FAILED. + * enum sci_status SCI_SUCCESS + */ + +/** + * + * @device: The struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device for which the request is to be started. + * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that + * is to be started. + * + * This method will attempt to start a task request for this device object. The + * remote device object will issue the start request for the task and if + * successful it will start the request for the port object then increment its + * own requet count. enum sci_status SCI_SUCCESS if the task request is started for + * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request + * object could not get the resources to start. + */ +static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status result; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *task_request = (struct scic_sds_request *)request; + + /* See if the port is in a state where we can start the IO request */ + result = scic_sds_port_start_io( + scic_sds_remote_device_get_port(this_device), this_device, task_request); + + if (result == SCI_SUCCESS) { + result = scic_sds_remote_node_context_start_task( + this_device->rnc, task_request + ); + + if (result == SCI_SUCCESS) { + result = scic_sds_request_start(task_request); + } + + scic_sds_remote_device_start_request(this_device, task_request, result); + } + + return result; +} + +/** + * + * @device: The struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device for which the request is to be started. + * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that + * is to be started. + * + * This method will attempt to start an io request for this device object. The + * remote device object will issue the start request for the io and if + * successful it will start the request for the port object then increment its + * own requet count. enum sci_status SCI_SUCCESS if the io request is started for + * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request + * object could not get the resources to start. + */ +static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status result; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *io_request = (struct scic_sds_request *)request; + + /* See if the port is in a state where we can start the IO request */ + result = scic_sds_port_start_io( + scic_sds_remote_device_get_port(this_device), this_device, io_request); + + if (result == SCI_SUCCESS) { + result = scic_sds_remote_node_context_start_io( + this_device->rnc, io_request + ); + + if (result == SCI_SUCCESS) { + result = scic_sds_request_start(io_request); + } + + scic_sds_remote_device_start_request(this_device, io_request, result); + } + + return result; +} + +/** + * + * @device: The struct sci_base_remote_device which is cast to a + * struct scic_sds_remote_device for which the request is to be completed. + * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that + * is to be completed. + * + * This method will complete the request for the remote device object. The + * method will call the completion handler for the request object and if + * successful it will complete the request on the port object then decrement + * its own started_request_count. enum sci_status + */ +static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status result; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *the_request = (struct scic_sds_request *)request; + + result = scic_sds_request_complete(the_request); + + if (result == SCI_SUCCESS) { + /* See if the port is in a state where we can start the IO request */ + result = scic_sds_port_complete_io( + scic_sds_remote_device_get_port(this_device), this_device, the_request); + + if (result == SCI_SUCCESS) { + scic_sds_remote_device_decrement_request_count(this_device); + } + } + + return result; +} + +/* + * ***************************************************************************** + * * STOPPING STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @this_device: The struct sci_base_remote_device which is cast into a + * struct scic_sds_remote_device. + * + * This method will stop a struct scic_sds_remote_device that is already in the + * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an error + * since we allow a stop request on a device that is alreay stopping or + * stopped. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( + struct sci_base_remote_device *device) +{ + /* + * All requests should have been terminated, but if there is an + * attempt to stop a device already in the stopping state, then + * try again to terminate. */ + return scic_sds_remote_device_terminate_requests( + (struct scic_sds_remote_device *)device); +} + + +/** + * + * @device: The device object for which the request is completing. + * @request: The task request that is being completed. + * + * This method completes requests for this struct scic_sds_remote_device while it is + * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the + * complete method for the request object and if that is successful the port + * object is called to complete the task request. Then the device object itself + * completes the task request. If struct scic_sds_remote_device started_request_count + * goes to 0 and the invalidate RNC request has completed the device object can + * transition to the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. enum sci_status + */ +static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status status = SCI_SUCCESS; + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + + status = scic_sds_request_complete(this_request); + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + scic_sds_remote_device_get_port(this_device), + this_device, + this_request + ); + + if (status == SCI_SUCCESS) { + scic_sds_remote_device_decrement_request_count(this_device); + + if (scic_sds_remote_device_get_request_count(this_device) == 0) { + scic_sds_remote_node_context_destruct( + this_device->rnc, + scic_sds_cb_remote_device_rnc_destruct_complete, + this_device + ); + } + } + } + + return status; +} + +/* + * ***************************************************************************** + * * RESETTING STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @device: The struct sci_base_remote_device which is to be cast into a + * struct scic_sds_remote_device object. + * + * This method will complete the reset operation when the device is in the + * resetting state. enum sci_status + */ +static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + + sci_base_state_machine_change_state( + &this_device->parent.state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_READY + ); + + return SCI_SUCCESS; +} + +/** + * + * @device: The struct sci_base_remote_device which is to be cast into a + * struct scic_sds_remote_device object. + * + * This method will stop the remote device while in the resetting state. + * enum sci_status + */ +static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( + struct sci_base_remote_device *device) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + + sci_base_state_machine_change_state( + &this_device->parent.state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING + ); + + return SCI_SUCCESS; +} + +/** + * + * @device: The device object for which the request is completing. + * @request: The task request that is being completed. + * + * This method completes requests for this struct scic_sds_remote_device while it is + * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the + * complete method for the request object and if that is successful the port + * object is called to complete the task request. Then the device object itself + * completes the task request. enum sci_status + */ +static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status status = SCI_SUCCESS; + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + + status = scic_sds_request_complete(this_request); + + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + scic_sds_remote_device_get_port(this_device), this_device, this_request); + + if (status == SCI_SUCCESS) { + scic_sds_remote_device_decrement_request_count(this_device); + } + } + + return status; +} + +/* + * ***************************************************************************** + * * FAILED STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @device: The struct sci_base_remote_device which is to be cast into a + * struct scic_sds_remote_device object. + * + * This method handles the remove request for a failed struct scic_sds_remote_device + * object. The method will transition the device object to the + * SCIC_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status SCI_SUCCESS + */ + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_remote_device_state_handler +scic_sds_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] = +{ + /* SCI_BASE_REMOTE_DEVICE_STATE_INITIAL */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_default_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_default_event_handler, + scic_sds_remote_device_default_frame_handler + }, + /* SCI_BASE_REMOTE_DEVICE_STATE_STOPPED */ + { + { + scic_sds_remote_device_stopped_state_start_handler, + scic_sds_remote_device_stopped_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_stopped_state_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_default_event_handler, + scic_sds_remote_device_default_frame_handler + }, + /* SCI_BASE_REMOTE_DEVICE_STATE_STARTING */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_starting_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_remote_device_default_frame_handler + }, + /* SCI_BASE_REMOTE_DEVICE_STATE_READY */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_ready_state_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_ready_state_start_io_handler, + scic_sds_remote_device_ready_state_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_ready_state_start_task_handler, + scic_sds_remote_device_ready_state_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_remote_device_general_frame_handler, + }, + /* SCI_BASE_REMOTE_DEVICE_STATE_STOPPING */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_stopping_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_stopping_state_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_stopping_state_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_remote_device_general_frame_handler + }, + /* SCI_BASE_REMOTE_DEVICE_STATE_FAILED */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_default_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_default_event_handler, + scic_sds_remote_device_general_frame_handler + }, + /* SCI_BASE_REMOTE_DEVICE_STATE_RESETTING */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_resetting_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_resetting_state_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_resetting_state_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_resetting_state_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_default_event_handler, + scic_sds_remote_device_general_frame_handler + }, + /* SCI_BASE_REMOTE_DEVICE_STATE_FINAL */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_default_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_default_event_handler, + scic_sds_remote_device_default_frame_handler + } +}; + +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the operations that are taken on the enter and exit state + * transitions for the struct sci_base_remote_device state machine. + * + * + */ + +#include "scic_remote_device.h" +#include "scic_user_callback.h" +#include "scic_sds_controller.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_request.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it + * immediatly transitions the remote device object to the stopped state. none + */ +static void scic_sds_remote_device_initial_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + this_device, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL + ); + + /* Initial state is a transitional state to the stopped state */ + sci_base_state_machine_change_state( + scic_sds_remote_device_get_base_state_machine(this_device), + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED + ); +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it + * sets the stopped state handlers and if this state is entered from the + * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that the + * device stop is complete. none + */ +static void scic_sds_remote_device_stopped_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + this_device, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED + ); + + /* + * If we are entering from the stopping state let the SCI User know that + * the stop operation has completed. */ + if (this_device->parent.state_machine.previous_state_id + == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) { + scic_cb_remote_device_stop_complete( + scic_sds_remote_device_get_controller(this_device), + this_device, + SCI_SUCCESS + ); + } +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it + * sets the starting state handlers, sets the device not ready, and posts the + * remote node context to the hardware. none + */ +static void scic_sds_remote_device_starting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_controller *the_controller; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + the_controller = scic_sds_remote_device_get_controller(this_device); + + SET_STATE_HANDLER( + this_device, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STARTING + ); + + scic_cb_remote_device_not_ready( + the_controller, + this_device, + SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED + ); +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it + * reports that the device start is complete. none + */ +static void scic_sds_remote_device_starting_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + /* + * / @todo Check the device object for the proper return code for this + * / callback */ + scic_cb_remote_device_start_complete( + scic_sds_remote_device_get_controller(this_device), + this_device, + SCI_SUCCESS + ); +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets + * the ready state handlers, and starts the ready substate machine. none + */ +static void scic_sds_remote_device_ready_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_controller *the_controller; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + the_controller = scic_sds_remote_device_get_controller(this_device); + + SET_STATE_HANDLER( + this_device, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_READY + ); + + the_controller->remote_device_sequence[this_device->rnc->remote_node_index]++; + + if (this_device->has_ready_substate_machine) { + sci_base_state_machine_start(&this_device->ready_substate_machine); + } else { + scic_cb_remote_device_ready(the_controller, this_device); + } +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does + * nothing. none + */ +static void scic_sds_remote_device_ready_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_controller *the_controller; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + the_controller = scic_sds_remote_device_get_controller(this_device); + + if (this_device->has_ready_substate_machine) { + sci_base_state_machine_stop(&this_device->ready_substate_machine); + } else { + scic_cb_remote_device_not_ready( + the_controller, + this_device, + SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED + ); + } +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it + * sets the stopping state handlers and posts an RNC invalidate request to the + * SCU hardware. none + */ +static void scic_sds_remote_device_stopping_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + this_device, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING + ); +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it sets + * the stopping state handlers. none + */ +static void scic_sds_remote_device_failed_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + this_device, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_FAILED + ); +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it + * sets the resetting state handlers. none + */ +static void scic_sds_remote_device_resetting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + this_device, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING + ); + + scic_sds_remote_node_context_suspend( + this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it + * does nothing. none + */ +static void scic_sds_remote_device_resetting_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + scic_sds_port_set_direct_attached_device_id( + scic_sds_remote_device_get_port(this_device), + this_device->rnc->remote_node_index + ); + + scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL); +} + +/** + * + * @object: This is the struct sci_base_object that is cast into a + * struct scic_sds_remote_device. + * + * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets + * the final state handlers. none + */ +static void scic_sds_remote_device_final_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + this_device, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_FINAL + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_remote_device_state_table[] = { + [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { + .enter_state = scic_sds_remote_device_initial_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { + .enter_state = scic_sds_remote_device_stopped_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { + .enter_state = scic_sds_remote_device_starting_state_enter, + .exit_state = scic_sds_remote_device_starting_state_exit + }, + [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { + .enter_state = scic_sds_remote_device_ready_state_enter, + .exit_state = scic_sds_remote_device_ready_state_exit + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { + .enter_state = scic_sds_remote_device_stopping_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { + .enter_state = scic_sds_remote_device_failed_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { + .enter_state = scic_sds_remote_device_resetting_state_enter, + .exit_state = scic_sds_remote_device_resetting_state_exit + }, + [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { + .enter_state = scic_sds_remote_device_final_state_enter, + }, +}; + diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h new file mode 100644 index 000000000000..44185a2738ec --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -0,0 +1,602 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_REMOTE_DEVICE_H_ +#define _SCIC_SDS_REMOTE_DEVICE_H_ + +/** + * This file contains the structures, constants, and prototypes for the + * struct scic_sds_remote_device object. + * + * + */ + +#include "intel_sas.h" +#include "sci_base_remote_device.h" +#include "sci_base_request.h" +#include "scu_remote_node_context.h" +#include "scic_sds_remote_node_context.h" + +struct scic_sds_controller; +struct scic_sds_port; +struct scic_sds_request; +struct scic_sds_remote_device_state_handler; + +/** + * enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES - + * + * This is the enumeration of the ready substates for the + * struct scic_sds_remote_device. + */ +enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES { + /** + * This is the initial state for the remote device ready substate. + */ + SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL, + + /** + * This is the ready operational substate for the remote device. This is the + * normal operational state for a remote device. + */ + SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL, + + /** + * This is the suspended state for the remote device. This is the state that + * the device is placed in when a RNC suspend is received by the SCU hardware. + */ + SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED, + + /** + * This is the final state that the device is placed in before a change to the + * base state machine. + */ + SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL, + + SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES +}; + +/** + * enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES - + * + * This is the enumeration for the struct scic_sds_remote_device ready substates for + * the STP remote device. + */ +enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES { + /** + * This is the idle substate for the stp remote device. When there are no + * active IO for the device it is is in this state. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, + + /** + * This is the command state for for the STP remote device. This state is + * entered when the device is processing a non-NCQ command. The device object + * will fail any new start IO requests until this command is complete. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD, + + /** + * This is the NCQ state for the STP remote device. This state is entered + * when the device is processing an NCQ reuqest. It will remain in this state + * so long as there is one or more NCQ requests being processed. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ, + + /** + * This is the NCQ error state for the STP remote device. This state is + * entered when an SDB error FIS is received by the device object while in the + * NCQ state. The device object will only accept a READ LOG command while in + * this state. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR, + +#if !defined(DISABLE_ATAPI) + /** + * This is the ATAPI error state for the STP ATAPI remote device. This state is + * entered when ATAPI device sends error status FIS without data while the device + * object is in CMD state. A suspension event is expected in this state. The device + * object will resume right away. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR, +#endif + + /** + * This is the READY substate indicates the device is waiting for the RESET task + * coming to be recovered from certain hardware specific error. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, + + SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES +}; + + +/** + * enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES - + * + * This is the enumeration of the ready substates for the SMP REMOTE DEVICE. + */ + +enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES { + /** + * This is the ready operational substate for the remote device. This is the + * normal operational state for a remote device. + */ + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, + + /** + * This is the suspended state for the remote device. This is the state that + * the device is placed in when a RNC suspend is received by the SCU hardware. + */ + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, + + SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES +}; + + + + +/** + * struct scic_sds_remote_device - This structure contains the data for an SCU + * implementation of the SCU Core device data. + * + * + */ +struct scic_sds_remote_device { + /** + * This field is the common base for all remote device objects. + */ + struct sci_base_remote_device parent; + + /** + * This field is the programmed device port width. This value is written to + * the RCN data structure to tell the SCU how many open connections this + * device can have. + */ + u32 device_port_width; + + /** + * This field is the programmed connection rate for this remote device. It is + * used to program the TC with the maximum allowed connection rate. + */ + enum sci_sas_link_rate connection_rate; + + /** + * This field contains the allowed target protocols for this remote device. + */ + struct smp_discover_response_protocols target_protocols; + + /** + * This field contains the device SAS address. + */ + struct sci_sas_address device_address; + + /** + * This filed is assinged the value of true if the device is directly attached + * to the port. + */ + bool is_direct_attached; + +#if !defined(DISABLE_ATAPI) + /** + * This filed is assinged the value of true if the device is an ATAPI device. + */ + bool is_atapi; +#endif + + /** + * This filed contains a pointer back to the port to which this device is + * assigned. + */ + struct scic_sds_port *owning_port; + + /** + * This field contains the SCU silicon remote node context specific + * information. + */ + struct scic_sds_remote_node_context *rnc; + + /** + * This field contains the stated request count for the remote device. The + * device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all + * requests are complete and the rnc_posted value is false. + */ + u32 started_request_count; + + /** + * This field contains a pointer to the working request object. It is only + * used only for SATA requests since the unsolicited frames we get from the + * hardware have no Tag value to look up the io request object. + */ + struct scic_sds_request *working_request; + + /** + * This field contains the reason for the remote device going not_ready. It is + * assigned in the state handlers and used in the state transition. + */ + u32 not_ready_reason; + + /** + * This field is true if this remote device has an initialzied ready substate + * machine. SSP devices do not have a ready substate machine and STP devices + * have a ready substate machine. + */ + bool has_ready_substate_machine; + + /** + * This field contains the state machine for the ready substate machine for + * this struct scic_sds_remote_device object. + */ + struct sci_base_state_machine ready_substate_machine; + + /** + * This field maintains the set of state handlers for the remote device + * object. These are changed each time the remote device enters a new state. + */ + struct scic_sds_remote_device_state_handler *state_handlers; +}; + + +typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_HANDLER_T)( + struct scic_sds_remote_device *this_device); + +typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T)( + struct scic_sds_remote_device *this_device, + u32 suspend_type); + +typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T)( + struct scic_sds_remote_device *this_device); + +typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T)( + struct scic_sds_remote_device *this_device, + u32 frame_index); + +typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T)( + struct scic_sds_remote_device *this_device, + u32 event_code); + +typedef void (*SCIC_SDS_REMOTE_DEVICE_READY_NOT_READY_HANDLER_T)( + struct scic_sds_remote_device *this_device); + +/** + * struct scic_sds_remote_device_state_handler - This structure conains the + * state handlers that are needed to process requests for the SCU remote + * device objects. + * + * + */ +struct scic_sds_remote_device_state_handler { + struct sci_base_remote_device_state_handler parent; + + SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T suspend_handler; + SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T resume_handler; + + SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T event_handler; + SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T frame_handler; + +}; + + +extern const struct sci_base_state scic_sds_remote_device_state_table[]; +extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[]; +extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[]; +extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[]; + +extern struct scic_sds_remote_device_state_handler + scic_sds_remote_device_state_handler_table[]; +extern struct scic_sds_remote_device_state_handler + scic_sds_ssp_remote_device_ready_substate_handler_table[]; +extern struct scic_sds_remote_device_state_handler + scic_sds_stp_remote_device_ready_substate_handler_table[]; +extern struct scic_sds_remote_device_state_handler + scic_sds_smp_remote_device_ready_substate_handler_table[]; + +/** + * scic_sds_remote_device_increment_request_count() - + * + * This macro incrments the request count for this device + */ +#define scic_sds_remote_device_increment_request_count(this_device) \ + ((this_device)->started_request_count++) + +/** + * scic_sds_remote_device_decrement_request_count() - + * + * This macro decrements the request count for this device. This count will + * never decrment past 0. + */ +#define scic_sds_remote_device_decrement_request_count(this_device) \ + ((this_device)->started_request_count > 0 ? \ + (this_device)->started_request_count-- : 0) + +/** + * scic_sds_remote_device_get_request_count() - + * + * This is a helper macro to return the current device request count. + */ +#define scic_sds_remote_device_get_request_count(this_device) \ + ((this_device)->started_request_count) + +/** + * scic_sds_remote_device_get_port() - + * + * This macro returns the owning port of this remote device obejct. + */ +#define scic_sds_remote_device_get_port(this_device) \ + ((this_device)->owning_port) + +/** + * scic_sds_remote_device_get_controller() - + * + * This macro returns the controller object that contains this device object + */ +#define scic_sds_remote_device_get_controller(this_device) \ + scic_sds_port_get_controller(scic_sds_remote_device_get_port(this_device)) + +/** + * scic_sds_remote_device_set_state_handlers() - + * + * This macro sets the remote device state handlers pointer and is set on entry + * to each device state. + */ +#define scic_sds_remote_device_set_state_handlers(this_device, handlers) \ + ((this_device)->state_handlers = (handlers)) + +/** + * scic_sds_remote_device_get_base_state_machine() - + * + * This macro returns the base sate machine object for the remote device. + */ +#define scic_sds_remote_device_get_base_state_machine(this_device) \ + (&(this_device)->parent.state_machine) + +/** + * scic_sds_remote_device_get_ready_substate_machine() - + * + * This macro returns the remote device ready substate machine + */ +#define scic_sds_remote_device_get_ready_substate_machine(this_device) \ + (&(this_device)->ready_substate_machine) + +/** + * scic_sds_remote_device_get_port() - + * + * This macro returns the owning port of this device + */ +#define scic_sds_remote_device_get_port(this_device) \ + ((this_device)->owning_port) + +/** + * scic_sds_remote_device_get_sequence() - + * + * This macro returns the remote device sequence value + */ +#define scic_sds_remote_device_get_sequence(this_device) \ + (\ + scic_sds_remote_device_get_controller(this_device)-> \ + remote_device_sequence[(this_device)->rnc->remote_node_index] \ + ) + +/** + * scic_sds_remote_device_get_controller_peg() - + * + * This macro returns the controllers protocol engine group + */ +#define scic_sds_remote_device_get_controller_peg(this_device) \ + (\ + scic_sds_controller_get_protocol_engine_group(\ + scic_sds_port_get_controller(\ + scic_sds_remote_device_get_port(this_device) \ + ) \ + ) \ + ) + +/** + * scic_sds_remote_device_get_port_index() - + * + * This macro returns the port index for the devices owning port + */ +#define scic_sds_remote_device_get_port_index(this_device) \ + (scic_sds_port_get_index(scic_sds_remote_device_get_port(this_device))) + +/** + * scic_sds_remote_device_get_index() - + * + * This macro returns the remote node index for this device object + */ +#define scic_sds_remote_device_get_index(this_device) \ + ((this_device)->rnc->remote_node_index) + +/** + * scic_sds_remote_device_build_command_context() - + * + * This macro builds a remote device context for the SCU post request operation + */ +#define scic_sds_remote_device_build_command_context(device, command) \ + ((command) \ + | (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \ + | (scic_sds_remote_device_get_port_index((device)) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \ + | (scic_sds_remote_device_get_index((device))) \ + ) + +/** + * scic_sds_remote_device_set_working_request() - + * + * This macro makes the working request assingment for the remote device + * object. To clear the working request use this macro with a NULL request + * object. + */ +#define scic_sds_remote_device_set_working_request(device, request) \ + ((device)->working_request = (request)) + +/* --------------------------------------------------------------------------- */ + + + +enum sci_status scic_sds_remote_device_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index); + +enum sci_status scic_sds_remote_device_event_handler( + struct scic_sds_remote_device *this_device, + u32 event_code); + +enum sci_status scic_sds_remote_device_start_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *this_device, + struct scic_sds_request *io_request); + +enum sci_status scic_sds_remote_device_complete_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *this_device, + struct scic_sds_request *io_request); + +enum sci_status scic_sds_remote_device_resume( + struct scic_sds_remote_device *this_device); + +enum sci_status scic_sds_remote_device_suspend( + struct scic_sds_remote_device *this_device, + u32 suspend_type); + +enum sci_status scic_sds_remote_device_start_task( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *this_device, + struct scic_sds_request *io_request); + +void scic_sds_remote_device_post_request( + struct scic_sds_remote_device *this_device, + u32 request); + +#if !defined(DISABLE_ATAPI) +bool scic_sds_remote_device_is_atapi( + struct scic_sds_remote_device *this_device); +#else /* !defined(DISABLE_ATAPI) */ +#define scic_sds_remote_device_is_atapi(this_device) false +#endif /* !defined(DISABLE_ATAPI) */ + +/* --------------------------------------------------------------------------- */ + +/* --------------------------------------------------------------------------- */ + +void scic_sds_remote_device_start_request( + struct scic_sds_remote_device *this_device, + struct scic_sds_request *the_request, + enum sci_status status); + +void scic_sds_remote_device_continue_request( + struct scic_sds_remote_device *this_device); + +enum sci_status scic_sds_remote_device_default_start_handler( + struct sci_base_remote_device *this_device); + + +enum sci_status scic_sds_remote_device_default_fail_handler( + struct sci_base_remote_device *this_device); + +enum sci_status scic_sds_remote_device_default_destruct_handler( + struct sci_base_remote_device *this_device); + +enum sci_status scic_sds_remote_device_default_reset_handler( + struct sci_base_remote_device *device); + +enum sci_status scic_sds_remote_device_default_reset_complete_handler( + struct sci_base_remote_device *device); + +enum sci_status scic_sds_remote_device_default_start_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request); + +enum sci_status scic_sds_remote_device_default_complete_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request); + +enum sci_status scic_sds_remote_device_default_continue_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request); + +enum sci_status scic_sds_remote_device_default_suspend_handler( + struct scic_sds_remote_device *this_device, + u32 suspend_type); + +enum sci_status scic_sds_remote_device_default_resume_handler( + struct scic_sds_remote_device *this_device); + + +enum sci_status scic_sds_remote_device_default_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index); + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_sds_remote_device_ready_state_stop_handler( + struct sci_base_remote_device *device); + +enum sci_status scic_sds_remote_device_ready_state_reset_handler( + struct sci_base_remote_device *device); + +enum sci_status scic_sds_remote_device_general_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index); + +enum sci_status scic_sds_remote_device_general_event_handler( + struct scic_sds_remote_device *this_device, + u32 event_code); + +enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler( + struct scic_sds_remote_device *this_device); + +/* --------------------------------------------------------------------------- */ + + +#endif /* _SCIC_SDS_REMOTE_DEVICE_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c new file mode 100644 index 000000000000..79fe9a8cd1ed --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c @@ -0,0 +1,1244 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sci_base_state_machine.h" +#include "scic_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_remote_node_context.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_event_codes.h" +#include "scu_task_context.h" + +void scic_sds_remote_node_context_construct( + struct scic_sds_remote_device *device, + struct scic_sds_remote_node_context *rnc, + u16 remote_node_index) +{ + memset(rnc, 0, sizeof(struct scic_sds_remote_node_context)); + + rnc->remote_node_index = remote_node_index; + rnc->device = device; + rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; + + sci_base_state_machine_construct( + &rnc->state_machine, + &rnc->parent, + scic_sds_remote_node_context_state_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE + ); + + sci_base_state_machine_start(&rnc->state_machine); +} + +/** + * + * @this_rnc: The RNC for which the is posted request is being made. + * + * This method will return true if the RNC is not in the initial state. In all + * other states the RNC is considered active and this will return true. The + * destroy request of the state machine drives the RNC back to the initial + * state. If the state machine changes then this routine will also have to be + * changed. bool true if the state machine is not in the initial state false if + * the state machine is in the initial state + */ + +/** + * + * @this_rnc: The state of the remote node context object to check. + * + * This method will return true if the remote node context is in a READY state + * otherwise it will return false bool true if the remote node context is in + * the ready state. false if the remote node context is not in the ready state. + */ +bool scic_sds_remote_node_context_is_ready( + struct scic_sds_remote_node_context *this_rnc) +{ + u32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine); + + if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { + return true; + } + + return false; +} + +/** + * + * @this_device: The remote device to use to construct the RNC buffer. + * @rnc: The buffer into which the remote device data will be copied. + * + * This method will construct the RNC buffer for this remote device object. none + */ +void scic_sds_remote_node_context_construct_buffer( + struct scic_sds_remote_node_context *this_rnc) +{ + union scu_remote_node_context *rnc; + struct scic_sds_controller *the_controller; + + the_controller = scic_sds_remote_device_get_controller(this_rnc->device); + + rnc = scic_sds_controller_get_remote_node_context_buffer( + the_controller, this_rnc->remote_node_index); + + memset( + rnc, + 0x00, + sizeof(union scu_remote_node_context) + * scic_sds_remote_device_node_count(this_rnc->device) + ); + + rnc->ssp.remote_node_index = this_rnc->remote_node_index; + rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width; + rnc->ssp.logical_port_index = + scic_sds_remote_device_get_port_index(this_rnc->device); + + rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high); + rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low); + + rnc->ssp.nexus_loss_timer_enable = true; + rnc->ssp.check_bit = false; + rnc->ssp.is_valid = false; + rnc->ssp.is_remote_node_context = true; + rnc->ssp.function_number = 0; + + rnc->ssp.arbitration_wait_time = 0; + + + if ( + this_rnc->device->target_protocols.u.bits.attached_sata_device + || this_rnc->device->target_protocols.u.bits.attached_stp_target + ) { + rnc->ssp.connection_occupancy_timeout = + the_controller->user_parameters.sds1.stp_max_occupancy_timeout; + rnc->ssp.connection_inactivity_timeout = + the_controller->user_parameters.sds1.stp_inactivity_timeout; + } else { + rnc->ssp.connection_occupancy_timeout = + the_controller->user_parameters.sds1.ssp_max_occupancy_timeout; + rnc->ssp.connection_inactivity_timeout = + the_controller->user_parameters.sds1.ssp_inactivity_timeout; + } + + rnc->ssp.initial_arbitration_wait_time = 0; + + /* Open Address Frame Parameters */ + rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate; + rnc->ssp.oaf_features = 0; + rnc->ssp.oaf_source_zone_group = 0; + rnc->ssp.oaf_more_compatibility_features = 0; +} + +/** + * + * @this_rnc: + * @the_callback: + * @callback_parameter: + * + * This method will setup the remote node context object so it will transition + * to its ready state. If the remote node context is already setup to + * transition to its final state then this function does nothing. none + */ +static void scic_sds_remote_node_context_setup_to_resume( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { + this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY; + this_rnc->user_callback = the_callback; + this_rnc->user_cookie = callback_parameter; + } +} + +/** + * + * @this_rnc: + * @the_callback: + * @callback_parameter: + * + * This method will setup the remote node context object so it will transistion + * to its final state. none + */ +static void scic_sds_remote_node_context_setup_to_destory( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; + this_rnc->user_callback = the_callback; + this_rnc->user_cookie = callback_parameter; +} + +/** + * + * @this_rnc: + * @the_callback: + * + * This method will continue to resume a remote node context. This is used in + * the states where a resume is requested while a resume is in progress. + */ +static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { + this_rnc->user_callback = the_callback; + this_rnc->user_cookie = callback_parameter; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_STATE; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_default_destruct_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to stop while " + "in unexpected state %d\n", + __func__, + this_rnc, + sci_base_state_machine_get_state(&this_rnc->state_machine)); + + /* + * We have decided that the destruct request on the remote node context can not fail + * since it is either in the initial/destroyed state or is can be destroyed. */ + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_remote_node_context_default_suspend_handler( + struct scic_sds_remote_node_context *this_rnc, + u32 suspend_type, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to suspend " + "while in wrong state %d\n", + __func__, + this_rnc, + sci_base_state_machine_get_state(&this_rnc->state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_remote_node_context_default_resume_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to resume " + "while in wrong state %d\n", + __func__, + this_rnc, + sci_base_state_machine_get_state(&this_rnc->state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_remote_node_context_default_start_io_handler( + struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_request *the_request) +{ + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to start io " + "0x%p while in wrong state %d\n", + __func__, + this_rnc, + the_request, + sci_base_state_machine_get_state(&this_rnc->state_machine)); + + return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; +} + +static enum sci_status scic_sds_remote_node_context_default_start_task_handler( + struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_request *the_request) +{ + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to start " + "task 0x%p while in wrong state %d\n", + __func__, + this_rnc, + the_request, + sci_base_state_machine_get_state(&this_rnc->state_machine)); + + return SCI_FAILURE; +} + +static enum sci_status scic_sds_remote_node_context_default_event_handler( + struct scic_sds_remote_node_context *this_rnc, + u32 event_code) +{ + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to process " + "event 0x%x while in wrong state %d\n", + __func__, + this_rnc, + event_code, + sci_base_state_machine_get_state(&this_rnc->state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @this_rnc: The rnc for which the task request is targeted. + * @the_request: The request which is going to be started. + * + * This method determines if the task request can be started by the SCU + * hardware. When the RNC is in the ready state any task can be started. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_success_start_task_handler( + struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_request *the_request) +{ + return SCI_SUCCESS; +} + +/** + * + * @this_rnc: + * @the_callback: + * @callback_parameter: + * + * This method handles destruct calls from the various state handlers. The + * remote node context can be requested to destroy from any state. If there was + * a user callback it is always replaced with the request to destroy user + * callback. enum sci_status + */ +static enum sci_status scic_sds_remote_node_context_general_destruct_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + scic_sds_remote_node_context_setup_to_destory( + this_rnc, the_callback, callback_parameter + ); + + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE + ); + + return SCI_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + scic_sds_remote_node_context_setup_to_resume( + this_rnc, the_callback, callback_parameter + ); + + scic_sds_remote_node_context_construct_buffer(this_rnc); + + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE + ); + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_STATE; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( + struct scic_sds_remote_node_context *this_rnc, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_POST_RNC_COMPLETE: + status = SCI_SUCCESS; + + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE + ); + break; + + default: + status = SCI_FAILURE; + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to " + "process unexpected event 0x%x while in posting " + "state\n", + __func__, + this_rnc, + event_code); + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + scic_sds_remote_node_context_setup_to_destory( + this_rnc, the_callback, callback_parameter + ); + + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler( + struct scic_sds_remote_node_context *this_rnc, + u32 event_code) +{ + enum sci_status status; + + if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { + status = SCI_SUCCESS; + + if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE + ); + } else { + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE + ); + } + } else { + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + /* + * We really dont care if the hardware is going to suspend + * the device since it's being invalidated anyway */ + dev_dbg(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p was " + "suspeneded by hardware while being " + "invalidated.\n", + __func__, + this_rnc); + status = SCI_SUCCESS; + break; + + default: + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p " + "requested to process event 0x%x while " + "in state %d.\n", + __func__, + this_rnc, + event_code, + sci_base_state_machine_get_state( + &this_rnc->state_machine)); + status = SCI_FAILURE; + break; + } + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + + +static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler( + struct scic_sds_remote_node_context *this_rnc, + u32 event_code) +{ + enum sci_status status; + + if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) { + status = SCI_SUCCESS; + + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE + ); + } else { + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + /* + * We really dont care if the hardware is going to suspend + * the device since it's being resumed anyway */ + dev_dbg(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p was " + "suspeneded by hardware while being resumed.\n", + __func__, + this_rnc); + status = SCI_SUCCESS; + break; + + default: + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested " + "to process event 0x%x while in state %d.\n", + __func__, + this_rnc, + event_code, + sci_base_state_machine_get_state( + &this_rnc->state_machine)); + status = SCI_FAILURE; + break; + } + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +/** + * + * @this_rnc: The remote node context object being suspended. + * @the_callback: The callback when the suspension is complete. + * @callback_parameter: The parameter that is to be passed into the callback. + * + * This method will handle the suspend requests from the ready state. + * SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( + struct scic_sds_remote_node_context *this_rnc, + u32 suspend_type, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + this_rnc->user_callback = the_callback; + this_rnc->user_cookie = callback_parameter; + this_rnc->suspension_code = suspend_type; + + if (suspend_type == SCI_SOFTWARE_SUSPENSION) { + scic_sds_remote_device_post_request( + this_rnc->device, + SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX + ); + } + + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE + ); + + return SCI_SUCCESS; +} + +/** + * + * @this_rnc: The rnc for which the io request is targeted. + * @the_request: The request which is going to be started. + * + * This method determines if the io request can be started by the SCU hardware. + * When the RNC is in the ready state any io request can be started. enum sci_status + * SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler( + struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_request *the_request) +{ + return SCI_SUCCESS; +} + + +static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( + struct scic_sds_remote_node_context *this_rnc, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TL_RNC_SUSPEND_TX: + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE + ); + + this_rnc->suspension_code = scu_get_event_specifier(event_code); + status = SCI_SUCCESS; + break; + + case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE + ); + + this_rnc->suspension_code = scu_get_event_specifier(event_code); + status = SCI_SUCCESS; + break; + + default: + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to " + "process event 0x%x while in state %d.\n", + __func__, + this_rnc, + event_code, + sci_base_state_machine_get_state( + &this_rnc->state_machine)); + + status = SCI_FAILURE; + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + enum sci_status status; + struct smp_discover_response_protocols protocols; + + scic_sds_remote_node_context_setup_to_resume( + this_rnc, the_callback, callback_parameter + ); + + /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ + + scic_remote_device_get_protocols(this_rnc->device, &protocols); + + if ( + (protocols.u.bits.attached_ssp_target == 1) + || (protocols.u.bits.attached_smp_target == 1) + ) { + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE + ); + + status = SCI_SUCCESS; + } else if (protocols.u.bits.attached_stp_target == 1) { + if (this_rnc->device->is_direct_attached) { + /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ + scic_sds_port_set_direct_attached_device_id( + this_rnc->device->owning_port, + this_rnc->remote_node_index + ); + + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE + ); + } else { + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE + ); + } + + status = SCI_SUCCESS; + } else { + status = SCI_FAILURE; + } + + return status; +} + +/** + * + * @this_rnc: The remote node context which is to receive the task request. + * @the_request: The task request to be transmitted to to the remote target + * device. + * + * This method will report a success or failure attempt to start a new task + * request to the hardware. Since all task requests are sent on the high + * priority queue they can be sent when the RCN is in a TX suspend state. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler( + struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_request *the_request) +{ + scic_sds_remote_node_context_resume(this_rnc, NULL, NULL); + + return SCI_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + scic_sds_remote_node_context_setup_to_resume( + this_rnc, the_callback, callback_parameter + ); + + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE + ); + + return SCI_FAILURE_INVALID_STATE; +} + +/* --------------------------------------------------------------------------- */ + +/** + * + * + * + */ +static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter) +{ + scic_sds_remote_node_context_setup_to_resume( + this_rnc, the_callback, callback_parameter + ); + + return SCI_SUCCESS; +} + +/** + * + * @this_rnc: The remote node context which is to receive the task request. + * @the_request: The task request to be transmitted to to the remote target + * device. + * + * This method will report a success or failure attempt to start a new task + * request to the hardware. Since all task requests are sent on the high + * priority queue they can be sent when the RCN is in a TX suspend state. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler( + struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_request *the_request) +{ + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler( + struct scic_sds_remote_node_context *this_rnc, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TL_RNC_SUSPEND_TX: + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE + ); + + this_rnc->suspension_code = scu_get_event_specifier(event_code); + status = SCI_SUCCESS; + break; + + case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: + sci_base_state_machine_change_state( + &this_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE + ); + + this_rnc->suspension_code = scu_get_event_specifier(event_code); + status = SCI_SUCCESS; + break; + + default: + dev_warn(scirdev_to_dev(this_rnc->device), + "%s: SCIC Remote Node Context 0x%p requested to " + "process event 0x%x while in state %d.\n", + __func__, + this_rnc, + event_code, + sci_base_state_machine_get_state( + &this_rnc->state_machine)); + + status = SCI_FAILURE; + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_remote_node_context_handlers +scic_sds_remote_node_context_state_handler_table[ + SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] = +{ + /* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */ + { + scic_sds_remote_node_context_default_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_initial_state_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_default_start_task_handler, + scic_sds_remote_node_context_default_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_continue_to_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_default_start_task_handler, + scic_sds_remote_node_context_posting_state_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */ + { + scic_sds_remote_node_context_invalidating_state_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_continue_to_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_default_start_task_handler, + scic_sds_remote_node_context_invalidating_state_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_continue_to_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_success_start_task_handler, + scic_sds_remote_node_context_resuming_state_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_ready_state_suspend_handler, + scic_sds_remote_node_context_default_resume_handler, + scic_sds_remote_node_context_ready_state_start_io_handler, + scic_sds_remote_node_context_success_start_task_handler, + scic_sds_remote_node_context_ready_state_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_tx_suspended_state_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_suspended_start_task_handler, + scic_sds_remote_node_context_default_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_suspended_start_task_handler, + scic_sds_remote_node_context_default_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_await_suspension_state_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_await_suspension_state_start_task_handler, + scic_sds_remote_node_context_await_suspension_state_event_handler + } +}; + +/* + * ***************************************************************************** + * * REMOTE NODE CONTEXT PRIVATE METHODS + * ***************************************************************************** */ + +/** + * + * + * This method just calls the user callback function and then resets the + * callback. + */ +static void scic_sds_remote_node_context_notify_user( + struct scic_sds_remote_node_context *rnc) +{ + if (rnc->user_callback != NULL) { + (*rnc->user_callback)(rnc->user_cookie); + + rnc->user_callback = NULL; + rnc->user_cookie = NULL; + } +} + +/** + * + * + * This method will continue the remote node context state machine by + * requesting to resume the remote node context state machine from its current + * state. + */ +static void scic_sds_remote_node_context_continue_state_transitions( + struct scic_sds_remote_node_context *rnc) +{ + if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { + rnc->state_handlers->resume_handler( + rnc, rnc->user_callback, rnc->user_cookie + ); + } +} + +/** + * + * @this_rnc: The remote node context object that is to be validated. + * + * This method will mark the rnc buffer as being valid and post the request to + * the hardware. none + */ +static void scic_sds_remote_node_context_validate_context_buffer( + struct scic_sds_remote_node_context *this_rnc) +{ + union scu_remote_node_context *rnc_buffer; + + rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( + scic_sds_remote_device_get_controller(this_rnc->device), + this_rnc->remote_node_index + ); + + rnc_buffer->ssp.is_valid = true; + + if ( + !this_rnc->device->is_direct_attached + && this_rnc->device->target_protocols.u.bits.attached_stp_target + ) { + scic_sds_remote_device_post_request( + this_rnc->device, + SCU_CONTEXT_COMMAND_POST_RNC_96 + ); + } else { + scic_sds_remote_device_post_request( + this_rnc->device, + SCU_CONTEXT_COMMAND_POST_RNC_32 + ); + + if (this_rnc->device->is_direct_attached) { + scic_sds_port_set_direct_attached_device_id( + this_rnc->device->owning_port, + this_rnc->remote_node_index + ); + } + } +} + +/** + * + * @this_rnc: The remote node context object that is to be invalidated. + * + * This method will update the RNC buffer and post the invalidate request. none + */ +static void scic_sds_remote_node_context_invalidate_context_buffer( + struct scic_sds_remote_node_context *this_rnc) +{ + union scu_remote_node_context *rnc_buffer; + + rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( + scic_sds_remote_device_get_controller(this_rnc->device), + this_rnc->remote_node_index + ); + + rnc_buffer->ssp.is_valid = false; + + scic_sds_remote_device_post_request( + this_rnc->device, + SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE + ); + + if (this_rnc->device->is_direct_attached) { + scic_sds_port_set_direct_attached_device_id( + this_rnc->device->owning_port, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX + ); + } +} + +/* + * ***************************************************************************** + * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS + * ***************************************************************************** */ + +/** + * + * + * + */ +static void scic_sds_remote_node_context_initial_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE + ); + + /* + * Check to see if we have gotten back to the initial state because someone + * requested to destroy the remote node context object. */ + if ( + rnc->state_machine.previous_state_id + == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE + ) { + rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; + + scic_sds_remote_node_context_notify_user(rnc); + } +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_posting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *this_rnc; + + this_rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + this_rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE + ); + + scic_sds_remote_node_context_validate_context_buffer(this_rnc); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_invalidating_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE + ); + + scic_sds_remote_node_context_invalidate_context_buffer(rnc); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_resuming_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE + ); + + scic_sds_remote_device_post_request( + rnc->device, + SCU_CONTEXT_COMMAND_POST_RNC_RESUME + ); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_ready_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE + ); + + rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; + + if (rnc->user_callback != NULL) { + scic_sds_remote_node_context_notify_user(rnc); + } +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_tx_suspended_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE + ); + + scic_sds_remote_node_context_continue_state_transitions(rnc); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE + ); + + scic_sds_remote_node_context_continue_state_transitions(rnc); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_await_suspension_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_remote_node_context_state_table[] = { + [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { + .enter_state = scic_sds_remote_node_context_initial_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { + .enter_state = scic_sds_remote_node_context_posting_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { + .enter_state = scic_sds_remote_node_context_invalidating_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { + .enter_state = scic_sds_remote_node_context_resuming_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { + .enter_state = scic_sds_remote_node_context_ready_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { + .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { + .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { + .enter_state = scic_sds_remote_node_context_await_suspension_state_enter, + }, +}; + diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h new file mode 100644 index 000000000000..59eacf8f400c --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h @@ -0,0 +1,342 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ +#define _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ + +/** + * This file contains the structures, constants, and prototypes associated with + * the remote node context in the silicon. It exists to model and manage + * the remote node context in the silicon. + * + * + */ + +#include "sci_types.h" +#include "sci_base_state.h" +#include "sci_base_state_machine.h" + +/* --------------------------------------------------------------------------- */ + +/** + * + * + * This constant represents an invalid remote device id, it is used to program + * the STPDARNI register so the driver knows when it has received a SIGNATURE + * FIS from the SCU. + */ +#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF + +#define SCU_HARDWARE_SUSPENSION (0) +#define SCI_SOFTWARE_SUSPENSION (1) + +struct scic_sds_request; +struct scic_sds_remote_device; +struct scic_sds_remote_node_context; + +typedef void (*SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK)(void *); + +typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION)( + struct scic_sds_remote_node_context *this_rnc, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter + ); + +typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION)( + struct scic_sds_remote_node_context *this_rnc, + u32 suspension_type, + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + void *callback_parameter + ); + +typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST)( + struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_request *the_request + ); + +typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER)( + struct scic_sds_remote_node_context *this_rnc, + u32 event_code + ); + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_remote_node_context_handlers { + /** + * This handle is invoked to stop the RNC. The callback is invoked when after + * the hardware notification that the RNC has been invalidated. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION destruct_handler; + + /** + * This handler is invoked when there is a request to suspend the RNC. The + * callback is invoked after the hardware notification that the remote node is + * suspended. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION suspend_handler; + + /** + * This handler is invoked when there is a request to resume the RNC. The + * callback is invoked when after the RNC has reached the ready state. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION resume_handler; + + /** + * This handler is invoked when there is a request to start an io request + * operation. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_io_handler; + + /** + * This handler is invoked when there is a request to start a task request + * operation. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_task_handler; + + /** + * This handler is invoked where there is an RNC event that must be processed. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER event_handler; + +}; + +/* --------------------------------------------------------------------------- */ + +/** + * + * + * This is the enumeration of the remote node context states. + */ +enum scis_sds_remote_node_context_states { + /** + * This state is the initial state for a remote node context. On a resume + * request the remote node context will transition to the posting state. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE, + + /** + * This is a transition state that posts the RNi to the hardware. Once the RNC + * is posted the remote node context will be made ready. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE, + + /** + * This is a transition state that will post an RNC invalidate to the + * hardware. Once the invalidate is complete the remote node context will + * transition to the posting state. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE, + + /** + * This is a transition state that will post an RNC resume to the hardare. + * Once the event notification of resume complete is received the remote node + * context will transition to the ready state. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE, + + /** + * This is the state that the remote node context must be in to accept io + * request operations. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE, + + /** + * This is the state that the remote node context transitions to when it gets + * a TX suspend notification from the hardware. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE, + + /** + * This is the state that the remote node context transitions to when it gets + * a TX RX suspend notification from the hardware. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE, + + /** + * This state is a wait state for the remote node context that waits for a + * suspend notification from the hardware. This state is entered when either + * there is a request to supend the remote node context or when there is a TC + * completion where the remote node will be suspended by the hardware. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE, + + SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES + +}; + +/** + * + * + * This enumeration is used to define the end destination state for the remote + * node context. + */ +enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE { + SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED, + SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY, + SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL +}; + +/** + * struct scic_sds_remote_node_context - This structure contains the data + * associated with the remote node context object. The remote node context + * (RNC) object models the the remote device information necessary to manage + * the silicon RNC. + * + * + */ +struct scic_sds_remote_node_context { + /* + * parent object + */ + struct sci_base_object parent; + + /** + * This pointer simply points to the remote device object containing + * this RNC. + * + * @todo Consider making the device pointer the associated object of the + * the parent object. + */ + struct scic_sds_remote_device *device; + + /** + * This field indicates the remote node index (RNI) associated with + * this RNC. + */ + u16 remote_node_index; + + /** + * This field is the recored suspension code or the reason for the remote node + * context suspension. + */ + u32 suspension_code; + + /** + * This field is true if the remote node context is resuming from its current + * state. This can cause an automatic resume on receiving a suspension + * notification. + */ + enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE destination_state; + + /** + * This field contains the callback function that the user requested to be + * called when the requested state transition is complete. + */ + SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK user_callback; + + /** + * This field contains the parameter that is called when the user requested + * state transition is completed. + */ + void *user_cookie; + + /** + * This field contains the data for the object's state machine. + */ + struct sci_base_state_machine state_machine; + + struct scic_sds_remote_node_context_handlers *state_handlers; +}; + +/* --------------------------------------------------------------------------- */ + +extern const struct sci_base_state scic_sds_remote_node_context_state_table[]; + +extern struct scic_sds_remote_node_context_handlers + scic_sds_remote_node_context_state_handler_table[ + SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES]; + +/* --------------------------------------------------------------------------- */ + +void scic_sds_remote_node_context_construct( + struct scic_sds_remote_device *device, + struct scic_sds_remote_node_context *rnc, + u16 remote_node_index); + +void scic_sds_remote_node_context_construct_buffer( + struct scic_sds_remote_node_context *rnc); + + +bool scic_sds_remote_node_context_is_ready( + struct scic_sds_remote_node_context *this_rnc); + +#define scic_sds_remote_node_context_set_remote_node_index(rnc, rni) \ + ((rnc)->remote_node_index = (rni)) + +#define scic_sds_remote_node_context_get_remote_node_index(rcn) \ + ((rnc)->remote_node_index) + +#define scic_sds_remote_node_context_event_handler(rnc, event_code) \ + ((rnc)->state_handlers->event_handler(rnc, event_code)) + +#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \ + ((rnc)->state_handlers->resume_handler(rnc, callback, parameter)) + +#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \ + ((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter)) + +#define scic_sds_remote_node_context_destruct(rnc, callback, parameter) \ + ((rnc)->state_handlers->destruct_handler(rnc, callback, parameter)) + +#define scic_sds_remote_node_context_start_io(rnc, request) \ + ((rnc)->state_handlers->start_io_handler(rnc, request)) + +#define scic_sds_remote_node_context_start_task(rnc, task) \ + ((rnc)->state_handlers->start_task_handler(rnc, task)) + +/* --------------------------------------------------------------------------- */ + +#endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ + diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.c b/drivers/scsi/isci/core/scic_sds_remote_node_table.c new file mode 100644 index 000000000000..77919a2cf652 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_node_table.c @@ -0,0 +1,600 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the implementation of the SCIC_SDS_REMOTE_NODE_TABLE + * public, protected, and private methods. + * + * + */ +#include "sci_util.h" +#include "sci_environment.h" +#include "scic_sds_remote_node_table.h" +#include "scic_sds_remote_node_context.h" + +/** + * + * @remote_node_table: This is the remote node index table from which the + * selection will be made. + * @group_table_index: This is the index to the group table from which to + * search for an available selection. + * + * This routine will find the bit position in absolute bit terms of the next 32 + * + bit position. If there are available bits in the first u32 then it is + * just bit position. u32 This is the absolute bit position for an available + * group. + */ +static u32 scic_sds_remote_node_table_get_group_index( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index) +{ + u32 dword_index; + u32 *group_table; + u32 bit_index; + + group_table = remote_node_table->remote_node_groups[group_table_index]; + + for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++) { + if (group_table[dword_index] != 0) { + for (bit_index = 0; bit_index < 32; bit_index++) { + if ((group_table[dword_index] & (1 << bit_index)) != 0) { + return (dword_index * 32) + bit_index; + } + } + } + } + + return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX; +} + +/** + * + * @out]: remote_node_table This the remote node table in which to clear the + * selector. + * @set_index: This is the remote node selector in which the change will be + * made. + * @group_index: This is the bit index in the table to be modified. + * + * This method will clear the group index entry in the specified group index + * table. none + */ +static void scic_sds_remote_node_table_clear_group_index( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index, + u32 group_index) +{ + u32 dword_index; + u32 bit_index; + u32 *group_table; + + BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT); + BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32)); + + dword_index = group_index / 32; + bit_index = group_index % 32; + group_table = remote_node_table->remote_node_groups[group_table_index]; + + group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index); +} + +/** + * + * @out]: remote_node_table This the remote node table in which to set the + * selector. + * @group_table_index: This is the remote node selector in which the change + * will be made. + * @group_index: This is the bit position in the table to be modified. + * + * This method will set the group index bit entry in the specified gropu index + * table. none + */ +static void scic_sds_remote_node_table_set_group_index( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index, + u32 group_index) +{ + u32 dword_index; + u32 bit_index; + u32 *group_table; + + BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT); + BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32)); + + dword_index = group_index / 32; + bit_index = group_index % 32; + group_table = remote_node_table->remote_node_groups[group_table_index]; + + group_table[dword_index] = group_table[dword_index] | (1 << bit_index); +} + +/** + * + * @out]: remote_node_table This is the remote node table in which to modify + * the remote node availability. + * @remote_node_index: This is the remote node index that is being returned to + * the table. + * + * This method will set the remote to available in the remote node allocation + * table. none + */ +static void scic_sds_remote_node_table_set_node_index( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 slot_normalized; + u32 slot_position; + + BUG_ON( + (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) + <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT) + ); + + dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD; + dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD; + slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32); + slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT; + + remote_node_table->available_remote_nodes[dword_location] |= + 1 << (slot_normalized + slot_position); +} + +/** + * + * @out]: remote_node_table This is the remote node table from which to clear + * the available remote node bit. + * @remote_node_index: This is the remote node index which is to be cleared + * from the table. + * + * This method clears the remote node index from the table of available remote + * nodes. none + */ +static void scic_sds_remote_node_table_clear_node_index( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 slot_position; + u32 slot_normalized; + + BUG_ON( + (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) + <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT) + ); + + dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD; + dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD; + slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32); + slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT; + + remote_node_table->available_remote_nodes[dword_location] &= + ~(1 << (slot_normalized + slot_position)); +} + +/** + * + * @out]: remote_node_table The remote node table from which the slot will be + * cleared. + * @group_index: The index for the slot that is to be cleared. + * + * This method clears the entire table slot at the specified slot index. none + */ +static void scic_sds_remote_node_table_clear_group( + struct scic_remote_node_table *remote_node_table, + u32 group_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 dword_value; + + BUG_ON( + (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) + <= (group_index / SCU_STP_REMOTE_NODE_COUNT) + ); + + dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + + dword_value = remote_node_table->available_remote_nodes[dword_location]; + dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); + remote_node_table->available_remote_nodes[dword_location] = dword_value; +} + +/** + * + * @remote_node_table: + * + * THis method sets an entire remote node group in the remote node table. + */ +static void scic_sds_remote_node_table_set_group( + struct scic_remote_node_table *remote_node_table, + u32 group_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 dword_value; + + BUG_ON( + (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) + <= (group_index / SCU_STP_REMOTE_NODE_COUNT) + ); + + dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + + dword_value = remote_node_table->available_remote_nodes[dword_location]; + dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); + remote_node_table->available_remote_nodes[dword_location] = dword_value; +} + +/** + * + * @remote_node_table: This is the remote node table that for which the group + * value is to be returned. + * @group_index: This is the group index to use to find the group value. + * + * This method will return the group value for the specified group index. The + * bit values at the specified remote node group index. + */ +static u8 scic_sds_remote_node_table_get_group_value( + struct scic_remote_node_table *remote_node_table, + u32 group_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 dword_value; + + dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + + dword_value = remote_node_table->available_remote_nodes[dword_location]; + dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); + dword_value = dword_value >> (dword_remainder * 4); + + return (u8)dword_value; +} + +/** + * + * @out]: remote_node_table The remote that which is to be initialized. + * @remote_node_entries: The number of entries to put in the table. + * + * This method will initialize the remote node table for use. none + */ +void scic_sds_remote_node_table_initialize( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_entries) +{ + u32 index; + + /* + * Initialize the raw data we could improve the speed by only initializing + * those entries that we are actually going to be used */ + memset( + remote_node_table->available_remote_nodes, + 0x00, + sizeof(remote_node_table->available_remote_nodes) + ); + + memset( + remote_node_table->remote_node_groups, + 0x00, + sizeof(remote_node_table->remote_node_groups) + ); + + /* Initialize the available remote node sets */ + remote_node_table->available_nodes_array_size = (u16) + (remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD) + + ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0); + + + /* Initialize each full DWORD to a FULL SET of remote nodes */ + for (index = 0; index < remote_node_entries; index++) { + scic_sds_remote_node_table_set_node_index(remote_node_table, index); + } + + remote_node_table->group_array_size = (u16) + (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32)) + + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0); + + for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++) { + /* + * These are all guaranteed to be full slot values so fill them in the + * available sets of 3 remote nodes */ + scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index); + } + + /* Now fill in any remainders that we may find */ + if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) { + scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index); + } else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) { + scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index); + } +} + +/** + * + * @out]: remote_node_table The remote node table from which to allocate a + * remote node. + * @table_index: The group index that is to be used for the search. + * + * This method will allocate a single RNi from the remote node table. The + * table index will determine from which remote node group table to search. + * This search may fail and another group node table can be specified. The + * function is designed to allow a serach of the available single remote node + * group up to the triple remote node group. If an entry is found in the + * specified table the remote node is removed and the remote node groups are + * updated. The RNi value or an invalid remote node context if an RNi can not + * be found. + */ +static u16 scic_sds_remote_node_table_allocate_single_remote_node( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index) +{ + u8 index; + u8 group_value; + u32 group_index; + u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + + group_index = scic_sds_remote_node_table_get_group_index( + remote_node_table, group_table_index); + + /* We could not find an available slot in the table selector 0 */ + if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { + group_value = scic_sds_remote_node_table_get_group_value( + remote_node_table, group_index); + + for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) { + if (((1 << index) & group_value) != 0) { + /* We have selected a bit now clear it */ + remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT + + index); + + scic_sds_remote_node_table_clear_group_index( + remote_node_table, group_table_index, group_index + ); + + scic_sds_remote_node_table_clear_node_index( + remote_node_table, remote_node_index + ); + + if (group_table_index > 0) { + scic_sds_remote_node_table_set_group_index( + remote_node_table, group_table_index - 1, group_index + ); + } + + break; + } + } + } + + return remote_node_index; +} + +/** + * + * @remote_node_table: This is the remote node table from which to allocate the + * remote node entries. + * @group_table_index: THis is the group table index which must equal two (2) + * for this operation. + * + * This method will allocate three consecutive remote node context entries. If + * there are no remaining triple entries the function will return a failure. + * The remote node index that represents three consecutive remote node entries + * or an invalid remote node context if none can be found. + */ +static u16 scic_sds_remote_node_table_allocate_triple_remote_node( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index) +{ + u32 group_index; + u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + + group_index = scic_sds_remote_node_table_get_group_index( + remote_node_table, group_table_index); + + if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { + remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT; + + scic_sds_remote_node_table_clear_group_index( + remote_node_table, group_table_index, group_index + ); + + scic_sds_remote_node_table_clear_group( + remote_node_table, group_index + ); + } + + return remote_node_index; +} + +/** + * + * @remote_node_table: This is the remote node table from which the remote node + * allocation is to take place. + * @remote_node_count: This is ther remote node count which is one of + * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). + * + * This method will allocate a remote node that mataches the remote node count + * specified by the caller. Valid values for remote node count is + * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). u16 This is + * the remote node index that is returned or an invalid remote node context. + */ +u16 scic_sds_remote_node_table_allocate_remote_node( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_count) +{ + u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + + if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { + remote_node_index = + scic_sds_remote_node_table_allocate_single_remote_node( + remote_node_table, 0); + + if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + remote_node_index = + scic_sds_remote_node_table_allocate_single_remote_node( + remote_node_table, 1); + } + + if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + remote_node_index = + scic_sds_remote_node_table_allocate_single_remote_node( + remote_node_table, 2); + } + } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { + remote_node_index = + scic_sds_remote_node_table_allocate_triple_remote_node( + remote_node_table, 2); + } + + return remote_node_index; +} + +/** + * + * @remote_node_table: + * + * This method will free a single remote node index back to the remote node + * table. This routine will update the remote node groups + */ +static void scic_sds_remote_node_table_release_single_remote_node( + struct scic_remote_node_table *remote_node_table, + u16 remote_node_index) +{ + u32 group_index; + u8 group_value; + + group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; + + group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index); + + /* + * Assert that we are not trying to add an entry to a slot that is already + * full. */ + BUG_ON(group_value == SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE); + + if (group_value == 0x00) { + /* + * There are no entries in this slot so it must be added to the single + * slot table. */ + scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index); + } else if ((group_value & (group_value - 1)) == 0) { + /* + * There is only one entry in this slot so it must be moved from the + * single slot table to the dual slot table */ + scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index); + scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index); + } else { + /* + * There are two entries in the slot so it must be moved from the dual + * slot table to the tripple slot table. */ + scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index); + scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index); + } + + scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index); +} + +/** + * + * @remote_node_table: This is the remote node table to which the remote node + * index is to be freed. + * + * This method will release a group of three consecutive remote nodes back to + * the free remote nodes. + */ +static void scic_sds_remote_node_table_release_triple_remote_node( + struct scic_remote_node_table *remote_node_table, + u16 remote_node_index) +{ + u32 group_index; + + group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; + + scic_sds_remote_node_table_set_group_index( + remote_node_table, 2, group_index + ); + + scic_sds_remote_node_table_set_group(remote_node_table, group_index); +} + +/** + * + * @remote_node_table: The remote node table to which the remote node index is + * to be freed. + * @remote_node_count: This is the count of consecutive remote nodes that are + * to be freed. + * + * This method will release the remote node index back into the remote node + * table free pool. + */ +void scic_sds_remote_node_table_release_remote_node_index( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_count, + u16 remote_node_index) +{ + if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { + scic_sds_remote_node_table_release_single_remote_node( + remote_node_table, remote_node_index); + } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { + scic_sds_remote_node_table_release_triple_remote_node( + remote_node_table, remote_node_index); + } +} + diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.h b/drivers/scsi/isci/core/scic_sds_remote_node_table.h new file mode 100644 index 000000000000..6ee5fbab25dd --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_node_table.h @@ -0,0 +1,196 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_ +#define _SCIC_SDS_REMOTE_NODE_TABLE_H_ + +/** + * This file contains the structures, constants and prototypes used for the + * remote node table. + * + * + */ + +#include "sci_types.h" +#include "sci_controller_constants.h" + +/** + * + * + * Remote node sets are sets of remote node index in the remtoe node table The + * SCU hardware requires that STP remote node entries take three consecutive + * remote node index so the table is arranged in sets of three. The bits are + * used as 0111 0111 to make a byte and the bits define the set of three remote + * nodes to use as a sequence. + */ +#define SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE 2 + +/** + * + * + * Since the remote node table is organized as DWORDS take the remote node sets + * in bytes and represent them in DWORDs. The lowest ordered bits are the ones + * used in case full DWORD is not being used. i.e. 0000 0000 0000 0000 0111 + * 0111 0111 0111 // if only a single WORD is in use in the DWORD. + */ +#define SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD \ + (sizeof(u32) * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE) +/** + * + * + * This is a count of the numeber of remote nodes that can be represented in a + * byte + */ +#define SCIC_SDS_REMOTE_NODES_PER_BYTE \ + (SCU_STP_REMOTE_NODE_COUNT * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE) + +/** + * + * + * This is a count of the number of remote nodes that can be represented in a + * DWROD + */ +#define SCIC_SDS_REMOTE_NODES_PER_DWORD \ + (sizeof(u32) * SCIC_SDS_REMOTE_NODES_PER_BYTE) + +/** + * + * + * This is the number of bits in a remote node group + */ +#define SCIC_SDS_REMOTE_NODES_BITS_PER_GROUP 4 + +#define SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX (0xFFFFFFFF) +#define SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE (0x07) +#define SCIC_SDS_REMOTE_NODE_TABLE_EMPTY_SLOT_VALUE (0x00) + +/** + * + * + * Expander attached sata remote node count + */ +#define SCU_STP_REMOTE_NODE_COUNT 3 + +/** + * + * + * Expander or direct attached ssp remote node count + */ +#define SCU_SSP_REMOTE_NODE_COUNT 1 + +/** + * + * + * Direct attached STP remote node count + */ +#define SCU_SATA_REMOTE_NODE_COUNT 1 + +/** + * struct scic_remote_node_table - + * + * + */ +struct scic_remote_node_table { + /** + * This field contains the array size in dwords + */ + u16 available_nodes_array_size; + + /** + * This field contains the array size of the + */ + u16 group_array_size; + + /** + * This field is the array of available remote node entries in bits. + * Because of the way STP remote node data is allocated on the SCU hardware + * the remote nodes must occupy three consecutive remote node context + * entries. For ease of allocation and de-allocation we have broken the + * sets of three into a single nibble. When the STP RNi is allocated all + * of the bits in the nibble are cleared. This math results in a table size + * of MAX_REMOTE_NODES / CONSECUTIVE RNi ENTRIES for STP / 2 entries per byte. + */ + u32 available_remote_nodes[ + (SCI_MAX_REMOTE_DEVICES / SCIC_SDS_REMOTE_NODES_PER_DWORD) + + ((SCI_MAX_REMOTE_DEVICES % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0)]; + + /** + * This field is the nibble selector for the above table. There are three + * possible selectors each for fast lookup when trying to find one, two or + * three remote node entries. + */ + u32 remote_node_groups[ + SCU_STP_REMOTE_NODE_COUNT][ + (SCI_MAX_REMOTE_DEVICES / (32 * SCU_STP_REMOTE_NODE_COUNT)) + + ((SCI_MAX_REMOTE_DEVICES % (32 * SCU_STP_REMOTE_NODE_COUNT)) != 0)]; + +}; + +/* --------------------------------------------------------------------------- */ + +void scic_sds_remote_node_table_initialize( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_entries); + +u16 scic_sds_remote_node_table_allocate_remote_node( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_count); + +void scic_sds_remote_node_table_release_remote_node_index( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_count, + u16 remote_node_index); + +#endif /* _SCIC_SDS_REMOTE_NODE_TABLE_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c new file mode 100644 index 000000000000..c696d246ea5a --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -0,0 +1,2179 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "intel_sas.h" +#include "intel_sata.h" +#include "intel_sat.h" +#include "sci_base_request.h" +#include "scic_controller.h" +#include "scic_io_request.h" +#include "scic_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_controller_registers.h" +#include "scic_sds_pci.h" +#include "scic_sds_port.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_request.h" +#include "scic_sds_smp_request.h" +#include "scic_sds_stp_request.h" +#include "scic_sds_unsolicited_frame_control.h" +#include "scic_user_callback.h" +#include "sci_environment.h" +#include "sci_types.h" +#include "sci_util.h" +#include "scu_completion_codes.h" +#include "scu_constants.h" +#include "scu_task_context.h" + +#if !defined(DISABLE_ATAPI) +#include "scic_sds_stp_packet_request.h" +#endif + +/* + * **************************************************************************** + * * SCIC SDS IO REQUEST CONSTANTS + * **************************************************************************** */ + +/** + * + * + * We have no timer requirements for IO requests right now + */ +#define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0) +#define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0) + +/* + * **************************************************************************** + * * SCIC SDS IO REQUEST MACROS + * **************************************************************************** */ + +/** + * scic_sds_request_get_user_request() - + * + * This is a helper macro to return the os handle for this request object. + */ +#define scic_sds_request_get_user_request(request) \ + ((request)->user_request) + + +/** + * scic_ssp_io_request_get_object_size() - + * + * This macro returns the sizeof memory required to store the an SSP IO + * request. This does not include the size of the SGL or SCU Task Context + * memory. + */ +#define scic_ssp_io_request_get_object_size() \ + (\ + sizeof(struct sci_ssp_command_iu) \ + + sizeof(struct sci_ssp_response_iu) \ + ) + +/** + * scic_sds_ssp_request_get_command_buffer() - + * + * This macro returns the address of the ssp command buffer in the io request + * memory + */ +#define scic_sds_ssp_request_get_command_buffer(memory) \ + ((struct sci_ssp_command_iu *)(\ + ((char *)(memory)) + sizeof(struct scic_sds_request) \ + )) + +/** + * scic_sds_ssp_request_get_response_buffer() - + * + * This macro returns the address of the ssp response buffer in the io request + * memory + */ +#define scic_sds_ssp_request_get_response_buffer(memory) \ + ((struct sci_ssp_response_iu *)(\ + ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \ + + sizeof(struct sci_ssp_command_iu) \ + )) + +/** + * scic_sds_ssp_request_get_task_context_buffer() - + * + * This macro returns the address of the task context buffer in the io request + * memory + */ +#define scic_sds_ssp_request_get_task_context_buffer(memory) \ + ((struct scu_task_context *)(\ + ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \ + + sizeof(struct sci_ssp_response_iu) \ + )) + +/** + * scic_sds_ssp_request_get_sgl_element_buffer() - + * + * This macro returns the address of the sgl elment pairs in the io request + * memory buffer + */ +#define scic_sds_ssp_request_get_sgl_element_buffer(memory) \ + ((struct scu_sgl_element_pair *)(\ + ((char *)(scic_sds_ssp_request_get_task_context_buffer(memory))) \ + + sizeof(struct scu_task_context) \ + )) + + +/** + * scic_ssp_task_request_get_object_size() - + * + * This macro returns the sizeof of memory required to store an SSP Task + * request. This does not include the size of the SCU Task Context memory. + */ +#define scic_ssp_task_request_get_object_size() \ + (\ + sizeof(struct sci_ssp_task_iu) \ + + sizeof(struct sci_ssp_response_iu) \ + ) + +/** + * scic_sds_ssp_task_request_get_command_buffer() - + * + * This macro returns the address of the ssp command buffer in the task request + * memory. Yes its the same as the above macro except for the name. + */ +#define scic_sds_ssp_task_request_get_command_buffer(memory) \ + ((struct sci_ssp_task_iu *)(\ + ((char *)(memory)) + sizeof(struct scic_sds_request) \ + )) + +/** + * scic_sds_ssp_task_request_get_response_buffer() - + * + * This macro returns the address of the ssp response buffer in the task + * request memory. + */ +#define scic_sds_ssp_task_request_get_response_buffer(memory) \ + ((struct sci_ssp_response_iu *)(\ + ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \ + + sizeof(struct sci_ssp_task_iu) \ + )) + +/** + * scic_sds_ssp_task_request_get_task_context_buffer() - + * + * This macro returs the task context buffer for the SSP task request. + */ +#define scic_sds_ssp_task_request_get_task_context_buffer(memory) \ + ((struct scu_task_context *)(\ + ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \ + + sizeof(struct sci_ssp_response_iu) \ + )) + + + +/* + * **************************************************************************** + * * SCIC SDS IO REQUEST PRIVATE METHODS + * **************************************************************************** */ + +/** + * + * + * This method returns the size required to store an SSP IO request object. u32 + */ +static u32 scic_sds_ssp_request_get_object_size(void) +{ + return sizeof(struct scic_sds_request) + + scic_ssp_io_request_get_object_size() + + sizeof(struct scu_task_context) + + CACHE_LINE_SIZE + + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; +} + +/** + * This method returns the sgl element pair for the specificed sgl_pair index. + * @this_request: This parameter specifies the IO request for which to retrieve + * the Scatter-Gather List element pair. + * @sgl_pair_index: This parameter specifies the index into the SGL element + * pair to be retrieved. + * + * This method returns a pointer to an struct scu_sgl_element_pair. + */ +static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( + struct scic_sds_request *this_request, + u32 sgl_pair_index + ) { + struct scu_task_context *task_context; + + task_context = (struct scu_task_context *)this_request->task_context_buffer; + + if (sgl_pair_index == 0) { + return &task_context->sgl_pair_ab; + } else if (sgl_pair_index == 1) { + return &task_context->sgl_pair_cd; + } + + return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2]; +} + +/** + * This function will build the SGL list for an IO request. + * @this_request: This parameter specifies the IO request for which to build + * the Scatter-Gather List. + * + */ +void scic_sds_request_build_sgl( + struct scic_sds_request *this_request) +{ + void *os_sge; + void *os_handle; + dma_addr_t physical_address; + u32 sgl_pair_index = 0; + struct scu_sgl_element_pair *scu_sgl_list = NULL; + struct scu_sgl_element_pair *previous_pair = NULL; + + os_handle = scic_sds_request_get_user_request(this_request); + scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge); + + while (os_sge != NULL) { + scu_sgl_list = + scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index); + + SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge); + + scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge); + + if (os_sge != NULL) { + SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge); + + scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge); + } else { + SCU_SGL_ZERO(scu_sgl_list->B); + } + + if (previous_pair != NULL) { + scic_cb_io_request_get_physical_address( + scic_sds_request_get_controller(this_request), + this_request, + scu_sgl_list, + &physical_address + ); + + previous_pair->next_pair_upper = + upper_32_bits(physical_address); + previous_pair->next_pair_lower = + lower_32_bits(physical_address); + } + + previous_pair = scu_sgl_list; + sgl_pair_index++; + } + + if (scu_sgl_list != NULL) { + scu_sgl_list->next_pair_upper = 0; + scu_sgl_list->next_pair_lower = 0; + } +} + +/** + * This method initializes common portions of the io request object. This + * includes construction of the struct sci_base_request parent. + * @the_controller: This parameter specifies the controller for which the + * request is being constructed. + * @the_target: This parameter specifies the remote device for which the + * request is being constructed. + * @io_tag: This parameter specifies the IO tag to be utilized for this + * request. This parameter can be set to SCI_CONTROLLER_INVALID_IO_TAG. + * @user_io_request_object: This parameter specifies the user request object + * for which the request is being constructed. + * @this_request: This parameter specifies the request being constructed. + * + */ +static void scic_sds_general_request_construct( + struct scic_sds_controller *the_controller, + struct scic_sds_remote_device *the_target, + u16 io_tag, + void *user_io_request_object, + struct scic_sds_request *this_request) +{ + sci_base_request_construct( + &this_request->parent, + scic_sds_request_state_table + ); + + this_request->io_tag = io_tag; + this_request->user_request = user_io_request_object; + this_request->owning_controller = the_controller; + this_request->target_device = the_target; + this_request->has_started_substate_machine = false; + this_request->protocol = SCIC_NO_PROTOCOL; + this_request->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; + this_request->device_sequence = scic_sds_remote_device_get_sequence(the_target); + + this_request->sci_status = SCI_SUCCESS; + this_request->scu_status = 0; + this_request->post_context = 0xFFFFFFFF; + + this_request->is_task_management_request = false; + + if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { + this_request->was_tag_assigned_by_user = false; + this_request->task_context_buffer = NULL; + } else { + this_request->was_tag_assigned_by_user = true; + + this_request->task_context_buffer = + scic_sds_controller_get_task_context_buffer( + this_request->owning_controller, io_tag); + } +} + +/** + * This method build the remainder of the IO request object. + * @this_request: This parameter specifies the request object being constructed. + * + * The scic_sds_general_request_construct() must be called before this call is + * valid. none + */ +static void scic_sds_ssp_io_request_assign_buffers( + struct scic_sds_request *this_request) +{ + this_request->command_buffer = + scic_sds_ssp_request_get_command_buffer(this_request); + this_request->response_buffer = + scic_sds_ssp_request_get_response_buffer(this_request); + this_request->sgl_element_pair_buffer = + scic_sds_ssp_request_get_sgl_element_buffer(this_request); + this_request->sgl_element_pair_buffer = + scic_sds_request_align_sgl_element_buffer(this_request->sgl_element_pair_buffer); + + if (this_request->was_tag_assigned_by_user == false) { + this_request->task_context_buffer = + scic_sds_ssp_request_get_task_context_buffer(this_request); + this_request->task_context_buffer = + scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); + } +} + +/** + * This method constructs the SSP Command IU data for this io request object. + * @this_request: This parameter specifies the request object for which the SSP + * command information unit is being built. + * + */ +static void scic_sds_io_request_build_ssp_command_iu( + struct scic_sds_request *this_request) +{ + struct sci_ssp_command_iu *command_frame; + void *os_handle; + u32 cdb_length; + u32 *cdb_buffer; + + command_frame = + (struct sci_ssp_command_iu *)this_request->command_buffer; + + os_handle = scic_sds_request_get_user_request(this_request); + + command_frame->lun_upper = 0; + command_frame->lun_lower = scic_cb_ssp_io_request_get_lun(os_handle); + + ((u32 *)command_frame)[2] = 0; + + cdb_length = scic_cb_ssp_io_request_get_cdb_length(os_handle); + cdb_buffer = (u32 *)scic_cb_ssp_io_request_get_cdb_address(os_handle); + + if (cdb_length > 16) { + command_frame->additional_cdb_length = cdb_length - 16; + } + + /* / @todo Is it ok to leave junk at the end of the cdb buffer? */ + scic_word_copy_with_swap( + (u32 *)(&command_frame->cdb), + (u32 *)(cdb_buffer), + (cdb_length + 3) / sizeof(u32) + ); + + command_frame->enable_first_burst = 0; + command_frame->task_priority = + scic_cb_ssp_io_request_get_command_priority(os_handle); + command_frame->task_attribute = + scic_cb_ssp_io_request_get_task_attribute(os_handle); +} + + +/** + * This method constructs the SSP Task IU data for this io request object. + * @this_request: + * + */ +static void scic_sds_task_request_build_ssp_task_iu( + struct scic_sds_request *this_request) +{ + struct sci_ssp_task_iu *command_frame; + void *os_handle; + + command_frame = + (struct sci_ssp_task_iu *)this_request->command_buffer; + + os_handle = scic_sds_request_get_user_request(this_request); + + command_frame->lun_upper = 0; + command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle); + + ((u32 *)command_frame)[2] = 0; + + command_frame->task_function = + scic_cb_ssp_task_request_get_function(os_handle); + command_frame->task_tag = + scic_cb_ssp_task_request_get_io_tag_to_manage(os_handle); +} + + +/** + * This method is will fill in the SCU Task Context for any type of SSP request. + * @this_request: + * @task_context: + * + */ +static void scu_ssp_reqeust_construct_task_context( + struct scic_sds_request *this_request, + struct scu_task_context *task_context) +{ + dma_addr_t physical_address; + struct scic_sds_controller *owning_controller; + struct scic_sds_remote_device *target_device; + struct scic_sds_port *target_port; + + owning_controller = scic_sds_request_get_controller(this_request); + target_device = scic_sds_request_get_device(this_request); + target_port = scic_sds_request_get_port(this_request); + + /* Fill in the TC with the its required data */ + task_context->abort = 0; + task_context->priority = 0; + task_context->initiator_request = 1; + task_context->connection_rate = + scic_remote_device_get_connection_rate(target_device); + task_context->protocol_engine_index = + scic_sds_controller_get_protocol_engine_group(owning_controller); + task_context->logical_port_index = + scic_sds_port_get_index(target_port); + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + task_context->remote_node_index = + scic_sds_remote_device_get_index(this_request->target_device); + task_context->command_code = 0; + + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 0; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + task_context->address_modifier = 0; + + /* task_context->type.ssp.tag = this_request->io_tag; */ + task_context->task_phase = 0x01; + + if (this_request->was_tag_assigned_by_user) { + /* Build the task context now since we have already read the data */ + this_request->post_context = ( + SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC + | ( + scic_sds_controller_get_protocol_engine_group(owning_controller) + << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT + ) + | ( + scic_sds_port_get_index(target_port) + << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT + ) + | scic_sds_io_tag_get_index(this_request->io_tag) + ); + } else { + /* Build the task context now since we have already read the data */ + this_request->post_context = ( + SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC + | ( + scic_sds_controller_get_protocol_engine_group(owning_controller) + << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT + ) + | ( + scic_sds_port_get_index(target_port) + << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT + ) + /* This is not assigned because we have to wait until we get a TCi */ + ); + } + + /* Copy the physical address for the command buffer to the SCU Task Context */ + scic_cb_io_request_get_physical_address( + scic_sds_request_get_controller(this_request), + this_request, + this_request->command_buffer, + &physical_address + ); + + task_context->command_iu_upper = + upper_32_bits(physical_address); + task_context->command_iu_lower = + lower_32_bits(physical_address); + + /* Copy the physical address for the response buffer to the SCU Task Context */ + scic_cb_io_request_get_physical_address( + scic_sds_request_get_controller(this_request), + this_request, + this_request->response_buffer, + &physical_address + ); + + task_context->response_iu_upper = + upper_32_bits(physical_address); + task_context->response_iu_lower = + lower_32_bits(physical_address); +} + +/** + * This method is will fill in the SCU Task Context for a SSP IO request. + * @this_request: + * + */ +static void scu_ssp_io_request_construct_task_context( + struct scic_sds_request *this_request, + SCI_IO_REQUEST_DATA_DIRECTION data_direction, + u32 transfer_length_bytes) +{ + struct scu_task_context *task_context; + + task_context = scic_sds_request_get_task_context(this_request); + + scu_ssp_reqeust_construct_task_context(this_request, task_context); + + task_context->ssp_command_iu_length = sizeof(struct sci_ssp_command_iu) / sizeof(u32); + task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME; + + switch (data_direction) { + case SCI_IO_REQUEST_DATA_IN: + case SCI_IO_REQUEST_NO_DATA: + task_context->task_type = SCU_TASK_TYPE_IOREAD; + break; + case SCI_IO_REQUEST_DATA_OUT: + task_context->task_type = SCU_TASK_TYPE_IOWRITE; + break; + } + + task_context->transfer_length_bytes = transfer_length_bytes; + + if (task_context->transfer_length_bytes > 0) { + scic_sds_request_build_sgl(this_request); + } +} + + +/** + * This method will fill in the remainder of the io request object for SSP Task + * requests. + * @this_request: + * + */ +static void scic_sds_ssp_task_request_assign_buffers( + struct scic_sds_request *this_request) +{ + /* Assign all of the buffer pointers */ + this_request->command_buffer = + scic_sds_ssp_task_request_get_command_buffer(this_request); + this_request->response_buffer = + scic_sds_ssp_task_request_get_response_buffer(this_request); + this_request->sgl_element_pair_buffer = NULL; + + if (this_request->was_tag_assigned_by_user == false) { + this_request->task_context_buffer = + scic_sds_ssp_task_request_get_task_context_buffer(this_request); + this_request->task_context_buffer = + scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); + } +} + +/** + * This method will fill in the SCU Task Context for a SSP Task request. The + * following important settings are utilized: -# priority == + * SCU_TASK_PRIORITY_HIGH. This ensures that the task request is issued + * ahead of other task destined for the same Remote Node. -# task_type == + * SCU_TASK_TYPE_IOREAD. This simply indicates that a normal request type + * (i.e. non-raw frame) is being utilized to perform task management. -# + * control_frame == 1. This ensures that the proper endianess is set so + * that the bytes are transmitted in the right order for a task frame. + * @this_request: This parameter specifies the task request object being + * constructed. + * + */ +static void scu_ssp_task_request_construct_task_context( + struct scic_sds_request *this_request) +{ + struct scu_task_context *task_context; + + task_context = scic_sds_request_get_task_context(this_request); + + scu_ssp_reqeust_construct_task_context(this_request, task_context); + + task_context->control_frame = 1; + task_context->priority = SCU_TASK_PRIORITY_HIGH; + task_context->task_type = SCU_TASK_TYPE_RAW_FRAME; + task_context->transfer_length_bytes = 0; + task_context->type.ssp.frame_type = SCI_SAS_TASK_FRAME; + task_context->ssp_command_iu_length = sizeof(struct sci_ssp_task_iu) / sizeof(u32); +} + + +/** + * This method constructs the SSP Command IU data for this ssp passthrough + * comand request object. + * @this_request: This parameter specifies the request object for which the SSP + * command information unit is being built. + * + * enum sci_status, returns invalid parameter is cdb > 16 + */ + + +/** + * This method constructs the SATA request object. + * @this_request: + * @sat_protocol: + * @transfer_length: + * @data_direction: + * @copy_rx_frame: + * + * enum sci_status + */ +static enum sci_status scic_io_request_construct_sata( + struct scic_sds_request *this_request, + u8 sat_protocol, + u32 transfer_length, + SCI_IO_REQUEST_DATA_DIRECTION data_direction, + bool copy_rx_frame) +{ + enum sci_status status = SCI_SUCCESS; + + switch (sat_protocol) { + case SAT_PROTOCOL_PIO_DATA_IN: + case SAT_PROTOCOL_PIO_DATA_OUT: + status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, copy_rx_frame); + break; + + case SAT_PROTOCOL_UDMA_DATA_IN: + case SAT_PROTOCOL_UDMA_DATA_OUT: + status = scic_sds_stp_udma_request_construct(this_request, transfer_length, data_direction); + break; + + case SAT_PROTOCOL_ATA_HARD_RESET: + case SAT_PROTOCOL_SOFT_RESET: + status = scic_sds_stp_soft_reset_request_construct(this_request); + break; + + case SAT_PROTOCOL_NON_DATA: + status = scic_sds_stp_non_data_request_construct(this_request); + break; + + case SAT_PROTOCOL_FPDMA: + status = scic_sds_stp_ncq_request_construct(this_request, transfer_length, data_direction); + break; + +#if !defined(DISABLE_ATAPI) + case SAT_PROTOCOL_PACKET_NON_DATA: + case SAT_PROTOCOL_PACKET_DMA_DATA_IN: + case SAT_PROTOCOL_PACKET_DMA_DATA_OUT: + case SAT_PROTOCOL_PACKET_PIO_DATA_IN: + case SAT_PROTOCOL_PACKET_PIO_DATA_OUT: + status = scic_sds_stp_packet_request_construct(this_request); + break; +#endif + + case SAT_PROTOCOL_DMA_QUEUED: + case SAT_PROTOCOL_DMA: + case SAT_PROTOCOL_DEVICE_DIAGNOSTIC: + case SAT_PROTOCOL_DEVICE_RESET: + case SAT_PROTOCOL_RETURN_RESPONSE_INFO: + default: + dev_err(scic_to_dev(this_request->owning_controller), + "%s: SCIC IO Request 0x%p received un-handled " + "SAT Protocl %d.\n", + __func__, this_request, sat_protocol); + + status = SCI_FAILURE; + break; + } + + return status; +} + +/* + * **************************************************************************** + * * SCIC Interface Implementation + * **************************************************************************** */ + + + + +/* --------------------------------------------------------------------------- */ + +u32 scic_io_request_get_object_size(void) +{ + u32 ssp_request_size; + u32 stp_request_size; + u32 smp_request_size; + + ssp_request_size = scic_sds_ssp_request_get_object_size(); + stp_request_size = scic_sds_stp_request_get_object_size(); + smp_request_size = scic_sds_smp_request_get_object_size(); + + return max(ssp_request_size, max(stp_request_size, smp_request_size)); +} + +/* --------------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------------- */ + + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_io_request_construct( + struct scic_sds_controller *scic_controller, + struct scic_sds_remote_device *scic_remote_device, + u16 io_tag, + void *user_io_request_object, + void *scic_io_request_memory, + struct scic_sds_request **new_scic_io_request_handle) +{ + enum sci_status status = SCI_SUCCESS; + struct scic_sds_request *this_request; + struct smp_discover_response_protocols device_protocol; + + this_request = (struct scic_sds_request *)scic_io_request_memory; + + /* Build the common part of the request */ + scic_sds_general_request_construct( + (struct scic_sds_controller *)scic_controller, + (struct scic_sds_remote_device *)scic_remote_device, + io_tag, + user_io_request_object, + this_request + ); + + if ( + scic_sds_remote_device_get_index((struct scic_sds_remote_device *)scic_remote_device) + == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX + ) { + return SCI_FAILURE_INVALID_REMOTE_DEVICE; + } + + scic_remote_device_get_protocols(scic_remote_device, &device_protocol); + + if (device_protocol.u.bits.attached_ssp_target) { + scic_sds_ssp_io_request_assign_buffers(this_request); + } else if (device_protocol.u.bits.attached_stp_target) { + scic_sds_stp_request_assign_buffers(this_request); + memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); + } else if (device_protocol.u.bits.attached_smp_target) { + scic_sds_smp_request_assign_buffers(this_request); + memset(this_request->command_buffer, 0, sizeof(struct smp_request)); + } else { + status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + } + + if (status == SCI_SUCCESS) { + memset( + this_request->task_context_buffer, + 0, + SCI_FIELD_OFFSET(struct scu_task_context, sgl_pair_ab) + ); + *new_scic_io_request_handle = scic_io_request_memory; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + + +enum sci_status scic_task_request_construct( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + u16 io_tag, + void *user_io_request_object, + void *scic_task_request_memory, + struct scic_sds_request **new_scic_task_request_handle) +{ + enum sci_status status = SCI_SUCCESS; + struct scic_sds_request *this_request = (struct scic_sds_request *) + scic_task_request_memory; + struct smp_discover_response_protocols device_protocol; + + /* Build the common part of the request */ + scic_sds_general_request_construct( + (struct scic_sds_controller *)controller, + (struct scic_sds_remote_device *)remote_device, + io_tag, + user_io_request_object, + this_request + ); + + scic_remote_device_get_protocols(remote_device, &device_protocol); + + if (device_protocol.u.bits.attached_ssp_target) { + scic_sds_ssp_task_request_assign_buffers(this_request); + + this_request->has_started_substate_machine = true; + + /* Construct the started sub-state machine. */ + sci_base_state_machine_construct( + &this_request->started_substate_machine, + &this_request->parent.parent, + scic_sds_io_request_started_task_mgmt_substate_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION + ); + } else if (device_protocol.u.bits.attached_stp_target) { + scic_sds_stp_request_assign_buffers(this_request); + } else { + status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + } + + if (status == SCI_SUCCESS) { + this_request->is_task_management_request = true; + memset(this_request->task_context_buffer, 0x00, sizeof(struct scu_task_context)); + *new_scic_task_request_handle = scic_task_request_memory; + } + + return status; +} + + +enum sci_status scic_io_request_construct_basic_ssp( + struct scic_sds_request *sci_req) +{ + void *os_handle; + + sci_req->protocol = SCIC_SSP_PROTOCOL; + + os_handle = scic_sds_request_get_user_request(sci_req); + + scu_ssp_io_request_construct_task_context( + sci_req, + scic_cb_io_request_get_data_direction(os_handle), + scic_cb_io_request_get_transfer_length(os_handle) + ); + + + scic_sds_io_request_build_ssp_command_iu(sci_req); + + sci_base_state_machine_change_state( + &sci_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED + ); + + return SCI_SUCCESS; +} + + +enum sci_status scic_task_request_construct_ssp( + struct scic_sds_request *sci_req) +{ + /* Construct the SSP Task SCU Task Context */ + scu_ssp_task_request_construct_task_context(sci_req); + + /* Fill in the SSP Task IU */ + scic_sds_task_request_build_ssp_task_iu(sci_req); + + sci_base_state_machine_change_state( + &sci_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED + ); + + return SCI_SUCCESS; +} + + +enum sci_status scic_io_request_construct_basic_sata( + struct scic_sds_request *sci_req) +{ + enum sci_status status; + struct scic_sds_stp_request *this_stp_request; + u8 sat_protocol; + u32 transfer_length; + SCI_IO_REQUEST_DATA_DIRECTION data_direction; + bool copy_rx_frame = false; + + this_stp_request = (struct scic_sds_stp_request *)sci_req; + + sci_req->protocol = SCIC_STP_PROTOCOL; + + transfer_length = + scic_cb_io_request_get_transfer_length(sci_req->user_request); + data_direction = + scic_cb_io_request_get_data_direction(sci_req->user_request); + + sat_protocol = scic_cb_request_get_sat_protocol(sci_req->user_request); + copy_rx_frame = scic_cb_io_request_do_copy_rx_frames(this_stp_request->parent.user_request); + + status = scic_io_request_construct_sata( + sci_req, + sat_protocol, + transfer_length, + data_direction, + copy_rx_frame + ); + + if (status == SCI_SUCCESS) + sci_base_state_machine_change_state( + &sci_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED + ); + + return status; +} + + +enum sci_status scic_task_request_construct_sata( + struct scic_sds_request *sci_req) +{ + enum sci_status status; + u8 sat_protocol = scic_cb_request_get_sat_protocol(sci_req->user_request); + + switch (sat_protocol) { + case SAT_PROTOCOL_ATA_HARD_RESET: + case SAT_PROTOCOL_SOFT_RESET: + status = scic_sds_stp_soft_reset_request_construct(sci_req); + break; + + default: + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: SCIC IO Request 0x%p received un-handled SAT " + "Protocl %d.\n", + __func__, + sci_req, + sat_protocol); + + status = SCI_FAILURE; + break; + } + + if (status == SCI_SUCCESS) + sci_base_state_machine_change_state( + &sci_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED + ); + + return status; +} + + +u16 scic_io_request_get_io_tag( + struct scic_sds_request *sci_req) +{ + return sci_req->io_tag; +} + + +u32 scic_request_get_controller_status( + struct scic_sds_request *sci_req) +{ + return sci_req->scu_status; +} + + +void *scic_io_request_get_command_iu_address( + struct scic_sds_request *sci_req) +{ + return sci_req->command_buffer; +} + + +void *scic_io_request_get_response_iu_address( + struct scic_sds_request *sci_req) +{ + return sci_req->response_buffer; +} + + +#define SCU_TASK_CONTEXT_SRAM 0x200000 +u32 scic_io_request_get_number_of_bytes_transferred( + struct scic_sds_request *scic_sds_request) +{ + u32 ret_val = 0; + + if (SMU_AMR_READ(scic_sds_request->owning_controller) == 0) { + /* + * get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where + * BAR1 is the scu_registers + * 0x20002C = 0x200000 + 0x2c + * = start of task context SRAM + offset of (type.ssp.data_offset) + * TCi is the io_tag of struct scic_sds_request */ + ret_val = scic_sds_pci_read_scu_dword( + scic_sds_request->owning_controller, + ( + (u8 *)scic_sds_request->owning_controller->scu_registers + + (SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(struct scu_task_context, type.ssp.data_offset)) + + ((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(scic_sds_request->io_tag)) + ) + ); + } + + return ret_val; +} + + +/* + * **************************************************************************** + * * SCIC SDS Interface Implementation + * **************************************************************************** */ + +/** + * + * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start + * operation is to be executed. + * + * This method invokes the base state start request handler for the + * SCIC_SDS_IO_REQUEST_T object. enum sci_status + */ +enum sci_status scic_sds_request_start( + struct scic_sds_request *this_request) +{ + if ( + this_request->device_sequence + == scic_sds_remote_device_get_sequence(this_request->target_device) + ) { + return this_request->state_handlers->parent.start_handler( + &this_request->parent + ); + } + + return SCI_FAILURE; +} + +/** + * + * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start + * operation is to be executed. + * + * This method invokes the base state terminate request handber for the + * SCIC_SDS_IO_REQUEST_T object. enum sci_status + */ +enum sci_status scic_sds_io_request_terminate( + struct scic_sds_request *this_request) +{ + return this_request->state_handlers->parent.abort_handler( + &this_request->parent); +} + +/** + * + * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start + * operation is to be executed. + * + * This method invokes the base state request completion handler for the + * SCIC_SDS_IO_REQUEST_T object. enum sci_status + */ +enum sci_status scic_sds_io_request_complete( + struct scic_sds_request *this_request) +{ + return this_request->state_handlers->parent.complete_handler( + &this_request->parent); +} + +/** + * + * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start + * operation is to be executed. + * @event_code: The event code returned by the hardware for the task reqeust. + * + * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T + * object. enum sci_status + */ +enum sci_status scic_sds_io_request_event_handler( + struct scic_sds_request *this_request, + u32 event_code) +{ + return this_request->state_handlers->event_handler(this_request, event_code); +} + +/** + * + * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start + * operation is to be executed. + * @frame_index: The frame index returned by the hardware for the reqeust + * object. + * + * This method invokes the core state frame handler for the + * SCIC_SDS_IO_REQUEST_T object. enum sci_status + */ +enum sci_status scic_sds_io_request_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index) +{ + return this_request->state_handlers->frame_handler(this_request, frame_index); +} + +/** + * + * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the task start + * operation is to be executed. + * + * This method invokes the core state task complete handler for the + * SCIC_SDS_IO_REQUEST_T object. enum sci_status + */ + +/* + * **************************************************************************** + * * SCIC SDS PROTECTED METHODS + * **************************************************************************** */ + +/** + * This method copies response data for requests returning response data + * instead of sense data. + * @this_request: This parameter specifies the request object for which to copy + * the response data. + * + */ +void scic_sds_io_request_copy_response( + struct scic_sds_request *this_request) +{ + void *response_buffer; + u32 user_response_length; + u32 core_response_length; + struct sci_ssp_response_iu *ssp_response; + + ssp_response = (struct sci_ssp_response_iu *)this_request->response_buffer; + + response_buffer = scic_cb_ssp_task_request_get_response_data_address( + this_request->user_request + ); + + user_response_length = scic_cb_ssp_task_request_get_response_data_length( + this_request->user_request + ); + + core_response_length = sci_ssp_get_response_data_length( + ssp_response->response_data_length + ); + + user_response_length = min(user_response_length, core_response_length); + + memcpy(response_buffer, ssp_response->data, user_response_length); +} + +/* + * ***************************************************************************** + * * DEFAULT STATE HANDLERS + * ***************************************************************************** */ + +/** + * scic_sds_request_default_start_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_start() request. The default action is + * to log a warning and return a failure status. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_request_default_start_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *scic_request = + (struct scic_sds_request *)request; + + dev_warn(scic_to_dev(scic_request->owning_controller), + "%s: SCIC IO Request requested to start while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state( + &((struct scic_sds_request *)request)->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_request_default_abort_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *scic_request = + (struct scic_sds_request *)request; + + dev_warn(scic_to_dev(scic_request->owning_controller), + "%s: SCIC IO Request requested to abort while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state( + &((struct scic_sds_request *)request)->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * scic_sds_request_default_complete_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_complete() request. The default action + * is to log a warning and return a failure status. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_request_default_complete_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *scic_request = + (struct scic_sds_request *)request; + + dev_warn(scic_to_dev(scic_request->owning_controller), + "%s: SCIC IO Request requested to complete while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state( + &((struct scic_sds_request *)request)->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * scic_sds_request_default_destruct_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_complete() request. The default action + * is to log a warning and return a failure status. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_request_default_destruct_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *scic_request = + (struct scic_sds_request *)request; + + dev_warn(scic_to_dev(scic_request->owning_controller), + "%s: SCIC IO Request requested to destroy while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state( + &((struct scic_sds_request *)request)->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * scic_sds_request_default_tc_completion_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_task_request_complete() request. The default + * action is to log a warning and return a failure status. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_request_default_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + dev_warn(scic_to_dev(this_request->owning_controller), + "%s: SCIC IO Request given task completion notification %x " + "while in wrong state %d\n", + __func__, + completion_code, + sci_base_state_machine_get_state( + &this_request->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; + +} + +/** + * scic_sds_request_default_event_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_event_handler() request. The default + * action is to log a warning and return a failure status. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_request_default_event_handler( + struct scic_sds_request *this_request, + u32 event_code) +{ + dev_warn(scic_to_dev(this_request->owning_controller), + "%s: SCIC IO Request given event code notification %x while " + "in wrong state %d\n", + __func__, + event_code, + sci_base_state_machine_get_state( + &this_request->parent.state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * scic_sds_request_default_frame_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_event_handler() request. The default + * action is to log a warning and return a failure status. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_request_default_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index) +{ + dev_warn(scic_to_dev(this_request->owning_controller), + "%s: SCIC IO Request given unexpected frame %x while in " + "state %d\n", + __func__, + frame_index, + sci_base_state_machine_get_state( + &this_request->parent.state_machine)); + + scic_sds_controller_release_frame( + this_request->owning_controller, frame_index); + + return SCI_FAILURE_INVALID_STATE; +} + +/* + * ***************************************************************************** + * * CONSTRUCTED STATE HANDLERS + * ***************************************************************************** */ + +/** + * scic_sds_request_constructed_state_start_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method implements the action taken when a constructed + * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request. + * This method will, if necessary, allocate a TCi for the io request object and + * then will, if necessary, copy the constructed TC data into the actual TC + * buffer. If everything is successful the post context field is updated with + * the TCi so the controller can post the request to the hardware. enum sci_status + * SCI_SUCCESS SCI_FAILURE_INSUFFICIENT_RESOURCES + */ +static enum sci_status scic_sds_request_constructed_state_start_handler( + struct sci_base_request *request) +{ + struct scu_task_context *task_context; + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + + if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { + this_request->io_tag = + scic_controller_allocate_io_tag(this_request->owning_controller); + } + + /* Record the IO Tag in the request */ + if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { + task_context = this_request->task_context_buffer; + + task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag); + + switch (task_context->protocol_type) { + case SCU_TASK_CONTEXT_PROTOCOL_SMP: + case SCU_TASK_CONTEXT_PROTOCOL_SSP: + /* SSP/SMP Frame */ + task_context->type.ssp.tag = this_request->io_tag; + task_context->type.ssp.target_port_transfer_tag = 0xFFFF; + break; + + case SCU_TASK_CONTEXT_PROTOCOL_STP: + /* + * STP/SATA Frame + * task_context->type.stp.ncq_tag = this_request->ncq_tag; */ + break; + + case SCU_TASK_CONTEXT_PROTOCOL_NONE: + /* / @todo When do we set no protocol type? */ + break; + + default: + /* This should never happen since we build the IO requests */ + break; + } + + /* + * Check to see if we need to copy the task context buffer + * or have been building into the task context buffer */ + if (this_request->was_tag_assigned_by_user == false) { + scic_sds_controller_copy_task_context( + this_request->owning_controller, this_request + ); + } + + /* Add to the post_context the io tag value */ + this_request->post_context |= scic_sds_io_tag_get_index(this_request->io_tag); + + /* Everything is good go ahead and change state */ + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_STARTED + ); + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INSUFFICIENT_RESOURCES; +} + +/** + * scic_sds_request_constructed_state_abort_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_terminate() request. Since the request + * has not yet been posted to the hardware the request transitions to the + * completed state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_constructed_state_abort_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + + /* + * This request has been terminated by the user make sure that the correct + * status code is returned */ + scic_sds_request_set_status( + this_request, + SCU_TASK_DONE_TASK_ABORT, + SCI_FAILURE_IO_TERMINATED + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + return SCI_SUCCESS; +} + +/* + * ***************************************************************************** + * * STARTED STATE HANDLERS + * ***************************************************************************** */ + +/** + * scic_sds_request_started_state_abort_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_terminate() request. Since the request + * has been posted to the hardware the io request state is changed to the + * aborting state. enum sci_status SCI_SUCCESS + */ +enum sci_status scic_sds_request_started_state_abort_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + + if (this_request->has_started_substate_machine) { + sci_base_state_machine_stop(&this_request->started_substate_machine); + } + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_ABORTING + ); + + return SCI_SUCCESS; +} + +/** + * scic_sds_request_started_state_tc_completion_handler() - This method process + * TC (task context) completions for normal IO request (i.e. Task/Abort + * Completions of type 0). This method will update the + * SCIC_SDS_IO_REQUEST_T::status field. + * @this_request: This parameter specifies the request for which a completion + * occurred. + * @completion_code: This parameter specifies the completion code received from + * the SCU. + * + */ +enum sci_status scic_sds_request_started_state_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + u8 data_present; + struct sci_ssp_response_iu *response_buffer; + + /** + * @todo Any SDMA return code of other than 0 is bad + * decode 0x003C0000 to determine SDMA status + */ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): + { + /* + * There are times when the SCU hardware will return an early response + * because the io request specified more data than is returned by the + * target device (mode pages, inquiry data, etc.). We must check the + * response stats to see if this is truly a failed request or a good + * request that just got completed early. */ + struct sci_ssp_response_iu *response = (struct sci_ssp_response_iu *) + this_request->response_buffer; + scic_word_copy_with_swap( + this_request->response_buffer, + this_request->response_buffer, + sizeof(struct sci_ssp_response_iu) / sizeof(u32) + ); + + if (response->status == 0) { + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY + ); + } else { + scic_sds_request_set_status( + this_request, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + } + } + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): + scic_word_copy_with_swap( + this_request->response_buffer, + this_request->response_buffer, + sizeof(struct sci_ssp_response_iu) / sizeof(u32) + ); + + scic_sds_request_set_status( + this_request, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR): + /* + * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed + * / to be received before this completion status is posted? */ + response_buffer = + (struct sci_ssp_response_iu *)this_request->response_buffer; + data_present = + response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK; + + if ((data_present == 0x01) || (data_present == 0x02)) { + scic_sds_request_set_status( + this_request, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + } else { + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + } + break; + + /* only stp device gets suspended. */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): + if (this_request->protocol == SCIC_STP_PROTOCOL) { + scic_sds_request_set_status( + this_request, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED + ); + } else { + scic_sds_request_set_status( + this_request, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + } + break; + + /* both stp/ssp device gets suspended */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): + scic_sds_request_set_status( + this_request, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED + ); + break; + + /* neither ssp nor stp gets suspended. */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): + default: + scic_sds_request_set_status( + this_request, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + break; + } + + /** + * @todo This is probably wrong for ACK/NAK timeout conditions + */ + + /* In all cases we will treat this as the completion of the IO request. */ + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + return SCI_SUCCESS; +} + +/** + * scic_sds_request_started_state_frame_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * @frame_index: This is the index of the unsolicited frame to be processed. + * + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_frame_handler() request. This method + * first determines the frame type received. If this is a response frame then + * the response data is copied to the io request response buffer for processing + * at completion time. If the frame type is not a response buffer an error is + * logged. enum sci_status SCI_SUCCESS SCI_FAILURE_INVALID_PARAMETER_VALUE + */ +static enum sci_status scic_sds_request_started_state_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index) +{ + enum sci_status status; + struct sci_ssp_frame_header *frame_header; + + /* / @todo If this is a response frame we must record that we received it */ + status = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_request_get_controller(this_request)->uf_control), + frame_index, + (void **)&frame_header + ); + + if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME) { + struct sci_ssp_response_iu *response_buffer; + + status = scic_sds_unsolicited_frame_control_get_buffer( + &(scic_sds_request_get_controller(this_request)->uf_control), + frame_index, + (void **)&response_buffer + ); + + scic_word_copy_with_swap( + this_request->response_buffer, + (u32 *)response_buffer, + sizeof(struct sci_ssp_response_iu) + ); + + response_buffer = (struct sci_ssp_response_iu *)this_request->response_buffer; + + if ((response_buffer->data_present == 0x01) || + (response_buffer->data_present == 0x02)) { + scic_sds_request_set_status( + this_request, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + } else + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + } else + /* This was not a response frame why did it get forwarded? */ + dev_err(scic_to_dev(this_request->owning_controller), + "%s: SCIC IO Request 0x%p received unexpected " + "frame %d type 0x%02x\n", + __func__, + this_request, + frame_index, + frame_header->frame_type); + + /* + * In any case we are done with this frame buffer return it to the + * controller */ + scic_sds_controller_release_frame( + this_request->owning_controller, frame_index + ); + + return SCI_SUCCESS; +} + +/* + * ***************************************************************************** + * * COMPLETED STATE HANDLERS + * ***************************************************************************** */ + + +/** + * scic_sds_request_completed_state_complete_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_complete() request. This method frees up + * any io request resources that have been allocated and transitions the + * request to its final state. Consider stopping the state machine instead of + * transitioning to the final state? enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_completed_state_complete_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + + if (this_request->was_tag_assigned_by_user != true) { + scic_controller_free_io_tag( + this_request->owning_controller, this_request->io_tag + ); + } + + if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) { + scic_sds_controller_release_frame( + this_request->owning_controller, this_request->saved_rx_frame_index); + } + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_FINAL + ); + + return SCI_SUCCESS; +} + +/* + * ***************************************************************************** + * * ABORTING STATE HANDLERS + * ***************************************************************************** */ + +/** + * scic_sds_request_aborting_state_abort_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_terminate() request. This method is the + * io request aborting state abort handlers. On receipt of a multiple + * terminate requests the io request will transition to the completed state. + * This should not happen in normal operation. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_aborting_state_abort_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + return SCI_SUCCESS; +} + +/** + * scic_sds_request_aborting_state_tc_completion_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_task_completion() request. This method + * decodes the completion type waiting for the abort task complete + * notification. When the abort task complete is received the io request + * transitions to the completed state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): + case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + + default: + /* + * Unless we get some strange error wait for the task abort to complete + * TODO: Should there be a state change for this completion? */ + break; + } + + return SCI_SUCCESS; +} + +/** + * scic_sds_request_aborting_state_frame_handler() - + * @request: This is the struct sci_base_request object that is cast to the + * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. + * + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_frame_handler() request. This method + * discards the unsolicited frame since we are waiting for the abort task + * completion. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_aborting_state_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index) +{ + /* TODO: Is it even possible to get an unsolicited frame in the aborting state? */ + + scic_sds_controller_release_frame( + this_request->owning_controller, frame_index); + + return SCI_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { + [SCI_BASE_REQUEST_STATE_INITIAL] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_default_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + }, + [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { + .parent.start_handler = scic_sds_request_constructed_state_start_handler, + .parent.abort_handler = scic_sds_request_constructed_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + }, + [SCI_BASE_REQUEST_STATE_STARTED] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_started_state_frame_handler, + }, + [SCI_BASE_REQUEST_STATE_COMPLETED] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_default_abort_handler, + .parent.complete_handler = scic_sds_request_completed_state_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + }, + [SCI_BASE_REQUEST_STATE_ABORTING] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_aborting_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_aborting_state_frame_handler, + }, + [SCI_BASE_REQUEST_STATE_FINAL] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_default_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + }, +}; + +/** + * scic_sds_request_initial_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occurring. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the initial + * base request is constructed. Entry into the initial state sets all handlers + * for the io request object to their default handlers. none + */ +static void scic_sds_request_initial_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_INITIAL + ); +} + +/** + * scic_sds_request_constructed_state_enter() - + * @object: The io request object that is to enter the constructed state. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_CONSTRUCTED state. The method sets the state handlers + * for the the constructed state. none + */ +static void scic_sds_request_constructed_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_CONSTRUCTED + ); +} + +/** + * scic_sds_request_started_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occuring. This is cast into a SCIC_SDS_IO_REQUEST object. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a + * SCSI Task request we must enter the started substate machine. none + */ +static void scic_sds_request_started_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_STARTED + ); + + /* + * Most of the request state machines have a started substate machine so + * start its execution on the entry to the started state. */ + if (this_request->has_started_substate_machine == true) + sci_base_state_machine_start(&this_request->started_substate_machine); +} + +/** + * scic_sds_request_started_state_exit() - + * @object: This parameter specifies the base object for which the state + * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST + * object. + * + * This method implements the actions taken when exiting the + * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be + * to stop the started substate machine. none + */ +static void scic_sds_request_started_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + if (this_request->has_started_substate_machine == true) + sci_base_state_machine_stop(&this_request->started_substate_machine); +} + +/** + * scic_sds_request_completed_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST + * object. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_COMPLETED state. This state is entered when the + * SCIC_SDS_IO_REQUEST has completed. The method will decode the request + * completion status and convert it to an enum sci_status to return in the + * completion callback function. none + */ +static void scic_sds_request_completed_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + /* Tell the SCI_USER that the IO request is complete */ + if (this_request->is_task_management_request == false) { + scic_cb_io_request_complete( + scic_sds_request_get_controller(this_request), + scic_sds_request_get_device(this_request), + this_request, + this_request->sci_status + ); + } else { + scic_cb_task_request_complete( + scic_sds_request_get_controller(this_request), + scic_sds_request_get_device(this_request), + this_request, + this_request->sci_status + ); + } +} + +/** + * scic_sds_request_aborting_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST + * object. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_ABORTING state. none + */ +static void scic_sds_request_aborting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + /* Setting the abort bit in the Task Context is required by the silicon. */ + this_request->task_context_buffer->abort = 1; + + SET_STATE_HANDLER( + this_request, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_ABORTING + ); +} + +/** + * scic_sds_request_final_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occuring. This is cast into a SCIC_SDS_IO_REQUEST object. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the + * state handlers in place. none + */ +static void scic_sds_request_final_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_FINAL + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_request_state_table[] = { + [SCI_BASE_REQUEST_STATE_INITIAL] = { + .enter_state = scic_sds_request_initial_state_enter, + }, + [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { + .enter_state = scic_sds_request_constructed_state_enter, + }, + [SCI_BASE_REQUEST_STATE_STARTED] = { + .enter_state = scic_sds_request_started_state_enter, + .exit_state = scic_sds_request_started_state_exit + }, + [SCI_BASE_REQUEST_STATE_COMPLETED] = { + .enter_state = scic_sds_request_completed_state_enter, + }, + [SCI_BASE_REQUEST_STATE_ABORTING] = { + .enter_state = scic_sds_request_aborting_state_enter, + }, + [SCI_BASE_REQUEST_STATE_FINAL] = { + .enter_state = scic_sds_request_final_state_enter, + }, +}; + diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h new file mode 100644 index 000000000000..0691a7552a2a --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -0,0 +1,484 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_IO_REQUEST_H_ +#define _SCIC_SDS_IO_REQUEST_H_ + +/** + * This file contains the structures, constants and prototypes for the + * SCIC_SDS_IO_REQUEST object. + * + * + */ + +#include "scic_io_request.h" + +#include "sci_base_request.h" +#include "scu_task_context.h" +#include "intel_sas.h" + +struct scic_sds_controller; +struct scic_sds_remote_device; +struct scic_sds_io_request_state_handler; + +/** + * enum _SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATES - This enumeration + * depicts all of the substates for a task management request to be + * performed in the STARTED super-state. + * + * + */ +enum scic_sds_raw_request_started_task_mgmt_substates { + /** + * The AWAIT_TC_COMPLETION sub-state indicates that the started raw + * task management request is waiting for the transmission of the + * initial frame (i.e. command, task, etc.). + */ + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, + + /** + * This sub-state indicates that the started task management request + * is waiting for the reception of an unsolicited frame + * (i.e. response IU). + */ + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, +}; + + +/** + * enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES - This enumeration depicts all + * of the substates for a SMP request to be performed in the STARTED + * super-state. + * + * + */ +enum scic_sds_smp_request_started_substates { + /** + * This sub-state indicates that the started task management request + * is waiting for the reception of an unsolicited frame + * (i.e. response IU). + */ + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, + + /** + * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is + * waiting for the transmission of the initial frame (i.e. command, task, etc.). + */ + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, +}; + +/** + * struct SCIC_SDS_IO_REQUEST - This structure contains or references all of + * the data necessary to process a task management or normal IO request. + * + * + */ +struct scic_sds_request { + /** + * This field indictes the parent object of the request. + */ + struct sci_base_request parent; + + void *user_request; + + /** + * This field simply points to the controller to which this IO request + * is associated. + */ + struct scic_sds_controller *owning_controller; + + /** + * This field simply points to the remote device to which this IO request + * is associated. + */ + struct scic_sds_remote_device *target_device; + + /** + * This field is utilized to determine if the SCI user is managing + * the IO tag for this request or if the core is managing it. + */ + bool was_tag_assigned_by_user; + + /** + * This field indicates the IO tag for this request. The IO tag is + * comprised of the task_index and a sequence count. The sequence count + * is utilized to help identify tasks from one life to another. + */ + u16 io_tag; + + /** + * This field specifies the protocol being utilized for this + * IO request. + */ + SCIC_TRANSPORT_PROTOCOL protocol; + + /** + * This field indicates the completion status taken from the SCUs + * completion code. It indicates the completion result for the SCU hardware. + */ + u32 scu_status; + + /** + * This field indicates the completion status returned to the SCI user. It + * indicates the users view of the io request completion. + */ + u32 sci_status; + + /** + * This field contains the value to be utilized when posting (e.g. Post_TC, + * Post_TC_Abort) this request to the silicon. + */ + u32 post_context; + + void *command_buffer; + void *response_buffer; + struct scu_task_context *task_context_buffer; + struct scu_sgl_element_pair *sgl_element_pair_buffer; + + /** + * This field indicates if this request is a task management request or + * normal IO request. + */ + bool is_task_management_request; + + /** + * This field indicates that this request contains an initialized started + * substate machine. + */ + bool has_started_substate_machine; + + /** + * This field is a pointer to the stored rx frame data. It is used in STP + * internal requests and SMP response frames. If this field is non-NULL the + * saved frame must be released on IO request completion. + * + * @todo In the future do we want to keep a list of RX frame buffers? + */ + u32 saved_rx_frame_index; + + /** + * This field specifies the data necessary to manage the sub-state + * machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state. + */ + struct sci_base_state_machine started_substate_machine; + + /** + * This field specifies the current state handlers in place for this + * IO Request object. This field is updated each time the request + * changes state. + */ + const struct scic_sds_io_request_state_handler *state_handlers; + + /** + * This field in the recorded device sequence for the io request. This is + * recorded during the build operation and is compared in the start + * operation. If the sequence is different then there was a change of + * devices from the build to start operations. + */ + u8 device_sequence; + +}; + + +typedef enum sci_status +(*scic_sds_io_request_frame_handler_t)(struct scic_sds_request *req, u32 frame); + +typedef enum sci_status +(*scic_sds_io_request_event_handler_t)(struct scic_sds_request *req, u32 event); + +typedef enum sci_status +(*scic_sds_io_request_task_completion_handler_t)(struct scic_sds_request *req, u32 completion_code); + +/** + * struct scic_sds_io_request_state_handler - This is the SDS core definition + * of the state handlers. + * + * + */ +struct scic_sds_io_request_state_handler { + struct sci_base_request_state_handler parent; + + scic_sds_io_request_task_completion_handler_t tc_completion_handler; + scic_sds_io_request_event_handler_t event_handler; + scic_sds_io_request_frame_handler_t frame_handler; + +}; + +extern const struct sci_base_state scic_sds_request_state_table[]; +extern const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[]; + +extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[]; +extern const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[]; + +extern const struct sci_base_state scic_sds_smp_request_started_substate_table[]; +extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[]; + +/** + * + * + * This macro returns the maximum number of SGL element paris that we will + * support in a single IO request. + */ +#define SCU_MAX_SGL_ELEMENT_PAIRS ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) + +/** + * scic_sds_request_get_controller() - + * + * This macro will return the controller for this io request object + */ +#define scic_sds_request_get_controller(this_request) \ + ((this_request)->owning_controller) + +/** + * scic_sds_request_get_device() - + * + * This macro will return the device for this io request object + */ +#define scic_sds_request_get_device(this_request) \ + ((this_request)->target_device) + +/** + * scic_sds_request_get_port() - + * + * This macro will return the port for this io request object + */ +#define scic_sds_request_get_port(this_request) \ + scic_sds_remote_device_get_port(scic_sds_request_get_device(this_request)) + +/** + * scic_sds_request_get_post_context() - + * + * This macro returns the constructed post context result for the io request. + */ +#define scic_sds_request_get_post_context(this_request) \ + ((this_request)->post_context) + +/** + * scic_sds_request_get_task_context() - + * + * This is a helper macro to return the os handle for this request object. + */ +#define scic_sds_request_get_task_context(request) \ + ((request)->task_context_buffer) + +#define CACHE_LINE_SIZE (64) +#define scic_sds_request_align_task_context_buffer(address) \ + ((struct scu_task_context *)(\ + (((unsigned long)(address)) + (CACHE_LINE_SIZE - 1)) \ + & ~(CACHE_LINE_SIZE - 1) \ + )) + +/** + * scic_sds_request_align_sgl_element_buffer() - + * + * This macro will align the memory address so that it is correct for the SCU + * hardware to DMA the SGL element pairs. + */ +#define scic_sds_request_align_sgl_element_buffer(address) \ + ((struct scu_sgl_element_pair *)(\ + ((char *)(address)) \ + + (\ + ((~(unsigned long)(address)) + 1) \ + & (sizeof(struct scu_sgl_element_pair) - 1) \ + ) \ + )) + +/** + * scic_sds_request_set_status() - + * + * This macro will set the scu hardware status and sci request completion + * status for an io request. + */ +#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \ + { \ + (request)->scu_status = (scu_status_code); \ + (request)->sci_status = (sci_status_code); \ + } + +#define scic_sds_request_complete(a_request) \ + ((a_request)->state_handlers->parent.complete_handler(&(a_request)->parent)) + + + + +/** + * scic_sds_io_request_tc_completion() - + * + * This macro invokes the core state task completion handler for the + * SCIC_SDS_IO_REQUEST_T object. + */ +#define scic_sds_io_request_tc_completion(this_request, completion_code) \ + { \ + if (this_request->parent.state_machine.current_state_id \ + == SCI_BASE_REQUEST_STATE_STARTED \ + && this_request->has_started_substate_machine \ + == false) \ + scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \ + else \ + this_request->state_handlers->tc_completion_handler(this_request, completion_code); \ + } + +/** + * SCU_SGL_ZERO() - + * + * This macro zeros the hardware SGL element data + */ +#define SCU_SGL_ZERO(scu_sge) \ + { \ + (scu_sge).length = 0; \ + (scu_sge).address_lower = 0; \ + (scu_sge).address_upper = 0; \ + (scu_sge).address_modifier = 0; \ + } + +/** + * SCU_SGL_COPY() - + * + * This macro copys the SGL Element data from the host os to the hardware SGL + * elment data + */ +#define SCU_SGL_COPY(os_handle, scu_sge, os_sge) \ + { \ + (scu_sge).length = \ + scic_cb_sge_get_length_field(os_handle, os_sge); \ + (scu_sge).address_upper = \ + upper_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \ + (scu_sge).address_lower = \ + lower_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \ + (scu_sge).address_modifier = 0; \ + } + +/* + * ***************************************************************************** + * * CORE REQUEST PROTOTYPES + * ***************************************************************************** */ + +void scic_sds_request_build_sgl( + struct scic_sds_request *this_request); + + + +void scic_sds_stp_request_assign_buffers( + struct scic_sds_request *this_request); + +void scic_sds_smp_request_assign_buffers( + struct scic_sds_request *this_request); + +/* --------------------------------------------------------------------------- */ + +enum sci_status scic_sds_request_start( + struct scic_sds_request *this_request); + +enum sci_status scic_sds_io_request_terminate( + struct scic_sds_request *this_request); + +enum sci_status scic_sds_io_request_complete( + struct scic_sds_request *this_request); + +void scic_sds_io_request_copy_response( + struct scic_sds_request *this_request); + +enum sci_status scic_sds_io_request_event_handler( + struct scic_sds_request *this_request, + u32 event_code); + +enum sci_status scic_sds_io_request_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index); + + +enum sci_status scic_sds_task_request_terminate( + struct scic_sds_request *this_request); + +/* + * ***************************************************************************** + * * DEFAULT STATE HANDLERS + * ***************************************************************************** */ + +enum sci_status scic_sds_request_default_start_handler( + struct sci_base_request *this_request); + + +enum sci_status scic_sds_request_default_complete_handler( + struct sci_base_request *this_request); + +enum sci_status scic_sds_request_default_destruct_handler( + struct sci_base_request *this_request); + +enum sci_status scic_sds_request_default_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code); + +enum sci_status scic_sds_request_default_event_handler( + struct scic_sds_request *this_request, + u32 event_code); + +enum sci_status scic_sds_request_default_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index); + +/* + * ***************************************************************************** + * * STARTED STATE HANDLERS + * ***************************************************************************** */ + +enum sci_status scic_sds_request_started_state_abort_handler( + struct sci_base_request *this_request); + +enum sci_status scic_sds_request_started_state_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code); + +#endif /* _SCIC_SDS_IO_REQUEST_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c new file mode 100644 index 000000000000..7cf78d3212cc --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -0,0 +1,410 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains This file contains the ready substate handlers for a SMP + * device. + * + * + */ + +#include "sci_environment.h" +#include "scic_user_callback.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "scic_sds_request.h" +#include "scu_event_codes.h" +#include "scu_task_context.h" + + +/* + * ***************************************************************************** + * * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @[in]: device The device the io is sent to. + * @[in]: request The io to start. + * + * This method will handle the start io operation for a SMP device that is in + * the idle state. enum sci_status + */ +static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status status; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *io_request = (struct scic_sds_request *)request; + + /* Will the port allow the io request to start? */ + status = this_device->owning_port->state_handlers->start_io_handler( + this_device->owning_port, + this_device, + io_request + ); + + if (status == SCI_SUCCESS) { + status = + scic_sds_remote_node_context_start_io(this_device->rnc, io_request); + + if (status == SCI_SUCCESS) { + status = scic_sds_request_start(io_request); + } + + if (status == SCI_SUCCESS) { + this_device->working_request = io_request; + + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD + ); + } + + scic_sds_remote_device_start_request(this_device, io_request, status); + } + + return status; +} + + +/* + * ****************************************************************************** + * * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS + * ****************************************************************************** */ +/** + * + * @device: This is the device object that is receiving the IO. + * @request: The io to start. + * + * This device is already handling a command it can not accept new commands + * until this one is complete. enum sci_status + */ +static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + return SCI_FAILURE_INVALID_STATE; +} + + +/** + * this is the complete_io_handler for smp device at ready cmd substate. + * @device: This is the device object that is receiving the IO. + * @request: The io to start. + * + * enum sci_status + */ +static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status status; + struct scic_sds_remote_device *this_device; + struct scic_sds_request *the_request; + + this_device = (struct scic_sds_remote_device *)device; + the_request = (struct scic_sds_request *)request; + + status = scic_sds_io_request_complete(the_request); + + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + this_device->owning_port, this_device, the_request); + + if (status == SCI_SUCCESS) { + scic_sds_remote_device_decrement_request_count(this_device); + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE + ); + } else + dev_err(scirdev_to_dev(this_device), + "%s: SCIC SDS Remote Device 0x%p io request " + "0x%p could not be completd on the port 0x%p " + "failed with status %d.\n", + __func__, + this_device, + the_request, + this_device->owning_port, + status); + } + + return status; +} + +/** + * This is frame handler for smp device ready cmd substate. + * @this_device: This is the device object that is receiving the frame. + * @frame_index: The index for the frame received. + * + * enum sci_status + */ +static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index) +{ + enum sci_status status; + + /* + * / The device does not process any UF received from the hardware while + * / in this state. All unsolicited frames are forwarded to the io request + * / object. */ + status = scic_sds_io_request_frame_handler( + this_device->working_request, + frame_index + ); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_remote_device_state_handler +scic_sds_smp_remote_device_ready_substate_handler_table[ + SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = +{ + /* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, + scic_sds_remote_device_default_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_remote_device_default_frame_handler + }, + /* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_default_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, + scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_remote_device_default_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_smp_remote_device_ready_cmd_substate_frame_handler + } +}; +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the enter and exit functions for the + * struct scic_sds_remote_device ready substate machine. + * + * + */ + +#include "scic_remote_device.h" +#include "scic_user_callback.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "sci_util.h" +#include "sci_environment.h" + +/** + * + * @object: This is the struct sci_base_object which is cast into a + * struct scic_sds_remote_device. + * + * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. + * This method sets the ready cmd substate handlers and reports the device as + * ready. none + */ +static void scic_sds_smp_remote_device_ready_idle_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + this_device, + scic_sds_smp_remote_device_ready_substate_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE + ); + + scic_cb_remote_device_ready( + scic_sds_remote_device_get_controller(this_device), this_device); +} + +/** + * + * @object: This is the struct sci_base_object which is cast into a + * struct scic_sds_remote_device. + * + * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This + * method sets the remote device objects ready cmd substate handlers, and + * notify core user that the device is not ready. none + */ +static void scic_sds_smp_remote_device_ready_cmd_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + BUG_ON(this_device->working_request == NULL); + + SET_STATE_HANDLER( + this_device, + scic_sds_smp_remote_device_ready_substate_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD + ); + + scic_cb_remote_device_not_ready( + scic_sds_remote_device_get_controller(this_device), + this_device, + SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED + ); +} + +/** + * + * @object: This is the struct sci_base_object which is cast into a + * struct scic_sds_remote_device. + * + * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none + */ +static void scic_sds_smp_remote_device_ready_cmd_substate_exit( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + + this_device->working_request = NULL; +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = { + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, + }, + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, + .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, + }, +}; diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c new file mode 100644 index 000000000000..949d23e7452a --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -0,0 +1,669 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "intel_sas.h" +#include "sci_base_state_machine.h" +#include "scic_controller.h" +#include "scic_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_request.h" +#include "scic_sds_smp_request.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_completion_codes.h" +#include "scu_task_context.h" + +static void scu_smp_request_construct_task_context( + struct scic_sds_request *this_request, + struct smp_request *smp_request); + +/** + * + * + * This method return the memory space required for STP PIO requests. u32 + */ +u32 scic_sds_smp_request_get_object_size(void) +{ + return sizeof(struct scic_sds_request) + + sizeof(struct smp_request) + + sizeof(struct smp_response) + + sizeof(struct scu_task_context); +} + +/** + * scic_sds_smp_request_get_command_buffer() - + * + * This macro returns the address of the smp command buffer in the smp request + * memory. No need to cast to SMP request type. + */ +#define scic_sds_smp_request_get_command_buffer(memory) \ + (((char *)(memory)) + sizeof(struct scic_sds_request)) + +/** + * scic_sds_smp_request_get_response_buffer() - + * + * This macro returns the address of the smp response buffer in the smp request + * memory. + */ +#define scic_sds_smp_request_get_response_buffer(memory) \ + (((char *)(scic_sds_smp_request_get_command_buffer(memory))) \ + + sizeof(struct smp_request)) + +/** + * scic_sds_smp_request_get_task_context_buffer() - + * + * This macro returs the task context buffer for the SMP request. + */ +#define scic_sds_smp_request_get_task_context_buffer(memory) \ + ((struct scu_task_context *)(\ + ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \ + + sizeof(struct smp_response) \ + )) + + + +/** + * This method build the remainder of the IO request object. + * @this_request: This parameter specifies the request object being constructed. + * + * The scic_sds_general_request_construct() must be called before this call is + * valid. none + */ + +void scic_sds_smp_request_assign_buffers( + struct scic_sds_request *this_request) +{ + /* Assign all of the buffer pointers */ + this_request->command_buffer = + scic_sds_smp_request_get_command_buffer(this_request); + this_request->response_buffer = + scic_sds_smp_request_get_response_buffer(this_request); + this_request->sgl_element_pair_buffer = NULL; + + if (this_request->was_tag_assigned_by_user == false) { + this_request->task_context_buffer = + scic_sds_smp_request_get_task_context_buffer(this_request); + this_request->task_context_buffer = + scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); + } + +} +/** + * This method is called by the SCI user to build an SMP IO request. + * + * - The user must have previously called scic_io_request_construct() on the + * supplied IO request. Indicate if the controller successfully built the IO + * request. SCI_SUCCESS This value is returned if the IO request was + * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned + * if the remote_device does not support the SMP protocol. + * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not + * properly set the association between the SCIC IO request and the user's IO + * request. Please refer to the sci_object_set_association() routine for more + * information. + */ +enum sci_status scic_io_request_construct_smp( + struct scic_sds_request *sci_req) +{ + struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); + + if (!smp_req) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + + sci_req->protocol = SCIC_SMP_PROTOCOL; + sci_req->has_started_substate_machine = true; + + /* Construct the started sub-state machine. */ + sci_base_state_machine_construct( + &sci_req->started_substate_machine, + &sci_req->parent.parent, + scic_sds_smp_request_started_substate_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE + ); + + /* Construct the SMP SCU Task Context */ + memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req)); + + /* + * Look at the SMP requests' header fields; for certain SAS 1.x SMP + * functions under SAS 2.0, a zero request length really indicates + * a non-zero default length. */ + if (smp_req->header.request_length == 0) { + switch (smp_req->header.function) { + case SMP_FUNCTION_DISCOVER: + case SMP_FUNCTION_REPORT_PHY_ERROR_LOG: + case SMP_FUNCTION_REPORT_PHY_SATA: + case SMP_FUNCTION_REPORT_ROUTE_INFORMATION: + smp_req->header.request_length = 2; + break; + case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION: + case SMP_FUNCTION_PHY_CONTROL: + case SMP_FUNCTION_PHY_TEST: + smp_req->header.request_length = 9; + break; + /* Default - zero is a valid default for 2.0. */ + } + } + + scu_smp_request_construct_task_context(sci_req, smp_req); + + sci_base_state_machine_change_state( + &sci_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED + ); + + kfree(smp_req); + + return SCI_SUCCESS; +} + +/** + * This method is called by the SCI user to build an SMP pass-through IO + * request. + * @scic_smp_request: This parameter specifies the handle to the io request + * object to be built. + * @passthru_cb: This parameter specifies the pointer to the callback structure + * that contains the function pointers + * + * - The user must have previously called scic_io_request_construct() on the + * supplied IO request. Indicate if the controller successfully built the IO + * request. + */ + +/** + * This method will fill in the SCU Task Context for a SMP request. The + * following important settings are utilized: -# task_type == + * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type + * (i.e. non-raw frame) is being utilized to perform task management. -# + * control_frame == 1. This ensures that the proper endianess is set so + * that the bytes are transmitted in the right order for a smp request frame. + * @this_request: This parameter specifies the smp request object being + * constructed. + * + */ +static void scu_smp_request_construct_task_context( + struct scic_sds_request *this_request, + struct smp_request *smp_request) +{ + dma_addr_t physical_address; + struct scic_sds_controller *owning_controller; + struct scic_sds_remote_device *target_device; + struct scic_sds_port *target_port; + struct scu_task_context *task_context; + + /* byte swap the smp request. */ + scic_word_copy_with_swap( + this_request->command_buffer, + (u32 *)smp_request, + sizeof(struct smp_request) / sizeof(u32) + ); + + task_context = scic_sds_request_get_task_context(this_request); + + owning_controller = scic_sds_request_get_controller(this_request); + target_device = scic_sds_request_get_device(this_request); + target_port = scic_sds_request_get_port(this_request); + + /* + * Fill in the TC with the its required data + * 00h */ + task_context->priority = 0; + task_context->initiator_request = 1; + task_context->connection_rate = + scic_remote_device_get_connection_rate(target_device); + task_context->protocol_engine_index = + scic_sds_controller_get_protocol_engine_group(owning_controller); + task_context->logical_port_index = + scic_sds_port_get_index(target_port); + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; + task_context->abort = 0; + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + /* 04h */ + task_context->remote_node_index = this_request->target_device->rnc->remote_node_index; + task_context->command_code = 0; + task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; + + /* 08h */ + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 1; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + /* 0ch */ + task_context->address_modifier = 0; + + /* 10h */ + task_context->ssp_command_iu_length = smp_request->header.request_length; + + /* 14h */ + task_context->transfer_length_bytes = 0; + + /* + * 18h ~ 30h, protocol specific + * since commandIU has been build by framework at this point, we just + * copy the frist DWord from command IU to this location. */ + memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(u32)); + + /* + * 40h + * "For SMP you could program it to zero. We would prefer that way so that + * done code will be consistent." - Venki */ + task_context->task_phase = 0; + + if (this_request->was_tag_assigned_by_user) { + /* Build the task context now since we have already read the data */ + this_request->post_context = ( + SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC + | ( + scic_sds_controller_get_protocol_engine_group(owning_controller) + << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT + ) + | ( + scic_sds_port_get_index(target_port) + << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT + ) + | scic_sds_io_tag_get_index(this_request->io_tag) + ); + } else { + /* Build the task context now since we have already read the data */ + this_request->post_context = ( + SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC + | ( + scic_sds_controller_get_protocol_engine_group(owning_controller) + << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT + ) + | ( + scic_sds_port_get_index(target_port) + << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT + ) + /* This is not assigned because we have to wait until we get a TCi */ + ); + } + + /* + * Copy the physical address for the command buffer to the SCU Task Context + * command buffer should not contain command header. */ + scic_cb_io_request_get_physical_address( + scic_sds_request_get_controller(this_request), + this_request, + ((char *)(this_request->command_buffer) + sizeof(u32)), + &physical_address + ); + + task_context->command_iu_upper = + upper_32_bits(physical_address); + task_context->command_iu_lower = + lower_32_bits(physical_address); + + + /* SMP response comes as UF, so no need to set response IU address. */ + task_context->response_iu_upper = 0; + task_context->response_iu_lower = 0; +} + +/** + * This method processes an unsolicited frame while the SMP request is waiting + * for a response frame. It will copy the response data, release the + * unsolicited frame, and transition the request to the + * SCI_BASE_REQUEST_STATE_COMPLETED state. + * @this_request: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This method returns an indication of whether the response frame was handled + * successfully or not. SCI_SUCCESS Currently this value is always returned and + * indicates successful processing of the TC response. + */ +static enum sci_status scic_sds_smp_request_await_response_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index) +{ + enum sci_status status; + void *frame_header; + struct smp_response_header *this_frame_header; + u8 *user_smp_buffer = this_request->response_buffer; + + status = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_request_get_controller(this_request)->uf_control), + frame_index, + &frame_header + ); + + /* byte swap the header. */ + scic_word_copy_with_swap( + (u32 *)user_smp_buffer, + frame_header, + sizeof(struct smp_response_header) / sizeof(u32) + ); + this_frame_header = (struct smp_response_header *)user_smp_buffer; + + if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) { + void *smp_response_buffer; + + status = scic_sds_unsolicited_frame_control_get_buffer( + &(scic_sds_request_get_controller(this_request)->uf_control), + frame_index, + &smp_response_buffer + ); + + scic_word_copy_with_swap( + (u32 *)(user_smp_buffer + sizeof(struct smp_response_header)), + smp_response_buffer, + sizeof(union smp_response_body) / sizeof(u32) + ); + if (this_frame_header->function == SMP_FUNCTION_DISCOVER) { + struct smp_response *this_smp_response; + + this_smp_response = (struct smp_response *)user_smp_buffer; + + /* + * Some expanders only report an attached SATA device, and + * not an STP target. Since the core depends on the STP + * target attribute to correctly build I/O, set the bit now + * if necessary. */ + if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device + && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) { + this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1; + + dev_dbg(scic_to_dev(this_request->owning_controller), + "%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n", + __func__, this_request); + } + } + + /* + * Don't need to copy to user space. User instead will refer to + * core request's response buffer. */ + + /* + * copy the smp response to framework smp request's response buffer. + * scic_sds_smp_request_copy_response(this_request); */ + + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION + ); + } else { + /* This was not a response frame why did it get forwarded? */ + dev_err(scic_to_dev(this_request->owning_controller), + "%s: SCIC SMP Request 0x%p received unexpected frame " + "%d type 0x%02x\n", + __func__, + this_request, + frame_index, + this_frame_header->smp_frame_type); + + scic_sds_request_set_status( + this_request, + SCU_TASK_DONE_SMP_FRM_TYPE_ERR, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + } + + scic_sds_controller_release_frame( + this_request->owning_controller, frame_index + ); + + return SCI_SUCCESS; +} + + +/** + * This method processes an abnormal TC completion while the SMP request is + * waiting for a response frame. It decides what happened to the IO based + * on TC completion status. + * @this_request: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + /* + * In the AWAIT RESPONSE state, any TC completion is unexpected. + * but if the TC has success status, we complete the IO anyway. */ + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): + /* + * These status has been seen in a specific LSI expander, which sometimes + * is not able to send smp response within 2 ms. This causes our hardware + * break the connection and set TC completion with one of these SMP_XXX_XX_ERR + * status. For these type of error, we ask scic user to retry the request. */ + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return SCI_SUCCESS; +} + + +/** + * This method processes the completions transport layer (TL) status to + * determine if the SMP request was sent successfully. If the SMP request + * was sent successfully, then the state for the SMP request transits to + * waiting for a response frame. + * @this_request: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return SCI_SUCCESS; +} + + +const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_smp_request_await_response_frame_handler, + }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + } +}; + +/** + * This method performs the actions required when entering the + * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This + * includes setting the IO request state handlers for this sub-state. + * @object: This parameter specifies the request object for which the sub-state + * change is occuring. + * + * none. + */ +static void scic_sds_smp_request_started_await_response_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_smp_request_started_substate_handler_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE + ); +} + +/** + * This method performs the actions required when entering the + * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state. + * This includes setting the SMP request state handlers for this sub-state. + * @object: This parameter specifies the request object for which the sub-state + * change is occuring. + * + * none. + */ +static void scic_sds_smp_request_started_await_tc_completion_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_smp_request_started_substate_handler_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION + ); +} + +const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { + .enter_state = scic_sds_smp_request_started_await_response_substate_enter, + }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { + .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, + }, +}; + diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.h b/drivers/scsi/isci/core/scic_sds_smp_request.h new file mode 100644 index 000000000000..b7c5b83b1989 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_smp_request.h @@ -0,0 +1,70 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SCIC_SDS_SMP_REQUEST_T_ +#define _SCIC_SDS_SMP_REQUEST_T_ + +#include "intel_sas.h" +#include "sci_types.h" +#include "scic_sds_request.h" + + +u32 scic_sds_smp_request_get_object_size(void); + + +void scic_sds_smp_request_copy_response( + struct scic_sds_request *this_request); + +#endif /* _SCIC_SDS_SMP_REQUEST_T_ */ + diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c new file mode 100644 index 000000000000..0d6441c5ce00 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -0,0 +1,340 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the task management substate handlers for the + * SCIC_SDS_IO_REQUEST object. + * + * + */ + +#include "intel_sas.h" +#include "sci_environment.h" +#include "scic_sds_request.h" +#include "scic_controller.h" +#include "scic_sds_controller.h" +#include "scu_completion_codes.h" +#include "scu_task_context.h" + +/** + * This method processes the completions transport layer (TL) status to + * determine if the RAW task management frame was sent successfully. If the + * raw frame was sent successfully, then the state for the task request + * transitions to waiting for a response frame. + * @this_request: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE + ); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): + /* + * Currently, the decision is to simply allow the task request to + * timeout if the task IU wasn't received successfully. + * There is a potential for receiving multiple task responses if we + * decide to send the task IU again. */ + dev_warn(scic_to_dev(this_request->owning_controller), + "%s: TaskRequest:0x%p CompletionCode:%x - " + "ACK/NAK timeout\n", + __func__, + this_request, + completion_code); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return SCI_SUCCESS; +} + +/** + * This method is responsible for processing a terminate/abort request for this + * TC while the request is waiting for the task management response + * unsolicited frame. + * @this_request: This parameter specifies the request for which the + * termination was requested. + * + * This method returns an indication as to whether the abort request was + * successfully handled. need to update to ensure the received UF doesn't cause + * damage to subsequent requests (i.e. put the extended tag in a holding + * pattern for this particular device). + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_ABORTING + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + return SCI_SUCCESS; +} + +/** + * This method processes an unsolicited frame while the task mgmt request is + * waiting for a response frame. It will copy the response data, release + * the unsolicited frame, and transition the request to the + * SCI_BASE_REQUEST_STATE_COMPLETED state. + * @this_request: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This method returns an indication of whether the TC response frame was + * handled successfully or not. SCI_SUCCESS Currently this value is always + * returned and indicates successful processing of the TC response. Should + * probably update to check frame type and make sure it is a response frame. + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index) +{ + scic_sds_io_request_copy_response(this_request); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + scic_sds_controller_release_frame( + this_request->owning_controller, frame_index + ); + + return SCI_SUCCESS; +} + +const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, + } +}; + +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the enter/exit methods associated with each of the task + * management raw request states. For more information on the task + * management request state machine please refer to scic_sds_io_request.h + * + * + */ + +#include "scic_sds_request.h" +#include "sci_base_state_machine.h" + +/** + * This method performs the actions required when entering the + * SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION + * sub-state. This includes setting the IO request state handlers for this + * sub-state. + * @object: This parameter specifies the request object for which the sub-state + * change is occuring. + * + * none. + */ +static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_ssp_task_request_started_substate_handler_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION + ); +} + +/** + * This method performs the actions required when entering the + * SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This + * includes setting the IO request state handlers for this sub-state. + * @object: This parameter specifies the request object for which the sub-state + * change is occuring. + * + * none. + */ +static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_ssp_task_request_started_substate_handler_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE + ); +} + +const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = { + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { + .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, + }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { + .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, + }, +}; + diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c new file mode 100644 index 000000000000..f52a8e32b48f --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c @@ -0,0 +1,838 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#if !defined(DISABLE_ATAPI) + +#include "intel_ata.h" +#include "intel_sas.h" +#include "intel_sata.h" +#include "intel_sat.h" +#include "sati_translator_sequence.h" +#include "sci_base_state.h" +#include "scic_controller.h" +#include "scic_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_request.h" +#include "scic_sds_stp_packet_request.h" +#include "scic_user_callback.h" +#include "sci_util.h" +#include "scu_completion_codes.h" +#include "scu_task_context.h" + + +/** + * This method will fill in the SCU Task Context for a PACKET fis. And + * construct the request STARTED sub-state machine for Packet Protocol IO. + * @this_request: This parameter specifies the stp packet request object being + * constructed. + * + */ +enum sci_status scic_sds_stp_packet_request_construct( + struct scic_sds_request *this_request) +{ + struct sata_fis_reg_h2d *h2d_fis = + scic_stp_io_request_get_h2d_reg_address( + this_request + ); + + /* + * Work around, we currently only support PACKET DMA protocol, so we + * need to make change to Packet Fis features field. */ + h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA; + + scic_sds_stp_non_ncq_request_construct(this_request); + + /* Build the Packet Fis task context structure */ + scu_stp_raw_request_construct_task_context( + (struct scic_sds_stp_request *)this_request, + this_request->task_context_buffer + ); + + sci_base_state_machine_construct( + &this_request->started_substate_machine, + &this_request->parent.parent, + scic_sds_stp_packet_request_started_substate_table, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE + ); + + return SCI_SUCCESS; +} + + +/** + * This method will fill in the SCU Task Context for a Packet request command + * phase in PACKET DMA DATA (IN/OUT) type. The following important settings + * are utilized: -# task_type == SCU_TASK_TYPE_PACKET_DMA. This simply + * indicates that a normal request type (i.e. non-raw frame) is being + * utilized to perform task management. -# control_frame == 1. This ensures + * that the proper endianess is set so that the bytes are transmitted in the + * right order for a smp request frame. + * @this_request: This parameter specifies the smp request object being + * constructed. + * @task_context: The task_context to be reconstruct for packet request command + * phase. + * + */ +void scu_stp_packet_request_command_phase_construct_task_context( + struct scic_sds_request *this_request, + struct scu_task_context *task_context) +{ + void *atapi_cdb; + u32 atapi_cdb_length; + struct scic_sds_stp_request *stp_request = (struct scic_sds_stp_request *)this_request; + + /* + * reference: SSTL 1.13.4.2 + * task_type, sata_direction */ + if (scic_cb_io_request_get_data_direction(this_request->user_request) + == SCI_IO_REQUEST_DATA_OUT) { + task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT; + task_context->sata_direction = 0; + } else { /* todo: for NO_DATA command, we need to send out raw frame. */ + task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN; + task_context->sata_direction = 1; + } + + /* sata header */ + memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT)); + task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; + + /* + * Copy in the command IU with CDB so that the commandIU address doesn't + * change. */ + memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); + + atapi_cdb = + scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request); + + atapi_cdb_length = + scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request); + + memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); + + atapi_cdb_length = + max(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length); + + task_context->ssp_command_iu_length = + ((atapi_cdb_length % 4) == 0) ? + (atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1); + + /* task phase is set to TX_CMD */ + task_context->task_phase = 0x1; + + /* retry counter */ + task_context->stp_retry_count = 0; + + if (scic_cb_request_is_initial_construction(this_request->user_request)) { + /* data transfer size. */ + task_context->transfer_length_bytes = + scic_cb_io_request_get_transfer_length(this_request->user_request); + + /* setup sgl */ + scic_sds_request_build_sgl(this_request); + } else { + /* data transfer size, need to be 4 bytes aligned. */ + task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2); + + scic_sds_stp_packet_internal_request_sense_build_sgl(this_request); + } +} + +/** + * This method will fill in the SCU Task Context for a DATA fis containing CDB + * in Raw Frame type. The TC for previous Packet fis was already there, we + * only need to change the H2D fis content. + * @this_request: This parameter specifies the smp request object being + * constructed. + * @task_context: The task_context to be reconstruct for packet request command + * phase. + * + */ +void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( + struct scic_sds_request *this_request, + struct scu_task_context *task_context) +{ + void *atapi_cdb = + scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request); + + u32 atapi_cdb_length = + scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request); + + memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); + memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); + + memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT)); + task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; + + /* + * Note the data send out has to be 4 bytes aligned. Or else out hardware will + * patch non-zero bytes and cause the target device unhappy. */ + task_context->transfer_length_bytes = 12; +} + + +/* + * *@brief This methods decode the D2H status FIS and retrieve the sense data, + * then pass the sense data to user request. + * + ***@param[in] this_request The request receive D2H status FIS. + ***@param[in] status_fis The D2H status fis to be processed. + * + */ +enum sci_status scic_sds_stp_packet_request_process_status_fis( + struct scic_sds_request *this_request, + struct sata_fis_reg_d2h *status_fis) +{ + enum sci_status status = SCI_SUCCESS; + + /* TODO: Process the error status fis, retrieve sense data. */ + if (status_fis->status & ATA_STATUS_REG_ERROR_BIT) + status = SCI_FAILURE_IO_RESPONSE_VALID; + + return status; +} + +/* + * *@brief This methods builds sgl for internal REQUEST SENSE stp packet + * command using this request response buffer, only one sge is + * needed. + * + ***@param[in] this_request The request receive request sense data. + * + */ +void scic_sds_stp_packet_internal_request_sense_build_sgl( + struct scic_sds_request *this_request) +{ + void *sge; + struct scu_sgl_element_pair *scu_sgl_list = NULL; + struct scu_task_context *task_context; + dma_addr_t physical_address; + + struct sci_ssp_response_iu *rsp_iu = + (struct sci_ssp_response_iu *)this_request->response_buffer; + + sge = (void *)&rsp_iu->data[0]; + + task_context = (struct scu_task_context *)this_request->task_context_buffer; + scu_sgl_list = &task_context->sgl_pair_ab; + + scic_cb_io_request_get_physical_address( + scic_sds_request_get_controller(this_request), + this_request, + ((char *)sge), + &physical_address + ); + + scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address); + scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address); + scu_sgl_list->A.length = task_context->transfer_length_bytes; + scu_sgl_list->A.address_modifier = 0; + + SCU_SGL_ZERO(scu_sgl_list->B); +} + +/** + * This method processes the completions transport layer (TL) status to + * determine if the Packet FIS was sent successfully. If the Packet FIS was + * sent successfully, then the state for the Packet request transits to + * waiting for a PIO SETUP frame. + * @this_request: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return status; +} + + +/** + * This method processes an unsolicited frame while the Packet request is + * waiting for a PIO SETUP FIS. It will release the unsolicited frame, and + * transition the request to the COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE + * state. + * @this_request: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This method returns an indication of whether the pio setup frame was handled + * successfully or not. SCI_SUCCESS Currently this value is always returned and + * indicates successful processing of the TC response. + */ +enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *this_request; + + this_request = (struct scic_sds_stp_request *)request; + + status = scic_sds_unsolicited_frame_control_get_header( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_header + ); + + if (status == SCI_SUCCESS) { + BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_PIO_SETUP); + + /* + * Get from the frame buffer the PIO Setup Data, although we don't need + * any info from this pio setup fis. */ + scic_sds_unsolicited_frame_control_get_buffer( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_buffer + ); + + /* + * Get the data from the PIO Setup + * The SCU Hardware returns first word in the frame_header and the rest + * of the data is in the frame buffer so we need to back up one dword */ + this_request->type.packet.device_preferred_cdb_length = + (u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count; + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame( + this_request->parent.owning_controller, frame_index + ); + + sci_base_state_machine_change_state( + &this_request->parent.started_substate_machine, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE + ); + } else + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, this_request, frame_index, status); + + return status; +} + + +/** + * This method processes the completions transport layer (TL) status to + * determine if the PACKET command data FIS was sent successfully. If + * successfully, then the state for the packet request transits to COMPLETE + * state. If not successfuly, the request transits to + * COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE. + * @this_request: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + u8 sat_packet_protocol = + scic_cb_request_get_sat_protocol(this_request->user_request); + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + if (sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN + || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT + ) + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + else + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE + ); + break; + + case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): + if (scic_io_request_get_number_of_bytes_transferred(this_request) < + scic_cb_io_request_get_transfer_length(this_request->user_request)) { + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + status = this_request->sci_status; + } + break; + + case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT): + /* In this case, there is no UF coming after. compelte the IO now. */ + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + break; + + default: + if (this_request->sci_status != SCI_SUCCESS) { /* The io status was set already. This means an UF for the status + * fis was received already. + */ + + /* + * A device suspension event is expected, we need to have the device + * coming out of suspension, then complete the IO. */ + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE + ); + + /* change the device state to ATAPI_ERROR. */ + sci_base_state_machine_change_state( + &this_request->target_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR + ); + + status = this_request->sci_status; + } else { /* If receiving any non-sucess TC status, no UF received yet, then an UF for + * the status fis is coming after. + */ + scic_sds_request_set_status( + this_request, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE + ); + } + break; + } + + return status; +} + + +/** + * This method processes an unsolicited frame. + * @this_request: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This method returns an indication of whether the UF frame was handled + * successfully or not. SCI_SUCCESS Currently this value is always returned and + * indicates successful processing of the TC response. + */ +enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *this_request; + + this_request = (struct scic_sds_stp_request *)request; + + status = scic_sds_unsolicited_frame_control_get_header( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_header + ); + + if (status == SCI_SUCCESS) { + BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_REGD2H); + + /* + * Get from the frame buffer the PIO Setup Data, although we don't need + * any info from this pio setup fis. */ + scic_sds_unsolicited_frame_control_get_buffer( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_buffer + ); + + scic_sds_controller_copy_sata_response( + &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer + ); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame( + this_request->parent.owning_controller, frame_index + ); + } + + return status; +} + +/** + * This method processes an unsolicited frame while the packet request is + * expecting TC completion. It will process the FIS and construct sense data. + * @this_request: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This method returns an indication of whether the UF frame was handled + * successfully or not. SCI_SUCCESS Currently this value is always returned and + * indicates successful processing of the TC response. + */ +enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + + enum sci_status status = + scic_sds_stp_packet_request_command_phase_common_frame_handler( + request, frame_index); + + if (status == SCI_SUCCESS) { + /* The command has completed with error status from target device. */ + status = scic_sds_stp_packet_request_process_status_fis( + request, &this_request->d2h_reg_fis); + + if (status != SCI_SUCCESS) { + scic_sds_request_set_status( + &this_request->parent, + SCU_TASK_DONE_CHECK_RESPONSE, + status + ); + } else + scic_sds_request_set_status( + &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + } + + return status; +} + + +/** + * This method processes an unsolicited frame while the packet request is + * expecting TC completion. It will process the FIS and construct sense data. + * @this_request: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This method returns an indication of whether the UF frame was handled + * successfully or not. SCI_SUCCESS Currently this value is always returned and + * indicates successful processing of the TC response. + */ +enum sci_status scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + enum sci_status status = + scic_sds_stp_packet_request_command_phase_common_frame_handler( + request, frame_index); + + struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + + if (status == SCI_SUCCESS) { + /* The command has completed with error status from target device. */ + status = scic_sds_stp_packet_request_process_status_fis( + request, &this_request->d2h_reg_fis); + + if (status != SCI_SUCCESS) { + scic_sds_request_set_status( + request, + SCU_TASK_DONE_CHECK_RESPONSE, + status + ); + } else + scic_sds_request_set_status( + request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + /* + * Always complete the NON_DATA command right away, no need to delay completion + * even an error status fis came from target device. */ + sci_base_state_machine_change_state( + &request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + } + + return status; +} + +enum sci_status scic_sds_stp_packet_request_started_completion_delay_complete_handler( + struct sci_base_request *request) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + return this_request->sci_status; +} + +/* --------------------------------------------------------------------------- */ + +const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[] = { + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler + .tc_completion_handler = scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler + }, + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler + }, + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler + .tc_completion_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler + }, + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler + }, + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_stp_packet_request_started_completion_delay_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler + }, +}; + +void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_packet_request_started_substate_handler_table, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + this_request->target_device, this_request + ); +} + +void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_packet_request_started_substate_handler_table, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE + ); +} + +void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + u8 sat_packet_protocol = + scic_cb_request_get_sat_protocol(this_request->user_request); + + struct scu_task_context *task_context; + enum sci_status status; + + /* + * Recycle the TC and reconstruct it for sending out data fis containing + * CDB. */ + task_context = scic_sds_controller_get_task_context_buffer( + this_request->owning_controller, this_request->io_tag); + + if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA) + scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( + this_request, task_context); + else + scu_stp_packet_request_command_phase_construct_task_context( + this_request, task_context); + + /* send the new TC out. */ + status = this_request->owning_controller->state_handlers->parent.continue_io_handler( + &this_request->owning_controller->parent, + &this_request->target_device->parent, + &this_request->parent + ); + + if (status == SCI_SUCCESS) + SET_STATE_HANDLER( + this_request, + scic_sds_stp_packet_request_started_substate_handler_table, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE + ); +} + +void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_packet_request_started_substate_handler_table, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE + ); +} + +void scic_sds_stp_packet_request_started_completion_delay_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_packet_request_started_substate_handler_table, + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE + ); +} + + +/* --------------------------------------------------------------------------- */ +const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[] = { + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter, + }, + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = { + .enter_state = scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter, + }, + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter, + }, + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = { + .enter_state = scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter, + }, + [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = { + .enter_state scic_sds_stp_packet_request_started_completion_delay_enter, + } +}; + +#endif /* !defined(DISABLE_ATAPI) */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h new file mode 100644 index 000000000000..fc18b3f6a13f --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h @@ -0,0 +1,154 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SCIC_SDS_STP_PACKET_REQUEST_H_ +#define _SCIC_SDS_STP_PACKET_REQUEST_H_ + +#include "intel_sas.h" +#include "sci_types.h" +#include "scic_sds_stp_request.h" + +/** + * This file contains the structures and constants for PACKET protocol requests. + * + * + */ + + +/** + * + * + * This is the enumeration of the SATA PIO DATA IN started substate machine. + */ +enum _SCIC_SDS_STP_PACKET_REQUEST_STARTED_SUBSTATES { + /** + * While in this state the IO request object is waiting for the TC completion + * notification for the H2D Register FIS + */ + SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE, + + /** + * While in this state the IO request object is waiting for either a PIO Setup. + */ + SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE, + + /** + * While in this state the IO request object is waiting for TC completion for + * the Packet DMA DATA fis or Raw Frame. + */ + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE, + + /** + * The non-data IO transit to this state in this state after receiving TC + * completion. While in this state IO request object is waiting for D2H status + * frame as UF. + */ + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE, + + /** + * The IO transit to this state in this state if the previous TC completion status + * is not success and the atapi device is suspended due to target device failed the IO. + * While in this state IO request object is waiting for device coming out of the + * suspension state then complete the IO. + */ + SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE, +}; + + + +#if !defined(DISABLE_ATAPI) +extern const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[]; +extern const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[]; +#endif /* !defined(DISABLE_ATAPI) */ + +#if !defined(DISABLE_ATAPI) +enum sci_status scic_sds_stp_packet_request_construct( + struct scic_sds_request *this_request); +#else /* !defined(DISABLE_ATAPI) */ +#define scic_sds_stp_packet_request_construct(request) SCI_FAILURE +#endif /* !defined(DISABLE_ATAPI) */ + +#if !defined(DISABLE_ATAPI) +void scu_stp_packet_request_command_phase_construct_task_context( + struct scic_sds_request *this_request, + struct scu_task_context *task_context); +#else /* !defined(DISABLE_ATAPI) */ +#define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc) +#endif /* !defined(DISABLE_ATAPI) */ + +#if !defined(DISABLE_ATAPI) +void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( + struct scic_sds_request *this_request, + struct scu_task_context *task_context); +#else /* !defined(DISABLE_ATAPI) */ +#define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc) +#endif /* !defined(DISABLE_ATAPI) */ + +#if !defined(DISABLE_ATAPI) +enum sci_status scic_sds_stp_packet_request_process_status_fis( + struct scic_sds_request *this_request, + struct sata_fis_reg_d2h *status_fis); +#else /* !defined(DISABLE_ATAPI) */ +#define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE +#endif /* !defined(DISABLE_ATAPI) */ + +#if !defined(DISABLE_ATAPI) +void scic_sds_stp_packet_internal_request_sense_build_sgl( + struct scic_sds_request *this_request); +#else /* !defined(DISABLE_ATAPI) */ +#define scic_sds_stp_packet_internal_request_sense_build_sgl(request) +#endif /* !defined(DISABLE_ATAPI) */ + +#endif /* _SCIC_SDS_STP_PACKET_REQUEST_H_ */ + diff --git a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h new file mode 100644 index 000000000000..64bf40a6e1d2 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h @@ -0,0 +1,116 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_SATA_PIO_REQUEST_H_ +#define _SCIC_SDS_SATA_PIO_REQUEST_H_ + +#include "sci_base_state.h" +#include "scic_sds_request.h" +#include "scu_task_context.h" + +/** + * This file contains the structures and constants for SATA PIO requests. + * + * + */ + + +/** + * + * + * This is the enumeration of the SATA PIO DATA IN started substate machine. + */ +enum _SCIC_SDS_STP_REQUEST_STARTED_PIO_SUBSTATES { + /** + * While in this state the IO request object is waiting for the TC completion + * notification for the H2D Register FIS + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE, + + /** + * While in this state the IO request object is waiting for either a PIO Setup + * FIS or a D2H register FIS. The type of frame received is based on the + * result of the prior frame and line conditions. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE, + + /** + * While in this state the IO request object is waiting for a DATA frame from + * the device. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE, + + /** + * While in this state the IO request object is waiting to transmit the next data + * frame to the device. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, +}; + + +/* --------------------------------------------------------------------------- */ + +extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[]; + +extern const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[]; + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_stp_request; + +struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl( + struct scic_sds_stp_request *this_request); + +#endif /* _SCIC_SDS_SATA_PIO_REQUEST_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c new file mode 100644 index 000000000000..abe8f331a15c --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -0,0 +1,975 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the ready substate handlers for an STP device. + * + * + */ + +#include "intel_sat.h" +#include "intel_ata.h" +#include "intel_sata.h" +#include "sci_environment.h" +#include "scic_remote_device.h" +#include "scic_user_callback.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_request.h" +#include "scu_event_codes.h" + +/** + * This method will perform the STP request completion processing common to IO + * requests and task requests of all types + * @device: This parameter specifies the device for which the request is being + * completed. + * @request: This parameter specifies the request being completed. + * + * This method returns an indication as to whether the request processing + * completed successfully. + */ +static enum sci_status scic_sds_stp_remote_device_complete_request( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *the_request = (struct scic_sds_request *)request; + enum sci_status status; + + status = scic_sds_io_request_complete(the_request); + + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + this_device->owning_port, this_device, the_request + ); + + if (status == SCI_SUCCESS) { + scic_sds_remote_device_decrement_request_count(this_device); + if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + /* + * This request causes hardware error, device needs to be Lun Reset. + * So here we force the state machine to IDLE state so the rest IOs + * can reach RNC state handler, these IOs will be completed by RNC with + * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET + ); + } else if (scic_sds_remote_device_get_request_count(this_device) == 0) { + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE + ); + } + } + } + + if (status != SCI_SUCCESS) + dev_err(scirdev_to_dev(this_device), + "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " + "could not complete\n", + __func__, + this_device->owning_port, + this_device, + the_request, + status); + + return status; +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * This is the READY NCQ substate handler to start task management request. In + * this routine, we suspend and resume the RNC. + * @device: The target device a task management request towards to. + * @request: The task request. + * + * enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to + * let controller_start_task_handler know that the controller can't post TC for + * task request yet, instead, when RNC gets resumed, a controller_continue_task + * callback will be called. + */ +static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status status; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *this_request = (struct scic_sds_request *)request; + + /* Will the port allow the io request to start? */ + status = this_device->owning_port->state_handlers->start_io_handler( + this_device->owning_port, + this_device, + this_request + ); + + if (SCI_SUCCESS == status) { + status = + scic_sds_remote_node_context_start_task(this_device->rnc, this_request); + + if (SCI_SUCCESS == status) { + status = this_request->state_handlers->parent.start_handler(request); + } + + if (status == SCI_SUCCESS) { + /* + * / @note If the remote device state is not IDLE this will replace + * / the request that probably resulted in the task management + * / request. */ + this_device->working_request = this_request; + + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD + ); + + /* + * The remote node context must cleanup the TCi to NCQ mapping table. + * The only way to do this correctly is to either write to the TLCR + * register or to invalidate and repost the RNC. In either case the + * remote node context state machine will take the correct action when + * the remote node context is suspended and later resumed. */ + scic_sds_remote_node_context_suspend( + this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); + + scic_sds_remote_node_context_resume( + this_device->rnc, + (SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK) + scic_sds_remote_device_continue_request, + this_device); + } + + scic_sds_remote_device_start_request(this_device, this_request, status); + + /* + * We need to let the controller start request handler know that it can't + * post TC yet. We will provide a callback function to post TC when RNC gets + * resumed. */ + return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; + } + + return status; +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * This method will handle the start io operation for a sata device that is in + * the command idle state. - Evalute the type of IO request to be started - + * If its an NCQ request change to NCQ substate - If its any other command + * change to the CMD substate + * @device: + * @request: + * + * If this is a softreset we may want to have a different substate. enum sci_status + */ +static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status status; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *io_request = (struct scic_sds_request *)request; + + + /* Will the port allow the io request to start? */ + status = this_device->owning_port->state_handlers->start_io_handler( + this_device->owning_port, + this_device, + io_request + ); + + if (status == SCI_SUCCESS) { + status = + scic_sds_remote_node_context_start_io(this_device->rnc, io_request); + + if (status == SCI_SUCCESS) { + status = io_request->state_handlers->parent.start_handler(request); + } + + if (status == SCI_SUCCESS) { + if ( + scic_cb_request_get_sat_protocol(io_request->user_request) + == SAT_PROTOCOL_FPDMA + ) { + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ + ); + } else { + this_device->working_request = io_request; + + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD + ); + } + } + + scic_sds_remote_device_start_request(this_device, io_request, status); + } + + return status; +} + + +/** + * + * @[in]: device The device received event. + * @[in]: event_code The event code. + * + * This method will handle the event for a sata device that is in the idle + * state. We pick up suspension events to handle specifically to this state. We + * resume the RNC right away. enum sci_status + */ +static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( + struct scic_sds_remote_device *this_device, + u32 event_code) +{ + enum sci_status status; + + status = scic_sds_remote_device_general_event_handler(this_device, event_code); + + if (status == SCI_SUCCESS) { + if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX + || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { + status = scic_sds_remote_node_context_resume( + this_device->rnc, NULL, NULL); + } + } + + return status; +} + + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS + * ***************************************************************************** */ + +static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + enum sci_status status; + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *io_request = (struct scic_sds_request *)request; + + if ( + scic_cb_request_get_sat_protocol(io_request->user_request) + == SAT_PROTOCOL_FPDMA + ) { + status = this_device->owning_port->state_handlers->start_io_handler( + this_device->owning_port, + this_device, + io_request + ); + + if (status == SCI_SUCCESS) { + status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request); + + if (status == SCI_SUCCESS) { + status = io_request->state_handlers->parent.start_handler(request); + } + + scic_sds_remote_device_start_request(this_device, io_request, status); + } + } else { + status = SCI_FAILURE_INVALID_STATE; + } + + return status; +} + + +/** + * This method will handle events received while the STP device is in the ready + * command substate. + * @this_device: This is the device object that is receiving the event. + * @event_code: The event code to process. + * + * enum sci_status + */ + +static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + + status = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_remote_device_get_controller(this_device)->uf_control), + frame_index, + (void **)&frame_header + ); + + if (status == SCI_SUCCESS) { + if ( + (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS) + && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) + ) { + this_device->not_ready_reason = + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR + ); + } else { + status = SCI_FAILURE; + } + + scic_sds_controller_release_frame( + scic_sds_remote_device_get_controller(this_device), frame_index + ); + } + + return status; +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * This device is already handling a command it can not accept new commands + * until this one is complete. + * @device: + * @request: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( + struct scic_sds_remote_device *this_device, + u32 suspend_type) +{ + enum sci_status status; + + status = scic_sds_remote_node_context_suspend( + this_device->rnc, suspend_type, NULL, NULL + ); + + return status; +} + +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( + struct scic_sds_remote_device *this_device, + u32 frame_index) +{ + enum sci_status status; + + /* + * / The device doe not process any UF received from the hardware while + * / in this state. All unsolicited frames are forwarded to the io request + * / object. */ + status = scic_sds_io_request_frame_handler( + this_device->working_request, + frame_index + ); + + return status; +} + + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS + * ***************************************************************************** */ + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS + * ***************************************************************************** */ + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS + * ***************************************************************************** */ +static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; +} + + + +/** + * This method will perform the STP request (both io or task) completion + * processing for await reset state. + * @device: This parameter specifies the device for which the request is being + * completed. + * @request: This parameter specifies the request being completed. + * + * This method returns an indication as to whether the request processing + * completed successfully. + */ +static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( + struct sci_base_remote_device *device, + struct sci_base_request *request) +{ + struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_request *the_request = (struct scic_sds_request *)request; + enum sci_status status; + + status = scic_sds_io_request_complete(the_request); + + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + this_device->owning_port, this_device, the_request + ); + + if (status == SCI_SUCCESS) + scic_sds_remote_device_decrement_request_count(this_device); + } + + if (status != SCI_SUCCESS) + dev_err(scirdev_to_dev(this_device), + "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " + "could not complete\n", + __func__, + this_device->owning_port, + this_device, + the_request, + status); + + return status; +} + +#if !defined(DISABLE_ATAPI) +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @[in]: device The device received event. + * @[in]: event_code The event code. + * + * This method will handle the event for a ATAPI device that is in the ATAPI + * ERROR state. We pick up suspension events to handle specifically to this + * state. We resume the RNC right away. We then complete the outstanding IO to + * this device. enum sci_status + */ +enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( + struct scic_sds_remote_device *this_device, + u32 event_code) +{ + enum sci_status status; + + status = scic_sds_remote_device_general_event_handler(this_device, event_code); + + if (status == SCI_SUCCESS) { + if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX + || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { + status = scic_sds_remote_node_context_resume( + this_device->rnc, + this_device->working_request->state_handlers->parent.complete_handler, + (void *)this_device->working_request + ); + } + } + + return status; +} +#endif /* !defined(DISABLE_ATAPI) */ + +/* --------------------------------------------------------------------------- */ + +struct scic_sds_remote_device_state_handler +scic_sds_stp_remote_device_ready_substate_handler_table[ + SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = +{ + /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_ready_state_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, + scic_sds_remote_device_default_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_stp_remote_device_ready_substate_start_request_handler, + scic_sds_remote_device_default_complete_request_handler + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_stp_remote_device_ready_idle_substate_event_handler, + scic_sds_remote_device_default_frame_handler + }, + /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_ready_state_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, + scic_sds_stp_remote_device_complete_request, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_stp_remote_device_ready_substate_start_request_handler, + scic_sds_stp_remote_device_complete_request, + }, + scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_stp_remote_device_ready_cmd_substate_frame_handler + }, + /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_ready_state_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, + scic_sds_stp_remote_device_complete_request, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_stp_remote_device_ready_substate_start_request_handler, + scic_sds_stp_remote_device_complete_request + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_stp_remote_device_ready_ncq_substate_frame_handler + }, + /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_ready_state_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_stp_remote_device_complete_request, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_stp_remote_device_ready_substate_start_request_handler, + scic_sds_stp_remote_device_complete_request + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_remote_device_general_frame_handler + }, +#if !defined(DISABLE_ATAPI) + /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_ready_state_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_remote_device_default_start_request_handler, + scic_sds_stp_remote_device_complete_request, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_stp_remote_device_ready_substate_start_request_handler, + scic_sds_stp_remote_device_complete_request + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, + scic_sds_remote_device_general_frame_handler + }, +#endif + /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET */ + { + { + scic_sds_remote_device_default_start_handler, + scic_sds_remote_device_ready_state_stop_handler, + scic_sds_remote_device_default_fail_handler, + scic_sds_remote_device_default_destruct_handler, + scic_sds_remote_device_ready_state_reset_handler, + scic_sds_remote_device_default_reset_complete_handler, + scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, + scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, + scic_sds_remote_device_default_continue_request_handler, + scic_sds_stp_remote_device_ready_substate_start_request_handler, + scic_sds_stp_remote_device_complete_request + }, + scic_sds_remote_device_default_suspend_handler, + scic_sds_remote_device_default_resume_handler, + scic_sds_remote_device_general_event_handler, + scic_sds_remote_device_general_frame_handler + } +}; + +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sci_base_state.h" +#include "scic_remote_device.h" +#include "scic_user_callback.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "scic_sds_remote_device.h" +#include "sci_util.h" +#include "sci_environment.h" + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS + * ***************************************************************************** */ + +static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( + void *user_cookie) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)user_cookie; + + /* + * For NCQ operation we do not issue a + * scic_cb_remote_device_not_ready(). As a result, avoid sending + * the ready notification. */ + if (this_device->ready_substate_machine.previous_state_id + != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) { + scic_cb_remote_device_ready( + scic_sds_remote_device_get_controller(this_device), this_device + ); + } +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY IDLE SUBSTATE + * ***************************************************************************** */ + +/** + * + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +static void scic_sds_stp_remote_device_ready_idle_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)device; + + SET_STATE_HANDLER( + this_device, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE + ); + + this_device->working_request = NULL; + + if (scic_sds_remote_node_context_is_ready(this_device->rnc)) { + /* + * Since the RNC is ready, it's alright to finish completion + * processing (e.g. signal the remote device is ready). */ + scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( + this_device + ); + } else { + scic_sds_remote_node_context_resume( + this_device->rnc, + scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, + this_device + ); + } +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY CMD SUBSTATE + * ***************************************************************************** */ + +/** + * + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +static void scic_sds_stp_remote_device_ready_cmd_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)device; + + BUG_ON(this_device->working_request == NULL); + + SET_STATE_HANDLER( + this_device, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD + ); + + scic_cb_remote_device_not_ready( + scic_sds_remote_device_get_controller(this_device), + this_device, + SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED + ); +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY NCQ SUBSTATE + * ***************************************************************************** */ + +/** + * + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +static void scic_sds_stp_remote_device_ready_ncq_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)device; + + SET_STATE_HANDLER( + this_device, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ + ); +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE + * ***************************************************************************** */ + +/** + * + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)device; + + SET_STATE_HANDLER( + this_device, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR + ); + + if (this_device->not_ready_reason == + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) { + scic_cb_remote_device_not_ready( + scic_sds_remote_device_get_controller(this_device), + this_device, + this_device->not_ready_reason + ); + } +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE + * ***************************************************************************** */ + +/** + * The enter routine to READY AWAIT RESET substate. + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)device; + + SET_STATE_HANDLER( + this_device, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET + ); +} + +#if !defined(DISABLE_ATAPI) +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE + * ***************************************************************************** */ + +/** + * The enter routine to READY ATAPI ERROR substate. + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +void scic_sds_stp_remote_device_ready_atapi_error_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *this_device; + + this_device = (struct scic_sds_remote_device *)device; + + SET_STATE_HANDLER( + this_device, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR + ); +} +#endif /* !defined(DISABLE_ATAPI) */ + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { + .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { + .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, + }, +#if !defined(DISABLE_ATAPI) + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { + .enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter, + }, +#endif + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { + .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, + }, +}; diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c new file mode 100644 index 000000000000..c14f6f10edb1 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -0,0 +1,2004 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "intel_ata.h" +#include "intel_sata.h" +#include "intel_sat.h" +#include "sci_base_state.h" +#include "sci_base_state_machine.h" +#include "scic_io_request.h" +#include "scic_remote_device.h" +#include "scic_sds_controller.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_request.h" +#include "scic_sds_stp_pio_request.h" +#include "scic_sds_stp_request.h" +#include "scic_sds_unsolicited_frame_control.h" +#include "scic_user_callback.h" +#include "sci_environment.h" +#include "sci_types.h" +#include "sci_util.h" +#include "scu_completion_codes.h" +#include "scu_event_codes.h" +#include "scu_task_context.h" + +/** + * scic_sds_stp_request_get_h2d_reg_buffer() - + * + * This macro returns the address of the stp h2d reg fis buffer in the io + * request memory + */ +#define scic_sds_stp_request_get_h2d_reg_buffer(memory) \ + ((struct sata_fis_reg_h2d *)(\ + ((char *)(memory)) + sizeof(struct scic_sds_stp_request) \ + )) + +/** + * scic_sds_stp_request_get_response_buffer() - + * + * This macro returns the address of the ssp response iu buffer in the io + * request memory + */ +#define scic_sds_stp_request_get_response_buffer(memory) \ + ((struct sata_fis_reg_d2h *)(\ + ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \ + + sizeof(struct sata_fis_reg_h2d) \ + )) + +/** + * scic_sds_stp_request_get_task_context_buffer() - + * + * This macro returns the address of the task context buffer in the io request + * memory + */ +#define scic_sds_stp_request_get_task_context_buffer(memory) \ + ((struct scu_task_context *)(\ + ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \ + + sizeof(struct sci_ssp_response_iu) \ + )) + +/** + * scic_sds_stp_request_get_sgl_element_buffer() - + * + * This macro returns the address of the sgl elment pairs in the io request + * memory buffer + */ +#define scic_sds_stp_request_get_sgl_element_buffer(memory) \ + ((struct scu_sgl_element_pair *)(\ + ((char *)(scic_sds_stp_request_get_task_context_buffer(memory))) \ + + sizeof(struct scu_task_context) \ + )) + +/** + * + * + * This method return the memory space required for STP PIO requests. u32 + */ +u32 scic_sds_stp_request_get_object_size(void) +{ + return sizeof(struct scic_sds_stp_request) + + sizeof(struct sata_fis_reg_h2d) + + sizeof(struct sata_fis_reg_d2h) + + sizeof(struct scu_task_context) + + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; +} + +/** + * + * + * + */ +void scic_sds_stp_request_assign_buffers( + struct scic_sds_request *request) +{ + struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + + this_request->parent.command_buffer = + scic_sds_stp_request_get_h2d_reg_buffer(this_request); + this_request->parent.response_buffer = + scic_sds_stp_request_get_response_buffer(this_request); + this_request->parent.sgl_element_pair_buffer = + scic_sds_stp_request_get_sgl_element_buffer(this_request); + this_request->parent.sgl_element_pair_buffer = + scic_sds_request_align_sgl_element_buffer(this_request->parent.sgl_element_pair_buffer); + + if (this_request->parent.was_tag_assigned_by_user == false) { + this_request->parent.task_context_buffer = + scic_sds_stp_request_get_task_context_buffer(this_request); + this_request->parent.task_context_buffer = + scic_sds_request_align_task_context_buffer(this_request->parent.task_context_buffer); + } +} + +/** + * This method is will fill in the SCU Task Context for any type of SATA + * request. This is called from the various SATA constructors. + * @this_request: The general IO request object which is to be used in + * constructing the SCU task context. + * @task_context: The buffer pointer for the SCU task context which is being + * constructed. + * + * The general io request construction is complete. The buffer assignment for + * the command buffer is complete. none Revisit task context construction to + * determine what is common for SSP/SMP/STP task context structures. + */ +static void scu_sata_reqeust_construct_task_context( + struct scic_sds_request *this_request, + struct scu_task_context *task_context) +{ + dma_addr_t physical_address; + struct scic_sds_controller *owning_controller; + struct scic_sds_remote_device *target_device; + struct scic_sds_port *target_port; + + owning_controller = scic_sds_request_get_controller(this_request); + target_device = scic_sds_request_get_device(this_request); + target_port = scic_sds_request_get_port(this_request); + + /* Fill in the TC with the its required data */ + task_context->abort = 0; + task_context->priority = SCU_TASK_PRIORITY_NORMAL; + task_context->initiator_request = 1; + task_context->connection_rate = + scic_remote_device_get_connection_rate(target_device); + task_context->protocol_engine_index = + scic_sds_controller_get_protocol_engine_group(owning_controller); + task_context->logical_port_index = + scic_sds_port_get_index(target_port); + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + task_context->remote_node_index = + scic_sds_remote_device_get_index(this_request->target_device); + task_context->command_code = 0; + + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 0; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + task_context->address_modifier = 0; + task_context->task_phase = 0x01; + + task_context->ssp_command_iu_length = + (sizeof(struct sata_fis_reg_h2d) - sizeof(u32)) / sizeof(u32); + + /* Set the first word of the H2D REG FIS */ + task_context->type.words[0] = *(u32 *)this_request->command_buffer; + + if (this_request->was_tag_assigned_by_user) { + /* Build the task context now since we have already read the data */ + this_request->post_context = ( + SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC + | ( + scic_sds_controller_get_protocol_engine_group(owning_controller) + << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT + ) + | ( + scic_sds_port_get_index(target_port) + << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT + ) + | scic_sds_io_tag_get_index(this_request->io_tag) + ); + } else { + /* Build the task context now since we have already read the data */ + this_request->post_context = ( + SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC + | ( + scic_sds_controller_get_protocol_engine_group(owning_controller) + << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT + ) + | ( + scic_sds_port_get_index(target_port) + << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT + ) + /* This is not assigned because we have to wait until we get a TCi */ + ); + } + + /* + * Copy the physical address for the command buffer to the SCU Task Context + * We must offset the command buffer by 4 bytes because the first 4 bytes are + * transfered in the body of the TC */ + scic_cb_io_request_get_physical_address( + scic_sds_request_get_controller(this_request), + this_request, + ((char *)this_request->command_buffer) + sizeof(u32), + &physical_address + ); + + task_context->command_iu_upper = + upper_32_bits(physical_address); + task_context->command_iu_lower = + lower_32_bits(physical_address); + + /* SATA Requests do not have a response buffer */ + task_context->response_iu_upper = 0; + task_context->response_iu_lower = 0; +} + +/** + * + * @this_request: + * + * This method will perform any general sata request construction. What part of + * SATA IO request construction is general? none + */ +void scic_sds_stp_non_ncq_request_construct( + struct scic_sds_request *this_request) +{ + this_request->has_started_substate_machine = true; +} + +/** + * + * @this_request: This parameter specifies the request to be constructed as an + * optimized request. + * @optimized_task_type: This parameter specifies whether the request is to be + * an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A + * value of 1 indicates NCQ. + * + * This method will perform request construction common to all types of STP + * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method + * returns an indication as to whether the construction was successful. + */ +static void scic_sds_stp_optimized_request_construct( + struct scic_sds_request *this_request, + u8 optimized_task_type, + u32 transfer_length, + SCI_IO_REQUEST_DATA_DIRECTION data_direction) +{ + struct scu_task_context *task_context = this_request->task_context_buffer; + + /* Build the STP task context structure */ + scu_sata_reqeust_construct_task_context(this_request, task_context); + + /* Copy over the SGL elements */ + scic_sds_request_build_sgl(this_request); + + /* Copy over the number of bytes to be transfered */ + task_context->transfer_length_bytes = transfer_length; + + if (data_direction == SCI_IO_REQUEST_DATA_OUT) { + /* + * The difference between the DMA IN and DMA OUT request task type + * values are consistent with the difference between FPDMA READ + * and FPDMA WRITE values. Add the supplied task type parameter + * to this difference to set the task type properly for this + * DATA OUT (WRITE) case. */ + task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT + - SCU_TASK_TYPE_DMA_IN); + } else { + /* + * For the DATA IN (READ) case, simply save the supplied + * optimized task type. */ + task_context->task_type = optimized_task_type; + } +} + +/** + * + * @this_request: This parameter specifies the request to be constructed. + * + * This method will construct the STP UDMA request and its associated TC data. + * This method returns an indication as to whether the construction was + * successful. SCI_SUCCESS Currently this method always returns this value. + */ +enum sci_status scic_sds_stp_udma_request_construct( + struct scic_sds_request *this_request, + u32 transfer_length, + SCI_IO_REQUEST_DATA_DIRECTION data_direction) +{ + scic_sds_stp_non_ncq_request_construct(this_request); + + scic_sds_stp_optimized_request_construct( + this_request, + SCU_TASK_TYPE_DMA_IN, + transfer_length, + data_direction + ); + + sci_base_state_machine_construct( + &this_request->started_substate_machine, + &this_request->parent.parent, + scic_sds_stp_request_started_udma_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE + ); + + return SCI_SUCCESS; +} + +/** + * + * @this_request: This parameter specifies the request to be constructed. + * + * This method will construct the STP UDMA request and its associated TC data. + * This method returns an indication as to whether the construction was + * successful. SCI_SUCCESS Currently this method always returns this value. + */ +enum sci_status scic_sds_stp_ncq_request_construct( + struct scic_sds_request *this_request, + u32 transfer_length, + SCI_IO_REQUEST_DATA_DIRECTION data_direction) +{ + scic_sds_stp_optimized_request_construct( + this_request, + SCU_TASK_TYPE_FPDMAQ_READ, + transfer_length, + data_direction + ); + return SCI_SUCCESS; +} + +/** + * + * @this_request: This parameter specifies the STP request object for which to + * construct a RAW command frame task context. + * @task_context: This parameter specifies the SCU specific task context buffer + * to construct. + * + * This method performs the operations common to all SATA/STP requests + * utilizing the raw frame method. none + */ +void scu_stp_raw_request_construct_task_context( + struct scic_sds_stp_request *this_request, + struct scu_task_context *task_context) +{ + scu_sata_reqeust_construct_task_context(&this_request->parent, task_context); + + task_context->control_frame = 0; + task_context->priority = SCU_TASK_PRIORITY_NORMAL; + task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; + task_context->type.stp.fis_type = SATA_FIS_TYPE_REGH2D; + task_context->transfer_length_bytes = sizeof(struct sata_fis_reg_h2d) - sizeof(u32); +} + +/** + * + * @this_request: This parameter specifies the core request object to + * construction into an STP/SATA non-data request. + * + * This method will construct the STP Non-data request and its associated TC + * data. A non-data request essentially behaves like a 0 length read request + * in the SCU. This method currently always returns SCI_SUCCESS + */ +enum sci_status scic_sds_stp_non_data_request_construct( + struct scic_sds_request *this_request) +{ + scic_sds_stp_non_ncq_request_construct(this_request); + + /* Build the STP task context structure */ + scu_stp_raw_request_construct_task_context( + (struct scic_sds_stp_request *)this_request, + this_request->task_context_buffer + ); + + sci_base_state_machine_construct( + &this_request->started_substate_machine, + &this_request->parent.parent, + scic_sds_stp_request_started_non_data_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE + ); + + return SCI_SUCCESS; +} + + +enum sci_status scic_sds_stp_soft_reset_request_construct( + struct scic_sds_request *this_request) +{ + scic_sds_stp_non_ncq_request_construct(this_request); + + /* Build the STP task context structure */ + scu_stp_raw_request_construct_task_context( + (struct scic_sds_stp_request *)this_request, + this_request->task_context_buffer + ); + + sci_base_state_machine_construct( + &this_request->started_substate_machine, + &this_request->parent.parent, + scic_sds_stp_request_started_soft_reset_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE + ); + + return SCI_SUCCESS; +} + + +void scic_stp_io_request_set_ncq_tag( + struct scic_sds_request *req, + u16 ncq_tag) +{ + /** + * @note This could be made to return an error to the user if the user + * attempts to set the NCQ tag in the wrong state. + */ + req->task_context_buffer->type.stp.ncq_tag = ncq_tag; +} + + +void *scic_stp_io_request_get_h2d_reg_address( + struct scic_sds_request *req) +{ + return req->command_buffer; +} + + +void *scic_stp_io_request_get_d2h_reg_address( + struct scic_sds_request *req) +{ + return &((struct scic_sds_stp_request *)req)->d2h_reg_fis; +} + +/** + * + * @this_request: + * + * Get the next SGL element from the request. - Check on which SGL element pair + * we are working - if working on SLG pair element A - advance to element B - + * else - check to see if there are more SGL element pairs for this IO request + * - if there are more SGL element pairs - advance to the next pair and return + * element A struct scu_sgl_element* + */ +struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl( + struct scic_sds_stp_request *this_request + ) { + struct scu_sgl_element *current_sgl; + + if (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + if ( + (this_request->type.pio.request_current.sgl_pair->B.address_lower == 0) + && (this_request->type.pio.request_current.sgl_pair->B.address_upper == 0) + ) { + current_sgl = NULL; + } else { + this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_B; + current_sgl = &(this_request->type.pio.request_current.sgl_pair->B); + } + } else { + if ( + (this_request->type.pio.request_current.sgl_pair->next_pair_lower == 0) + && (this_request->type.pio.request_current.sgl_pair->next_pair_upper == 0) + ) { + current_sgl = NULL; + } else { + dma_addr_t physical_address; + + sci_cb_make_physical_address( + physical_address, + this_request->type.pio.request_current.sgl_pair->next_pair_upper, + this_request->type.pio.request_current.sgl_pair->next_pair_lower + ); + + this_request->type.pio.request_current.sgl_pair = + (struct scu_sgl_element_pair *)scic_cb_get_virtual_address( + this_request->parent.owning_controller, + physical_address + ); + + this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; + + current_sgl = &(this_request->type.pio.request_current.sgl_pair->A); + } + } + + return current_sgl; +} + +/** + * + * @scic_io_request: The core request object which is cast to a SATA PIO + * request object. + * + * This method will construct the SATA PIO request. This method returns an + * indication as to whether the construction was successful. SCI_SUCCESS + * Currently this method always returns this value. + */ +enum sci_status scic_sds_stp_pio_request_construct( + struct scic_sds_request *scic_io_request, + u8 sat_protocol, + bool copy_rx_frame) +{ + struct scic_sds_stp_request *this_request; + + this_request = (struct scic_sds_stp_request *)scic_io_request; + + scic_sds_stp_non_ncq_request_construct(&this_request->parent); + + scu_stp_raw_request_construct_task_context( + this_request, this_request->parent.task_context_buffer + ); + + this_request->type.pio.current_transfer_bytes = 0; + this_request->type.pio.ending_error = 0; + this_request->type.pio.ending_status = 0; + + this_request->type.pio.request_current.sgl_offset = 0; + this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; + this_request->type.pio.sat_protocol = sat_protocol; + + if (copy_rx_frame) { + scic_sds_request_build_sgl(&this_request->parent); + /* + * Since the IO request copy of the TC contains the same data as + * the actual TC this pointer is vaild for either. */ + this_request->type.pio.request_current.sgl_pair = + &this_request->parent.task_context_buffer->sgl_pair_ab; + } else { + /* The user does not want the data copied to the SGL buffer location */ + this_request->type.pio.request_current.sgl_pair = NULL; + } + + sci_base_state_machine_construct( + &this_request->parent.started_substate_machine, + &this_request->parent.parent.parent, + scic_sds_stp_request_started_pio_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE + ); + + return SCI_SUCCESS; +} + +/** + * + * @this_request: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. + */ +static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return SCI_SUCCESS; +} + +/** + * + * @request: This parameter specifies the request for which a frame has been + * received. + * @frame_index: This parameter specifies the index of the frame that has been + * received. + * + * This method processes frames received from the target while waiting for a + * device to host register FIS. If a non-register FIS is received during this + * time, it is treated as a protocol violation from an IO perspective. Indicate + * if the received frame was processed successfully. + */ +static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + + status = scic_sds_unsolicited_frame_control_get_header( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_header + ); + + if (status == SCI_SUCCESS) { + switch (frame_header->fis_type) { + case SATA_FIS_TYPE_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_buffer + ); + + scic_sds_controller_copy_sata_response( + &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer + ); + + /* The command has completed with error */ + scic_sds_request_set_status( + &this_request->parent, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + break; + + default: + dev_warn(scic_to_dev(request->owning_controller), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", + __func__, this_request, frame_index); + + scic_sds_request_set_status( + &this_request->parent, + SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION + ); + break; + } + + sci_base_state_machine_change_state( + &this_request->parent.parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame( + this_request->parent.owning_controller, frame_index + ); + } else + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, this_request, frame_index, status); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, + } +}; + +static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_non_data_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + this_request->target_device, this_request + ); +} + +static void scic_sds_stp_request_started_non_data_await_d2h_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_non_data_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter, + }, +}; + +#define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ + +/** + * + * @this_request: + * @length: + * + * This function will transmit DATA_FIS from (current sgl + offset) for input + * parameter length. current sgl and offset is alreay stored in the IO request + * enum sci_status + */ + +static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( + struct scic_sds_request *this_request, + u32 length) +{ + struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_request; + sci_base_controller_request_handler_t continue_io; + struct scu_sgl_element *current_sgl; + struct scic_sds_controller *scic; + u32 state; + + /* + * Recycle the TC and reconstruct it for sending out DATA FIS containing + * for the data from current_sgl+offset for the input length */ + struct scu_task_context *task_context = scic_sds_controller_get_task_context_buffer( + this_request->owning_controller, + this_request->io_tag + ); + + if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) + current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A); + else + current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B); + + /* update the TC */ + task_context->command_iu_upper = current_sgl->address_upper; + task_context->command_iu_lower = current_sgl->address_lower; + task_context->transfer_length_bytes = length; + task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; + + /* send the new TC out. */ + scic = this_request->owning_controller; + state = scic->parent.state_machine.current_state_id; + continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; + return continue_io(&scic->parent, &this_request->target_device->parent, + &this_request->parent); +} + +/** + * + * @this_request: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data( + struct scic_sds_request *this_sds_request) +{ + + struct scu_sgl_element *current_sgl; + u32 sgl_offset; + u32 remaining_bytes_in_current_sgl = 0; + enum sci_status status = SCI_SUCCESS; + + struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_sds_request; + + sgl_offset = this_sds_stp_request->type.pio.request_current.sgl_offset; + + if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A); + remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->A.length - sgl_offset; + } else { + current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B); + remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->B.length - sgl_offset; + } + + + if (this_sds_stp_request->type.pio.pio_transfer_bytes > 0) { + if (this_sds_stp_request->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { + /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ + status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(this_sds_request, remaining_bytes_in_current_sgl); + if (status == SCI_SUCCESS) { + this_sds_stp_request->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; + + /* update the current sgl, sgl_offset and save for future */ + current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_sds_stp_request); + sgl_offset = 0; + } + } else if (this_sds_stp_request->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { + /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */ + scic_sds_stp_request_pio_data_out_trasmit_data_frame(this_sds_request, this_sds_stp_request->type.pio.pio_transfer_bytes); + + if (status == SCI_SUCCESS) { + /* Sgl offset will be adjusted and saved for future */ + sgl_offset += this_sds_stp_request->type.pio.pio_transfer_bytes; + current_sgl->address_lower += this_sds_stp_request->type.pio.pio_transfer_bytes; + this_sds_stp_request->type.pio.pio_transfer_bytes = 0; + } + } + } + + if (status == SCI_SUCCESS) { + this_sds_stp_request->type.pio.request_current.sgl_offset = sgl_offset; + } + + return status; +} + +/** + * + * @this_request: The request that is used for the SGL processing. + * @data_buffer: The buffer of data to be copied. + * @length: The length of the data transfer. + * + * Copy the data from the buffer for the length specified to the IO reqeust SGL + * specified data region. enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_in_copy_data_buffer( + struct scic_sds_stp_request *this_request, + u8 *data_buffer, + u32 length) +{ + enum sci_status status; + struct scu_sgl_element *current_sgl; + u32 sgl_offset; + u32 data_offset; + u8 *source_address; + u8 *destination_address; + u32 copy_length; + + /* Initial setup to get the current working SGL and the offset within the buffer */ + current_sgl = + (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ? + &(this_request->type.pio.request_current.sgl_pair->A) : + &(this_request->type.pio.request_current.sgl_pair->B); + + sgl_offset = this_request->type.pio.request_current.sgl_offset; + + source_address = data_buffer; + data_offset = 0; + + status = SCI_SUCCESS; + + /* While we are still doing Ok and there is more data to transfer */ + while ( + (length > 0) + && (status == SCI_SUCCESS) + ) { + if (current_sgl->length == sgl_offset) { + /* This SGL has been exauhasted so we need to get the next SGL */ + current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request); + + if (current_sgl == NULL) + status = SCI_FAILURE; + else + sgl_offset = 0; + } else { + dma_addr_t physical_address; + + sci_cb_make_physical_address( + physical_address, + current_sgl->address_upper, + current_sgl->address_lower + ); + + destination_address = (u8 *)scic_cb_get_virtual_address( + this_request->parent.owning_controller, + physical_address + ); + + source_address += data_offset; + destination_address += sgl_offset; + + copy_length = min(length, current_sgl->length - sgl_offset); + + memcpy(destination_address, source_address, copy_length); + + length -= copy_length; + sgl_offset += copy_length; + data_offset += copy_length; + } + } + + this_request->type.pio.request_current.sgl_offset = sgl_offset; + + return status; +} + +/** + * + * @this_request: The PIO DATA IN request that is to receive the data. + * @data_buffer: The buffer to copy from. + * + * Copy the data buffer to the io request data region. enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( + struct scic_sds_stp_request *this_request, + u8 *data_buffer) +{ + enum sci_status status; + + /* + * If there is less than 1K remaining in the transfer request + * copy just the data for the transfer */ + if (this_request->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { + status = scic_sds_stp_request_pio_data_in_copy_data_buffer( + this_request, data_buffer, this_request->type.pio.pio_transfer_bytes); + + if (status == SCI_SUCCESS) + this_request->type.pio.pio_transfer_bytes = 0; + } else { + /* We are transfering the whole frame so copy */ + status = scic_sds_stp_request_pio_data_in_copy_data_buffer( + this_request, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); + + if (status == SCI_SUCCESS) + this_request->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; + } + + return status; +} + +/** + * + * @this_request: + * @completion_code: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return status; +} + +/** + * + * @this_request: + * @frame_index: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *this_request; + + this_request = (struct scic_sds_stp_request *)request; + + status = scic_sds_unsolicited_frame_control_get_header( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_header + ); + + if (status == SCI_SUCCESS) { + switch (frame_header->fis_type) { + case SATA_FIS_TYPE_PIO_SETUP: + /* Get from the frame buffer the PIO Setup Data */ + scic_sds_unsolicited_frame_control_get_buffer( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_buffer + ); + + /* + * Get the data from the PIO Setup + * The SCU Hardware returns first word in the frame_header and the rest + * of the data is in the frame buffer so we need to back up one dword */ + this_request->type.pio.pio_transfer_bytes = + (u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count; + this_request->type.pio.ending_status = + (u8)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->ending_status; + + scic_sds_controller_copy_sata_response( + &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer + ); + + this_request->d2h_reg_fis.status = + this_request->type.pio.ending_status; + + /* The next state is dependent on whether the request was PIO Data-in or Data out */ + if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN) { + sci_base_state_machine_change_state( + &this_request->parent.started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE + ); + } else if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT) { + /* Transmit data */ + status = scic_sds_stp_request_pio_data_out_transmit_data(request); + if (status == SCI_SUCCESS) { + sci_base_state_machine_change_state( + &this_request->parent.started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE + ); + } + } + break; + + case SATA_FIS_TYPE_SETDEVBITS: + sci_base_state_machine_change_state( + &this_request->parent.started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + break; + + case SATA_FIS_TYPE_REGD2H: + if ((frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0) { + scic_sds_unsolicited_frame_control_get_buffer( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_buffer + ); + + scic_sds_controller_copy_sata_response( + &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer); + + scic_sds_request_set_status( + &this_request->parent, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + + sci_base_state_machine_change_state( + &this_request->parent.parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + } else { + /* + * Now why is the drive sending a D2H Register FIS when it is still busy? + * Do nothing since we are still in the right state. */ + dev_dbg(scic_to_dev(request->owning_controller), + "%s: SCIC PIO Request 0x%p received " + "D2H Register FIS with BSY status " + "0x%x\n", + __func__, + this_request, + frame_header->status); + } + break; + + default: + break; + } + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame( + this_request->parent.owning_controller, + frame_index + ); + } else + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, this_request, frame_index, status); + + return status; +} + +/** + * + * @this_request: + * @frame_index: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + struct sata_fis_data *frame_buffer; + struct scic_sds_stp_request *this_request; + + this_request = (struct scic_sds_stp_request *)request; + + status = scic_sds_unsolicited_frame_control_get_header( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_header + ); + + if (status == SCI_SUCCESS) { + if (frame_header->fis_type == SATA_FIS_TYPE_DATA) { + if (this_request->type.pio.request_current.sgl_pair == NULL) { + this_request->parent.saved_rx_frame_index = frame_index; + this_request->type.pio.pio_transfer_bytes = 0; + } else { + status = scic_sds_unsolicited_frame_control_get_buffer( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_buffer + ); + + status = scic_sds_stp_request_pio_data_in_copy_data(this_request, (u8 *)frame_buffer); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame( + this_request->parent.owning_controller, + frame_index + ); + } + + /* + * Check for the end of the transfer, are there more bytes remaining + * for this data transfer */ + if ( + (status == SCI_SUCCESS) + && (this_request->type.pio.pio_transfer_bytes == 0) + ) { + if ((this_request->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0) { + scic_sds_request_set_status( + &this_request->parent, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + + sci_base_state_machine_change_state( + &this_request->parent.parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + } else { + sci_base_state_machine_change_state( + &this_request->parent.started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + } + } + } else { + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC PIO Request 0x%p received frame %d " + "with fis type 0x%02x when expecting a data " + "fis.\n", + __func__, + this_request, + frame_index, + frame_header->fis_type); + + scic_sds_request_set_status( + &this_request->parent, + SCU_TASK_DONE_GOOD, + SCI_FAILURE_IO_REQUIRES_SCSI_ABORT + ); + + sci_base_state_machine_change_state( + &this_request->parent.parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame( + this_request->parent.owning_controller, + frame_index + ); + } + } else + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, this_request, frame_index, status); + + return status; +} + + +/** + * + * @this_request: + * @completion_code: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( + + struct scic_sds_request *this_request, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + bool all_frames_transferred = false; + + struct scic_sds_stp_request *this_scic_sds_stp_request = (struct scic_sds_stp_request *)this_request; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + /* Transmit data */ + if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes != 0) { + status = scic_sds_stp_request_pio_data_out_transmit_data(this_request); + if (status == SCI_SUCCESS) { + if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) + all_frames_transferred = true; + } + } else if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) { + /* + * this will happen if the all data is written at the + * first time after the pio setup fis is received + */ + all_frames_transferred = true; + } + + /* all data transferred. */ + if (all_frames_transferred) { + /* + * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE + * and wait for PIO_SETUP fis / or D2H REg fis. */ + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + } + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return status; +} + +/** + * + * @request: This is the request which is receiving the event. + * @event_code: This is the event code that the request on which the request is + * expected to take action. + * + * This method will handle any link layer events while waiting for the data + * frame. enum sci_status SCI_SUCCESS SCI_FAILURE + */ +static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler( + struct scic_sds_request *request, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_specifier(event_code)) { + case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: + /* + * We are waiting for data and the SCU has R_ERR the data frame. + * Go back to waiting for the D2H Register FIS */ + sci_base_state_machine_change_state( + &request->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + + status = SCI_SUCCESS; + break; + + default: + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC PIO Request 0x%p received unexpected " + "event 0x%08x\n", + __func__, request, event_code); + + /* / @todo Should we fail the PIO request when we get an unexpected event? */ + status = SCI_FAILURE; + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, + .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + } +}; + +static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_pio_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + this_request->target_device, this_request); +} + +static void scic_sds_stp_request_started_pio_await_frame_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_pio_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); +} + +static void scic_sds_stp_request_started_pio_data_in_await_data_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_pio_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE + ); +} + +static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_pio_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_await_frame_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter, + } +}; + +static void scic_sds_stp_request_udma_complete_request( + struct scic_sds_request *this_request, + u32 scu_status, + enum sci_status sci_status) +{ + scic_sds_request_set_status( + this_request, scu_status, sci_status + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); +} + +/** + * + * @this_request: + * @frame_index: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_udma_general_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + u32 *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header( + &this_request->owning_controller->uf_control, + frame_index, + (void **)&frame_header + ); + + if ( + (status == SCI_SUCCESS) + && (frame_header->fis_type == SATA_FIS_TYPE_REGD2H) + ) { + scic_sds_unsolicited_frame_control_get_buffer( + &this_request->owning_controller->uf_control, + frame_index, + (void **)&frame_buffer + ); + + scic_sds_controller_copy_sata_response( + &((struct scic_sds_stp_request *)this_request)->d2h_reg_fis, + (u32 *)frame_header, + frame_buffer + ); + } + + scic_sds_controller_release_frame( + this_request->owning_controller, frame_index); + + return status; +} + +/** + * This method process TC completions while in the state where we are waiting + * for TC completions. + * @this_request: + * @completion_code: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( + struct scic_sds_request *request, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_stp_request_udma_complete_request( + &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): + /* + * We must check ther response buffer to see if the D2H Register FIS was + * received before we got the TC completion. */ + if (this_request->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H) { + scic_sds_remote_device_suspend( + this_request->parent.target_device, + SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) + ); + + scic_sds_stp_request_udma_complete_request( + &this_request->parent, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + } else { + /* + * If we have an error completion status for the TC then we can expect a + * D2H register FIS from the device so we must change state to wait for it */ + sci_base_state_machine_change_state( + &this_request->parent.started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE + ); + } + break; + + /* + * / @todo Check to see if any of these completion status need to wait for + * / the device to host register fis. */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): + scic_sds_remote_device_suspend( + this_request->parent.target_device, + SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) + ); + /* Fall through to the default case */ + default: + /* All other completion status cause the IO to be complete. */ + scic_sds_stp_request_udma_complete_request( + &this_request->parent, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + break; + } + + return status; +} + +static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( + struct scic_sds_request *this_request, + u32 frame_index) +{ + enum sci_status status; + + /* Use the general frame handler to copy the resposne data */ + status = scic_sds_stp_request_udma_general_frame_handler(this_request, frame_index); + + if (status == SCI_SUCCESS) { + scic_sds_stp_request_udma_complete_request( + this_request, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_udma_general_frame_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, + }, +}; + +static void scic_sds_stp_request_started_udma_await_tc_completion_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_udma_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE + ); +} + +/** + * + * + * This state is entered when there is an TC completion failure. The hardware + * received an unexpected condition while processing the IO request and now + * will UF the D2H register FIS to complete the IO. + */ +static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_udma_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter, + }, +}; + +/** + * + * @this_request: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. + */ +static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return SCI_SUCCESS; +} + +/** + * + * @this_request: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. + */ +static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( + struct scic_sds_request *this_request, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &this_request->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + this_request, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return SCI_SUCCESS; +} + +/** + * + * @request: This parameter specifies the request for which a frame has been + * received. + * @frame_index: This parameter specifies the index of the frame that has been + * received. + * + * This method processes frames received from the target while waiting for a + * device to host register FIS. If a non-register FIS is received during this + * time, it is treated as a protocol violation from an IO perspective. Indicate + * if the received frame was processed successfully. + */ +static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + + status = scic_sds_unsolicited_frame_control_get_header( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_header + ); + + if (status == SCI_SUCCESS) { + switch (frame_header->fis_type) { + case SATA_FIS_TYPE_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer( + &(this_request->parent.owning_controller->uf_control), + frame_index, + (void **)&frame_buffer + ); + + scic_sds_controller_copy_sata_response( + &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer + ); + + /* The command has completed with error */ + scic_sds_request_set_status( + &this_request->parent, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID + ); + break; + + default: + dev_warn(scic_to_dev(request->owning_controller), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", + __func__, + this_request, + frame_index); + + scic_sds_request_set_status( + &this_request->parent, + SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION + ); + break; + } + + sci_base_state_machine_change_state( + &this_request->parent.parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame( + this_request->parent.owning_controller, frame_index + ); + } else + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, this_request, frame_index, status); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { + .parent.start_handler = scic_sds_request_default_start_handler, + .parent.abort_handler = scic_sds_request_started_state_abort_handler, + .parent.complete_handler = scic_sds_request_default_complete_handler, + .parent.destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, + }, +}; + +static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_soft_reset_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + this_request->target_device, this_request + ); +} + +static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + sci_base_controller_request_handler_t continue_io; + struct scu_task_context *task_context; + struct sata_fis_reg_h2d *h2d_fis; + struct scic_sds_controller *scic; + enum sci_status status; + u32 state; + + /* Clear the SRST bit */ + h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request); + h2d_fis->control = 0; + + /* Clear the TC control bit */ + task_context = scic_sds_controller_get_task_context_buffer( + this_request->owning_controller, this_request->io_tag); + task_context->control_frame = 0; + + scic = this_request->owning_controller; + state = scic->parent.state_machine.current_state_id; + continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; + + status = continue_io(&scic->parent, &this_request->target_device->parent, + &this_request->parent); + + if (status == SCI_SUCCESS) { + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_soft_reset_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE + ); + } +} + +static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( + struct sci_base_object *object) +{ + struct scic_sds_request *this_request = (struct scic_sds_request *)object; + + SET_STATE_HANDLER( + this_request, + scic_sds_stp_request_started_soft_reset_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE + ); +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter, + }, +}; + diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h new file mode 100644 index 000000000000..5578d2baf7ca --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -0,0 +1,221 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_STP_REQUEST_T_ +#define _SCIC_SDS_STP_REQUEST_T_ + +#include "intel_sata.h" +#include "sci_types.h" +#include "scic_sds_request.h" + +/** + * This structure represents the additional information that is required to + * handle SATA PIO requests. + * + * + */ +struct scic_sds_stp_request { + struct scic_sds_request parent; + + struct sata_fis_reg_d2h d2h_reg_fis; + + union { + u32 ncq; + + u32 udma; + + struct { + /** + * Total transfer for the entire PIO request recorded at request constuction + * time. + * + * @todo Should we just decrement this value for each byte of data transitted + * or received to elemenate the current_transfer_bytes field? + */ + u32 total_transfer_bytes; + + /** + * Total number of bytes received/transmitted in data frames since the start + * of the IO request. At the end of the IO request this should equal the + * total_transfer_bytes. + */ + u32 current_transfer_bytes; + + /** + * The number of bytes requested in the in the PIO setup. + */ + u32 pio_transfer_bytes; + + /** + * PIO Setup ending status value to tell us if we need to wait for another FIS + * or if the transfer is complete. On the receipt of a D2H FIS this will be + * the status field of that FIS. + */ + u8 ending_status; + + /** + * On receipt of a D2H FIS this will be the ending error field if the + * ending_status has the SATA_STATUS_ERR bit set. + */ + u8 ending_error; + + /** + * Protocol Type. This is filled in by core during IO Request construction type. + */ + u8 sat_protocol; + + struct { + struct scu_sgl_element_pair *sgl_pair; + u8 sgl_set; + u32 sgl_offset; + } request_current; + } pio; + + struct { + /** + * The number of bytes requested in the PIO setup before CDB data frame. + */ + u32 device_preferred_cdb_length; + } packet; + } type; + +}; + +/** + * enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES - This enumeration depicts + * the various sub-states associated with a SATA/STP UDMA protocol operation. + * + * + */ +enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES { + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, +}; + +/** + * enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES - This enumeration + * depicts the various sub-states associated with a SATA/STP non-data + * protocol operation. + * + * + */ +enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES { + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, +}; + +/** + * enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES - THis enumeration + * depicts the various sub-states associated with a SATA/STP soft reset + * operation. + * + * + */ +enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES { + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, +}; + +extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[]; + +extern const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[]; + +extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[]; + +extern const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[]; + +extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[]; + +extern const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[]; + +/* --------------------------------------------------------------------------- */ + +u32 scic_sds_stp_request_get_object_size(void); + + +void scic_sds_stp_non_ncq_request_construct( + struct scic_sds_request *this_request); + +enum sci_status scic_sds_stp_pio_request_construct( + struct scic_sds_request *scic_io_request, + u8 sat_protocol, + bool copy_rx_frame); + +enum sci_status scic_sds_stp_pio_request_construct_pass_through( + struct scic_sds_request *scic_io_request, + struct scic_stp_passthru_request_callbacks *passthru_cb); + +enum sci_status scic_sds_stp_udma_request_construct( + struct scic_sds_request *this_request, + u32 transfer_length, + SCI_IO_REQUEST_DATA_DIRECTION data_direction); + +enum sci_status scic_sds_stp_non_data_request_construct( + struct scic_sds_request *this_request); + +enum sci_status scic_sds_stp_soft_reset_request_construct( + struct scic_sds_request *this_request); + +enum sci_status scic_sds_stp_ncq_request_construct( + struct scic_sds_request *this_request, + u32 transfer_length, + SCI_IO_REQUEST_DATA_DIRECTION data_direction); + +void scu_stp_raw_request_construct_task_context( + struct scic_sds_stp_request *this_request, + struct scu_task_context *task_context); + +#endif /* _SCIC_SDS_STP_REQUEST_T_ */ diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c new file mode 100644 index 000000000000..7ca2f1709f6d --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c @@ -0,0 +1,379 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the implementation of the + * struct scic_sds_unsolicited_frame_control object and it's public, protected, and + * private methods. + * + * + */ + +#include "scic_sds_unsolicited_frame_control.h" +#include "scu_registers.h" +#include "scic_sds_controller.h" +#include "scic_user_callback.h" +#include "sci_util.h" +#include "sci_environment.h" + +/** + * The UF buffer address table size must be programmed to a power of 2. Find + * the first power of 2 that is equal to or greater then the number of + * unsolicited frame buffers to be utilized. + * @uf_control: This parameter specifies the UF control object for which to + * update the address table count. + * + */ +void scic_sds_unsolicited_frame_control_set_address_table_count( + struct scic_sds_unsolicited_frame_control *uf_control) +{ + uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES; + while ( + (uf_control->address_table.count < uf_control->buffers.count) + && (uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES) + ) { + uf_control->address_table.count <<= 1; + } +} + +/** + * This method will program the unsolicited frames (UFs) into the UF address + * table and construct the UF frame structure being modeled in the core. It + * will handle the case where some of the UFs are not being used and thus + * should have entries programmed to zero in the address table. + * @uf_control: This parameter specifies the unsolicted frame control object + * for which to construct the unsolicited frames objects. + * @uf_buffer_phys_address: This parameter specifies the physical address for + * the first unsolicited frame buffer. + * @uf_buffer_virt_address: This parameter specifies the virtual address for + * the first unsolicited frame buffer. + * @unused_uf_header_entries: This parameter specifies the number of unused UF + * headers. This value can be non-zero when there are a non-power of 2 + * number of unsolicited frames being supported. + * @used_uf_header_entries: This parameter specifies the number of actually + * utilized UF headers. + * + */ +static void scic_sds_unsolicited_frame_control_construct_frames( + struct scic_sds_unsolicited_frame_control *uf_control, + dma_addr_t uf_buffer_phys_address, + unsigned long uf_buffer_virt_address, + u32 unused_uf_header_entries, + u32 used_uf_header_entries) +{ + u32 index; + struct scic_sds_unsolicited_frame *uf; + + /* + * Program the unused buffers into the UF address table and the + * controller's array of UFs. */ + for (index = 0; index < unused_uf_header_entries; index++) { + uf = &uf_control->buffers.array[index]; + + sci_cb_make_physical_address( + uf_control->address_table.array[index], 0, 0 + ); + uf->buffer = NULL; + uf->header = &uf_control->headers.array[index]; + uf->state = UNSOLICITED_FRAME_EMPTY; + } + + /* + * Program the actual used UF buffers into the UF address table and + * the controller's array of UFs. */ + for (index = unused_uf_header_entries; + index < unused_uf_header_entries + used_uf_header_entries; + index++) { + uf = &uf_control->buffers.array[index]; + + uf_control->address_table.array[index] = uf_buffer_phys_address; + + uf->buffer = (void *)uf_buffer_virt_address; + uf->header = &uf_control->headers.array[index]; + uf->state = UNSOLICITED_FRAME_EMPTY; + + /* + * Increment the address of the physical and virtual memory pointers + * Everything is aligned on 1k boundary with an increment of 1k */ + uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; + sci_physical_address_add( + uf_buffer_phys_address, SCU_UNSOLICITED_FRAME_BUFFER_SIZE + ); + } +} + +/** + * This method constructs the various members of the unsolicted frame control + * object (buffers, headers, address, table, etc). + * @uf_control: This parameter specifies the unsolicited frame control object + * to construct. + * @mde: This parameter specifies the memory descriptor from which to derive + * all of the address information needed to get the unsolicited frame + * functionality working. + * @controller: This parameter specifies the controller object associated with + * the uf_control being constructed. + * + */ +void scic_sds_unsolicited_frame_control_construct( + struct scic_sds_unsolicited_frame_control *uf_control, + struct sci_physical_memory_descriptor *mde, + struct scic_sds_controller *controller) +{ + u32 unused_uf_header_entries; + u32 used_uf_header_entries; + u32 used_uf_buffer_bytes; + u32 unused_uf_header_bytes; + u32 used_uf_header_bytes; + dma_addr_t uf_buffer_phys_address; + + /* + * Prepare all of the memory sizes for the UF headers, UF address + * table, and UF buffers themselves. */ + used_uf_buffer_bytes = uf_control->buffers.count + * SCU_UNSOLICITED_FRAME_BUFFER_SIZE; + unused_uf_header_entries = uf_control->address_table.count + - uf_control->buffers.count; + used_uf_header_entries = uf_control->buffers.count; + unused_uf_header_bytes = unused_uf_header_entries + * sizeof(struct scu_unsolicited_frame_header); + used_uf_header_bytes = used_uf_header_entries + * sizeof(struct scu_unsolicited_frame_header); + + /* + * The Unsolicited Frame buffers are set at the start of the UF + * memory descriptor entry. The headers and address table will be + * placed after the buffers. */ + uf_buffer_phys_address = mde->physical_address; + + /* + * Program the location of the UF header table into the SCU. + * Notes: + * - The address must align on a 64-byte boundary. Guaranteed to be + * on 64-byte boundary already 1KB boundary for unsolicited frames. + * - Program unused header entries to overlap with the last + * unsolicited frame. The silicon will never DMA to these unused + * headers, since we program the UF address table pointers to + * NULL. */ + uf_control->headers.physical_address = uf_buffer_phys_address; + sci_physical_address_add( + uf_control->headers.physical_address, used_uf_buffer_bytes); + sci_physical_address_subtract( + uf_control->headers.physical_address, unused_uf_header_bytes); + uf_control->headers.array + = (struct scu_unsolicited_frame_header *) + scic_cb_get_virtual_address( + controller, uf_control->headers.physical_address + ); + + /* + * Program the location of the UF address table into the SCU. + * Notes: + * - The address must align on a 64-bit boundary. Guaranteed to be on 64 + * byte boundary already due to above programming headers being on a + * 64-bit boundary and headers are on a 64-bytes in size. */ + uf_control->address_table.physical_address = uf_buffer_phys_address; + sci_physical_address_add( + uf_control->address_table.physical_address, used_uf_buffer_bytes); + sci_physical_address_add( + uf_control->address_table.physical_address, used_uf_header_bytes); + uf_control->address_table.array + = (dma_addr_t *) + scic_cb_get_virtual_address( + controller, uf_control->address_table.physical_address + ); + + uf_control->get = 0; + + /* + * UF buffer requirements are: + * - The last entry in the UF queue is not NULL. + * - There is a power of 2 number of entries (NULL or not-NULL) + * programmed into the queue. + * - Aligned on a 1KB boundary. */ + + /* + * If the user provided less then the maximum amount of memory, + * then be sure that we programm the first entries in the UF + * address table to NULL. */ + scic_sds_unsolicited_frame_control_construct_frames( + uf_control, + uf_buffer_phys_address, + (unsigned long)mde->virtual_address, + unused_uf_header_entries, + used_uf_header_entries + ); +} + +/** + * This method returns the frame header for the specified frame index. + * @uf_control: + * @frame_index: + * @frame_header: + * + * enum sci_status + */ +enum sci_status scic_sds_unsolicited_frame_control_get_header( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_header) +{ + if (frame_index < uf_control->address_table.count) { + /* + * Skip the first word in the frame since this is a controll word used + * by the hardware. */ + *frame_header = &uf_control->buffers.array[frame_index].header->data; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_PARAMETER_VALUE; +} + +/** + * This method returns the frame buffer for the specified frame index. + * @uf_control: + * @frame_index: + * @frame_buffer: + * + * enum sci_status + */ +enum sci_status scic_sds_unsolicited_frame_control_get_buffer( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_buffer) +{ + if (frame_index < uf_control->address_table.count) { + *frame_buffer = uf_control->buffers.array[frame_index].buffer; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_PARAMETER_VALUE; +} + +/** + * This method releases the frame once this is done the frame is available for + * re-use by the hardware. The data contained in the frame header and frame + * buffer is no longer valid. + * @uf_control: This parameter specifies the UF control object + * @frame_index: This parameter specifies the frame index to attempt to release. + * + * This method returns an indication to the caller as to whether the + * unsolicited frame get pointer should be updated. true This value indicates + * the unsolicited frame get pointer should be updated (i.e. write + * SCU_UFQGP_WRITE). false This value indicates the get pointer should not be + * updated. + */ +bool scic_sds_unsolicited_frame_control_release_frame( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index) +{ + u32 frame_get; + u32 frame_cycle; + + frame_get = uf_control->get & (uf_control->address_table.count - 1); + frame_cycle = uf_control->get & uf_control->address_table.count; + + /* + * In the event there are NULL entries in the UF table, we need to + * advance the get pointer in order to find out if this frame should + * be released (i.e. update the get pointer). */ + while (((lower_32_bits(uf_control->address_table.array[frame_get]) + == 0) && + (upper_32_bits(uf_control->address_table.array[frame_get]) + == 0)) && + (frame_get < uf_control->address_table.count)) + frame_get++; + + /* + * The table has a NULL entry as it's last element. This is + * illegal. */ + BUG_ON(frame_get >= uf_control->address_table.count); + + if (frame_index < uf_control->address_table.count) { + uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED; + + /* + * The frame index is equal to the current get pointer so we + * can now free up all of the frame entries that */ + if (frame_get == frame_index) { + while ( + uf_control->buffers.array[frame_get].state + == UNSOLICITED_FRAME_RELEASED + ) { + uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY; + + INCREMENT_QUEUE_GET( + frame_get, + frame_cycle, + uf_control->address_table.count - 1, + uf_control->address_table.count + ); + } + + uf_control->get = + (SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get); + + return true; + } else { + /* + * Frames remain in use until we advance the get pointer + * so there is nothing we can do here */ + } + } + + return false; +} + diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h new file mode 100644 index 000000000000..49db83faac37 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h @@ -0,0 +1,286 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains all of the unsolicited frame related management for the + * address table, the headers, and actual payload buffers. + * + * + */ + +#ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ +#define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ + +#include "scu_unsolicited_frame.h" +#include "sci_memory_descriptor_list.h" +#include "scu_constants.h" +#include "sci_status.h" + +/** + * enum UNSOLICITED_FRAME_STATE - + * + * This enumeration represents the current unsolicited frame state. The + * controller object can not updtate the hardware unsolicited frame put pointer + * unless it has already processed the priror unsolicited frames. + */ +enum UNSOLICITED_FRAME_STATE { + /** + * This state is when the frame is empty and not in use. It is + * different from the released state in that the hardware could DMA + * data to this frame buffer. + */ + UNSOLICITED_FRAME_EMPTY, + + /** + * This state is set when the frame buffer is in use by by some + * object in the system. + */ + UNSOLICITED_FRAME_IN_USE, + + /** + * This state is set when the frame is returned to the free pool + * but one or more frames prior to this one are still in use. + * Once all of the frame before this one are freed it will go to + * the empty state. + */ + UNSOLICITED_FRAME_RELEASED, + + UNSOLICITED_FRAME_MAX_STATES +}; + +/** + * struct scic_sds_unsolicited_frame - + * + * This is the unsolicited frame data structure it acts as the container for + * the current frame state, frame header and frame buffer. + */ +struct scic_sds_unsolicited_frame { + /** + * This field contains the current frame state + */ + enum UNSOLICITED_FRAME_STATE state; + + /** + * This field points to the frame header data. + */ + struct scu_unsolicited_frame_header *header; + + /** + * This field points to the frame buffer data. + */ + void *buffer; + +}; + +/** + * struct scic_sds_uf_header_array - + * + * This structure contains all of the unsolicited frame header information. + */ +struct scic_sds_uf_header_array { + /** + * This field is represents a virtual pointer to the start + * address of the UF address table. The table contains + * 64-bit pointers as required by the hardware. + */ + struct scu_unsolicited_frame_header *array; + + /** + * This field specifies the physical address location for the UF + * buffer array. + */ + dma_addr_t physical_address; + +}; + +/* + * Determine the size of the unsolicited frame array including + * unused buffers. */ +#if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES +#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES +#else +#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES +#endif /* SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES */ + +/** + * struct scic_sds_uf_buffer_array - + * + * This structure contains all of the unsolicited frame buffer (actual payload) + * information. + */ +struct scic_sds_uf_buffer_array { + /** + * This field is the minimum number of unsolicited frames supported by the + * hardware and the number of unsolicited frames requested by the software. + */ + u32 count; + + /** + * This field is the SCIC_UNSOLICITED_FRAME data its used to manage + * the data for the unsolicited frame requests. It also represents + * the virtual address location that corresponds to the + * physical_address field. + */ + struct scic_sds_unsolicited_frame array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE]; + + /** + * This field specifies the physical address location for the UF + * buffer array. + */ + dma_addr_t physical_address; + +}; + +/** + * struct scic_sds_uf_address_table_array - + * + * This object maintains all of the unsolicited frame address table specific + * data. The address table is a collection of 64-bit pointers that point to + * 1KB buffers into which the silicon will DMA unsolicited frames. + */ +struct scic_sds_uf_address_table_array { + /** + * This field specifies the actual programmed size of the + * unsolicited frame buffer address table. The size of the table + * can be larger than the actual number of UF buffers, but it must + * be a power of 2 and the last entry in the table is not allowed + * to be NULL. + */ + u32 count; + + /** + * This field represents a virtual pointer that refers to the + * starting address of the UF address table. + * 64-bit pointers are required by the hardware. + */ + dma_addr_t *array; + + /** + * This field specifies the physical address location for the UF + * address table. + */ + dma_addr_t physical_address; + +}; + +/** + * struct scic_sds_unsolicited_frame_control - + * + * This object contains all of the data necessary to handle unsolicited frames. + */ +struct scic_sds_unsolicited_frame_control { + /** + * This field is the software copy of the unsolicited frame queue + * get pointer. The controller object writes this value to the + * hardware to let the hardware put more unsolicited frame entries. + */ + u32 get; + + /** + * This field contains all of the unsolicited frame header + * specific fields. + */ + struct scic_sds_uf_header_array headers; + + /** + * This field contains all of the unsolicited frame buffer + * specific fields. + */ + struct scic_sds_uf_buffer_array buffers; + + /** + * This field contains all of the unsolicited frame address table + * specific fields. + */ + struct scic_sds_uf_address_table_array address_table; + +}; + +void scic_sds_unsolicited_frame_control_set_address_table_count( + struct scic_sds_unsolicited_frame_control *uf_control); + +struct scic_sds_controller; +void scic_sds_unsolicited_frame_control_construct( + struct scic_sds_unsolicited_frame_control *uf_control, + struct sci_physical_memory_descriptor *mde, + struct scic_sds_controller *this_controller); + +enum sci_status scic_sds_unsolicited_frame_control_get_header( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_header); + +enum sci_status scic_sds_unsolicited_frame_control_get_buffer( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_buffer); + +bool scic_sds_unsolicited_frame_control_release_frame( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index); + +/** + * scic_sds_unsolicited_frame_control_get_mde_size() - + * + * This macro simply calculates the size of the memory descriptor entry that + * relates to unsolicited frames and the surrounding silicon memory required to + * utilize it. + */ +#define scic_sds_unsolicited_frame_control_get_mde_size(uf_control) \ + (((uf_control).buffers.count * SCU_UNSOLICITED_FRAME_BUFFER_SIZE) \ + + ((uf_control).address_table.count * sizeof(dma_addr_t)) \ + + ((uf_control).buffers.count * sizeof(struct scu_unsolicited_frame_header))) + +#endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */ diff --git a/drivers/scsi/isci/core/scic_task_request.h b/drivers/scsi/isci/core/scic_task_request.h new file mode 100644 index 000000000000..ef76cb6bdbea --- /dev/null +++ b/drivers/scsi/isci/core/scic_task_request.h @@ -0,0 +1,148 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_TASK_REQUEST_H_ +#define _SCIC_TASK_REQUEST_H_ + +/** + * This file contains the structures and interface methods that can be + * referenced and used by the SCI user for to utilize task management + * requests. + * + * + */ + + +#include "sci_types.h" +#include "sci_status.h" + +struct scic_sds_request; +struct scic_sds_remote_device; +struct scic_sds_controller; + + +/** + * scic_task_request_construct() - This method is called by the SCI user to + * construct all SCI Core task management requests, regardless of protocol. + * Memory initialization and functionality common to all task request types + * is performed in this method. + * @scic_controller: the handle to the core controller object for which to + * build the task managmement request. + * @scic_remote_device: the handle to the core remote device object for which + * to build the task management request. passed, then a copy of the request + * is built internally. The request will be copied into the actual + * controller request memory when the task is allocated internally during + * the scic_controller_start_task() method. + * @io_tag: This parameter specifies the IO tag to be associated with this + * request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the + * request is built internally. The request will be copied into the actual + * controller request memory when the IO tag is allocated internally during + * the scic_controller_start_io() method. + * @user_task_request_object: This parameter specifies the user task request to + * be utilized during construction. This task pointer will become the + * associated object for the core task request object. + * @scic_task_request_memory: This parameter specifies the memory location to + * be utilized when building the core request. + * @new_scic_task_request_handle: This parameter specifies a pointer to the + * handle the core will expect in further interactions with the core task + * request object. + * + * The SCI core implementation will create an association between the user task + * request object and the core task request object. Indicate if the controller + * successfully built the task request. SCI_SUCCESS This value is returned if + * the task request was successfully built. + */ +enum sci_status scic_task_request_construct( + struct scic_sds_controller *scic_controller, + struct scic_sds_remote_device *scic_remote_device, + u16 io_tag, + void *user_task_request_object, + void *scic_task_request_memory, + struct scic_sds_request **new_scic_task_request_handle); + +/** + * scic_task_request_construct_ssp() - This method is called by the SCI user to + * construct all SCI Core SSP task management requests. Memory + * initialization and functionality common to all task request types is + * performed in this method. + * @scic_task_request: This parameter specifies the handle to the core task + * request object for which to construct a SATA specific task management + * request. + * + * Indicate if the controller successfully built the task request. SCI_SUCCESS + * This value is returned if the task request was successfully built. + */ +enum sci_status scic_task_request_construct_ssp( + struct scic_sds_request *scic_task_request); + +/** + * scic_task_request_construct_sata() - This method is called by the SCI user + * to construct all SCI Core SATA task management requests. Memory + * initialization and functionality common to all task request types is + * performed in this method. + * @scic_task_request_handle: This parameter specifies the handle to the core + * task request object for which to construct a SATA specific task + * management request. + * + * Indicate if the controller successfully built the task request. SCI_SUCCESS + * This value is returned if the task request was successfully built. + */ +enum sci_status scic_task_request_construct_sata( + struct scic_sds_request *scic_task_request_handle); + + + +#endif /* _SCIC_TASK_REQUEST_H_ */ + diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h new file mode 100644 index 000000000000..6eca5a96649e --- /dev/null +++ b/drivers/scsi/isci/core/scic_user_callback.h @@ -0,0 +1,740 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_USER_CALLBACK_H_ +#define _SCIC_USER_CALLBACK_H_ + +/** + * This file contains all of the interface methods/macros that must be + * implemented by an SCI Core user. + * + * + */ + + +#include "sci_types.h" +#include "sci_status.h" + +struct scic_sds_request; +struct scic_sds_phy; +struct scic_sds_port; +struct scic_sds_remote_device; +struct scic_sds_controller; + +/** + * scic_cb_timer_create() - This callback method asks the user to create a + * timer and provide a handle for this timer for use in further timer + * interactions. + * @controller: This parameter specifies the controller with which this timer + * is to be associated. + * @timer_callback: This parameter specifies the callback method to be invoked + * whenever the timer expires. + * @cookie: This parameter specifies a piece of information that the user must + * retain. This cookie is to be supplied by the user anytime a timeout + * occurs for the created timer. + * + * The "timer_callback" method should be executed in a mutually exlusive manner + * from the controller completion handler handler (refer to + * scic_controller_get_handler_methods()). This method returns a handle to a + * timer object created by the user. The handle will be utilized for all + * further interactions relating to this timer. + */ +void *scic_cb_timer_create( + struct scic_sds_controller *controller, + void (*timer_callback)(void *), + void *cookie); + + +/** + * scic_cb_timer_start() - This callback method asks the user to start the + * supplied timer. + * @controller: This parameter specifies the controller with which this timer + * is to associated. + * @timer: This parameter specifies the timer to be started. + * @milliseconds: This parameter specifies the number of milliseconds for which + * to stall. The operating system driver is allowed to round this value up + * where necessary. + * + * All timers in the system started by the SCI Core are one shot timers. + * Therefore, the SCI user should make sure that it removes the timer from it's + * list when a timer actually fires. Additionally, SCI Core user's should be + * able to handle calls from the SCI Core to stop a timer that may already be + * stopped. none + */ +void scic_cb_timer_start( + struct scic_sds_controller *controller, + void *timer, + u32 milliseconds); + +/** + * scic_cb_timer_stop() - This callback method asks the user to stop the + * supplied timer. + * @controller: This parameter specifies the controller with which this timer + * is to associated. + * @timer: This parameter specifies the timer to be stopped. + * + */ +void scic_cb_timer_stop( + struct scic_sds_controller *controller, + void *timer); + +/** + * scic_cb_stall_execution() - This method is called when the core requires the + * OS driver to stall execution. This method is utilized during + * initialization or non-performance paths only. + * @microseconds: This parameter specifies the number of microseconds for which + * to stall. The operating system driver is allowed to round this value up + * where necessary. + * + * none. + */ +void scic_cb_stall_execution( + u32 microseconds); + +/** + * scic_cb_controller_start_complete() - This user callback will inform the + * user that the controller has finished the start process. + * @controller: This parameter specifies the controller that was started. + * @completion_status: This parameter specifies the results of the start + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void scic_cb_controller_start_complete( + struct scic_sds_controller *controller, + enum sci_status completion_status); + +/** + * scic_cb_controller_stop_complete() - This user callback will inform the user + * that the controller has finished the stop process. + * @controller: This parameter specifies the controller that was stopped. + * @completion_status: This parameter specifies the results of the stop + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void scic_cb_controller_stop_complete( + struct scic_sds_controller *controller, + enum sci_status completion_status); + +/** + * scic_cb_io_request_complete() - This user callback will inform the user that + * an IO request has completed. + * @controller: This parameter specifies the controller on which the IO is + * completing. + * @remote_device: This parameter specifies the remote device on which this IO + * request is completing. + * @io_request: This parameter specifies the IO request that has completed. + * @completion_status: This parameter specifies the results of the IO request + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void scic_cb_io_request_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *io_request, + enum sci_io_status completion_status); + +/** + * scic_cb_task_request_complete() - This user callback will inform the user + * that a task management request completed. + * @controller: This parameter specifies the controller on which the task + * management request is completing. + * @remote_device: This parameter specifies the remote device on which this + * task management request is completing. + * @task_request: This parameter specifies the task management request that has + * completed. + * @completion_status: This parameter specifies the results of the IO request + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void scic_cb_task_request_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *task_request, + enum sci_task_status completion_status); + +#ifndef SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED +/** + * scic_cb_io_request_get_physical_address() - This callback method asks the + * user to provide the physical address for the supplied virtual address + * when building an io request object. + * @controller: This parameter is the core controller object handle. + * @io_request: This parameter is the io request object handle for which the + * physical address is being requested. + * @virtual_address: This paramter is the virtual address which is to be + * returned as a physical address. + * @physical_address: The physical address for the supplied virtual address. + * + * None. + */ +void scic_cb_io_request_get_physical_address( + struct scic_sds_controller *controller, + struct scic_sds_request *io_request, + void *virtual_address, + dma_addr_t *physical_address); +#endif /* SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED */ + +/** + * scic_cb_io_request_get_transfer_length() - This callback method asks the + * user to provide the number of bytes to be transfered as part of this + * request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the number of payload data bytes to be transfered for + * this IO request. + */ +u32 scic_cb_io_request_get_transfer_length( + void *scic_user_io_request); + +/** + * scic_cb_io_request_get_data_direction() - This callback method asks the user + * to provide the data direction for this request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the value of SCI_IO_REQUEST_DATA_OUT or + * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA. + */ +SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction( + void *scic_user_io_request); + +#ifndef SCI_SGL_OPTIMIZATION_ENABLED +/** + * scic_cb_io_request_get_next_sge() - This callback method asks the user to + * provide the address to where the next Scatter-Gather Element is located. + * Details regarding usage: - Regarding the first SGE: the user should + * initialize an index, or a pointer, prior to construction of the request + * that will reference the very first scatter-gather element. This is + * important since this method is called for every scatter-gather element, + * including the first element. - Regarding the last SGE: the user should + * return NULL from this method when this method is called and the SGL has + * exhausted all elements. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * @current_sge_address: This parameter specifies the address for the current + * SGE (i.e. the one that has just processed). + * @next_sge: An address specifying the location for the next scatter gather + * element to be processed. + * + * None + */ +void scic_cb_io_request_get_next_sge( + void *scic_user_io_request, + void *current_sge_address, + void **next_sge); +#endif /* SCI_SGL_OPTIMIZATION_ENABLED */ + +/** + * scic_cb_sge_get_address_field() - This callback method asks the user to + * provide the contents of the "address" field in the Scatter-Gather Element. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * @sge_address: This parameter specifies the address for the SGE from which to + * retrieve the address field. + * + * A physical address specifying the contents of the SGE's address field. + */ +dma_addr_t scic_cb_sge_get_address_field( + void *scic_user_io_request, + void *sge_address); + +/** + * scic_cb_sge_get_length_field() - This callback method asks the user to + * provide the contents of the "length" field in the Scatter-Gather Element. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * @sge_address: This parameter specifies the address for the SGE from which to + * retrieve the address field. + * + * This method returns the length field specified inside the SGE referenced by + * the sge_address parameter. + */ +u32 scic_cb_sge_get_length_field( + void *scic_user_io_request, + void *sge_address); + +/** + * scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the + * user to provide the address for the command descriptor block (CDB) + * associated with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the virtual address of the CDB. + */ +void *scic_cb_ssp_io_request_get_cdb_address( + void *scic_user_io_request); + +/** + * scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user + * to provide the length of the command descriptor block (CDB) associated + * with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the length of the CDB. + */ +u32 scic_cb_ssp_io_request_get_cdb_length( + void *scic_user_io_request); + +/** + * scic_cb_ssp_io_request_get_lun() - This callback method asks the user to + * provide the Logical Unit (LUN) associated with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * The contents of the value returned from this callback are defined by the + * protocol standard (e.g. T10 SAS specification). Please refer to the + * transport command information unit description in the associated standard. + * This method returns the LUN associated with this request. This should be u64? + */ +u32 scic_cb_ssp_io_request_get_lun( + void *scic_user_io_request); + +/** + * scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the + * user to provide the task attribute associated with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * The contents of the value returned from this callback are defined by the + * protocol standard (e.g. T10 SAS specification). Please refer to the + * transport command information unit description in the associated standard. + * This method returns the task attribute associated with this IO request. + */ +u32 scic_cb_ssp_io_request_get_task_attribute( + void *scic_user_io_request); + +/** + * scic_cb_ssp_io_request_get_command_priority() - This callback method asks + * the user to provide the command priority associated with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * The contents of the value returned from this callback are defined by the + * protocol standard (e.g. T10 SAS specification). Please refer to the + * transport command information unit description in the associated standard. + * This method returns the command priority associated with this IO request. + */ +u32 scic_cb_ssp_io_request_get_command_priority( + void *scic_user_io_request); + +/** + * scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user + * if the received RX frame data is to be copied to the SGL or should be + * stored by the SCI core to be retrieved later with the + * scic_io_request_get_rx_frame(). + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns true if the SCI core should copy the received frame data + * to the SGL location or false if the SCI user wants to retrieve the frame + * data at a later time. + */ +bool scic_cb_io_request_do_copy_rx_frames( + void *scic_user_io_request); + +/** + * scic_cb_request_get_sat_protocol() - This callback method asks the user to + * return the SAT protocol definition for this IO request. This method is + * only called by the SCI core if the request type constructed is SATA. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns one of the sat.h defined protocols for the given io + * request. + */ +u8 scic_cb_request_get_sat_protocol( + void *scic_user_io_request); + + +/** + * scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to + * be utilized for this task management request. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * The contents of the value returned from this callback are defined by the + * protocol standard (e.g. T10 SAS specification). Please refer to the + * transport task information unit description in the associated standard. This + * method returns the LUN associated with this request. This should be u64? + */ +u32 scic_cb_ssp_task_request_get_lun( + void *scic_user_task_request); + +/** + * scic_cb_ssp_task_request_get_function() - This method returns the task + * management function to be utilized for this task request. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * The contents of the value returned from this callback are defined by the + * protocol standard (e.g. T10 SAS specification). Please refer to the + * transport task information unit description in the associated standard. This + * method returns an unsigned byte representing the task management function to + * be performed. + */ +u8 scic_cb_ssp_task_request_get_function( + void *scic_user_task_request); + +/** + * scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the + * task management IO tag to be managed. Depending upon the task management + * function the value returned from this method may be ignored. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns an unsigned 16-bit word depicting the IO tag to be + * managed. + */ +u16 scic_cb_ssp_task_request_get_io_tag_to_manage( + void *scic_user_task_request); + +/** + * scic_cb_ssp_task_request_get_response_data_address() - This callback method + * asks the user to provide the virtual address of the response data buffer + * for the supplied IO request. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the virtual address for the response data buffer + * associated with this IO request. + */ +void *scic_cb_ssp_task_request_get_response_data_address( + void *scic_user_task_request); + +/** + * scic_cb_ssp_task_request_get_response_data_length() - This callback method + * asks the user to provide the length of the response data buffer for the + * supplied IO request. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the length of the response buffer data associated with + * this IO request. + */ +u32 scic_cb_ssp_task_request_get_response_data_length( + void *scic_user_task_request); + +/** + * scic_cb_pci_get_bar() - In this method the user must return the base address + * register (BAR) value for the supplied base address register number. + * @controller: The controller for which to retrieve the bar number. + * @bar_number: This parameter depicts the BAR index/number to be read. + * + * Return a pointer value indicating the contents of the BAR. NULL indicates an + * invalid BAR index/number was specified. All other values indicate a valid + * VIRTUAL address from the BAR. + */ +void *scic_cb_pci_get_bar( + struct scic_sds_controller *controller, + u16 bar_number); + +/** + * scic_cb_get_virtual_address() - This callback method asks the user to + * provide the virtual address for the supplied physical address. + * @controller: This parameter is the core controller object handle. + * @physical_address: This parameter is the physical address which is to be + * returned as a virtual address. + * + * The method returns the virtual address for the supplied physical address. + */ +void *scic_cb_get_virtual_address( + struct scic_sds_controller *controller, + dma_addr_t physical_address); + +/** + * scic_cb_port_stop_complete() - This method informs the user when a stop + * operation on the port has completed. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @completion_status: This parameter specifies the status for the operation + * being completed. + * + */ +void scic_cb_port_stop_complete( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + enum sci_status completion_status); + +/** + * scic_cb_port_hard_reset_complete() - This method informs the user when a + * hard reset on the port has completed. This hard reset could have been + * initiated by the user or by the remote port. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @completion_status: This parameter specifies the status for the operation + * being completed. + * + */ +void scic_cb_port_hard_reset_complete( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + enum sci_status completion_status); + +/** + * scic_cb_port_ready() - This method informs the user that the port is now in + * a ready state and can be utilized to issue IOs. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * + */ +void scic_cb_port_ready( + struct scic_sds_controller *controller, + struct scic_sds_port *port); + +/** + * scic_cb_port_not_ready() - This method informs the user that the port is now + * not in a ready (i.e. busy) state and can't be utilized to issue IOs. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @reason_code: This parameter specifies the reason for the port not ready + * callback. + * + */ +void scic_cb_port_not_ready( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + u32 reason_code); + +/** + * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that + * a phy/link became ready, but the phy is not allowed in the port. In some + * situations the underlying hardware only allows for certain phy to port + * mappings. If these mappings are violated, then this API is invoked. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @phy: This parameter specifies the phy that came ready, but the phy can't be + * a valid member of the port. + * + */ +void scic_cb_port_invalid_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +/** + * scic_cb_port_bc_change_primitive_received() - This callback method informs + * the user that a broadcast change primitive was received. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. For instances where the phy on which the primitive was + * received is not part of a port, this parameter will be + * SCI_INVALID_HANDLE_T. + * @phy: This parameter specifies the phy on which the primitive was received. + * + */ +void scic_cb_port_bc_change_primitive_received( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + + + + +/** + * scic_cb_port_link_up() - This callback method informs the user that a phy + * has become operational and is capable of communicating with the remote + * end point. + * @controller: This parameter represents the controller associated with the + * phy. + * @port: This parameter specifies the port object for which the user callback + * is being invoked. There may be conditions where this parameter can be + * SCI_INVALID_HANDLE + * @phy: This parameter specifies the phy object for which the user callback is + * being invoked. + * + */ +void scic_cb_port_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +/** + * scic_cb_port_link_down() - This callback method informs the user that a phy + * is no longer operational and is not capable of communicating with the + * remote end point. + * @controller: This parameter represents the controller associated with the + * phy. + * @port: This parameter specifies the port object for which the user callback + * is being invoked. There may be conditions where this parameter can be + * SCI_INVALID_HANDLE + * @phy: This parameter specifies the phy object for which the user callback is + * being invoked. + * + */ +void scic_cb_port_link_down( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +/** + * scic_cb_remote_device_start_complete() - This user callback method will + * inform the user that a start operation has completed. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the completion callback. + * @completion_status: This parameter specifies the completion status for the + * operation. + * + */ +void scic_cb_remote_device_start_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + enum sci_status completion_status); + +/** + * scic_cb_remote_device_stop_complete() - This user callback method will + * inform the user that a stop operation has completed. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the completion callback. + * @completion_status: This parameter specifies the completion status for the + * operation. + * + */ +void scic_cb_remote_device_stop_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + enum sci_status completion_status); + +/** + * scic_cb_remote_device_ready() - This user callback method will inform the + * user that a remote device is now capable of handling IO requests. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the callback. + * + */ +void scic_cb_remote_device_ready( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device); + +/** + * scic_cb_remote_device_not_ready() - This user callback method will inform + * the user that a remote device is no longer capable of handling IO + * requests (until a ready callback is invoked). + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the callback. + * @reason_code: This paramete specifies the reason the remote device is not + * ready. + * + */ +void scic_cb_remote_device_not_ready( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + u32 reason_code); + +#if !defined(DISABLE_ATAPI) +/** + * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback gets + * from stp packet io's user request the CDB address. + * @scic_user_io_request: + * + * The cdb adress. + */ +void *scic_cb_stp_packet_io_request_get_cdb_address( + void *scic_user_io_request); + +/** + * scic_cb_stp_packet_io_request_get_cdb_length() - This user callback gets + * from stp packet io's user request the CDB length. + * @scic_user_io_request: + * + * The cdb length. + */ +u32 scic_cb_stp_packet_io_request_get_cdb_length( + void *scic_user_io_request); +#else /* !defined(DISABLE_ATAPI) */ +#define scic_cb_stp_packet_io_request_get_cdb_address(scic_user_io_request) NULL +#define scic_cb_stp_packet_io_request_get_cdb_length(scic_user_io_request) 0 +#endif /* !defined(DISABLE_ATAPI) */ + + +#endif /* _SCIC_USER_CALLBACK_H_ */ + diff --git a/drivers/scsi/isci/core/scu_completion_codes.h b/drivers/scsi/isci/core/scu_completion_codes.h new file mode 100644 index 000000000000..17ee4c8b9122 --- /dev/null +++ b/drivers/scsi/isci/core/scu_completion_codes.h @@ -0,0 +1,280 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCU_COMPLETION_CODES_HEADER_ +#define _SCU_COMPLETION_CODES_HEADER_ + +/** + * This file contains the constants and macros for the SCU hardware completion + * codes. + * + * + */ + +#define SCU_COMPLETION_TYPE_SHIFT 28 +#define SCU_COMPLETION_TYPE_MASK 0x70000000 + +/** + * SCU_COMPLETION_TYPE() - + * + * This macro constructs an SCU completion type + */ +#define SCU_COMPLETION_TYPE(type) \ + ((u32)(type) << SCU_COMPLETION_TYPE_SHIFT) + +/** + * SCU_COMPLETION_TYPE() - + * + * These macros contain the SCU completion types SCU_COMPLETION_TYPE + */ +#define SCU_COMPLETION_TYPE_TASK SCU_COMPLETION_TYPE(0) +#define SCU_COMPLETION_TYPE_SDMA SCU_COMPLETION_TYPE(1) +#define SCU_COMPLETION_TYPE_UFI SCU_COMPLETION_TYPE(2) +#define SCU_COMPLETION_TYPE_EVENT SCU_COMPLETION_TYPE(3) +#define SCU_COMPLETION_TYPE_NOTIFY SCU_COMPLETION_TYPE(4) + +/** + * + * + * These constants provide the shift and mask values for the various parts of + * an SCU completion code. + */ +#define SCU_COMPLETION_STATUS_MASK 0x0FFC0000 +#define SCU_COMPLETION_TL_STATUS_MASK 0x0FC00000 +#define SCU_COMPLETION_TL_STATUS_SHIFT 22 +#define SCU_COMPLETION_SDMA_STATUS_MASK 0x003C0000 +#define SCU_COMPLETION_PEG_MASK 0x00010000 +#define SCU_COMPLETION_PORT_MASK 0x00007000 +#define SCU_COMPLETION_PE_MASK SCU_COMPLETION_PORT_MASK +#define SCU_COMPLETION_PE_SHIFT 12 +#define SCU_COMPLETION_INDEX_MASK 0x00000FFF + +/** + * SCU_GET_COMPLETION_TYPE() - + * + * This macro returns the SCU completion type. + */ +#define SCU_GET_COMPLETION_TYPE(completion_code) \ + ((completion_code) & SCU_COMPLETION_TYPE_MASK) + +/** + * SCU_GET_COMPLETION_STATUS() - + * + * This macro returns the SCU completion status. + */ +#define SCU_GET_COMPLETION_STATUS(completion_code) \ + ((completion_code) & SCU_COMPLETION_STATUS_MASK) + +/** + * SCU_GET_COMPLETION_TL_STATUS() - + * + * This macro returns the transport layer completion status. + */ +#define SCU_GET_COMPLETION_TL_STATUS(completion_code) \ + ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) + +/** + * SCU_MAKE_COMPLETION_STATUS() - + * + * This macro takes a completion code and performs the shift and mask + * operations to turn it into a completion code that can be compared to a + * SCU_GET_COMPLETION_TL_STATUS. + */ +#define SCU_MAKE_COMPLETION_STATUS(completion_code) \ + ((u32)(completion_code) << SCU_COMPLETION_TL_STATUS_SHIFT) + +/** + * SCU_NORMALIZE_COMPLETION_STATUS() - + * + * This macro takes a SCU_GET_COMPLETION_TL_STATUS and normalizes it for a + * return code. + */ +#define SCU_NORMALIZE_COMPLETION_STATUS(completion_code) \ + (\ + ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) \ + >> SCU_COMPLETION_TL_STATUS_SHIFT \ + ) + +/** + * SCU_GET_COMPLETION_SDMA_STATUS() - + * + * This macro returns the SDMA completion status. + */ +#define SCU_GET_COMPLETION_SDMA_STATUS(completion_code) \ + ((completion_code) & SCU_COMPLETION_SDMA_STATUS_MASK) + +/** + * SCU_GET_COMPLETION_PEG() - + * + * This macro returns the Protocol Engine Group from the completion code. + */ +#define SCU_GET_COMPLETION_PEG(completion_code) \ + ((completion_code) & SCU_COMPLETION_PEG_MASK) + +/** + * SCU_GET_COMPLETION_PORT() - + * + * This macro reuturns the logical port index from the completion code. + */ +#define SCU_GET_COMPLETION_PORT(completion_code) \ + ((completion_code) & SCU_COMPLETION_PORT_MASK) + +/** + * SCU_GET_PROTOCOL_ENGINE_INDEX() - + * + * This macro returns the PE index from the completion code. + */ +#define SCU_GET_PROTOCOL_ENGINE_INDEX(completion_code) \ + (((completion_code) & SCU_COMPLETION_PE_MASK) >> SCU_COMPLETION_PE_SHIFT) + +/** + * SCU_GET_COMPLETION_INDEX() - + * + * This macro returns the index of the completion which is either a TCi or an + * RNi depending on the completion type. + */ +#define SCU_GET_COMPLETION_INDEX(completion_code) \ + ((completion_code) & SCU_COMPLETION_INDEX_MASK) + +#define SCU_UNSOLICITED_FRAME_MASK 0x0FFF0000 +#define SCU_UNSOLICITED_FRAME_SHIFT 16 + +/** + * SCU_GET_FRAME_INDEX() - + * + * This macro returns a normalized frame index from an unsolicited frame + * completion. + */ +#define SCU_GET_FRAME_INDEX(completion_code) \ + (\ + ((completion_code) & SCU_UNSOLICITED_FRAME_MASK) \ + >> SCU_UNSOLICITED_FRAME_SHIFT \ + ) + +#define SCU_UNSOLICITED_FRAME_ERROR_MASK 0x00008000 + +/** + * SCU_GET_FRAME_ERROR() - + * + * This macro returns a zero (0) value if there is no frame error otherwise it + * returns non-zero (!0). + */ +#define SCU_GET_FRAME_ERROR(completion_code) \ + ((completion_code) & SCU_UNSOLICITED_FRAME_ERROR_MASK) + +/** + * + * + * These constants represent normalized completion codes which must be shifted + * 18 bits to match it with the hardware completion code. In a 16-bit compiler, + * immediate constants are 16-bit values (the size of an int). If we shift + * those by 18 bits, we completely lose the value. To ensure the value is a + * 32-bit value like we want, each immediate value must be cast to a u32. + */ +#define SCU_TASK_DONE_GOOD ((u32)0x00) +#define SCU_TASK_DONE_CRC_ERR ((u32)0x14) +#define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14) +#define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15) +#define SCU_TASK_DONE_NAK_CMD_ERR ((u32)0x16) +#define SCU_TASK_DONE_LL_R_ERR ((u32)0x17) +#define SCU_TASK_DONE_ACK_NAK_TO ((u32)0x17) +#define SCU_TASK_DONE_LL_PERR ((u32)0x18) +#define SCU_TASK_DONE_LL_SY_TERM ((u32)0x19) +#define SCU_TASK_DONE_NAK_ERR ((u32)0x19) +#define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A) +#define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A) +#define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B) +#define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B) +#define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C) +#define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C) +#define SCU_TASK_DONE_INV_FIS_TYPE ((u32)0x1D) +#define SCU_TASK_DONE_XR_IU_LEN_ERR ((u32)0x1D) +#define SCU_TASK_DONE_INV_FIS_LEN ((u32)0x1E) +#define SCU_TASK_DONE_XR_WD_LEN ((u32)0x1E) +#define SCU_TASK_DONE_SDMA_ERR ((u32)0x1F) +#define SCU_TASK_DONE_OFFSET_ERR ((u32)0x20) +#define SCU_TASK_DONE_MAX_PLD_ERR ((u32)0x21) +#define SCU_TASK_DONE_EXCESS_DATA ((u32)0x22) +#define SCU_TASK_DONE_LF_ERR ((u32)0x23) +#define SCU_TASK_DONE_UNEXP_FIS ((u32)0x24) +#define SCU_TASK_DONE_UNEXP_RESP ((u32)0x24) +#define SCU_TASK_DONE_EARLY_RESP ((u32)0x25) +#define SCU_TASK_DONE_SMP_RESP_TO_ERR ((u32)0x26) +#define SCU_TASK_DONE_DMASETUP_DIRERR ((u32)0x27) +#define SCU_TASK_DONE_SMP_UFI_ERR ((u32)0x27) +#define SCU_TASK_DONE_XFERCNT_ERR ((u32)0x28) +#define SCU_TASK_DONE_SMP_FRM_TYPE_ERR ((u32)0x28) +#define SCU_TASK_DONE_SMP_LL_RX_ERR ((u32)0x29) +#define SCU_TASK_DONE_RESP_LEN_ERR ((u32)0x2A) +#define SCU_TASK_DONE_UNEXP_DATA ((u32)0x2B) +#define SCU_TASK_DONE_OPEN_FAIL ((u32)0x2C) +#define SCU_TASK_DONE_UNEXP_SDBFIS ((u32)0x2D) +#define SCU_TASK_DONE_REG_ERR ((u32)0x2E) +#define SCU_TASK_DONE_SDB_ERR ((u32)0x2F) +#define SCU_TASK_DONE_TASK_ABORT ((u32)0x30) +#define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION ((u32)0x34) +#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1 ((u32)0x35) +#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2 ((u32)0x36) +#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3 ((u32)0x37) +#define SCU_TASK_OPEN_REJECT_BAD_DESTINATION ((u32)0x38) +#define SCU_TASK_OPEN_REJECT_ZONE_VIOLATION ((u32)0x39) +#define SCU_TASK_DONE_VIIT_ENTRY_NV ((u32)0x3A) +#define SCU_TASK_DONE_IIT_ENTRY_NV ((u32)0x3B) +#define SCU_TASK_DONE_RNCNV_OUTBOUND ((u32)0x3C) +#define SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY ((u32)0x3D) +#define SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED ((u32)0x3E) +#define SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED ((u32)0x3F) + +#endif /* _SCU_COMPLETION_CODES_HEADER_ */ diff --git a/drivers/scsi/isci/core/scu_constants.h b/drivers/scsi/isci/core/scu_constants.h new file mode 100644 index 000000000000..a99d1103ad3b --- /dev/null +++ b/drivers/scsi/isci/core/scu_constants.h @@ -0,0 +1,151 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCU_CONSTANTS_H_ +#define _SCU_CONSTANTS_H_ + +/** + * This file contains the SCU hardware constants. + * + * + */ + +#include "sci_controller_constants.h" + +/** + * + * + * 2 indicates the maximum number of UFs that can occur for a given IO request. + * The hardware handles reception of additional unsolicited frames while all + * UFs are in use, by holding off the transmitting device. This number could + * be theoretically reduced to 1, but 2 provides for more reliable operation. + * During SATA PIO operation, it is possible under some conditions for there to + * be 3 separate FISes received, back to back to back (PIO Setup, Data, D2H + * Register). It is unlikely to have all 3 pending all at once without some of + * them already being processed. + */ +#define SCU_MIN_UNSOLICITED_FRAMES (1) +#define SCU_MIN_CRITICAL_NOTIFICATIONS (24) +#define SCU_MIN_EVENTS (4) +#define SCU_MIN_COMPLETION_QUEUE_SCRATCH (2) +#define SCU_MIN_COMPLETION_QUEUE_ENTRIES (SCU_MIN_CRITICAL_NOTIFICATIONS \ + + SCU_MIN_EVENTS \ + + SCU_MIN_UNSOLICITED_FRAMES \ + + SCI_MIN_IO_REQUESTS \ + + SCU_MIN_COMPLETION_QUEUE_SCRATCH) + +#define SCU_MAX_CRITICAL_NOTIFICATIONS (384) +#define SCU_MAX_EVENTS (128) +#define SCU_MAX_UNSOLICITED_FRAMES (128) +#define SCU_MAX_COMPLETION_QUEUE_SCRATCH (128) +#define SCU_MAX_COMPLETION_QUEUE_ENTRIES (SCU_MAX_CRITICAL_NOTIFICATIONS \ + + SCU_MAX_EVENTS \ + + SCU_MAX_UNSOLICITED_FRAMES \ + + SCI_MAX_IO_REQUESTS \ + + SCU_MAX_COMPLETION_QUEUE_SCRATCH) + +#if !defined(ENABLE_MINIMUM_MEMORY_MODE) +#define SCU_UNSOLICITED_FRAME_COUNT SCU_MAX_UNSOLICITED_FRAMES +#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MAX_CRITICAL_NOTIFICATIONS +#define SCU_EVENT_COUNT SCU_MAX_EVENTS +#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MAX_COMPLETION_QUEUE_SCRATCH +#define SCU_IO_REQUEST_COUNT SCI_MAX_IO_REQUESTS +#define SCU_IO_REQUEST_SGE_COUNT SCI_MAX_SCATTER_GATHER_ELEMENTS +#define SCU_COMPLETION_QUEUE_COUNT SCU_MAX_COMPLETION_QUEUE_ENTRIES +#else +#define SCU_UNSOLICITED_FRAME_COUNT SCU_MIN_UNSOLICITED_FRAMES +#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MIN_CRITICAL_NOTIFICATIONS +#define SCU_EVENT_COUNT SCU_MIN_EVENTS +#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MIN_COMPLETION_QUEUE_SCRATCH +#define SCU_IO_REQUEST_COUNT SCI_MIN_IO_REQUESTS +#define SCU_IO_REQUEST_SGE_COUNT SCI_MIN_SCATTER_GATHER_ELEMENTS +#define SCU_COMPLETION_QUEUE_COUNT SCU_MIN_COMPLETION_QUEUE_ENTRIES +#endif /* !defined(ENABLE_MINIMUM_MEMORY_OPERATION) */ + +/** + * + * + * The SCU_COMPLETION_QUEUE_COUNT constant indicates the size of the completion + * queue into which the hardware DMAs 32-bit quantas (completion entries). + */ + +/** + * + * + * This queue must be programmed to a power of 2 size (e.g. 32, 64, 1024, etc.). + */ +#if (SCU_COMPLETION_QUEUE_COUNT != 16) && \ + (SCU_COMPLETION_QUEUE_COUNT != 32) && \ + (SCU_COMPLETION_QUEUE_COUNT != 64) && \ + (SCU_COMPLETION_QUEUE_COUNT != 128) && \ + (SCU_COMPLETION_QUEUE_COUNT != 256) && \ + (SCU_COMPLETION_QUEUE_COUNT != 512) && \ + (SCU_COMPLETION_QUEUE_COUNT != 1024) +#error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2." +#endif + +#if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES +#error "Invalid configuration of unsolicited frame constants" +#endif /* SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES */ + +#define SCU_MIN_UF_TABLE_ENTRIES (8) +#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096) +#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024) +#define SCU_INVALID_FRAME_INDEX (0xFFFF) + +#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF) +#define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH (0x00FFFFFF) + +#endif /* _SCU_CONSTANTS_H_ */ diff --git a/drivers/scsi/isci/core/scu_event_codes.h b/drivers/scsi/isci/core/scu_event_codes.h new file mode 100644 index 000000000000..36a945ad5722 --- /dev/null +++ b/drivers/scsi/isci/core/scu_event_codes.h @@ -0,0 +1,336 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCU_EVENT_CODES_HEADER__ +#define __SCU_EVENT_CODES_HEADER__ + +/** + * This file contains the constants and macros for the SCU event codes. + * + * + */ + +#define SCU_EVENT_TYPE_CODE_SHIFT 24 +#define SCU_EVENT_TYPE_CODE_MASK 0x0F000000 + +#define SCU_EVENT_SPECIFIC_CODE_SHIFT 18 +#define SCU_EVENT_SPECIFIC_CODE_MASK 0x00FC0000 + +#define SCU_EVENT_CODE_MASK \ + (SCU_EVENT_TYPE_CODE_MASK | SCU_EVENT_SPECIFIC_CODE_MASK) + +/** + * SCU_EVENT_TYPE() - + * + * This macro constructs an SCU event type from the type value. + */ +#define SCU_EVENT_TYPE(type) \ + ((u32)(type) << SCU_EVENT_TYPE_CODE_SHIFT) + +/** + * SCU_EVENT_SPECIFIC() - + * + * This macro constructs an SCU event specifier from the code value. + */ +#define SCU_EVENT_SPECIFIC(code) \ + ((u32)(code) << SCU_EVENT_SPECIFIC_CODE_SHIFT) + +/** + * SCU_EVENT_MESSAGE() - + * + * This macro constructs a combines an SCU event type and SCU event specifier + * from the type and code values. + */ +#define SCU_EVENT_MESSAGE(type, code) \ + ((type) | SCU_EVENT_SPECIFIC(code)) + +/** + * SCU_EVENT_TYPE() - + * + * SCU_EVENT_TYPES + */ +#define SCU_EVENT_TYPE_SMU_COMMAND_ERROR SCU_EVENT_TYPE(0x08) +#define SCU_EVENT_TYPE_SMU_PCQ_ERROR SCU_EVENT_TYPE(0x09) +#define SCU_EVENT_TYPE_SMU_ERROR SCU_EVENT_TYPE(0x00) +#define SCU_EVENT_TYPE_TRANSPORT_ERROR SCU_EVENT_TYPE(0x01) +#define SCU_EVENT_TYPE_BROADCAST_CHANGE SCU_EVENT_TYPE(0x02) +#define SCU_EVENT_TYPE_OSSP_EVENT SCU_EVENT_TYPE(0x03) +#define SCU_EVENT_TYPE_FATAL_MEMORY_ERROR SCU_EVENT_TYPE(0x0F) +#define SCU_EVENT_TYPE_RNC_SUSPEND_TX SCU_EVENT_TYPE(0x04) +#define SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX SCU_EVENT_TYPE(0x05) +#define SCU_EVENT_TYPE_RNC_OPS_MISC SCU_EVENT_TYPE(0x06) +#define SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT SCU_EVENT_TYPE(0x07) +#define SCU_EVENT_TYPE_ERR_CNT_EVENT SCU_EVENT_TYPE(0x0A) + +/** + * + * + * SCU_EVENT_SPECIFIERS + */ +#define SCU_EVENT_SPECIFIER_DRIVER_SUSPEND 0x20 +#define SCU_EVENT_SPECIFIER_RNC_RELEASE 0x00 + +/** + * + * + * SMU_COMMAND_EVENTS + */ +#define SCU_EVENT_INVALID_CONTEXT_COMMAND \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_COMMAND_ERROR, 0x00) + +/** + * + * + * SMU_PCQ_EVENTS + */ +#define SCU_EVENT_UNCORRECTABLE_PCQ_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_PCQ_ERROR, 0x00) + +/** + * + * + * SMU_EVENTS + */ +#define SCU_EVENT_UNCORRECTABLE_REGISTER_WRITE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x02) +#define SCU_EVENT_UNCORRECTABLE_REGISTER_READ \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x03) +#define SCU_EVENT_PCIE_INTERFACE_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x04) +#define SCU_EVENT_FUNCTION_LEVEL_RESET \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x05) + +/** + * + * + * TRANSPORT_LEVEL_ERRORS + */ +#define SCU_EVENT_ACK_NAK_TIMEOUT_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_TRANSPORT_ERROR, 0x00) + +/** + * + * + * BROADCAST_CHANGE_EVENTS + */ +#define SCU_EVENT_BROADCAST_CHANGE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x01) +#define SCU_EVENT_BROADCAST_RESERVED0 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x02) +#define SCU_EVENT_BROADCAST_RESERVED1 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x03) +#define SCU_EVENT_BROADCAST_SES \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x04) +#define SCU_EVENT_BROADCAST_EXPANDER \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x05) +#define SCU_EVENT_BROADCAST_AEN \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x06) +#define SCU_EVENT_BROADCAST_RESERVED3 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x07) +#define SCU_EVENT_BROADCAST_RESERVED4 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x08) +#define SCU_EVENT_PE_SUSPENDED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x09) + +/** + * + * + * OSSP_EVENTS + */ +#define SCU_EVENT_PORT_SELECTOR_DETECTED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x10) +#define SCU_EVENT_SENT_PORT_SELECTION \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x11) +#define SCU_EVENT_HARD_RESET_TRANSMITTED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x12) +#define SCU_EVENT_HARD_RESET_RECEIVED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x13) +#define SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x15) +#define SCU_EVENT_LINK_FAILURE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x16) +#define SCU_EVENT_SATA_SPINUP_HOLD \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x17) +#define SCU_EVENT_SAS_15_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x18) +#define SCU_EVENT_SAS_15 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x19) +#define SCU_EVENT_SAS_30_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1A) +#define SCU_EVENT_SAS_30 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1B) +#define SCU_EVENT_SAS_60_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1C) +#define SCU_EVENT_SAS_60 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1D) +#define SCU_EVENT_SATA_15_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1E) +#define SCU_EVENT_SATA_15 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1F) +#define SCU_EVENT_SATA_30_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x20) +#define SCU_EVENT_SATA_30 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x21) +#define SCU_EVENT_SATA_60_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x22) +#define SCU_EVENT_SATA_60 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x23) +#define SCU_EVENT_SAS_PHY_DETECTED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x24) +#define SCU_EVENT_SATA_PHY_DETECTED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x25) + +/** + * + * + * FATAL_INTERNAL_MEMORY_ERROR_EVENTS + */ +#define SCU_EVENT_TSC_RNSC_UNCORRECTABLE_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x00) +#define SCU_EVENT_TC_RNC_UNCORRECTABLE_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x01) +#define SCU_EVENT_ZPT_UNCORRECTABLE_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x02) + +/** + * + * + * REMOTE_NODE_SUSPEND_EVENTS + */ +#define SCU_EVENT_TL_RNC_SUSPEND_TX \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x00) +#define SCU_EVENT_TL_RNC_SUSPEND_TX_RX \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x00) +#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20) +#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX_RX \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x20) + +/** + * + * + * REMOTE_NODE_MISC_EVENTS + */ +#define SCU_EVENT_POST_RCN_RELEASE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, SCU_EVENT_SPECIFIER_RNC_RELEASE) +#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_ENABLE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x01) +#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_DISABLE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x02) +#define SCU_EVENT_POST_RNC_COMPLETE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x03) +#define SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x04) + +/** + * + * + * ERROR_COUNT_EVENT + */ +#define SCU_EVENT_RX_CREDIT_BLOCKED_RECEIVED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x00) +#define SCU_EVENT_TX_DONE_CREDIT_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x01) +#define SCU_EVENT_RX_DONE_CREDIT_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x02) + +/** + * scu_get_event_type() - + * + * This macro returns the SCU event type from the event code. + */ +#define scu_get_event_type(event_code) \ + ((event_code) & SCU_EVENT_TYPE_CODE_MASK) + +/** + * scu_get_event_specifier() - + * + * This macro returns the SCU event specifier from the event code. + */ +#define scu_get_event_specifier(event_code) \ + ((event_code) & SCU_EVENT_SPECIFIC_CODE_MASK) + +/** + * scu_get_event_code() - + * + * This macro returns the combined SCU event type and SCU event specifier from + * the event code. + */ +#define scu_get_event_code(event_code) \ + ((event_code) & SCU_EVENT_CODE_MASK) + + +/** + * + * + * PTS_SCHEDULE_EVENT + */ +#define SCU_EVENT_SMP_RESPONSE_NO_PE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x00) +#define SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE \ + scu_get_event_specifier(SCU_EVENT_SMP_RESPONSE_NO_PE) + +#define SCU_EVENT_TASK_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x01) +#define SCU_EVENT_SPECIFIC_TASK_TIMEOUT \ + scu_get_event_specifier(SCU_EVENT_TASK_TIMEOUT) + +#define SCU_EVENT_IT_NEXUS_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x02) +#define SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT \ + scu_get_event_specifier(SCU_EVENT_IT_NEXUS_TIMEOUT) + + +#endif /* __SCU_EVENT_CODES_HEADER__ */ diff --git a/drivers/scsi/isci/core/scu_registers.h b/drivers/scsi/isci/core/scu_registers.h new file mode 100644 index 000000000000..175d2b98bdf2 --- /dev/null +++ b/drivers/scsi/isci/core/scu_registers.h @@ -0,0 +1,1824 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCU_REGISTERS_H_ +#define _SCU_REGISTERS_H_ + +/** + * This file contains the constants and structures for the SCU memory mapped + * registers. + * + * + */ + +#include "sci_types.h" +#include "scu_viit_data.h" + + +/* Generate a value for an SCU register */ +#define SCU_GEN_VALUE(name, value) \ + (((value) << name ## _SHIFT) & (name ## _MASK)) + +/* + * Generate a bit value for an SCU register + * Make sure that the register MASK is just a single bit */ +#define SCU_GEN_BIT(name) \ + SCU_GEN_VALUE(name, ((u32)1)) + +#define SCU_SET_BIT(name, reg_value) \ + ((reg_value) | SCU_GEN_BIT(name)) + +#define SCU_CLEAR_BIT(name, reg_value) \ + ((reg_value)$ ~(SCU_GEN_BIT(name))) + +/* + * ***************************************************************************** + * Unions for bitfield definitions of SCU Registers + * SMU Post Context Port + * ***************************************************************************** */ +#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_SHIFT (0) +#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_MASK (0x00000FFF) +#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_SHIFT (12) +#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_MASK (0x0000F000) +#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_SHIFT (16) +#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_MASK (0x00030000) +#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_SHIFT (18) +#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_MASK (0x00FC0000) +#define SMU_POST_CONTEXT_PORT_RESERVED_MASK (0xFF000000) + +#define SMU_PCP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_POST_CONTEXT_PORT_ ## name, value) + +/* ***************************************************************************** */ +#define SMU_INTERRUPT_STATUS_COMPLETION_SHIFT (31) +#define SMU_INTERRUPT_STATUS_COMPLETION_MASK (0x80000000) +#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_SHIFT (1) +#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_MASK (0x00000002) +#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_SHIFT (0) +#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_MASK (0x00000001) +#define SMU_INTERRUPT_STATUS_RESERVED_MASK (0x7FFFFFFC) + +#define SMU_ISR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_INTERRUPT_STATUS_ ## name) + +#define SMU_ISR_QUEUE_ERROR SMU_ISR_GEN_BIT(QUEUE_ERROR) +#define SMU_ISR_QUEUE_SUSPEND SMU_ISR_GEN_BIT(QUEUE_SUSPEND) +#define SMU_ISR_COMPLETION SMU_ISR_GEN_BIT(COMPLETION) + +/* ***************************************************************************** */ +#define SMU_INTERRUPT_MASK_COMPLETION_SHIFT (31) +#define SMU_INTERRUPT_MASK_COMPLETION_MASK (0x80000000) +#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_SHIFT (1) +#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_MASK (0x00000002) +#define SMU_INTERRUPT_MASK_QUEUE_ERROR_SHIFT (0) +#define SMU_INTERRUPT_MASK_QUEUE_ERROR_MASK (0x00000001) +#define SMU_INTERRUPT_MASK_RESERVED_MASK (0x7FFFFFFC) + +#define SMU_IMR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_INTERRUPT_MASK_ ## name) + +#define SMU_IMR_QUEUE_ERROR SMU_IMR_GEN_BIT(QUEUE_ERROR) +#define SMU_IMR_QUEUE_SUSPEND SMU_IMR_GEN_BIT(QUEUE_SUSPEND) +#define SMU_IMR_COMPLETION SMU_IMR_GEN_BIT(COMPLETION) + +/* ***************************************************************************** */ +#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_SHIFT (0) +#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_MASK (0x0000001F) +#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_SHIFT (8) +#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_MASK (0x0000FF00) +#define SMU_INTERRUPT_COALESCING_CONTROL_RESERVED_MASK (0xFFFF00E0) + +#define SMU_ICC_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_INTERRUPT_COALESCING_CONTROL_ ## name, value) + +/* ***************************************************************************** */ +#define SMU_TASK_CONTEXT_RANGE_START_SHIFT (0) +#define SMU_TASK_CONTEXT_RANGE_START_MASK (0x00000FFF) +#define SMU_TASK_CONTEXT_RANGE_ENDING_SHIFT (16) +#define SMU_TASK_CONTEXT_RANGE_ENDING_MASK (0x0FFF0000) +#define SMU_TASK_CONTEXT_RANGE_ENABLE_SHIFT (31) +#define SMU_TASK_CONTEXT_RANGE_ENABLE_MASK (0x80000000) +#define SMU_TASK_CONTEXT_RANGE_RESERVED_MASK (0x7000F000) + +#define SMU_TCR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_TASK_CONTEXT_RANGE_ ## name, value) + +#define SMU_TCR_GEN_BIT(name, value) \ + SCU_GEN_BIT(SMU_TASK_CONTEXT_RANGE_ ## name) + +/* ***************************************************************************** */ + +#define SMU_COMPLETION_QUEUE_PUT_POINTER_SHIFT (0) +#define SMU_COMPLETION_QUEUE_PUT_POINTER_MASK (0x00003FFF) +#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_SHIFT (15) +#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_MASK (0x00008000) +#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_SHIFT (16) +#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_MASK (0x03FF0000) +#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_SHIFT (26) +#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_MASK (0x04000000) +#define SMU_COMPLETION_QUEUE_PUT_RESERVED_MASK (0xF8004000) + +#define SMU_CQPR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_PUT_ ## name, value) + +#define SMU_CQPR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_COMPLETION_QUEUE_PUT_ ## name) + +/* ***************************************************************************** */ + +#define SMU_COMPLETION_QUEUE_GET_POINTER_SHIFT (0) +#define SMU_COMPLETION_QUEUE_GET_POINTER_MASK (0x00003FFF) +#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT (15) +#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_MASK (0x00008000) +#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT (16) +#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK (0x03FF0000) +#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT (26) +#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_MASK (0x04000000) +#define SMU_COMPLETION_QUEUE_GET_ENABLE_SHIFT (30) +#define SMU_COMPLETION_QUEUE_GET_ENABLE_MASK (0x40000000) +#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_SHIFT (31) +#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_MASK (0x80000000) +#define SMU_COMPLETION_QUEUE_GET_RESERVED_MASK (0x38004000) + +#define SMU_CQGR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_GET_ ## name, value) + +#define SMU_CQGR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_COMPLETION_QUEUE_GET_ ## name) + +#define SMU_CQGR_CYCLE_BIT \ + SMU_CQGR_GEN_BIT(CYCLE_BIT) + +#define SMU_CQGR_EVENT_CYCLE_BIT \ + SMU_CQGR_GEN_BIT(EVENT_CYCLE_BIT) + +#define SMU_CQGR_GET_POINTER_SET(value) \ + SMU_CQGR_GEN_VAL(POINTER, value) + + +/* ***************************************************************************** */ +#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_SHIFT (0) +#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_MASK (0x00003FFF) +#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_SHIFT (16) +#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_MASK (0x03FF0000) +#define SMU_COMPLETION_QUEUE_CONTROL_RESERVED_MASK (0xFC00C000) + +#define SMU_CQC_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_CONTROL_ ## name, value) + +#define SMU_CQC_QUEUE_LIMIT_SET(value) \ + SMU_CQC_GEN_VAL(QUEUE_LIMIT, value) + +#define SMU_CQC_EVENT_LIMIT_SET(value) \ + SMU_CQC_GEN_VAL(EVENT_LIMIT, value) + + +/* ***************************************************************************** */ +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT (0) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK (0x00000FFF) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT (12) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK (0x00007000) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT (15) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK (0x07FF8000) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_SHIFT (27) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK (0x08000000) +#define SMU_DEVICE_CONTEXT_CAPACITY_RESERVED_MASK (0xF0000000) + +#define SMU_DCC_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_DEVICE_CONTEXT_CAPACITY_ ## name, value) + +#define SMU_DCC_GET_MAX_PEG(value) \ + (\ + ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \ + ) + +#define SMU_DCC_GET_MAX_LP(value) \ + (\ + ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \ + ) + +#define SMU_DCC_GET_MAX_TC(value) \ + (\ + ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT \ + ) + +#define SMU_DCC_GET_MAX_RNC(value) \ + (\ + ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT \ + ) + +/* -------------------------------------------------------------------------- */ + +#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_SHIFT (0) +#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_MASK (0x00000001) +#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_SHIFT (1) +#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_MASK (0x00000002) +#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_SHIFT (16) +#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_MASK (0x00010000) +#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_SHIFT (17) +#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_MASK (0x00020000) +#define SMU_CONTROL_STATUS_RESERVED_MASK (0xFFFCFFFC) + +#define SMU_SMUCSR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_CONTROL_STATUS_ ## name) + +#define SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \ + (SMU_SMUCSR_GEN_BIT(SCHEDULER_RAM_INIT_COMPLETED)) + +#define SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \ + (SMU_SMUCSR_GEN_BIT(CONTEXT_RAM_INIT_COMPLETED)) + +#define SCU_RAM_INIT_COMPLETED \ + (\ + SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \ + | SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \ + ) + +/* -------------------------------------------------------------------------- */ + +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_SHIFT (0) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_MASK (0x00000001) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_SHIFT (1) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_MASK (0x00000002) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_SHIFT (2) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_MASK (0x00000004) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_SHIFT (3) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_MASK (0x00000008) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_SHIFT (8) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_MASK (0x00000100) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_SHIFT (9) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_MASK (0x00000200) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_SHIFT (10) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_MASK (0x00000400) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_SHIFT (11) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_MASK (0x00000800) + +#define SMU_RESET_PROTOCOL_ENGINE(peg, pe) \ + ((1 << (pe)) << ((peg) * 8)) + +#define SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \ + (\ + SMU_RESET_PROTOCOL_ENGINE(peg, 0) \ + | SMU_RESET_PROTOCOL_ENGINE(peg, 1) \ + | SMU_RESET_PROTOCOL_ENGINE(peg, 2) \ + | SMU_RESET_PROTOCOL_ENGINE(peg, 3) \ + ) + +#define SMU_RESET_ALL_PROTOCOL_ENGINES() \ + (\ + SMU_RESET_PEG_PROTOCOL_ENGINES(0) \ + | SMU_RESET_PEG_PROTOCOL_ENGINES(1) \ + ) + +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_SHIFT (16) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_MASK (0x00010000) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_SHIFT (17) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_MASK (0x00020000) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_SHIFT (18) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_MASK (0x00040000) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_SHIFT (19) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_MASK (0x00080000) + +#define SMU_RESET_WIDE_PORT_QUEUE(peg, wide_port) \ + ((1 << ((wide_port) / 2)) << ((peg) * 2) << 16) + +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_SHIFT (20) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_MASK (0x00100000) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_SHIFT (21) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_MASK (0x00200000) +#define SMU_SOFTRESET_CONTROL_RESET_SCU_SHIFT (22) +#define SMU_SOFTRESET_CONTROL_RESET_SCU_MASK (0x00400000) + +/* + * It seems to make sense that if you are going to reset the protocol + * engine group that you would also reset all of the protocol engines */ +#define SMU_RESET_PROTOCOL_ENGINE_GROUP(peg) \ + (\ + (1 << ((peg) + 20)) \ + | SMU_RESET_WIDE_PORT_QUEUE(peg, 0) \ + | SMU_RESET_WIDE_PORT_QUEUE(peg, 1) \ + | SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \ + ) + +#define SMU_RESET_ALL_PROTOCOL_ENGINE_GROUPS() \ + (\ + SMU_RESET_PROTOCOL_ENGINE_GROUP(0) \ + | SMU_RESET_PROTOCOL_ENGINE_GROUP(1) \ + ) + +#define SMU_RESET_SCU() (0xFFFFFFFF) + + + +/* ***************************************************************************** */ +#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_SHIFT (0) +#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_MASK (0x00000FFF) +#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_SHIFT (16) +#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_MASK (0x0FFF0000) +#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_SHIFT (31) +#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_MASK (0x80000000) +#define SMU_TASK_CONTEXT_ASSIGNMENT_RESERVED_MASK (0x7000F000) + +#define SMU_TCA_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name, value) + +#define SMU_TCA_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name) + +/* ***************************************************************************** */ +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_SHIFT (0) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_MASK (0x00000FFF) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_RESERVED_MASK (0xFFFFF000) + +#define SCU_UFQC_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_ ## name, value) + +#define SCU_UFQC_QUEUE_SIZE_SET(value) \ + SCU_UFQC_GEN_VAL(QUEUE_SIZE, value) + +/* ***************************************************************************** */ +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_SHIFT (0) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_MASK (0x00000FFF) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_SHIFT (12) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_MASK (0x00001000) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_RESERVED_MASK (0xFFFFE000) + +#define SCU_UFQPP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name, value) + +#define SCU_UFQPP_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name) + +/* + * ***************************************************************************** + * * SDMA Registers + * ***************************************************************************** */ +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_SHIFT (0) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_MASK (0x00000FFF) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_SHIFT (12) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_MASK (12) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_SHIFT (31) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_MASK (0x80000000) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_RESERVED_MASK (0x7FFFE000) + +#define SCU_UFQGP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name, value) + +#define SCU_UFQGP_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name) + +#define SCU_UFQGP_CYCLE_BIT(value) \ + SCU_UFQGP_GEN_BIT(CYCLE_BIT, value) + +#define SCU_UFQGP_GET_POINTER(value) \ + SCU_UFQGP_GEN_VALUE(POINTER, value) + +#define SCU_UFQGP_ENABLE(value) \ + (SCU_UFQGP_GEN_BIT(ENABLE) | value) + +#define SCU_UFQGP_DISABLE(value) \ + (~SCU_UFQGP_GEN_BIT(ENABLE) & value) + +#define SCU_UFQGP_VALUE(bit, value) \ + (SCU_UFQGP_CYCLE_BIT(bit) | SCU_UFQGP_GET_POINTER(value)) + +/* ***************************************************************************** */ +#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SHIFT (0) +#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_MASK (0x0000FFFF) +#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT (16) +#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK (0x00010000) +#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_SHIFT (17) +#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_MASK (0x00020000) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_SHIFT (18) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_MASK (0x00040000) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_SHIFT (19) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_MASK (0x00080000) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_SHIFT (20) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_MASK (0x00100000) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_SHIFT (21) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_MASK (0x00200000) +#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_SHIFT (22) +#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_MASK (0x00400000) +#define SCU_PDMA_CONFIGURATION_RESERVED_MASK (0xFF800000) + +#define SCU_PDMACR_GEN_VALUE(name, value) \ + SCU_GEN_VALUE(SCU_PDMA_CONFIGURATION_ ## name, value) + +#define SCU_PDMACR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PDMA_CONFIGURATION_ ## name) + +#define SCU_PDMACR_BE_GEN_BIT(name) \ + SCU_PCMACR_GEN_BIT(BIG_ENDIAN_CONTROL_ ## name) + +/* ***************************************************************************** */ +#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT (8) +#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK (0x00000100) + +#define SCU_CDMACR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_CDMA_CONFIGURATION_ ## name) + +/* + * ***************************************************************************** + * * SCU Link Layer Registers + * ***************************************************************************** */ +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_SHIFT (0) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_MASK (0x000000FF) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_SHIFT (8) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_MASK (0x0000FF00) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_SHIFT (16) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_MASK (0x00FF0000) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_SHIFT (24) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_MASK (0xFF000000) +#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_REQUIRED_MASK (0x00000000) +#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_DEFAULT_MASK (0x7D00676F) +#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_RESERVED_MASK (0x00FF0000) + +#define SCU_SAS_SPDTOV_GEN_VALUE(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_ ## name, value) + + +#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_SHIFT (2) +#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_MASK (0x00000004) +#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_SHIFT (4) +#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_MASK (0x00000010) +#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_SHIFT (5) +#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_MASK (0x00000020) +#define SCU_LINK_STATUS_RESERVED_MASK (0xFFFFFFCD) + +#define SCU_SAS_LLSTA_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_STATUS_ ## name) + + +/* TODO: Where is the SATA_PSELTOV register? */ + +/* + * ***************************************************************************** + * * SCU SAS Maximum Arbitration Wait Time Timeout Register + * ***************************************************************************** */ +#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_SHIFT (0) +#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_MASK (0x00007FFF) +#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_SHIFT (15) +#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_MASK (0x00008000) + +#define SCU_SAS_MAWTTOV_GEN_VALUE(name, value) \ + SCU_GEN_VALUE(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name, value) + +#define SCU_SAS_MAWTTOV_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name) + + +/* + * TODO: Where is the SAS_LNKTOV regsiter? + * TODO: Where is the SAS_PHYTOV register? */ + +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_SHIFT (1) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_MASK (0x00000002) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_SHIFT (2) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_MASK (0x00000004) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_SHIFT (3) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_MASK (0x00000008) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_SHIFT (8) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_MASK (0x00000100) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_SHIFT (9) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_MASK (0x00000200) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_SHIFT (10) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_MASK (0x00000400) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_SHIFT (11) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_MASK (0x00000800) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_SHIFT (16) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_MASK (0x000F0000) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_SHIFT (24) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_MASK (0x0F000000) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_SHIFT (28) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_MASK (0x70000000) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_RESERVED_MASK (0x80F0F1F1) + +#define SCU_SAS_TIID_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name, value) + +#define SCU_SAS_TIID_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name) + +/* SAS Identify Frame PHY Identifier Register */ +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_SHIFT (16) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_MASK (0x00010000) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_SHIFT (17) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_MASK (0x00020000) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_SHIFT (18) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_MASK (0x00040000) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_SHIFT (24) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_MASK (0xFF000000) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_RESERVED_MASK (0x00F800FF) + +#define SCU_SAS_TIPID_GEN_VALUE(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name, value) + +#define SCU_SAS_TIPID_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name) + + +#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_SHIFT (4) +#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_MASK (0x00000010) +#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_SHIFT (6) +#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_MASK (0x00000040) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_SHIFT (7) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_MASK (0x00000080) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_SHIFT (8) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_MASK (0x00000100) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_SHIFT (9) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_MASK (0x00000200) +#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_SHIFT (11) +#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_MASK (0x00000800) +#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_SHIFT (12) +#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_MASK (0x00001000) +#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_SHIFT (13) +#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_MASK (0x00002000) +#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_SHIFT (14) +#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_MASK (0x00004000) +#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_SHIFT (15) +#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_MASK (0x00008000) +#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_SHIFT (23) +#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_MASK (0x00800000) +#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_SHIFT (27) +#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_MASK (0x08000000) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_SHIFT (28) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_MASK (0x10000000) +#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_SHIFT (29) +#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_MASK (0x20000000) +#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_SHIFT (30) +#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_MASK (0x40000000) +#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_SHIFT (31) +#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_MASK (0x80000000) +#define SCU_SAS_PHY_CONFIGURATION_REQUIRED_MASK (0x0100000F) +#define SCU_SAS_PHY_CONFIGURATION_DEFAULT_MASK (0x4180100F) +#define SCU_SAS_PHY_CONFIGURATION_RESERVED_MASK (0x00000000) + +#define SCU_SAS_PCFG_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SAS_PHY_CONFIGURATION_ ## name) + + +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_SHIFT (0) +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_MASK (0x0003FFFF) +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_SHIFT (31) +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_MASK (0x80000000) +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_RESERVED_MASK (0x7FFC0000) + +#define SCU_ENSPINUP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name, value) + +#define SCU_ENSPINUP_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name) + + +#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_SHIFT (1) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_MASK (0x00000002) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_SHIFT (4) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_MASK (0x000000F0) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_SHIFT (8) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_MASK (0x00000100) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_SHIFT (9) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_MASK (0x00000201) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_SHIFT (10) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_MASK (0x00000401) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_SHIFT (11) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_MASK (0x00000801) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_SHIFT (12) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_MASK (0x00001001) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_SHIFT (13) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_MASK (0x00002001) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_SHIFT (31) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_MASK (0x80000000) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_DEFAULT_MASK (0x00003F01) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_REQUIRED_MASK (0x00000001) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_RESERVED_MASK (0x7FFFC00D) + +#define SCU_SAS_PHYCAP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name, value) + +#define SCU_SAS_PHYCAP_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name) + + +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_SHIFT (0) +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_MASK (0x000000FF) +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_SHIFT (31) +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_MASK (0x80000000) +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_RESERVED_MASK (0x7FFFFF00) + +#define SCU_PSZGCR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name, value) + +#define SCU_PSZGCR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name) + +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_SHIFT (1) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_MASK (0x00000002) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_SHIFT (2) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_MASK (0x00000004) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_SHIFT (4) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_MASK (0x00000010) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_SHIFT (5) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_MASK (0x00000020) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_SHIFT (16) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_MASK (0x00030000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_SHIFT (19) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_MASK (0x00080000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_SHIFT (20) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_MASK (0x00300000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_SHIFT (23) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_MASK (0x00800000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_SHIFT (24) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_MASK (0x03000000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_SHIFT (27) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_MASK (0x08000000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_SHIFT (28) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_MASK (0x30000000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_SHIFT (31) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_MASK (0x80000000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_RESERVED_MASK (0x4444FFC9) + +#define SCU_PEG_SCUVZECR_GEN_VAL(name, val) \ + SCU_GEN_VALUE(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name, val) + +#define SCU_PEG_SCUVZECR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name) + + +/* + * ***************************************************************************** + * * Port Task Scheduler registers shift and mask values + * ***************************************************************************** */ +#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_SHIFT (0) +#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_MASK (0x0000FFFF) +#define SCU_PTSG_CONTROL_TASK_TIMEOUT_SHIFT (16) +#define SCU_PTSG_CONTROL_TASK_TIMEOUT_MASK (0x00FF0000) +#define SCU_PTSG_CONTROL_PTSG_ENABLE_SHIFT (24) +#define SCU_PTSG_CONTROL_PTSG_ENABLE_MASK (0x01000000) +#define SCU_PTSG_CONTROL_ETM_ENABLE_SHIFT (25) +#define SCU_PTSG_CONTROL_ETM_ENABLE_MASK (0x02000000) +#define SCU_PTSG_CONTROL_DEFAULT_MASK (0x00020002) +#define SCU_PTSG_CONTROL_REQUIRED_MASK (0x00000000) +#define SCU_PTSG_CONTROL_RESERVED_MASK (0xFC000000) + +#define SCU_PTSGCR_GEN_VAL(name, val) \ + SCU_GEN_VALUE(SCU_PTSG_CONTROL_ ## name, val) + +#define SCU_PTSGCR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PTSG_CONTROL_ ## name) + + +/* ***************************************************************************** */ +#define SCU_PTSG_REAL_TIME_CLOCK_SHIFT (0) +#define SCU_PTSG_REAL_TIME_CLOCK_MASK (0x0000FFFF) +#define SCU_PTSG_REAL_TIME_CLOCK_RESERVED_MASK (0xFFFF0000) + +#define SCU_RTCR_GEN_VAL(name, val) \ + SCU_GEN_VALUE(SCU_PTSG_ ## name, val) + + +#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_SHIFT (0) +#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_MASK (0x00FFFFFF) +#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_RESERVED_MASK (0xFF000000) + +#define SCU_RTCCR_GEN_VAL(name, val) \ + SCU_GEN_VALUE(SCU_PTSG_REAL_TIME_CLOCK_CONTROL_ ## name, val) + + +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_SHIFT (0) +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_MASK (0x00000001) +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_SHIFT (1) +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_MASK (0x00000002) +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_RESERVED_MASK (0xFFFFFFFC) + +#define SCU_PTSxCR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ ## name) + + +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_SHIFT (0) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_MASK (0x00000001) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_SHIFT (1) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_MASK (0x00000002) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_SHIFT (2) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_MASK (0x00000004) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_RESERVED_MASK (0xFFFFFFF8) + +#define SCU_PTSxSR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ ## name) + + +/* + * ***************************************************************************** + * * SGPIO Register shift and mask values + * ***************************************************************************** */ +#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_SHIFT (0) +#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_MASK (0x00000001) +#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_SHIFT (1) +#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_MASK (0x00000002) +#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_SHIFT (2) +#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_MASK (0x00000004) +#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_SHIFT (15) +#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_MASK (0x00008000) +#define SCU_SGPIO_CONTROL_SGPIO_RESERVED_MASK (0xFFFF7FF8) + +#define SCU_SGICRx_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SGPIO_CONTROL_SGPIO_ ## name) + +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_SHIFT (0) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_MASK (0x0000000F) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_SHIFT (4) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_MASK (0x000000F0) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_SHIFT (8) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_MASK (0x00000F00) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_SHIFT (12) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_MASK (0x0000F000) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_RESERVED_MASK (0xFFFF0000) + +#define SCU_SGPBRx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_ ## name, value) + +#define SCU_SGPIO_START_DRIVE_LOWER_R0_SHIFT (0) +#define SCU_SGPIO_START_DRIVE_LOWER_R0_MASK (0x00000003) +#define SCU_SGPIO_START_DRIVE_LOWER_R1_SHIFT (4) +#define SCU_SGPIO_START_DRIVE_LOWER_R1_MASK (0x00000030) +#define SCU_SGPIO_START_DRIVE_LOWER_R2_SHIFT (8) +#define SCU_SGPIO_START_DRIVE_LOWER_R2_MASK (0x00000300) +#define SCU_SGPIO_START_DRIVE_LOWER_R3_SHIFT (12) +#define SCU_SGPIO_START_DRIVE_LOWER_R3_MASK (0x00003000) +#define SCU_SGPIO_START_DRIVE_LOWER_RESERVED_MASK (0xFFFF8888) + +#define SCU_SGSDLRx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value) + +#define SCU_SGPIO_START_DRIVE_UPPER_R0_SHIFT (0) +#define SCU_SGPIO_START_DRIVE_UPPER_R0_MASK (0x00000003) +#define SCU_SGPIO_START_DRIVE_UPPER_R1_SHIFT (4) +#define SCU_SGPIO_START_DRIVE_UPPER_R1_MASK (0x00000030) +#define SCU_SGPIO_START_DRIVE_UPPER_R2_SHIFT (8) +#define SCU_SGPIO_START_DRIVE_UPPER_R2_MASK (0x00000300) +#define SCU_SGPIO_START_DRIVE_UPPER_R3_SHIFT (12) +#define SCU_SGPIO_START_DRIVE_UPPER_R3_MASK (0x00003000) +#define SCU_SGPIO_START_DRIVE_UPPER_RESERVED_MASK (0xFFFF8888) + +#define SCU_SGSDURx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value) + +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_SHIFT (0) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_MASK (0x00000003) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_SHIFT (4) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_MASK (0x00000030) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_SHIFT (8) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_MASK (0x00000300) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_SHIFT (12) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_MASK (0x00003000) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_RESERVED_MASK (0xFFFF8888) + +#define SCU_SGSIDLRx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value) + +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_SHIFT (0) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_MASK (0x00000003) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_SHIFT (4) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_MASK (0x00000030) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_SHIFT (8) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_MASK (0x00000300) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_SHIFT (12) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_MASK (0x00003000) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_RESERVED_MASK (0xFFFF8888) + +#define SCU_SGSIDURx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value) + +#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_SHIFT (0) +#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_MASK (0x0000000F) +#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_RESERVED_MASK (0xFFFFFFF0) + +#define SCU_SGVSCR_GEN_VAL(value) \ + SCU_GEN_VALUE(SCU_SGPIO_VENDOR_SPECIFIC_CODE ## name, value) + +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_SHIFT (0) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_MASK (0x00000003) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_SHIFT (2) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_MASK (0x00000004) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_SHIFT (3) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_MASK (0x00000008) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_SHIFT (4) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_MASK (0x00000030) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_SHIFT (6) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_MASK (0x00000040) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_SHIFT (7) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_MASK (0x00000080) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_SHIFT (8) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_MASK (0x00000300) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_SHIFT (10) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_MASK (0x00000400) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_SHIFT (11) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_MASK (0x00000800) +#define SCU_SGPIO_OUPUT_DATA_SELECT_RESERVED_MASK (0xFFFFF000) + +#define SCU_SGODSR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name, value) + +#define SCU_SGODSR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name) + +/* + * ***************************************************************************** + * * SMU Registers + * ***************************************************************************** */ + +/* + * ---------------------------------------------------------------------------- + * SMU Registers + * These registers are based off of BAR0 + * + * To calculate the offset for other functions use + * BAR0 + FN# * SystemPageSize * 2 + * + * The TCA is only accessable from FN#0 (Physical Function) and each + * is programmed by (BAR0 + SCU_SMU_TCA_OFFSET + (FN# * 0x04)) or + * TCA0 for FN#0 is at BAR0 + 0x0400 + * TCA1 for FN#1 is at BAR0 + 0x0404 + * etc. + * ---------------------------------------------------------------------------- + * Accessable to all FN#s */ +#define SCU_SMU_PCP_OFFSET 0x0000 +#define SCU_SMU_AMR_OFFSET 0x0004 +#define SCU_SMU_ISR_OFFSET 0x0010 +#define SCU_SMU_IMR_OFFSET 0x0014 +#define SCU_SMU_ICC_OFFSET 0x0018 +#define SCU_SMU_HTTLBAR_OFFSET 0x0020 +#define SCU_SMU_HTTUBAR_OFFSET 0x0024 +#define SCU_SMU_TCR_OFFSET 0x0028 +#define SCU_SMU_CQLBAR_OFFSET 0x0030 +#define SCU_SMU_CQUBAR_OFFSET 0x0034 +#define SCU_SMU_CQPR_OFFSET 0x0040 +#define SCU_SMU_CQGR_OFFSET 0x0044 +#define SCU_SMU_CQC_OFFSET 0x0048 +/* Accessable to FN#0 only */ +#define SCU_SMU_RNCLBAR_OFFSET 0x0080 +#define SCU_SMU_RNCUBAR_OFFSET 0x0084 +#define SCU_SMU_DCC_OFFSET 0x0090 +#define SCU_SMU_DFC_OFFSET 0x0094 +#define SCU_SMU_SMUCSR_OFFSET 0x0098 +#define SCU_SMU_SCUSRCR_OFFSET 0x009C +#define SCU_SMU_SMAW_OFFSET 0x00A0 +#define SCU_SMU_SMDW_OFFSET 0x00A4 +/* Accessable to FN#0 only */ +#define SCU_SMU_TCA_OFFSET 0x0400 +/* Accessable to all FN#s */ +#define SCU_SMU_MT_MLAR0_OFFSET 0x2000 +#define SCU_SMU_MT_MUAR0_OFFSET 0x2004 +#define SCU_SMU_MT_MDR0_OFFSET 0x2008 +#define SCU_SMU_MT_VCR0_OFFSET 0x200C +#define SCU_SMU_MT_MLAR1_OFFSET 0x2010 +#define SCU_SMU_MT_MUAR1_OFFSET 0x2014 +#define SCU_SMU_MT_MDR1_OFFSET 0x2018 +#define SCU_SMU_MT_VCR1_OFFSET 0x201C +#define SCU_SMU_MPBA_OFFSET 0x3000 + +/** + * struct smu_registers - These are the SMU registers + * + * + */ +struct smu_registers { +/* 0x0000 PCP */ + u32 post_context_port; +/* 0x0004 AMR */ + u32 address_modifier; + u32 reserved_08; + u32 reserved_0C; +/* 0x0010 ISR */ + u32 interrupt_status; +/* 0x0014 IMR */ + u32 interrupt_mask; +/* 0x0018 ICC */ + u32 interrupt_coalesce_control; + u32 reserved_1C; +/* 0x0020 HTTLBAR */ + u32 host_task_table_lower; +/* 0x0024 HTTUBAR */ + u32 host_task_table_upper; +/* 0x0028 TCR */ + u32 task_context_range; + u32 reserved_2C; +/* 0x0030 CQLBAR */ + u32 completion_queue_lower; +/* 0x0034 CQUBAR */ + u32 completion_queue_upper; + u32 reserved_38; + u32 reserved_3C; +/* 0x0040 CQPR */ + u32 completion_queue_put; +/* 0x0044 CQGR */ + u32 completion_queue_get; +/* 0x0048 CQC */ + u32 completion_queue_control; + u32 reserved_4C; + u32 reserved_5x[4]; + u32 reserved_6x[4]; + u32 reserved_7x[4]; +/* + * Accessable to FN#0 only + * 0x0080 RNCLBAR */ + u32 remote_node_context_lower; +/* 0x0084 RNCUBAR */ + u32 remote_node_context_upper; + u32 reserved_88; + u32 reserved_8C; +/* 0x0090 DCC */ + u32 device_context_capacity; +/* 0x0094 DFC */ + u32 device_function_capacity; +/* 0x0098 SMUCSR */ + u32 control_status; +/* 0x009C SCUSRCR */ + u32 soft_reset_control; +/* 0x00A0 SMAW */ + u32 mmr_address_window; +/* 0x00A4 SMDW */ + u32 mmr_data_window; + u32 reserved_A8; + u32 reserved_AC; +/* A whole bunch of reserved space */ + u32 reserved_Bx[4]; + u32 reserved_Cx[4]; + u32 reserved_Dx[4]; + u32 reserved_Ex[4]; + u32 reserved_Fx[4]; + u32 reserved_1xx[64]; + u32 reserved_2xx[64]; + u32 reserved_3xx[64]; +/* + * Accessable to FN#0 only + * 0x0400 TCA */ + u32 task_context_assignment[256]; +/* MSI-X registers not included */ +}; + +/* + * ***************************************************************************** + * SDMA Registers + * ***************************************************************************** */ +#define SCU_SDMA_BASE 0x6000 +#define SCU_SDMA_PUFATLHAR_OFFSET 0x0000 +#define SCU_SDMA_PUFATUHAR_OFFSET 0x0004 +#define SCU_SDMA_UFLHBAR_OFFSET 0x0008 +#define SCU_SDMA_UFUHBAR_OFFSET 0x000C +#define SCU_SDMA_UFQC_OFFSET 0x0010 +#define SCU_SDMA_UFQPP_OFFSET 0x0014 +#define SCU_SDMA_UFQGP_OFFSET 0x0018 +#define SCU_SDMA_PDMACR_OFFSET 0x001C +#define SCU_SDMA_CDMACR_OFFSET 0x0080 + +/** + * struct scu_sdma_registers - These are the SCU SDMA Registers + * + * + */ +struct scu_sdma_registers { +/* 0x0000 PUFATLHAR */ + u32 uf_address_table_lower; +/* 0x0004 PUFATUHAR */ + u32 uf_address_table_upper; +/* 0x0008 UFLHBAR */ + u32 uf_header_base_address_lower; +/* 0x000C UFUHBAR */ + u32 uf_header_base_address_upper; +/* 0x0010 UFQC */ + u32 unsolicited_frame_queue_control; +/* 0x0014 UFQPP */ + u32 unsolicited_frame_put_pointer; +/* 0x0018 UFQGP */ + u32 unsolicited_frame_get_pointer; +/* 0x001C PDMACR */ + u32 pdma_configuration; +/* Reserved until offset 0x80 */ + u32 reserved_0020_007C[0x18]; +/* 0x0080 CDMACR */ + u32 cdma_configuration; +/* Remainder SDMA register space */ + u32 reserved_0084_0400[0xDF]; + +}; + +/* + * ***************************************************************************** + * * SCU Link Registers + * ***************************************************************************** */ +#define SCU_PEG0_OFFSET 0x0000 +#define SCU_PEG1_OFFSET 0x8000 + +#define SCU_TL0_OFFSET 0x0000 +#define SCU_TL1_OFFSET 0x0400 +#define SCU_TL2_OFFSET 0x0800 +#define SCU_TL3_OFFSET 0x0C00 + +#define SCU_LL_OFFSET 0x0080 +#define SCU_LL0_OFFSET (SCU_TL0_OFFSET + SCU_LL_OFFSET) +#define SCU_LL1_OFFSET (SCU_TL1_OFFSET + SCU_LL_OFFSET) +#define SCU_LL2_OFFSET (SCU_TL2_OFFSET + SCU_LL_OFFSET) +#define SCU_LL3_OFFSET (SCU_TL3_OFFSET + SCU_LL_OFFSET) + +/* Transport Layer Offsets (PEG + TL) */ +#define SCU_TLCR_OFFSET 0x0000 +#define SCU_TLADTR_OFFSET 0x0004 +#define SCU_TLTTMR_OFFSET 0x0008 +#define SCU_TLEECR0_OFFSET 0x000C +#define SCU_STPTLDARNI_OFFSET 0x0010 + + +#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_SHIFT (0) +#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_MASK (0x00000001) +#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_SHIFT (1) +#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_MASK (0x00000002) +#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_SHIFT (3) +#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_MASK (0x00000008) +#define SCU_TLCR_CMD_NAK_STATUS_CODE_SHIFT (4) +#define SCU_TLCR_CMD_NAK_STATUS_CODE_MASK (0x00000010) +#define SCU_TLCR_RESERVED_MASK (0xFFFFFFEB) + +#define SCU_TLCR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_TLCR_ ## name) + +/** + * struct scu_transport_layer_registers - These are the SCU Transport Layer + * registers + * + * + */ +struct scu_transport_layer_registers { + /* 0x0000 TLCR */ + u32 control; + /* 0x0004 TLADTR */ + u32 arbitration_delay_timer; + /* 0x0008 TLTTMR */ + u32 timer_test_mode; + /* 0x000C reserved */ + u32 reserved_0C; + /* 0x0010 STPTLDARNI */ + u32 stp_rni; + /* 0x0014 TLFEWPORCTRL */ + u32 tlfe_wpo_read_control; + /* 0x0018 TLFEWPORDATA */ + u32 tlfe_wpo_read_data; + /* 0x001C RXTLSSCSR1 */ + u32 rxtl_single_step_control_status_1; + /* 0x0020 RXTLSSCSR2 */ + u32 rxtl_single_step_control_status_2; + /* 0x0024 AWTRDDCR */ + u32 tlfe_awt_retry_delay_debug_control; + /* Remainder of TL memory space */ + u32 reserved_0028_007F[0x16]; + +}; + +/* Protocol Engine Group Registers */ +#define SCU_SCUVZECRx_OFFSET 0x1080 + +/* Link Layer Offsets (PEG + TL + LL) */ +#define SCU_SAS_SPDTOV_OFFSET 0x0000 +#define SCU_SAS_LLSTA_OFFSET 0x0004 +#define SCU_SATA_PSELTOV_OFFSET 0x0008 +#define SCU_SAS_TIMETOV_OFFSET 0x0010 +#define SCU_SAS_LOSTOT_OFFSET 0x0014 +#define SCU_SAS_LNKTOV_OFFSET 0x0018 +#define SCU_SAS_PHYTOV_OFFSET 0x001C +#define SCU_SAS_AFERCNT_OFFSET 0x0020 +#define SCU_SAS_WERCNT_OFFSET 0x0024 +#define SCU_SAS_TIID_OFFSET 0x0028 +#define SCU_SAS_TIDNH_OFFSET 0x002C +#define SCU_SAS_TIDNL_OFFSET 0x0030 +#define SCU_SAS_TISSAH_OFFSET 0x0034 +#define SCU_SAS_TISSAL_OFFSET 0x0038 +#define SCU_SAS_TIPID_OFFSET 0x003C +#define SCU_SAS_TIRES2_OFFSET 0x0040 +#define SCU_SAS_ADRSTA_OFFSET 0x0044 +#define SCU_SAS_MAWTTOV_OFFSET 0x0048 +#define SCU_SAS_FRPLDFIL_OFFSET 0x0054 +#define SCU_SAS_RFCNT_OFFSET 0x0060 +#define SCU_SAS_TFCNT_OFFSET 0x0064 +#define SCU_SAS_RFDCNT_OFFSET 0x0068 +#define SCU_SAS_TFDCNT_OFFSET 0x006C +#define SCU_SAS_LERCNT_OFFSET 0x0070 +#define SCU_SAS_RDISERRCNT_OFFSET 0x0074 +#define SCU_SAS_CRERCNT_OFFSET 0x0078 +#define SCU_STPCTL_OFFSET 0x007C +#define SCU_SAS_PCFG_OFFSET 0x0080 +#define SCU_SAS_CLKSM_OFFSET 0x0084 +#define SCU_SAS_TXCOMWAKE_OFFSET 0x0088 +#define SCU_SAS_TXCOMINIT_OFFSET 0x008C +#define SCU_SAS_TXCOMSAS_OFFSET 0x0090 +#define SCU_SAS_COMINIT_OFFSET 0x0094 +#define SCU_SAS_COMWAKE_OFFSET 0x0098 +#define SCU_SAS_COMSAS_OFFSET 0x009C +#define SCU_SAS_SFERCNT_OFFSET 0x00A0 +#define SCU_SAS_CDFERCNT_OFFSET 0x00A4 +#define SCU_SAS_DNFERCNT_OFFSET 0x00A8 +#define SCU_SAS_PRSTERCNT_OFFSET 0x00AC +#define SCU_SAS_CNTCTL_OFFSET 0x00B0 +#define SCU_SAS_SSPTOV_OFFSET 0x00B4 +#define SCU_FTCTL_OFFSET 0x00B8 +#define SCU_FRCTL_OFFSET 0x00BC +#define SCU_FTWMRK_OFFSET 0x00C0 +#define SCU_ENSPINUP_OFFSET 0x00C4 +#define SCU_SAS_TRNTOV_OFFSET 0x00C8 +#define SCU_SAS_PHYCAP_OFFSET 0x00CC +#define SCU_SAS_PHYCTL_OFFSET 0x00D0 +#define SCU_SAS_LLCTL_OFFSET 0x00D8 +#define SCU_AFE_XCVRCR_OFFSET 0x00DC +#define SCU_AFE_LUTCR_OFFSET 0x00E0 + +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_SHIFT (0) +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_MASK (0x00000003) +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 (0) +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 (1) +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3 (2) +#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_SHIFT (2) +#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_MASK (0x000003FC) +#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_SHIFT (16) +#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_MASK (0x00010000) +#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_SHIFT (17) +#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_MASK (0x00020000) +#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_SHIFT (24) +#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_MASK (0xFF000000) +#define SCU_SAS_LINK_LAYER_CONTROL_RESERVED (0x00FCFC00) + +#define SCU_SAS_LLCTL_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SAS_LINK_LAYER_CONTROL_ ## name, value) + +#define SCU_SAS_LLCTL_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SAS_LINK_LAYER_CONTROL_ ## name) + + +/* #define SCU_FRXHECR_DCNT_OFFSET 0x00B0 */ +#define SCU_PSZGCR_OFFSET 0x00E4 +#define SCU_SAS_RECPHYCAP_OFFSET 0x00E8 +/* #define SCU_TX_LUTSEL_OFFSET 0x00B8 */ + +#define SCU_SAS_PTxC_OFFSET 0x00D4 /* Same offset as SAS_TCTSTM */ + +/** + * struct scu_link_layer_registers - SCU Link Layer Registers + * + * + */ +struct scu_link_layer_registers { +/* 0x0000 SAS_SPDTOV */ + u32 speed_negotiation_timers; +/* 0x0004 SAS_LLSTA */ + u32 link_layer_status; +/* 0x0008 SATA_PSELTOV */ + u32 port_selector_timeout; + u32 reserved0C; +/* 0x0010 SAS_TIMETOV */ + u32 timeout_unit_value; +/* 0x0014 SAS_RCDTOV */ + u32 rcd_timeout; +/* 0x0018 SAS_LNKTOV */ + u32 link_timer_timeouts; +/* 0x001C SAS_PHYTOV */ + u32 sas_phy_timeouts; +/* 0x0020 SAS_AFERCNT */ + u32 received_address_frame_error_counter; +/* 0x0024 SAS_WERCNT */ + u32 invalid_dword_counter; +/* 0x0028 SAS_TIID */ + u32 transmit_identification; +/* 0x002C SAS_TIDNH */ + u32 sas_device_name_high; +/* 0x0030 SAS_TIDNL */ + u32 sas_device_name_low; +/* 0x0034 SAS_TISSAH */ + u32 source_sas_address_high; +/* 0x0038 SAS_TISSAL */ + u32 source_sas_address_low; +/* 0x003C SAS_TIPID */ + u32 identify_frame_phy_id; +/* 0x0040 SAS_TIRES2 */ + u32 identify_frame_reserved; +/* 0x0044 SAS_ADRSTA */ + u32 received_address_frame; +/* 0x0048 SAS_MAWTTOV */ + u32 maximum_arbitration_wait_timer_timeout; +/* 0x004C SAS_PTxC */ + u32 transmit_primitive; +/* 0x0050 SAS_RORES */ + u32 error_counter_event_notification_control; +/* 0x0054 SAS_FRPLDFIL */ + u32 frxq_payload_fill_threshold; +/* 0x0058 SAS_LLHANG_TOT */ + u32 link_layer_hang_detection_timeout; + u32 reserved_5C; +/* 0x0060 SAS_RFCNT */ + u32 received_frame_count; +/* 0x0064 SAS_TFCNT */ + u32 transmit_frame_count; +/* 0x0068 SAS_RFDCNT */ + u32 received_dword_count; +/* 0x006C SAS_TFDCNT */ + u32 transmit_dword_count; +/* 0x0070 SAS_LERCNT */ + u32 loss_of_sync_error_count; +/* 0x0074 SAS_RDISERRCNT */ + u32 running_disparity_error_count; +/* 0x0078 SAS_CRERCNT */ + u32 received_frame_crc_error_count; +/* 0x007C STPCTL */ + u32 stp_control; +/* 0x0080 SAS_PCFG */ + u32 phy_configuration; +/* 0x0084 SAS_CLKSM */ + u32 clock_skew_management; +/* 0x0088 SAS_TXCOMWAKE */ + u32 transmit_comwake_signal; +/* 0x008C SAS_TXCOMINIT */ + u32 transmit_cominit_signal; +/* 0x0090 SAS_TXCOMSAS */ + u32 transmit_comsas_signal; +/* 0x0094 SAS_COMINIT */ + u32 cominit_control; +/* 0x0098 SAS_COMWAKE */ + u32 comwake_control; +/* 0x009C SAS_COMSAS */ + u32 comsas_control; +/* 0x00A0 SAS_SFERCNT */ + u32 received_short_frame_count; +/* 0x00A4 SAS_CDFERCNT */ + u32 received_frame_without_credit_count; +/* 0x00A8 SAS_DNFERCNT */ + u32 received_frame_after_done_count; +/* 0x00AC SAS_PRSTERCNT */ + u32 phy_reset_problem_count; +/* 0x00B0 SAS_CNTCTL */ + u32 counter_control; +/* 0x00B4 SAS_SSPTOV */ + u32 ssp_timer_timeout_values; +/* 0x00B8 FTCTL */ + u32 ftx_control; +/* 0x00BC FRCTL */ + u32 frx_control; +/* 0x00C0 FTWMRK */ + u32 ftx_watermark; +/* 0x00C4 ENSPINUP */ + u32 notify_enable_spinup_control; +/* 0x00C8 SAS_TRNTOV */ + u32 sas_training_sequence_timer_values; +/* 0x00CC SAS_PHYCAP */ + u32 phy_capabilities; +/* 0x00D0 SAS_PHYCTL */ + u32 phy_control; + u32 reserved_d4; +/* 0x00D8 LLCTL */ + u32 link_layer_control; +/* 0x00DC AFE_XCVRCR */ + u32 afe_xcvr_control; +/* 0x00E0 AFE_LUTCR */ + u32 afe_lookup_table_control; +/* 0x00E4 PSZGCR */ + u32 phy_source_zone_group_control; +/* 0x00E8 SAS_RECPHYCAP */ + u32 receive_phycap; + u32 reserved_ec; +/* 0x00F0 SNAFERXRSTCTL */ + u32 speed_negotiation_afe_rx_reset_control; +/* 0x00F4 SAS_SSIPMCTL */ + u32 power_management_control; +/* 0x00F8 SAS_PSPREQ_PRIM */ + u32 sas_pm_partial_request_primitive; +/* 0x00FC SAS_PSSREQ_PRIM */ + u32 sas_pm_slumber_request_primitive; +/* 0x0100 SAS_PPSACK_PRIM */ + u32 sas_pm_ack_primitive_register; +/* 0x0104 SAS_PSNAK_PRIM */ + u32 sas_pm_nak_primitive_register; +/* 0x0108 SAS_SSIPMTOV */ + u32 sas_primitive_timeout; + u32 reserved_10c; +/* 0x0110 - 0x011C PLAPRDCTRLxREG */ + u32 pla_product_control[4]; +/* 0x0120 PLAPRDSUMREG */ + u32 pla_product_sum; +/* 0x0124 PLACONTROLREG */ + u32 pla_control; +/* Remainder of memory space 896 bytes */ + u32 reserved_0128_037f[0x96]; + +}; + +/* + * 0x00D4 // Same offset as SAS_TCTSTM SAS_PTxC + * u32 primitive_transmit_control; */ + +/* + * ---------------------------------------------------------------------------- + * SGPIO + * ---------------------------------------------------------------------------- */ +#define SCU_SGPIO_OFFSET 0x1400 + +/* #define SCU_SGPIO_OFFSET 0x6000 // later moves to 0x1400 see HSD 652625 */ +#define SCU_SGPIO_SGICR_OFFSET 0x0000 +#define SCU_SGPIO_SGPBR_OFFSET 0x0004 +#define SCU_SGPIO_SGSDLR_OFFSET 0x0008 +#define SCU_SGPIO_SGSDUR_OFFSET 0x000C +#define SCU_SGPIO_SGSIDLR_OFFSET 0x0010 +#define SCU_SGPIO_SGSIDUR_OFFSET 0x0014 +#define SCU_SGPIO_SGVSCR_OFFSET 0x0018 +/* Address from 0x0820 to 0x083C */ +#define SCU_SGPIO_SGODSR_OFFSET 0x0020 + +/** + * struct scu_sgpio_registers - SCU SGPIO Registers + * + * + */ +struct scu_sgpio_registers { +/* 0x0000 SGPIO_SGICR */ + u32 interface_control; +/* 0x0004 SGPIO_SGPBR */ + u32 blink_rate; +/* 0x0008 SGPIO_SGSDLR */ + u32 start_drive_lower; +/* 0x000C SGPIO_SGSDUR */ + u32 start_drive_upper; +/* 0x0010 SGPIO_SGSIDLR */ + u32 serial_input_lower; +/* 0x0014 SGPIO_SGSIDUR */ + u32 serial_input_upper; +/* 0x0018 SGPIO_SGVSCR */ + u32 vendor_specific_code; +/* 0x0020 SGPIO_SGODSR */ + u32 ouput_data_select[8]; +/* Remainder of memory space 256 bytes */ + u32 reserved_1444_14ff[0x31]; + +}; + +/* + * ***************************************************************************** + * * Defines for VIIT entry offsets + * * Access additional entries by SCU_VIIT_BASE + index * 0x10 + * ***************************************************************************** */ +#define SCU_VIIT_BASE 0x1c00 + +struct SCU_VIIT_REGISTERS { + u32 registers[256]; +}; + +/* + * ***************************************************************************** + * * SCU PORT TASK SCHEDULER REGISTERS + * ***************************************************************************** */ + +#define SCU_PTSG_BASE 0x1000 + +#define SCU_PTSG_PTSGCR_OFFSET 0x0000 +#define SCU_PTSG_RTCR_OFFSET 0x0004 +#define SCU_PTSG_RTCCR_OFFSET 0x0008 +#define SCU_PTSG_PTS0CR_OFFSET 0x0010 +#define SCU_PTSG_PTS0SR_OFFSET 0x0014 +#define SCU_PTSG_PTS1CR_OFFSET 0x0018 +#define SCU_PTSG_PTS1SR_OFFSET 0x001C +#define SCU_PTSG_PTS2CR_OFFSET 0x0020 +#define SCU_PTSG_PTS2SR_OFFSET 0x0024 +#define SCU_PTSG_PTS3CR_OFFSET 0x0028 +#define SCU_PTSG_PTS3SR_OFFSET 0x002C +#define SCU_PTSG_PCSPE0CR_OFFSET 0x0030 +#define SCU_PTSG_PCSPE1CR_OFFSET 0x0034 +#define SCU_PTSG_PCSPE2CR_OFFSET 0x0038 +#define SCU_PTSG_PCSPE3CR_OFFSET 0x003C +#define SCU_PTSG_ETMTSCCR_OFFSET 0x0040 +#define SCU_PTSG_ETMRNSCCR_OFFSET 0x0044 + +/** + * struct scu_port_task_scheduler_registers - These are the control/stats pairs + * for each Port Task Scheduler. + * + * + */ +struct scu_port_task_scheduler_registers { + u32 control; + u32 status; +}; + +typedef u32 SCU_PORT_PE_CONFIGURATION_REGISTER_T; + +/** + * struct scu_port_task_scheduler_group_registers - These are the PORT Task + * Scheduler registers + * + * + */ +struct scu_port_task_scheduler_group_registers { +/* 0x0000 PTSGCR */ + u32 control; +/* 0x0004 RTCR */ + u32 real_time_clock; +/* 0x0008 RTCCR */ + u32 real_time_clock_control; +/* 0x000C */ + u32 reserved_0C; +/* + * 0x0010 PTS0CR + * 0x0014 PTS0SR + * 0x0018 PTS1CR + * 0x001C PTS1SR + * 0x0020 PTS2CR + * 0x0024 PTS2SR + * 0x0028 PTS3CR + * 0x002C PTS3SR */ + struct scu_port_task_scheduler_registers port[4]; +/* + * 0x0030 PCSPE0CR + * 0x0034 PCSPE1CR + * 0x0038 PCSPE2CR + * 0x003C PCSPE3CR */ + SCU_PORT_PE_CONFIGURATION_REGISTER_T protocol_engine[4]; +/* 0x0040 ETMTSCCR */ + u32 tc_scanning_interval_control; +/* 0x0044 ETMRNSCCR */ + u32 rnc_scanning_interval_control; +/* Remainder of memory space 128 bytes */ + u32 reserved_1048_107f[0x0E]; + +}; + +#define SCU_PTSG_SCUVZECR_OFFSET 0x003C + +/* + * ***************************************************************************** + * * AFE REGISTERS + * ***************************************************************************** */ +#define SCU_AFE_MMR_BASE 0xE000 + +/* + * AFE 0 is at offset 0x0800 + * AFE 1 is at offset 0x0900 + * AFE 2 is at offset 0x0a00 + * AFE 3 is at offset 0x0b00 */ +struct scu_afe_transceiver { + /* 0x0000 AFE_XCVR_CTRL0 */ + u32 afe_xcvr_control0; + /* 0x0004 AFE_XCVR_CTRL1 */ + u32 afe_xcvr_control1; + /* 0x0008 */ + u32 reserved_0008; + /* 0x000c afe_dfx_rx_control0 */ + u32 afe_dfx_rx_control0; + /* 0x0010 AFE_DFX_RX_CTRL1 */ + u32 afe_dfx_rx_control1; + /* 0x0014 */ + u32 reserved_0014; + /* 0x0018 AFE_DFX_RX_STS0 */ + u32 afe_dfx_rx_status0; + /* 0x001c AFE_DFX_RX_STS1 */ + u32 afe_dfx_rx_status1; + /* 0x0020 */ + u32 reserved_0020; + /* 0x0024 AFE_TX_CTRL */ + u32 afe_tx_control; + /* 0x0028 AFE_TX_AMP_CTRL0 */ + u32 afe_tx_amp_control0; + /* 0x002c AFE_TX_AMP_CTRL1 */ + u32 afe_tx_amp_control1; + /* 0x0030 AFE_TX_AMP_CTRL2 */ + u32 afe_tx_amp_control2; + /* 0x0034 AFE_TX_AMP_CTRL3 */ + u32 afe_tx_amp_control3; + /* 0x0038 afe_tx_ssc_control */ + u32 afe_tx_ssc_control; + /* 0x003c */ + u32 reserved_003c; + /* 0x0040 AFE_RX_SSC_CTRL0 */ + u32 afe_rx_ssc_control0; + /* 0x0044 AFE_RX_SSC_CTRL1 */ + u32 afe_rx_ssc_control1; + /* 0x0048 AFE_RX_SSC_CTRL2 */ + u32 afe_rx_ssc_control2; + /* 0x004c AFE_RX_EQ_STS0 */ + u32 afe_rx_eq_status0; + /* 0x0050 AFE_RX_EQ_STS1 */ + u32 afe_rx_eq_status1; + /* 0x0054 AFE_RX_CDR_STS */ + u32 afe_rx_cdr_status; + /* 0x0058 */ + u32 reserved_0058; + /* 0x005c AFE_CHAN_CTRL */ + u32 afe_channel_control; + /* 0x0060-0x006c */ + u32 reserved_0060_006c[0x04]; + /* 0x0070 AFE_XCVR_EC_STS0 */ + u32 afe_xcvr_error_capture_status0; + /* 0x0074 AFE_XCVR_EC_STS1 */ + u32 afe_xcvr_error_capture_status1; + /* 0x0078 AFE_XCVR_EC_STS2 */ + u32 afe_xcvr_error_capture_status2; + /* 0x007c afe_xcvr_ec_status3 */ + u32 afe_xcvr_error_capture_status3; + /* 0x0080 AFE_XCVR_EC_STS4 */ + u32 afe_xcvr_error_capture_status4; + /* 0x0084 AFE_XCVR_EC_STS5 */ + u32 afe_xcvr_error_capture_status5; + /* 0x0088-0x00fc */ + u32 reserved_008c_00fc[0x1e]; +}; + +/** + * struct scu_afe_registers - AFE Regsiters + * + * + */ +/* Uaoa AFE registers */ +struct scu_afe_registers { + /* 0Xe000 AFE_BIAS_CTRL */ + u32 afe_bias_control; + u32 reserved_0004; + /* 0x0008 AFE_PLL_CTRL0 */ + u32 afe_pll_control0; + /* 0x000c AFE_PLL_CTRL1 */ + u32 afe_pll_control1; + /* 0x0010 AFE_PLL_CTRL2 */ + u32 afe_pll_control2; + /* 0x0014 AFE_CB_STS */ + u32 afe_common_block_status; + /* 0x0018-0x007c */ + u32 reserved_18_7c[0x1a]; + /* 0x0080 AFE_PMSN_MCTRL0 */ + u32 afe_pmsn_master_control0; + /* 0x0084 AFE_PMSN_MCTRL1 */ + u32 afe_pmsn_master_control1; + /* 0x0088 AFE_PMSN_MCTRL2 */ + u32 afe_pmsn_master_control2; + /* 0x008C-0x00fc */ + u32 reserved_008c_00fc[0x1D]; + /* 0x0100 AFE_DFX_MST_CTRL0 */ + u32 afe_dfx_master_control0; + /* 0x0104 AFE_DFX_MST_CTRL1 */ + u32 afe_dfx_master_control1; + /* 0x0108 AFE_DFX_DCL_CTRL */ + u32 afe_dfx_dcl_control; + /* 0x010c AFE_DFX_DMON_CTRL */ + u32 afe_dfx_digital_monitor_control; + /* 0x0110 AFE_DFX_AMONP_CTRL */ + u32 afe_dfx_analog_p_monitor_control; + /* 0x0114 AFE_DFX_AMONN_CTRL */ + u32 afe_dfx_analog_n_monitor_control; + /* 0x0118 AFE_DFX_NTL_STS */ + u32 afe_dfx_ntl_status; + /* 0x011c AFE_DFX_FIFO_STS0 */ + u32 afe_dfx_fifo_status0; + /* 0x0120 AFE_DFX_FIFO_STS1 */ + u32 afe_dfx_fifo_status1; + /* 0x0124 AFE_DFX_MPAT_CTRL */ + u32 afe_dfx_master_pattern_control; + /* 0x0128 AFE_DFX_P0_CTRL */ + u32 afe_dfx_p0_control; + /* 0x012c-0x01a8 AFE_DFX_P0_DRx */ + u32 afe_dfx_p0_data[32]; + /* 0x01ac */ + u32 reserved_01ac; + /* 0x01b0-0x020c AFE_DFX_P0_IRx */ + u32 afe_dfx_p0_instruction[24]; + /* 0x0210 */ + u32 reserved_0210; + /* 0x0214 AFE_DFX_P1_CTRL */ + u32 afe_dfx_p1_control; + /* 0x0218-0x245 AFE_DFX_P1_DRx */ + u32 afe_dfx_p1_data[16]; + /* 0x0258-0x029c */ + u32 reserved_0258_029c[0x12]; + /* 0x02a0-0x02bc AFE_DFX_P1_IRx */ + u32 afe_dfx_p1_instruction[8]; + /* 0x02c0-0x2fc */ + u32 reserved_02c0_02fc[0x10]; + /* 0x0300 AFE_DFX_TX_PMSN_CTRL */ + u32 afe_dfx_tx_pmsn_control; + /* 0x0304 AFE_DFX_RX_PMSN_CTRL */ + u32 afe_dfx_rx_pmsn_control; + u32 reserved_0308; + /* 0x030c AFE_DFX_NOA_CTRL0 */ + u32 afe_dfx_noa_control0; + /* 0x0310 AFE_DFX_NOA_CTRL1 */ + u32 afe_dfx_noa_control1; + /* 0x0314 AFE_DFX_NOA_CTRL2 */ + u32 afe_dfx_noa_control2; + /* 0x0318 AFE_DFX_NOA_CTRL3 */ + u32 afe_dfx_noa_control3; + /* 0x031c AFE_DFX_NOA_CTRL4 */ + u32 afe_dfx_noa_control4; + /* 0x0320 AFE_DFX_NOA_CTRL5 */ + u32 afe_dfx_noa_control5; + /* 0x0324 AFE_DFX_NOA_CTRL6 */ + u32 afe_dfx_noa_control6; + /* 0x0328 AFE_DFX_NOA_CTRL7 */ + u32 afe_dfx_noa_control7; + /* 0x032c-0x07fc */ + u32 reserved_032c_07fc[0x135]; + + /* 0x0800-0x0bfc */ + struct scu_afe_transceiver scu_afe_xcvr[4]; + + /* 0x0c00-0x0ffc */ + u32 reserved_0c00_0ffc[0x0100]; +}; + +struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS { + u32 table[0xE0]; +}; + + +struct SCU_VIIT_IIT { + u32 table[256]; +}; + +/** + * Placeholder for the ZONE Partition Table information ZONING will not be + * included in the 1.1 release. + * + * + */ +struct SCU_ZONE_PARTITION_TABLE { + u32 table[2048]; +}; + +/** + * Placeholder for the CRAM register since I am not sure if we need to + * read/write to these registers as yet. + * + * + */ +struct SCU_COMPLETION_RAM { + u32 ram[128]; +}; + +/** + * Placeholder for the FBRAM registers since I am not sure if we need to + * read/write to these registers as yet. + * + * + */ +struct SCU_FRAME_BUFFER_RAM { + u32 ram[128]; +}; + +#define SCU_SCRATCH_RAM_SIZE_IN_DWORDS 256 + +/** + * Placeholder for the scratch RAM registers. + * + * + */ +struct SCU_SCRATCH_RAM { + u32 ram[SCU_SCRATCH_RAM_SIZE_IN_DWORDS]; +}; + +/** + * Placeholder since I am not yet sure what these registers are here for. + * + * + */ +struct NOA_PROTOCOL_ENGINE_PARTITION { + u32 reserved[64]; +}; + +/** + * Placeholder since I am not yet sure what these registers are here for. + * + * + */ +struct NOA_HUB_PARTITION { + u32 reserved[64]; +}; + +/** + * Placeholder since I am not yet sure what these registers are here for. + * + * + */ +struct NOA_HOST_INTERFACE_PARTITION { + u32 reserved[64]; +}; + +/** + * struct TRANSPORT_LINK_LAYER_PAIR - The SCU Hardware pairs up the TL + * registers with the LL registers so we must place them adjcent to make the + * array of registers in the PEG. + * + * + */ +struct TRANSPORT_LINK_LAYER_PAIR { + struct scu_transport_layer_registers tl; + struct scu_link_layer_registers ll; +}; + +/** + * struct SCU_PEG_REGISTERS - SCU Protocol Engine Memory mapped register space. + * These registers are unique to each protocol engine group. There can be + * at most two PEG for a single SCU part. + * + * + */ +struct SCU_PEG_REGISTERS { + struct TRANSPORT_LINK_LAYER_PAIR pe[4]; + struct scu_port_task_scheduler_group_registers ptsg; + struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS peg; + struct scu_sgpio_registers sgpio; + u32 reserved_01500_1BFF[0x1C0]; + struct scu_viit_entry viit[64]; + struct SCU_ZONE_PARTITION_TABLE zpt0; + struct SCU_ZONE_PARTITION_TABLE zpt1; +}; + +/** + * struct scu_registers - SCU regsiters including both PEG registers if we turn + * on that compile option. All of these registers are in the memory mapped + * space returned from BAR1. + * + * + */ +struct scu_registers { + /* 0x0000 - PEG 0 */ + struct SCU_PEG_REGISTERS peg0; + + /* 0x6000 - SDMA and Miscellaneous */ + struct scu_sdma_registers sdma; + struct SCU_COMPLETION_RAM cram; + struct SCU_FRAME_BUFFER_RAM fbram; + u32 reserved_6800_69FF[0x80]; + struct NOA_PROTOCOL_ENGINE_PARTITION noa_pe; + struct NOA_HUB_PARTITION noa_hub; + struct NOA_HOST_INTERFACE_PARTITION noa_if; + u32 reserved_6d00_7fff[0x4c0]; + + /* 0x8000 - PEG 1 */ + struct SCU_PEG_REGISTERS peg1; + + /* 0xE000 - AFE Registers */ + struct scu_afe_registers afe; + + /* 0xF000 - reserved */ + u32 reserved_f000_211fff[0x80c00]; + + /* 0x212000 - scratch RAM */ + struct SCU_SCRATCH_RAM scratch_ram; + +}; + + +#endif /* _SCU_REGISTERS_HEADER_ */ diff --git a/drivers/scsi/isci/core/scu_remote_node_context.h b/drivers/scsi/isci/core/scu_remote_node_context.h new file mode 100644 index 000000000000..8006f2ee2d1d --- /dev/null +++ b/drivers/scsi/isci/core/scu_remote_node_context.h @@ -0,0 +1,230 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCU_REMOTE_NODE_CONTEXT_HEADER__ +#define __SCU_REMOTE_NODE_CONTEXT_HEADER__ + +/** + * This file contains the structures and constatns used by the SCU hardware to + * describe a remote node context. + * + * + */ +#include "sci_types.h" + +/** + * struct ssp_remote_node_context - This structure contains the SCU hardware + * definition for an SSP remote node. + * + * + */ +struct ssp_remote_node_context { + /* WORD 0 */ + + /** + * This field is the remote node index assigned for this remote node. All + * remote nodes must have a unique remote node index. The value of the remote + * node index can not exceed the maximum number of remote nodes reported in + * the SCU device context capacity register. + */ + u32 remote_node_index:12; + u32 reserved0_1:4; + + /** + * This field tells the SCU hardware how many simultaneous connections that + * this remote node will support. + */ + u32 remote_node_port_width:4; + + /** + * This field tells the SCU hardware which logical port to associate with this + * remote node. + */ + u32 logical_port_index:3; + u32 reserved0_2:5; + + /** + * This field will enable the I_T nexus loss timer for this remote node. + */ + u32 nexus_loss_timer_enable:1; + + /** + * This field is the for driver debug only and is not used. + */ + u32 check_bit:1; + + /** + * This field must be set to true when the hardware DMAs the remote node + * context to the hardware SRAM. When the remote node is being invalidated + * this field must be set to false. + */ + u32 is_valid:1; + + /** + * This field must be set to true. + */ + u32 is_remote_node_context:1; + + /* WORD 1 - 2 */ + + /** + * This is the low word of the remote device SAS Address + */ + u32 remote_sas_address_lo; + + /** + * This field is the high word of the remote device SAS Address + */ + u32 remote_sas_address_hi; + + /* WORD 3 */ + /** + * This field reprensets the function number assigned to this remote device. + * This value must match the virtual function number that is being used to + * communicate to the device. + */ + u32 function_number:8; + u32 reserved3_1:8; + + /** + * This field provides the driver a way to cheat on the arbitration wait time + * for this remote node. + */ + u32 arbitration_wait_time:16; + + /* WORD 4 */ + /** + * This field tells the SCU hardware how long this device may occupy the + * connection before it must be closed. + */ + u32 connection_occupancy_timeout:16; + + /** + * This field tells the SCU hardware how long to maintain a connection when + * there are no frames being transmitted on the link. + */ + u32 connection_inactivity_timeout:16; + + /* WORD 5 */ + /** + * This field allows the driver to cheat on the arbitration wait time for this + * remote node. + */ + u32 initial_arbitration_wait_time:16; + + /** + * This field is tells the hardware what to program for the connection rate in + * the open address frame. See the SAS spec for valid values. + */ + u32 oaf_connection_rate:4; + + /** + * This field tells the SCU hardware what to program for the features in the + * open address frame. See the SAS spec for valid values. + */ + u32 oaf_features:4; + + /** + * This field tells the SCU hardware what to use for the source zone group in + * the open address frame. See the SAS spec for more details on zoning. + */ + u32 oaf_source_zone_group:8; + + /* WORD 6 */ + /** + * This field tells the SCU hardware what to use as the more capibilities in + * the open address frame. See the SAS Spec for details. + */ + u32 oaf_more_compatibility_features; + + /* WORD 7 */ + u32 reserved7; + +}; + +/** + * struct stp_remote_node_context - This structure contains the SCU hardware + * definition for a STP remote node. + * + * STP Targets are not yet supported so this definition is a placeholder until + * we do support them. + */ +struct stp_remote_node_context { + /** + * Placeholder data for the STP remote node. + */ + u32 data[8]; + +}; + +/** + * This union combines the SAS and SATA remote node definitions. + * + * union scu_remote_node_context + */ +union scu_remote_node_context { + /** + * SSP Remote Node + */ + struct ssp_remote_node_context ssp; + + /** + * STP Remote Node + */ + struct stp_remote_node_context stp; + +}; + +#endif /* __SCU_REMOTE_NODE_CONTEXT_HEADER__ */ diff --git a/drivers/scsi/isci/core/scu_task_context.h b/drivers/scsi/isci/core/scu_task_context.h new file mode 100644 index 000000000000..d08c51bb2262 --- /dev/null +++ b/drivers/scsi/isci/core/scu_task_context.h @@ -0,0 +1,943 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCU_TASK_CONTEXT_H_ +#define _SCU_TASK_CONTEXT_H_ + +/** + * This file contains the structures and constants for the SCU hardware task + * context. + * + * + */ + +#include "sci_types.h" + +/** + * enum SCU_SSP_TASK_TYPE - This enumberation defines the various SSP task + * types the SCU hardware will accept. The definition for the various task + * types the SCU hardware will accept can be found in the DS specification. + * + * + */ +typedef enum { + SCU_TASK_TYPE_IOREAD, /* /< IO READ direction or no direction */ + SCU_TASK_TYPE_IOWRITE, /* /< IO Write direction */ + SCU_TASK_TYPE_SMP_REQUEST, /* /< SMP Request type */ + SCU_TASK_TYPE_RESPONSE, /* /< Driver generated response frame (targt mode) */ + SCU_TASK_TYPE_RAW_FRAME, /* /< Raw frame request type */ + SCU_TASK_TYPE_PRIMITIVE /* /< Request for a primitive to be transmitted */ +} SCU_SSP_TASK_TYPE; + +/** + * enum SCU_SATA_TASK_TYPE - This enumeration defines the various SATA task + * types the SCU hardware will accept. The definition for the various task + * types the SCU hardware will accept can be found in the DS specification. + * + * + */ +typedef enum { + SCU_TASK_TYPE_DMA_IN, /* /< Read request */ + SCU_TASK_TYPE_FPDMAQ_READ, /* /< NCQ read request */ + SCU_TASK_TYPE_PACKET_DMA_IN, /* /< Packet read request */ + SCU_TASK_TYPE_SATA_RAW_FRAME, /* /< Raw frame request */ + RESERVED_4, + RESERVED_5, + RESERVED_6, + RESERVED_7, + SCU_TASK_TYPE_DMA_OUT, /* /< Write request */ + SCU_TASK_TYPE_FPDMAQ_WRITE, /* /< NCQ write Request */ + SCU_TASK_TYPE_PACKET_DMA_OUT /* /< Packet write request */ +} SCU_SATA_TASK_TYPE; + + +/** + * + * + * SCU_CONTEXT_TYPE + */ +#define SCU_TASK_CONTEXT_TYPE 0 +#define SCU_RNC_CONTEXT_TYPE 1 + +/** + * + * + * SCU_TASK_CONTEXT_VALIDITY + */ +#define SCU_TASK_CONTEXT_INVALID 0 +#define SCU_TASK_CONTEXT_VALID 1 + +/** + * + * + * SCU_COMMAND_CODE + */ +#define SCU_COMMAND_CODE_INITIATOR_NEW_TASK 0 +#define SCU_COMMAND_CODE_ACTIVE_TASK 1 +#define SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK 2 +#define SCU_COMMAND_CODE_TARGET_RAW_FRAMES 3 + +/** + * + * + * SCU_TASK_PRIORITY + */ +/** + * + * + * This priority is used when there is no priority request for this request. + */ +#define SCU_TASK_PRIORITY_NORMAL 0 + +/** + * + * + * This priority indicates that the task should be scheduled to the head of the + * queue. The task will NOT be executed if the TX is suspended for the remote + * node. + */ +#define SCU_TASK_PRIORITY_HEAD_OF_Q 1 + +/** + * + * + * This priority indicates that the task will be executed before all + * SCU_TASK_PRIORITY_NORMAL and SCU_TASK_PRIORITY_HEAD_OF_Q tasks. The task + * WILL be executed if the TX is suspended for the remote node. + */ +#define SCU_TASK_PRIORITY_HIGH 2 + +/** + * + * + * This task priority is reserved and should not be used. + */ +#define SCU_TASK_PRIORITY_RESERVED 3 + +#define SCU_TASK_INITIATOR_MODE 1 +#define SCU_TASK_TARGET_MODE 0 + +#define SCU_TASK_REGULAR 0 +#define SCU_TASK_ABORTED 1 + +/* direction bit defintion */ +/** + * + * + * SATA_DIRECTION + */ +#define SCU_SATA_WRITE_DATA_DIRECTION 0 +#define SCU_SATA_READ_DATA_DIRECTION 1 + +/** + * + * + * SCU_COMMAND_CONTEXT_MACROS These macros provide the mask and shift + * operations to construct the various SCU commands + */ +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT 21 +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK 0x00E00000 +#define scu_get_command_request_type(x) \ + ((x) & SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK) + +#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT 18 +#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK 0x001C0000 +#define scu_get_command_request_subtype(x) \ + ((x) & SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK) + +#define SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK \ + (\ + SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK \ + | SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK \ + ) +#define scu_get_command_request_full_type(x) \ + ((x) & SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK) + +#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 16 +#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK 0x00010000 +#define scu_get_command_protocl_engine_group(x) \ + ((x) & SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK) + +#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 12 +#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK 0x00007000 +#define scu_get_command_reqeust_logical_port(x) \ + ((x) & SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK) + + +#define MAKE_SCU_CONTEXT_COMMAND_TYPE(type) \ + ((u32)(type) << SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT) + +/** + * MAKE_SCU_CONTEXT_COMMAND_TYPE() - + * + * SCU_COMMAND_TYPES These constants provide the grouping of the different SCU + * command types. + */ +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(0) +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(1) +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(2) +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(3) +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(6) + +#define MAKE_SCU_CONTEXT_COMMAND_REQUEST(type, command) \ + ((type) | ((command) << SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT)) + +/** + * + * + * SCU_REQUEST_TYPES These constants are the various request types that can be + * posted to the SCU hardware. + */ +#define SCU_CONTEXT_COMMAND_REQUST_POST_TC \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 0)) + +#define SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 1)) + +#define SCU_CONTEXT_COMMAND_REQUST_DUMP_TC \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC, 0)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_32 \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 0)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_96 \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 1)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 2)) + +#define SCU_CONTEXT_COMMAND_DUMP_RNC_32 \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 0)) + +#define SCU_CONTEXT_COMMAND_DUMP_RNC_96 \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 1)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 0)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 1)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_RESUME \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 2)) + +#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_ENABLE \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 3)) + +#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_DISABLE \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 4)) + +/** + * + * + * SCU_TASK_CONTEXT_PROTOCOL SCU Task context protocol types this is uesd to + * program the SCU Task context protocol field in word 0x00. + */ +#define SCU_TASK_CONTEXT_PROTOCOL_SMP 0x00 +#define SCU_TASK_CONTEXT_PROTOCOL_SSP 0x01 +#define SCU_TASK_CONTEXT_PROTOCOL_STP 0x02 +#define SCU_TASK_CONTEXT_PROTOCOL_NONE 0x07 + +/** + * struct SSP_TASK_CONTEXT - This is the SCU hardware definition for an SSP + * request. + * + * + */ +struct SSP_TASK_CONTEXT { + /* OFFSET 0x18 */ + u32 reserved00:24; + u32 frame_type:8; + + /* OFFSET 0x1C */ + u32 reserved01; + + /* OFFSET 0x20 */ + u32 fill_bytes:2; + u32 reserved02:6; + u32 changing_data_pointer:1; + u32 retransmit:1; + u32 retry_data_frame:1; + u32 tlr_control:2; + u32 reserved03:19; + + /* OFFSET 0x24 */ + u32 uiRsvd4; + + /* OFFSET 0x28 */ + u32 target_port_transfer_tag:16; + u32 tag:16; + + /* OFFSET 0x2C */ + u32 data_offset; +}; + +/** + * struct STP_TASK_CONTEXT - This is the SCU hardware definition for an STP + * request. + * + * + */ +struct STP_TASK_CONTEXT { + /* OFFSET 0x18 */ + u32 fis_type:8; + u32 pm_port:4; + u32 reserved0:3; + u32 control:1; + u32 command:8; + u32 features:8; + + /* OFFSET 0x1C */ + u32 reserved1; + + /* OFFSET 0x20 */ + u32 reserved2; + + /* OFFSET 0x24 */ + u32 reserved3; + + /* OFFSET 0x28 */ + u32 ncq_tag:5; + u32 reserved4:27; + + /* OFFSET 0x2C */ + u32 data_offset; /* TODO: What is this used for? */ +}; + +/** + * struct SMP_TASK_CONTEXT - This is the SCU hardware definition for an SMP + * request. + * + * + */ +struct SMP_TASK_CONTEXT { + /* OFFSET 0x18 */ + u32 response_length:8; + u32 function_result:8; + u32 function:8; + u32 frame_type:8; + + /* OFFSET 0x1C */ + u32 smp_response_ufi:12; + u32 reserved1:20; + + /* OFFSET 0x20 */ + u32 reserved2; + + /* OFFSET 0x24 */ + u32 reserved3; + + /* OFFSET 0x28 */ + u32 reserved4; + + /* OFFSET 0x2C */ + u32 reserved5; +}; + +/** + * struct PRIMITIVE_TASK_CONTEXT - This is the SCU hardware definition used + * when the driver wants to send a primitive on the link. + * + * + */ +struct PRIMITIVE_TASK_CONTEXT { + /* OFFSET 0x18 */ + /** + * This field is the control word and it must be 0. + */ + u32 control; /* /< must be set to 0 */ + + /* OFFSET 0x1C */ + /** + * This field specifies the primitive that is to be transmitted. + */ + u32 sequence; + + /* OFFSET 0x20 */ + u32 reserved0; + + /* OFFSET 0x24 */ + u32 reserved1; + + /* OFFSET 0x28 */ + u32 reserved2; + + /* OFFSET 0x2C */ + u32 reserved3; +}; + +/** + * The union of the protocols that can be selected in the SCU task context + * field. + * + * PROTOCOL_CONTEXT + */ +union PROTOCOL_CONTEXT { + struct SSP_TASK_CONTEXT ssp; + struct STP_TASK_CONTEXT stp; + struct SMP_TASK_CONTEXT smp; + struct PRIMITIVE_TASK_CONTEXT primitive; + u32 words[6]; +}; + +/** + * struct scu_sgl_element - This structure represents a single SCU defined SGL + * element. SCU SGLs contain a 64 bit address with the maximum data transfer + * being 24 bits in size. The SGL can not cross a 4GB boundary. + * + * struct scu_sgl_element + */ +struct scu_sgl_element { + /** + * This field is the upper 32 bits of the 64 bit physical address. + */ + u32 address_upper; + + /** + * This field is the lower 32 bits of the 64 bit physical address. + */ + u32 address_lower; + + /** + * This field is the number of bytes to transfer. + */ + u32 length:24; + + /** + * This field is the address modifier to be used when a virtual function is + * requesting a data transfer. + */ + u32 address_modifier:8; + +}; + +#define SCU_SGL_ELEMENT_PAIR_A 0 +#define SCU_SGL_ELEMENT_PAIR_B 1 + +/** + * struct scu_sgl_element_pair - This structure is the SCU hardware definition + * of a pair of SGL elements. The SCU hardware always works on SGL pairs. + * They are refered to in the DS specification as SGL A and SGL B. Each SGL + * pair is followed by the address of the next pair. + * + * + */ +struct scu_sgl_element_pair { + /* OFFSET 0x60-0x68 */ + /** + * This field is the SGL element A of the SGL pair. + */ + struct scu_sgl_element A; + + /* OFFSET 0x6C-0x74 */ + /** + * This field is the SGL element B of the SGL pair. + */ + struct scu_sgl_element B; + + /* OFFSET 0x78-0x7C */ + /** + * This field is the upper 32 bits of the 64 bit address to the next SGL + * element pair. + */ + u32 next_pair_upper; + + /** + * This field is the lower 32 bits of the 64 bit address to the next SGL + * element pair. + */ + u32 next_pair_lower; + +}; + +/** + * struct TRANSPORT_SNAPSHOT - This structure is the SCU hardware scratch area + * for the task context. This is set to 0 by the driver but can be read by + * issuing a dump TC request to the SCU. + * + * + */ +struct TRANSPORT_SNAPSHOT { + /* OFFSET 0x48 */ + u32 xfer_rdy_write_data_length; + + /* OFFSET 0x4C */ + u32 data_offset; + + /* OFFSET 0x50 */ + u32 data_transfer_size:24; + u32 reserved_50_0:8; + + /* OFFSET 0x54 */ + u32 next_initiator_write_data_offset; + + /* OFFSET 0x58 */ + u32 next_initiator_write_data_xfer_size:24; + u32 reserved_58_0:8; +}; + +/** + * struct scu_task_context - This structure defines the contents of the SCU + * silicon task context. It lays out all of the fields according to the + * expected order and location for the Storage Controller unit. + * + * + */ +struct scu_task_context { + /* OFFSET 0x00 ------ */ + /** + * This field must be encoded to one of the valid SCU task priority values + * - SCU_TASK_PRIORITY_NORMAL + * - SCU_TASK_PRIORITY_HEAD_OF_Q + * - SCU_TASK_PRIORITY_HIGH + */ + u32 priority:2; + + /** + * This field must be set to true if this is an initiator generated request. + * Until target mode is supported all task requests are initiator requests. + */ + u32 initiator_request:1; + + /** + * This field must be set to one of the valid connection rates valid values + * are 0x8, 0x9, and 0xA. + */ + u32 connection_rate:4; + + /** + * This field muse be programed when generating an SMP response since the SMP + * connection remains open until the SMP response is generated. + */ + u32 protocol_engine_index:3; + + /** + * This field must contain the logical port for the task request. + */ + u32 logical_port_index:3; + + /** + * This field must be set to one of the SCU_TASK_CONTEXT_PROTOCOL values + * - SCU_TASK_CONTEXT_PROTOCOL_SMP + * - SCU_TASK_CONTEXT_PROTOCOL_SSP + * - SCU_TASK_CONTEXT_PROTOCOL_STP + * - SCU_TASK_CONTEXT_PROTOCOL_NONE + */ + u32 protocol_type:3; + + /** + * This filed must be set to the TCi allocated for this task + */ + u32 task_index:12; + + /** + * This field is reserved and must be set to 0x00 + */ + u32 reserved_00_0:1; + + /** + * For a normal task request this must be set to 0. If this is an abort of + * this task request it must be set to 1. + */ + u32 abort:1; + + /** + * This field must be set to true for the SCU hardware to process the task. + */ + u32 valid:1; + + /** + * This field must be set to SCU_TASK_CONTEXT_TYPE + */ + u32 context_type:1; + + /* OFFSET 0x04 */ + /** + * This field contains the RNi that is the target of this request. + */ + u32 remote_node_index:12; + + /** + * This field is programmed if this is a mirrored request, which we are not + * using, in which case it is the RNi for the mirrored target. + */ + u32 mirrored_node_index:12; + + /** + * This field is programmed with the direction of the SATA reqeust + * - SCU_SATA_WRITE_DATA_DIRECTION + * - SCU_SATA_READ_DATA_DIRECTION + */ + u32 sata_direction:1; + + /** + * This field is programmsed with one of the following SCU_COMMAND_CODE + * - SCU_COMMAND_CODE_INITIATOR_NEW_TASK + * - SCU_COMMAND_CODE_ACTIVE_TASK + * - SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK + * - SCU_COMMAND_CODE_TARGET_RAW_FRAMES + */ + u32 command_code:2; + + /** + * This field is set to true if the remote node should be suspended. + * This bit is only valid for SSP & SMP target devices. + */ + u32 suspend_node:1; + + /** + * This field is programmed with one of the following command type codes + * + * For SAS requests use the SCU_SSP_TASK_TYPE + * - SCU_TASK_TYPE_IOREAD + * - SCU_TASK_TYPE_IOWRITE + * - SCU_TASK_TYPE_SMP_REQUEST + * - SCU_TASK_TYPE_RESPONSE + * - SCU_TASK_TYPE_RAW_FRAME + * - SCU_TASK_TYPE_PRIMITIVE + * + * For SATA requests use the SCU_SATA_TASK_TYPE + * - SCU_TASK_TYPE_DMA_IN + * - SCU_TASK_TYPE_FPDMAQ_READ + * - SCU_TASK_TYPE_PACKET_DMA_IN + * - SCU_TASK_TYPE_SATA_RAW_FRAME + * - SCU_TASK_TYPE_DMA_OUT + * - SCU_TASK_TYPE_FPDMAQ_WRITE + * - SCU_TASK_TYPE_PACKET_DMA_OUT + */ + u32 task_type:4; + + /* OFFSET 0x08 */ + /** + * This field is reserved and the must be set to 0x00 + */ + u32 link_layer_control:8; /* presently all reserved */ + + /** + * This field is set to true when TLR is to be enabled + */ + u32 ssp_tlr_enable:1; + + /** + * This is field specifies if the SCU DMAs a response frame to host + * memory for good response frames when operating in target mode. + */ + u32 dma_ssp_target_good_response:1; + + /** + * This field indicates if the SCU should DMA the response frame to + * host memory. + */ + u32 do_not_dma_ssp_good_response:1; + + /** + * This field is set to true when strict ordering is to be enabled + */ + u32 strict_ordering:1; + + /** + * This field indicates the type of endianess to be utilized for the + * frame. command, task, and response frames utilized control_frame + * set to 1. + */ + u32 control_frame:1; + + /** + * This field is reserved and the driver should set to 0x00 + */ + u32 tl_control_reserved:3; + + /** + * This field is set to true when the SCU hardware task timeout control is to + * be enabled + */ + u32 timeout_enable:1; + + /** + * This field is reserved and the driver should set it to 0x00 + */ + u32 pts_control_reserved:7; + + /** + * This field should be set to true when block guard is to be enabled + */ + u32 block_guard_enable:1; + + /** + * This field is reserved and the driver should set to 0x00 + */ + u32 sdma_control_reserved:7; + + /* OFFSET 0x0C */ + /** + * This field is the address modifier for this io request it should be + * programmed with the virtual function that is making the request. + */ + u32 address_modifier:16; + + /** + * @todo What we support mirrored SMP response frame? + */ + u32 mirrored_protocol_engine:3; /* mirrored protocol Engine Index */ + + /** + * If this is a mirrored request the logical port index for the mirrored RNi + * must be programmed. + */ + u32 mirrored_logical_port:4; /* mirrored local port index */ + + /** + * This field is reserved and the driver must set it to 0x00 + */ + u32 reserved_0C_0:8; + + /** + * This field must be set to true if the mirrored request processing is to be + * enabled. + */ + u32 mirror_request_enable:1; /* Mirrored request Enable */ + + /* OFFSET 0x10 */ + /** + * This field is the command iu length in dwords + */ + u32 ssp_command_iu_length:8; + + /** + * This is the target TLR enable bit it must be set to 0 when creatning the + * task context. + */ + u32 xfer_ready_tlr_enable:1; + + /** + * This field is reserved and the driver must set it to 0x00 + */ + u32 reserved_10_0:7; + + /** + * This is the maximum burst size that the SCU hardware will send in one + * connection its value is (N x 512) and N must be a multiple of 2. If the + * value is 0x00 then maximum burst size is disabled. + */ + u32 ssp_max_burst_size:16; + + /* OFFSET 0x14 */ + /** + * This filed is set to the number of bytes to be transfered in the request. + */ + u32 transfer_length_bytes:24; /* In terms of bytes */ + + /** + * This field is reserved and the driver should set it to 0x00 + */ + u32 reserved_14_0:8; + + /* OFFSET 0x18-0x2C */ + /** + * This union provides for the protocol specif part of the SCU Task Context. + */ + union PROTOCOL_CONTEXT type; + + /* OFFSET 0x30-0x34 */ + /** + * This field is the upper 32 bits of the 64 bit physical address of the + * command iu buffer + */ + u32 command_iu_upper; + + /** + * This field is the lower 32 bits of the 64 bit physical address of the + * command iu buffer + */ + u32 command_iu_lower; + + /* OFFSET 0x38-0x3C */ + /** + * This field is the upper 32 bits of the 64 bit physical address of the + * response iu buffer + */ + u32 response_iu_upper; + + /** + * This field is the lower 32 bits of the 64 bit physical address of the + * response iu buffer + */ + u32 response_iu_lower; + + /* OFFSET 0x40 */ + /** + * This field is set to the task phase of the SCU hardware. The driver must + * set this to 0x01 + */ + u32 task_phase:8; + + /** + * This field is set to the transport layer task status. The driver must set + * this to 0x00 + */ + u32 task_status:8; + + /** + * This field is used during initiator write TLR + */ + u32 previous_extended_tag:4; + + /** + * This field is set the maximum number of retries for a STP non-data FIS + */ + u32 stp_retry_count:2; + + /** + * This field is reserved and the driver must set it to 0x00 + */ + u32 reserved_40_1:2; + + /** + * This field is used by the SCU TL to determine when to take a snapshot when + * tranmitting read data frames. + * - 0x00 The entire IO + * - 0x01 32k + * - 0x02 64k + * - 0x04 128k + * - 0x08 256k + */ + u32 ssp_tlr_threshold:4; + + /** + * This field is reserved and the driver must set it to 0x00 + */ + u32 reserved_40_2:4; + + /* OFFSET 0x44 */ + u32 write_data_length; /* read only set to 0 */ + + /* OFFSET 0x48-0x58 */ + struct TRANSPORT_SNAPSHOT snapshot; /* read only set to 0 */ + + /* OFFSET 0x5C */ + u32 block_protection_enable:1; + u32 block_size:2; + u32 block_protection_function:2; + u32 reserved_5C_0:9; + u32 active_sgl_element:2; /* read only set to 0 */ + u32 sgl_exhausted:1; /* read only set to 0 */ + u32 payload_data_transfer_error:4; /* read only set to 0 */ + u32 frame_buffer_offset:11; /* read only set to 0 */ + + /* OFFSET 0x60-0x7C */ + /** + * This field is the first SGL element pair found in the TC data structure. + */ + struct scu_sgl_element_pair sgl_pair_ab; + /* OFFSET 0x80-0x9C */ + /** + * This field is the second SGL element pair found in the TC data structure. + */ + struct scu_sgl_element_pair sgl_pair_cd; + + /* OFFSET 0xA0-BC */ + struct scu_sgl_element_pair sgl_snapshot_ac; + + /* OFFSET 0xC0 */ + u32 active_sgl_element_pair; /* read only set to 0 */ + + /* OFFSET 0xC4-0xCC */ + u32 reserved_C4_CC[3]; + + /* OFFSET 0xD0 */ + u32 intermediate_crc_value:16; + u32 initial_crc_seed:16; + + /* OFFSET 0xD4 */ + u32 application_tag_for_verify:16; + u32 application_tag_for_generate:16; + + /* OFFSET 0xD8 */ + u32 reference_tag_seed_for_verify_function; + + /* OFFSET 0xDC */ + u32 reserved_DC; + + /* OFFSET 0xE0 */ + u32 reserved_E0_0:16; + u32 application_tag_mask_for_generate:16; + + /* OFFSET 0xE4 */ + u32 block_protection_control:16; + u32 application_tag_mask_for_verify:16; + + /* OFFSET 0xE8 */ + u32 block_protection_error:8; + u32 reserved_E8_0:24; + + /* OFFSET 0xEC */ + u32 reference_tag_seed_for_verify; + + /* OFFSET 0xF0 */ + u32 intermediate_crc_valid_snapshot:16; + u32 reserved_F0_0:16; + + /* OFFSET 0xF4 */ + u32 reference_tag_seed_for_verify_function_snapshot; + + /* OFFSET 0xF8 */ + u32 snapshot_of_reserved_dword_DC_of_tc; + + /* OFFSET 0xFC */ + u32 reference_tag_seed_for_generate_function_snapshot; + +}; + +#endif /* _SCU_TASK_CONTEXT_H_ */ diff --git a/drivers/scsi/isci/core/scu_unsolicited_frame.h b/drivers/scsi/isci/core/scu_unsolicited_frame.h new file mode 100644 index 000000000000..590ea02745fd --- /dev/null +++ b/drivers/scsi/isci/core/scu_unsolicited_frame.h @@ -0,0 +1,117 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This field defines the SCU format of an unsolicited frame (UF). A UF is a + * frame received by the SCU for which there is no known corresponding task + * context (TC). + * + * + */ + +#ifndef _SCU_UNSOLICITED_FRAME_H_ +#define _SCU_UNSOLICITED_FRAME_H_ + +#include "sci_types.h" + +/** + * + * + * This constant defines the number of DWORDS found the unsolicited frame + * header data member. + */ +#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15 + +/** + * struct scu_unsolicited_frame_header - + * + * This structure delineates the format of an unsolicited frame header. The + * first DWORD are UF attributes defined by the silicon architecture. The data + * depicts actual header information received on the link. + */ +struct scu_unsolicited_frame_header { + /** + * This field indicates if there is an Initiator Index Table entry with + * which this header is associated. + */ + u32 iit_exists:1; + + /** + * This field simply indicates the protocol type (i.e. SSP, STP, SMP). + */ + u32 protocol_type:3; + + /** + * This field indicates if the frame is an address frame (IAF or OAF) + * or if it is a information unit frame. + */ + u32 is_address_frame:1; + + /** + * This field simply indicates the connection rate at which the frame + * was received. + */ + u32 connection_rate:4; + + u32 reserved:23; + + /** + * This field represents the actual header data received on the link. + */ + u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS]; + +}; + +#endif /* _SCU_UNSOLICITED_FRAME_H_ */ diff --git a/drivers/scsi/isci/core/scu_viit_data.h b/drivers/scsi/isci/core/scu_viit_data.h new file mode 100644 index 000000000000..4601d1962ca3 --- /dev/null +++ b/drivers/scsi/isci/core/scu_viit_data.h @@ -0,0 +1,179 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCU_VIIT_DATA_HEADER_ +#define _SCU_VIIT_DATA_HEADER_ + +/** + * This file contains the constants and structures for the SCU hardware VIIT + * table entries. + * + * + */ + +#include "sci_types.h" + +#define SCU_VIIT_ENTRY_ID_MASK (0xC0000000) +#define SCU_VIIT_ENTRY_ID_SHIFT (30) + +#define SCU_VIIT_ENTRY_FUNCTION_MASK (0x0FF00000) +#define SCU_VIIT_ENTRY_FUNCTION_SHIFT (20) + +#define SCU_VIIT_ENTRY_IPPTMODE_MASK (0x0001F800) +#define SCU_VIIT_ENTRY_IPPTMODE_SHIFT (12) + +#define SCU_VIIT_ENTRY_LPVIE_MASK (0x00000F00) +#define SCU_VIIT_ENTRY_LPVIE_SHIFT (8) + +#define SCU_VIIT_ENTRY_STATUS_MASK (0x000000FF) +#define SCU_VIIT_ENTRY_STATUS_SHIFT (0) + +#define SCU_VIIT_ENTRY_ID_INVALID (0 << SCU_VIIT_ENTRY_ID_SHIFT) +#define SCU_VIIT_ENTRY_ID_VIIT (1 << SCU_VIIT_ENTRY_ID_SHIFT) +#define SCU_VIIT_ENTRY_ID_IIT (2 << SCU_VIIT_ENTRY_ID_SHIFT) +#define SCU_VIIT_ENTRY_ID_VIRT_EXP (3 << SCU_VIIT_ENTRY_ID_SHIFT) + +#define SCU_VIIT_IPPT_SSP_INITIATOR (0x01 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) +#define SCU_VIIT_IPPT_SMP_INITIATOR (0x02 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) +#define SCU_VIIT_IPPT_STP_INITIATOR (0x04 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) +#define SCU_VIIT_IPPT_INITIATOR \ + (\ + SCU_VIIT_IPPT_SSP_INITIATOR \ + | SCU_VIIT_IPPT_SMP_INITIATOR \ + | SCU_VIIT_IPPT_STP_INITIATOR \ + ) + +#define SCU_VIIT_STATUS_RNC_VALID (0x01 << SCU_VIIT_ENTRY_STATUS_SHIFT) +#define SCU_VIIT_STATUS_ADDRESS_VALID (0x02 << SCU_VIIT_ENTRY_STATUS_SHIFT) +#define SCU_VIIT_STATUS_RNI_VALID (0x04 << SCU_VIIT_ENTRY_STATUS_SHIFT) +#define SCU_VIIT_STATUS_ALL_VALID \ + (\ + SCU_VIIT_STATUS_RNC_VALID \ + | SCU_VIIT_STATUS_ADDRESS_VALID \ + | SCU_VIIT_STATUS_RNI_VALID \ + ) + +#define SCU_VIIT_IPPT_SMP_TARGET (0x10 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) + +/** + * struct scu_viit_entry - This is the SCU Virtual Initiator Table Entry + * + * + */ +struct scu_viit_entry { + /** + * This must be encoded as to the type of initiator that is being constructed + * for this port. + */ + u32 status; + + /** + * Virtual initiator high SAS Address + */ + u32 initiator_sas_address_hi; + + /** + * Virtual initiator low SAS Address + */ + u32 initiator_sas_address_lo; + + /** + * This must be 0 + */ + u32 reserved; + +}; + + +/* IIT Status Defines */ +#define SCU_IIT_ENTRY_ID_MASK (0xC0000000) +#define SCU_IIT_ENTRY_ID_SHIFT (30) + +#define SCU_IIT_ENTRY_STATUS_UPDATE_MASK (0x20000000) +#define SCU_IIT_ENTRY_STATUS_UPDATE_SHIFT (29) + +#define SCU_IIT_ENTRY_LPI_MASK (0x00000F00) +#define SCU_IIT_ENTRY_LPI_SHIFT (8) + +#define SCU_IIT_ENTRY_STATUS_MASK (0x000000FF) +#define SCU_IIT_ENTRY_STATUS_SHIFT (0) + +/* IIT Remote Initiator Defines */ +#define SCU_IIT_ENTRY_REMOTE_TAG_MASK (0x0000FFFF) +#define SCU_IIT_ENTRY_REMOTE_TAG_SHIFT (0) + +#define SCU_IIT_ENTRY_REMOTE_RNC_MASK (0x0FFF0000) +#define SCU_IIT_ENTRY_REMOTE_RNC_SHIFT (16) + +#define SCU_IIT_ENTRY_ID_INVALID (0 << SCU_IIT_ENTRY_ID_SHIFT) +#define SCU_IIT_ENTRY_ID_VIIT (1 << SCU_IIT_ENTRY_ID_SHIFT) +#define SCU_IIT_ENTRY_ID_IIT (2 << SCU_IIT_ENTRY_ID_SHIFT) +#define SCU_IIT_ENTRY_ID_VIRT_EXP (3 << SCU_IIT_ENTRY_ID_SHIFT) + +/** + * struct scu_iit_entry - This will be implemented later when we support + * virtual functions + * + * + */ +struct scu_iit_entry { + u32 status; + u32 remote_initiator_sas_address_hi; + u32 remote_initiator_sas_address_lo; + u32 remote_initiator; + +}; + +#endif /* _SCU_VIIT_DATA_HEADER_ */ diff --git a/drivers/scsi/isci/deprecated.c b/drivers/scsi/isci/deprecated.c new file mode 100644 index 000000000000..847e6874e1a8 --- /dev/null +++ b/drivers/scsi/isci/deprecated.c @@ -0,0 +1,491 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * This file contains isci module object implementation. + * + * + */ + +#include "isci.h" +#include "request.h" +#include "sata.h" +#include "task.h" + + +/** + * scic_cb_stall_execution() - This method is called when the core requires the + * OS driver to stall execution. This method is utilized during + * initialization or non-performance paths only. + * @microseconds: This parameter specifies the number of microseconds for which + * to stall. The operating system driver is allowed to round this value up + * where necessary. + * + * none. + */ +void scic_cb_stall_execution( + u32 microseconds) +{ + udelay(microseconds); +} + + +/** + * scic_cb_io_request_get_physical_address() - This callback method asks the + * user to provide the physical address for the supplied virtual address + * when building an io request object. + * @controller: This parameter is the core controller object handle. + * @io_request: This parameter is the io request object handle for which the + * physical address is being requested. + * + * + */ +void scic_cb_io_request_get_physical_address( + struct scic_sds_controller *controller, + struct scic_sds_request *io_request, + void *virtual_address, + dma_addr_t *physical_address) +{ + struct isci_request *request = + (struct isci_request *)sci_object_get_association(io_request); + + char *requested_address = (char *)virtual_address; + char *base_address = (char *)request; + + BUG_ON(requested_address < base_address); + BUG_ON((requested_address - base_address) >= + request->request_alloc_size); + + *physical_address = request->request_daddr + + (requested_address - base_address); +} + +/** + * scic_cb_io_request_get_transfer_length() - This callback method asks the + * user to provide the number of bytes to be transfered as part of this + * request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the number of payload data bytes to be transfered for + * this IO request. + */ +u32 scic_cb_io_request_get_transfer_length( + void *scic_user_io_request) +{ + return isci_request_io_request_get_transfer_length( + scic_user_io_request + ); +} + + +/** + * scic_cb_io_request_get_data_direction() - This callback method asks the user + * to provide the data direction for this request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the value of SCI_IO_REQUEST_DATA_OUT or + * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA. + */ +SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction( + void *scic_user_io_request) +{ + return isci_request_io_request_get_data_direction( + scic_user_io_request + ); +} + + +/** + * scic_cb_io_request_get_next_sge() - This callback method asks the user to + * provide the address to where the next Scatter-Gather Element is located. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * @current_sge_address: This parameter specifies the address for the current + * SGE (i.e. the one that has just processed). + * + * An address specifying the location for the next scatter gather element to be + * processed. + */ +void scic_cb_io_request_get_next_sge( + void *scic_user_io_request, + void *current_sge_address, + void **next_sge) +{ + *next_sge = isci_request_io_request_get_next_sge( + scic_user_io_request, + current_sge_address + ); +} + +/** + * scic_cb_sge_get_address_field() - This callback method asks the user to + * provide the contents of the "address" field in the Scatter-Gather Element. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * @sge_address: This parameter specifies the address for the SGE from which to + * retrieve the address field. + * + * A physical address specifying the contents of the SGE's address field. + */ +dma_addr_t scic_cb_sge_get_address_field( + void *scic_user_io_request, + void *sge_address) +{ + return isci_request_sge_get_address_field( + scic_user_io_request, + sge_address + ); +} + +/** + * scic_cb_sge_get_length_field() - This callback method asks the user to + * provide the contents of the "length" field in the Scatter-Gather Element. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * @sge_address: This parameter specifies the address for the SGE from which to + * retrieve the address field. + * + * This method returns the length field specified inside the SGE referenced by + * the sge_address parameter. + */ +u32 scic_cb_sge_get_length_field( + void *scic_user_io_request, + void *sge_address) +{ + return isci_request_sge_get_length_field( + scic_user_io_request, + sge_address + ); +} + +/** + * scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the + * user to provide the address for the command descriptor block (CDB) + * associated with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the virtual address of the CDB. + */ +void *scic_cb_ssp_io_request_get_cdb_address( + void *scic_user_io_request) +{ + return isci_request_ssp_io_request_get_cdb_address( + scic_user_io_request + ); +} + +/** + * scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user + * to provide the length of the command descriptor block (CDB) associated + * with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the length of the CDB. + */ +u32 scic_cb_ssp_io_request_get_cdb_length( + void *scic_user_io_request) +{ + return isci_request_ssp_io_request_get_cdb_length( + scic_user_io_request + ); +} + +/** + * scic_cb_ssp_io_request_get_lun() - This callback method asks the user to + * provide the Logical Unit (LUN) associated with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the LUN associated with this request. This should be u64? + */ +u32 scic_cb_ssp_io_request_get_lun( + void *scic_user_io_request) +{ + return isci_request_ssp_io_request_get_lun(scic_user_io_request); +} + +/** + * scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the + * user to provide the task attribute associated with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the task attribute associated with this IO request. + */ +u32 scic_cb_ssp_io_request_get_task_attribute( + void *scic_user_io_request) +{ + return isci_request_ssp_io_request_get_task_attribute( + scic_user_io_request + ); +} + +/** + * scic_cb_ssp_io_request_get_command_priority() - This callback method asks + * the user to provide the command priority associated with this IO request. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the command priority associated with this IO request. + */ +u32 scic_cb_ssp_io_request_get_command_priority( + void *scic_user_io_request) +{ + return isci_request_ssp_io_request_get_command_priority( + scic_user_io_request + ); +} + +/** + * scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to + * be utilized for this task management request. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the LUN associated with this request. This should be u64? + */ +u32 scic_cb_ssp_task_request_get_lun( + void *scic_user_task_request) +{ + return isci_task_ssp_request_get_lun( + (struct isci_request *)scic_user_task_request + ); +} + +/** + * scic_cb_ssp_task_request_get_function() - This method returns the task + * management function to be utilized for this task request. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns an unsigned byte representing the task management + * function to be performed. + */ +u8 scic_cb_ssp_task_request_get_function( + void *scic_user_task_request) +{ + return isci_task_ssp_request_get_function( + (struct isci_request *)scic_user_task_request + ); +} + +/** + * scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the + * task management IO tag to be managed. Depending upon the task management + * function the value returned from this method may be ignored. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns an unsigned 16-bit word depicting the IO tag to be + * managed. + */ +u16 scic_cb_ssp_task_request_get_io_tag_to_manage( + void *scic_user_task_request) +{ + return isci_task_ssp_request_get_io_tag_to_manage( + (struct isci_request *)scic_user_task_request + ); +} + +/** + * scic_cb_ssp_task_request_get_response_data_address() - This callback method + * asks the user to provide the virtual address of the response data buffer + * for the supplied IO request. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the virtual address for the response data buffer + * associated with this IO request. + */ +void *scic_cb_ssp_task_request_get_response_data_address( + void *scic_user_task_request) +{ + return isci_task_ssp_request_get_response_data_address( + (struct isci_request *)scic_user_task_request + ); +} + +/** + * scic_cb_ssp_task_request_get_response_data_length() - This callback method + * asks the user to provide the length of the response data buffer for the + * supplied IO request. + * @scic_user_task_request: This parameter points to the user's task request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns the length of the response buffer data associated with + * this IO request. + */ +u32 scic_cb_ssp_task_request_get_response_data_length( + void *scic_user_task_request) +{ + return isci_task_ssp_request_get_response_data_length( + (struct isci_request *)scic_user_task_request + ); +} + +#if !defined(DISABLE_ATAPI) +/** + * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback asks + * the user to provide stp packet io's the CDB address. + * @scic_user_io_request: + * + * The packet IO's cdb adress. + */ +void *scic_cb_stp_packet_io_request_get_cdb_address( + void *scic_user_io_request) +{ + return isci_request_stp_packet_io_request_get_cdb_address( + scic_user_io_request + ); +} + + +/** + * scic_cb_stp_packet_io_request_get_cdb_length() - This user callback asks the + * user to provide stp packet io's the CDB length. + * @scic_user_io_request: + * + * The packet IO's cdb length. + */ +u32 scic_cb_stp_packet_io_request_get_cdb_length( + void *scic_user_io_request) +{ + return isci_request_stp_packet_io_request_get_cdb_length( + scic_user_io_request + ); +} +#endif /* #if !defined(DISABLE_ATAPI) */ + + +/** + * scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user + * if the received RX frame data is to be copied to the SGL or should be + * stored by the SCI core to be retrieved later with the + * scic_io_request_get_rx_frame(). + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns true if the SCI core should copy the received frame data + * to the SGL location or false if the SCI user wants to retrieve the frame + * data at a later time. + */ +bool scic_cb_io_request_do_copy_rx_frames( + void *scic_user_io_request) +{ + struct sas_task *task + = isci_request_access_task( + (struct isci_request *)scic_user_io_request + ); + + return (task->data_dir == DMA_NONE) ? false : true; +} + +/** + * scic_cb_get_virtual_address() - This callback method asks the user to + * provide the virtual address for the supplied physical address. + * @controller: This parameter is the core controller object handle. + * @physical_address: This parameter is the physical address which is to be + * returned as a virtual address. + * + * The method returns the virtual address for the supplied physical address. + */ +void *scic_cb_get_virtual_address( + struct scic_sds_controller *controller, + dma_addr_t physical_address) +{ + void *virt_addr = (void *)phys_to_virt(physical_address); + + return virt_addr; +} + +/** + * scic_cb_request_get_sat_protocol() - This callback method asks the user to + * return the SAT protocol definition for this IO request. This method is + * only called by the SCI core if the request type constructed is SATA. + * @scic_user_io_request: This parameter points to the user's IO request + * object. It is a cookie that allows the user to provide the necessary + * information for this callback. + * + * This method returns one of the sat.h defined protocols for the given io + * request. + */ +u8 scic_cb_request_get_sat_protocol( + void *scic_user_io_request) +{ + return isci_sata_get_sat_protocol( + (struct isci_request *)scic_user_io_request + ); +} diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c new file mode 100644 index 000000000000..75f9cd551278 --- /dev/null +++ b/drivers/scsi/isci/events.c @@ -0,0 +1,619 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * This file contains isci module object implementation. + * + * + */ + +#include "isci.h" +#include "request.h" +#include "sata.h" +#include "task.h" + +/** + * scic_cb_timer_create() - This callback method asks the user to create a + * timer and provide a handle for this timer for use in further timer + * interactions. The appropriate isci timer object function is called to + * create a timer object. + * @timer_callback: This parameter specifies the callback method to be invoked + * whenever the timer expires. + * @controller: This parameter specifies the controller with which this timer + * is to be associated. + * @cookie: This parameter specifies a piece of information that the user must + * retain. This cookie is to be supplied by the user anytime a timeout + * occurs for the created timer. + * + * This method returns a handle to a timer object created by the user. The + * handle will be utilized for all further interactions relating to this timer. + */ +void *scic_cb_timer_create( + struct scic_sds_controller *controller, + void (*timer_callback)(void *), + void *cookie) +{ + struct isci_host *isci_host; + struct isci_timer *timer = NULL; + + isci_host = (struct isci_host *)sci_object_get_association(controller); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host = %p", + __func__, isci_host); + + timer = isci_timer_create(&isci_host->timer_list_struct, + isci_host, + cookie, + timer_callback); + + dev_dbg(&isci_host->pdev->dev, "%s: timer = %p\n", __func__, timer); + + return (void *)timer; +} + + +/** + * scic_cb_timer_start() - This callback method asks the user to start the + * supplied timer. The appropriate isci timer object function is called to + * start the timer. + * @controller: This parameter specifies the controller with which this timer + * is to associated. + * @timer: This parameter specifies the timer to be started. + * @milliseconds: This parameter specifies the number of milliseconds for which + * to stall. The operating system driver is allowed to round this value up + * where necessary. + * + */ +void scic_cb_timer_start( + struct scic_sds_controller *controller, + void *timer, + u32 milliseconds) +{ + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host = %p, timer = %p, milliseconds = %d\n", + __func__, isci_host, timer, milliseconds); + + isci_timer_start((struct isci_timer *)timer, milliseconds); + +} + +/** + * scic_cb_timer_stop() - This callback method asks the user to stop the + * supplied timer. The appropriate isci timer object function is called to + * stop the timer. + * @controller: This parameter specifies the controller with which this timer + * is to associated. + * @timer: This parameter specifies the timer to be stopped. + * + */ +void scic_cb_timer_stop( + struct scic_sds_controller *controller, + void *timer) +{ + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host = %p, timer = %p\n", + __func__, isci_host, timer); + + isci_timer_stop((struct isci_timer *)timer); +} + +/** + * scic_cb_controller_start_complete() - This user callback will inform the + * user that the controller has finished the start process. The associated + * isci host adapter's start_complete function is called. + * @controller: This parameter specifies the controller that was started. + * @completion_status: This parameter specifies the results of the start + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void scic_cb_controller_start_complete( + struct scic_sds_controller *controller, + enum sci_status completion_status) +{ + struct isci_host *isci_host = + (struct isci_host *)sci_object_get_association(controller); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host = %p\n", __func__, isci_host); + + isci_host_start_complete(isci_host, completion_status); +} + +/** + * scic_cb_controller_stop_complete() - This user callback will inform the user + * that the controller has finished the stop process. The associated isci + * host adapter's start_complete function is called. + * @controller: This parameter specifies the controller that was stopped. + * @completion_status: This parameter specifies the results of the stop + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void scic_cb_controller_stop_complete( + struct scic_sds_controller *controller, + enum sci_status completion_status) +{ + struct isci_host *isci_host = + (struct isci_host *)sci_object_get_association(controller); + + dev_dbg(&isci_host->pdev->dev, + "%s: status = 0x%x\n", __func__, completion_status); + isci_host_stop_complete(isci_host, completion_status); +} + +/** + * scic_cb_io_request_complete() - This user callback will inform the user that + * an IO request has completed. + * @controller: This parameter specifies the controller on which the IO is + * completing. + * @remote_device: This parameter specifies the remote device on which this IO + * request is completing. + * @io_request: This parameter specifies the IO request that has completed. + * @completion_status: This parameter specifies the results of the IO request + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void scic_cb_io_request_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *scic_io_request, + enum sci_io_status completion_status) +{ + struct isci_request *request; + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + request = + (struct isci_request *)sci_object_get_association( + scic_io_request + ); + + isci_request_io_request_complete(isci_host, + request, + completion_status); +} + +/** + * scic_cb_task_request_complete() - This user callback will inform the user + * that a task management request completed. + * @controller: This parameter specifies the controller on which the task + * management request is completing. + * @remote_device: This parameter specifies the remote device on which this + * task management request is completing. + * @task_request: This parameter specifies the task management request that has + * completed. + * @completion_status: This parameter specifies the results of the IO request + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void scic_cb_task_request_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *scic_task_request, + enum sci_task_status completion_status) +{ + struct isci_request *request; + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + request = + (struct isci_request *)sci_object_get_association( + scic_task_request); + + isci_task_request_complete(isci_host, request, completion_status); +} + +/** + * scic_cb_port_stop_complete() - This method informs the user when a stop + * operation on the port has completed. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @completion_status: This parameter specifies the status for the operation + * being completed. + * + */ +void scic_cb_port_stop_complete( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + enum sci_status completion_status) +{ + pr_warn("%s:************************************************\n", + __func__); +} + +/** + * scic_cb_port_hard_reset_complete() - This method informs the user when a + * hard reset on the port has completed. This hard reset could have been + * initiated by the user or by the remote port. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @completion_status: This parameter specifies the status for the operation + * being completed. + * + */ +void scic_cb_port_hard_reset_complete( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + enum sci_status completion_status) +{ + struct isci_port *isci_port + = (struct isci_port *)sci_object_get_association(port); + + isci_port_hard_reset_complete(isci_port, completion_status); +} + +/** + * scic_cb_port_ready() - This method informs the user that the port is now in + * a ready state and can be utilized to issue IOs. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * + */ +void scic_cb_port_ready( + struct scic_sds_controller *controller, + struct scic_sds_port *port) +{ + struct isci_port *isci_port; + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + isci_port = + (struct isci_port *)sci_object_get_association(port); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p\n", __func__, isci_port); + + isci_port_ready(isci_host, isci_port); +} + +/** + * scic_cb_port_not_ready() - This method informs the user that the port is now + * not in a ready (i.e. busy) state and can't be utilized to issue IOs. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * + */ +void scic_cb_port_not_ready( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + u32 reason_code) +{ + struct isci_port *isci_port; + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + isci_port = + (struct isci_port *)sci_object_get_association(port); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p\n", __func__, isci_port); + + isci_port_not_ready(isci_host, isci_port); +} + +/** + * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that + * a phy/link became ready, but the phy is not allowed in the port. In some + * situations the underlying hardware only allows for certain phy to port + * mappings. If these mappings are violated, then this API is invoked. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @phy: This parameter specifies the phy that came ready, but the phy can't be + * a valid member of the port. + * + */ +void scic_cb_port_invalid_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + pr_warn("%s:************************************************\n", + __func__); +} + +/** + * scic_cb_port_bc_change_primitive_received() - This callback method informs + * the user that a broadcast change primitive was received. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. For instances where the phy on which the primitive was + * received is not part of a port, this parameter will be + * SCI_INVALID_HANDLE_T. + * @phy: This parameter specifies the phy on which the primitive was received. + * + */ +void scic_cb_port_bc_change_primitive_received( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + dev_dbg(&isci_host->pdev->dev, + "%s: port = %p, phy = %p\n", __func__, port, phy); + isci_port_bc_change_received(isci_host, port, phy); +} + + + + +/** + * scic_cb_port_link_up() - This callback method informs the user that a phy + * has become operational and is capable of communicating with the remote + * end point. + * @controller: This parameter represents the controller associated with the + * phy. + * @port: This parameter specifies the port object for which the user callback + * is being invoked. There may be conditions where this parameter can be + * SCI_INVALID_HANDLE + * @phy: This parameter specifies the phy object for which the user callback is + * being invoked. + * + * none. + */ +void scic_cb_port_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + dev_dbg(&isci_host->pdev->dev, + "%s: phy = %p\n", __func__, phy); + + isci_port_link_up(isci_host, port, phy); +} + +/** + * scic_cb_port_link_down() - This callback method informs the user that a phy + * is no longer operational and is not capable of communicating with the + * remote end point. + * @controller: This parameter represents the controller associated with the + * phy. + * @port: This parameter specifies the port object for which the user callback + * is being invoked. There may be conditions where this parameter can be + * SCI_INVALID_HANDLE + * @phy: This parameter specifies the phy object for which the user callback is + * being invoked. + * + * none. + */ +void scic_cb_port_link_down( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + struct isci_host *isci_host; + struct isci_phy *isci_phy; + struct isci_port *isci_port; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + isci_phy = + (struct isci_phy *)sci_object_get_association(phy); + + isci_port = + (struct isci_port *)sci_object_get_association(port); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p\n", __func__, isci_port); + + isci_port_link_down(isci_host, isci_phy, isci_port); +} + +/** + * scic_cb_remote_device_start_complete() - This user callback method will + * inform the user that a start operation has completed. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the completion callback. + * @completion_status: This parameter specifies the completion status for the + * operation. + * + */ +void scic_cb_remote_device_start_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + enum sci_status completion_status) +{ + struct isci_host *isci_host; + struct isci_remote_device *isci_device; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + isci_device = + (struct isci_remote_device *)sci_object_get_association( + remote_device + ); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + isci_remote_device_start_complete( + isci_host, isci_device, completion_status); + +} + +/** + * scic_cb_remote_device_stop_complete() - This user callback method will + * inform the user that a stop operation has completed. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the completion callback. + * @completion_status: This parameter specifies the completion status for the + * operation. + * + */ +void scic_cb_remote_device_stop_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + enum sci_status completion_status) +{ + struct isci_host *isci_host; + struct isci_remote_device *isci_device; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + isci_device = + (struct isci_remote_device *)sci_object_get_association( + remote_device + ); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + isci_remote_device_stop_complete( + isci_host, isci_device, completion_status); + +} + +/** + * scic_cb_remote_device_ready() - This user callback method will inform the + * user that a remote device is now capable of handling IO requests. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the callback. + * + */ +void scic_cb_remote_device_ready( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device) +{ + struct isci_remote_device *isci_device = + (struct isci_remote_device *) + sci_object_get_association(remote_device); + + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + isci_remote_device_ready(isci_device); +} + +/** + * scic_cb_remote_device_not_ready() - This user callback method will inform + * the user that a remote device is no longer capable of handling IO + * requests (until a ready callback is invoked). + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the callback. + * @reason_code: This parameter specifies the reason for the remote device + * going to a not ready state. + * + */ +void scic_cb_remote_device_not_ready( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + u32 reason_code) +{ + struct isci_remote_device *isci_device = + (struct isci_remote_device *) + sci_object_get_association(remote_device); + + struct isci_host *isci_host; + + isci_host = + (struct isci_host *)sci_object_get_association(controller); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p, reason_code = %x\n", + __func__, isci_device, reason_code); + + isci_remote_device_not_ready(isci_device, reason_code); +} + + diff --git a/drivers/scsi/isci/firmware/Makefile b/drivers/scsi/isci/firmware/Makefile new file mode 100644 index 000000000000..5f54461cabc5 --- /dev/null +++ b/drivers/scsi/isci/firmware/Makefile @@ -0,0 +1,19 @@ +# Makefile for create_fw +# +CC=gcc +CFLAGS=-c -Wall -O2 -g +LDFLAGS= +SOURCES=create_fw.c +OBJECTS=$(SOURCES:.cpp=.o) +EXECUTABLE=create_fw + +all: $(SOURCES) $(EXECUTABLE) + +$(EXECUTABLE): $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -o $@ + +.c.o: + $(CC) $(CFLAGS) $< -O $@ + +clean: + rm -f *.o $(EXECUTABLE) diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README new file mode 100644 index 000000000000..cf7e4286e896 --- /dev/null +++ b/drivers/scsi/isci/firmware/README @@ -0,0 +1,36 @@ +This defines the temporary binary blow we are to pass to the SCU +driver to emulate the binary firmware that we will eventually be +able to access via NVRAM on the SCU controller. + +The current size of the binary blob is expected to be 149 bytes or larger + +Header Types: +0x1: Phy Masks +0x2: Phy Gens +0x3: SAS Addrs +0xff: End of Data + +ID string - u8[12]: "#SCU MAGIC#\0" +Version - u8: 1 +SubVersion - u8: 0 + +Header Type - u8: 0x1 +Size - u8: 8 +Phy Mask - u32[8] + +Header Type - u8: 0x2 +Size - u8: 8 +Phy Gen - u32[8] + +Header Type - u8: 0x3 +Size - u8: 8 +Sas Addr - u64[8] + +Header Type - u8: 0xf + + +============================================================================== + +Place isci_firmware.bin in /lib/firmware +Be sure to recreate the initramfs image to include the firmware. + diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c new file mode 100644 index 000000000000..442caac9675d --- /dev/null +++ b/drivers/scsi/isci/firmware/create_fw.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +char blob_name[] = "isci_firmware.bin"; +char id[] = "#SCU MAGIC#"; +unsigned char version = 1; +unsigned char sub_version = 0; + + +/* + * For all defined arrays: + * elements 0-3 are for SCU0, ports 0-3 + * elements 4-7 are for SCU1, ports 0-3 + * + * valid configurations for one SCU are: + * P0 P1 P2 P3 + * ---------------- + * 0xF,0x0,0x0,0x0 # 1 x4 port + * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1 + * # ports + * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2 + * # port + * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port + * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration) + * + * if there is a port/phy on which you do not wish to override the default + * values, use the value assigned to UNINIT_PARAM (255). + */ +unsigned int phy_mask[] = { 1, 2, 4, 8, 1, 2, 4, 8 }; + + +/* denotes SAS generation. i.e. 3: SAS Gen 3 6G */ +unsigned int phy_gen[] = { 3, 3, 3, 3, 3, 3, 3, 3 }; + +/* + * if there is a port/phy on which you do not wish to override the default + * values, use the value "0000000000000000". SAS address of zero's is + * considered invalid and will not be used. + */ +unsigned long long sas_addr[] = { 0x5FCFFFFFF0000000ULL, + 0x5FCFFFFFF1000000ULL, + 0x5FCFFFFFF2000000ULL, + 0x5FCFFFFFF3000000ULL, + 0x5FCFFFFFF4000000ULL, + 0x5FCFFFFFF5000000ULL, + 0x5FCFFFFFF6000000ULL, + 0x5FCFFFFFF7000000ULL }; + +int write_blob(void) +{ + FILE *fd; + int err; + + fd = fopen(blob_name, "w+"); + if (!fd) { + perror("Open file for write failed"); + return -EIO; + } + + /* write id */ + err = fwrite((void *)id, sizeof(char), strlen(id)+1, fd); + if (err == 0) { + perror("write id failed"); + return err; + } + + /* write version */ + err = fwrite((void *)&version, sizeof(version), 1, fd); + if (err == 0) { + perror("write version failed"); + return err; + } + + /* write sub version */ + err = fwrite((void *)&sub_version, sizeof(sub_version), 1, fd); + if (err == 0) { + perror("write subversion failed"); + return err; + } + + /* write phy mask header */ + err = fputc(0x1, fd); + if (err == EOF) { + perror("write phy mask header failed"); + return -EIO; + } + + /* write size */ + err = fputc(8, fd); + if (err == EOF) { + perror("write phy mask size failed"); + return -EIO; + } + + /* write phy masks */ + err = fwrite((void *)phy_mask, 1, sizeof(phy_mask), fd); + if (err == 0) { + perror("write phy_mask failed"); + return err; + } + + /* write phy gen header */ + err = fputc(0x2, fd); + if (err == EOF) { + perror("write phy gen header failed"); + return -EIO; + } + + /* write size */ + err = fputc(8, fd); + if (err == EOF) { + perror("write phy gen size failed"); + return -EIO; + } + + /* write phy_gen */ + err = fwrite((void *)phy_gen, + 1, + sizeof(phy_gen), + fd); + if (err == 0) { + perror("write phy_gen failed"); + return err; + } + + /* write phy gen header */ + err = fputc(0x3, fd); + if (err == EOF) { + perror("write sas addr header failed"); + return -EIO; + } + + /* write size */ + err = fputc(8, fd); + if (err == EOF) { + perror("write sas addr size failed"); + return -EIO; + } + + /* write sas_addr */ + err = fwrite((void *)sas_addr, + 1, + sizeof(sas_addr), + fd); + if (err == 0) { + perror("write sas_addr failed"); + return err; + } + + /* write end header */ + err = fputc(0xff, fd); + if (err == EOF) { + perror("write end header failed"); + return -EIO; + } + + fclose(fd); + + return 0; +} + +int main(void) +{ + int err; + + err = write_blob(); + if (err < 0) + return err; + + return 0; +} diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c new file mode 100644 index 000000000000..6f16f4d6c82b --- /dev/null +++ b/drivers/scsi/isci/host.c @@ -0,0 +1,781 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "isci.h" +#include "scic_io_request.h" +#include "scic_remote_device.h" +#include "scic_port.h" + +#include "port.h" +#include "request.h" +#include "host.h" + +/** + * isci_isr() - This function is the interrupt service routine for the + * controller. It schedules the tasklet and returns. + * @vec: This parameter specifies the interrupt vector. + * @data: This parameter specifies the ISCI host object. + * + * IRQ_HANDLED if out interrupt otherwise, IRQ_NONE + */ +irqreturn_t isci_isr(int vec, void *data) +{ + struct isci_host *isci_host + = (struct isci_host *)data; + struct scic_controller_handler_methods *handlers + = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; + irqreturn_t ret = IRQ_NONE; + + if (isci_host_get_state(isci_host) != isci_starting + && handlers->interrupt_handler) { + + if (handlers->interrupt_handler(isci_host->core_controller)) { + if (isci_host_get_state(isci_host) != isci_stopped) { + tasklet_schedule( + &isci_host->completion_tasklet); + } else + dev_dbg(&isci_host->pdev->dev, + "%s: controller stopped\n", + __func__); + ret = IRQ_HANDLED; + } + } else + dev_warn(&isci_host->pdev->dev, + "%s: get_handler_methods failed, " + "isci_host->status = 0x%x\n", + __func__, + isci_host_get_state(isci_host)); + + return ret; +} + +irqreturn_t isci_legacy_isr(int vec, void *data) +{ + struct pci_dev *pdev = data; + struct isci_host *isci_host; + struct scic_controller_handler_methods *handlers; + irqreturn_t ret = IRQ_NONE; + + /* + * Since this is a legacy interrupt, either or both + * controllers could have triggered it. Thus, we have to call + * the legacy interrupt handler for all controllers on the + * PCI function. + */ + for_each_isci_host(isci_host, pdev) { + handlers = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; + + if (isci_host_get_state(isci_host) != isci_starting + && handlers->interrupt_handler) { + + if (handlers->interrupt_handler(isci_host->core_controller)) { + if (isci_host_get_state(isci_host) != isci_stopped) { + tasklet_schedule( + &isci_host->completion_tasklet); + } else + dev_dbg(&isci_host->pdev->dev, + "%s: controller stopped\n", + __func__); + ret = IRQ_HANDLED; + } + } else + dev_warn(&isci_host->pdev->dev, + "%s: get_handler_methods failed, " + "isci_host->status = 0x%x\n", + __func__, + isci_host_get_state(isci_host)); + } + return ret; +} + + +/** + * isci_host_start_complete() - This function is called by the core library, + * through the ISCI Module, to indicate controller start status. + * @isci_host: This parameter specifies the ISCI host object + * @completion_status: This parameter specifies the completion status from the + * core library. + * + */ +void isci_host_start_complete( + struct isci_host *isci_host, + enum sci_status completion_status) +{ + if (completion_status == SCI_SUCCESS) { + dev_dbg(&isci_host->pdev->dev, + "%s: completion_status: SCI_SUCCESS\n", __func__); + isci_host_change_state(isci_host, isci_ready); + complete_all(&isci_host->start_complete); + } else + dev_err(&isci_host->pdev->dev, + "controller start failed with " + "completion_status = 0x%x;", + completion_status); + +} + + + +/** + * isci_host_scan_finished() - This function is one of the SCSI Host Template + * functions. The SCSI midlayer calls this function during a target scan, + * approx. once every 10 millisecs. + * @shost: This parameter specifies the SCSI host being scanned + * @time: This parameter specifies the number of ticks since the scan started. + * + * scan status, zero indicates the SCSI midlayer should continue to poll, + * otherwise assume controller is ready. + */ +int isci_host_scan_finished( + struct Scsi_Host *shost, + unsigned long time) +{ + struct isci_host *isci_host + = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); + + struct scic_controller_handler_methods *handlers + = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; + + if (handlers->interrupt_handler == NULL) { + dev_err(&isci_host->pdev->dev, + "%s: scic_controller_get_handler_methods failed\n", + __func__); + return 1; + } + + /** + * check interrupt_handler's status and call completion_handler if true, + * link_up events should be coming from the scu core lib, as phy's come + * online. for each link_up from the core, call + * get_received_identify_address_frame, copy the frame into the + * sas_phy object and call libsas notify_port_event(PORTE_BYTES_DMAED). + * continue to return zero from thee scan_finished routine until + * the scic_cb_controller_start_complete() call comes from the core. + **/ + if (handlers->interrupt_handler(isci_host->core_controller)) + handlers->completion_handler(isci_host->core_controller); + + if (isci_starting == isci_host_get_state(isci_host) + && time < (HZ * 10)) { + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host->status = %d, time = %ld\n", + __func__, isci_host_get_state(isci_host), time); + return 0; + } + + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host->status = %d, time = %ld\n", + __func__, isci_host_get_state(isci_host), time); + + scic_controller_enable_interrupts(isci_host->core_controller); + + return 1; + +} + + +/** + * isci_host_scan_start() - This function is one of the SCSI Host Template + * function, called by the SCSI mid layer berfore a target scan begins. The + * core library controller start routine is called from here. + * @shost: This parameter specifies the SCSI host to be scanned + * + */ +void isci_host_scan_start(struct Scsi_Host *shost) +{ + struct isci_host *isci_host; + + isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); + isci_host_change_state(isci_host, isci_starting); + + scic_controller_disable_interrupts(isci_host->core_controller); + init_completion(&isci_host->start_complete); + scic_controller_start( + isci_host->core_controller, + scic_controller_get_suggested_start_timeout( + isci_host->core_controller) + ); +} + +void isci_host_stop_complete( + struct isci_host *isci_host, + enum sci_status completion_status) +{ + isci_host_change_state(isci_host, isci_stopped); + scic_controller_disable_interrupts( + isci_host->core_controller + ); + complete(&isci_host->stop_complete); +} + +static struct coherent_memory_info *isci_host_alloc_mdl_struct( + struct isci_host *isci_host, + u32 size) +{ + struct coherent_memory_info *mdl_struct; + void *uncached_address = NULL; + + + mdl_struct = devm_kzalloc(&isci_host->pdev->dev, + sizeof(*mdl_struct), + GFP_KERNEL); + if (!mdl_struct) + return NULL; + + INIT_LIST_HEAD(&mdl_struct->node); + + uncached_address = dmam_alloc_coherent(&isci_host->pdev->dev, + size, + &mdl_struct->dma_handle, + GFP_KERNEL); + if (!uncached_address) + return NULL; + + /* memset the whole memory area. */ + memset((char *)uncached_address, 0, size); + mdl_struct->vaddr = uncached_address; + mdl_struct->size = (size_t)size; + + return mdl_struct; +} + +static void isci_host_build_mde( + struct sci_physical_memory_descriptor *mde_struct, + struct coherent_memory_info *mdl_struct) +{ + unsigned long address = 0; + dma_addr_t dma_addr = 0; + + address = (unsigned long)mdl_struct->vaddr; + dma_addr = mdl_struct->dma_handle; + + /* to satisfy the alignment. */ + if ((address % mde_struct->constant_memory_alignment) != 0) { + int align_offset + = (mde_struct->constant_memory_alignment + - (address % mde_struct->constant_memory_alignment)); + address += align_offset; + dma_addr += align_offset; + } + + mde_struct->virtual_address = (void *)address; + mde_struct->physical_address = dma_addr; + mdl_struct->mde = mde_struct; +} + +static int isci_host_mdl_allocate_coherent( + struct isci_host *isci_host) +{ + struct sci_physical_memory_descriptor *current_mde; + struct coherent_memory_info *mdl_struct; + u32 size = 0; + + struct sci_base_memory_descriptor_list *mdl_handle + = sci_controller_get_memory_descriptor_list_handle( + isci_host->core_controller); + + sci_mdl_first_entry(mdl_handle); + + current_mde = sci_mdl_get_current_entry(mdl_handle); + + while (current_mde != NULL) { + + size = (current_mde->constant_memory_size + + current_mde->constant_memory_alignment); + + mdl_struct = isci_host_alloc_mdl_struct(isci_host, size); + if (!mdl_struct) + return -ENOMEM; + + list_add_tail(&mdl_struct->node, &isci_host->mdl_struct_list); + + isci_host_build_mde(current_mde, mdl_struct); + + sci_mdl_next_entry(mdl_handle); + current_mde = sci_mdl_get_current_entry(mdl_handle); + } + + return 0; +} + + +/** + * isci_host_completion_routine() - This function is the delayed service + * routine that calls the sci core library's completion handler. It's + * scheduled as a tasklet from the interrupt service routine when interrupts + * in use, or set as the timeout function in polled mode. + * @data: This parameter specifies the ISCI host object + * + */ +static void isci_host_completion_routine(unsigned long data) +{ + struct isci_host *isci_host = (struct isci_host *)data; + struct scic_controller_handler_methods *handlers + = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; + struct list_head completed_request_list; + struct list_head aborted_request_list; + struct list_head *current_position; + struct list_head *next_position; + struct isci_request *request; + struct isci_request *next_request; + struct sas_task *task; + + INIT_LIST_HEAD(&completed_request_list); + INIT_LIST_HEAD(&aborted_request_list); + + spin_lock_irq(&isci_host->scic_lock); + + if (handlers->completion_handler) { + handlers->completion_handler( + isci_host->core_controller + ); + } + /* Take the lists of completed I/Os from the host. */ + list_splice_init(&isci_host->requests_to_complete, + &completed_request_list); + + list_splice_init(&isci_host->requests_to_abort, + &aborted_request_list); + + spin_unlock_irq(&isci_host->scic_lock); + + /* Process any completions in the lists. */ + list_for_each_safe(current_position, next_position, + &completed_request_list) { + + request = list_entry(current_position, struct isci_request, + completed_node); + task = isci_request_access_task(request); + + /* Normal notification (task_done) */ + dev_dbg(&isci_host->pdev->dev, + "%s: Normal - request/task = %p/%p\n", + __func__, + request, + task); + + task->task_done(task); + task->lldd_task = NULL; + + /* Free the request object. */ + isci_request_free(isci_host, request); + } + list_for_each_entry_safe(request, next_request, &aborted_request_list, + completed_node) { + + task = isci_request_access_task(request); + + /* Use sas_task_abort */ + dev_warn(&isci_host->pdev->dev, + "%s: Error - request/task = %p/%p\n", + __func__, + request, + task); + + /* Put the task into the abort path. */ + sas_task_abort(task); + } + +} + +void isci_host_deinit( + struct isci_host *isci_host) +{ + int i; + + isci_host_change_state(isci_host, isci_stopping); + for (i = 0; i < SCI_MAX_PORTS; i++) { + struct isci_port *port = &isci_host->isci_ports[i]; + struct isci_remote_device *device, *tmpdev; + list_for_each_entry_safe(device, tmpdev, + &port->remote_dev_list, node) { + isci_remote_device_change_state(device, isci_stopping); + isci_remote_device_stop(device); + } + } + + /* stop the comtroller and wait for completion. */ + init_completion(&isci_host->stop_complete); + scic_controller_stop( + isci_host->core_controller, + SCIC_CONTROLLER_STOP_TIMEOUT + ); + wait_for_completion(&isci_host->stop_complete); + /* next, reset the controller. */ + scic_controller_reset(isci_host->core_controller); +} + +static int isci_verify_firmware(const struct firmware *fw, + struct isci_firmware *isci_fw) +{ + const u8 *tmp; + + if (fw->size < ISCI_FIRMWARE_MIN_SIZE) + return -EINVAL; + + tmp = fw->data; + + /* 12th char should be the NULL terminate for the ID string */ + if (tmp[11] != '\0') + return -EINVAL; + + if (strncmp("#SCU MAGIC#", tmp, 11) != 0) + return -EINVAL; + + isci_fw->id = tmp; + isci_fw->version = fw->data[ISCI_FW_VER_OFS]; + isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS]; + + tmp = fw->data + ISCI_FW_DATA_OFS; + + while (*tmp != ISCI_FW_HDR_EOF) { + switch (*tmp) { + case ISCI_FW_HDR_PHYMASK: + tmp++; + isci_fw->phy_masks_size = *tmp; + tmp++; + isci_fw->phy_masks = (const u32 *)tmp; + tmp += sizeof(u32) * isci_fw->phy_masks_size; + break; + + case ISCI_FW_HDR_PHYGEN: + tmp++; + isci_fw->phy_gens_size = *tmp; + tmp++; + isci_fw->phy_gens = (const u32 *)tmp; + tmp += sizeof(u32) * isci_fw->phy_gens_size; + break; + + case ISCI_FW_HDR_SASADDR: + tmp++; + isci_fw->sas_addrs_size = *tmp; + tmp++; + isci_fw->sas_addrs = (const u64 *)tmp; + tmp += sizeof(u64) * isci_fw->sas_addrs_size; + break; + + default: + pr_err("bad field in firmware binary blob\n"); + return -EINVAL; + } + } + + pr_info("isci firmware v%u.%u loaded.\n", + isci_fw->version, isci_fw->subversion); + + return SCI_SUCCESS; +} + +static void __iomem *scu_base(struct isci_host *isci_host) +{ + struct pci_dev *pdev = isci_host->pdev; + int id = isci_host->id; + + return pcim_iomap_table(pdev)[SCI_SCU_BAR * 2] + SCI_SCU_BAR_SIZE * id; +} + +static void __iomem *smu_base(struct isci_host *isci_host) +{ + struct pci_dev *pdev = isci_host->pdev; + int id = isci_host->id; + + return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; +} + +#define SCI_MAX_TIMER_COUNT 25 + +int isci_host_init(struct isci_host *isci_host) +{ + int err = 0; + int index = 0; + enum sci_status status; + struct scic_sds_controller *controller; + struct scic_sds_port *scic_port; + struct scic_controller_handler_methods *handlers + = &isci_host->scic_irq_handlers[0]; + union scic_oem_parameters scic_oem_params; + union scic_user_parameters scic_user_params; + const struct firmware *fw = NULL; + struct isci_firmware *isci_fw = NULL; + + INIT_LIST_HEAD(&isci_host->timer_list_struct.timers); + isci_timer_list_construct( + &isci_host->timer_list_struct, + SCI_MAX_TIMER_COUNT + ); + + controller = scic_controller_alloc(&isci_host->pdev->dev); + + if (!controller) { + err = -ENOMEM; + dev_err(&isci_host->pdev->dev, "%s: failed (%d)\n", __func__, err); + goto out; + } + + isci_host->core_controller = controller; + spin_lock_init(&isci_host->state_lock); + spin_lock_init(&isci_host->scic_lock); + spin_lock_init(&isci_host->queue_lock); + + isci_host_change_state(isci_host, isci_starting); + isci_host->can_queue = ISCI_CAN_QUEUE_VAL; + + status = scic_controller_construct(controller, scu_base(isci_host), + smu_base(isci_host)); + + if (status != SCI_SUCCESS) { + dev_err(&isci_host->pdev->dev, + "%s: scic_controller_construct failed - status = %x\n", + __func__, + status); + err = -ENODEV; + goto out; + } + + isci_host->sas_ha.dev = &isci_host->pdev->dev; + isci_host->sas_ha.lldd_ha = isci_host; + + /*----------- SCIC controller Initialization Stuff ------------------ + * set association host adapter struct in core controller. + */ + sci_object_set_association(isci_host->core_controller, + (void *)isci_host + ); + + /* grab initial values stored in the controller object for OEM and USER + * parameters */ + scic_oem_parameters_get(controller, &scic_oem_params); + scic_user_parameters_get(controller, &scic_user_params); + + isci_fw = devm_kzalloc(&isci_host->pdev->dev, + sizeof(struct isci_firmware), + GFP_KERNEL); + if (!isci_fw) { + dev_warn(&isci_host->pdev->dev, + "allocating firmware struct failed\n"); + dev_warn(&isci_host->pdev->dev, + "Default OEM configuration being used:" + " 4 narrow ports, and default SAS Addresses\n"); + goto set_default_params; + } + + status = request_firmware(&fw, ISCI_FW_NAME, &isci_host->pdev->dev); + if (status) { + dev_warn(&isci_host->pdev->dev, + "Loading firmware failed, using default values\n"); + dev_warn(&isci_host->pdev->dev, + "Default OEM configuration being used:" + " 4 narrow ports, and default SAS Addresses\n"); + goto set_default_params; + } + else { + status = isci_verify_firmware(fw, isci_fw); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "firmware verification failed\n"); + dev_warn(&isci_host->pdev->dev, + "Default OEM configuration being used:" + " 4 narrow ports, and default SAS " + "Addresses\n"); + goto set_default_params; + } + + /* grab any OEM and USER parameters specified at module load */ + status = isci_parse_oem_parameters(&scic_oem_params, + isci_host->id, isci_fw); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "parsing firmware oem parameters failed\n"); + err = -EINVAL; + goto out; + } + + status = isci_parse_user_parameters(&scic_user_params, + isci_host->id, isci_fw); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: isci_parse_user_parameters" + " failed\n", __func__); + err = -EINVAL; + goto out; + } + } + + set_default_params: + + status = scic_oem_parameters_set(isci_host->core_controller, + &scic_oem_params + ); + + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: scic_oem_parameters_set failed\n", + __func__); + err = -ENODEV; + goto out; + } + + + status = scic_user_parameters_set(isci_host->core_controller, + &scic_user_params + ); + + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: scic_user_parameters_set failed\n", + __func__); + err = -ENODEV; + goto out; + } + + status = scic_controller_initialize(isci_host->core_controller); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: scic_controller_initialize failed -" + " status = 0x%x\n", + __func__, status); + err = -ENODEV; + goto out; + } + + /* @todo: use both MSI-X interrupts, and don't do indirect + * calls to the handlers just register direct calls + */ + if (isci_host->pdev->msix_enabled) { + status = scic_controller_get_handler_methods( + SCIC_MSIX_INTERRUPT_TYPE, + SCI_MSIX_DOUBLE_VECTOR, + handlers + ); + } else { + status = scic_controller_get_handler_methods( + SCIC_LEGACY_LINE_INTERRUPT_TYPE, + 0, + handlers + ); + } + + if (status != SCI_SUCCESS) { + handlers->interrupt_handler = NULL; + handlers->completion_handler = NULL; + dev_err(&isci_host->pdev->dev, + "%s: scic_controller_get_handler_methods failed\n", + __func__); + } + + tasklet_init(&isci_host->completion_tasklet, + isci_host_completion_routine, + (unsigned long)isci_host + ); + + INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); + + INIT_LIST_HEAD(&isci_host->requests_to_complete); + INIT_LIST_HEAD(&isci_host->requests_to_abort); + + /* populate mdl with dma memory. scu_mdl_allocate_coherent() */ + err = isci_host_mdl_allocate_coherent(isci_host); + + if (err) + goto err_out; + + /* + * keep the pool alloc size around, will use it for a bounds checking + * when trying to convert virtual addresses to physical addresses + */ + isci_host->dma_pool_alloc_size = sizeof(struct isci_request) + + scic_io_request_get_object_size(); + isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev, + isci_host->dma_pool_alloc_size, + SLAB_HWCACHE_ALIGN, 0); + + if (!isci_host->dma_pool) { + err = -ENOMEM; + goto req_obj_err_out; + } + + for (index = 0; index < SCI_MAX_PORTS; index++) { + isci_port_init(&isci_host->isci_ports[index], + isci_host, index); + } + + for (index = 0; index < SCI_MAX_PHYS; index++) + isci_phy_init(&isci_host->phys[index], isci_host, index); + + /* Why are we doing this? Is this even necessary? */ + memcpy(&isci_host->sas_addr[0], &isci_host->phys[0].sas_addr[0], + SAS_ADDR_SIZE); + + /* Start the ports */ + for (index = 0; index < SCI_MAX_PORTS; index++) { + + scic_controller_get_port_handle(controller, index, &scic_port); + scic_port_start(scic_port); + } + + goto out; + +/* SPB_Debug: destroy request object cache */ + req_obj_err_out: +/* SPB_Debug: destroy remote object cache */ + err_out: +/* SPB_Debug: undo controller init, construct and alloc, remove from parent + * controller list. */ + out: + if (fw) + release_firmware(fw); + return err; +} diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h new file mode 100644 index 000000000000..3530076d6107 --- /dev/null +++ b/drivers/scsi/isci/host.h @@ -0,0 +1,283 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the isci_module initialization routines. + * + * host.h + */ + + + +#if !defined(_SCI_HOST_H_) +#define _SCI_HOST_H_ + +#include "phy.h" +/*#include "task.h"*/ +#include "timers.h" +#include "remote_device.h" +#include "scic_user_callback.h" + +#define DRV_NAME "isci" +#define SCI_PCI_BAR_COUNT 2 +#define SCI_NUM_MSI_X_INT 2 +#define SCI_SMU_BAR 0 +#define SCI_SMU_BAR_SIZE (16*1024) +#define SCI_SCU_BAR 1 +#define SCI_SCU_BAR_SIZE (4*1024*1024) +#define SCI_IO_SPACE_BAR0 2 +#define SCI_IO_SPACE_BAR1 3 +#define SCI_MSIX_NORMAL_VECTOR 0 +#define SCI_MSIX_ERROR_VECTOR 1 +#define SCI_MSIX_SINGLE_VECTOR 1 +#define SCI_MSIX_DOUBLE_VECTOR 2 +#define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */ +#define SCIC_CONTROLLER_STOP_TIMEOUT 5000 + +struct coherent_memory_info { + struct list_head node; + dma_addr_t dma_handle; + void *vaddr; + size_t size; + struct sci_physical_memory_descriptor *mde; +}; + +struct isci_host { + struct scic_sds_controller *core_controller; + struct scic_controller_handler_methods scic_irq_handlers[SCI_NUM_MSI_X_INT]; + union scic_oem_parameters oem_parameters; + + int id; /* unique within a given pci device */ + struct isci_timer_list timer_list_struct; + void *core_ctrl_memory; + struct dma_pool *dma_pool; + unsigned int dma_pool_alloc_size; + struct isci_phy phys[SCI_MAX_PHYS]; + + /* isci_ports and sas_ports are implicitly parallel to the + * ports maintained by the core + */ + struct isci_port isci_ports[SCI_MAX_PORTS]; + struct asd_sas_port sas_ports[SCI_MAX_PORTS]; + struct sas_ha_struct sas_ha; + + int can_queue; + spinlock_t queue_lock; + spinlock_t state_lock; + + struct pci_dev *pdev; + u8 sas_addr[SAS_ADDR_SIZE]; + + enum isci_status status; + struct Scsi_Host *shost; + struct tasklet_struct completion_tasklet; + struct list_head mdl_struct_list; + struct list_head requests_to_complete; + struct list_head requests_to_abort; + struct completion stop_complete; + struct completion start_complete; + spinlock_t scic_lock; + struct isci_host *next; +}; + + +/** + * struct isci_pci_info - This class represents the pci function containing the + * controllers. Depending on PCI SKU, there could be up to 2 controllers in + * the PCI function. + */ +#define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS) + +struct isci_pci_info { + struct msix_entry msix_entries[SCI_MAX_MSIX_INT]; + int core_lib_array_index; + SCI_LIBRARY_HANDLE_T core_lib_handle; + struct isci_host *hosts; +}; + +static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev) +{ + return pci_get_drvdata(pdev); +} + +#define for_each_isci_host(isci_host, pdev) \ + for (isci_host = to_pci_info(pdev)->hosts;\ + isci_host; isci_host = isci_host->next) + +static inline +enum isci_status isci_host_get_state( + struct isci_host *isci_host) +{ + return isci_host->status; +} + + +static inline void isci_host_change_state( + struct isci_host *isci_host, + enum isci_status status) +{ + unsigned long flags; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host = %p, state = 0x%x", + __func__, + isci_host, + status); + spin_lock_irqsave(&isci_host->state_lock, flags); + isci_host->status = status; + spin_unlock_irqrestore(&isci_host->state_lock, flags); + +} + +static inline int isci_host_can_queue( + struct isci_host *isci_host, + int num) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&isci_host->queue_lock, flags); + if ((isci_host->can_queue - num) < 0) { + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host->can_queue = %d\n", + __func__, + isci_host->can_queue); + ret = -SAS_QUEUE_FULL; + + } else + isci_host->can_queue -= num; + + spin_unlock_irqrestore(&isci_host->queue_lock, flags); + + return ret; +} + +static inline void isci_host_can_dequeue( + struct isci_host *isci_host, + int num) +{ + unsigned long flags; + + spin_lock_irqsave(&isci_host->queue_lock, flags); + isci_host->can_queue += num; + spin_unlock_irqrestore(&isci_host->queue_lock, flags); +} + +/** + * isci_host_from_sas_ha() - This accessor retrieves the isci_host object + * reference from the Linux sas_ha_struct reference. + * @ha_struct,: This parameter points to the Linux sas_ha_struct object + * + * A reference to the associated isci_host structure. + */ +#define isci_host_from_sas_ha(ha_struct) \ + ((struct isci_host *)(ha_struct)->lldd_ha) + +/** + * isci_host_scan_finished() - + * + * This function is one of the SCSI Host Template functions. The SCSI midlayer + * calls this function during a target scan, approx. once every 10 millisecs. + */ +int isci_host_scan_finished( + struct Scsi_Host *, + unsigned long); + + +/** + * isci_host_scan_start() - + * + * This function is one of the SCSI Host Template function, called by the SCSI + * mid layer berfore a target scan begins. The core library controller start + * routine is called from here. + */ +void isci_host_scan_start( + struct Scsi_Host *); + +/** + * isci_host_start_complete() - + * + * This function is called by the core library, through the ISCI Module, to + * indicate controller start status. + */ +void isci_host_start_complete( + struct isci_host *, + enum sci_status); + +void isci_host_stop_complete( + struct isci_host *isci_host, + enum sci_status completion_status); + +int isci_host_init(struct isci_host *); + +void isci_host_init_controller_names( + struct isci_host *isci_host, + unsigned int controller_idx); + +void isci_host_deinit( + struct isci_host *); + +void isci_host_port_link_up( + struct isci_host *, + struct scic_sds_port *, + struct scic_sds_phy *); +int isci_host_dev_found(struct domain_device *); + +void isci_host_remote_device_start_complete( + struct isci_host *, + struct isci_remote_device *, + enum sci_status); + +#endif /* !defined(_SCI_HOST_H_) */ diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c new file mode 100644 index 000000000000..07b072f3004d --- /dev/null +++ b/drivers/scsi/isci/init.c @@ -0,0 +1,613 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "isci.h" +#include "task.h" +#include "sci_controller_constants.h" +#include "scic_remote_device.h" +#include "sci_environment.h" + +static struct scsi_transport_template *isci_transport_template; +struct kmem_cache *isci_kmem_cache; + +static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { + { PCI_VDEVICE(INTEL, 0x1D61),}, + { PCI_VDEVICE(INTEL, 0x1D63),}, + { PCI_VDEVICE(INTEL, 0x1D65),}, + { PCI_VDEVICE(INTEL, 0x1D67),}, + { PCI_VDEVICE(INTEL, 0x1D69),}, + { PCI_VDEVICE(INTEL, 0x1D6B),}, + { PCI_VDEVICE(INTEL, 0x1D60),}, + { PCI_VDEVICE(INTEL, 0x1D62),}, + { PCI_VDEVICE(INTEL, 0x1D64),}, + { PCI_VDEVICE(INTEL, 0x1D66),}, + { PCI_VDEVICE(INTEL, 0x1D68),}, + { PCI_VDEVICE(INTEL, 0x1D6A),}, + {} +}; + +static int __devinit isci_pci_probe( + struct pci_dev *pdev, + const struct pci_device_id *device_id_p); + +static void __devexit isci_pci_remove(struct pci_dev *pdev); + +MODULE_DEVICE_TABLE(pci, isci_id_table); + +static struct pci_driver isci_pci_driver = { + .name = DRV_NAME, + .id_table = isci_id_table, + .probe = isci_pci_probe, + .remove = __devexit_p(isci_pci_remove), +}; + +/* linux isci specific settings */ +int loglevel = 3; +module_param(loglevel, int, S_IRUGO | S_IWUSR); + +#if defined(CONFIG_PBG_HBA_A0) +int isci_si_rev = ISCI_SI_REVA0; +#elif defined(CONFIG_PBG_HBA_A2) +int isci_si_rev = ISCI_SI_REVA2; +#else +int isci_si_rev = ISCI_SI_REVB0; +#endif +module_param(isci_si_rev, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(isci_si_rev, "override default si rev (0: A0 1: A2 2: B0)"); + +static struct scsi_host_template isci_sht = { + + .module = THIS_MODULE, + .name = DRV_NAME, + .queuecommand = sas_queuecommand, + .target_alloc = sas_target_alloc, + .slave_configure = sas_slave_configure, + .slave_destroy = sas_slave_destroy, + .scan_finished = isci_host_scan_finished, + .scan_start = isci_host_scan_start, + .change_queue_depth = sas_change_queue_depth, + .change_queue_type = sas_change_queue_type, + .bios_param = sas_bios_param, + .can_queue = ISCI_CAN_QUEUE_VAL, + .cmd_per_lun = 1, + .this_id = -1, + .sg_tablesize = SG_ALL, + .max_sectors = SCSI_DEFAULT_MAX_SECTORS, + .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, + .eh_bus_reset_handler = isci_bus_reset_handler, + .slave_alloc = sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, +}; + +static struct sas_domain_function_template isci_transport_ops = { + + /* The class calls these to notify the LLDD of an event. */ + .lldd_port_formed = isci_port_formed, + .lldd_port_deformed = isci_port_deformed, + + /* The class calls these when a device is found or gone. */ + .lldd_dev_found = isci_remote_device_found, + .lldd_dev_gone = isci_remote_device_gone, + + .lldd_execute_task = isci_task_execute_task, + /* Task Management Functions. Must be called from process context. */ + .lldd_abort_task = isci_task_abort_task, + .lldd_abort_task_set = isci_task_abort_task_set, + .lldd_clear_aca = isci_task_clear_aca, + .lldd_clear_task_set = isci_task_clear_task_set, + .lldd_I_T_nexus_reset = isci_task_I_T_nexus_reset, + .lldd_lu_reset = isci_task_lu_reset, + .lldd_query_task = isci_task_query_task, + + /* Port and Adapter management */ + .lldd_clear_nexus_port = isci_task_clear_nexus_port, + .lldd_clear_nexus_ha = isci_task_clear_nexus_ha, + + /* Phy management */ + .lldd_control_phy = isci_phy_control, +}; + + +/****************************************************************************** +* P R O T E C T E D M E T H O D S +******************************************************************************/ + + + +/** + * isci_register_sas_ha() - This method initializes various lldd + * specific members of the sas_ha struct and calls the libsas + * sas_register_ha() function. + * @isci_host: This parameter specifies the lldd specific wrapper for the + * libsas sas_ha struct. + * + * This method returns an error code indicating sucess or failure. The user + * should check for possible memory allocation error return otherwise, a zero + * indicates success. + */ +static int isci_register_sas_ha(struct isci_host *isci_host) +{ + int i; + struct sas_ha_struct *sas_ha = &(isci_host->sas_ha); + struct asd_sas_phy **sas_phys; + struct asd_sas_port **sas_ports; + + sas_phys = devm_kzalloc(&isci_host->pdev->dev, + SCI_MAX_PHYS * sizeof(void *), + GFP_KERNEL); + if (!sas_phys) + return -ENOMEM; + + sas_ports = devm_kzalloc(&isci_host->pdev->dev, + SCI_MAX_PORTS * sizeof(void *), + GFP_KERNEL); + if (!sas_ports) + return -ENOMEM; + + /*----------------- Libsas Initialization Stuff---------------------- + * Set various fields in the sas_ha struct: + */ + + sas_ha->sas_ha_name = DRV_NAME; + sas_ha->lldd_module = THIS_MODULE; + sas_ha->sas_addr = &(isci_host->sas_addr[0]); + + /* set the array of phy and port structs. */ + for (i = 0; i < SCI_MAX_PHYS; i++) { + sas_phys[i] = &(isci_host->phys[i].sas_phy); + sas_ports[i] = &(isci_host->sas_ports[i]); + } + + sas_ha->sas_phy = sas_phys; + sas_ha->sas_port = sas_ports; + sas_ha->num_phys = SCI_MAX_PHYS; + + sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL; + sas_ha->lldd_max_execute_num = 1; + sas_ha->strict_wide_ports = 1; + + sas_register_ha(sas_ha); + + return 0; +} + +static void isci_unregister_sas_ha(struct isci_host *isci_host) +{ + if (!isci_host) + return; + + sas_unregister_ha(&(isci_host->sas_ha)); + + sas_remove_host(isci_host->shost); + scsi_remove_host(isci_host->shost); + scsi_host_put(isci_host->shost); +} + +static int __devinit isci_pci_init(struct pci_dev *pdev) +{ + int err, bar_num, bar_mask; + void __iomem * const *iomap; + + err = pcim_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, + "failed enable PCI device %s!\n", + pci_name(pdev)); + return err; + } + + for (bar_num = 0; bar_num < SCI_PCI_BAR_COUNT; bar_num++) + bar_mask |= 1 << (bar_num * 2); + + err = pcim_iomap_regions(pdev, bar_mask, DRV_NAME); + if (err) + return err; + + iomap = pcim_iomap_table(pdev); + if (!iomap) + return -ENOMEM; + + pci_set_master(pdev); + + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (err) { + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) + return err; + } + + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (err) { + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) + return err; + } + + return 0; +} + +static struct isci_host *isci_host_by_id(struct pci_dev *pdev, int id) +{ + struct isci_host *h; + + for_each_isci_host(h, pdev) + if (h->id == id) + return h; + return NULL; +} + +static int num_controllers(struct pci_dev *pdev) +{ + /* bar size alone can tell us if we are running with a dual controller + * part, no need to trust revision ids that might be under broken firmware + * control + */ + resource_size_t scu_bar_size = pci_resource_len(pdev, SCI_SCU_BAR*2); + resource_size_t smu_bar_size = pci_resource_len(pdev, SCI_SMU_BAR*2); + + if (scu_bar_size >= SCI_SCU_BAR_SIZE*SCI_MAX_CONTROLLERS && + smu_bar_size >= SCI_SMU_BAR_SIZE*SCI_MAX_CONTROLLERS) + return SCI_MAX_CONTROLLERS; + else + return 1; +} + +static int isci_setup_interrupts(struct pci_dev *pdev) +{ + int err, i, num_msix; + struct isci_pci_info *pci_info = to_pci_info(pdev); + + /* + * Determine the number of vectors associated with this + * PCI function. + */ + num_msix = num_controllers(pdev) * SCI_NUM_MSI_X_INT; + + for (i = 0; i < num_msix; i++) + pci_info->msix_entries[i].entry = i; + + err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix); + if (err) + goto intx; + + for (i = 0; i < num_msix; i++) { + int id = i / SCI_NUM_MSI_X_INT; + struct msix_entry *msix = &pci_info->msix_entries[i]; + struct isci_host *isci_host = isci_host_by_id(pdev, id); + + BUG_ON(!isci_host); + + /* @todo: need to handle error case. */ + err = devm_request_irq(&pdev->dev, msix->vector, isci_isr, 0, + DRV_NAME"-msix", isci_host); + if (!err) + continue; + + dev_info(&pdev->dev, "msix setup failed falling back to intx\n"); + while (i--) { + id = i / SCI_NUM_MSI_X_INT; + isci_host = isci_host_by_id(pdev, id); + msix = &pci_info->msix_entries[i]; + devm_free_irq(&pdev->dev, msix->vector, isci_host); + } + pci_disable_msix(pdev); + goto intx; + } + + return 0; + + intx: + err = devm_request_irq(&pdev->dev, pdev->irq, isci_legacy_isr, + IRQF_SHARED, DRV_NAME"-intx", pdev); + + return err; +} + +/** + * isci_parse_oem_parameters() - This method will take OEM parameters + * from the module init parameters and copy them to oem_params. This will + * only copy values that are not set to the module parameter default values + * @oem_parameters: This parameter specifies the controller default OEM + * parameters. It is expected that this has been initialized to the default + * parameters for the controller + * + * + */ +enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, + int scu_index, + struct isci_firmware *fw) +{ + int i; + + /* check for valid inputs */ + if (!(scu_index >= 0 + && scu_index < SCI_MAX_CONTROLLERS + && oem_params != NULL)) { + return SCI_FAILURE; + } + + for (i = 0; i < SCI_MAX_PHYS; i++) { + int array_idx = i + (SCI_MAX_PHYS * scu_index); + u64 sas_addr = fw->sas_addrs[array_idx]; + + if (sas_addr != 0) { + oem_params->sds1.phys[i].sas_address.low = + (u32)(sas_addr & 0xffffffff); + oem_params->sds1.phys[i].sas_address.high = + (u32)((sas_addr >> 32) & 0xffffffff); + } + } + + for (i = 0; i < SCI_MAX_PORTS; i++) { + int array_idx = i + (SCI_MAX_PORTS * scu_index); + u32 pmask = fw->phy_masks[array_idx]; + + oem_params->sds1.ports[i].phy_mask = pmask; + } + + return SCI_SUCCESS; +} + +/** + * isci_parse_user_parameters() - This method will take user parameters + * from the module init parameters and copy them to user_params. This will + * only copy values that are not set to the module parameter default values + * @user_parameters: This parameter specifies the controller default user + * parameters. It is expected that this has been initialized to the default + * parameters for the controller + * + * + */ +enum sci_status isci_parse_user_parameters( + union scic_user_parameters *user_params, + int scu_index, + struct isci_firmware *fw) +{ + int i; + + if (!(scu_index >= 0 + && scu_index < SCI_MAX_CONTROLLERS + && user_params != NULL)) { + return SCI_FAILURE; + } + + for (i = 0; i < SCI_MAX_PORTS; i++) { + int array_idx = i + (SCI_MAX_PORTS * scu_index); + u32 gen = fw->phy_gens[array_idx]; + + user_params->sds1.phys[i].max_speed_generation = gen; + + } + + return SCI_SUCCESS; +} + +static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) +{ + struct isci_host *isci_host; + struct Scsi_Host *shost; + int err; + + isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); + if (!isci_host) + return NULL; + + isci_host->pdev = pdev; + isci_host->id = id; + + shost = scsi_host_alloc(&isci_sht, sizeof(void *)); + if (!shost) + return NULL; + isci_host->shost = shost; + + err = isci_host_init(isci_host); + if (err) + goto err_shost; + + SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha; + isci_host->sas_ha.core.shost = shost; + shost->transportt = isci_transport_template; + + shost->max_id = ~0; + shost->max_lun = ~0; + shost->max_cmd_len = MAX_COMMAND_SIZE; + + err = scsi_add_host(shost, &pdev->dev); + if (err) + goto err_shost; + + err = isci_register_sas_ha(isci_host); + if (err) + goto err_shost_remove; + + return isci_host; + + err_shost_remove: + scsi_remove_host(shost); + err_shost: + scsi_host_put(shost); + + return NULL; +} + +static void check_si_rev(struct pci_dev *pdev) +{ + if (num_controllers(pdev) > 1) + isci_si_rev = ISCI_SI_REVB0; + else { + switch (pdev->revision) { + case 0: + case 1: + /* if the id is ambiguous don't update isci_si_rev */ + break; + case 3: + isci_si_rev = ISCI_SI_REVA2; + break; + default: + case 4: + isci_si_rev = ISCI_SI_REVB0; + break; + } + } + + dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n", + isci_si_rev == ISCI_SI_REVA0 ? "A0" : + isci_si_rev == ISCI_SI_REVA2 ? "A2" : "B0", pdev->revision); + +} + +static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct isci_pci_info *pci_info; + int err, i; + struct isci_host *isci_host; + + check_si_rev(pdev); + + pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL); + if (!pci_info) + return -ENOMEM; + pci_set_drvdata(pdev, pci_info); + + err = isci_pci_init(pdev); + if (err) + return err; + + for (i = 0; i < num_controllers(pdev); i++) { + struct isci_host *h = isci_host_alloc(pdev, i); + + if (!h) { + err = -ENOMEM; + goto err_host_alloc; + } + + h->next = pci_info->hosts; + pci_info->hosts = h; + } + + err = isci_setup_interrupts(pdev); + if (err) + goto err_host_alloc; + + for_each_isci_host(isci_host, pdev) + scsi_scan_host(isci_host->shost); + + return 0; + + err_host_alloc: + for_each_isci_host(isci_host, pdev) + isci_unregister_sas_ha(isci_host); + return err; +} + +static void __devexit isci_pci_remove(struct pci_dev *pdev) +{ + struct isci_host *isci_host; + + for_each_isci_host(isci_host, pdev) { + isci_unregister_sas_ha(isci_host); + isci_host_deinit(isci_host); + scic_controller_disable_interrupts(isci_host->core_controller); + } +} + +static __init int isci_init(void) +{ + int err = -ENOMEM; + + pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME); + + isci_kmem_cache = kmem_cache_create(DRV_NAME, + sizeof(struct isci_remote_device) + + scic_remote_device_get_object_size(), + 0, 0, NULL); + if (!isci_kmem_cache) + return err; + + isci_transport_template = sas_domain_attach_transport(&isci_transport_ops); + if (!isci_transport_template) + goto err_kmem; + + err = pci_register_driver(&isci_pci_driver); + if (err) + goto err_sas; + + return 0; + + err_sas: + sas_release_transport(isci_transport_template); + err_kmem: + kmem_cache_destroy(isci_kmem_cache); + + return err; +} + +static __exit void isci_exit(void) +{ + pci_unregister_driver(&isci_pci_driver); + sas_release_transport(isci_transport_template); + kmem_cache_destroy(isci_kmem_cache); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_FIRMWARE(ISCI_FW_NAME); +module_init(isci_init); +module_exit(isci_exit); diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h new file mode 100644 index 000000000000..7d984f408f24 --- /dev/null +++ b/drivers/scsi/isci/isci.h @@ -0,0 +1,138 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the isci_module object definition. + * + * isci.h + */ + +#if !defined(_SCI_MODULE_H_) +#define _SCI_MODULE_H_ + +/** + * This file contains the SCI low level driver interface to the SCI and Libsas + * Libraries. + * + * isci.h + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sci_types.h" +#include "sci_base_controller.h" +#include "scic_controller.h" +#include "host.h" +#include "timers.h" +#include "sci_status.h" + +extern int loglevel; +extern struct kmem_cache *isci_kmem_cache; + +#define ISCI_FW_NAME "isci/isci_firmware.bin" + +#define ISCI_FIRMWARE_MIN_SIZE 149 + +#define ISCI_FW_IDSIZE 12 +#define ISCI_FW_VER_OFS ISCI_FW_IDSIZE +#define ISCI_FW_SUBVER_OFS ISCI_FW_VER_OFS + 1 +#define ISCI_FW_DATA_OFS ISCI_FW_SUBVER_OFS + 1 + +#define ISCI_FW_HDR_PHYMASK 0x1 +#define ISCI_FW_HDR_PHYGEN 0x2 +#define ISCI_FW_HDR_SASADDR 0x3 +#define ISCI_FW_HDR_EOF 0xff + +struct isci_firmware { + const u8 *id; + u8 version; + u8 subversion; + const u32 *phy_masks; + u8 phy_masks_size; + const u32 *phy_gens; + u8 phy_gens_size; + const u64 *sas_addrs; + u8 sas_addrs_size; +}; + +irqreturn_t isci_isr(int vec, void *data); +irqreturn_t isci_legacy_isr(int vec, void *data); + +enum sci_status isci_parse_oem_parameters( + union scic_oem_parameters *oem_params, + int scu_index, + struct isci_firmware *fw); + +enum sci_status isci_parse_user_parameters( + union scic_user_parameters *user_params, + int scu_index, + struct isci_firmware *fw); + +#ifdef ISCI_SLAVE_ALLOC +extern int ISCI_SLAVE_ALLOC(struct scsi_device *scsi_dev); +#endif /* ISCI_SLAVE_ALLOC */ + +#ifdef ISCI_SLAVE_DESTROY +extern void ISCI_SLAVE_DESTROY(struct scsi_device *scsi_dev); +#endif /* ISCI_SLAVE_DESTROY */ +#endif /* !defined(_SCI_MODULE_H_) */ diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c new file mode 100644 index 000000000000..fbda570d25e1 --- /dev/null +++ b/drivers/scsi/isci/phy.c @@ -0,0 +1,179 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "isci.h" +#include "phy.h" +#include "scic_port.h" +#include "scic_config_parameters.h" + + +/** + * isci_phy_init() - This function is called by the probe function to + * initialize the phy objects. This func assumes that the isci_port objects + * associated with the SCU have been initialized. + * @isci_phy: This parameter specifies the isci_phy object to initialize + * @isci_host: This parameter specifies the parent SCU host object for this + * isci_phy + * @index: This parameter specifies which SCU phy associates with this + * isci_phy. Generally, SCU phy 0 relates isci_phy 0, etc. + * + */ +void isci_phy_init( + struct isci_phy *phy, + struct isci_host *isci_host, + int index) +{ + struct scic_sds_controller *controller = isci_host->core_controller; + struct scic_sds_phy *scic_phy; + union scic_oem_parameters oem_parameters; + enum sci_status status = SCI_SUCCESS; + + /*--------------- SCU_Phy Initialization Stuff -----------------------*/ + + status = scic_controller_get_phy_handle(controller, index, &scic_phy); + if (status == SCI_SUCCESS) { + sci_object_set_association(scic_phy, (void *)phy); + phy->sci_phy_handle = scic_phy; + } else + dev_err(&isci_host->pdev->dev, + "failed scic_controller_get_phy_handle\n"); + + scic_oem_parameters_get(controller, &oem_parameters); + + phy->sas_addr[0] = oem_parameters.sds1.phys[index].sas_address.low + & 0xFF; + phy->sas_addr[1] = (oem_parameters.sds1.phys[index].sas_address.low + >> 8) & 0xFF; + phy->sas_addr[2] = (oem_parameters.sds1.phys[index].sas_address.low + >> 16) & 0xFF; + phy->sas_addr[3] = (oem_parameters.sds1.phys[index].sas_address.low + >> 24) & 0xFF; + phy->sas_addr[4] = oem_parameters.sds1.phys[index].sas_address.high + & 0xFF; + phy->sas_addr[5] = (oem_parameters.sds1.phys[index].sas_address.high + >> 8) & 0xFF; + phy->sas_addr[6] = (oem_parameters.sds1.phys[index].sas_address.high + >> 16) & 0xFF; + phy->sas_addr[7] = (oem_parameters.sds1.phys[index].sas_address.high + >> 24) & 0xFF; + + phy->isci_port = NULL; + phy->sas_phy.enabled = 0; + phy->sas_phy.id = index; + phy->sas_phy.sas_addr = &phy->sas_addr[0]; + phy->sas_phy.frame_rcvd = (u8 *)&phy->frame_rcvd; + phy->sas_phy.ha = &isci_host->sas_ha; + phy->sas_phy.lldd_phy = phy; + phy->sas_phy.enabled = 1; + phy->sas_phy.class = SAS; + phy->sas_phy.iproto = SAS_PROTOCOL_ALL; + phy->sas_phy.tproto = 0; + phy->sas_phy.type = PHY_TYPE_PHYSICAL; + phy->sas_phy.role = PHY_ROLE_INITIATOR; + phy->sas_phy.oob_mode = OOB_NOT_CONNECTED; + phy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN; + memset((u8 *)&phy->frame_rcvd, 0, sizeof(phy->frame_rcvd)); +} + + +/** + * isci_phy_control() - This function is one of the SAS Domain Template + * functions. This is a phy management function. + * @phy: This parameter specifies the sphy being controlled. + * @func: This parameter specifies the phy control function being invoked. + * @buf: This parameter is specific to the phy function being invoked. + * + * status, zero indicates success. + */ +int isci_phy_control( + struct asd_sas_phy *phy, + enum phy_func func, + void *buf) +{ + int ret = TMF_RESP_FUNC_COMPLETE; + struct isci_phy *isci_phy_ptr = (struct isci_phy *)phy->lldd_phy; + struct isci_port *isci_port_ptr = NULL; + + if (isci_phy_ptr != NULL) + isci_port_ptr = isci_phy_ptr->isci_port; + + if ((isci_phy_ptr == NULL) || (isci_port_ptr == NULL)) { + pr_err("%s: asd_sas_phy %p: lldd_phy %p or " + "isci_port %p == NULL!\n", + __func__, phy, isci_phy_ptr, isci_port_ptr); + return TMF_RESP_FUNC_FAILED; + } + + pr_debug("%s: phy %p; func %d; buf %p; isci phy %p, port %p\n", + __func__, phy, func, buf, isci_phy_ptr, isci_port_ptr); + + switch (func) { + case PHY_FUNC_HARD_RESET: + case PHY_FUNC_LINK_RESET: + + /* Perform the port reset. */ + ret = isci_port_perform_hard_reset(isci_port_ptr, isci_phy_ptr); + + break; + + case PHY_FUNC_DISABLE: + default: + pr_debug("%s: phy %p; func %d NOT IMPLEMENTED!\n", + __func__, phy, func); + ret = TMF_RESP_FUNC_FAILED; + break; + } + return ret; +} diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h new file mode 100644 index 000000000000..44b727f1c455 --- /dev/null +++ b/drivers/scsi/isci/phy.h @@ -0,0 +1,104 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#if !defined(_ISCI_PHY_H_) +#define _ISCI_PHY_H_ + +#include "port.h" +#include "host.h" +#include + + +/** + * struct isci_phy - This class implements the ISCI specific representation of + * the phy object. + * + * + */ + +struct isci_phy { + + struct scic_sds_phy *sci_phy_handle; + + struct asd_sas_phy sas_phy; + struct sas_identify_frame *frame; + struct isci_port *isci_port; + u8 sas_addr[SAS_ADDR_SIZE]; + + union { + + u8 aif[sizeof(struct sci_sas_identify_address_frame)]; + u8 fis[sizeof(struct sata_fis_reg_d2h)]; + + } frame_rcvd; +}; + +#define to_isci_phy(p) \ + container_of(p, struct isci_phy, sas_phy); + +struct isci_host; + +void isci_phy_init( + struct isci_phy *phy, + struct isci_host *isci_host, + int index); + +int isci_phy_control( + struct asd_sas_phy *phy, + enum phy_func func, + void *buf); + +#endif /* !defined(_ISCI_PHY_H_) */ diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c new file mode 100644 index 000000000000..2343f6556428 --- /dev/null +++ b/drivers/scsi/isci/port.c @@ -0,0 +1,484 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the isci port implementation. + * + * + */ + + +#include +#include "isci.h" +#include "scic_io_request.h" +#include "scic_remote_device.h" +#include "scic_phy.h" +#include "scic_sds_phy.h" +#include "scic_port.h" +#include "port.h" +#include "request.h" + +static void isci_port_change_state( + struct isci_port *isci_port, + enum isci_status status); + + + +/** + * isci_port_init() - This function initializes the given isci_port object. + * @isci_port: This parameter specifies the port object to be initialized. + * @isci_host: This parameter specifies parent controller object for the port. + * @index: This parameter specifies which SCU port the isci_port associates + * with. Generally, SCU port 0 relates to isci_port 0, etc. + * + */ +void isci_port_init( + struct isci_port *isci_port, + struct isci_host *isci_host, + int index) +{ + struct scic_sds_port *scic_port; + struct scic_sds_controller *controller = isci_host->core_controller; + + INIT_LIST_HEAD(&isci_port->remote_dev_list); + INIT_LIST_HEAD(&isci_port->domain_dev_list); + spin_lock_init(&isci_port->remote_device_lock); + spin_lock_init(&isci_port->state_lock); + init_completion(&isci_port->start_complete); + isci_port->isci_host = isci_host; + isci_port_change_state(isci_port, isci_freed); + + (void)scic_controller_get_port_handle(controller, index, &scic_port); + sci_object_set_association(scic_port, isci_port); + isci_port->sci_port_handle = scic_port; +} + + +/** + * isci_port_get_state() - This function gets the status of the port object. + * @isci_port: This parameter points to the isci_port object + * + * status of the object as a isci_status enum. + */ +enum isci_status isci_port_get_state( + struct isci_port *isci_port) +{ + return isci_port->status; +} + +static void isci_port_change_state( + struct isci_port *isci_port, + enum isci_status status) +{ + unsigned long flags; + + dev_dbg(&isci_port->isci_host->pdev->dev, + "%s: isci_port = %p, state = 0x%x\n", + __func__, isci_port, status); + + spin_lock_irqsave(&isci_port->state_lock, flags); + isci_port->status = status; + spin_unlock_irqrestore(&isci_port->state_lock, flags); +} + +void isci_port_bc_change_received( + struct isci_host *isci_host, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + struct isci_phy *isci_phy = + (struct isci_phy *)sci_object_get_association(phy); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_phy = %p, sas_phy = %p\n", + __func__, + isci_phy, + &isci_phy->sas_phy); + + isci_host->sas_ha.notify_port_event( + &isci_phy->sas_phy, + PORTE_BROADCAST_RCVD + ); + + scic_port_enable_broadcast_change_notification(port); +} + +/** + * isci_port_link_up() - This function is called by the sci core when a link + * becomes active. the identify address frame is retrieved from the core and + * a notify port event is sent to libsas. + * @isci_host: This parameter specifies the isci host object. + * @port: This parameter specifies the sci port with the active link. + * @phy: This parameter specifies the sci phy with the active link. + * + */ +void isci_port_link_up( + struct isci_host *isci_host, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + unsigned long flags; + struct scic_port_properties properties; + struct isci_phy *isci_phy + = (struct isci_phy *)sci_object_get_association(phy); + struct isci_port *isci_port + = (struct isci_port *)sci_object_get_association(port); + enum sci_status call_status; + unsigned long success = true; + + BUG_ON(isci_phy->isci_port != NULL); + isci_phy->isci_port = isci_port; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p\n", + __func__, isci_port); + + spin_lock_irqsave(&isci_phy->sas_phy.frame_rcvd_lock, flags); + + isci_port_change_state(isci_phy->isci_port, isci_starting); + + scic_port_get_properties(port, &properties); + + if (properties.remote.protocols.u.bits.stp_target) { + + struct scic_sata_phy_properties sata_phy_properties; + + isci_phy->sas_phy.oob_mode = SATA_OOB_MODE; + + /* Get a copy of the signature fis for libsas */ + call_status = scic_sata_phy_get_properties(phy, + &sata_phy_properties); + + /* + * XXX I am concerned about this "assert". shouldn't we + * handle the return appropriately? + */ + BUG_ON(call_status != SCI_SUCCESS); + + memcpy(isci_phy->frame_rcvd.fis, + &sata_phy_properties.signature_fis, + sizeof(struct sata_fis_reg_d2h)); + + isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sata_fis_reg_d2h); + + /* + * For direct-attached SATA devices, the SCI core will + * automagically assign a SAS address to the end device + * for the purpose of creating a port. This SAS address + * will not be the same as assigned to the PHY and needs + * to be obtained from struct scic_port_properties properties. + */ + + BUG_ON(((size_t)SAS_ADDR_SIZE / 2) + != sizeof(properties.remote.sas_address.low)); + + memcpy(&isci_phy->sas_phy.attached_sas_addr[0], + &properties.remote.sas_address.low, + SAS_ADDR_SIZE / 2); + + memcpy(&isci_phy->sas_phy.attached_sas_addr[4], + &properties.remote.sas_address.high, + SAS_ADDR_SIZE / 2); + + } else if (properties.remote.protocols.u.bits.ssp_target || + properties.remote.protocols.u.bits.smp_target) { + + struct scic_sas_phy_properties sas_phy_properties; + + isci_phy->sas_phy.oob_mode = SAS_OOB_MODE; + + /* Get a copy of the identify address frame for libsas */ + call_status = scic_sas_phy_get_properties(phy, + &sas_phy_properties); + + BUG_ON(call_status != SCI_SUCCESS); + + memcpy(isci_phy->frame_rcvd.aif, + &(sas_phy_properties.received_iaf), + sizeof(struct sci_sas_identify_address_frame)); + + isci_phy->sas_phy.frame_rcvd_size + = sizeof(struct sci_sas_identify_address_frame); + + /* Copy the attached SAS address from the IAF */ + memcpy(isci_phy->sas_phy.attached_sas_addr, + ((struct sas_identify_frame *) + (&isci_phy->frame_rcvd.aif))->sas_addr, + SAS_ADDR_SIZE); + + } else { + dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__); + success = false; + } + + spin_unlock_irqrestore(&isci_phy->sas_phy.frame_rcvd_lock, flags); + + /* Notify libsas that we have an address frame, if indeed + * we've found an SSP, SMP, or STP target */ + if (success) + isci_host->sas_ha.notify_port_event(&isci_phy->sas_phy, + PORTE_BYTES_DMAED); +} + + +/** + * isci_port_link_down() - This function is called by the sci core when a link + * becomes inactive. + * @isci_host: This parameter specifies the isci host object. + * @phy: This parameter specifies the isci phy with the active link. + * @port: This parameter specifies the isci port with the active link. + * + */ +void isci_port_link_down( + struct isci_host *isci_host, + struct isci_phy *isci_phy, + struct isci_port *isci_port) +{ + struct isci_remote_device *isci_device; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p\n", __func__, isci_port); + + if (isci_port) { + + /* check to see if this is the last phy on this port. */ + if (isci_phy->sas_phy.port + && isci_phy->sas_phy.port->num_phys == 1) { + + /* change the state for all devices on this port. + * The next task sent to this device will be returned + * as SAS_TASK_UNDELIVERED, and the scsi mid layer + * will remove the target + */ + list_for_each_entry(isci_device, + &isci_port->remote_dev_list, + node) { + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", + __func__, isci_device); + isci_remote_device_change_state(isci_device, + isci_stopping); + } + } + isci_port_change_state(isci_port, isci_stopping); + } + + /* Notify libsas of the borken link, this will trigger calls to our + * isci_port_deformed and isci_dev_gone functions. + */ + sas_phy_disconnected(&isci_phy->sas_phy); + isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy, + PHYE_LOSS_OF_SIGNAL); + + isci_phy->isci_port = NULL; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p - Done\n", __func__, isci_port); +} + + +/** + * isci_port_deformed() - This function is called by libsas when a port becomes + * inactive. + * @phy: This parameter specifies the libsas phy with the inactive port. + * + */ +void isci_port_deformed( + struct asd_sas_phy *phy) +{ + pr_debug("%s: sas_phy = %p\n", __func__, phy); +} + +/** + * isci_port_formed() - This function is called by libsas when a port becomes + * active. + * @phy: This parameter specifies the libsas phy with the active port. + * + */ +void isci_port_formed( + struct asd_sas_phy *phy) +{ + pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port); +} + +/** + * isci_port_ready() - This function is called by the sci core when a link + * becomes ready. + * @isci_host: This parameter specifies the isci host object. + * @port: This parameter specifies the sci port with the active link. + * + */ +void isci_port_ready( + struct isci_host *isci_host, + struct isci_port *isci_port) +{ + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p\n", __func__, isci_port); + + complete_all(&isci_port->start_complete); + isci_port_change_state(isci_port, isci_ready); + return; +} + +/** + * isci_port_not_ready() - This function is called by the sci core when a link + * is not ready. All remote devices on this link will be removed if they are + * in the stopping state. + * @isci_host: This parameter specifies the isci host object. + * @port: This parameter specifies the sci port with the active link. + * + */ +void isci_port_not_ready( + struct isci_host *isci_host, + struct isci_port *isci_port) +{ + dev_dbg(&isci_host->pdev->dev, + "%s: isci_port = %p\n", __func__, isci_port); +} + +/** + * isci_port_hard_reset_complete() - This function is called by the sci core + * when the hard reset complete notification has been received. + * @port: This parameter specifies the sci port with the active link. + * @completion_status: This parameter specifies the core status for the reset + * process. + * + */ +void isci_port_hard_reset_complete( + struct isci_port *isci_port, + enum sci_status completion_status) +{ + dev_dbg(&isci_port->isci_host->pdev->dev, + "%s: isci_port = %p, completion_status=%x\n", + __func__, isci_port, completion_status); + + /* Save the status of the hard reset from the port. */ + isci_port->hard_reset_status = completion_status; + + complete_all(&isci_port->hard_reset_complete); +} +/** + * isci_port_perform_hard_reset() - This function is one of the SAS Domain + * Template functions. This is a phy management function. + * @isci_port: + * @isci_phy: + * + * status, TMF_RESP_FUNC_COMPLETE indicates success. + */ +int isci_port_perform_hard_reset( + struct isci_port *isci_port, + struct isci_phy *isci_phy) +{ + enum sci_status status; + int ret = TMF_RESP_FUNC_COMPLETE; + unsigned long flags; + + + dev_dbg(&isci_port->isci_host->pdev->dev, + "%s: isci_port = %p\n", + __func__, isci_port); + + BUG_ON(isci_port == NULL); + + init_completion(&isci_port->hard_reset_complete); + + spin_lock_irqsave(&isci_port->isci_host->scic_lock, flags); + + #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT + status = scic_port_hard_reset(isci_port->sci_port_handle, + ISCI_PORT_RESET_TIMEOUT); + + spin_unlock_irqrestore(&isci_port->isci_host->scic_lock, flags); + + if (status == SCI_SUCCESS) { + wait_for_completion(&isci_port->hard_reset_complete); + + dev_dbg(&isci_port->isci_host->pdev->dev, + "%s: isci_port = %p; hard reset completion\n", + __func__, isci_port); + + if (isci_port->hard_reset_status != SCI_SUCCESS) + ret = TMF_RESP_FUNC_FAILED; + } else { + ret = TMF_RESP_FUNC_FAILED; + + dev_err(&isci_port->isci_host->pdev->dev, + "%s: isci_port = %p; scic_port_hard_reset call" + " failed 0x%x\n", + __func__, isci_port, status); + + } + + /* If the hard reset for the port has failed, consider this + * the same as link failures on all phys in the port. + */ + if (ret != TMF_RESP_FUNC_COMPLETE) { + BUG_ON(isci_port->isci_host == NULL); + + dev_err(&isci_port->isci_host->pdev->dev, + "%s: isci_port = %p; hard reset failed " + "(0x%x) - sending link down to libsas for phy %p\n", + __func__, + isci_port, + isci_port->hard_reset_status, + isci_phy); + + isci_port_link_down(isci_port->isci_host, + isci_phy, + isci_port); + } + + return ret; +} diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h new file mode 100644 index 000000000000..b01b0c63e53f --- /dev/null +++ b/drivers/scsi/isci/port.h @@ -0,0 +1,153 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the isci_port object definition. + * + * port.h + */ + +#if !defined(_ISCI_PORT_H_) +#define _ISCI_PORT_H_ + +struct isci_phy; +struct isci_host; + + +enum isci_status { + isci_freed = 0x00, + isci_starting = 0x01, + isci_ready = 0x02, + isci_ready_for_io = 0x03, + isci_stopping = 0x04, + isci_stopped = 0x05, + isci_host_quiesce = 0x06 +}; + +/** + * struct isci_port - This class represents the port object used to internally + * represent libsas port objects. It also keeps a list of remote device + * objects. + * + * + */ +struct isci_port { + + struct scic_sds_port *sci_port_handle; + + enum isci_status status; + struct isci_host *isci_host; + struct asd_sas_port sas_port; + struct list_head remote_dev_list; + spinlock_t remote_device_lock; + spinlock_t state_lock; + struct list_head domain_dev_list; + struct completion start_complete; + struct completion hard_reset_complete; + enum sci_status hard_reset_status; +}; + +#define to_isci_port(p) \ + container_of(p, struct isci_port, sas_port); + +enum isci_status isci_port_get_state( + struct isci_port *isci_port); + + + +void isci_port_formed( + struct asd_sas_phy *); + +void isci_port_deformed( + struct asd_sas_phy *); + +void isci_port_bc_change_received( + struct isci_host *isci_host, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +void isci_port_link_up( + struct isci_host *isci_host, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +void isci_port_link_down( + struct isci_host *isci_host, + struct isci_phy *isci_phy, + struct isci_port *port); + +void isci_port_ready( + struct isci_host *isci_host, + struct isci_port *isci_port); + +void isci_port_not_ready( + struct isci_host *isci_host, + struct isci_port *port); + +void isci_port_init( + struct isci_port *port, + struct isci_host *host, + int index); + +void isci_port_hard_reset_complete( + struct isci_port *isci_port, + enum sci_status completion_status); + +int isci_port_perform_hard_reset( + struct isci_port *isci_port_ptr, + struct isci_phy *isci_phy_ptr); + +#endif /* !defined(_ISCI_PORT_H_) */ + diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c new file mode 100644 index 000000000000..dbf3c82f6195 --- /dev/null +++ b/drivers/scsi/isci/remote_device.c @@ -0,0 +1,698 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "isci.h" +#include "scic_io_request.h" +#include "scic_remote_device.h" +#include "scic_phy.h" +#include "scic_port.h" +#include "port.h" +#include "remote_device.h" +#include "request.h" +#include "task.h" + + + +/** + * isci_remote_device_deconstruct() - This function frees an isci_remote_device. + * @isci_host: This parameter specifies the isci host object. + * @isci_device: This parameter specifies the remote device to be freed. + * + */ +static void isci_remote_device_deconstruct( + struct isci_host *isci_host, + struct isci_remote_device *isci_device) +{ + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + /* There should not be any outstanding io's. All paths to + * here should go through isci_remote_device_nuke_requests. + * If we hit this condition, we will need a way to complete + * io requests in process */ + while (!list_empty(&isci_device->reqs_in_process)) { + + dev_err(&isci_host->pdev->dev, + "%s: ** request list not empty! **\n", __func__); + BUG(); + } + + /* Remove all related references to this device and free + * the cache object. + */ + scic_remote_device_destruct(isci_device->sci_device_handle); + isci_device->domain_dev->lldd_dev = NULL; + list_del(&isci_device->node); + kmem_cache_free(isci_kmem_cache, isci_device); +} + + +/** + * isci_remote_device_construct() - This function calls the scic remote device + * construct and start functions, it waits on the remote device start + * completion. + * @port: This parameter specifies the isci port with the remote device. + * @isci_device: This parameter specifies the isci remote device + * + * status from the scic calls, the caller to this function should clean up + * resources as appropriate. + */ +static enum sci_status isci_remote_device_construct( + struct isci_port *port, + struct isci_remote_device *isci_device) +{ + enum sci_status status = SCI_SUCCESS; + + /* let the core do it's common constuction. */ + scic_remote_device_construct(port->sci_port_handle, + isci_device->sci_device_handle); + + /* let the core do it's device specific constuction. */ + if (isci_device->domain_dev->parent && + (isci_device->domain_dev->parent->dev_type == EDGE_DEV)) { + int i; + + /* struct smp_response_discover discover_response; */ + struct discover_resp discover_response; + struct domain_device *parent = + isci_device->domain_dev->parent; + + struct expander_device *parent_ex = &parent->ex_dev; + + for (i = 0; i < parent_ex->num_phys; i++) { + + struct ex_phy *phy = &parent_ex->ex_phy[i]; + + if ((phy->phy_state == PHY_VACANT) || + (phy->phy_state == PHY_NOT_PRESENT)) + continue; + + if (SAS_ADDR(phy->attached_sas_addr) + == SAS_ADDR(isci_device->domain_dev->sas_addr)) { + + discover_response.attached_dev_type + = phy->attached_dev_type; + discover_response.linkrate + = phy->linkrate; + discover_response.attached_sata_host + = phy->attached_sata_host; + discover_response.attached_sata_dev + = phy->attached_sata_dev; + discover_response.attached_sata_ps + = phy->attached_sata_ps; + discover_response.iproto + = phy->attached_iproto >> 1; + discover_response.tproto + = phy->attached_tproto >> 1; + memcpy( + discover_response.attached_sas_addr, + phy->attached_sas_addr, + SAS_ADDR_SIZE + ); + discover_response.attached_phy_id + = phy->attached_phy_id; + discover_response.change_count + = phy->phy_change_count; + discover_response.routing_attr + = phy->routing_attr; + discover_response.hmin_linkrate + = phy->phy->minimum_linkrate_hw; + discover_response.hmax_linkrate + = phy->phy->maximum_linkrate_hw; + discover_response.pmin_linkrate + = phy->phy->minimum_linkrate; + discover_response.pmax_linkrate + = phy->phy->maximum_linkrate; + } + } + + + dev_dbg(&port->isci_host->pdev->dev, + "%s: parent->dev_type = EDGE_DEV\n", + __func__); + + status = scic_remote_device_ea_construct( + isci_device->sci_device_handle, + (struct smp_response_discover *)&discover_response + ); + + } else + status = scic_remote_device_da_construct( + isci_device->sci_device_handle + ); + + + if (status != SCI_SUCCESS) { + dev_dbg(&port->isci_host->pdev->dev, + "%s: scic_remote_device_da_construct failed - " + "isci_device = %p\n", + __func__, + isci_device); + + return status; + } + + sci_object_set_association( + isci_device->sci_device_handle, + isci_device + ); + + BUG_ON(port->isci_host == NULL); + + /* start the device. */ + status = scic_remote_device_start( + isci_device->sci_device_handle, + ISCI_REMOTE_DEVICE_START_TIMEOUT + ); + + if (status != SCI_SUCCESS) { + dev_warn(&port->isci_host->pdev->dev, + "%s: scic_remote_device_start failed\n", + __func__); + return status; + } + + return status; +} + + +/** + * isci_remote_device_nuke_requests() - This function terminates all requests + * for a given remote device. + * @isci_device: This parameter specifies the remote device + * + */ +void isci_remote_device_nuke_requests( + struct isci_remote_device *isci_device) +{ + DECLARE_COMPLETION_ONSTACK(aborted_task_completion); + struct isci_host *isci_host; + + isci_host = isci_device->isci_port->isci_host; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + /* Cleanup all requests pending for this device. */ + isci_terminate_pending_requests(isci_host, isci_device, terminating); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p, done\n", __func__, isci_device); +} + + + +/** + * This function builds the isci_remote_device when a libsas dev_found message + * is received. + * @isci_host: This parameter specifies the isci host object. + * @port: This parameter specifies the isci_port conected to this device. + * + * pointer to new isci_remote_device. + */ +static struct isci_remote_device * +isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port) +{ + struct isci_remote_device *isci_device; + struct scic_sds_remote_device *sci_dev; + + isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL); + + if (!isci_device) { + dev_warn(&isci_host->pdev->dev, "%s: failed\n", __func__); + return NULL; + } + + sci_dev = (struct scic_sds_remote_device *) &isci_device[1]; + isci_device->sci_device_handle = sci_dev; + INIT_LIST_HEAD(&isci_device->reqs_in_process); + INIT_LIST_HEAD(&isci_device->node); + isci_device->host_quiesce = false; + + spin_lock_init(&isci_device->state_lock); + spin_lock_init(&isci_device->host_quiesce_lock); + isci_remote_device_change_state(isci_device, isci_freed); + + return isci_device; + +} +/** + * isci_device_set_host_quiesce_lock_state() - This function sets the host I/O + * quiesce lock state for the remote_device object. + * @isci_device,: This parameter points to the isci_remote_device object + * @isci_device: This parameter specifies the new quiesce state. + * + */ +void isci_device_set_host_quiesce_lock_state( + struct isci_remote_device *isci_device, + bool lock_state) +{ + unsigned long flags; + + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + "%s: isci_device=%p, lock_state=%d\n", + __func__, isci_device, lock_state); + + spin_lock_irqsave(&isci_device->host_quiesce_lock, flags); + isci_device->host_quiesce = lock_state; + spin_unlock_irqrestore(&isci_device->host_quiesce_lock, flags); +} + +/** + * isci_remote_device_ready() - This function is called by the scic when the + * remote device is ready. We mark the isci device as ready and signal the + * waiting proccess. + * @isci_host: This parameter specifies the isci host object. + * @isci_device: This parameter specifies the remote device + * + */ +void isci_remote_device_ready(struct isci_remote_device *isci_device) +{ + unsigned long flags; + + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + /* device ready is actually a "ready for io" state. */ + if ((isci_starting == isci_remote_device_get_state(isci_device)) || + (isci_ready == isci_remote_device_get_state(isci_device))) { + spin_lock_irqsave(&isci_device->isci_port->remote_device_lock, + flags); + isci_remote_device_change_state(isci_device, isci_ready_for_io); + if (isci_device->completion) + complete(isci_device->completion); + spin_unlock_irqrestore( + &isci_device->isci_port->remote_device_lock, + flags); + } + +} + +/** + * isci_remote_device_not_ready() - This function is called by the scic when + * the remote device is not ready. We mark the isci device as ready (not + * "ready_for_io") and signal the waiting proccess. + * @isci_host: This parameter specifies the isci host object. + * @isci_device: This parameter specifies the remote device + * + */ +void isci_remote_device_not_ready( + struct isci_remote_device *isci_device, + u32 reason_code) +{ + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) + isci_remote_device_change_state(isci_device, isci_stopping); + else + /* device ready is actually a "not ready for io" state. */ + isci_remote_device_change_state(isci_device, isci_ready); +} + +/** + * isci_remote_device_stop_complete() - This function is called by the scic + * when the remote device stop has completed. We mark the isci device as not + * ready and remove the isci remote device. + * @isci_host: This parameter specifies the isci host object. + * @isci_device: This parameter specifies the remote device. + * @status: This parameter specifies status of the completion. + * + */ +void isci_remote_device_stop_complete( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + enum sci_status status) +{ + struct completion *completion = isci_device->completion; + + dev_dbg(&isci_host->pdev->dev, + "%s: complete isci_device = %p, status = 0x%x\n", + __func__, + isci_device, + status); + + isci_remote_device_change_state(isci_device, isci_stopped); + + /* after stop, we can tear down resources. */ + isci_remote_device_deconstruct(isci_host, isci_device); + + /* notify interested parties. */ + if (completion) + complete(completion); +} + +/** + * isci_remote_device_start_complete() - This function is called by the scic + * when the remote device start has completed + * @isci_host: This parameter specifies the isci host object. + * @isci_device: This parameter specifies the remote device. + * @status: This parameter specifies status of the completion. + * + */ +void isci_remote_device_start_complete( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + enum sci_status status) +{ + + +} + + +/** + * isci_remote_device_stop() - This function is called internally to stop the + * remote device. + * @isci_host: This parameter specifies the isci host object. + * @isci_device: This parameter specifies the remote device. + * + * The status of the scic request to stop. + */ +enum sci_status isci_remote_device_stop( + struct isci_remote_device *isci_device) +{ + enum sci_status status; + unsigned long flags; + + DECLARE_COMPLETION_ONSTACK(completion); + + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + isci_remote_device_change_state(isci_device, isci_stopping); + + /* We need comfirmation that stop completed. */ + isci_device->completion = &completion; + + BUG_ON(isci_device->isci_port == NULL); + BUG_ON(isci_device->isci_port->isci_host == NULL); + + spin_lock_irqsave(&isci_device->isci_port->isci_host->scic_lock, flags); + + status = scic_remote_device_stop( + isci_device->sci_device_handle, + 50 + ); + + spin_unlock_irqrestore(&isci_device->isci_port->isci_host->scic_lock, flags); + + /* Wait for the stop complete callback. */ + if (status == SCI_SUCCESS) + wait_for_completion(&completion); + + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + "%s: isci_device = %p - after completion wait\n", + __func__, isci_device); + + isci_device->completion = NULL; + return status; +} + +/** + * isci_remote_device_gone() - This function is called by libsas when a domain + * device is removed. + * @domain_device: This parameter specifies the libsas domain device. + * + */ +void isci_remote_device_gone( + struct domain_device *domain_dev) +{ + struct isci_remote_device *isci_device = isci_dev_from_domain_dev( + domain_dev); + + dev_err(&isci_device->isci_port->isci_host->pdev->dev, + "%s: domain_device = %p, isci_device = %p, isci_port = %p\n", + __func__, domain_dev, isci_device, isci_device->isci_port); + + if (isci_device != NULL) + isci_remote_device_stop(isci_device); +} + + +/** + * isci_remote_device_found() - This function is called by libsas when a remote + * device is discovered. A remote device object is created and started. the + * function then sleeps until the sci core device started message is + * received. + * @domain_device: This parameter specifies the libsas domain device. + * + * status, zero indicates success. + */ +int isci_remote_device_found(struct domain_device *domain_dev) +{ + unsigned long flags; + struct isci_host *isci_host; + struct isci_port *isci_port; + struct isci_phy *isci_phy; + struct asd_sas_port *sas_port; + struct asd_sas_phy *sas_phy; + struct isci_remote_device *isci_device; + enum sci_status status; + DECLARE_COMPLETION_ONSTACK(completion); + + isci_host = isci_host_from_sas_ha(domain_dev->port->ha); + + dev_dbg(&isci_host->pdev->dev, + "%s: domain_device = %p\n", __func__, domain_dev); + + sas_port = domain_dev->port; + sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy, + port_phy_el); + isci_phy = to_isci_phy(sas_phy); + isci_port = isci_phy->isci_port; + + /* we are being called for a device on this port, + * so it has to come up eventually + */ + wait_for_completion(&isci_port->start_complete); + + if ((isci_stopping == isci_port_get_state(isci_port)) || + (isci_stopped == isci_port_get_state(isci_port))) + return -ENODEV; + + isci_device = isci_remote_device_alloc(isci_host, isci_port); + + INIT_LIST_HEAD(&isci_device->node); + domain_dev->lldd_dev = isci_device; + isci_device->domain_dev = domain_dev; + isci_device->isci_port = isci_port; + isci_remote_device_change_state(isci_device, isci_starting); + + + spin_lock_irqsave(&isci_port->remote_device_lock, flags); + list_add_tail(&isci_device->node, &isci_port->remote_dev_list); + + /* for the device ready event. */ + isci_device->completion = &completion; + + status = isci_remote_device_construct(isci_port, isci_device); + + spin_unlock_irqrestore(&isci_port->remote_device_lock, flags); + + /* wait for the device ready callback. */ + wait_for_completion(isci_device->completion); + isci_device->completion = NULL; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", + __func__, isci_device); + + if (status != SCI_SUCCESS) { + + spin_lock_irqsave(&isci_port->remote_device_lock, flags); + isci_remote_device_deconstruct( + isci_host, + isci_device + ); + spin_unlock_irqrestore(&isci_port->remote_device_lock, flags); + return -ENODEV; + } + + wait_for_completion(&isci_host->start_complete); + + return 0; +} +/** + * isci_device_is_reset_pending() - This function will check if there is any + * pending reset condition on the device. + * @request: This parameter is the isci_device object. + * + * true if there is a reset pending for the device. + */ +bool isci_device_is_reset_pending( + struct isci_host *isci_host, + struct isci_remote_device *isci_device) +{ + struct isci_request *isci_request; + struct isci_request *tmp_req; + bool reset_is_pending = false; + unsigned long flags; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + /* Check for reset on all pending requests. */ + list_for_each_entry_safe(isci_request, tmp_req, + &isci_device->reqs_in_process, dev_node) { + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p request = %p\n", + __func__, isci_device, isci_request); + + if (isci_request->ttype == io_task) { + + unsigned long flags; + struct sas_task *task = isci_request_access_task( + isci_request); + + spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) + reset_is_pending = true; + spin_unlock_irqrestore(&task->task_state_lock, flags); + } + } + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p reset_is_pending = %d\n", + __func__, isci_device, reset_is_pending); + + return reset_is_pending; +} + +/** + * isci_device_clear_reset_pending() - This function will clear if any pending + * reset condition flags on the device. + * @request: This parameter is the isci_device object. + * + * true if there is a reset pending for the device. + */ +void isci_device_clear_reset_pending(struct isci_remote_device *isci_device) +{ + struct isci_request *isci_request; + struct isci_request *tmp_req; + struct isci_host *isci_host = NULL; + unsigned long flags = 0; + + /* FIXME more port gone confusion, and this time it makes the + * locking "fun" + */ + if (isci_device->isci_port != NULL) + isci_host = isci_device->isci_port->isci_host; + + /* + * FIXME when the isci_host gets sorted out + * use dev_dbg() + */ + pr_debug("%s: isci_device=%p, isci_host=%p\n", + __func__, isci_device, isci_host); + + if (isci_host != NULL) + spin_lock_irqsave(&isci_host->scic_lock, flags); + else + pr_err("%s: isci_device %p; isci_host == NULL!\n", + __func__, isci_device); + + /* Clear reset pending on all pending requests. */ + list_for_each_entry_safe(isci_request, tmp_req, + &isci_device->reqs_in_process, dev_node) { + /* + * FIXME when the conditional spinlock is gone + * change to dev_dbg() + */ + pr_debug("%s: isci_device = %p request = %p\n", + __func__, isci_device, isci_request); + + if (isci_request->ttype == io_task) { + + unsigned long flags2; + struct sas_task *task = isci_request_access_task( + isci_request); + + spin_lock_irqsave(&task->task_state_lock, flags2); + task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&task->task_state_lock, flags2); + } + } + + if (isci_host != NULL) + spin_unlock_irqrestore(&isci_host->scic_lock, flags); +} + +/** + * isci_remote_device_change_state() - This function gets the status of the + * remote_device object. + * @isci_device: This parameter points to the isci_remote_device object + * + * status of the object as a isci_status enum. + */ +void isci_remote_device_change_state( + struct isci_remote_device *isci_device, + enum isci_status status) +{ + unsigned long flags; + + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + "%s: isci_device = %p, state = 0x%x", + __func__, + isci_device, + status); + + spin_lock_irqsave(&isci_device->state_lock, flags); + isci_device->status = status; + spin_unlock_irqrestore(&isci_device->state_lock, flags); +} diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h new file mode 100644 index 000000000000..a208f81785eb --- /dev/null +++ b/drivers/scsi/isci/remote_device.h @@ -0,0 +1,154 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(_ISCI_REMOTE_DEVICE_H_) +#define _ISCI_REMOTE_DEVICE_H_ +#include "scic_user_callback.h" + +struct isci_host; +struct scic_sds_remote_device; + +struct isci_remote_device { + struct scic_sds_remote_device *sci_device_handle; + enum isci_status status; + struct isci_port *isci_port; + struct domain_device *domain_dev; + struct completion *completion; + struct list_head node; + struct list_head reqs_in_process; + struct work_struct stop_work; + spinlock_t state_lock; + spinlock_t host_quiesce_lock; + bool host_quiesce; +}; + +#define to_isci_remote_device(p) \ + container_of(p, struct isci_remote_device, sci_remote_device); + +#define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 + + +/** + * This function gets the status of the remote_device object. + * @isci_device: This parameter points to the isci_remote_device object + * + * status of the object as a isci_status enum. + */ +static inline +enum isci_status isci_remote_device_get_state( + struct isci_remote_device *isci_device) +{ + return (isci_device->host_quiesce) + ? isci_host_quiesce + : isci_device->status; +} + + +/** + * isci_dev_from_domain_dev() - This accessor retrieves the remote_device + * object reference from the Linux domain_device reference. + * @domdev,: This parameter points to the Linux domain_device object . + * + * A reference to the associated isci remote device. + */ +#define isci_dev_from_domain_dev(domdev) \ + ((struct isci_remote_device *)(domdev)->lldd_dev) + +void isci_remote_device_start_complete( + struct isci_host *, + struct isci_remote_device *, + enum sci_status); + +void isci_remote_device_stop_complete( + struct isci_host *, + struct isci_remote_device *, + enum sci_status); + +enum sci_status isci_remote_device_stop( + struct isci_remote_device *isci_device); + +void isci_remote_device_nuke_requests( + struct isci_remote_device *isci_device); + +void isci_remote_device_ready( + struct isci_remote_device *); + +void isci_remote_device_not_ready( + struct isci_remote_device *, + u32); + +void isci_remote_device_gone( + struct domain_device *domain_dev); + +int isci_remote_device_found( + struct domain_device *domain_dev); + +bool isci_device_is_reset_pending( + struct isci_host *isci_host, + struct isci_remote_device *isci_device); + +void isci_device_clear_reset_pending( + struct isci_remote_device *isci_device); + +void isci_device_set_host_quiesce_lock_state( + struct isci_remote_device *isci_device, + bool lock_state); + +void isci_remote_device_change_state( + struct isci_remote_device *isci_device, + enum isci_status status); + +#endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ + diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c new file mode 100644 index 000000000000..e564121b6726 --- /dev/null +++ b/drivers/scsi/isci/request.c @@ -0,0 +1,1472 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "isci.h" +#include "scic_remote_device.h" +#include "scic_io_request.h" +#include "scic_task_request.h" +#include "scic_port.h" +#include "task.h" +#include "request.h" +#include "sata.h" +#include "scu_completion_codes.h" + + +static enum sci_status isci_request_ssp_request_construct( + struct isci_request *request) +{ + enum sci_status status; + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p\n", + __func__, + request); + status = scic_io_request_construct_basic_ssp( + request->sci_request_handle + ); + return status; +} + +static enum sci_status isci_request_stp_request_construct( + struct isci_request *request) +{ + struct sas_task *task = isci_request_access_task(request); + enum sci_status status; + struct host_to_dev_fis *register_fis; + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p\n", + __func__, + request); + + /* Get the host_to_dev_fis from the core and copy + * the fis from the task into it. + */ + register_fis = isci_sata_task_to_fis_copy(task); + + status = scic_io_request_construct_basic_sata( + request->sci_request_handle + ); + + /* Set the ncq tag in the fis, from the queue + * command in the task. + */ + if (isci_sata_is_task_ncq(task)) { + + isci_sata_set_ncq_tag( + register_fis, + task + ); + } + + return status; +} + +/** + * isci_smp_request_build() - This function builds the smp request object. + * @isci_host: This parameter specifies the ISCI host object + * @request: This parameter points to the isci_request object allocated in the + * request construct function. + * @sci_device: This parameter is the handle for the sci core's remote device + * object that is the destination for this request. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +static enum sci_status isci_smp_request_build( + struct isci_request *request) +{ + enum sci_status status = SCI_FAILURE; + struct sas_task *task = isci_request_access_task(request); + + void *command_iu_address = + scic_io_request_get_command_iu_address( + request->sci_request_handle + ); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p\n", + __func__, + request); + dev_dbg(&request->isci_host->pdev->dev, + "%s: smp_req len = %d\n", + __func__, + task->smp_task.smp_req.length); + + /* copy the smp_command to the address; */ + sg_copy_to_buffer(&task->smp_task.smp_req, 1, + (char *)command_iu_address, + sizeof(struct smp_request) + ); + + status = scic_io_request_construct_smp(request->sci_request_handle); + if (status != SCI_SUCCESS) + dev_warn(&request->isci_host->pdev->dev, + "%s: scic_io_request_construct_smp failed with " + "status = %d\n", + __func__, + status); + + return status; +} + +/** + * isci_io_request_build() - This function builds the io request object. + * @isci_host: This parameter specifies the ISCI host object + * @request: This parameter points to the isci_request object allocated in the + * request construct function. + * @sci_device: This parameter is the handle for the sci core's remote device + * object that is the destination for this request. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +static enum sci_status isci_io_request_build( + struct isci_host *isci_host, + struct isci_request *request, + struct isci_remote_device *isci_device) +{ + struct smp_discover_response_protocols dev_protocols; + enum sci_status status = SCI_SUCCESS; + struct sas_task *task = isci_request_access_task(request); + struct scic_sds_remote_device *sci_device = + isci_device->sci_device_handle; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = 0x%p; request = %p, " + "num_scatter = %d\n", + __func__, + isci_device, + request, + task->num_scatter); + + /* map the sgl addresses, if present. + * libata does the mapping for sata devices + * before we get the request. + */ + if (task->num_scatter && + !sas_protocol_ata(task->task_proto) && + !(SAS_PROTOCOL_SMP & task->task_proto)) { + + request->num_sg_entries = dma_map_sg( + &isci_host->pdev->dev, + task->scatter, + task->num_scatter, + task->data_dir + ); + + if (request->num_sg_entries == 0) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + } + + /* build the common request object. For now, + * we will let the core allocate the IO tag. + */ + status = scic_io_request_construct( + isci_host->core_controller, + sci_device, + SCI_CONTROLLER_INVALID_IO_TAG, + request, + request->sci_request_mem_ptr, + (struct scic_sds_request **)&request->sci_request_handle + ); + + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: failed request construct\n", + __func__); + return SCI_FAILURE; + } + + sci_object_set_association(request->sci_request_handle, request); + + /* Determine protocol and call the appropriate basic constructor */ + scic_remote_device_get_protocols(sci_device, &dev_protocols); + if (dev_protocols.u.bits.attached_ssp_target) + status = isci_request_ssp_request_construct(request); + else if (dev_protocols.u.bits.attached_stp_target) + status = isci_request_stp_request_construct(request); + else if (dev_protocols.u.bits.attached_smp_target) + status = isci_smp_request_build(request); + else { + dev_warn(&isci_host->pdev->dev, + "%s: unknown protocol\n", __func__); + return SCI_FAILURE; + } + + return SCI_SUCCESS; +} + + +/** + * isci_request_alloc_core() - This function gets the request object from the + * isci_host dma cache. + * @isci_host: This parameter specifies the ISCI host object + * @isci_request: This parameter will contain the pointer to the new + * isci_request object. + * @isci_device: This parameter is the pointer to the isci remote device object + * that is the destination for this request. + * @gfp_flags: This parameter specifies the os allocation flags. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +static int isci_request_alloc_core( + struct isci_host *isci_host, + struct isci_request **isci_request, + struct isci_remote_device *isci_device, + gfp_t gfp_flags) +{ + int ret = 0; + dma_addr_t handle; + struct isci_request *request; + + + /* get pointer to dma memory. This actually points + * to both the isci_remote_device object and the + * sci object. The isci object is at the beginning + * of the memory allocated here. + */ + request = dma_pool_alloc(isci_host->dma_pool, gfp_flags, &handle); + if (!request) { + dev_warn(&isci_host->pdev->dev, + "%s: dma_pool_alloc returned NULL\n", __func__); + return -ENOMEM; + } + + /* initialize the request object. */ + spin_lock_init(&request->state_lock); + isci_request_change_state(request, allocated); + request->sci_request_mem_ptr = ((u8 *)request) + + sizeof(struct isci_request); + request->request_daddr = handle; + request->isci_host = isci_host; + request->isci_device = isci_device; + request->io_request_completion = NULL; + + request->request_alloc_size = isci_host->dma_pool_alloc_size; + request->num_sg_entries = 0; + + request->complete_in_target = false; + + INIT_LIST_HEAD(&request->completed_node); + INIT_LIST_HEAD(&request->dev_node); + + *isci_request = request; + + return ret; +} + +static int isci_request_alloc_io( + struct isci_host *isci_host, + struct sas_task *task, + struct isci_request **isci_request, + struct isci_remote_device *isci_device, + gfp_t gfp_flags) +{ + int retval = isci_request_alloc_core(isci_host, isci_request, + isci_device, gfp_flags); + + if (!retval) { + (*isci_request)->ttype_ptr.io_task_ptr = task; + (*isci_request)->ttype = io_task; + + task->lldd_task = *isci_request; + } + return retval; +} + +/** + * isci_request_alloc_tmf() - This function gets the request object from the + * isci_host dma cache and initializes the relevant fields as a sas_task. + * @isci_host: This parameter specifies the ISCI host object + * @sas_task: This parameter is the task struct from the upper layer driver. + * @isci_request: This parameter will contain the pointer to the new + * isci_request object. + * @isci_device: This parameter is the pointer to the isci remote device object + * that is the destination for this request. + * @gfp_flags: This parameter specifies the os allocation flags. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +int isci_request_alloc_tmf( + struct isci_host *isci_host, + struct isci_tmf *isci_tmf, + struct isci_request **isci_request, + struct isci_remote_device *isci_device, + gfp_t gfp_flags) +{ + int retval = isci_request_alloc_core(isci_host, isci_request, + isci_device, gfp_flags); + + if (!retval) { + + (*isci_request)->ttype_ptr.tmf_task_ptr = isci_tmf; + (*isci_request)->ttype = tmf_task; + } + return retval; +} + +/** + * isci_request_signal_device_reset() - This function will set the "device + * needs target reset" flag in the given sas_tasks' task_state_flags, and + * then cause the task to be added into the SCSI error handler queue which + * will eventually be escalated to a target reset. + * + * + */ +static void isci_request_signal_device_reset( + struct isci_request *isci_request) +{ + unsigned long flags; + struct sas_task *task = isci_request_access_task(isci_request); + + dev_dbg(&isci_request->isci_host->pdev->dev, + "%s: request=%p, task=%p\n", __func__, isci_request, task); + + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + /* Cause this task to be scheduled in the SCSI error handler + * thread. + */ + sas_task_abort(task); +} + +/** + * isci_request_execute() - This function allocates the isci_request object, + * all fills in some common fields. + * @isci_host: This parameter specifies the ISCI host object + * @sas_task: This parameter is the task struct from the upper layer driver. + * @isci_request: This parameter will contain the pointer to the new + * isci_request object. + * @gfp_flags: This parameter specifies the os allocation flags. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +int isci_request_execute( + struct isci_host *isci_host, + struct sas_task *task, + struct isci_request **isci_request, + gfp_t gfp_flags) +{ + int ret = 0; + struct scic_sds_remote_device *sci_device; + enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + struct isci_remote_device *isci_device; + struct isci_request *request; + unsigned long flags; + + isci_device = isci_dev_from_domain_dev(task->dev); + sci_device = isci_device->sci_device_handle; + + /* do common allocation and init of request object. */ + ret = isci_request_alloc_io( + isci_host, + task, + &request, + isci_device, + gfp_flags + ); + + if (ret) + goto out; + + status = isci_io_request_build(isci_host, request, isci_device); + if (status == SCI_SUCCESS) { + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + /* send the request, let the core assign the IO TAG. */ + status = scic_controller_start_io( + isci_host->core_controller, + sci_device, + request->sci_request_handle, + SCI_CONTROLLER_INVALID_IO_TAG + ); + + if (status == SCI_SUCCESS || + status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + + /* Either I/O started OK, or the core has signaled that + * the device needs a target reset. + * + * In either case, hold onto the I/O for later. + * + * Update it's status and add it to the list in the + * remote device object. + */ + isci_request_change_state(request, started); + list_add(&request->dev_node, + &isci_device->reqs_in_process); + + if (status == + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + /* Signal libsas that we need the SCSI error + * handler thread to work on this I/O and that + * we want a device reset. + */ + isci_request_signal_device_reset(request); + + /* Change the status, since we are holding + * the I/O until it is managed by the SCSI + * error handler. + */ + status = SCI_SUCCESS; + } + } else + dev_warn(&isci_host->pdev->dev, + "%s: failed request start\n", + __func__); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + } else + dev_warn(&isci_host->pdev->dev, + "%s: request_construct failed - status = 0x%x\n", + __func__, + status); + + out: + if (status != SCI_SUCCESS) { + + /* release dma memory on failure. */ + isci_request_free(isci_host, request); + request = NULL; + ret = SCI_FAILURE; + } + + *isci_request = request; + return ret; +} + + +/** + * isci_request_process_response_iu() - This function sets the status and + * response iu, in the task struct, from the request object for the upper + * layer driver. + * @sas_task: This parameter is the task struct from the upper layer driver. + * @resp_iu: This parameter points to the response iu of the completed request. + * @dev: This parameter specifies the linux device struct. + * + * none. + */ +static void isci_request_process_response_iu( + struct sas_task *task, + struct ssp_response_iu *resp_iu, + struct device *dev) +{ + dev_dbg(dev, + "%s: resp_iu = %p " + "resp_iu->status = 0x%x,\nresp_iu->datapres = %d " + "resp_iu->response_data_len = %x, " + "resp_iu->sense_data_len = %x\nrepsonse data: ", + __func__, + resp_iu, + resp_iu->status, + resp_iu->datapres, + resp_iu->response_data_len, + resp_iu->sense_data_len); + + task->task_status.stat = resp_iu->status; + + /* libsas updates the task status fields based on the response iu. */ + sas_ssp_task_response(dev, task, resp_iu); +} + +/** + * isci_request_set_open_reject_status() - This function prepares the I/O + * completion for OPEN_REJECT conditions. + * @request: This parameter is the completed isci_request object. + * @response_ptr: This parameter specifies the service response for the I/O. + * @status_ptr: This parameter specifies the exec status for the I/O. + * @complete_to_host_ptr: This parameter specifies the action to be taken by + * the LLDD with respect to completing this request or forcing an abort + * condition on the I/O. + * @open_rej_reason: This parameter specifies the encoded reason for the + * abandon-class reject. + * + * none. + */ +static void isci_request_set_open_reject_status( + struct isci_request *request, + struct sas_task *task, + enum service_response *response_ptr, + enum exec_status *status_ptr, + enum isci_completion_selection *complete_to_host_ptr, + enum sas_open_rej_reason open_rej_reason) +{ + /* Task in the target is done. */ + request->complete_in_target = true; + *response_ptr = SAS_TASK_UNDELIVERED; + *status_ptr = SAS_OPEN_REJECT; + *complete_to_host_ptr = isci_perform_normal_io_completion; + task->task_status.open_rej_reason = open_rej_reason; +} + +/** + * isci_request_handle_controller_specific_errors() - This function decodes + * controller-specific I/O completion error conditions. + * @request: This parameter is the completed isci_request object. + * @response_ptr: This parameter specifies the service response for the I/O. + * @status_ptr: This parameter specifies the exec status for the I/O. + * @complete_to_host_ptr: This parameter specifies the action to be taken by + * the LLDD with respect to completing this request or forcing an abort + * condition on the I/O. + * + * none. + */ +static void isci_request_handle_controller_specific_errors( + struct isci_remote_device *isci_device, + struct isci_request *request, + struct sas_task *task, + enum service_response *response_ptr, + enum exec_status *status_ptr, + enum isci_completion_selection *complete_to_host_ptr) +{ + unsigned int cstatus; + + cstatus = scic_request_get_controller_status( + request->sci_request_handle + ); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: %p SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR " + "- controller status = 0x%x\n", + __func__, request, cstatus); + + /* Decode the controller-specific errors; most + * important is to recognize those conditions in which + * the target may still have a task outstanding that + * must be aborted. + * + * Note that there are SCU completion codes being + * named in the decode below for which SCIC has already + * done work to handle them in a way other than as + * a controller-specific completion code; these are left + * in the decode below for completeness sake. + */ + switch (cstatus) { + case SCU_TASK_DONE_DMASETUP_DIRERR: + /* Also SCU_TASK_DONE_SMP_FRM_TYPE_ERR: */ + case SCU_TASK_DONE_XFERCNT_ERR: + /* Also SCU_TASK_DONE_SMP_UFI_ERR: */ + if (task->task_proto == SAS_PROTOCOL_SMP) { + /* SCU_TASK_DONE_SMP_UFI_ERR == Task Done. */ + *response_ptr = SAS_TASK_COMPLETE; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + *status_ptr = SAS_DEVICE_UNKNOWN; + else + *status_ptr = SAS_ABORTED_TASK; + + request->complete_in_target = true; + + *complete_to_host_ptr = + isci_perform_normal_io_completion; + } else { + /* Task in the target is not done. */ + *response_ptr = SAS_TASK_UNDELIVERED; + + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + *status_ptr = SAS_DEVICE_UNKNOWN; + else + *status_ptr = SAM_STAT_TASK_ABORTED; + + request->complete_in_target = false; + + *complete_to_host_ptr = + isci_perform_error_io_completion; + } + + break; + + case SCU_TASK_DONE_CRC_ERR: + case SCU_TASK_DONE_NAK_CMD_ERR: + case SCU_TASK_DONE_EXCESS_DATA: + case SCU_TASK_DONE_UNEXP_FIS: + /* Also SCU_TASK_DONE_UNEXP_RESP: */ + case SCU_TASK_DONE_VIIT_ENTRY_NV: /* TODO - conditions? */ + case SCU_TASK_DONE_IIT_ENTRY_NV: /* TODO - conditions? */ + case SCU_TASK_DONE_RNCNV_OUTBOUND: /* TODO - conditions? */ + /* These are conditions in which the target + * has completed the task, so that no cleanup + * is necessary. + */ + *response_ptr = SAS_TASK_COMPLETE; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + *status_ptr = SAS_DEVICE_UNKNOWN; + else + *status_ptr = SAS_ABORTED_TASK; + + request->complete_in_target = true; + + *complete_to_host_ptr = isci_perform_normal_io_completion; + break; + + + /* Note that the only open reject completion codes seen here will be + * abandon-class codes; all others are automatically retried in the SCU. + */ + case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION: + + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_WRONG_DEST); + break; + + case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION: + + /* Note - the return of AB0 will change when + * libsas implements detection of zone violations. + */ + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_RESV_AB0); + break; + + case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1: + + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_RESV_AB1); + break; + + case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2: + + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_RESV_AB2); + break; + + case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3: + + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_RESV_AB3); + break; + + case SCU_TASK_OPEN_REJECT_BAD_DESTINATION: + + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_BAD_DEST); + break; + + case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY: + + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_STP_NORES); + break; + + case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED: + + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_EPROTO); + break; + + case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED: + + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_CONN_RATE); + break; + + case SCU_TASK_DONE_LL_R_ERR: + /* Also SCU_TASK_DONE_ACK_NAK_TO: */ + case SCU_TASK_DONE_LL_PERR: + case SCU_TASK_DONE_LL_SY_TERM: + /* Also SCU_TASK_DONE_NAK_ERR:*/ + case SCU_TASK_DONE_LL_LF_TERM: + /* Also SCU_TASK_DONE_DATA_LEN_ERR: */ + case SCU_TASK_DONE_LL_ABORT_ERR: + case SCU_TASK_DONE_SEQ_INV_TYPE: + /* Also SCU_TASK_DONE_UNEXP_XR: */ + case SCU_TASK_DONE_XR_IU_LEN_ERR: + case SCU_TASK_DONE_INV_FIS_LEN: + /* Also SCU_TASK_DONE_XR_WD_LEN: */ + case SCU_TASK_DONE_SDMA_ERR: + case SCU_TASK_DONE_OFFSET_ERR: + case SCU_TASK_DONE_MAX_PLD_ERR: + case SCU_TASK_DONE_LF_ERR: + case SCU_TASK_DONE_SMP_RESP_TO_ERR: /* Escalate to dev reset? */ + case SCU_TASK_DONE_SMP_LL_RX_ERR: + case SCU_TASK_DONE_UNEXP_DATA: + case SCU_TASK_DONE_UNEXP_SDBFIS: + case SCU_TASK_DONE_REG_ERR: + case SCU_TASK_DONE_SDB_ERR: + case SCU_TASK_DONE_TASK_ABORT: + default: + /* Task in the target is not done. */ + *response_ptr = SAS_TASK_UNDELIVERED; + *status_ptr = SAM_STAT_TASK_ABORTED; + request->complete_in_target = false; + + *complete_to_host_ptr = isci_perform_error_io_completion; + break; + } +} + +/** + * isci_task_save_for_upper_layer_completion() - This function saves the + * request for later completion to the upper layer driver. + * @host: This parameter is a pointer to the host on which the the request + * should be queued (either as an error or success). + * @request: This parameter is the completed request. + * @response: This parameter is the response code for the completed task. + * @status: This parameter is the status code for the completed task. + * + * none. + */ +static void isci_task_save_for_upper_layer_completion( + struct isci_host *host, + struct isci_request *request, + enum service_response response, + enum exec_status status, + enum isci_completion_selection task_notification_selection) +{ + struct sas_task *task = isci_request_access_task(request); + + isci_task_set_completion_status(task, response, status, + task_notification_selection); + + + /* Tasks aborted specifically by a call to the lldd_abort_task + * function should not be completed to the host in the regular path. + */ + switch (task_notification_selection) { + + case isci_perform_normal_io_completion: + + /* Normal notification (task_done) */ + dev_dbg(&host->pdev->dev, + "%s: Normal - task = %p, response=%d, status=%d\n", + __func__, + task, + response, + status); + /* Add to the completed list. */ + list_add(&request->completed_node, + &host->requests_to_complete); + break; + + case isci_perform_aborted_io_completion: + /* + * No notification because this request is already + * in the abort path. + */ + dev_warn(&host->pdev->dev, + "%s: Aborted - task = %p, response=%d, status=%d\n", + __func__, + task, + response, + status); + break; + + case isci_perform_error_io_completion: + /* Use sas_task_abort */ + dev_warn(&host->pdev->dev, + "%s: Error - task = %p, response=%d, status=%d\n", + __func__, + task, + response, + status); + /* Add to the aborted list. */ + list_add(&request->completed_node, + &host->requests_to_abort); + break; + + default: + dev_warn(&host->pdev->dev, + "%s: Unknown - task = %p, response=%d, status=%d\n", + __func__, + task, + response, + status); + + /* Add to the aborted list. */ + list_add(&request->completed_node, + &host->requests_to_abort); + break; + } +} + +/** + * isci_request_io_request_complete() - This function is called by the sci core + * when an io request completes. + * @isci_host: This parameter specifies the ISCI host object + * @request: This parameter is the completed isci_request object. + * @completion_status: This parameter specifies the completion status from the + * sci core. + * + * none. + */ +void isci_request_io_request_complete( + struct isci_host *isci_host, + struct isci_request *request, + enum sci_io_status completion_status) +{ + struct sas_task *task = isci_request_access_task(request); + struct ssp_response_iu *resp_iu; + void *resp_buf; + unsigned long task_flags; + unsigned long state_flags; + struct completion *io_request_completion; + struct isci_remote_device *isci_device = request->isci_device; + enum service_response response = SAS_TASK_UNDELIVERED; + enum exec_status status = SAS_ABORTED_TASK; + enum isci_request_status request_status; + enum isci_completion_selection complete_to_host + = isci_perform_normal_io_completion; + + dev_dbg(&isci_host->pdev->dev, + "%s: request = %p, task = %p,\n" + "task->data_dir = %d completion_status = 0x%x\n", + __func__, + request, + task, + task->data_dir, + completion_status); + + spin_lock_irqsave(&request->state_lock, state_flags); + request_status = isci_request_get_state(request); + spin_unlock_irqrestore(&request->state_lock, state_flags); + + /* Decode the request status. Note that if the request has been + * aborted by a task management function, we don't care + * what the status is. + */ + switch (request_status) { + + case aborted: + /* "aborted" indicates that the request was aborted by a task + * management function, since once a task management request is + * perfomed by the device, the request only completes because + * of the subsequent driver terminate. + * + * Aborted also means an external thread is explicitly managing + * this request, so that we do not complete it up the stack. + * + * The target is still there (since the TMF was successful). + */ + request->complete_in_target = true; + response = SAS_TASK_COMPLETE; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) + || (isci_device->status == isci_stopped) + ) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_aborted_io_completion; + /* This was an aborted request. */ + break; + + case aborting: + /* aborting means that the task management function tried and + * failed to abort the request. We need to note the request + * as SAS_TASK_UNDELIVERED, so that the scsi mid layer marks the + * target as down. + * + * Aborting also means an external thread is explicitly managing + * this request, so that we do not complete it up the stack. + */ + request->complete_in_target = true; + response = SAS_TASK_UNDELIVERED; + + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + /* The device has been /is being stopped. Note that + * we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_PHY_DOWN; + + complete_to_host = isci_perform_aborted_io_completion; + + /* This was an aborted request. */ + break; + + case terminating: + + /* This was an terminated request. This happens when + * the I/O is being terminated because of an action on + * the device (reset, tear down, etc.), and the I/O needs + * to be completed up the stack. + */ + request->complete_in_target = true; + response = SAS_TASK_UNDELIVERED; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_normal_io_completion; + + /* This was a terminated request. */ + break; + + default: + + /* This is an active request being completed from the core. */ + switch (completion_status) { + + case SCI_IO_FAILURE_RESPONSE_VALID: + dev_dbg(&isci_host->pdev->dev, + "%s: SCI_IO_FAILURE_RESPONSE_VALID (%p/%p)\n", + __func__, + request, + task); + + if (sas_protocol_ata(task->task_proto)) { + resp_buf + = scic_stp_io_request_get_d2h_reg_address( + request->sci_request_handle + ); + isci_request_process_stp_response(task, + resp_buf + ); + + } else if (SAS_PROTOCOL_SSP == task->task_proto) { + + /* crack the iu response buffer. */ + resp_iu + = scic_io_request_get_response_iu_address( + request->sci_request_handle + ); + + isci_request_process_response_iu(task, resp_iu, + &isci_host->pdev->dev + ); + + } else if (SAS_PROTOCOL_SMP == task->task_proto) { + + dev_err(&isci_host->pdev->dev, + "%s: SCI_IO_FAILURE_RESPONSE_VALID: " + "SAS_PROTOCOL_SMP protocol\n", + __func__); + + } else + dev_err(&isci_host->pdev->dev, + "%s: unknown protocol\n", __func__); + + /* use the task status set in the task struct by the + * isci_request_process_response_iu call. + */ + request->complete_in_target = true; + response = task->task_status.resp; + status = task->task_status.stat; + break; + + case SCI_IO_SUCCESS: + case SCI_IO_SUCCESS_IO_DONE_EARLY: + + response = SAS_TASK_COMPLETE; + status = SAM_STAT_GOOD; + request->complete_in_target = true; + + if (task->task_proto == SAS_PROTOCOL_SMP) { + + u8 *command_iu_address + = scic_io_request_get_command_iu_address( + request->sci_request_handle + ); + + dev_dbg(&isci_host->pdev->dev, + "%s: SMP protocol completion\n", + __func__); + + sg_copy_from_buffer( + &task->smp_task.smp_resp, 1, + command_iu_address + + sizeof(struct smp_request), + sizeof(struct smp_resp) + ); + } else if (completion_status + == SCI_IO_SUCCESS_IO_DONE_EARLY) { + + /* This was an SSP / STP / SATA transfer. + * There is a possibility that less data than + * the maximum was transferred. + */ + u32 transferred_length + = scic_io_request_get_number_of_bytes_transferred( + request->sci_request_handle); + + task->task_status.residual + = task->total_xfer_len - transferred_length; + + /* If there were residual bytes, call this an + * underrun. + */ + if (task->task_status.residual != 0) + status = SAS_DATA_UNDERRUN; + + dev_dbg(&isci_host->pdev->dev, + "%s: SCI_IO_SUCCESS_IO_DONE_EARLY %d\n", + __func__, + status); + + } else + dev_dbg(&isci_host->pdev->dev, + "%s: SCI_IO_SUCCESS\n", + __func__); + + break; + + case SCI_IO_FAILURE_TERMINATED: + dev_dbg(&isci_host->pdev->dev, + "%s: SCI_IO_FAILURE_TERMINATED (%p/%p)\n", + __func__, + request, + task); + + /* The request was terminated explicitly. No handling + * is needed in the SCSI error handler path. + */ + request->complete_in_target = true; + response = SAS_TASK_UNDELIVERED; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_normal_io_completion; + break; + + case SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR: + + isci_request_handle_controller_specific_errors( + isci_device, request, task, &response, &status, + &complete_to_host); + + break; + + case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED: + /* This is a special case, in that the I/O completion + * is telling us that the device needs a reset. + * In order for the device reset condition to be + * noticed, the I/O has to be handled in the error + * handler. Set the reset flag and cause the + * SCSI error thread to be scheduled. + */ + spin_lock_irqsave(&task->task_state_lock, task_flags); + task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&task->task_state_lock, task_flags); + + complete_to_host = isci_perform_error_io_completion; + request->complete_in_target = false; + break; + + default: + /* Catch any otherwise unhandled error codes here. */ + dev_warn(&isci_host->pdev->dev, + "%s: invalid completion code: 0x%x - " + "isci_request = %p\n", + __func__, completion_status, request); + + response = SAS_TASK_UNDELIVERED; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_error_io_completion; + request->complete_in_target = false; + break; + } + break; + } + + isci_request_unmap_sgl(request, isci_host->pdev); + + /* Put the completed request on the correct list */ + isci_task_save_for_upper_layer_completion(isci_host, request, response, + status, complete_to_host + ); + + /* complete the io request to the core. */ + scic_controller_complete_io( + isci_host->core_controller, + isci_device->sci_device_handle, + request->sci_request_handle + ); + /* NULL the request handle so it cannot be completed or + * terminated again, and to cause any calls into abort + * task to recognize the already completed case. + */ + request->sci_request_handle = NULL; + + /* Only remove the request from the remote device list + * of pending requests if we have not requested error + * handling on this request. + */ + if (complete_to_host != isci_perform_error_io_completion) + list_del_init(&request->dev_node); + + + /* Save possible completion ptr. */ + io_request_completion = request->io_request_completion; + + if (io_request_completion) { + + /* This is inherantly a regular I/O request, + * since we are currently in the regular + * I/O completion callback function. + * Signal whoever is waiting that this + * request is complete. + */ + complete(io_request_completion); + } + + isci_host_can_dequeue(isci_host, 1); +} + +/** + * isci_request_io_request_get_transfer_length() - This function is called by + * the sci core to retrieve the transfer length for a given request. + * @request: This parameter is the isci_request object. + * + * length of transfer for specified request. + */ +u32 isci_request_io_request_get_transfer_length(struct isci_request *request) +{ + struct sas_task *task = isci_request_access_task(request); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: total_xfer_len: %d\n", + __func__, + task->total_xfer_len); + return task->total_xfer_len; +} + + +/** + * isci_request_io_request_get_data_direction() - This function is called by + * the sci core to retrieve the data direction for a given request. + * @request: This parameter is the isci_request object. + * + * data direction for specified request. + */ +SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction( + struct isci_request *request) +{ + struct sas_task *task = isci_request_access_task(request); + SCI_IO_REQUEST_DATA_DIRECTION ret; + + switch (task->data_dir) { + + case DMA_FROM_DEVICE: + ret = SCI_IO_REQUEST_DATA_IN; + dev_dbg(&request->isci_host->pdev->dev, + "%s: request=%p, FROM_DEVICE\n", + __func__, + request); + break; + + case DMA_TO_DEVICE: + ret = SCI_IO_REQUEST_DATA_OUT; + dev_dbg(&request->isci_host->pdev->dev, + "%s: request=%p, TO_DEVICE\n", + __func__, + request); + break; + + case DMA_BIDIRECTIONAL: + case DMA_NONE: + default: + ret = SCI_IO_REQUEST_NO_DATA; + dev_dbg(&request->isci_host->pdev->dev, + "%s: request=%p, unhandled direction case, " + "data_dir=%d\n", + __func__, + request, + task->data_dir); + break; + + } + return ret; +} + +/** + * isci_request_sge_get_address_field() - This function is called by the sci + * core to retrieve the address field contents for a given sge. + * @request: This parameter is the isci_request object. + * @sge_address: This parameter is the sge. + * + * physical address in the specified sge. + */ +dma_addr_t isci_request_sge_get_address_field( + struct isci_request *request, + void *sge_address) +{ + struct sas_task *task = isci_request_access_task(request); + dma_addr_t ret; + struct isci_host *isci_host = isci_host_from_sas_ha( + task->dev->port->ha); + + dev_dbg(&isci_host->pdev->dev, + "%s: request = %p, sge_address = %p\n", + __func__, + request, + sge_address); + + if (task->data_dir == PCI_DMA_NONE) + return 0; + + /* the case where num_scatter == 0 is special, in that + * task->scatter is the actual buffer address, not an sgl. + * so a map single is required here. + */ + if ((task->num_scatter == 0) && + !sas_protocol_ata(task->task_proto)) { + ret = dma_map_single( + &isci_host->pdev->dev, + task->scatter, + task->total_xfer_len, + task->data_dir + ); + request->zero_scatter_daddr = ret; + } else + ret = sg_dma_address(((struct scatterlist *)sge_address)); + + dev_dbg(&isci_host->pdev->dev, + "%s: bus address = %lx\n", + __func__, + (unsigned long)ret); + + return ret; +} + + +/** + * isci_request_sge_get_length_field() - This function is called by the sci + * core to retrieve the length field contents for a given sge. + * @request: This parameter is the isci_request object. + * @sge_address: This parameter is the sge. + * + * length field value in the specified sge. + */ +u32 isci_request_sge_get_length_field( + struct isci_request *request, + void *sge_address) +{ + struct sas_task *task = isci_request_access_task(request); + int ret; + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p, sge_address = %p\n", + __func__, + request, + sge_address); + + if (task->data_dir == PCI_DMA_NONE) + return 0; + + /* the case where num_scatter == 0 is special, in that + * task->scatter is the actual buffer address, not an sgl. + * so we return total_xfer_len here. + */ + if (task->num_scatter == 0) + ret = task->total_xfer_len; + else + ret = sg_dma_len((struct scatterlist *)sge_address); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: len = %d\n", + __func__, + ret); + + return ret; +} + + +/** + * isci_request_ssp_io_request_get_cdb_address() - This function is called by + * the sci core to retrieve the cdb address for a given request. + * @request: This parameter is the isci_request object. + * + * cdb address for specified request. + */ +void *isci_request_ssp_io_request_get_cdb_address( + struct isci_request *request) +{ + struct sas_task *task = isci_request_access_task(request); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request->task->ssp_task.cdb = %p\n", + __func__, + task->ssp_task.cdb); + return task->ssp_task.cdb; +} + + +/** + * isci_request_ssp_io_request_get_cdb_length() - This function is called by + * the sci core to retrieve the cdb length for a given request. + * @request: This parameter is the isci_request object. + * + * cdb length for specified request. + */ +u32 isci_request_ssp_io_request_get_cdb_length( + struct isci_request *request) +{ + return 16; +} + + +/** + * isci_request_ssp_io_request_get_lun() - This function is called by the sci + * core to retrieve the lun for a given request. + * @request: This parameter is the isci_request object. + * + * lun for specified request. + */ +u32 isci_request_ssp_io_request_get_lun( + struct isci_request *request) +{ + struct sas_task *task = isci_request_access_task(request); + +#ifdef DEBUG + int i; + + for (i = 0; i < 8; i++) + dev_dbg(&request->isci_host->pdev->dev, + "%s: request->task->ssp_task.LUN[%d] = %x\n", + __func__, i, request->task->ssp_task.LUN[i]); + +#endif + + return task->ssp_task.LUN[0]; +} + + +/** + * isci_request_ssp_io_request_get_task_attribute() - This function is called + * by the sci core to retrieve the task attribute for a given request. + * @request: This parameter is the isci_request object. + * + * task attribute for specified request. + */ +u32 isci_request_ssp_io_request_get_task_attribute( + struct isci_request *request) +{ + struct sas_task *task = isci_request_access_task(request); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request->task->ssp_task.task_attr = %x\n", + __func__, + task->ssp_task.task_attr); + + return task->ssp_task.task_attr; +} + + +/** + * isci_request_ssp_io_request_get_command_priority() - This function is called + * by the sci core to retrieve the command priority for a given request. + * @request: This parameter is the isci_request object. + * + * command priority for specified request. + */ +u32 isci_request_ssp_io_request_get_command_priority( + struct isci_request *request) +{ + struct sas_task *task = isci_request_access_task(request); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request->task->ssp_task.task_prio = %x\n", + __func__, + task->ssp_task.task_prio); + + return task->ssp_task.task_prio; +} diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h new file mode 100644 index 000000000000..5079d4a7c41b --- /dev/null +++ b/drivers/scsi/isci/request.h @@ -0,0 +1,429 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(_ISCI_REQUEST_H_) +#define _ISCI_REQUEST_H_ + +#include "isci.h" + +/** + * struct isci_request_status - This enum defines the possible states of an I/O + * request. + * + * + */ +enum isci_request_status { + unallocated = 0x00, + allocated = 0x01, + started = 0x02, + completed = 0x03, + aborting = 0x04, + aborted = 0x05, + terminating = 0x06 +}; + +enum task_type { + io_task = 0, + tmf_task = 1 +}; + +/** + * struct isci_request - This class represents the request object used to track + * IO, smp and TMF request internal. It wraps the SCIC request object. + * + * + */ +struct isci_request { + + struct scic_sds_request *sci_request_handle; + + enum isci_request_status status; + enum task_type ttype; + unsigned short io_tag; + bool complete_in_target; + + union ttype_ptr_union { + struct sas_task *io_task_ptr; /* When ttype==io_task */ + struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */ + } ttype_ptr; + struct isci_host *isci_host; + struct isci_remote_device *isci_device; + /* For use in the requests_to_{complete|abort} lists: */ + struct list_head completed_node; + /* For use in the reqs_in_process list: */ + struct list_head dev_node; + void *sci_request_mem_ptr; + spinlock_t state_lock; + dma_addr_t request_daddr; + dma_addr_t zero_scatter_daddr; + + unsigned int num_sg_entries; /* returned by pci_alloc_sg */ + unsigned int request_alloc_size; /* size of block from dma_pool_alloc */ + + /** Note: "io_request_completion" is completed in two different ways + * depending on whether this is a TMF or regular request. + * - TMF requests are completed in the thread that started them; + * - regular requests are completed in the request completion callback + * function. + * This difference in operation allows the aborter of a TMF request + * to be sure that once the TMF request completes, the I/O that the + * TMF was aborting is guaranteed to have completed. + */ + struct completion *io_request_completion; +}; + +/** + * This function gets the status of the request object. + * @request: This parameter points to the isci_request object + * + * status of the object as a isci_request_status enum. + */ +static inline +enum isci_request_status isci_request_get_state( + struct isci_request *isci_request) +{ + BUG_ON(isci_request == NULL); + + /*probably a bad sign... */ + if (isci_request->status == unallocated) + dev_warn(&isci_request->isci_host->pdev->dev, + "%s: isci_request->status == unallocated\n", + __func__); + + return isci_request->status; +} + + +/** + * isci_request_change_state() - This function sets the status of the request + * object. + * @request: This parameter points to the isci_request object + * @status: This Parameter is the new status of the object + * + */ +static inline enum isci_request_status isci_request_change_state( + struct isci_request *isci_request, + enum isci_request_status status) +{ + enum isci_request_status old_state; + unsigned long flags; + + dev_dbg(&isci_request->isci_host->pdev->dev, + "%s: isci_request = %p, state = 0x%x\n", + __func__, + isci_request, + status); + + BUG_ON(isci_request == NULL); + + spin_lock_irqsave(&isci_request->state_lock, flags); + old_state = isci_request->status; + isci_request->status = status; + spin_unlock_irqrestore(&isci_request->state_lock, flags); + + return old_state; +} + +/** + * isci_request_change_started_to_newstate() - This function sets the status of + * the request object. + * @request: This parameter points to the isci_request object + * @status: This Parameter is the new status of the object + * + * state previous to any change. + */ +static inline enum isci_request_status isci_request_change_started_to_newstate( + struct isci_request *isci_request, + struct completion *completion_ptr, + enum isci_request_status newstate) +{ + enum isci_request_status old_state; + unsigned long flags; + + BUG_ON(isci_request == NULL); + + spin_lock_irqsave(&isci_request->state_lock, flags); + + old_state = isci_request->status; + + if (old_state == started) { + BUG_ON(isci_request->io_request_completion != NULL); + + isci_request->io_request_completion = completion_ptr; + isci_request->status = newstate; + } + spin_unlock_irqrestore(&isci_request->state_lock, flags); + + dev_dbg(&isci_request->isci_host->pdev->dev, + "%s: isci_request = %p, old_state = 0x%x\n", + __func__, + isci_request, + old_state); + + return old_state; +} + +/** + * isci_request_change_started_to_aborted() - This function sets the status of + * the request object. + * @request: This parameter points to the isci_request object + * @completion_ptr: This parameter is saved as the kernel completion structure + * signalled when the old request completes. + * + * state previous to any change. + */ +static inline enum isci_request_status isci_request_change_started_to_aborted( + struct isci_request *isci_request, + struct completion *completion_ptr) +{ + return isci_request_change_started_to_newstate( + isci_request, completion_ptr, aborted + ); +} +/** + * isci_request_free() - This function frees the request object. + * @isci_host: This parameter specifies the ISCI host object + * @isci_request: This parameter points to the isci_request object + * + */ +static inline void isci_request_free( + struct isci_host *isci_host, + struct isci_request *isci_request) +{ + BUG_ON(isci_request == NULL); + + /* release the dma memory if we fail. */ + dma_pool_free(isci_host->dma_pool, isci_request, + isci_request->request_daddr); +} + + +/* #define ISCI_REQUEST_VALIDATE_ACCESS + */ + +#ifdef ISCI_REQUEST_VALIDATE_ACCESS + +static inline +struct sas_task *isci_request_access_task(struct isci_request *isci_request) +{ + BUG_ON(isci_request->ttype != io_task); + return isci_request->ttype_ptr.io_task_ptr; +} + +static inline +struct isci_tmf *isci_request_access_tmf(struct isci_request *isci_request) +{ + BUG_ON(isci_request->ttype != tmf_task); + return isci_request->ttype_ptr.tmf_task_ptr; +} + +#else /* not ISCI_REQUEST_VALIDATE_ACCESS */ + +#define isci_request_access_task(RequestPtr) \ + ((RequestPtr)->ttype_ptr.io_task_ptr) + +#define isci_request_access_tmf(RequestPtr) \ + ((RequestPtr)->ttype_ptr.tmf_task_ptr) + +#endif /* not ISCI_REQUEST_VALIDATE_ACCESS */ + + +int isci_request_alloc_tmf( + struct isci_host *isci_host, + struct isci_tmf *isci_tmf, + struct isci_request **isci_request, + struct isci_remote_device *isci_device, + gfp_t gfp_flags); + + +int isci_request_execute( + struct isci_host *isci_host, + struct sas_task *task, + struct isci_request **request, + gfp_t gfp_flags); + +/** + * isci_request_unmap_sgl() - This function unmaps the DMA address of a given + * sgl + * @request: This parameter points to the isci_request object + * @*pdev: This Parameter is the pci_device struct for the controller + * + */ +static inline void isci_request_unmap_sgl( + struct isci_request *request, + struct pci_dev *pdev) +{ + struct sas_task *task = isci_request_access_task(request); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p, task = %p,\n" + "task->data_dir = %d, is_sata = %d\n ", + __func__, + request, + task, + task->data_dir, + sas_protocol_ata(task->task_proto)); + + if ((task->data_dir != PCI_DMA_NONE) && + !sas_protocol_ata(task->task_proto)) { + if (task->num_scatter == 0) + /* 0 indicates a single dma address */ + dma_unmap_single( + &pdev->dev, + request->zero_scatter_daddr, + task->total_xfer_len, + task->data_dir + ); + + else /* unmap the sgl dma addresses */ + dma_unmap_sg( + &pdev->dev, + task->scatter, + request->num_sg_entries, + task->data_dir + ); + } +} + + +void isci_request_io_request_complete( + struct isci_host *isci_host, + struct isci_request *request, + enum sci_io_status completion_status); + +u32 isci_request_io_request_get_transfer_length( + struct isci_request *request); + +SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction( + struct isci_request *request); + +/** + * isci_request_io_request_get_next_sge() - This function is called by the sci + * core to retrieve the next sge for a given request. + * @request: This parameter is the isci_request object. + * @current_sge_address: This parameter is the last sge retrieved by the sci + * core for this request. + * + * pointer to the next sge for specified request. + */ +static inline void *isci_request_io_request_get_next_sge( + struct isci_request *request, + void *current_sge_address) +{ + struct sas_task *task = isci_request_access_task(request); + void *ret = NULL; + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p, " + "current_sge_address = %p, " + "num_scatter = %d\n", + __func__, + request, + current_sge_address, + task->num_scatter); + + if (!current_sge_address) /* First time through.. */ + ret = task->scatter; /* always task->scatter */ + else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */ + ret = NULL; /* there is only one element. */ + else + ret = sg_next(current_sge_address); /* sg_next returns NULL + * for the last element + */ + + dev_dbg(&request->isci_host->pdev->dev, + "%s: next sge address = %p\n", + __func__, + ret); + + return ret; +} + +dma_addr_t isci_request_sge_get_address_field( + struct isci_request *request, + void *sge_address); + +u32 isci_request_sge_get_length_field( + struct isci_request *request, + void *sge_address); + +void *isci_request_ssp_io_request_get_cdb_address( + struct isci_request *request); + +u32 isci_request_ssp_io_request_get_cdb_length( + struct isci_request *request); + +u32 isci_request_ssp_io_request_get_lun( + struct isci_request *request); + +u32 isci_request_ssp_io_request_get_task_attribute( + struct isci_request *request); + +u32 isci_request_ssp_io_request_get_command_priority( + struct isci_request *request); + + + + + +void isci_terminate_pending_requests( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + enum isci_request_status new_request_state); + + + + +#endif /* !defined(_ISCI_REQUEST_H_) */ diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c new file mode 100644 index 000000000000..19b0eea93ca7 --- /dev/null +++ b/drivers/scsi/isci/sata.c @@ -0,0 +1,356 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "isci.h" +#include "scic_remote_device.h" +#include "scic_sds_remote_device.h" +#include "scic_io_request.h" +#include "scic_task_request.h" +#include "task.h" +#include "request.h" +#include "sata.h" +#include "intel_sat.h" +#include "intel_ata.h" + +static u8 isci_sata_get_management_task_protocol(struct isci_tmf *tmf); + + +/** + * isci_sata_task_to_fis_copy() - This function gets the host_to_dev_fis from + * the core and copies the fis from the task into it. + * @task: This parameter is a pointer to the task struct from libsas. + * + * pointer to the host_to_dev_fis from the core request object. + */ +struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task) +{ + struct isci_request *request = task->lldd_task; + struct host_to_dev_fis *register_fis = + scic_stp_io_request_get_h2d_reg_address( + request->sci_request_handle + ); + + memcpy( + (u8 *)register_fis, + (u8 *)&task->ata_task.fis, + sizeof(struct host_to_dev_fis) + ); + + if (!task->ata_task.device_control_reg_update) + register_fis->flags |= 0x80; + + register_fis->flags &= 0xF0; + + return register_fis; +} + +/** + * isci_sata_is_task_ncq() - This function determines if the given stp task is + * a ncq request. + * @task: This parameter is a pointer to the task struct from libsas. + * + * true if the task is ncq + */ +bool isci_sata_is_task_ncq(struct sas_task *task) +{ + struct ata_queued_cmd *qc = task->uldd_task; + + bool ret = (qc && + (qc->tf.command == ATA_CMD_FPDMA_WRITE || + qc->tf.command == ATA_CMD_FPDMA_READ)); + + return ret; +} + +/** + * isci_sata_set_ncq_tag() - This function sets the ncq tag field in the + * host_to_dev_fis equal to the tag in the queue command in the task. + * @task: This parameter is a pointer to the task struct from libsas. + * @register_fis: This parameter is a pointer to the host_to_dev_fis from the + * core request object. + * + */ +void isci_sata_set_ncq_tag( + struct host_to_dev_fis *register_fis, + struct sas_task *task) +{ + struct ata_queued_cmd *qc = task->uldd_task; + struct isci_request *request = task->lldd_task; + + register_fis->sector_count = qc->tag << 3; + scic_stp_io_request_set_ncq_tag(request->sci_request_handle, qc->tag); +} + +/** + * isci_request_process_stp_response() - This function sets the status and + * response, in the task struct, from the request object for the upper layer + * driver. + * @sas_task: This parameter is the task struct from the upper layer driver. + * @response_buffer: This parameter points to the response of the completed + * request. + * + * none. + */ +void isci_request_process_stp_response( + struct sas_task *task, + void *response_buffer) +{ + struct sata_fis_reg_d2h *d2h_reg_fis = (struct sata_fis_reg_d2h *)response_buffer; + struct task_status_struct *ts = &task->task_status; + struct ata_task_resp *resp = (void *)&ts->buf[0]; + + resp->frame_len = le16_to_cpu(*(__le16 *)(response_buffer + 6)); + memcpy(&resp->ending_fis[0], response_buffer + 16, 24); + ts->buf_valid_size = sizeof(*resp); + + /** + * If the device fault bit is set in the status register, then + * set the sense data and return. + */ + if (d2h_reg_fis->status & ATA_STATUS_REG_DEVICE_FAULT_BIT) + ts->stat = SAS_PROTO_RESPONSE; + else + ts->stat = SAM_STAT_GOOD; + + ts->resp = SAS_TASK_COMPLETE; +} + +/** + * isci_sata_get_sat_protocol() - retrieve the sat protocol for the request + * @isci_request: ata request + * + * Note: temporary implementation until expert mode removes the callback + * + */ +u8 isci_sata_get_sat_protocol(struct isci_request *isci_request) +{ + struct sas_task *task; + struct domain_device *dev; + + dev_dbg(&isci_request->isci_host->pdev->dev, + "%s: isci_request = %p, ttype = %d\n", + __func__, isci_request, isci_request->ttype); + + if (tmf_task == isci_request->ttype) { + struct isci_tmf *tmf = isci_request_access_tmf(isci_request); + + return isci_sata_get_management_task_protocol(tmf); + } + + task = isci_request_access_task(isci_request); + dev = task->dev; + + if (!sas_protocol_ata(task->task_proto)) { + WARN(1, "unhandled task protocol\n"); + return SAT_PROTOCOL_NON_DATA; + } + + if (task->data_dir == DMA_NONE) + return SAT_PROTOCOL_NON_DATA; + + /* the "_IN" protocol types are equivalent to their "_OUT" + * analogs as far as the core is concerned + */ + if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { + if (task->ata_task.dma_xfer) + return SAT_PROTOCOL_PACKET_DMA_DATA_IN; + else + return SAT_PROTOCOL_PACKET_PIO_DATA_IN; + } + + if (task->ata_task.use_ncq) + return SAT_PROTOCOL_FPDMA; + + if (task->ata_task.dma_xfer) + return SAT_PROTOCOL_UDMA_DATA_IN; + else + return SAT_PROTOCOL_PIO_DATA_IN; +} + +static u8 isci_sata_get_management_task_protocol( + struct isci_tmf *tmf) +{ + u8 ret = 0; + + pr_warn("tmf = %p, func = %d\n", tmf, tmf->tmf_code); + + if ((tmf->tmf_code == isci_tmf_sata_srst_high) || + (tmf->tmf_code == isci_tmf_sata_srst_low)) { + pr_warn("%s: tmf->tmf_code == TMF_LU_RESET\n", __func__); + ret = SAT_PROTOCOL_SOFT_RESET; + } + + return ret; +} + +enum sci_status isci_sata_management_task_request_build( + struct isci_request *isci_request) +{ + struct isci_tmf *isci_tmf; + enum sci_status status; + + if (tmf_task != isci_request->ttype) + return SCI_FAILURE; + + isci_tmf = isci_request_access_tmf(isci_request); + + switch (isci_tmf->tmf_code) { + + case isci_tmf_sata_srst_high: + case isci_tmf_sata_srst_low: + { + struct host_to_dev_fis *register_fis = + scic_stp_io_request_get_h2d_reg_address( + isci_request->sci_request_handle + ); + + memset(register_fis, 0, sizeof(*register_fis)); + + register_fis->fis_type = 0x27; + register_fis->flags &= ~0x80; + register_fis->flags &= 0xF0; + if (isci_tmf->tmf_code == isci_tmf_sata_srst_high) + register_fis->control |= ATA_SRST; + else + register_fis->control &= ~ATA_SRST; + break; + } + /* other management commnd go here... */ + default: + return SCI_FAILURE; + } + + /* core builds the protocol specific request + * based on the h2d fis. + */ + status = scic_task_request_construct_sata( + isci_request->sci_request_handle + ); + + return status; +} + +/** + * isci_task_send_lu_reset_sata() - This function is called by of the SAS + * Domain Template functions. This is one of the Task Management functoins + * called by libsas, to reset the given SAS lun. Note the assumption that + * while this call is executing, no I/O will be sent by the host to the + * device. + * @lun: This parameter specifies the lun to be reset. + * + * status, zero indicates success. + */ +int isci_task_send_lu_reset_sata( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + u8 *lun) +{ + struct isci_tmf tmf; + int ret = TMF_RESP_FUNC_FAILED; + unsigned long flags; + + /* Send the initial SRST to the target */ + #define ISCI_SRST_TIMEOUT_MS 20 /* 20 ms timeout. */ + isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_high, + NULL, NULL + ); + + ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS); + + if (ret != TMF_RESP_FUNC_COMPLETE) { + dev_warn(&isci_host->pdev->dev, + "%s: Assert SRST failed (%p) = %x", + __func__, + isci_device, + ret); + + /* Return the failure so that the LUN reset is escalated + * to a target reset. + */ + goto out; + } + + /* Leave SRST high for a bit. */ + #define ISCI_SRST_ASSERT_DELAY 100 /* usecs */ + scic_cb_stall_execution(ISCI_SRST_ASSERT_DELAY); + + /* Deassert SRST. */ + isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_low, + NULL, NULL + ); + ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS); + + if (ret == TMF_RESP_FUNC_COMPLETE) + dev_dbg(&isci_host->pdev->dev, + "%s: SATA LUN reset passed (%p)\n", + __func__, + isci_device); + else + dev_warn(&isci_host->pdev->dev, + "%s: Deassert SRST failed (%p)=%x\n", + __func__, + isci_device, + ret); + + out: + spin_lock_irqsave(&isci_host->scic_lock, flags); + + /* Resume the device. */ + scic_sds_remote_device_resume(isci_device->sci_device_handle); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + return ret; +} diff --git a/drivers/scsi/isci/sata.h b/drivers/scsi/isci/sata.h new file mode 100644 index 000000000000..b6ba25b52d2c --- /dev/null +++ b/drivers/scsi/isci/sata.h @@ -0,0 +1,83 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "intel_sat.h" + + + +struct host_to_dev_fis *isci_sata_task_to_fis_copy( + struct sas_task *task); + +bool isci_sata_is_task_ncq( + struct sas_task *task); + +void isci_sata_set_ncq_tag( + struct host_to_dev_fis *register_fis, + struct sas_task *task); + +void isci_request_process_stp_response( + struct sas_task *task, + void *response_buffer); + +u8 isci_sata_get_sat_protocol( + struct isci_request *isci_request); + +enum sci_status isci_sata_management_task_request_build( + struct isci_request *isci_request); + +int isci_task_send_lu_reset_sata( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + u8 *lun); diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h new file mode 100644 index 000000000000..e1020ee6c38e --- /dev/null +++ b/drivers/scsi/isci/sci_environment.h @@ -0,0 +1,112 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_ENVIRONMENT_H_ +#define _SCI_ENVIRONMENT_H_ + +#include "isci.h" + +struct scic_sds_controller; +struct scic_sds_phy; +struct scic_sds_port; +struct scic_sds_remote_device; + +static inline struct device *scic_to_dev(struct scic_sds_controller *scic) +{ + struct isci_host *isci_host = sci_object_get_association(scic); + + return &isci_host->pdev->dev; +} + +static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) +{ + struct isci_phy *iphy = sci_object_get_association(sci_phy); + + if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host) + return NULL; + + return &iphy->isci_port->isci_host->pdev->dev; +} + +static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port) +{ + struct isci_port *iport = sci_object_get_association(sci_port); + + if (!iport || !iport->isci_host) + return NULL; + + return &iport->isci_host->pdev->dev; +} + +static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev) +{ + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + if (!idev || !idev->isci_port || !idev->isci_port->isci_host) + return NULL; + + return &idev->isci_port->isci_host->pdev->dev; +} + +enum { + ISCI_SI_REVA0, + ISCI_SI_REVA2, + ISCI_SI_REVB0, +}; + +extern int isci_si_rev; + + +#endif diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c new file mode 100644 index 000000000000..5e6f55863407 --- /dev/null +++ b/drivers/scsi/isci/task.c @@ -0,0 +1,1691 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "scic_task_request.h" +#include "scic_remote_device.h" +#include "scic_io_request.h" +#include "scic_sds_remote_device.h" +#include "scic_sds_remote_node_context.h" +#include "isci.h" +#include "request.h" +#include "sata.h" +#include "task.h" + + +/** + * isci_task_execute_task() - This function is one of the SAS Domain Template + * functions. This function is called by libsas to send a task down to + * hardware. + * @task: This parameter specifies the SAS task to send. + * @num: This parameter specifies the number of tasks to queue. + * @gfp_flags: This parameter specifies the context of this call. + * + * status, zero indicates success. + */ +int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) +{ + struct isci_host *isci_host; + struct isci_request *request = NULL; + struct isci_remote_device *device; + unsigned long flags; + unsigned long quiesce_flags = 0; + int ret; + enum sci_status status; + + + dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num); + + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + + isci_task_complete_for_upper_layer( + task, + SAS_TASK_UNDELIVERED, + SAM_STAT_TASK_ABORTED, + isci_perform_normal_io_completion + ); + + return 0; /* The I/O was accepted (and failed). */ + } + if ((task->dev == NULL) || (task->dev->port == NULL)) { + + /* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer + * removes the target. + */ + isci_task_complete_for_upper_layer( + task, + SAS_TASK_UNDELIVERED, + SAS_DEVICE_UNKNOWN, + isci_perform_normal_io_completion + ); + return 0; /* The I/O was accepted (and failed). */ + } + isci_host = isci_host_from_sas_ha(task->dev->port->ha); + + /* Check if we have room for more tasks */ + ret = isci_host_can_queue(isci_host, num); + + if (ret) { + dev_warn(task->dev->port->ha->dev, "%s: queue full\n", __func__); + return ret; + } + + do { + dev_dbg(task->dev->port->ha->dev, + "task = %p, num = %d; dev = %p; cmd = %p\n", + task, num, task->dev, task->uldd_task); + + if ((task->dev == NULL) || (task->dev->port == NULL)) { + dev_warn(task->dev->port->ha->dev, + "%s: task %p's port or dev == NULL!\n", + __func__, task); + + /* Indicate SAS_TASK_UNDELIVERED, so that the scsi + * midlayer removes the target. + */ + isci_task_complete_for_upper_layer( + task, + SAS_TASK_UNDELIVERED, + SAS_DEVICE_UNKNOWN, + isci_perform_normal_io_completion + ); + /* We don't have a valid host reference, so we + * can't control the host queueing condition. + */ + continue; + } + + device = isci_dev_from_domain_dev(task->dev); + + isci_host = isci_host_from_sas_ha(task->dev->port->ha); + + /* check if the controller hasn't started or if the device + * is ready but not accepting IO. + */ + if (device) { + + spin_lock_irqsave(&device->host_quiesce_lock, + quiesce_flags); + } + /* From this point onward, any process that needs to guarantee + * that there is no kernel I/O being started will have to wait + * for the quiesce spinlock. + */ + + if (isci_host_get_state(isci_host) == isci_starting || + (device && ((isci_remote_device_get_state(device) == isci_ready) || + (isci_remote_device_get_state(device) == isci_host_quiesce)))) { + + /* Forces a retry from scsi mid layer. */ + dev_warn(task->dev->port->ha->dev, + "%s: task %p: isci_host->status = %d, " + "device = %p\n", + __func__, + task, + isci_host_get_state(isci_host), + device); + + if (device) + dev_dbg(task->dev->port->ha->dev, + "%s: device->status = 0x%x\n", + __func__, + isci_remote_device_get_state(device)); + + /* Indicate QUEUE_FULL so that the scsi midlayer + * retries. + */ + isci_task_complete_for_upper_layer( + task, + SAS_TASK_COMPLETE, + SAS_QUEUE_FULL, + isci_perform_normal_io_completion + ); + isci_host_can_dequeue(isci_host, 1); + } + /* the device is going down... */ + else if (!device || (isci_ready_for_io != isci_remote_device_get_state(device))) { + + dev_dbg(task->dev->port->ha->dev, + "%s: task %p: isci_host->status = %d, " + "device = %p\n", + __func__, + task, + isci_host_get_state(isci_host), + device); + + if (device) + dev_dbg(task->dev->port->ha->dev, + "%s: device->status = 0x%x\n", + __func__, + isci_remote_device_get_state(device)); + + /* Indicate SAS_TASK_UNDELIVERED, so that the scsi + * midlayer removes the target. + */ + isci_task_complete_for_upper_layer( + task, + SAS_TASK_UNDELIVERED, + SAS_DEVICE_UNKNOWN, + isci_perform_normal_io_completion + ); + isci_host_can_dequeue(isci_host, 1); + + } else { + /* build and send the request. */ + status = isci_request_execute(isci_host, task, &request, + gfp_flags); + + if (status == SCI_SUCCESS) { + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags |= SAS_TASK_AT_INITIATOR; + spin_unlock_irqrestore(&task->task_state_lock, flags); + } else { + /* Indicate QUEUE_FULL so that the scsi + * midlayer retries. if the request + * failed for remote device reasons, + * it gets returned as + * SAS_TASK_UNDELIVERED next time + * through. + */ + isci_task_complete_for_upper_layer( + task, + SAS_TASK_COMPLETE, + SAS_QUEUE_FULL, + isci_perform_normal_io_completion + ); + isci_host_can_dequeue(isci_host, 1); + } + } + if (device) { + spin_unlock_irqrestore(&device->host_quiesce_lock, + quiesce_flags + ); + } + task = list_entry(task->list.next, struct sas_task, list); + } while (--num > 0); + return 0; +} + + + +/** + * isci_task_request_build() - This function builds the task request object. + * @isci_host: This parameter specifies the ISCI host object + * @request: This parameter points to the isci_request object allocated in the + * request construct function. + * @tmf: This parameter is the task management struct to be built + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +static enum sci_status isci_task_request_build( + struct isci_host *isci_host, + struct isci_request **isci_request, + struct isci_tmf *isci_tmf) +{ + struct scic_sds_remote_device *sci_device; + enum sci_status status = SCI_FAILURE; + struct isci_request *request; + struct isci_remote_device *isci_device; +/* struct sci_sas_identify_address_frame_protocols dev_protocols; */ + struct smp_discover_response_protocols dev_protocols; + + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_tmf = %p\n", __func__, isci_tmf); + + isci_device = isci_tmf->device; + sci_device = isci_device->sci_device_handle; + + /* do common allocation and init of request object. */ + status = isci_request_alloc_tmf( + isci_host, + isci_tmf, + &request, + isci_device, + GFP_ATOMIC + ); + + if (status != SCI_SUCCESS) + goto out; + + /* let the core do it's construct. */ + status = scic_task_request_construct( + isci_host->core_controller, + sci_device, + SCI_CONTROLLER_INVALID_IO_TAG, + request, + request->sci_request_mem_ptr, + &request->sci_request_handle + ); + + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: scic_task_request_construct failed - " + "status = 0x%x\n", + __func__, + status); + goto errout; + } + + sci_object_set_association( + request->sci_request_handle, + request + ); + + scic_remote_device_get_protocols( + sci_device, + &dev_protocols + ); + + /* let the core do it's protocol + * specific construction. + */ + if (dev_protocols.u.bits.attached_ssp_target) { + + isci_tmf->proto = SAS_PROTOCOL_SSP; + status = scic_task_request_construct_ssp( + request->sci_request_handle + ); + if (status != SCI_SUCCESS) + goto errout; + } + + if (dev_protocols.u.bits.attached_stp_target) { + + isci_tmf->proto = SAS_PROTOCOL_SATA; + status = isci_sata_management_task_request_build(request); + + if (status != SCI_SUCCESS) + goto errout; + } + + goto out; + + errout: + + /* release the dma memory if we fail. */ + isci_request_free(isci_host, request); + request = NULL; + + out: + *isci_request = request; + return status; +} + +/** + * isci_tmf_timeout_cb() - This function is called as a kernel callback when + * the timeout period for the TMF has expired. + * + * + */ +static void isci_tmf_timeout_cb(void *tmf_request_arg) +{ + struct isci_request *request = (struct isci_request *)tmf_request_arg; + struct isci_tmf *tmf = isci_request_access_tmf(request); + enum sci_status status; + + BUG_ON(request->ttype != tmf_task); + + /* This task management request has timed-out. Terminate the request + * so that the request eventually completes to the requestor in the + * request completion callback path. + */ + /* Note - the timer callback function itself has provided spinlock + * exclusion from the start and completion paths. No need to take + * the request->isci_host->scic_lock here. + */ + + if (tmf->timeout_timer != NULL) { + /* Call the users callback, if any. */ + if (tmf->cb_state_func != NULL) + tmf->cb_state_func(isci_tmf_timed_out, tmf, + tmf->cb_data); + + /* Terminate the TMF transmit request. */ + status = scic_controller_terminate_request( + request->isci_host->core_controller, + request->isci_device->sci_device_handle, + request->sci_request_handle + ); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: tmf_request = %p; tmf = %p; status = %d\n", + __func__, request, tmf, status); + } else + dev_dbg(&request->isci_host->pdev->dev, + "%s: timer already canceled! " + "tmf_request = %p; tmf = %p\n", + __func__, request, tmf); + + /* No need to unlock since the caller to this callback is doing it for + * us. + * request->isci_host->scic_lock + */ +} + +/** + * isci_task_execute_tmf() - This function builds and sends a task request, + * then waits for the completion. + * @isci_host: This parameter specifies the ISCI host object + * @tmf: This parameter is the pointer to the task management structure for + * this request. + * @timeout_ms: This parameter specifies the timeout period for the task + * management request. + * + * TMF_RESP_FUNC_COMPLETE on successful completion of the TMF (this includes + * error conditions reported in the IU status), or TMF_RESP_FUNC_FAILED. + */ +int isci_task_execute_tmf( + struct isci_host *isci_host, + struct isci_tmf *tmf, + unsigned long timeout_ms) +{ + DECLARE_COMPLETION_ONSTACK(completion); + enum sci_status status = SCI_FAILURE; + struct scic_sds_remote_device *sci_device; + struct isci_remote_device *isci_device = tmf->device; + struct isci_request *request; + int ret = TMF_RESP_FUNC_FAILED; + unsigned long flags; + + /* sanity check, return TMF_RESP_FUNC_FAILED + * if the device is not there and ready. + */ + if (!isci_device || + ((isci_ready_for_io != isci_remote_device_get_state(isci_device)) && + (isci_host_quiesce != isci_remote_device_get_state(isci_device)))) { + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p not ready (%d)\n", + __func__, + isci_device, + isci_remote_device_get_state(isci_device)); + return TMF_RESP_FUNC_FAILED; + } else + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", + __func__, isci_device); + + sci_device = isci_device->sci_device_handle; + + /* Assign the pointer to the TMF's completion kernel wait structure. */ + tmf->complete = &completion; + + isci_task_request_build( + isci_host, + &request, + tmf + ); + + if (!request) { + dev_warn(&isci_host->pdev->dev, + "%s: isci_task_request_build failed\n", + __func__); + return TMF_RESP_FUNC_FAILED; + } + + /* Allocate the TMF timeout timer. */ + tmf->timeout_timer = isci_timer_create( + &isci_host->timer_list_struct, + isci_host, + request, + isci_tmf_timeout_cb + ); + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + /* Start the timer. */ + if (tmf->timeout_timer) + isci_timer_start(tmf->timeout_timer, timeout_ms); + else + dev_warn(&isci_host->pdev->dev, + "%s: isci_timer_create failed!!!!\n", + __func__); + + /* start the TMF io. */ + status = scic_controller_start_task( + isci_host->core_controller, + sci_device, + request->sci_request_handle, + SCI_CONTROLLER_INVALID_IO_TAG + ); + + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: start_io failed - status = 0x%x, request = %p\n", + __func__, + status, + request); + goto cleanup_request; + } + + /* Call the users callback, if any. */ + if (tmf->cb_state_func != NULL) + tmf->cb_state_func(isci_tmf_started, tmf, tmf->cb_data); + + /* Change the state of the TMF-bearing request to "started". */ + isci_request_change_state(request, started); + + /* add the request to the remote device request list. */ + list_add(&request->dev_node, &isci_device->reqs_in_process); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + /* Wait for the TMF to complete, or a timeout. */ + wait_for_completion(&completion); + + isci_print_tmf(tmf); + + if (tmf->status == SCI_SUCCESS) + ret = TMF_RESP_FUNC_COMPLETE; + else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) { + dev_dbg(&isci_host->pdev->dev, + "%s: tmf.status == " + "SCI_FAILURE_IO_RESPONSE_VALID\n", + __func__); + ret = TMF_RESP_FUNC_COMPLETE; + } + /* Else - leave the default "failed" status alone. */ + + dev_dbg(&isci_host->pdev->dev, + "%s: completed request = %p\n", + __func__, + request); + + if (request->io_request_completion != NULL) { + + /* The fact that this is non-NULL for a TMF request + * means there is a thread waiting for this TMF to + * finish. + */ + complete(request->io_request_completion); + } + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + cleanup_request: + + /* Clean up the timer if needed. */ + if (tmf->timeout_timer) { + isci_timer_stop(tmf->timeout_timer); + isci_timer_free(&isci_host->timer_list_struct, + tmf->timeout_timer); + tmf->timeout_timer = NULL; + } + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + isci_request_free(isci_host, request); + + return ret; +} + +void isci_task_build_tmf( + struct isci_tmf *tmf, + struct isci_remote_device *isci_device, + enum isci_tmf_function_codes code, + void (*tmf_sent_cb)(enum isci_tmf_cb_state, + struct isci_tmf *, + void *), + void *cb_data) +{ + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + "%s: isci_device = %p\n", __func__, isci_device); + + memset(tmf, 0, sizeof(*tmf)); + + tmf->device = isci_device; + tmf->tmf_code = code; + tmf->timeout_timer = NULL; + tmf->cb_state_func = tmf_sent_cb; + tmf->cb_data = cb_data; +} + +static struct isci_request *isci_task_get_request_from_task( + struct sas_task *task, + struct isci_host **isci_host, + struct isci_remote_device **isci_device) +{ + + struct isci_request *request = NULL; + unsigned long flags; + + spin_lock_irqsave(&task->task_state_lock, flags); + + request = task->lldd_task; + + /* If task is already done, the request isn't valid */ + if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && + (task->task_state_flags & SAS_TASK_AT_INITIATOR) && + (request != NULL)) { + + if (isci_host != NULL) + *isci_host = request->isci_host; + + if (isci_device != NULL) + *isci_device = request->isci_device; + } + + spin_unlock_irqrestore(&task->task_state_lock, flags); + + return request; +} + +/** + * isci_task_validate_request_to_abort() - This function checks the given I/O + * against the "started" state. If the request is still "started", it's + * state is changed to aborted. NOTE: isci_host->scic_lock MUST BE HELD + * BEFORE CALLING THIS FUNCTION. + * @isci_request: This parameter specifies the request object to control. + * @isci_host: This parameter specifies the ISCI host object + * @isci_device: This is the device to which the request is pending. + * @aborted_io_completion: This is a completion structure that will be added to + * the request in case it is changed to aborting; this completion is + * triggered when the request is fully completed. + * + * Either "started" on successful change of the task status to "aborted", or + * "unallocated" if the task cannot be controlled. + */ +static enum isci_request_status isci_task_validate_request_to_abort( + struct isci_request *isci_request, + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + struct completion *aborted_io_completion) +{ + enum isci_request_status old_state = unallocated; + + /* Only abort the task if it's in the + * device's request_in_process list + */ + if (isci_request && !list_empty(&isci_request->dev_node)) { + old_state = isci_request_change_started_to_aborted( + isci_request, aborted_io_completion); + + /* Only abort requests in the started state. */ + if (old_state != started) + old_state = unallocated; + } + + return old_state; +} + +static void isci_request_cleanup_completed_loiterer( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + struct isci_request *isci_request) +{ + struct sas_task *task = isci_request_access_task(isci_request); + unsigned long flags; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device=%p, request=%p, task=%p\n", + __func__, isci_device, isci_request, + isci_request->ttype_ptr.io_task_ptr); + + spin_lock_irqsave(&isci_host->scic_lock, flags); + list_del_init(&isci_request->dev_node); + if (task != NULL) + task->lldd_task = NULL; + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + isci_request_free(isci_host, isci_request); +} +/** + * isci_terminate_request_core() - This function will terminate the given + * request, and wait for it to complete. This function must only be called + * from a thread that can wait. Note that the request is terminated and + * completed (back to the host, if started there). + * @isci_host: This SCU. + * @isci_device: The target. + * @isci_request: The I/O request to be terminated. + * + * + */ +static void isci_terminate_request_core( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + struct isci_request *isci_request, + struct completion *request_completion) +{ + enum sci_status status = SCI_SUCCESS; + bool was_terminated = false; + bool needs_cleanup_handling = false; + enum isci_request_status request_status; + unsigned long flags; + + dev_dbg(&isci_host->pdev->dev, + "%s: device = %p; request = %p\n", + __func__, isci_device, isci_request); + + /* Peek at the current status of the request. This will tell + * us if there was special handling on the request such that it + * needs to be detached and freed here. + */ + spin_lock_irqsave(&isci_request->state_lock, flags); + request_status = isci_request_get_state(isci_request); + + /* TMFs are in their own thread */ + if ((isci_request->ttype == io_task) && + ((request_status == aborted) || + (request_status == aborting) || + (request_status == terminating))) + /* The completion routine won't free a request in + * the aborted/aborting/terminating state, so we do + * it here. + */ + needs_cleanup_handling = true; + + spin_unlock_irqrestore(&isci_request->state_lock, flags); + + spin_lock_irqsave(&isci_host->scic_lock, flags); + /* Make sure the request wasn't just sitting around signalling + * device condition (if the request handle is NULL, then the + * request completed but needed additional handling here). + */ + if (isci_request->sci_request_handle != NULL) { + was_terminated = true; + status = scic_controller_terminate_request( + isci_host->core_controller, + isci_device->sci_device_handle, + isci_request->sci_request_handle + ); + } + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + /* + * The only time the request to terminate will + * fail is when the io request is completed and + * being aborted. + */ + if (status != SCI_SUCCESS) + dev_err(&isci_host->pdev->dev, + "%s: scic_controller_terminate_request" + " returned = 0x%x\n", + __func__, + status); + else { + if (was_terminated) { + dev_dbg(&isci_host->pdev->dev, + "%s: before completion wait (%p)\n", + __func__, + request_completion); + + /* Wait here for the request to complete. */ + wait_for_completion(request_completion); + + dev_dbg(&isci_host->pdev->dev, + "%s: after completion wait (%p)\n", + __func__, + request_completion); + } + + if (needs_cleanup_handling) + isci_request_cleanup_completed_loiterer( + isci_host, isci_device, isci_request + ); + } +} +static void isci_terminate_request( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + struct isci_request *isci_request, + enum isci_request_status new_request_state) +{ + enum isci_request_status old_state; + + DECLARE_COMPLETION_ONSTACK(request_completion); + unsigned long flags; + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + /* Change state to "new_request_state" if it is currently "started" */ + old_state = isci_request_change_started_to_newstate( + isci_request, + &request_completion, + new_request_state + ); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + if (old_state == started) + /* This request was not already being aborted. If it had been, + * then the aborting I/O (ie. the TMF request) would not be in + * the aborting state, and thus would be terminated here. Note + * that since the TMF completion's call to the kernel function + * "complete()" does not happen until the pending I/O request + * terminate fully completes, we do not have to implement a + * special wait here for already aborting requests - the + * termination of the TMF request will force the request + * to finish it's already started terminate. + */ + isci_terminate_request_core(isci_host, isci_device, + isci_request, &request_completion); +} + +/** + * isci_terminate_pending_requests() - This function will change the all of the + * requests on the given device's state to "aborting", will terminate the + * requests, and wait for them to complete. This function must only be + * called from a thread that can wait. Note that the requests are all + * terminated and completed (back to the host, if started there). + * @isci_host: This parameter specifies SCU. + * @isci_device: This parameter specifies the target. + * + * + */ +void isci_terminate_pending_requests( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + enum isci_request_status new_request_state) +{ + struct isci_request *isci_request; + struct sas_task *task; + bool done = false; + unsigned long flags; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p (new request state = %d)\n", + __func__, isci_device, new_request_state); + + #define ISCI_TERMINATE_SHOW_PENDING_REQUESTS + #ifdef ISCI_TERMINATE_SHOW_PENDING_REQUESTS + { + struct isci_request *request; + + /* Only abort the task if it's in the + * device's request_in_process list + */ + list_for_each_entry(request, + &isci_device->reqs_in_process, + dev_node) + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p; request is on " + "reqs_in_process list: %p\n", + __func__, isci_device, request); + } + #endif /* ISCI_TERMINATE_SHOW_PENDING_REQUESTS */ + + /* Clean up all pending requests. */ + do { + spin_lock_irqsave(&isci_host->scic_lock, flags); + + if (list_empty(&isci_device->reqs_in_process)) { + + done = true; + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p; done.\n", + __func__, isci_device); + } else { + /* The list was not empty - grab the first request. */ + isci_request = list_first_entry( + &isci_device->reqs_in_process, + struct isci_request, dev_node + ); + /* Note that we are not expecting to have to control + * the target to abort the request. + */ + isci_request->complete_in_target = true; + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + /* Get the libsas task reference. */ + task = isci_request_access_task(isci_request); + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device=%p request=%p; task=%p\n", + __func__, isci_device, isci_request, task); + + /* Mark all still pending I/O with the selected next + * state. + */ + isci_terminate_request(isci_host, isci_device, + isci_request, new_request_state + ); + + /* Set the 'done' state on the task. */ + if (task) + isci_task_all_done(task); + } + } while (!done); +} + +/** + * isci_task_send_lu_reset_sas() - This function is called by of the SAS Domain + * Template functions. + * @lun: This parameter specifies the lun to be reset. + * + * status, zero indicates success. + */ +static int isci_task_send_lu_reset_sas( + struct isci_host *isci_host, + struct isci_remote_device *isci_device, + u8 *lun) +{ + struct isci_tmf tmf; + int ret = TMF_RESP_FUNC_FAILED; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_host = %p, isci_device = %p\n", + __func__, isci_host, isci_device); + /* Send the LUN reset to the target. By the time the call returns, + * the TMF has fully exected in the target (in which case the return + * value is "TMF_RESP_FUNC_COMPLETE", or the request timed-out (or + * was otherwise unable to be executed ("TMF_RESP_FUNC_FAILED"). + */ + isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_lun_reset, NULL, + NULL); + + #define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */ + ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_LU_RESET_TIMEOUT_MS); + + if (ret == TMF_RESP_FUNC_COMPLETE) + dev_dbg(&isci_host->pdev->dev, + "%s: %p: TMF_LU_RESET passed\n", + __func__, isci_device); + else + dev_dbg(&isci_host->pdev->dev, + "%s: %p: TMF_LU_RESET failed (%x)\n", + __func__, isci_device, ret); + + return ret; +} + +/** + * isci_task_lu_reset() - This function is one of the SAS Domain Template + * functions. This is one of the Task Management functoins called by libsas, + * to reset the given lun. Note the assumption that while this call is + * executing, no I/O will be sent by the host to the device. + * @lun: This parameter specifies the lun to be reset. + * + * status, zero indicates success. + */ +int isci_task_lu_reset( + struct domain_device *domain_device, + u8 *lun) +{ + struct isci_host *isci_host = NULL; + struct isci_remote_device *isci_device = NULL; + int ret; + bool device_stopping = false; + + if (domain_device == NULL) { + pr_warn("%s: domain_device == NULL\n", __func__); + return TMF_RESP_FUNC_FAILED; + } + + isci_device = isci_dev_from_domain_dev(domain_device); + + if (domain_device->port != NULL) + isci_host = isci_host_from_sas_ha(domain_device->port->ha); + + pr_debug("%s: domain_device=%p, isci_host=%p; isci_device=%p\n", + __func__, domain_device, isci_host, isci_device); + + if (isci_device != NULL) + device_stopping = (isci_device->status == isci_stopping) + || (isci_device->status == isci_stopped); + + /* If there is a device reset pending on any request in the + * device's list, fail this LUN reset request in order to + * escalate to the device reset. + */ + if ((isci_device == NULL) || + (isci_host == NULL) || + ((isci_host != NULL) && + (isci_device != NULL) && + (device_stopping || + (isci_device_is_reset_pending(isci_host, isci_device))))) { + dev_warn(&isci_host->pdev->dev, + "%s: No dev (%p), no host (%p), or " + "RESET PENDING: domain_device=%p\n", + __func__, isci_device, isci_host, domain_device); + return TMF_RESP_FUNC_FAILED; + } + + /* Stop I/O to the remote device. */ + isci_device_set_host_quiesce_lock_state(isci_device, true); + + /* Send the task management part of the reset. */ + if (sas_protocol_ata(domain_device->tproto)) { + ret = isci_task_send_lu_reset_sata( + isci_host, isci_device, lun + ); + } else + ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun); + + /* If the LUN reset worked, all the I/O can now be terminated. */ + if (ret == TMF_RESP_FUNC_COMPLETE) + /* Terminate all I/O now. */ + isci_terminate_pending_requests(isci_host, + isci_device, + terminating); + + /* Resume I/O to the remote device. */ + isci_device_set_host_quiesce_lock_state(isci_device, false); + + return ret; +} + + +/* int (*lldd_clear_nexus_port)(struct asd_sas_port *); */ +int isci_task_clear_nexus_port(struct asd_sas_port *port) +{ + return TMF_RESP_FUNC_FAILED; +} + + + +int isci_task_clear_nexus_ha(struct sas_ha_struct *ha) +{ + return TMF_RESP_FUNC_FAILED; +} + +int isci_task_I_T_nexus_reset(struct domain_device *dev) +{ + return TMF_RESP_FUNC_FAILED; +} + + +/* Task Management Functions. Must be called from process context. */ + +/** + * isci_abort_task_process_cb() - This is a helper function for the abort task + * TMF command. It manages the request state with respect to the successful + * transmission / completion of the abort task request. + * @cb_state: This parameter specifies when this function was called - after + * the TMF request has been started and after it has timed-out. + * @tmf: This parameter specifies the TMF in progress. + * + * + */ +static void isci_abort_task_process_cb( + enum isci_tmf_cb_state cb_state, + struct isci_tmf *tmf, + void *cb_data) +{ + struct isci_request *old_request; + + old_request = (struct isci_request *)cb_data; + + dev_dbg(&old_request->isci_host->pdev->dev, + "%s: tmf=%p, old_request=%p\n", + __func__, tmf, old_request); + + switch (cb_state) { + + case isci_tmf_started: + /* The TMF has been started. Nothing to do here, since the + * request state was already set to "aborted" by the abort + * task function. + */ + BUG_ON(old_request->status != aborted); + break; + + case isci_tmf_timed_out: + + /* Set the task's state to "aborting", since the abort task + * function thread set it to "aborted" (above) in anticipation + * of the task management request working correctly. Since the + * timeout has now fired, the TMF request failed. We set the + * state such that the request completion will indicate the + * device is no longer present. + */ + isci_request_change_state(old_request, aborting); + break; + + default: + dev_err(&old_request->isci_host->pdev->dev, + "%s: Bad cb_state (%d): tmf=%p, old_request=%p\n", + __func__, cb_state, tmf, old_request); + break; + } +} + +/** + * isci_task_abort_task() - This function is one of the SAS Domain Template + * functions. This function is called by libsas to abort a specified task. + * @task: This parameter specifies the SAS task to abort. + * + * status, zero indicates success. + */ +int isci_task_abort_task(struct sas_task *task) +{ + DECLARE_COMPLETION_ONSTACK(aborted_io_completion); + struct isci_request *old_request = NULL; + struct isci_remote_device *isci_device = NULL; + struct isci_host *isci_host = NULL; + struct isci_tmf tmf; + int ret = TMF_RESP_FUNC_FAILED; + unsigned long flags; + bool any_dev_reset, device_stopping; + + /* Get the isci_request reference from the task. Note that + * this check does not depend on the pending request list + * in the device, because tasks driving resets may land here + * after completion in the core. + */ + old_request = isci_task_get_request_from_task(task, &isci_host, + &isci_device); + + dev_dbg(&isci_host->pdev->dev, + "%s: task = %p\n", __func__, task); + + /* Check if the device has been / is currently being removed. + * If so, no task management will be done, and the I/O will + * be terminated. + */ + device_stopping = (isci_device->status == isci_stopping) + || (isci_device->status == isci_stopped); + +#ifdef NOMORE + /* This abort task function is the first stop of the libsas error + * handler thread. Since libsas is executing in a thread with a + * referernce to the "task" parameter, that task cannot be completed + * directly back to the upper layers. In order to make sure that + * the task is managed correctly if this abort task fails, set the + * "SAS_TASK_STATE_ABORTED" bit now such that completions up the + * stack will be intercepted and only allowed to happen in the + * libsas SCSI error handler thread. + */ + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags |= SAS_TASK_STATE_ABORTED; + spin_unlock_irqrestore(&task->task_state_lock, flags); +#endif /* NOMORE */ + + /* This version of the driver will fail abort requests for + * SATA/STP. Failing the abort request this way will cause the + * SCSI error handler thread to escalate to LUN reset + */ + if (sas_protocol_ata(task->task_proto) && !device_stopping) { + dev_warn(&isci_host->pdev->dev, + " task %p is for a STP/SATA device;" + " returning TMF_RESP_FUNC_FAILED\n" + " to cause a LUN reset...\n", task); + return TMF_RESP_FUNC_FAILED; + } + + dev_dbg(&isci_host->pdev->dev, + "%s: old_request == %p\n", __func__, old_request); + + spin_lock_irqsave(&task->task_state_lock, flags); + + /* Don't do resets to stopping devices. */ + if (device_stopping) + task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; + + /* See if there is a pending device reset for this device. */ + any_dev_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; + + spin_unlock_irqrestore(&task->task_state_lock, flags); + + if ((isci_device != NULL) && !device_stopping) + any_dev_reset = any_dev_reset + || isci_device_is_reset_pending(isci_host, + isci_device + ); + + /* If the extraction of the request reference from the task + * failed, then the request has been completed (or if there is a + * pending reset then this abort request function must be failed + * in order to escalate to the target reset). + */ + if ((old_request == NULL) || + ((old_request != NULL) && + (old_request->sci_request_handle == NULL) && + (old_request->complete_in_target)) || + any_dev_reset) { + + spin_lock_irqsave(&task->task_state_lock, flags); + + /* If the device reset task flag is set, fail the task + * management request. Otherwise, the original request + * has completed. + */ + if (any_dev_reset) { + + /* Turn off the task's DONE to make sure this + * task is escalated to a target reset. + */ + task->task_state_flags &= ~SAS_TASK_STATE_DONE; + + /* Fail the task management request in order to + * escalate to the target reset. + */ + ret = TMF_RESP_FUNC_FAILED; + + dev_dbg(&isci_host->pdev->dev, + "%s: Failing task abort in order to " + "escalate to target reset because\n" + "SAS_TASK_NEED_DEV_RESET is set for " + "task %p on dev %p\n", + __func__, task, isci_device); + + } else { + ret = TMF_RESP_FUNC_COMPLETE; + + dev_dbg(&isci_host->pdev->dev, + "%s: abort task not needed for %p\n", + __func__, task); + + /* The request has already completed and there + * is nothing to do here other than to set the task + * done bit, and indicate that the task abort function + * was sucessful. + */ + isci_set_task_doneflags(task); + + /* Set the abort bit to make sure that libsas sticks the + * task in the completed task queue. + */ +/* task->task_state_flags |= SAS_TASK_STATE_ABORTED; */ + + /* Check for the situation where the request was + * left around on the device list but the + * request already completed. + */ + if (old_request && !old_request->sci_request_handle) { + + isci_request_cleanup_completed_loiterer( + isci_host, isci_device, old_request + ); + } + } + spin_unlock_irqrestore(&task->task_state_lock, flags); + + return ret; + } + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + /* Sanity check the request status, and set the I/O kernel completion + * struct that will be triggered when the request completes. + */ + if (isci_task_validate_request_to_abort( + old_request, + isci_host, + isci_device, + &aborted_io_completion) + == unallocated) { + dev_dbg(&isci_host->pdev->dev, + "%s: old_request not valid for device = %p\n", + __func__, + isci_device); + old_request = NULL; + } + + if (!old_request) { + + /* There is no isci_request attached to the sas_task. + * It must have been completed and detached. + */ + dev_dbg(&isci_host->pdev->dev, + "%s: old_request == NULL\n", + __func__); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + /* Set the state on the task. */ + isci_task_all_done(task); + + return TMF_RESP_FUNC_COMPLETE; + } + if (task->task_proto == SAS_PROTOCOL_SMP || device_stopping) { + + if (device_stopping) + dev_dbg(&isci_host->pdev->dev, + "%s: device is stopping, thus no TMF\n", + __func__); + else + dev_dbg(&isci_host->pdev->dev, + "%s: request is SMP, thus no TMF\n", + __func__); + + old_request->complete_in_target = true; + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + /* Set the state on the task. */ + isci_task_all_done(task); + + ret = TMF_RESP_FUNC_COMPLETE; + + /* Stopping and SMP devices are not sent a TMF, and are not + * reset, but the outstanding I/O request is terminated here. + * + * Clean up the request on our side, and wait for the aborted + * I/O to complete. + */ + isci_terminate_request_core(isci_host, isci_device, old_request, + &aborted_io_completion); + } else { + /* Fill in the tmf stucture */ + isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_task_abort, + isci_abort_task_process_cb, old_request); + + tmf.io_tag = scic_io_request_get_io_tag( + old_request->sci_request_handle + ); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */ + ret = isci_task_execute_tmf(isci_host, &tmf, + ISCI_ABORT_TASK_TIMEOUT_MS); + + if (ret == TMF_RESP_FUNC_COMPLETE) { + old_request->complete_in_target = true; + + /* Clean up the request on our side, and wait for the aborted I/O to + * complete. + */ + isci_terminate_request_core(isci_host, isci_device, old_request, + &aborted_io_completion); + + /* Set the state on the task. */ + isci_task_all_done(task); + } else + dev_err(&isci_host->pdev->dev, + "%s: isci_task_send_tmf failed\n", + __func__); + } + + return ret; +} + +/** + * isci_task_abort_task_set() - This function is one of the SAS Domain Template + * functions. This is one of the Task Management functoins called by libsas, + * to abort all task for the given lun. + * @d_device: This parameter specifies the domain device associated with this + * request. + * @lun: This parameter specifies the lun associated with this request. + * + * status, zero indicates success. + */ +int isci_task_abort_task_set( + struct domain_device *d_device, + u8 *lun) +{ + return TMF_RESP_FUNC_FAILED; +} + + +/** + * isci_task_clear_aca() - This function is one of the SAS Domain Template + * functions. This is one of the Task Management functoins called by libsas. + * @d_device: This parameter specifies the domain device associated with this + * request. + * @lun: This parameter specifies the lun associated with this request. + * + * status, zero indicates success. + */ +int isci_task_clear_aca( + struct domain_device *d_device, + u8 *lun) +{ + return TMF_RESP_FUNC_FAILED; +} + + + +/** + * isci_task_clear_task_set() - This function is one of the SAS Domain Template + * functions. This is one of the Task Management functoins called by libsas. + * @d_device: This parameter specifies the domain device associated with this + * request. + * @lun: This parameter specifies the lun associated with this request. + * + * status, zero indicates success. + */ +int isci_task_clear_task_set( + struct domain_device *d_device, + u8 *lun) +{ + return TMF_RESP_FUNC_FAILED; +} + + +/** + * isci_task_query_task() - This function is implemented to cause libsas to + * correctly escalate the failed abort to a LUN or target reset (this is + * because sas_scsi_find_task libsas function does not correctly interpret + * all return codes from the abort task call). When TMF_RESP_FUNC_SUCC is + * returned, libsas turns this into a LUN reset; when FUNC_FAILED is + * returned, libsas will turn this into a target reset + * @task: This parameter specifies the sas task being queried. + * @lun: This parameter specifies the lun associated with this request. + * + * status, zero indicates success. + */ +int isci_task_query_task( + struct sas_task *task) +{ + /* See if there is a pending device reset for this device. */ + if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) + return TMF_RESP_FUNC_FAILED; + else + return TMF_RESP_FUNC_SUCC; +} + +/** + * isci_task_request_complete() - This function is called by the sci core when + * an task request completes. + * @isci_host: This parameter specifies the ISCI host object + * @request: This parameter is the completed isci_request object. + * @completion_status: This parameter specifies the completion status from the + * sci core. + * + * none. + */ +void isci_task_request_complete( + struct isci_host *isci_host, + struct isci_request *request, + enum sci_task_status completion_status) +{ + struct isci_remote_device *isci_device = request->isci_device; + enum isci_request_status old_state; + struct isci_tmf *tmf = isci_request_access_tmf(request); + struct completion *tmf_complete; + + dev_dbg(&isci_host->pdev->dev, + "%s: request = %p, status=%d\n", + __func__, request, completion_status); + + old_state = isci_request_change_state(request, completed); + + tmf->status = completion_status; + request->complete_in_target = true; + + if (SAS_PROTOCOL_SSP == tmf->proto) { + + memcpy(&tmf->resp.resp_iu, + scic_io_request_get_response_iu_address( + request->sci_request_handle + ), + sizeof(struct sci_ssp_response_iu)); + + } else if (SAS_PROTOCOL_SATA == tmf->proto) { + + memcpy(&tmf->resp.d2h_fis, + scic_stp_io_request_get_d2h_reg_address( + request->sci_request_handle + ), + sizeof(struct sata_fis_reg_d2h) + ); + } + + /* Manage the timer if it is still running. */ + if (tmf->timeout_timer) { + + isci_timer_stop(tmf->timeout_timer); + isci_timer_free(&isci_host->timer_list_struct, + tmf->timeout_timer); + tmf->timeout_timer = NULL; + } + + /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ + tmf_complete = tmf->complete; + + scic_controller_complete_task( + isci_host->core_controller, + isci_device->sci_device_handle, + request->sci_request_handle + ); + /* NULL the request handle to make sure it cannot be terminated + * or completed again. + */ + request->sci_request_handle = NULL; + + isci_request_change_state(request, unallocated); + list_del_init(&request->dev_node); + + /* The task management part completes last. */ + complete(tmf_complete); +} + + +/** + * isci_task_ssp_request_get_lun() - This function is called by the sci core to + * retrieve the lun for a given task request. + * @request: This parameter is the isci_request object. + * + * lun for specified task request. + */ +u32 isci_task_ssp_request_get_lun(struct isci_request *request) +{ + struct isci_tmf *isci_tmf = isci_request_access_tmf(request); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: lun = %d\n", __func__, isci_tmf->lun[0]); +/* @todo: build lun from array of bytes to 32 bit */ + return isci_tmf->lun[0]; +} + +/** + * isci_task_ssp_request_get_function() - This function is called by the sci + * core to retrieve the function for a given task request. + * @request: This parameter is the isci_request object. + * + * function code for specified task request. + */ +u8 isci_task_ssp_request_get_function(struct isci_request *request) +{ + struct isci_tmf *isci_tmf = isci_request_access_tmf(request); + + dev_dbg(&request->isci_host->pdev->dev, + "%s: func = %d\n", __func__, isci_tmf->tmf_code); + + return isci_tmf->tmf_code; +} + +/** + * isci_task_ssp_request_get_io_tag_to_manage() - This function is called by + * the sci core to retrieve the io tag for a given task request. + * @request: This parameter is the isci_request object. + * + * io tag for specified task request. + */ +u16 isci_task_ssp_request_get_io_tag_to_manage(struct isci_request *request) +{ + u16 io_tag = SCI_CONTROLLER_INVALID_IO_TAG; + + if (tmf_task == request->ttype) { + struct isci_tmf *tmf = isci_request_access_tmf(request); + io_tag = tmf->io_tag; + } + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p, io_tag = %d\n", + __func__, request, io_tag); + + return io_tag; +} + +/** + * isci_task_ssp_request_get_response_data_address() - This function is called + * by the sci core to retrieve the response data address for a given task + * request. + * @request: This parameter is the isci_request object. + * + * response data address for specified task request. + */ +void *isci_task_ssp_request_get_response_data_address( + struct isci_request *request) +{ + struct isci_tmf *isci_tmf = isci_request_access_tmf(request); + + return &isci_tmf->resp.resp_iu; +} + +/** + * isci_task_ssp_request_get_response_data_length() - This function is called + * by the sci core to retrieve the response data length for a given task + * request. + * @request: This parameter is the isci_request object. + * + * response data length for specified task request. + */ +u32 isci_task_ssp_request_get_response_data_length( + struct isci_request *request) +{ + struct isci_tmf *isci_tmf = isci_request_access_tmf(request); + + return sizeof(isci_tmf->resp.resp_iu); +} + +/** + * isci_bus_reset_handler() - This function performs a target reset of the + * device referenced by "cmd'. This function is exported through the + * "struct scsi_host_template" structure such that it is called when an I/O + * recovery process has escalated to a target reset. Note that this function + * is called from the scsi error handler event thread, so may block on calls. + * @scsi_cmd: This parameter specifies the target to be reset. + * + * SUCCESS if the reset process was successful, else FAILED. + */ +int isci_bus_reset_handler(struct scsi_cmnd *cmd) +{ + unsigned long flags = 0; + struct isci_host *isci_host = NULL; + enum sci_status status; + int base_status; + struct isci_remote_device *isci_dev + = isci_dev_from_domain_dev( + sdev_to_domain_dev(cmd->device)); + + dev_dbg(&cmd->device->sdev_gendev, + "%s: cmd %p, isci_dev %p\n", + __func__, cmd, isci_dev); + + if (!isci_dev) { + dev_warn(&cmd->device->sdev_gendev, + "%s: isci_dev is GONE!\n", + __func__); + + return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */ + } + + if (isci_dev->isci_port != NULL) + isci_host = isci_dev->isci_port->isci_host; + + if (isci_host != NULL) + spin_lock_irqsave(&isci_host->scic_lock, flags); + + status = scic_remote_device_reset(isci_dev->sci_device_handle); + if (status != SCI_SUCCESS) { + + if (isci_host != NULL) + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + scmd_printk(KERN_WARNING, cmd, + "%s: scic_remote_device_reset(%p) returned %d!\n", + __func__, isci_dev, status); + + return TMF_RESP_FUNC_FAILED; + } + if (isci_host != NULL) + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + /* Stop I/O to the remote device. */ + isci_device_set_host_quiesce_lock_state(isci_dev, true); + + /* Make sure all pending requests are able to be fully terminated. */ + isci_device_clear_reset_pending(isci_dev); + + /* Terminate in-progress I/O now. */ + isci_remote_device_nuke_requests(isci_dev); + + /* Call into the libsas default handler (which calls sas_phy_reset). */ + base_status = sas_eh_bus_reset_handler(cmd); + + if (base_status != SUCCESS) { + + /* There can be cases where the resets to individual devices + * behind an expander will fail because of an unplug of the + * expander itself. + */ + scmd_printk(KERN_WARNING, cmd, + "%s: sas_eh_bus_reset_handler(%p) returned %d!\n", + __func__, cmd, base_status); + } + + /* WHAT TO DO HERE IF sas_phy_reset FAILS? */ + + if (isci_host != NULL) + spin_lock_irqsave(&isci_host->scic_lock, flags); + status + = scic_remote_device_reset_complete(isci_dev->sci_device_handle); + + if (isci_host != NULL) + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + if (status != SCI_SUCCESS) { + scmd_printk(KERN_WARNING, cmd, + "%s: scic_remote_device_reset_complete(%p) " + "returned %d!\n", + __func__, isci_dev, status); + } + /* WHAT TO DO HERE IF scic_remote_device_reset_complete FAILS? */ + + dev_dbg(&cmd->device->sdev_gendev, + "%s: cmd %p, isci_dev %p complete.\n", + __func__, cmd, isci_dev); + + /* Resume I/O to the remote device. */ + isci_device_set_host_quiesce_lock_state(isci_dev, false); + + return TMF_RESP_FUNC_COMPLETE; +} diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h new file mode 100644 index 000000000000..ced6a8be1b31 --- /dev/null +++ b/drivers/scsi/isci/task.h @@ -0,0 +1,368 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(_ISCI_TASK_H_) +#define _ISCI_TASK_H_ + +struct isci_request; +struct isci_host; + +/** + * enum isci_tmf_cb_state - This enum defines the possible states in which the + * TMF callback function is invoked during the TMF execution process. + * + * + */ +enum isci_tmf_cb_state { + + isci_tmf_init_state = 0, + isci_tmf_started, + isci_tmf_timed_out +}; + +/** + * enum isci_tmf_function_codes - This enum defines the possible preparations + * of task management requests. + * + * + */ +enum isci_tmf_function_codes { + + isci_tmf_func_none = 0, + isci_tmf_ssp_task_abort = TMF_ABORT_TASK, + isci_tmf_ssp_lun_reset = TMF_LU_RESET, + isci_tmf_sata_srst_high = TMF_LU_RESET + 0x100, /* Non SCSI */ + isci_tmf_sata_srst_low = TMF_LU_RESET + 0x101 /* Non SCSI */ +}; +/** + * struct isci_tmf - This class represents the task management object which + * acts as an interface to libsas for processing task management requests + * + * + */ +struct isci_tmf { + + struct completion *complete; + enum sas_protocol proto; + union { + struct sci_ssp_response_iu resp_iu; + struct dev_to_host_fis d2h_fis; + } resp; + unsigned char lun[8]; + u16 io_tag; + struct isci_remote_device *device; + enum isci_tmf_function_codes tmf_code; + int status; + + struct isci_timer *timeout_timer; + + /* The optional callback function allows the user process to + * track the TMF transmit / timeout conditions. + */ + void (*cb_state_func)( + enum isci_tmf_cb_state, + struct isci_tmf *, void *); + void *cb_data; + +}; + +static inline void isci_print_tmf( + struct isci_tmf *tmf) +{ + if (SAS_PROTOCOL_SATA == tmf->proto) + dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev, + "%s: status = %x\n" + "tmf->resp.d2h_fis.status = %x\n" + "tmf->resp.d2h_fis.error = %x\n", + __func__, + tmf->status, + tmf->resp.d2h_fis.status, + tmf->resp.d2h_fis.error); + else + dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev, + "%s: status = %x\n" + "tmf->resp.resp_iu.data_present = %x\n" + "tmf->resp.resp_iu.status = %x\n" + "tmf->resp.resp_iu.data_length = %x\n" + "tmf->resp.resp_iu.data[0] = %x\n" + "tmf->resp.resp_iu.data[1] = %x\n" + "tmf->resp.resp_iu.data[2] = %x\n" + "tmf->resp.resp_iu.data[3] = %x\n", + __func__, + tmf->status, + tmf->resp.resp_iu.data_present, + tmf->resp.resp_iu.status, + (tmf->resp.resp_iu.response_data_length[0] << 24) + + (tmf->resp.resp_iu.response_data_length[1] << 16) + + (tmf->resp.resp_iu.response_data_length[2] << 8) + + tmf->resp.resp_iu.response_data_length[3], + tmf->resp.resp_iu.data[0], + tmf->resp.resp_iu.data[1], + tmf->resp.resp_iu.data[2], + tmf->resp.resp_iu.data[3]); +} + + +int isci_task_execute_task( + struct sas_task *task, + int num, + gfp_t gfp_flags); + +int isci_task_abort_task( + struct sas_task *task); + +int isci_task_abort_task_set( + struct domain_device *d_device, + u8 *lun); + +int isci_task_clear_aca( + struct domain_device *d_device, + u8 *lun); + +int isci_task_clear_task_set( + struct domain_device *d_device, + u8 *lun); + +int isci_task_query_task( + struct sas_task *task); + +int isci_task_lu_reset( + struct domain_device *d_device, + u8 *lun); + +int isci_task_clear_nexus_port( + struct asd_sas_port *port); + +int isci_task_clear_nexus_ha( + struct sas_ha_struct *ha); + +int isci_task_I_T_nexus_reset( + struct domain_device *d_device); + +void isci_task_request_complete( + struct isci_host *isci_host, + struct isci_request *request, + enum sci_task_status completion_status); + +u16 isci_task_ssp_request_get_io_tag_to_manage( + struct isci_request *request); + +u8 isci_task_ssp_request_get_function( + struct isci_request *request); + +u32 isci_task_ssp_request_get_lun( + struct isci_request *request); + +void *isci_task_ssp_request_get_response_data_address( + struct isci_request *request); + +u32 isci_task_ssp_request_get_response_data_length( + struct isci_request *request); + +int isci_queuecommand( + struct scsi_cmnd *scsi_cmd, + void (*donefunc)(struct scsi_cmnd *)); + +int isci_bus_reset_handler(struct scsi_cmnd *cmd); + +void isci_task_build_tmf( + struct isci_tmf *tmf, + struct isci_remote_device *isci_device, + enum isci_tmf_function_codes code, + void (*tmf_sent_cb)( + enum isci_tmf_cb_state, + struct isci_tmf *, void *), + void *cb_data); + +int isci_task_execute_tmf( + struct isci_host *isci_host, + struct isci_tmf *tmf, + unsigned long timeout_ms); + +/** + * enum isci_completion_selection - This enum defines the possible actions to + * take with respect to a given request's notification back to libsas. + * + * + */ +enum isci_completion_selection { + + isci_perform_normal_io_completion, /* Normal notify (task_done) */ + isci_perform_aborted_io_completion, /* No notification. */ + isci_perform_error_io_completion /* Use sas_task_abort */ +}; + +static inline void isci_set_task_doneflags( + struct sas_task *task) +{ + /* Since no futher action will be taken on this task, + * make sure to mark it complete from the lldd perspective. + */ + task->task_state_flags |= SAS_TASK_STATE_DONE; + task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; +} +/** + * isci_task_all_done() - This function clears the task bits to indicate the + * LLDD is done with the task. + * + * + */ +static inline void isci_task_all_done( + struct sas_task *task) +{ + unsigned long flags; + + /* Since no futher action will be taken on this task, + * make sure to mark it complete from the lldd perspective. + */ + spin_lock_irqsave(&task->task_state_lock, flags); + isci_set_task_doneflags(task); + spin_unlock_irqrestore(&task->task_state_lock, flags); +} + +/** + * isci_task_set_completion_status() - This function sets the completion status + * for the request. + * @task: This parameter is the completed request. + * @response: This parameter is the response code for the completed task. + * @status: This parameter is the status code for the completed task. + * + * none. + */ +static inline void isci_task_set_completion_status( + struct sas_task *task, + enum service_response response, + enum exec_status status, + enum isci_completion_selection task_notification_selection) +{ + unsigned long flags; + + spin_lock_irqsave(&task->task_state_lock, flags); + + task->task_status.resp = response; + task->task_status.stat = status; + + /* Don't set DONE (or clear AT_INITIATOR) for any task going into the + * error path, because the EH interprets that as a handled error condition. + * Also don't take action if there is a reset pending. + */ + if ((task_notification_selection != isci_perform_error_io_completion) + && !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET)) + isci_set_task_doneflags(task); + + spin_unlock_irqrestore(&task->task_state_lock, flags); +} +/** + * isci_task_complete_for_upper_layer() - This function completes the request + * to the upper layer driver. + * @host: This parameter is a pointer to the host on which the the request + * should be queued (either as an error or success). + * @request: This parameter is the completed request. + * @response: This parameter is the response code for the completed task. + * @status: This parameter is the status code for the completed task. + * + * none. + */ +static inline void isci_task_complete_for_upper_layer( + struct sas_task *task, + enum service_response response, + enum exec_status status, + enum isci_completion_selection task_notification_selection) +{ + isci_task_set_completion_status(task, response, status, + task_notification_selection); + + + /* Tasks aborted specifically by a call to the lldd_abort_task + * function should not be completed to the host in the regular path. + */ + switch (task_notification_selection) { + case isci_perform_normal_io_completion: + /* Normal notification (task_done) */ + dev_dbg(task->dev->port->ha->dev, + "%s: Normal - task = %p, response=%d, status=%d\n", + __func__, task, response, status); + task->task_done(task); + task->lldd_task = NULL; + break; + + case isci_perform_aborted_io_completion: + /* No notification because this request is already in the + * abort path. + */ + dev_warn(task->dev->port->ha->dev, + "%s: Aborted - task = %p, response=%d, status=%d\n", + __func__, task, response, status); + break; + + case isci_perform_error_io_completion: + /* Use sas_task_abort */ + dev_warn(task->dev->port->ha->dev, + "%s: Error - task = %p, response=%d, status=%d\n", + __func__, task, response, status); + sas_task_abort(task); + break; + + default: + dev_warn(task->dev->port->ha->dev, + "%s: isci task notification default case!", + __func__); + sas_task_abort(task); + break; + } +} + +#endif /* !defined(_SCI_TASK_H_) */ diff --git a/drivers/scsi/isci/timers.c b/drivers/scsi/isci/timers.c new file mode 100644 index 000000000000..ca723089ee88 --- /dev/null +++ b/drivers/scsi/isci/timers.c @@ -0,0 +1,319 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "isci.h" +#include "timers.h" + + +/** + * isci_timer_list_construct() - This method contrucst the SCI Timer List + * object used by the SCI Module class. The construction process involves + * creating isci_timer objects and adding them to the SCI Timer List + * object's list member. The number of isci_timer objects is determined by + * the timer_list_size parameter. + * @isci_timer_list: This parameter points to the SCI Timer List object being + * constructed. The calling routine is responsible for allocating the memory + * for isci_timer_list and initializing the timer list_head member of + * isci_timer_list. + * @timer_list_size: This parameter specifies the number of isci_timer objects + * contained by the SCI Timer List. which this timer is to be associated. + * + * This method returns an error code indicating sucess or failure. The user + * should check for possible memory allocation error return otherwise, a zero + * indicates success. + */ +int isci_timer_list_construct( + struct isci_timer_list *isci_timer_list, + int timer_list_size) +{ + struct isci_timer *isci_timer; + int i; + int err = 0; + + + for (i = 0; i < timer_list_size; i++) { + + isci_timer = kzalloc(sizeof(*isci_timer), GFP_KERNEL); + + if (!isci_timer) { + + err = -ENOMEM; + break; + } + isci_timer->used = 0; + isci_timer->stopped = 1; + isci_timer->parent = isci_timer_list; + list_add(&isci_timer->node, &isci_timer_list->timers); + } + + return 0; + +} + + +/** + * isci_timer_list_destroy() - This method destroys the SCI Timer List object + * used by the SCI Module class. The destruction process involves freeing + * memory allocated for isci_timer objects on the SCI Timer List object's + * timers list_head member. If any isci_timer objects are mark as "in use", + * they are not freed and the function returns an error code of -EBUSY. + * @isci_timer_list: This parameter points to the SCI Timer List object being + * destroyed. + * + * This method returns an error code indicating sucess or failure. The user + * should check for possible -EBUSY error return, in the event of one or more + * isci_timers still "in use", otherwise, a zero indicates success. + */ +int isci_timer_list_destroy( + struct isci_timer_list *isci_timer_list) +{ + struct isci_timer *timer, *tmp; + + list_for_each_entry_safe(timer, tmp, &isci_timer_list->timers, node) { + isci_timer_free(isci_timer_list, timer); + list_del(&timer->node); + kfree(timer); + } + return 0; +} + + + +static void isci_timer_restart(struct isci_timer *isci_timer) +{ + struct timer_list *timer = + &isci_timer->timer; + unsigned long timeout; + + dev_dbg(&isci_timer->isci_host->pdev->dev, + "%s: isci_timer = %p\n", __func__, isci_timer); + + isci_timer->restart = 0; + isci_timer->stopped = 0; + timeout = isci_timer->timeout_value; + timeout = (timeout * HZ) / 1000; + timeout = timeout ? timeout : 1; + mod_timer(timer, jiffies + timeout); +} + +/** + * This method pulls an isci_timer object off of the list for the SCI Timer + * List object specified, marks the isci_timer as "in use" and initializes + * it with user callback function and cookie data. The timer is not start at + * this time, just reserved for the user. + * @isci_timer_list: This parameter points to the SCI Timer List from which the + * timer is reserved. + * @cookie: This parameter specifies a piece of information that the user must + * retain. This cookie is to be supplied by the user anytime a timeout + * occurs for the created timer. + * @timer_callback: This parameter specifies the callback method to be invoked + * whenever the timer expires. + * + * This method returns a pointer to an isci_timer object reserved from the SCI + * Timer List. The pointer will be utilized for all further interactions + * relating to this timer. + */ + +static void timer_function(unsigned long data) +{ + + struct isci_timer *timer = (struct isci_timer *)data; + struct isci_host *isci_host = timer->isci_host; + unsigned long flags; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_timer = %p\n", __func__, timer); + + if (isci_stopped == isci_host_get_state(isci_host)) { + timer->stopped = 1; + return; + } + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + if (!timer->stopped) { + timer->stopped = 1; + timer->timer_callback(timer->cookie); + + if (timer->restart) + isci_timer_restart(timer); + } + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); +} + + +struct isci_timer *isci_timer_create( + struct isci_timer_list *isci_timer_list, + struct isci_host *isci_host, + void *cookie, + void (*timer_callback)(void *)) +{ + + struct timer_list *timer; + struct isci_timer *isci_timer; + struct list_head *timer_list = + &isci_timer_list->timers; + unsigned long flags; + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + if (list_empty(timer_list)) { + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + return NULL; + } + + isci_timer = list_entry(timer_list->next, struct isci_timer, node); + + if (isci_timer->used) { + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + return NULL; + } + isci_timer->used = 1; + isci_timer->stopped = 1; + list_move_tail(&isci_timer->node, timer_list); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + timer = &isci_timer->timer; + timer->data = (unsigned long)isci_timer; + timer->function = timer_function; + isci_timer->cookie = cookie; + isci_timer->timer_callback = timer_callback; + isci_timer->isci_host = isci_host; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_timer = %p\n", __func__, isci_timer); + + return isci_timer; +} + +/** + * isci_timer_free() - This method frees the isci_timer, marking it "free to + * use", then places its back at the head of the timers list for the SCI + * Timer List object specified. + * @isci_timer_list: This parameter points to the SCI Timer List from which the + * timer is reserved. + * @isci_timer: This parameter specifies the timer to be freed. + * + */ +void isci_timer_free( + struct isci_timer_list *isci_timer_list, + struct isci_timer *isci_timer) +{ + struct list_head *timer_list = &isci_timer_list->timers; + + dev_dbg(&isci_timer->isci_host->pdev->dev, + "%s: isci_timer = %p\n", __func__, isci_timer); + + if (list_empty(timer_list)) + return; + + isci_timer->used = 0; + list_move(&isci_timer->node, timer_list); + + if (!isci_timer->stopped) { + del_timer(&isci_timer->timer); + isci_timer->stopped = 1; + } +} + +/** + * isci_timer_start() - This method starts the specified isci_timer, with the + * specified timeout value. + * @isci_timer: This parameter specifies the timer to be started. + * @timeout: This parameter specifies the timeout, in milliseconds, after which + * the associated callback function will be called. + * + */ +void isci_timer_start( + struct isci_timer *isci_timer, + unsigned long timeout) +{ + struct timer_list *timer = &isci_timer->timer; + + dev_dbg(&isci_timer->isci_host->pdev->dev, + "%s: isci_timer = %p\n", __func__, isci_timer); + + isci_timer->timeout_value = timeout; + init_timer(timer); + timeout = (timeout * HZ) / 1000; + timeout = timeout ? timeout : 1; + + timer->expires = jiffies + timeout; + timer->data = (unsigned long)isci_timer; + timer->function = timer_function; + isci_timer->stopped = 0; + isci_timer->restart = 0; + add_timer(timer); +} + +/** + * isci_timer_stop() - This method stops the supplied isci_timer. + * @isci_timer: This parameter specifies the isci_timer to be stopped. + * + */ +void isci_timer_stop(struct isci_timer *isci_timer) +{ + dev_dbg(&isci_timer->isci_host->pdev->dev, + "%s: isci_timer = %p\n", __func__, isci_timer); + + if (isci_timer->stopped) + return; + + isci_timer->stopped = 1; + + del_timer(&isci_timer->timer); +} diff --git a/drivers/scsi/isci/timers.h b/drivers/scsi/isci/timers.h new file mode 100644 index 000000000000..ca5c2159a1c2 --- /dev/null +++ b/drivers/scsi/isci/timers.h @@ -0,0 +1,126 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(_SCI_TIMER_H_) +#define _SCI_TIMER_H_ + +#include +#include + +/*************************************************** + * isci_timer + *************************************************** + */ +/** + * struct isci_timer_list - This class is the container for all isci_timer + * objects + * + * + */ +struct isci_timer_list { + + struct list_head timers; +}; + +/** + * struct isci_timer - This class represents the timer object used by SCIC. It + * wraps the Linux timer_list object. + * + * + */ +struct isci_timer { + int used; + int stopped; + int restart; + int timeout_value; + void *cookie; + void (*timer_callback)(void *); + struct list_head node; + struct timer_list timer; + struct isci_timer_list *parent; + struct isci_host *isci_host; +}; + +#define to_isci_timer(t) \ + container_of(t, struct isci_timer, timer); + +int isci_timer_list_construct( + struct isci_timer_list *isci_timer_list, + int timer_list_size); + + +int isci_timer_list_destroy( + struct isci_timer_list *isci_timer_list); + +struct isci_timer *isci_timer_create( + struct isci_timer_list *isci_timer_list, + struct isci_host *isci_host, + void *cookie, + void (*timer_callback)(void *)); + +void isci_timer_free( + struct isci_timer_list *isci_timer_list, + struct isci_timer *isci_timer); + +void isci_timer_start( + struct isci_timer *isci_timer, + unsigned long timeout); + +void isci_timer_stop( + struct isci_timer *isci_timer); + + +#endif /* !defined (_SCI_TIMER_H_) */ + diff --git a/firmware/Makefile b/firmware/Makefile index 0d15a3d113a2..5f43bfba3c7a 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -82,6 +82,7 @@ fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis \ fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \ advansys/3550.bin advansys/38C0800.bin +fw-shipped-$(CONFIG_SCSI_ISCI) += isci/isci_firmware.bin fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \ qlogic/12160.bin fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex new file mode 100644 index 000000000000..9fc9e60f399c --- /dev/null +++ b/firmware/isci/isci_firmware.bin.ihex @@ -0,0 +1,11 @@ +:1000000023534355204D4147494323000100010834 +:1000100001000000020000000400000008000000D1 +:1000200001000000020000000400000008000000C1 +:1000300002080300000003000000030000000300AA +:1000400000000300000003000000030000000300A4 +:1000500000000308000000F0FFFFCF5F000000F188 +:10006000FFFFCF5F000000F2FFFFCF5F000000F353 +:10007000FFFFCF5F000000F4FFFFCF5F000000F53F +:10008000FFFFCF5F000000F6FFFFCF5F000000F72B +:05009000FFFFCF5FFF40 +:00000001FF -- cgit v1.2.3 From 74ea9c163a5c09638b453208cd129b686b85e91e Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Tue, 8 Feb 2011 08:09:10 -0700 Subject: isci: remove unused SC_LIBRARY_HANDLE_T typedef Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_types.h | 9 --------- drivers/scsi/isci/host.h | 1 - 2 files changed, 10 deletions(-) diff --git a/drivers/scsi/isci/core/sci_types.h b/drivers/scsi/isci/core/sci_types.h index 431735d1a589..72a56bf40811 100644 --- a/drivers/scsi/isci/core/sci_types.h +++ b/drivers/scsi/isci/core/sci_types.h @@ -63,15 +63,6 @@ #define SCI_INVALID_HANDLE 0x0 -/** - * The SCI_LIBRARY_HANDLE_T will be utilized by SCI users as an opaque handle - * for the SCI Library object. - * - * SCI_LIBRARY_HANDLE_T - */ -typedef void *SCI_LIBRARY_HANDLE_T; - - typedef enum { SCI_IO_REQUEST_DATA_IN = 0, /* Read operation */ SCI_IO_REQUEST_DATA_OUT, /* Write operation */ diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 3530076d6107..4f4b99d29589 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -143,7 +143,6 @@ struct isci_host { struct isci_pci_info { struct msix_entry msix_entries[SCI_MAX_MSIX_INT]; int core_lib_array_index; - SCI_LIBRARY_HANDLE_T core_lib_handle; struct isci_host *hosts; }; -- cgit v1.2.3 From a7e536c7d6f1796e8727f5c90d33765ae7cfd8d8 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Tue, 8 Feb 2011 09:28:42 -0700 Subject: isci: remove SCI_INVALID_HANDLE Replace SCI_INVALID_HANDLE with NULL Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- .../isci/core/sci_base_memory_descriptor_list.c | 6 +++--- .../isci/core/sci_base_memory_descriptor_list.h | 3 +-- drivers/scsi/isci/core/sci_types.h | 2 -- drivers/scsi/isci/core/scic_phy.h | 2 +- drivers/scsi/isci/core/scic_sds_controller.c | 24 +++++++++++----------- drivers/scsi/isci/core/scic_sds_phy.c | 8 ++++---- drivers/scsi/isci/core/scic_sds_port.c | 20 +++++++++--------- .../isci/core/scic_sds_port_configuration_agent.c | 24 +++++++++++----------- drivers/scsi/isci/core/scic_sds_remote_device.c | 2 +- drivers/scsi/isci/core/scic_user_callback.h | 6 +++--- drivers/scsi/isci/events.c | 7 +++---- 11 files changed, 50 insertions(+), 54 deletions(-) diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c index 86ae6a855399..2d785b518a06 100644 --- a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c +++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c @@ -76,7 +76,7 @@ void sci_mdl_first_entry( /* * If this MDL is managing another MDL, then recursively rewind that MDL * object as well. */ - if (base_mdl->next_mdl != SCI_INVALID_HANDLE) + if (base_mdl->next_mdl != NULL) sci_mdl_first_entry(base_mdl->next_mdl); } @@ -93,7 +93,7 @@ void sci_mdl_next_entry( /* * This MDL has exhausted it's set of entries. If this MDL is managing * another MDL, then start iterating through that MDL. */ - if (base_mdl->next_mdl != SCI_INVALID_HANDLE) + if (base_mdl->next_mdl != NULL) sci_mdl_next_entry(base_mdl->next_mdl); } } @@ -108,7 +108,7 @@ struct sci_physical_memory_descriptor *sci_mdl_get_current_entry( /* * This MDL has exhausted it's set of entries. If this MDL is managing * another MDL, then return it's current entry. */ - if (base_mdl->next_mdl != SCI_INVALID_HANDLE) + if (base_mdl->next_mdl != NULL) return sci_mdl_get_current_entry(base_mdl->next_mdl); } diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h index 257d6e368b4a..614e0a98c614 100644 --- a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h +++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h @@ -94,8 +94,7 @@ struct sci_base_memory_descriptor_list { /** * This field simply allows a user to chain memory descriptor lists - * together if desired. This field will be initialized to - * SCI_INVALID_HANDLE. + * together if desired. This field will be initialized to NULL. */ struct sci_base_memory_descriptor_list *next_mdl; diff --git a/drivers/scsi/isci/core/sci_types.h b/drivers/scsi/isci/core/sci_types.h index 72a56bf40811..e15dc0c89e5c 100644 --- a/drivers/scsi/isci/core/sci_types.h +++ b/drivers/scsi/isci/core/sci_types.h @@ -61,8 +61,6 @@ #define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) -#define SCI_INVALID_HANDLE 0x0 - typedef enum { SCI_IO_REQUEST_DATA_IN = 0, /* Read operation */ SCI_IO_REQUEST_DATA_OUT, /* Write operation */ diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 25a6140fa9e4..fec273b123d4 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -82,7 +82,7 @@ struct scic_sds_port; struct scic_phy_properties { /** * This field specifies the port that currently contains the - * supplied phy. This field may be set to SCI_INVALID_HANDLE + * supplied phy. This field may be set to NULL * if the phy is not currently contained in a port. */ struct scic_sds_port *owning_port; diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 35f7796df661..6a32d91742b5 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -890,7 +890,7 @@ enum sci_status scic_sds_controller_start_next_phy( for (index = 0; index < SCI_MAX_PHYS; index++) { the_phy = &this_controller->phy_table[index]; - if (scic_sds_phy_get_port(the_phy) != SCI_INVALID_HANDLE) { + if (scic_sds_phy_get_port(the_phy) != NULL) { /** * The controller start operation is complete if and only * if: @@ -940,7 +940,7 @@ enum sci_status scic_sds_controller_start_next_phy( scic_sds_controller_get_port_configuration_mode(this_controller) == SCIC_PORT_MANUAL_CONFIGURATION_MODE ) { - if (scic_sds_phy_get_port(the_phy) == SCI_INVALID_HANDLE) { + if (scic_sds_phy_get_port(the_phy) == NULL) { this_controller->next_phy_to_start++; /* @@ -1025,7 +1025,7 @@ enum sci_status scic_sds_controller_stop_devices( status = SCI_SUCCESS; for (index = 0; index < this_controller->remote_node_entries; index++) { - if (this_controller->device_table[index] != SCI_INVALID_HANDLE) { + if (this_controller->device_table[index] != NULL) { /* / @todo What timeout value do we want to provide to this request? */ device_status = scic_remote_device_stop(this_controller->device_table[index], 0); @@ -1197,7 +1197,7 @@ static void scic_sds_controller_task_completion( /* Make sure that we really want to process this IO request */ if ( - (io_request != SCI_INVALID_HANDLE) + (io_request != NULL) && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) && ( scic_sds_io_tag_get_sequence(io_request->io_tag) @@ -1395,7 +1395,7 @@ static void scic_sds_controller_event_completion( case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: io_request = this_controller->io_request_table[index]; - if (io_request != SCI_INVALID_HANDLE) + if (io_request != NULL) scic_sds_io_request_event_handler(io_request, completion_entry); else dev_warn(scic_to_dev(this_controller), @@ -1410,7 +1410,7 @@ static void scic_sds_controller_event_completion( case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: device = this_controller->device_table[index]; - if (device != SCI_INVALID_HANDLE) + if (device != NULL) scic_sds_remote_device_event_handler(device, completion_entry); else dev_warn(scic_to_dev(this_controller), @@ -2174,7 +2174,7 @@ struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( task_index = scic_sds_io_tag_get_index(io_tag); if (task_index < this_controller->task_context_entries) { - if (this_controller->io_request_table[task_index] != SCI_INVALID_HANDLE) { + if (this_controller->io_request_table[task_index] != NULL) { task_sequence = scic_sds_io_tag_get_sequence(io_tag); if (task_sequence == this_controller->io_request_sequence[task_index]) { @@ -2183,7 +2183,7 @@ struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( } } - return SCI_INVALID_HANDLE; + return NULL; } /** @@ -2240,7 +2240,7 @@ void scic_sds_controller_free_remote_node_context( u32 remote_node_count = scic_sds_remote_device_node_count(the_device); if (this_controller->device_table[node_id] == the_device) { - this_controller->device_table[node_id] = SCI_INVALID_HANDLE; + this_controller->device_table[node_id] = NULL; scic_sds_remote_node_table_release_remote_node_index( &this_controller->available_remote_nodes, remote_node_count, node_id @@ -2262,7 +2262,7 @@ union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffe ) { if ( (node_id < this_controller->remote_node_entries) - && (this_controller->device_table[node_id] != SCI_INVALID_HANDLE) + && (this_controller->device_table[node_id] != NULL) ) { return &this_controller->remote_node_context_table[node_id]; } @@ -2449,7 +2449,7 @@ u32 scic_controller_get_suggested_start_timeout( struct scic_sds_controller *sc) { /* Validate the user supplied parameters. */ - if (sc == SCI_INVALID_HANDLE) + if (sc == NULL) return 0; /* @@ -3659,7 +3659,7 @@ static enum sci_status scic_sds_controller_ready_state_complete_io_handler( if (status == SCI_SUCCESS) { index = scic_sds_io_tag_get_index(the_request->io_tag); - this_controller->io_request_table[index] = SCI_INVALID_HANDLE; + this_controller->io_request_table[index] = NULL; } return status; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 7d012b571b5b..01da46ae270a 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -414,15 +414,15 @@ void scic_sds_phy_construct( * containing port. * * This method returns a handle to a port that contains the supplied phy. - * SCI_INVALID_HANDLE This value is returned if the phy is not part of a real - * port (i.e. it's contained in the dummy port). !SCI_INVALID_HANDLE All other + * NULL This value is returned if the phy is not part of a real + * port (i.e. it's contained in the dummy port). !NULL All other * values indicate a handle/pointer to the port containing the phy. */ struct scic_sds_port *scic_sds_phy_get_port( struct scic_sds_phy *this_phy) { if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT) - return SCI_INVALID_HANDLE; + return NULL; return this_phy->owning_port; } @@ -2373,7 +2373,7 @@ static enum sci_status scic_sds_phy_ready_state_event_handler( case SCU_EVENT_BROADCAST_CHANGE: /* Broadcast change received. Notify the port. */ - if (scic_sds_phy_get_port(this_phy) != SCI_INVALID_HANDLE) + if (scic_sds_phy_get_port(this_phy) != NULL) scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); else this_phy->bcn_received_while_port_unassigned = true; diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 1af38505840c..9749e3abbf8e 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -277,8 +277,8 @@ enum sci_status scic_sds_port_set_phy( * that means that the phy is not part of a port and that the port does * not already have a phy assinged to the phy index. */ if ( - (port->phy_table[phy->phy_index] == SCI_INVALID_HANDLE) - && (scic_sds_phy_get_port(phy) == SCI_INVALID_HANDLE) + (port->phy_table[phy->phy_index] == NULL) + && (scic_sds_phy_get_port(phy) == NULL) && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index) ) { /* @@ -318,7 +318,7 @@ enum sci_status scic_sds_port_clear_phy( &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS] ); - port->phy_table[phy->phy_index] = SCI_INVALID_HANDLE; + port->phy_table[phy->phy_index] = NULL; return SCI_SUCCESS; } @@ -529,7 +529,7 @@ void scic_sds_port_construct( this_port->started_request_count = 0; this_port->assigned_device_count = 0; - this_port->timer_handle = SCI_INVALID_HANDLE; + this_port->timer_handle = NULL; this_port->transport_layer_registers = NULL; this_port->port_task_scheduler_registers = NULL; @@ -669,7 +669,7 @@ enum sci_status scic_port_get_properties( struct scic_sds_port *port, struct scic_port_properties *prop) { - if ((port == SCI_INVALID_HANDLE) || + if ((port == NULL) || (port->logical_port_index == SCIC_SDS_DUMMY_PORT)) return SCI_FAILURE_INVALID_PORT; @@ -1267,29 +1267,29 @@ static enum sci_status scic_sds_port_ready_operational_substate_reset_handler( enum sci_status status = SCI_FAILURE_INVALID_PHY; u32 phy_index; struct scic_sds_port *this_port = (struct scic_sds_port *)port; - struct scic_sds_phy *selected_phy = SCI_INVALID_HANDLE; + struct scic_sds_phy *selected_phy = NULL; /* Select a phy on which we can send the hard reset request. */ for ( phy_index = 0; (phy_index < SCI_MAX_PHYS) - && (selected_phy == SCI_INVALID_HANDLE); + && (selected_phy == NULL); phy_index++ ) { selected_phy = this_port->phy_table[phy_index]; if ( - (selected_phy != SCI_INVALID_HANDLE) + (selected_phy != NULL) && !scic_sds_port_active_phy(this_port, selected_phy) ) { /* We found a phy but it is not ready select different phy */ - selected_phy = SCI_INVALID_HANDLE; + selected_phy = NULL; } } /* If we have a phy then go ahead and start the reset procedure */ - if (selected_phy != SCI_INVALID_HANDLE) { + if (selected_phy != NULL) { status = scic_sds_phy_reset(selected_phy); if (status == SCI_SUCCESS) { diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index 37d4469162a7..dd2cdd4a6fe1 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -118,9 +118,9 @@ static s32 sci_sas_address_compare( * * This routine will find a matching port for the phy. This means that the * port and phy both have the same broadcast sas address and same received sas - * address. The port address or the SCI_INVALID_HANDLE if there is no matching + * address. The port address or the NULL if there is no matching * port. port address if the port can be found to match the phy. - * SCI_INVALID_HANDLE if there is no matching port for the phy. + * NULL if there is no matching port for the phy. */ static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( struct scic_sds_controller *controller, @@ -156,7 +156,7 @@ static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( } } - return SCI_INVALID_HANDLE; + return NULL; } /** @@ -390,7 +390,7 @@ static void scic_sds_mpc_agent_timeout_handler( * @controller: This is the controller object that receives the link up * notification. * @port: This is the port object associated with the phy. If the is no - * associated port this is an SCI_INVALID_HANDLE. + * associated port this is an NULL. * @phy: This is the phy object which has gone ready. * * This method handles the manual port configuration link up notifications. @@ -409,7 +409,7 @@ static void scic_sds_mpc_agent_link_up( * If the port has an invalid handle then the phy was not assigned to * a port. This is because the phy was not given the same SAS Address * as the other PHYs in the port. */ - if (port != SCI_INVALID_HANDLE) { + if (port != NULL) { port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); scic_sds_port_link_up(port, phy); @@ -425,7 +425,7 @@ static void scic_sds_mpc_agent_link_up( * @controller: This is the controller object that receives the link down * notification. * @port: This is the port object associated with the phy. If the is no - * associated port this is an SCI_INVALID_HANDLE. The port is an invalid + * associated port this is an NULL. The port is an invalid * handle only if the phy was never port of this port. This happens when * the phy is not broadcasting the same SAS address as the other phys in the * assigned port. @@ -443,7 +443,7 @@ static void scic_sds_mpc_agent_link_down( struct scic_sds_port *port, struct scic_sds_phy *phy) { - if (port != SCI_INVALID_HANDLE) { + if (port != NULL) { /* * If we can form a new port from the remainder of the phys then we want * to start the timer to allow the SCI User to cleanup old devices and @@ -573,7 +573,7 @@ static void scic_sds_apc_agent_configure_ports( port = scic_sds_port_configuration_agent_find_port(controller, phy); - if (port != SCI_INVALID_HANDLE) { + if (port != NULL) { if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) apc_activity = SCIC_SDS_APC_ADD_PHY; else @@ -680,7 +680,7 @@ static void scic_sds_apc_agent_configure_ports( * @controller: This is the controller object that receives the link up * notification. * @port: This is the port object associated with the phy. If the is no - * associated port this is an SCI_INVALID_HANDLE. + * associated port this is an NULL. * @phy: This is the phy object which has gone link up. * * This method handles the automatic port configuration for link up @@ -693,7 +693,7 @@ static void scic_sds_apc_agent_link_up( struct scic_sds_port *port, struct scic_sds_phy *phy) { - BUG_ON(port != SCI_INVALID_HANDLE); + BUG_ON(port != NULL); port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); @@ -705,7 +705,7 @@ static void scic_sds_apc_agent_link_up( * @controller: This is the controller object that receives the link down * notification. * @port: This is the port object associated with the phy. If the is no - * associated port this is an SCI_INVALID_HANDLE. + * associated port this is an NULL. * @phy: This is the phy object which has gone link down. * * This method handles the automatic port configuration link down @@ -721,7 +721,7 @@ static void scic_sds_apc_agent_link_down( { port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); - if (port != SCI_INVALID_HANDLE) { + if (port != NULL) { if (port_agent->phy_configured_mask & (1 << phy->phy_index)) { enum sci_status status; diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 21f03bc7d797..cb26d0c3c21c 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1170,7 +1170,7 @@ enum sci_status scic_sds_remote_device_general_frame_handler( io_request = scic_sds_controller_get_io_request_from_tag( scic_sds_remote_device_get_controller(this_device), frame_header->tag); - if ((io_request == SCI_INVALID_HANDLE) + if ((io_request == NULL) || (io_request->target_device != this_device)) { /* * We could not map this tag to a valid IO request diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h index 6eca5a96649e..4aa020e2f079 100644 --- a/drivers/scsi/isci/core/scic_user_callback.h +++ b/drivers/scsi/isci/core/scic_user_callback.h @@ -600,7 +600,7 @@ void scic_cb_port_invalid_link_up( * @port: This parameter specifies the SCI port object for which the callback * is being invoked. For instances where the phy on which the primitive was * received is not part of a port, this parameter will be - * SCI_INVALID_HANDLE_T. + * NULL. * @phy: This parameter specifies the phy on which the primitive was received. * */ @@ -620,7 +620,7 @@ void scic_cb_port_bc_change_primitive_received( * phy. * @port: This parameter specifies the port object for which the user callback * is being invoked. There may be conditions where this parameter can be - * SCI_INVALID_HANDLE + * NULL * @phy: This parameter specifies the phy object for which the user callback is * being invoked. * @@ -638,7 +638,7 @@ void scic_cb_port_link_up( * phy. * @port: This parameter specifies the port object for which the user callback * is being invoked. There may be conditions where this parameter can be - * SCI_INVALID_HANDLE + * NULL * @phy: This parameter specifies the phy object for which the user callback is * being invoked. * diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c index 75f9cd551278..6911ea5d1937 100644 --- a/drivers/scsi/isci/events.c +++ b/drivers/scsi/isci/events.c @@ -399,8 +399,7 @@ void scic_cb_port_invalid_link_up( * port. * @port: This parameter specifies the SCI port object for which the callback * is being invoked. For instances where the phy on which the primitive was - * received is not part of a port, this parameter will be - * SCI_INVALID_HANDLE_T. + * received is not part of a port, this parameter will be NULL. * @phy: This parameter specifies the phy on which the primitive was received. * */ @@ -430,7 +429,7 @@ void scic_cb_port_bc_change_primitive_received( * phy. * @port: This parameter specifies the port object for which the user callback * is being invoked. There may be conditions where this parameter can be - * SCI_INVALID_HANDLE + * NULL * @phy: This parameter specifies the phy object for which the user callback is * being invoked. * @@ -460,7 +459,7 @@ void scic_cb_port_link_up( * phy. * @port: This parameter specifies the port object for which the user callback * is being invoked. There may be conditions where this parameter can be - * SCI_INVALID_HANDLE + * NULL * @phy: This parameter specifies the phy object for which the user callback is * being invoked. * -- cgit v1.2.3 From 82d29928c1c1c6a6605895f8240a9943394244d7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 8 Feb 2011 17:53:10 -0800 Subject: isci: kill SCI_IO_REQUEST_DATA_DIRECTION It's an unnecessary typedef that mirrors the kernel's enum dma_data_direction. Also cleanup some long variable names along the way. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_types.h | 7 --- drivers/scsi/isci/core/scic_sds_request.c | 88 ++++++++++++--------------- drivers/scsi/isci/core/scic_sds_stp_request.c | 62 ++++++++----------- drivers/scsi/isci/core/scic_sds_stp_request.h | 5 +- drivers/scsi/isci/core/scic_user_callback.h | 5 +- drivers/scsi/isci/deprecated.c | 10 +-- drivers/scsi/isci/request.c | 36 +---------- drivers/scsi/isci/request.h | 3 +- 8 files changed, 73 insertions(+), 143 deletions(-) diff --git a/drivers/scsi/isci/core/sci_types.h b/drivers/scsi/isci/core/sci_types.h index e15dc0c89e5c..fda3680546e3 100644 --- a/drivers/scsi/isci/core/sci_types.h +++ b/drivers/scsi/isci/core/sci_types.h @@ -61,13 +61,6 @@ #define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) -typedef enum { - SCI_IO_REQUEST_DATA_IN = 0, /* Read operation */ - SCI_IO_REQUEST_DATA_OUT, /* Write operation */ - SCI_IO_REQUEST_NO_DATA -} SCI_IO_REQUEST_DATA_DIRECTION; - - enum sci_controller_mode { SCI_MODE_SPEED, /* Optimized for performance */ SCI_MODE_SIZE /* Optimized for memory use */ diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index c696d246ea5a..7c5b61bdee67 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -588,34 +588,34 @@ static void scu_ssp_reqeust_construct_task_context( * */ static void scu_ssp_io_request_construct_task_context( - struct scic_sds_request *this_request, - SCI_IO_REQUEST_DATA_DIRECTION data_direction, - u32 transfer_length_bytes) + struct scic_sds_request *sci_req, + enum dma_data_direction dir, + u32 len) { struct scu_task_context *task_context; - task_context = scic_sds_request_get_task_context(this_request); + task_context = scic_sds_request_get_task_context(sci_req); - scu_ssp_reqeust_construct_task_context(this_request, task_context); + scu_ssp_reqeust_construct_task_context(sci_req, task_context); task_context->ssp_command_iu_length = sizeof(struct sci_ssp_command_iu) / sizeof(u32); task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME; - switch (data_direction) { - case SCI_IO_REQUEST_DATA_IN: - case SCI_IO_REQUEST_NO_DATA: + switch (dir) { + case DMA_FROM_DEVICE: + case DMA_NONE: + default: task_context->task_type = SCU_TASK_TYPE_IOREAD; break; - case SCI_IO_REQUEST_DATA_OUT: + case DMA_TO_DEVICE: task_context->task_type = SCU_TASK_TYPE_IOWRITE; break; } - task_context->transfer_length_bytes = transfer_length_bytes; + task_context->transfer_length_bytes = len; - if (task_context->transfer_length_bytes > 0) { - scic_sds_request_build_sgl(this_request); - } + if (task_context->transfer_length_bytes > 0) + scic_sds_request_build_sgl(sci_req); } @@ -694,37 +694,35 @@ static void scu_ssp_task_request_construct_task_context( * * enum sci_status */ -static enum sci_status scic_io_request_construct_sata( - struct scic_sds_request *this_request, - u8 sat_protocol, - u32 transfer_length, - SCI_IO_REQUEST_DATA_DIRECTION data_direction, - bool copy_rx_frame) +static enum sci_status scic_io_request_construct_sata(struct scic_sds_request *sci_req, + u8 proto, u32 len, + enum dma_data_direction dir, + bool copy) { enum sci_status status = SCI_SUCCESS; - switch (sat_protocol) { + switch (proto) { case SAT_PROTOCOL_PIO_DATA_IN: case SAT_PROTOCOL_PIO_DATA_OUT: - status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, copy_rx_frame); + status = scic_sds_stp_pio_request_construct(sci_req, proto, copy); break; case SAT_PROTOCOL_UDMA_DATA_IN: case SAT_PROTOCOL_UDMA_DATA_OUT: - status = scic_sds_stp_udma_request_construct(this_request, transfer_length, data_direction); + status = scic_sds_stp_udma_request_construct(sci_req, len, dir); break; case SAT_PROTOCOL_ATA_HARD_RESET: case SAT_PROTOCOL_SOFT_RESET: - status = scic_sds_stp_soft_reset_request_construct(this_request); + status = scic_sds_stp_soft_reset_request_construct(sci_req); break; case SAT_PROTOCOL_NON_DATA: - status = scic_sds_stp_non_data_request_construct(this_request); + status = scic_sds_stp_non_data_request_construct(sci_req); break; case SAT_PROTOCOL_FPDMA: - status = scic_sds_stp_ncq_request_construct(this_request, transfer_length, data_direction); + status = scic_sds_stp_ncq_request_construct(sci_req, len, dir); break; #if !defined(DISABLE_ATAPI) @@ -733,7 +731,7 @@ static enum sci_status scic_io_request_construct_sata( case SAT_PROTOCOL_PACKET_DMA_DATA_OUT: case SAT_PROTOCOL_PACKET_PIO_DATA_IN: case SAT_PROTOCOL_PACKET_PIO_DATA_OUT: - status = scic_sds_stp_packet_request_construct(this_request); + status = scic_sds_stp_packet_request_construct(sci_req); break; #endif @@ -743,10 +741,10 @@ static enum sci_status scic_io_request_construct_sata( case SAT_PROTOCOL_DEVICE_RESET: case SAT_PROTOCOL_RETURN_RESPONSE_INFO: default: - dev_err(scic_to_dev(this_request->owning_controller), + dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC IO Request 0x%p received un-handled " "SAT Protocl %d.\n", - __func__, this_request, sat_protocol); + __func__, sci_req, proto); status = SCI_FAILURE; break; @@ -945,35 +943,25 @@ enum sci_status scic_task_request_construct_ssp( } -enum sci_status scic_io_request_construct_basic_sata( - struct scic_sds_request *sci_req) +enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_request *sci_req) { enum sci_status status; - struct scic_sds_stp_request *this_stp_request; - u8 sat_protocol; - u32 transfer_length; - SCI_IO_REQUEST_DATA_DIRECTION data_direction; - bool copy_rx_frame = false; + struct scic_sds_stp_request *stp_req; + u8 proto; + u32 len; + enum dma_data_direction dir; + bool copy = false; - this_stp_request = (struct scic_sds_stp_request *)sci_req; + stp_req = container_of(sci_req, typeof(*stp_req), parent); sci_req->protocol = SCIC_STP_PROTOCOL; - transfer_length = - scic_cb_io_request_get_transfer_length(sci_req->user_request); - data_direction = - scic_cb_io_request_get_data_direction(sci_req->user_request); + len = scic_cb_io_request_get_transfer_length(sci_req->user_request); + dir = scic_cb_io_request_get_data_direction(sci_req->user_request); + proto = scic_cb_request_get_sat_protocol(sci_req->user_request); + copy = scic_cb_io_request_do_copy_rx_frames(stp_req->parent.user_request); - sat_protocol = scic_cb_request_get_sat_protocol(sci_req->user_request); - copy_rx_frame = scic_cb_io_request_do_copy_rx_frames(this_stp_request->parent.user_request); - - status = scic_io_request_construct_sata( - sci_req, - sat_protocol, - transfer_length, - data_direction, - copy_rx_frame - ); + status = scic_io_request_construct_sata(sci_req, proto, len, dir, copy); if (status == SCI_SUCCESS) sci_base_state_machine_change_state( diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index c14f6f10edb1..49c494c097cb 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -288,7 +288,7 @@ void scic_sds_stp_non_ncq_request_construct( /** * - * @this_request: This parameter specifies the request to be constructed as an + * @sci_req: This parameter specifies the request to be constructed as an * optimized request. * @optimized_task_type: This parameter specifies whether the request is to be * an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A @@ -298,24 +298,23 @@ void scic_sds_stp_non_ncq_request_construct( * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method * returns an indication as to whether the construction was successful. */ -static void scic_sds_stp_optimized_request_construct( - struct scic_sds_request *this_request, - u8 optimized_task_type, - u32 transfer_length, - SCI_IO_REQUEST_DATA_DIRECTION data_direction) +static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sci_req, + u8 optimized_task_type, + u32 len, + enum dma_data_direction dir) { - struct scu_task_context *task_context = this_request->task_context_buffer; + struct scu_task_context *task_context = sci_req->task_context_buffer; /* Build the STP task context structure */ - scu_sata_reqeust_construct_task_context(this_request, task_context); + scu_sata_reqeust_construct_task_context(sci_req, task_context); /* Copy over the SGL elements */ - scic_sds_request_build_sgl(this_request); + scic_sds_request_build_sgl(sci_req); /* Copy over the number of bytes to be transfered */ - task_context->transfer_length_bytes = transfer_length; + task_context->transfer_length_bytes = len; - if (data_direction == SCI_IO_REQUEST_DATA_OUT) { + if (dir == DMA_TO_DEVICE) { /* * The difference between the DMA IN and DMA OUT request task type * values are consistent with the difference between FPDMA READ @@ -334,29 +333,24 @@ static void scic_sds_stp_optimized_request_construct( /** * - * @this_request: This parameter specifies the request to be constructed. + * @sci_req: This parameter specifies the request to be constructed. * * This method will construct the STP UDMA request and its associated TC data. * This method returns an indication as to whether the construction was * successful. SCI_SUCCESS Currently this method always returns this value. */ -enum sci_status scic_sds_stp_udma_request_construct( - struct scic_sds_request *this_request, - u32 transfer_length, - SCI_IO_REQUEST_DATA_DIRECTION data_direction) +enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, + u32 len, + enum dma_data_direction dir) { - scic_sds_stp_non_ncq_request_construct(this_request); + scic_sds_stp_non_ncq_request_construct(sci_req); - scic_sds_stp_optimized_request_construct( - this_request, - SCU_TASK_TYPE_DMA_IN, - transfer_length, - data_direction - ); + scic_sds_stp_optimized_request_construct(sci_req, SCU_TASK_TYPE_DMA_IN, + len, dir); sci_base_state_machine_construct( - &this_request->started_substate_machine, - &this_request->parent.parent, + &sci_req->started_substate_machine, + &sci_req->parent.parent, scic_sds_stp_request_started_udma_substate_table, SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE ); @@ -366,23 +360,19 @@ enum sci_status scic_sds_stp_udma_request_construct( /** * - * @this_request: This parameter specifies the request to be constructed. + * @sci_req: This parameter specifies the request to be constructed. * * This method will construct the STP UDMA request and its associated TC data. * This method returns an indication as to whether the construction was * successful. SCI_SUCCESS Currently this method always returns this value. */ -enum sci_status scic_sds_stp_ncq_request_construct( - struct scic_sds_request *this_request, - u32 transfer_length, - SCI_IO_REQUEST_DATA_DIRECTION data_direction) +enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_req, + u32 len, + enum dma_data_direction dir) { - scic_sds_stp_optimized_request_construct( - this_request, - SCU_TASK_TYPE_FPDMAQ_READ, - transfer_length, - data_direction - ); + scic_sds_stp_optimized_request_construct(sci_req, + SCU_TASK_TYPE_FPDMAQ_READ, + len, dir); return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index 5578d2baf7ca..0a12ff6417cc 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -56,6 +56,7 @@ #ifndef _SCIC_SDS_STP_REQUEST_T_ #define _SCIC_SDS_STP_REQUEST_T_ +#include #include "intel_sata.h" #include "sci_types.h" #include "scic_sds_request.h" @@ -201,7 +202,7 @@ enum sci_status scic_sds_stp_pio_request_construct_pass_through( enum sci_status scic_sds_stp_udma_request_construct( struct scic_sds_request *this_request, u32 transfer_length, - SCI_IO_REQUEST_DATA_DIRECTION data_direction); + enum dma_data_direction dir); enum sci_status scic_sds_stp_non_data_request_construct( struct scic_sds_request *this_request); @@ -212,7 +213,7 @@ enum sci_status scic_sds_stp_soft_reset_request_construct( enum sci_status scic_sds_stp_ncq_request_construct( struct scic_sds_request *this_request, u32 transfer_length, - SCI_IO_REQUEST_DATA_DIRECTION data_direction); + enum dma_data_direction dir); void scu_stp_raw_request_construct_task_context( struct scic_sds_stp_request *this_request, diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h index 4aa020e2f079..4df7106f61aa 100644 --- a/drivers/scsi/isci/core/scic_user_callback.h +++ b/drivers/scsi/isci/core/scic_user_callback.h @@ -246,11 +246,8 @@ u32 scic_cb_io_request_get_transfer_length( * object. It is a cookie that allows the user to provide the necessary * information for this callback. * - * This method returns the value of SCI_IO_REQUEST_DATA_OUT or - * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA. */ -SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction( - void *scic_user_io_request); +enum dma_data_direction scic_cb_io_request_get_data_direction(void *req); #ifndef SCI_SGL_OPTIMIZATION_ENABLED /** diff --git a/drivers/scsi/isci/deprecated.c b/drivers/scsi/isci/deprecated.c index 847e6874e1a8..0ee6679b8107 100644 --- a/drivers/scsi/isci/deprecated.c +++ b/drivers/scsi/isci/deprecated.c @@ -139,16 +139,10 @@ u32 scic_cb_io_request_get_transfer_length( * @scic_user_io_request: This parameter points to the user's IO request * object. It is a cookie that allows the user to provide the necessary * information for this callback. - * - * This method returns the value of SCI_IO_REQUEST_DATA_OUT or - * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA. */ -SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction( - void *scic_user_io_request) +enum dma_data_direction scic_cb_io_request_get_data_direction(void *req) { - return isci_request_io_request_get_data_direction( - scic_user_io_request - ); + return isci_request_io_request_get_data_direction(req); } diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index e564121b6726..f7ba047d64ce 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1237,44 +1237,12 @@ u32 isci_request_io_request_get_transfer_length(struct isci_request *request) * * data direction for specified request. */ -SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction( +enum dma_data_direction isci_request_io_request_get_data_direction( struct isci_request *request) { struct sas_task *task = isci_request_access_task(request); - SCI_IO_REQUEST_DATA_DIRECTION ret; - switch (task->data_dir) { - - case DMA_FROM_DEVICE: - ret = SCI_IO_REQUEST_DATA_IN; - dev_dbg(&request->isci_host->pdev->dev, - "%s: request=%p, FROM_DEVICE\n", - __func__, - request); - break; - - case DMA_TO_DEVICE: - ret = SCI_IO_REQUEST_DATA_OUT; - dev_dbg(&request->isci_host->pdev->dev, - "%s: request=%p, TO_DEVICE\n", - __func__, - request); - break; - - case DMA_BIDIRECTIONAL: - case DMA_NONE: - default: - ret = SCI_IO_REQUEST_NO_DATA; - dev_dbg(&request->isci_host->pdev->dev, - "%s: request=%p, unhandled direction case, " - "data_dir=%d\n", - __func__, - request, - task->data_dir); - break; - - } - return ret; + return task->data_dir; } /** diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 5079d4a7c41b..166295ee8cfd 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -346,8 +346,7 @@ void isci_request_io_request_complete( u32 isci_request_io_request_get_transfer_length( struct isci_request *request); -SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction( - struct isci_request *request); +enum dma_data_direction isci_request_io_request_get_data_direction(struct isci_request *req); /** * isci_request_io_request_get_next_sge() - This function is called by the sci -- cgit v1.2.3 From b5739b60507af0607fe99f1582b2dce4aa70e0b8 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Tue, 8 Feb 2011 09:31:55 -0700 Subject: isci: kill sci_types.h Signed-off-by: Edmund Nadolski [rebased after killing SCI_IO_REQUEST_DATA_DIRECTION] Signed-off-by: Dan Williams --- .../isci/core/sci_base_memory_descriptor_list.h | 1 - drivers/scsi/isci/core/sci_base_state_machine.h | 2 + drivers/scsi/isci/core/sci_controller.h | 2 - .../scsi/isci/core/sci_memory_descriptor_list.h | 1 - drivers/scsi/isci/core/sci_object.h | 1 - drivers/scsi/isci/core/sci_types.h | 70 ---------------------- drivers/scsi/isci/core/sci_util.h | 7 ++- drivers/scsi/isci/core/scic_config_parameters.h | 1 - drivers/scsi/isci/core/scic_controller.h | 8 ++- drivers/scsi/isci/core/scic_io_request.h | 1 - drivers/scsi/isci/core/scic_phy.h | 1 - drivers/scsi/isci/core/scic_port.h | 1 - drivers/scsi/isci/core/scic_remote_device.h | 1 - drivers/scsi/isci/core/scic_sds_controller.h | 2 + drivers/scsi/isci/core/scic_sds_pci.h | 1 - .../scsi/isci/core/scic_sds_remote_node_context.h | 1 - .../scsi/isci/core/scic_sds_remote_node_table.h | 1 - drivers/scsi/isci/core/scic_sds_request.c | 1 - drivers/scsi/isci/core/scic_sds_smp_request.h | 1 - .../scsi/isci/core/scic_sds_stp_packet_request.h | 1 - drivers/scsi/isci/core/scic_sds_stp_request.c | 1 - drivers/scsi/isci/core/scic_sds_stp_request.h | 1 - drivers/scsi/isci/core/scic_task_request.h | 1 - drivers/scsi/isci/core/scic_user_callback.h | 2 +- drivers/scsi/isci/core/scu_registers.h | 1 - drivers/scsi/isci/core/scu_remote_node_context.h | 1 - drivers/scsi/isci/core/scu_task_context.h | 1 - drivers/scsi/isci/core/scu_unsolicited_frame.h | 2 +- drivers/scsi/isci/core/scu_viit_data.h | 1 - drivers/scsi/isci/isci.h | 1 - 30 files changed, 19 insertions(+), 98 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_types.h diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h index 614e0a98c614..b58d4e86e7b9 100644 --- a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h +++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h @@ -64,7 +64,6 @@ */ -#include "sci_types.h" #include "sci_memory_descriptor_list.h" diff --git a/drivers/scsi/isci/core/sci_base_state_machine.h b/drivers/scsi/isci/core/sci_base_state_machine.h index cee38bd3d127..13f6ee80e15c 100644 --- a/drivers/scsi/isci/core/sci_base_state_machine.h +++ b/drivers/scsi/isci/core/sci_base_state_machine.h @@ -56,6 +56,8 @@ #ifndef _SCI_BASE_STATE_MACHINE_H_ #define _SCI_BASE_STATE_MACHINE_H_ +#include + /** * This file contains all structures, constants, or method declarations common * to all state machines defined in SCI. diff --git a/drivers/scsi/isci/core/sci_controller.h b/drivers/scsi/isci/core/sci_controller.h index 26c3548cbf7a..5c7774e75ddf 100644 --- a/drivers/scsi/isci/core/sci_controller.h +++ b/drivers/scsi/isci/core/sci_controller.h @@ -64,8 +64,6 @@ */ -#include "sci_types.h" - struct sci_base_memory_descriptor_list; struct scic_sds_controller; diff --git a/drivers/scsi/isci/core/sci_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_memory_descriptor_list.h index 44de1c18d2c8..a039998d01c6 100644 --- a/drivers/scsi/isci/core/sci_memory_descriptor_list.h +++ b/drivers/scsi/isci/core/sci_memory_descriptor_list.h @@ -64,7 +64,6 @@ */ -#include "sci_types.h" struct sci_base_memory_descriptor_list; diff --git a/drivers/scsi/isci/core/sci_object.h b/drivers/scsi/isci/core/sci_object.h index 930694264f1a..801b01bc8964 100644 --- a/drivers/scsi/isci/core/sci_object.h +++ b/drivers/scsi/isci/core/sci_object.h @@ -65,7 +65,6 @@ */ -#include "sci_types.h" #include "sci_status.h" /** diff --git a/drivers/scsi/isci/core/sci_types.h b/drivers/scsi/isci/core/sci_types.h deleted file mode 100644 index fda3680546e3..000000000000 --- a/drivers/scsi/isci/core/sci_types.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_TYPES_H_ -#define _SCI_TYPES_H_ - -#include - -#define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ - ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) - -enum sci_controller_mode { - SCI_MODE_SPEED, /* Optimized for performance */ - SCI_MODE_SIZE /* Optimized for memory use */ -}; - -#endif /* _SCI_TYPES_H_ */ - diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h index 67e2badf8ea8..8f2ba35d955f 100644 --- a/drivers/scsi/isci/core/sci_util.h +++ b/drivers/scsi/isci/core/sci_util.h @@ -56,7 +56,7 @@ #ifndef _SCI_UTIL_H_ #define _SCI_UTIL_H_ -#include "sci_types.h" +#include /** * SCIC_SWAP_DWORD() - @@ -81,6 +81,11 @@ #define SCI_FIELD_OFFSET(type, field) ((unsigned long)&(((type *)0)->field)) + +#define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ + ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) + + /** * sci_physical_address_add() - * diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index 4c16a50a0658..8bd85605130c 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -65,7 +65,6 @@ */ -#include "sci_types.h" #include "sci_status.h" #include "intel_sas.h" #include "sci_controller_constants.h" diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 756b14fcd9a4..1d459d6af21b 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -64,7 +64,6 @@ */ -#include "sci_types.h" #include "sci_status.h" #include "sci_controller.h" #include "scic_config_parameters.h" @@ -74,6 +73,13 @@ struct scic_sds_phy; struct scic_sds_port; struct scic_sds_remote_device; + +enum sci_controller_mode { + SCI_MODE_SPEED, /* Optimized for performance */ + SCI_MODE_SIZE /* Optimized for memory use */ +}; + + /** * enum _SCIC_INTERRUPT_TYPE - This enumeration depicts the various types of * interrupts that are potentially supported by a SCI Core implementation. diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h index 7378f335066c..a52f33d94abd 100644 --- a/drivers/scsi/isci/core/scic_io_request.h +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -64,7 +64,6 @@ */ -#include "sci_types.h" #include "sci_status.h" #include "intel_sas.h" diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index fec273b123d4..13f8a304fdef 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -64,7 +64,6 @@ */ -#include "sci_types.h" #include "sci_status.h" #include "intel_sata.h" diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h index 34d22c04aa56..e55abb68ff9a 100644 --- a/drivers/scsi/isci/core/scic_port.h +++ b/drivers/scsi/isci/core/scic_port.h @@ -64,7 +64,6 @@ */ -#include "sci_types.h" #include "sci_status.h" #include "intel_sas.h" diff --git a/drivers/scsi/isci/core/scic_remote_device.h b/drivers/scsi/isci/core/scic_remote_device.h index e8c04592763e..1401844349e6 100644 --- a/drivers/scsi/isci/core/scic_remote_device.h +++ b/drivers/scsi/isci/core/scic_remote_device.h @@ -64,7 +64,6 @@ */ -#include "sci_types.h" #include "sci_status.h" #include "intel_sas.h" diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index afa45f9874a4..cce0da6a6a3d 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -56,6 +56,8 @@ #ifndef _SCIC_SDS_CONTROLLER_H_ #define _SCIC_SDS_CONTROLLER_H_ +#include + /** * This file contains the structures, constants and prototypes used for the * core controller object. diff --git a/drivers/scsi/isci/core/scic_sds_pci.h b/drivers/scsi/isci/core/scic_sds_pci.h index 21326777acc6..bf0cbcaac526 100644 --- a/drivers/scsi/isci/core/scic_sds_pci.h +++ b/drivers/scsi/isci/core/scic_sds_pci.h @@ -64,7 +64,6 @@ */ #include -#include "sci_types.h" struct scic_sds_controller; diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h index 59eacf8f400c..9e759a3619f1 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.h +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h @@ -64,7 +64,6 @@ * */ -#include "sci_types.h" #include "sci_base_state.h" #include "sci_base_state_machine.h" diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.h b/drivers/scsi/isci/core/scic_sds_remote_node_table.h index 6ee5fbab25dd..9c02a6ccb2fe 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_table.h +++ b/drivers/scsi/isci/core/scic_sds_remote_node_table.h @@ -63,7 +63,6 @@ * */ -#include "sci_types.h" #include "sci_controller_constants.h" /** diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 7c5b61bdee67..2bd47f49e536 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -72,7 +72,6 @@ #include "scic_sds_unsolicited_frame_control.h" #include "scic_user_callback.h" #include "sci_environment.h" -#include "sci_types.h" #include "sci_util.h" #include "scu_completion_codes.h" #include "scu_constants.h" diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.h b/drivers/scsi/isci/core/scic_sds_smp_request.h index b7c5b83b1989..bcad282ce753 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.h +++ b/drivers/scsi/isci/core/scic_sds_smp_request.h @@ -56,7 +56,6 @@ #define _SCIC_SDS_SMP_REQUEST_T_ #include "intel_sas.h" -#include "sci_types.h" #include "scic_sds_request.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h index fc18b3f6a13f..2a7aec922dee 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h @@ -56,7 +56,6 @@ #define _SCIC_SDS_STP_PACKET_REQUEST_H_ #include "intel_sas.h" -#include "sci_types.h" #include "scic_sds_stp_request.h" /** diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 49c494c097cb..0b6b0552186a 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -69,7 +69,6 @@ #include "scic_sds_unsolicited_frame_control.h" #include "scic_user_callback.h" #include "sci_environment.h" -#include "sci_types.h" #include "sci_util.h" #include "scu_completion_codes.h" #include "scu_event_codes.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index 0a12ff6417cc..4a4c68aa56de 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -58,7 +58,6 @@ #include #include "intel_sata.h" -#include "sci_types.h" #include "scic_sds_request.h" /** diff --git a/drivers/scsi/isci/core/scic_task_request.h b/drivers/scsi/isci/core/scic_task_request.h index ef76cb6bdbea..7e6d20aa0f02 100644 --- a/drivers/scsi/isci/core/scic_task_request.h +++ b/drivers/scsi/isci/core/scic_task_request.h @@ -65,7 +65,6 @@ */ -#include "sci_types.h" #include "sci_status.h" struct scic_sds_request; diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h index 4df7106f61aa..ec4eb278cd5f 100644 --- a/drivers/scsi/isci/core/scic_user_callback.h +++ b/drivers/scsi/isci/core/scic_user_callback.h @@ -64,8 +64,8 @@ */ -#include "sci_types.h" #include "sci_status.h" +#include "scic_io_request.h" struct scic_sds_request; struct scic_sds_phy; diff --git a/drivers/scsi/isci/core/scu_registers.h b/drivers/scsi/isci/core/scu_registers.h index 175d2b98bdf2..de2ce93b7836 100644 --- a/drivers/scsi/isci/core/scu_registers.h +++ b/drivers/scsi/isci/core/scu_registers.h @@ -63,7 +63,6 @@ * */ -#include "sci_types.h" #include "scu_viit_data.h" diff --git a/drivers/scsi/isci/core/scu_remote_node_context.h b/drivers/scsi/isci/core/scu_remote_node_context.h index 8006f2ee2d1d..33745adc826b 100644 --- a/drivers/scsi/isci/core/scu_remote_node_context.h +++ b/drivers/scsi/isci/core/scu_remote_node_context.h @@ -62,7 +62,6 @@ * * */ -#include "sci_types.h" /** * struct ssp_remote_node_context - This structure contains the SCU hardware diff --git a/drivers/scsi/isci/core/scu_task_context.h b/drivers/scsi/isci/core/scu_task_context.h index d08c51bb2262..818a575298d3 100644 --- a/drivers/scsi/isci/core/scu_task_context.h +++ b/drivers/scsi/isci/core/scu_task_context.h @@ -63,7 +63,6 @@ * */ -#include "sci_types.h" /** * enum SCU_SSP_TASK_TYPE - This enumberation defines the various SSP task diff --git a/drivers/scsi/isci/core/scu_unsolicited_frame.h b/drivers/scsi/isci/core/scu_unsolicited_frame.h index 590ea02745fd..187c4f03f596 100644 --- a/drivers/scsi/isci/core/scu_unsolicited_frame.h +++ b/drivers/scsi/isci/core/scu_unsolicited_frame.h @@ -64,7 +64,7 @@ #ifndef _SCU_UNSOLICITED_FRAME_H_ #define _SCU_UNSOLICITED_FRAME_H_ -#include "sci_types.h" +#include /** * diff --git a/drivers/scsi/isci/core/scu_viit_data.h b/drivers/scsi/isci/core/scu_viit_data.h index 4601d1962ca3..c959d9158225 100644 --- a/drivers/scsi/isci/core/scu_viit_data.h +++ b/drivers/scsi/isci/core/scu_viit_data.h @@ -63,7 +63,6 @@ * */ -#include "sci_types.h" #define SCU_VIIT_ENTRY_ID_MASK (0xC0000000) #define SCU_VIIT_ENTRY_ID_SHIFT (30) diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 7d984f408f24..21371e73e296 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -79,7 +79,6 @@ #include #include -#include "sci_types.h" #include "sci_base_controller.h" #include "scic_controller.h" #include "host.h" -- cgit v1.2.3 From 6e473dd112f95806a4bfd12eced5b73632d6c032 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Fri, 11 Feb 2011 18:04:28 -0800 Subject: isci: removing unused loglevel module param We no longer use the loglevel parameter. Remove. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/init.c | 2 -- drivers/scsi/isci/isci.h | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 07b072f3004d..e3d9b15d0cbf 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -98,8 +98,6 @@ static struct pci_driver isci_pci_driver = { }; /* linux isci specific settings */ -int loglevel = 3; -module_param(loglevel, int, S_IRUGO | S_IWUSR); #if defined(CONFIG_PBG_HBA_A0) int isci_si_rev = ISCI_SI_REVA0; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 21371e73e296..6aee3c9c8827 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -85,7 +85,6 @@ #include "timers.h" #include "sci_status.h" -extern int loglevel; extern struct kmem_cache *isci_kmem_cache; #define ISCI_FW_NAME "isci/isci_firmware.bin" -- cgit v1.2.3 From 7fbafaa51960cd2f2a7afa63829b4135c9682a75 Mon Sep 17 00:00:00 2001 From: Henryk Dembkowski Date: Sat, 12 Feb 2011 11:50:05 -0800 Subject: isci: remote device and node cleanup step1 c99 the struct initializers (scic_sds_remote_device_state_handler_table[]): 1/ allows grep to consistently show method name associations. The naming is mostly consistent (except when it isn't) so this guarantees coverage of present and future exception cases. 2/ let's the compiler guarantee that the state table array entry correlates with an actual state name and detect accidental reordering or deletion of states. 3/ allows default handler's to be identified easily Change names from upper to low letters Cleanup empty lines Signed-off-by: Henryk Dembkowski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_remote_device.h | 3 - drivers/scsi/isci/core/scic_sds_remote_device.c | 284 ++++++++++----------- drivers/scsi/isci/core/scic_sds_remote_device.h | 77 ++---- .../scsi/isci/core/scic_sds_remote_node_context.c | 26 +- .../scsi/isci/core/scic_sds_remote_node_context.h | 46 +--- .../scsi/isci/core/scic_sds_stp_remote_device.c | 2 +- 6 files changed, 184 insertions(+), 254 deletions(-) diff --git a/drivers/scsi/isci/core/sci_base_remote_device.h b/drivers/scsi/isci/core/sci_base_remote_device.h index fe6614b8ef5b..25c6ddd4fdbe 100644 --- a/drivers/scsi/isci/core/sci_base_remote_device.h +++ b/drivers/scsi/isci/core/sci_base_remote_device.h @@ -130,9 +130,6 @@ enum sci_base_remote_device_states { * Simply the final state for the base remote device state machine. */ SCI_BASE_REMOTE_DEVICE_STATE_FINAL, - - SCI_BASE_REMOTE_DEVICE_MAX_STATES - }; /** diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index cb26d0c3c21c..b824e570a494 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1707,168 +1707,142 @@ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_h /* --------------------------------------------------------------------------- */ -struct scic_sds_remote_device_state_handler -scic_sds_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] = -{ - /* SCI_BASE_REMOTE_DEVICE_STATE_INITIAL */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_default_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_default_event_handler, - scic_sds_remote_device_default_frame_handler +const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { + [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_default_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, - /* SCI_BASE_REMOTE_DEVICE_STATE_STOPPED */ - { - { - scic_sds_remote_device_stopped_state_start_handler, - scic_sds_remote_device_stopped_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_stopped_state_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_default_event_handler, - scic_sds_remote_device_default_frame_handler + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { + .parent.start_handler = scic_sds_remote_device_stopped_state_start_handler, + .parent.stop_handler = scic_sds_remote_device_stopped_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, - /* SCI_BASE_REMOTE_DEVICE_STATE_STARTING */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_starting_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_remote_device_default_frame_handler + [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_starting_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, - /* SCI_BASE_REMOTE_DEVICE_STATE_READY */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_ready_state_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_ready_state_start_io_handler, - scic_sds_remote_device_ready_state_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_ready_state_start_task_handler, - scic_sds_remote_device_ready_state_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_remote_device_general_frame_handler, + [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, + .parent.complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, + .parent.complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler, }, - /* SCI_BASE_REMOTE_DEVICE_STATE_STOPPING */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_stopping_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_stopping_state_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_stopping_state_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_remote_device_general_frame_handler + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_stopping_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler }, - /* SCI_BASE_REMOTE_DEVICE_STATE_FAILED */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_default_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_default_event_handler, - scic_sds_remote_device_general_frame_handler + [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_default_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler }, - /* SCI_BASE_REMOTE_DEVICE_STATE_RESETTING */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_resetting_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_resetting_state_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_resetting_state_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_resetting_state_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_default_event_handler, - scic_sds_remote_device_general_frame_handler + [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_resetting_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler }, - /* SCI_BASE_REMOTE_DEVICE_STATE_FINAL */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_default_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_default_event_handler, - scic_sds_remote_device_default_frame_handler + [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_default_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler } }; diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index 44185a2738ec..8aa0a5e4d72e 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -87,20 +87,21 @@ enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES { SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL, /** - * This is the ready operational substate for the remote device. This is the - * normal operational state for a remote device. + * This is the ready operational substate for the remote device. + * This is the normal operational state for a remote device. */ SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL, /** - * This is the suspended state for the remote device. This is the state that - * the device is placed in when a RNC suspend is received by the SCU hardware. + * This is the suspended state for the remote device. This is the state + * that the device is placed in when a RNC suspend is received by + * the SCU hardware. */ SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED, /** - * This is the final state that the device is placed in before a change to the - * base state machine. + * This is the final state that the device is placed in before a change + * to the base state machine. */ SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL, @@ -110,8 +111,8 @@ enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES { /** * enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES - * - * This is the enumeration for the struct scic_sds_remote_device ready substates for - * the STP remote device. + * This is the enumeration for the struct scic_sds_remote_device ready substates + * for the STP remote device. */ enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES { /** @@ -161,13 +162,11 @@ enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES { SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES }; - /** * enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES - * * This is the enumeration of the ready substates for the SMP REMOTE DEVICE. */ - enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES { /** * This is the ready operational substate for the remote device. This is the @@ -184,9 +183,6 @@ enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES { SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES }; - - - /** * struct scic_sds_remote_device - This structure contains the data for an SCU * implementation of the SCU Core device data. @@ -223,21 +219,22 @@ struct scic_sds_remote_device { struct sci_sas_address device_address; /** - * This filed is assinged the value of true if the device is directly attached - * to the port. + * This filed is assinged the value of true if the device is directly + * attached to the port. */ bool is_direct_attached; #if !defined(DISABLE_ATAPI) /** - * This filed is assinged the value of true if the device is an ATAPI device. + * This filed is assinged the value of true if the device is an ATAPI + * device. */ bool is_atapi; #endif /** - * This filed contains a pointer back to the port to which this device is - * assigned. + * This filed contains a pointer back to the port to which this device + * is assigned. */ struct scic_sds_port *owning_port; @@ -284,29 +281,28 @@ struct scic_sds_remote_device { * This field maintains the set of state handlers for the remote device * object. These are changed each time the remote device enters a new state. */ - struct scic_sds_remote_device_state_handler *state_handlers; + const struct scic_sds_remote_device_state_handler *state_handlers; }; - -typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_HANDLER_T)( +typedef enum sci_status (*scic_sds_remote_device_handler_t)( struct scic_sds_remote_device *this_device); -typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T)( +typedef enum sci_status (*scic_sds_remote_device_suspend_handler_t)( struct scic_sds_remote_device *this_device, u32 suspend_type); -typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T)( +typedef enum sci_status (*scic_sds_remote_device_resume_handler_t)( struct scic_sds_remote_device *this_device); -typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T)( +typedef enum sci_status (*scic_sds_remote_device_frame_handler_t)( struct scic_sds_remote_device *this_device, u32 frame_index); -typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T)( +typedef enum sci_status (*scic_sds_remote_device_event_handler_t)( struct scic_sds_remote_device *this_device, u32 event_code); -typedef void (*SCIC_SDS_REMOTE_DEVICE_READY_NOT_READY_HANDLER_T)( +typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( struct scic_sds_remote_device *this_device); /** @@ -318,23 +314,18 @@ typedef void (*SCIC_SDS_REMOTE_DEVICE_READY_NOT_READY_HANDLER_T)( */ struct scic_sds_remote_device_state_handler { struct sci_base_remote_device_state_handler parent; - - SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T suspend_handler; - SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T resume_handler; - - SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T event_handler; - SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T frame_handler; - + scic_sds_remote_device_suspend_handler_t suspend_handler; + scic_sds_remote_device_resume_handler_t resume_handler; + scic_sds_remote_device_event_handler_t event_handler; + scic_sds_remote_device_frame_handler_t frame_handler; }; - extern const struct sci_base_state scic_sds_remote_device_state_table[]; extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[]; extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[]; extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[]; -extern struct scic_sds_remote_device_state_handler - scic_sds_remote_device_state_handler_table[]; +extern const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[]; extern struct scic_sds_remote_device_state_handler scic_sds_ssp_remote_device_ready_substate_handler_table[]; extern struct scic_sds_remote_device_state_handler @@ -480,10 +471,6 @@ extern struct scic_sds_remote_device_state_handler #define scic_sds_remote_device_set_working_request(device, request) \ ((device)->working_request = (request)) -/* --------------------------------------------------------------------------- */ - - - enum sci_status scic_sds_remote_device_frame_handler( struct scic_sds_remote_device *this_device, u32 frame_index); @@ -525,10 +512,6 @@ bool scic_sds_remote_device_is_atapi( #define scic_sds_remote_device_is_atapi(this_device) false #endif /* !defined(DISABLE_ATAPI) */ -/* --------------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------------- */ - void scic_sds_remote_device_start_request( struct scic_sds_remote_device *this_device, struct scic_sds_request *the_request, @@ -540,7 +523,6 @@ void scic_sds_remote_device_continue_request( enum sci_status scic_sds_remote_device_default_start_handler( struct sci_base_remote_device *this_device); - enum sci_status scic_sds_remote_device_default_fail_handler( struct sci_base_remote_device *this_device); @@ -577,8 +559,6 @@ enum sci_status scic_sds_remote_device_default_frame_handler( struct scic_sds_remote_device *this_device, u32 frame_index); -/* --------------------------------------------------------------------------- */ - enum sci_status scic_sds_remote_device_ready_state_stop_handler( struct sci_base_remote_device *device); @@ -596,7 +576,4 @@ enum sci_status scic_sds_remote_device_general_event_handler( enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler( struct scic_sds_remote_device *this_device); -/* --------------------------------------------------------------------------- */ - - #endif /* _SCIC_SDS_REMOTE_DEVICE_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c index 79fe9a8cd1ed..7fec322571ef 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.c +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c @@ -195,7 +195,7 @@ void scic_sds_remote_node_context_construct_buffer( */ static void scic_sds_remote_node_context_setup_to_resume( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { @@ -216,7 +216,7 @@ static void scic_sds_remote_node_context_setup_to_resume( */ static void scic_sds_remote_node_context_setup_to_destory( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; @@ -234,7 +234,7 @@ static void scic_sds_remote_node_context_setup_to_destory( */ static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { @@ -251,7 +251,7 @@ static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( static enum sci_status scic_sds_remote_node_context_default_destruct_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { dev_warn(scirdev_to_dev(this_rnc->device), @@ -270,7 +270,7 @@ static enum sci_status scic_sds_remote_node_context_default_destruct_handler( static enum sci_status scic_sds_remote_node_context_default_suspend_handler( struct scic_sds_remote_node_context *this_rnc, u32 suspend_type, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { dev_warn(scirdev_to_dev(this_rnc->device), @@ -285,7 +285,7 @@ static enum sci_status scic_sds_remote_node_context_default_suspend_handler( static enum sci_status scic_sds_remote_node_context_default_resume_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { dev_warn(scirdev_to_dev(this_rnc->device), @@ -372,7 +372,7 @@ static enum sci_status scic_sds_remote_node_context_success_start_task_handler( */ static enum sci_status scic_sds_remote_node_context_general_destruct_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { scic_sds_remote_node_context_setup_to_destory( @@ -391,7 +391,7 @@ static enum sci_status scic_sds_remote_node_context_general_destruct_handler( static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { @@ -449,7 +449,7 @@ static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { scic_sds_remote_node_context_setup_to_destory( @@ -575,7 +575,7 @@ static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( struct scic_sds_remote_node_context *this_rnc, u32 suspend_type, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { this_rnc->user_callback = the_callback; @@ -662,7 +662,7 @@ static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { enum sci_status status; @@ -737,7 +737,7 @@ static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { scic_sds_remote_node_context_setup_to_resume( @@ -761,7 +761,7 @@ static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume */ static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter) { scic_sds_remote_node_context_setup_to_resume( diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h index 9e759a3619f1..86c6d75a1110 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.h +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h @@ -67,8 +67,6 @@ #include "sci_base_state.h" #include "sci_base_state_machine.h" -/* --------------------------------------------------------------------------- */ - /** * * @@ -85,77 +83,71 @@ struct scic_sds_request; struct scic_sds_remote_device; struct scic_sds_remote_node_context; -typedef void (*SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK)(void *); +typedef void (*scics_sds_remote_node_context_callback)(void *); -typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION)( +typedef enum sci_status (*scic_sds_remote_node_context_operation)( struct scic_sds_remote_node_context *this_rnc, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter ); -typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION)( +typedef enum sci_status (*scic_sds_remote_node_context_suspend_operation)( struct scic_sds_remote_node_context *this_rnc, u32 suspension_type, - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, + scics_sds_remote_node_context_callback the_callback, void *callback_parameter ); -typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST)( +typedef enum sci_status (*scic_sds_remote_node_context_io_request)( struct scic_sds_remote_node_context *this_rnc, struct scic_sds_request *the_request ); -typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER)( +typedef enum sci_status (*scic_sds_remote_node_context_event_handler)( struct scic_sds_remote_node_context *this_rnc, u32 event_code ); -/* --------------------------------------------------------------------------- */ - struct scic_sds_remote_node_context_handlers { /** * This handle is invoked to stop the RNC. The callback is invoked when after * the hardware notification that the RNC has been invalidated. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION destruct_handler; + scic_sds_remote_node_context_operation destruct_handler; /** * This handler is invoked when there is a request to suspend the RNC. The * callback is invoked after the hardware notification that the remote node is * suspended. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION suspend_handler; + scic_sds_remote_node_context_suspend_operation suspend_handler; /** * This handler is invoked when there is a request to resume the RNC. The * callback is invoked when after the RNC has reached the ready state. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION resume_handler; + scic_sds_remote_node_context_operation resume_handler; /** * This handler is invoked when there is a request to start an io request * operation. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_io_handler; + scic_sds_remote_node_context_io_request start_io_handler; /** * This handler is invoked when there is a request to start a task request * operation. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_task_handler; + scic_sds_remote_node_context_io_request start_task_handler; /** * This handler is invoked where there is an RNC event that must be processed. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER event_handler; + scic_sds_remote_node_context_event_handler event_handler; }; -/* --------------------------------------------------------------------------- */ - /** - * - * * This is the enumeration of the remote node context states. */ enum scis_sds_remote_node_context_states { @@ -232,8 +224,6 @@ enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE { * associated with the remote node context object. The remote node context * (RNC) object models the the remote device information necessary to manage * the silicon RNC. - * - * */ struct scic_sds_remote_node_context { /* @@ -273,7 +263,7 @@ struct scic_sds_remote_node_context { * This field contains the callback function that the user requested to be * called when the requested state transition is complete. */ - SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK user_callback; + scics_sds_remote_node_context_callback user_callback; /** * This field contains the parameter that is called when the user requested @@ -289,16 +279,12 @@ struct scic_sds_remote_node_context { struct scic_sds_remote_node_context_handlers *state_handlers; }; -/* --------------------------------------------------------------------------- */ - extern const struct sci_base_state scic_sds_remote_node_context_state_table[]; extern struct scic_sds_remote_node_context_handlers scic_sds_remote_node_context_state_handler_table[ SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES]; -/* --------------------------------------------------------------------------- */ - void scic_sds_remote_node_context_construct( struct scic_sds_remote_device *device, struct scic_sds_remote_node_context *rnc, @@ -307,7 +293,6 @@ void scic_sds_remote_node_context_construct( void scic_sds_remote_node_context_construct_buffer( struct scic_sds_remote_node_context *rnc); - bool scic_sds_remote_node_context_is_ready( struct scic_sds_remote_node_context *this_rnc); @@ -335,7 +320,4 @@ bool scic_sds_remote_node_context_is_ready( #define scic_sds_remote_node_context_start_task(rnc, task) \ ((rnc)->state_handlers->start_task_handler(rnc, task)) -/* --------------------------------------------------------------------------- */ - #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ - diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index abe8f331a15c..1320c95ee8d4 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -192,7 +192,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_h scic_sds_remote_node_context_resume( this_device->rnc, - (SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK) + (scics_sds_remote_node_context_callback) scic_sds_remote_device_continue_request, this_device); } -- cgit v1.2.3 From 2f02f556abd4411d4d348b3bd9ce4d21c316f447 Mon Sep 17 00:00:00 2001 From: Henryk Dembkowski Date: Sat, 12 Feb 2011 11:50:07 -0800 Subject: isci: coding style changes for remote device Change names from upper to low letters Signed-off-by: Henryk Dembkowski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_remote_device.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index 8aa0a5e4d72e..aed4eb640c26 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -75,12 +75,12 @@ struct scic_sds_request; struct scic_sds_remote_device_state_handler; /** - * enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES - + * enum scic_sds_ssp_remote_device_ready_substates - * * This is the enumeration of the ready substates for the * struct scic_sds_remote_device. */ -enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES { +enum scic_sds_ssp_remote_device_ready_substates { /** * This is the initial state for the remote device ready substate. */ @@ -109,12 +109,12 @@ enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES { }; /** - * enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES - + * enum scic_sds_stp_remote_device_ready_substates - * * This is the enumeration for the struct scic_sds_remote_device ready substates * for the STP remote device. */ -enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES { +enum scic_sds_stp_remote_device_ready_substates { /** * This is the idle substate for the stp remote device. When there are no * active IO for the device it is is in this state. @@ -163,11 +163,11 @@ enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES { }; /** - * enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES - + * enum scic_sds_smp_remote_device_ready_substates - * * This is the enumeration of the ready substates for the SMP REMOTE DEVICE. */ -enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES { +enum scic_sds_smp_remote_device_ready_substates { /** * This is the ready operational substate for the remote device. This is the * normal operational state for a remote device. -- cgit v1.2.3 From db48255b32a2664d8b321a51f46084a669e11ac6 Mon Sep 17 00:00:00 2001 From: Henryk Dembkowski Date: Sat, 12 Feb 2011 11:50:09 -0800 Subject: isci: c99 tables cleanup step1 scic_sds_stp_remote_device_ready_substate_handler_table[] scic_sds_smp_remote_device_ready_substate_handler_table[] c99 the struct initializers: 1/ allows grep to consistently show method name associations. The naming is mostly consistent (except when it isn't) so this guarantees coverage of present and future exception cases. 2/ let's the compiler guarantee that the state table array entry correlates with an actual state name and detect accidental reordering or deletion of states. 3/ allows default handler's to be identified easily Signed-off-by: Henryk Dembkowski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_remote_device.h | 12 +- .../scsi/isci/core/scic_sds_smp_remote_device.c | 75 ++++--- .../scsi/isci/core/scic_sds_stp_remote_device.c | 215 ++++++++++----------- 3 files changed, 132 insertions(+), 170 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index aed4eb640c26..d91570f212c6 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -158,8 +158,6 @@ enum scic_sds_stp_remote_device_ready_substates { * coming to be recovered from certain hardware specific error. */ SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, - - SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES }; /** @@ -179,8 +177,6 @@ enum scic_sds_smp_remote_device_ready_substates { * the device is placed in when a RNC suspend is received by the SCU hardware. */ SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, - - SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES }; /** @@ -326,12 +322,8 @@ extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_tab extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[]; extern const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[]; -extern struct scic_sds_remote_device_state_handler - scic_sds_ssp_remote_device_ready_substate_handler_table[]; -extern struct scic_sds_remote_device_state_handler - scic_sds_stp_remote_device_ready_substate_handler_table[]; -extern struct scic_sds_remote_device_state_handler - scic_sds_smp_remote_device_ready_substate_handler_table[]; +extern const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[]; +extern const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[]; /** * scic_sds_remote_device_increment_request_count() - diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index 7cf78d3212cc..b0ed9d11eb2d 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -214,49 +214,40 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl /* --------------------------------------------------------------------------- */ -struct scic_sds_remote_device_state_handler -scic_sds_smp_remote_device_ready_substate_handler_table[ - SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = -{ - /* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, - scic_sds_remote_device_default_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_remote_device_default_frame_handler +const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = { + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, + .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, - /* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_default_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, - scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_remote_device_default_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_smp_remote_device_ready_cmd_substate_frame_handler + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_default_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, + .parent.complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler } }; /* diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index 1320c95ee8d4..6aa170e92500 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -547,131 +547,110 @@ enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_hand /* --------------------------------------------------------------------------- */ -struct scic_sds_remote_device_state_handler -scic_sds_stp_remote_device_ready_substate_handler_table[ - SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = -{ - /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_ready_state_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, - scic_sds_remote_device_default_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_stp_remote_device_ready_substate_start_request_handler, - scic_sds_remote_device_default_complete_request_handler - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_stp_remote_device_ready_idle_substate_event_handler, - scic_sds_remote_device_default_frame_handler +const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, + .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, - /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_ready_state_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, - scic_sds_stp_remote_device_complete_request, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_stp_remote_device_ready_substate_start_request_handler, - scic_sds_stp_remote_device_complete_request, - }, - scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_stp_remote_device_ready_cmd_substate_frame_handler + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, + .parent.complete_io_handler = scic_sds_stp_remote_device_complete_request, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, - /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_ready_state_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, - scic_sds_stp_remote_device_complete_request, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_stp_remote_device_ready_substate_start_request_handler, - scic_sds_stp_remote_device_complete_request - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_stp_remote_device_ready_ncq_substate_frame_handler + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, + .parent.complete_io_handler = scic_sds_stp_remote_device_complete_request, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, - /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_ready_state_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_stp_remote_device_complete_request, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_stp_remote_device_ready_substate_start_request_handler, - scic_sds_stp_remote_device_complete_request - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_remote_device_general_frame_handler + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_stp_remote_device_complete_request, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler }, #if !defined(DISABLE_ATAPI) - /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_ready_state_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_remote_device_default_start_request_handler, - scic_sds_stp_remote_device_complete_request, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_stp_remote_device_ready_substate_start_request_handler, - scic_sds_stp_remote_device_complete_request - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, - scic_sds_remote_device_general_frame_handler + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, + .parent.complete_io_handler = scic_sds_stp_remote_device_complete_request, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler }, #endif - /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET */ - { - { - scic_sds_remote_device_default_start_handler, - scic_sds_remote_device_ready_state_stop_handler, - scic_sds_remote_device_default_fail_handler, - scic_sds_remote_device_default_destruct_handler, - scic_sds_remote_device_ready_state_reset_handler, - scic_sds_remote_device_default_reset_complete_handler, - scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, - scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, - scic_sds_remote_device_default_continue_request_handler, - scic_sds_stp_remote_device_ready_substate_start_request_handler, - scic_sds_stp_remote_device_complete_request - }, - scic_sds_remote_device_default_suspend_handler, - scic_sds_remote_device_default_resume_handler, - scic_sds_remote_device_general_event_handler, - scic_sds_remote_device_general_frame_handler + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { + .parent.start_handler = scic_sds_remote_device_default_start_handler, + .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .parent.fail_handler = scic_sds_remote_device_default_fail_handler, + .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, + .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .parent.start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, + .parent.complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, + .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler } }; -- cgit v1.2.3 From e574a8c18069bcc04537c4a3d7c5dbab2265007c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 12 Feb 2011 11:50:11 -0800 Subject: isci: cleanup core consolidation leftovers Remove duplicated license and header file includes that were leftover from commit 4c1db2d0 "isci: consolidate core" (in the isci.git historical branch). Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_remote_device.c | 167 ++------------------- .../scsi/isci/core/scic_sds_smp_remote_device.c | 85 +---------- drivers/scsi/isci/core/scic_sds_ssp_request.c | 78 +--------- .../scsi/isci/core/scic_sds_stp_remote_device.c | 78 +--------- 4 files changed, 23 insertions(+), 385 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index b824e570a494..5fc1baaa56d0 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -53,23 +53,22 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the implementation of remote device methods. - * - * - */ - #include "intel_sas.h" -#include "sci_util.h" -#include "sci_environment.h" -#include "scic_port.h" +#include "scic_controller.h" #include "scic_phy.h" +#include "scic_port.h" #include "scic_remote_device.h" -#include "scic_sds_port.h" +#include "scic_sds_controller.h" #include "scic_sds_phy.h" +#include "scic_sds_port.h" #include "scic_sds_remote_device.h" +#include "scic_sds_remote_node_context.h" #include "scic_sds_request.h" -#include "scic_sds_controller.h" +#include "scic_user_callback.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_event_codes.h" + #define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT (1000) @@ -501,82 +500,6 @@ bool scic_sds_remote_device_is_atapi( } } #endif -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains the state handlers for the struct scic_sds_remote_device for the - * base state machine. - * - * - */ - -#include "sci_environment.h" -#include "scic_user_callback.h" -#include "scic_controller.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_controller.h" -#include "scic_sds_port.h" -#include "scic_sds_request.h" -#include "scic_sds_remote_node_context.h" -#include "scu_event_codes.h" - -/* - * ***************************************************************************** - * * PROTECTED METHODS - * ***************************************************************************** */ /** * @@ -1846,76 +1769,6 @@ const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_h } }; -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains the operations that are taken on the enter and exit state - * transitions for the struct sci_base_remote_device state machine. - * - * - */ - -#include "scic_remote_device.h" -#include "scic_user_callback.h" -#include "scic_sds_controller.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_request.h" -#include "scic_sds_controller.h" -#include "scic_sds_port.h" - /** * * @object: This is the struct sci_base_object that is cast into a diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index b0ed9d11eb2d..ea608c1ad8cb 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -53,23 +53,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains This file contains the ready substate handlers for a SMP - * device. - * - * - */ - -#include "sci_environment.h" -#include "scic_user_callback.h" -#include "scic_sds_remote_device.h" +#include "scic_remote_device.h" #include "scic_sds_controller.h" #include "scic_sds_port.h" +#include "scic_sds_remote_device.h" #include "scic_sds_request.h" +#include "scic_user_callback.h" +#include "sci_environment.h" +#include "sci_util.h" #include "scu_event_codes.h" #include "scu_task_context.h" - /* * ***************************************************************************** * * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS @@ -250,75 +244,6 @@ const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_rea .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler } }; -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains the enter and exit functions for the - * struct scic_sds_remote_device ready substate machine. - * - * - */ - -#include "scic_remote_device.h" -#include "scic_user_callback.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_controller.h" -#include "scic_sds_port.h" -#include "sci_util.h" -#include "sci_environment.h" /** * diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index 0d6441c5ce00..a826e4bf2928 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -53,18 +53,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the task management substate handlers for the - * SCIC_SDS_IO_REQUEST object. - * - * - */ - #include "intel_sas.h" -#include "sci_environment.h" -#include "scic_sds_request.h" +#include "sci_base_state_machine.h" #include "scic_controller.h" #include "scic_sds_controller.h" +#include "scic_sds_request.h" +#include "sci_environment.h" #include "scu_completion_codes.h" #include "scu_task_context.h" @@ -220,72 +214,6 @@ const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started } }; -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains the enter/exit methods associated with each of the task - * management raw request states. For more information on the task - * management request state machine please refer to scic_sds_io_request.h - * - * - */ - -#include "scic_sds_request.h" -#include "sci_base_state_machine.h" - /** * This method performs the actions required when entering the * SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index 6aa170e92500..0060804a2402 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -53,22 +53,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the ready substate handlers for an STP device. - * - * - */ - -#include "intel_sat.h" #include "intel_ata.h" #include "intel_sata.h" -#include "sci_environment.h" +#include "intel_sat.h" +#include "sci_base_state.h" #include "scic_remote_device.h" -#include "scic_user_callback.h" #include "scic_sds_controller.h" #include "scic_sds_port.h" #include "scic_sds_remote_device.h" #include "scic_sds_request.h" +#include "scic_user_callback.h" +#include "sci_environment.h" +#include "sci_util.h" #include "scu_event_codes.h" /** @@ -654,70 +650,6 @@ const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_rea } }; -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "sci_base_state.h" -#include "scic_remote_device.h" -#include "scic_user_callback.h" -#include "scic_sds_controller.h" -#include "scic_sds_port.h" -#include "scic_sds_remote_device.h" -#include "sci_util.h" -#include "sci_environment.h" - /* * ***************************************************************************** * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS -- cgit v1.2.3 From 27d42e3e794523c3cec02a17fb221ade00e98648 Mon Sep 17 00:00:00 2001 From: Henryk Dembkowski Date: Sat, 12 Feb 2011 11:50:13 -0800 Subject: isci: coding style changes for remote device Change names from upper to low letters Signed-off-by: Henryk Dembkowski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_remote_device.h | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/isci/core/sci_base_remote_device.h b/drivers/scsi/isci/core/sci_base_remote_device.h index 25c6ddd4fdbe..45414ce6a2c6 100644 --- a/drivers/scsi/isci/core/sci_base_remote_device.h +++ b/drivers/scsi/isci/core/sci_base_remote_device.h @@ -153,16 +153,16 @@ struct sci_base_remote_device { }; -typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HANDLER_T)( +typedef enum sci_status (*sci_base_remote_device_handler_t)( struct sci_base_remote_device * ); -typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T)( +typedef enum sci_status (*sci_base_remote_device_request_handler_t)( struct sci_base_remote_device *, struct sci_base_request * ); -typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T)( +typedef enum sci_status (*sci_base_remote_device_high_priority_request_complete_handler_t)( struct sci_base_remote_device *, struct sci_base_request *, void *, @@ -182,68 +182,68 @@ struct sci_base_remote_device_state_handler { * The start_handler specifies the method invoked when a user attempts to * start a remote device. */ - SCI_BASE_REMOTE_DEVICE_HANDLER_T start_handler; + sci_base_remote_device_handler_t start_handler; /** * The stop_handler specifies the method invoked when a user attempts to * stop a remote device. */ - SCI_BASE_REMOTE_DEVICE_HANDLER_T stop_handler; + sci_base_remote_device_handler_t stop_handler; /** * The fail_handler specifies the method invoked when a remote device * failure has occurred. A failure may be due to an inability to * initialize/configure the device. */ - SCI_BASE_REMOTE_DEVICE_HANDLER_T fail_handler; + sci_base_remote_device_handler_t fail_handler; /** * The destruct_handler specifies the method invoked when attempting to * destruct a remote device. */ - SCI_BASE_REMOTE_DEVICE_HANDLER_T destruct_handler; + sci_base_remote_device_handler_t destruct_handler; /** * The reset handler specifies the method invloked when requesting to reset a * remote device. */ - SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_handler; + sci_base_remote_device_handler_t reset_handler; /** * The reset complete handler specifies the method invloked when reporting * that a reset has completed to the remote device. */ - SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_complete_handler; + sci_base_remote_device_handler_t reset_complete_handler; /** * The start_io_handler specifies the method invoked when a user * attempts to start an IO request for a remote device. */ - SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_io_handler; + sci_base_remote_device_request_handler_t start_io_handler; /** * The complete_io_handler specifies the method invoked when a user * attempts to complete an IO request for a remote device. */ - SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_io_handler; + sci_base_remote_device_request_handler_t complete_io_handler; /** * The continue_io_handler specifies the method invoked when a user * attempts to continue an IO request for a remote device. */ - SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T continue_io_handler; + sci_base_remote_device_request_handler_t continue_io_handler; /** * The start_task_handler specifies the method invoked when a user * attempts to start a task management request for a remote device. */ - SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_task_handler; + sci_base_remote_device_request_handler_t start_task_handler; /** * The complete_task_handler specifies the method invoked when a user * attempts to complete a task management request for a remote device. */ - SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_task_handler; + sci_base_remote_device_request_handler_t complete_task_handler; }; -- cgit v1.2.3 From f7d36e1872c0d79ea9e31445c3b1b70602dbac4b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 12 Feb 2011 11:50:15 -0800 Subject: isci: kill a callback cast Callbacks are already type unsafe, obfuscating things further by casting the callback routine is less safe because now function argument number changes will not be caught by the compiler. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_remote_device.c | 15 ++++++++------- drivers/scsi/isci/core/scic_sds_remote_device.h | 3 +-- drivers/scsi/isci/core/scic_sds_stp_remote_device.c | 1 - 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 5fc1baaa56d0..643247f46a7e 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -583,19 +583,20 @@ void scic_sds_remote_device_start_request( * serves as a callback when RNC gets resumed during a task management * sequence. none */ -void scic_sds_remote_device_continue_request( - struct scic_sds_remote_device *this_device) +void scic_sds_remote_device_continue_request(void *dev) { + struct scic_sds_remote_device *sci_dev = dev; + struct scic_sds_request *sci_req = sci_dev->working_request; + /* we need to check if this request is still valid to continue. */ - if (this_device->working_request != NULL) { - struct scic_sds_request *this_request = this_device->working_request; - struct scic_sds_controller *scic = this_request->owning_controller; + if (sci_req) { + struct scic_sds_controller *scic = sci_req->owning_controller; u32 state = scic->parent.state_machine.current_state_id; sci_base_controller_request_handler_t continue_io; continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; - continue_io(&scic->parent, &this_request->target_device->parent, - &this_request->parent); + continue_io(&scic->parent, &sci_req->target_device->parent, + &sci_req->parent); } } diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index d91570f212c6..4841e4579643 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -509,8 +509,7 @@ void scic_sds_remote_device_start_request( struct scic_sds_request *the_request, enum sci_status status); -void scic_sds_remote_device_continue_request( - struct scic_sds_remote_device *this_device); +void scic_sds_remote_device_continue_request(void *sci_dev); enum sci_status scic_sds_remote_device_default_start_handler( struct sci_base_remote_device *this_device); diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index 0060804a2402..880e0e5932c0 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -188,7 +188,6 @@ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_h scic_sds_remote_node_context_resume( this_device->rnc, - (scics_sds_remote_node_context_callback) scic_sds_remote_device_continue_request, this_device); } -- cgit v1.2.3 From 11c88986290712fc3ae6993af85a0f9a15886278 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Feb 2011 15:01:46 -0800 Subject: isci: remove SCIC_DEBUG_ENABLED, and fixup an odd macro This will be replaced by state machine tracepoints and should have been a part of the logger removal. Ran across scic_sds_port_decrement_request_count() which is an ugly macro which silently hides accounting errors. Turn it into a WARN_ONCE to see if it ever triggers. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_phy.c | 99 ---------------------------------- drivers/scsi/isci/core/scic_sds_phy.h | 23 -------- drivers/scsi/isci/core/scic_sds_port.c | 13 ----- drivers/scsi/isci/core/scic_sds_port.h | 48 ++++++----------- 4 files changed, 15 insertions(+), 168 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 01da46ae270a..d9213e215beb 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -267,101 +267,6 @@ static void scic_sds_phy_sata_timeout(void *phy) ); } -/* - * ***************************************************************************** - * * SCIC SDS PHY External Methods - * ***************************************************************************** */ - -/** - * This method returns the object size for a phy object. - * - * u32 - */ - -/** - * This method returns the minimum number of timers required for a phy object. - * - * u32 - */ - -/** - * This method returns the maximum number of timers required for a phy object. - * - * u32 - */ - -#ifdef SCIC_DEBUG_ENABLED -/** - * scic_sds_phy_observe_state_change() - - * @our_observer: - * - * Debug code to record the state transitions in the phy - */ -void scic_sds_phy_observe_state_change( - struct sci_base_observer *our_observer, - struct sci_base_subject *the_subject) -{ - struct scic_sds_phy *this_phy; - struct sci_base_state_machine *the_state_machine; - - u8 transition_requestor; - u32 base_state_id; - u32 starting_substate_id; - - the_state_machine = (struct sci_base_state_machine *)the_subject; - this_phy = (struct scic_sds_phy *)the_state_machine->state_machine_owner; - - if (the_state_machine == &this_phy->parent.state_machine) { - transition_requestor = 0x01; - } else if (the_state_machine == &this_phy->starting_substate_machine) { - transition_requestor = 0x02; - } else { - transition_requestor = 0xFF; - } - - base_state_id = - sci_base_state_machine_get_state(&this_phy->parent.state_machine); - starting_substate_id = - sci_base_state_machine_get_state(&this_phy->starting_substate_machine); - - this_phy->state_record.state_transition_table[ - this_phy->state_record.index++] = ((transition_requestor << 24) - | ((u8)base_state_id << 8) - | ((u8)starting_substate_id)); - - this_phy->state_record.index = - this_phy->state_record.index & (MAX_STATE_TRANSITION_RECORD - 1); - -} -#endif /* SCIC_DEBUG_ENABLED */ - -#ifdef SCIC_DEBUG_ENABLED -/** - * scic_sds_phy_initialize_state_recording() - - * - * This method initializes the state record debug information for the phy - * object. The state machines for the phy object must be constructed before - * this function is called. - */ -void scic_sds_phy_initialize_state_recording( - struct scic_sds_phy *this_phy) -{ - this_phy->state_record.index = 0; - - sci_base_observer_initialize( - &this_phy->state_record.base_state_observer, - scic_sds_phy_observe_state_change, - &this_phy->parent.state_machine.parent - ); - - sci_base_observer_initialize( - &this_phy->state_record.starting_state_observer, - scic_sds_phy_observe_state_change, - &this_phy->starting_substate_machine.parent - ); -} -#endif /* SCIC_DEBUG_ENABLED */ - /** * This method will construct the struct scic_sds_phy object * @this_phy: @@ -400,10 +305,6 @@ void scic_sds_phy_construct( scic_sds_phy_starting_substates, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL ); - - #ifdef SCIC_DEBUG_ENABLED - scic_sds_phy_initialize_state_recording(this_phy); - #endif /* SCIC_DEBUG_ENABLED */ } /** diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index d9691b30e457..3b88259d7c87 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -156,25 +156,6 @@ enum SCIC_SDS_PHY_STARTING_SUBSTATES { struct scic_sds_port; struct scic_sds_controller; -#ifdef SCIC_DEBUG_ENABLED -#define MAX_STATE_TRANSITION_RECORD (256) - -/** - * - * - * Debug code to record the state transitions for the phy object - */ -struct scic_sds_phy_state_record { - struct sci_base_observer base_state_observer; - struct sci_base_observer starting_state_observer; - - u16 index; - - u32 state_transition_table[MAX_STATE_TRANSITION_RECORD]; - -}; -#endif /* SCIC_DEBUG_ENABLED */ - /** * This enumeration provides a named phy type for the state machine * @@ -271,10 +252,6 @@ struct scic_sds_phy { struct sci_base_state_machine starting_substate_machine; - #ifdef SCIC_DEBUG_ENABLED - struct scic_sds_phy_state_record state_record; - #endif /* SCIC_DEBUG_ENABLED */ - /** * This field points to the link layer register set within the SCU. */ diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 9749e3abbf8e..ff06f8cb15b8 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -974,19 +974,6 @@ static void scic_sds_port_timeout_handler(void *port) /* --------------------------------------------------------------------------- */ -#ifdef SCIC_DEBUG_ENABLED -void scic_sds_port_decrement_request_count(struct scic_sds_port *this_port) -{ - if (this_port->started_request_count == 0) - dev_warn(sciport_to_dev(this_port), - __func__, - "%s: SCIC Port object requested to decrement started " - "io count past zero.\n"); - else - this_port->started_request_count--; -} -#endif - /** * This function updates the hardwares VIIT entry for this port. * diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index bbb9de5228ed..56c15fcbeb8d 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -63,6 +63,7 @@ * */ +#include #include "sci_controller_constants.h" #include "intel_sas.h" #include "sci_base_port.h" @@ -286,40 +287,21 @@ extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_t #define scic_sds_port_get_index(this_port) \ ((this_port)->physical_port_index) -/** - * scic_sds_port_increment_request_count() - - * - * Helper macro to increment the started request count - */ -#define scic_sds_port_increment_request_count(this_port) \ - ((this_port)->started_request_count++) -#ifdef SCIC_DEBUG_ENABLED -/** - * scic_sds_port_decrement_request_count() - This method decrements the started - * io request count. The method will not decrment the started io request - * count below 0 and will log a debug message if this is attempted. - * - * - */ -void scic_sds_port_decrement_request_count( - struct scic_sds_port *this_port); -#else -/** - * scic_sds_port_decrement_request_count() - - * - * Helper macro to decrement the started io request count. The macro will not - * decrement the started io request count below 0. - */ -#define scic_sds_port_decrement_request_count(this_port) \ - (\ - (this_port)->started_request_count = (\ - ((this_port)->started_request_count == 0) ? \ - (this_port)->started_request_count : \ - ((this_port)->started_request_count - 1) \ - ) \ - ) -#endif +static inline void scic_sds_port_increment_request_count(struct scic_sds_port *sci_port) +{ + sci_port->started_request_count++; +} + +static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) +{ + if (WARN_ONCE(sci_port->started_request_count == 0, + "%s: tried to decrement started_request_count past 0!?", + __func__)) + /* pass */; + else + sci_port->started_request_count--; +} /** * scic_sds_port_write_phy_assignment() - -- cgit v1.2.3 From c7ef4031f01301298bbaba2666740183cd399f8c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Feb 2011 09:25:05 -0800 Subject: isci: bypass scic_controller_get_handler_methods() The indirection is unecessary and broken in the current case that assigns the handlers based on a not up-to-date pdev->msix_enabled value. Route the handlers directly to the requisite core routines. Todo: hook up error interrupt handling Reported-by: Jeff Garzik Cc: Christoph Hellwig Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 10 +- drivers/scsi/isci/host.c | 158 ++++++--------------------- drivers/scsi/isci/host.h | 12 -- drivers/scsi/isci/init.c | 4 +- drivers/scsi/isci/isci.h | 7 +- 5 files changed, 45 insertions(+), 146 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 6a32d91742b5..cd8017f048c1 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1898,8 +1898,7 @@ static void scic_sds_controller_single_vector_completion_handler( * * bool true if an interrupt is processed false if no interrupt was processed */ -static bool scic_sds_controller_normal_vector_interrupt_handler( - struct scic_sds_controller *scic) +bool scic_sds_controller_isr(struct scic_sds_controller *scic) { if (scic_sds_controller_completion_queue_has_entries(scic)) { return true; @@ -1925,8 +1924,7 @@ static bool scic_sds_controller_normal_vector_interrupt_handler( * This is the method provided to handle the completions for a normal MSIX * message. */ -static void scic_sds_controller_normal_vector_completion_handler( - struct scic_sds_controller *scic) +void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) { /* Empty out the completion queue */ if (scic_sds_controller_completion_queue_has_entries(scic)) @@ -2582,9 +2580,9 @@ enum sci_status scic_controller_get_handler_methods( status = SCI_SUCCESS; } else if (message_count == 2) { handler_methods[0].interrupt_handler - = scic_sds_controller_normal_vector_interrupt_handler; + = scic_sds_controller_isr; handler_methods[0].completion_handler - = scic_sds_controller_normal_vector_completion_handler; + = scic_sds_controller_completion_handler; handler_methods[1].interrupt_handler = scic_sds_controller_error_vector_interrupt_handler; diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 6f16f4d6c82b..b66e62027247 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -62,80 +62,49 @@ #include "request.h" #include "host.h" -/** - * isci_isr() - This function is the interrupt service routine for the - * controller. It schedules the tasklet and returns. - * @vec: This parameter specifies the interrupt vector. - * @data: This parameter specifies the ISCI host object. - * - * IRQ_HANDLED if out interrupt otherwise, IRQ_NONE - */ -irqreturn_t isci_isr(int vec, void *data) +irqreturn_t isci_msix_isr(int vec, void *data) { - struct isci_host *isci_host - = (struct isci_host *)data; - struct scic_controller_handler_methods *handlers - = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; - irqreturn_t ret = IRQ_NONE; - - if (isci_host_get_state(isci_host) != isci_starting - && handlers->interrupt_handler) { - - if (handlers->interrupt_handler(isci_host->core_controller)) { - if (isci_host_get_state(isci_host) != isci_stopped) { - tasklet_schedule( - &isci_host->completion_tasklet); - } else - dev_dbg(&isci_host->pdev->dev, - "%s: controller stopped\n", - __func__); - ret = IRQ_HANDLED; + struct isci_host *ihost = data; + struct scic_sds_controller *scic = ihost->core_controller; + + if (isci_host_get_state(ihost) != isci_starting) { + if (scic_sds_controller_isr(scic)) { + if (isci_host_get_state(ihost) != isci_stopped) + tasklet_schedule(&ihost->completion_tasklet); + else + dev_dbg(&ihost->pdev->dev, + "%s: controller stopped\n", __func__); } - } else - dev_warn(&isci_host->pdev->dev, - "%s: get_handler_methods failed, " - "isci_host->status = 0x%x\n", - __func__, - isci_host_get_state(isci_host)); + } - return ret; + return IRQ_HANDLED; } -irqreturn_t isci_legacy_isr(int vec, void *data) +irqreturn_t isci_intx_isr(int vec, void *data) { struct pci_dev *pdev = data; - struct isci_host *isci_host; - struct scic_controller_handler_methods *handlers; + struct isci_host *ihost; irqreturn_t ret = IRQ_NONE; - /* - * Since this is a legacy interrupt, either or both - * controllers could have triggered it. Thus, we have to call - * the legacy interrupt handler for all controllers on the - * PCI function. - */ - for_each_isci_host(isci_host, pdev) { - handlers = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; - - if (isci_host_get_state(isci_host) != isci_starting - && handlers->interrupt_handler) { - - if (handlers->interrupt_handler(isci_host->core_controller)) { - if (isci_host_get_state(isci_host) != isci_stopped) { - tasklet_schedule( - &isci_host->completion_tasklet); - } else - dev_dbg(&isci_host->pdev->dev, + for_each_isci_host(ihost, pdev) { + struct scic_sds_controller *scic = ihost->core_controller; + + if (isci_host_get_state(ihost) != isci_starting) { + if (scic_sds_controller_isr(scic)) { + if (isci_host_get_state(ihost) != isci_stopped) + tasklet_schedule(&ihost->completion_tasklet); + else + dev_dbg(&ihost->pdev->dev, "%s: controller stopped\n", __func__); ret = IRQ_HANDLED; } } else - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: get_handler_methods failed, " - "isci_host->status = 0x%x\n", + "ihost->status = 0x%x\n", __func__, - isci_host_get_state(isci_host)); + isci_host_get_state(ihost)); } return ret; } @@ -166,34 +135,9 @@ void isci_host_start_complete( } - - -/** - * isci_host_scan_finished() - This function is one of the SCSI Host Template - * functions. The SCSI midlayer calls this function during a target scan, - * approx. once every 10 millisecs. - * @shost: This parameter specifies the SCSI host being scanned - * @time: This parameter specifies the number of ticks since the scan started. - * - * scan status, zero indicates the SCSI midlayer should continue to poll, - * otherwise assume controller is ready. - */ -int isci_host_scan_finished( - struct Scsi_Host *shost, - unsigned long time) +int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) { - struct isci_host *isci_host - = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); - - struct scic_controller_handler_methods *handlers - = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; - - if (handlers->interrupt_handler == NULL) { - dev_err(&isci_host->pdev->dev, - "%s: scic_controller_get_handler_methods failed\n", - __func__); - return 1; - } + struct isci_host *isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); /** * check interrupt_handler's status and call completion_handler if true, @@ -204,8 +148,8 @@ int isci_host_scan_finished( * continue to return zero from thee scan_finished routine until * the scic_cb_controller_start_complete() call comes from the core. **/ - if (handlers->interrupt_handler(isci_host->core_controller)) - handlers->completion_handler(isci_host->core_controller); + if (scic_sds_controller_isr(isci_host->core_controller)) + scic_sds_controller_completion_handler(isci_host->core_controller); if (isci_starting == isci_host_get_state(isci_host) && time < (HZ * 10)) { @@ -363,8 +307,6 @@ static int isci_host_mdl_allocate_coherent( static void isci_host_completion_routine(unsigned long data) { struct isci_host *isci_host = (struct isci_host *)data; - struct scic_controller_handler_methods *handlers - = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; struct list_head completed_request_list; struct list_head aborted_request_list; struct list_head *current_position; @@ -378,11 +320,8 @@ static void isci_host_completion_routine(unsigned long data) spin_lock_irq(&isci_host->scic_lock); - if (handlers->completion_handler) { - handlers->completion_handler( - isci_host->core_controller - ); - } + scic_sds_controller_completion_handler(isci_host->core_controller); + /* Take the lists of completed I/Os from the host. */ list_splice_init(&isci_host->requests_to_complete, &completed_request_list); @@ -544,8 +483,6 @@ int isci_host_init(struct isci_host *isci_host) enum sci_status status; struct scic_sds_controller *controller; struct scic_sds_port *scic_port; - struct scic_controller_handler_methods *handlers - = &isci_host->scic_irq_handlers[0]; union scic_oem_parameters scic_oem_params; union scic_user_parameters scic_user_params; const struct firmware *fw = NULL; @@ -691,35 +628,8 @@ int isci_host_init(struct isci_host *isci_host) goto out; } - /* @todo: use both MSI-X interrupts, and don't do indirect - * calls to the handlers just register direct calls - */ - if (isci_host->pdev->msix_enabled) { - status = scic_controller_get_handler_methods( - SCIC_MSIX_INTERRUPT_TYPE, - SCI_MSIX_DOUBLE_VECTOR, - handlers - ); - } else { - status = scic_controller_get_handler_methods( - SCIC_LEGACY_LINE_INTERRUPT_TYPE, - 0, - handlers - ); - } - - if (status != SCI_SUCCESS) { - handlers->interrupt_handler = NULL; - handlers->completion_handler = NULL; - dev_err(&isci_host->pdev->dev, - "%s: scic_controller_get_handler_methods failed\n", - __func__); - } - tasklet_init(&isci_host->completion_tasklet, - isci_host_completion_routine, - (unsigned long)isci_host - ); + isci_host_completion_routine, (unsigned long)isci_host); INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 4f4b99d29589..421d3debdaed 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -53,13 +53,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the isci_module initialization routines. - * - * host.h - */ - - #if !defined(_SCI_HOST_H_) #define _SCI_HOST_H_ @@ -79,10 +72,6 @@ #define SCI_SCU_BAR_SIZE (4*1024*1024) #define SCI_IO_SPACE_BAR0 2 #define SCI_IO_SPACE_BAR1 3 -#define SCI_MSIX_NORMAL_VECTOR 0 -#define SCI_MSIX_ERROR_VECTOR 1 -#define SCI_MSIX_SINGLE_VECTOR 1 -#define SCI_MSIX_DOUBLE_VECTOR 2 #define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */ #define SCIC_CONTROLLER_STOP_TIMEOUT 5000 @@ -96,7 +85,6 @@ struct coherent_memory_info { struct isci_host { struct scic_sds_controller *core_controller; - struct scic_controller_handler_methods scic_irq_handlers[SCI_NUM_MSI_X_INT]; union scic_oem_parameters oem_parameters; int id; /* unique within a given pci device */ diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index e3d9b15d0cbf..f2bd92b81136 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -334,7 +334,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev) BUG_ON(!isci_host); /* @todo: need to handle error case. */ - err = devm_request_irq(&pdev->dev, msix->vector, isci_isr, 0, + err = devm_request_irq(&pdev->dev, msix->vector, isci_msix_isr, 0, DRV_NAME"-msix", isci_host); if (!err) continue; @@ -353,7 +353,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev) return 0; intx: - err = devm_request_irq(&pdev->dev, pdev->irq, isci_legacy_isr, + err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr, IRQF_SHARED, DRV_NAME"-intx", pdev); return err; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 6aee3c9c8827..3dc0f6c21174 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -113,8 +113,11 @@ struct isci_firmware { u8 sas_addrs_size; }; -irqreturn_t isci_isr(int vec, void *data); -irqreturn_t isci_legacy_isr(int vec, void *data); +irqreturn_t isci_msix_isr(int vec, void *data); +irqreturn_t isci_intx_isr(int vec, void *data); + +bool scic_sds_controller_isr(struct scic_sds_controller *scic); +void scic_sds_controller_completion_handler(struct scic_sds_controller *scic); enum sci_status isci_parse_oem_parameters( union scic_oem_parameters *oem_params, -- cgit v1.2.3 From 0cf89d1d27c1bdd0abf1714096f98ea44704dcff Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Feb 2011 09:25:07 -0800 Subject: isci: cleanup "starting" state handling The lldd actively disallows requests in the "starting" state. Retrying or holding off commands in this state is sub-optimal: 1/ it adds another state check to the fast path 2/ retrying can cause libsas to give up However, isci's ->lldd_dev_found() routine already waits for controller start to complete before allowing further progress. Checking the "starting" state in isci_task_execute_task and the isr is redundant and misleading. Clean this up and introduce a controller-wide event queue to start reeling in "completion" proliferation in the driver. The "stopping" state cleanups are in a similar vein, rely on the the isr and other paths being precluded from occurring rather than implementing state checking logic. Reported-by: Christoph Hellwig Cc: Jeff Garzik Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 145 +++++++++++++------------------------- drivers/scsi/isci/host.h | 17 ++++- drivers/scsi/isci/remote_device.c | 4 +- drivers/scsi/isci/task.c | 3 +- 4 files changed, 67 insertions(+), 102 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index b66e62027247..dbdc3bab9ca3 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -67,15 +67,8 @@ irqreturn_t isci_msix_isr(int vec, void *data) struct isci_host *ihost = data; struct scic_sds_controller *scic = ihost->core_controller; - if (isci_host_get_state(ihost) != isci_starting) { - if (scic_sds_controller_isr(scic)) { - if (isci_host_get_state(ihost) != isci_stopped) - tasklet_schedule(&ihost->completion_tasklet); - else - dev_dbg(&ihost->pdev->dev, - "%s: controller stopped\n", __func__); - } - } + if (scic_sds_controller_isr(scic)) + tasklet_schedule(&ihost->completion_tasklet); return IRQ_HANDLED; } @@ -89,22 +82,10 @@ irqreturn_t isci_intx_isr(int vec, void *data) for_each_isci_host(ihost, pdev) { struct scic_sds_controller *scic = ihost->core_controller; - if (isci_host_get_state(ihost) != isci_starting) { - if (scic_sds_controller_isr(scic)) { - if (isci_host_get_state(ihost) != isci_stopped) - tasklet_schedule(&ihost->completion_tasklet); - else - dev_dbg(&ihost->pdev->dev, - "%s: controller stopped\n", - __func__); - ret = IRQ_HANDLED; - } - } else - dev_warn(&ihost->pdev->dev, - "%s: get_handler_methods failed, " - "ihost->status = 0x%x\n", - __func__, - isci_host_get_state(ihost)); + if (scic_sds_controller_isr(scic)) { + tasklet_schedule(&ihost->completion_tasklet); + ret = IRQ_HANDLED; + } } return ret; } @@ -118,26 +99,19 @@ irqreturn_t isci_intx_isr(int vec, void *data) * core library. * */ -void isci_host_start_complete( - struct isci_host *isci_host, - enum sci_status completion_status) +void isci_host_start_complete(struct isci_host *ihost, enum sci_status completion_status) { - if (completion_status == SCI_SUCCESS) { - dev_dbg(&isci_host->pdev->dev, - "%s: completion_status: SCI_SUCCESS\n", __func__); - isci_host_change_state(isci_host, isci_ready); - complete_all(&isci_host->start_complete); - } else - dev_err(&isci_host->pdev->dev, - "controller start failed with " - "completion_status = 0x%x;", - completion_status); - + if (completion_status != SCI_SUCCESS) + dev_info(&ihost->pdev->dev, + "controller start timed out, continuing...\n"); + isci_host_change_state(ihost, isci_ready); + clear_bit(IHOST_START_PENDING, &ihost->flags); + wake_up(&ihost->eventq); } int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) { - struct isci_host *isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); + struct isci_host *ihost = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); /** * check interrupt_handler's status and call completion_handler if true, @@ -148,61 +122,44 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) * continue to return zero from thee scan_finished routine until * the scic_cb_controller_start_complete() call comes from the core. **/ - if (scic_sds_controller_isr(isci_host->core_controller)) - scic_sds_controller_completion_handler(isci_host->core_controller); + if (scic_sds_controller_isr(ihost->core_controller)) + scic_sds_controller_completion_handler(ihost->core_controller); - if (isci_starting == isci_host_get_state(isci_host) - && time < (HZ * 10)) { - dev_dbg(&isci_host->pdev->dev, - "%s: isci_host->status = %d, time = %ld\n", - __func__, isci_host_get_state(isci_host), time); + if (test_bit(IHOST_START_PENDING, &ihost->flags) && time < HZ*10) { + dev_dbg(&ihost->pdev->dev, + "%s: ihost->status = %d, time = %ld\n", + __func__, isci_host_get_state(ihost), time); return 0; } - dev_dbg(&isci_host->pdev->dev, - "%s: isci_host->status = %d, time = %ld\n", - __func__, isci_host_get_state(isci_host), time); + dev_dbg(&ihost->pdev->dev, + "%s: ihost->status = %d, time = %ld\n", + __func__, isci_host_get_state(ihost), time); - scic_controller_enable_interrupts(isci_host->core_controller); + scic_controller_enable_interrupts(ihost->core_controller); return 1; } - -/** - * isci_host_scan_start() - This function is one of the SCSI Host Template - * function, called by the SCSI mid layer berfore a target scan begins. The - * core library controller start routine is called from here. - * @shost: This parameter specifies the SCSI host to be scanned - * - */ void isci_host_scan_start(struct Scsi_Host *shost) { - struct isci_host *isci_host; - - isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); - isci_host_change_state(isci_host, isci_starting); + struct isci_host *ihost = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); + struct scic_sds_controller *scic = ihost->core_controller; + unsigned long tmo = scic_controller_get_suggested_start_timeout(scic); - scic_controller_disable_interrupts(isci_host->core_controller); - init_completion(&isci_host->start_complete); - scic_controller_start( - isci_host->core_controller, - scic_controller_get_suggested_start_timeout( - isci_host->core_controller) - ); + set_bit(IHOST_START_PENDING, &ihost->flags); + scic_controller_disable_interrupts(ihost->core_controller); + scic_controller_start(scic, tmo); } -void isci_host_stop_complete( - struct isci_host *isci_host, - enum sci_status completion_status) +void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) { - isci_host_change_state(isci_host, isci_stopped); - scic_controller_disable_interrupts( - isci_host->core_controller - ); - complete(&isci_host->stop_complete); + isci_host_change_state(ihost, isci_stopped); + scic_controller_disable_interrupts(ihost->core_controller); + clear_bit(IHOST_STOP_PENDING, &ihost->flags); + wake_up(&ihost->eventq); } static struct coherent_memory_info *isci_host_alloc_mdl_struct( @@ -370,31 +327,26 @@ static void isci_host_completion_routine(unsigned long data) } -void isci_host_deinit( - struct isci_host *isci_host) +void isci_host_deinit(struct isci_host *ihost) { + struct scic_sds_controller *scic = ihost->core_controller; int i; - isci_host_change_state(isci_host, isci_stopping); + isci_host_change_state(ihost, isci_stopping); for (i = 0; i < SCI_MAX_PORTS; i++) { - struct isci_port *port = &isci_host->isci_ports[i]; - struct isci_remote_device *device, *tmpdev; - list_for_each_entry_safe(device, tmpdev, - &port->remote_dev_list, node) { - isci_remote_device_change_state(device, isci_stopping); - isci_remote_device_stop(device); + struct isci_port *port = &ihost->isci_ports[i]; + struct isci_remote_device *idev, *d; + + list_for_each_entry_safe(idev, d, &port->remote_dev_list, node) { + isci_remote_device_change_state(idev, isci_stopping); + isci_remote_device_stop(idev); } } - /* stop the comtroller and wait for completion. */ - init_completion(&isci_host->stop_complete); - scic_controller_stop( - isci_host->core_controller, - SCIC_CONTROLLER_STOP_TIMEOUT - ); - wait_for_completion(&isci_host->stop_complete); - /* next, reset the controller. */ - scic_controller_reset(isci_host->core_controller); + set_bit(IHOST_STOP_PENDING, &ihost->flags); + scic_controller_stop(scic, SCIC_CONTROLLER_STOP_TIMEOUT); + wait_for_stop(ihost); + scic_controller_reset(scic); } static int isci_verify_firmware(const struct firmware *fw, @@ -506,6 +458,7 @@ int isci_host_init(struct isci_host *isci_host) spin_lock_init(&isci_host->state_lock); spin_lock_init(&isci_host->scic_lock); spin_lock_init(&isci_host->queue_lock); + init_waitqueue_head(&isci_host->eventq); isci_host_change_state(isci_host, isci_starting); isci_host->can_queue = ISCI_CAN_QUEUE_VAL; diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 421d3debdaed..26768c5bbe01 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -109,13 +109,15 @@ struct isci_host { u8 sas_addr[SAS_ADDR_SIZE]; enum isci_status status; + #define IHOST_START_PENDING 0 + #define IHOST_STOP_PENDING 1 + unsigned long flags; + wait_queue_head_t eventq; struct Scsi_Host *shost; struct tasklet_struct completion_tasklet; struct list_head mdl_struct_list; struct list_head requests_to_complete; struct list_head requests_to_abort; - struct completion stop_complete; - struct completion start_complete; spinlock_t scic_lock; struct isci_host *next; }; @@ -202,6 +204,17 @@ static inline void isci_host_can_dequeue( spin_unlock_irqrestore(&isci_host->queue_lock, flags); } +static inline void wait_for_start(struct isci_host *ihost) +{ + wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags)); +} + +static inline void wait_for_stop(struct isci_host *ihost) +{ + wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags)); +} + + /** * isci_host_from_sas_ha() - This accessor retrieves the isci_host object * reference from the Linux sas_ha_struct reference. diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index dbf3c82f6195..936f22957e5b 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -507,6 +507,8 @@ int isci_remote_device_found(struct domain_device *domain_dev) dev_dbg(&isci_host->pdev->dev, "%s: domain_device = %p\n", __func__, domain_dev); + wait_for_start(isci_host); + sas_port = domain_dev->port; sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy, port_phy_el); @@ -560,8 +562,6 @@ int isci_remote_device_found(struct domain_device *domain_dev) return -ENODEV; } - wait_for_completion(&isci_host->start_complete); - return 0; } /** diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 5e6f55863407..6f98f6c74efb 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -164,8 +164,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) * for the quiesce spinlock. */ - if (isci_host_get_state(isci_host) == isci_starting || - (device && ((isci_remote_device_get_state(device) == isci_ready) || + if ((device && ((isci_remote_device_get_state(device) == isci_ready) || (isci_remote_device_get_state(device) == isci_host_quiesce)))) { /* Forces a retry from scsi mid layer. */ -- cgit v1.2.3 From 77950f51f5299c1b4f4fa4a19974128da720d199 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Fri, 18 Feb 2011 09:25:09 -0800 Subject: isci: enable interrupts during controller start, and flush discovery Polling the event queue during scan is an unneeded holdover from the original driver. Signed-off-by: Edmund Nadolski [djbw: ensure we flush all port events and domain discovery] Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index dbdc3bab9ca3..7f351a35e87b 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -113,32 +113,18 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) { struct isci_host *ihost = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); - /** - * check interrupt_handler's status and call completion_handler if true, - * link_up events should be coming from the scu core lib, as phy's come - * online. for each link_up from the core, call - * get_received_identify_address_frame, copy the frame into the - * sas_phy object and call libsas notify_port_event(PORTE_BYTES_DMAED). - * continue to return zero from thee scan_finished routine until - * the scic_cb_controller_start_complete() call comes from the core. - **/ - if (scic_sds_controller_isr(ihost->core_controller)) - scic_sds_controller_completion_handler(ihost->core_controller); - - if (test_bit(IHOST_START_PENDING, &ihost->flags) && time < HZ*10) { - dev_dbg(&ihost->pdev->dev, - "%s: ihost->status = %d, time = %ld\n", - __func__, isci_host_get_state(ihost), time); + if (test_bit(IHOST_START_PENDING, &ihost->flags)) return 0; - } + /* todo: use sas_flush_discovery once it is upstream */ + scsi_flush_work(shost); + + scsi_flush_work(shost); dev_dbg(&ihost->pdev->dev, "%s: ihost->status = %d, time = %ld\n", __func__, isci_host_get_state(ihost), time); - scic_controller_enable_interrupts(ihost->core_controller); - return 1; } @@ -150,8 +136,11 @@ void isci_host_scan_start(struct Scsi_Host *shost) unsigned long tmo = scic_controller_get_suggested_start_timeout(scic); set_bit(IHOST_START_PENDING, &ihost->flags); - scic_controller_disable_interrupts(ihost->core_controller); + + spin_lock_irq(&ihost->scic_lock); scic_controller_start(scic, tmo); + scic_controller_enable_interrupts(scic); + spin_unlock_irq(&ihost->scic_lock); } void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) -- cgit v1.2.3 From 92f4f0f544a6a75979bace0c43fee9c4fb95830c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Feb 2011 09:25:11 -0800 Subject: isci: implement error isr Add basic support for handling/reporting error interrupts. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 26 ++++++-------------------- drivers/scsi/isci/host.c | 16 ++++++++++++++++ drivers/scsi/isci/init.c | 10 ++++++++-- drivers/scsi/isci/isci.h | 3 +++ 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index cd8017f048c1..7ea36624f568 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1937,18 +1937,12 @@ void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) SMU_IMR_WRITE(scic, 0x00000000); } -/** - * This is the method provided to handle the error MSIX message interrupt. - * This is the normal operating mode for the hardware if MSIX is enabled. - * - * bool true if an interrupt is processed false if no interrupt was processed - */ -static bool scic_sds_controller_error_vector_interrupt_handler( - struct scic_sds_controller *scic) +bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) { u32 interrupt_status; interrupt_status = SMU_ISR_READ(scic); + interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); if (interrupt_status != 0) { @@ -1970,12 +1964,7 @@ static bool scic_sds_controller_error_vector_interrupt_handler( return false; } -/** - * This is the method provided to handle the error completions when the - * hardware is using two MSIX messages. - */ -static void scic_sds_controller_error_vector_completion_handler( - struct scic_sds_controller *scic) +void scic_sds_controller_error_handler(struct scic_sds_controller *scic) { u32 interrupt_status; @@ -1988,10 +1977,7 @@ static void scic_sds_controller_error_vector_completion_handler( SMU_ISR_WRITE(scic, SMU_ISR_QUEUE_SUSPEND); } else { - dev_err(scic_to_dev(scic), - "%s: SCIC Controller reports CRC error on completion " - "ISR %x\n", - __func__, + dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, interrupt_status); sci_base_state_machine_change_state( @@ -2585,9 +2571,9 @@ enum sci_status scic_controller_get_handler_methods( = scic_sds_controller_completion_handler; handler_methods[1].interrupt_handler - = scic_sds_controller_error_vector_interrupt_handler; + = scic_sds_controller_error_isr; handler_methods[1].completion_handler - = scic_sds_controller_error_vector_completion_handler; + = scic_sds_controller_error_handler; status = SCI_SUCCESS; } diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 7f351a35e87b..cb2e3f9558e9 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -85,11 +85,27 @@ irqreturn_t isci_intx_isr(int vec, void *data) if (scic_sds_controller_isr(scic)) { tasklet_schedule(&ihost->completion_tasklet); ret = IRQ_HANDLED; + } else if (scic_sds_controller_error_isr(scic)) { + spin_lock(&ihost->scic_lock); + scic_sds_controller_error_handler(scic); + spin_unlock(&ihost->scic_lock); + ret = IRQ_HANDLED; } } + return ret; } +irqreturn_t isci_error_isr(int vec, void *data) +{ + struct isci_host *ihost = data; + struct scic_sds_controller *scic = ihost->core_controller; + + if (scic_sds_controller_error_isr(scic)) + scic_sds_controller_error_handler(scic); + + return IRQ_HANDLED; +} /** * isci_host_start_complete() - This function is called by the core library, diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index f2bd92b81136..4d6decb6d08c 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -330,11 +330,17 @@ static int isci_setup_interrupts(struct pci_dev *pdev) int id = i / SCI_NUM_MSI_X_INT; struct msix_entry *msix = &pci_info->msix_entries[i]; struct isci_host *isci_host = isci_host_by_id(pdev, id); + irq_handler_t isr; + + /* odd numbered vectors are error interrupts */ + if (i & 1) + isr = isci_error_isr; + else + isr = isci_msix_isr; BUG_ON(!isci_host); - /* @todo: need to handle error case. */ - err = devm_request_irq(&pdev->dev, msix->vector, isci_msix_isr, 0, + err = devm_request_irq(&pdev->dev, msix->vector, isr, 0, DRV_NAME"-msix", isci_host); if (!err) continue; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 3dc0f6c21174..39efd5f27200 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -115,9 +115,12 @@ struct isci_firmware { irqreturn_t isci_msix_isr(int vec, void *data); irqreturn_t isci_intx_isr(int vec, void *data); +irqreturn_t isci_error_isr(int vec, void *data); bool scic_sds_controller_isr(struct scic_sds_controller *scic); void scic_sds_controller_completion_handler(struct scic_sds_controller *scic); +bool scic_sds_controller_error_isr(struct scic_sds_controller *scic); +void scic_sds_controller_error_handler(struct scic_sds_controller *scic); enum sci_status isci_parse_oem_parameters( union scic_oem_parameters *oem_params, -- cgit v1.2.3 From 83e514301ec73b16fb258618c9f9b443cca3744a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Feb 2011 09:25:13 -0800 Subject: isci: advertise linkrate Inform libsas of the linkrate of direct attached links. Reported-by: Haavard Skinnemoen Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_phy.h | 3 +++ drivers/scsi/isci/core/scic_sds_phy.c | 5 +++++ drivers/scsi/isci/port.c | 2 ++ 3 files changed, 10 insertions(+) diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 13f8a304fdef..bf0d3be58eda 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -72,6 +72,9 @@ struct scic_sds_phy; struct scic_sds_port; + +enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy); + /** * struct scic_phy_properties - This structure defines the properties common to * all phys that can be retrieved. diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index d9213e215beb..743e5a6b7409 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -73,6 +73,11 @@ /* Maximum arbitration wait time in micro-seconds */ #define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) +enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy) +{ + return sci_phy->max_negotiated_speed; +} + /* * ***************************************************************************** * * SCIC SDS PHY Internal Methods diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 2343f6556428..446da20521c9 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -263,6 +263,8 @@ void isci_port_link_up( success = false; } + isci_phy->sas_phy.phy->negotiated_linkrate = sci_phy_linkrate(phy); + spin_unlock_irqrestore(&isci_phy->sas_phy.frame_rcvd_lock, flags); /* Notify libsas that we have an address frame, if indeed -- cgit v1.2.3 From 83f5eeef59581faed6f002432bafe24da8cbf401 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Feb 2011 09:25:15 -0800 Subject: isci: debug fixes Some of the chain walks to get back to our dev are invalid. isci_remote_device_change_state: delete rather than adding conditional deref chain walking isci_request_change_state: fix, it was being called too early isci_request_ssp_io_request_get_lun: fix compile breakage hidden by ifdef DEBUG Signed-off-by: Maciej Trela Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 6 ------ drivers/scsi/isci/request.c | 6 +++--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 936f22957e5b..dec9033d674d 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -686,12 +686,6 @@ void isci_remote_device_change_state( { unsigned long flags; - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, - "%s: isci_device = %p, state = 0x%x", - __func__, - isci_device, - status); - spin_lock_irqsave(&isci_device->state_lock, flags); isci_device->status = status; spin_unlock_irqrestore(&isci_device->state_lock, flags); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index f7ba047d64ce..81a77335fdb3 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -285,7 +285,6 @@ static int isci_request_alloc_core( /* initialize the request object. */ spin_lock_init(&request->state_lock); - isci_request_change_state(request, allocated); request->sci_request_mem_ptr = ((u8 *)request) + sizeof(struct isci_request); request->request_daddr = handle; @@ -302,6 +301,7 @@ static int isci_request_alloc_core( INIT_LIST_HEAD(&request->dev_node); *isci_request = request; + isci_request_change_state(request, allocated); return ret; } @@ -1389,8 +1389,8 @@ u32 isci_request_ssp_io_request_get_lun( for (i = 0; i < 8; i++) dev_dbg(&request->isci_host->pdev->dev, - "%s: request->task->ssp_task.LUN[%d] = %x\n", - __func__, i, request->task->ssp_task.LUN[i]); + "%s: task->ssp_task.LUN[%d] = %x\n", + __func__, i, task->ssp_task.LUN[i]); #endif -- cgit v1.2.3 From 5d147e73836723b81fd72b078e78887598999d5a Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Fri, 18 Feb 2011 09:25:17 -0800 Subject: isci: remove scic_controller_get_handler_methods and ilk This removes scic_controller_get_handler_methods and its associated unused code. Signed-off-by: Edmund Nadolski [djbw: kill off the legacy handler, now that we have basic error isr support] Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_controller.h | 97 ------- drivers/scsi/isci/core/scic_sds_controller.c | 412 --------------------------- drivers/scsi/isci/core/scic_sds_controller.h | 13 - drivers/scsi/isci/core/scic_user_callback.h | 5 +- 4 files changed, 2 insertions(+), 525 deletions(-) diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 1d459d6af21b..481e0de5148b 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -80,62 +80,6 @@ enum sci_controller_mode { }; -/** - * enum _SCIC_INTERRUPT_TYPE - This enumeration depicts the various types of - * interrupts that are potentially supported by a SCI Core implementation. - * - * - */ -enum scic_interrupt_type { - SCIC_LEGACY_LINE_INTERRUPT_TYPE, - SCIC_MSIX_INTERRUPT_TYPE, - - /** - * This enumeration value indicates the use of polling. - */ - SCIC_NO_INTERRUPTS - -}; - -/** - * This method is called by the SCI user in order to have the SCI - * implementation handle the interrupt. This method performs minimal - * processing to allow for streamlined interrupt time usage. - * - * SCIC_CONTROLLER_INTERRUPT_HANDLER true: returned if there is an interrupt to - * process and it was processed. false: returned if no interrupt was processed. - */ -typedef bool (*SCIC_CONTROLLER_INTERRUPT_HANDLER)( - struct scic_sds_controller *controller - ); - -/** - * This method is called by the SCI user to process completions generated as a - * result of a previously handled interrupt. This method will result in the - * completion of IO requests and handling of other controller generated - * events. This method should be called some time after the interrupt - * handler. - * - * Most, if not all, of the user callback APIs are invoked from within this - * API. As a result, the user should be cognizent of the operating level at - * which they invoke this API. - */ -typedef void (*SCIC_CONTROLLER_COMPLETION_HANDLER)( - struct scic_sds_controller *controller - ); - -/** - * struct scic_controller_handler_methods - This structure contains an - * interrupt handler and completion handler function pointers. - * - * - */ -struct scic_controller_handler_methods { - SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler; - SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler; - -}; - /** * scic_controller_construct() - This method will attempt to construct a * controller object utilizing the supplied parameter information. @@ -176,47 +120,6 @@ void scic_controller_enable_interrupts( void scic_controller_disable_interrupts( struct scic_sds_controller *controller); -/** - * scic_controller_get_handler_methods() - This method will return provide - * function pointers for the interrupt handler and completion handler. The - * interrupt handler is expected to be invoked at interrupt time. The - * completion handler is scheduled to run as a result of the interrupt - * handler. The completion handler performs the bulk work for processing - * silicon events. - * @interrupt_type: This parameter informs the core which type of - * interrupt/completion methods are being requested. These are the types: - * SCIC_LEGACY_LINE_INTERRUPT_TYPE, SCIC_MSIX_INTERRUPT_TYPE, - * SCIC_NO_INTERRUPTS (POLLING) - * @message_count: This parameter informs the core the number of MSI-X messages - * to be utilized. This parameter must be 0 when requesting legacy line - * based handlers. - * @handler_methods: The caller provides a pointer to a buffer of type - * struct scic_controller_handler_methods. The size depends on the combination of - * the interrupt_type and message_count input parameters: - * SCIC_LEGACY_LINE_INTERRUPT_TYPE: - size = - * sizeof(struct scic_controller_handler_methods) SCIC_MSIX_INTERRUPT_TYPE: - * sizeof(struct scic_controller_handler_methods) - * @handler_methods: SCIC fills out the caller's buffer with the appropriate - * interrupt and completion handlers based on the info provided in the - * interrupt_type and message_count input parameters. For - * SCIC_LEGACY_LINE_INTERRUPT_TYPE, the buffer receives a single - * struct scic_controller_handler_methods element regardless that the - * message_count parameter is zero. For SCIC_MSIX_INTERRUPT_TYPE, the buffer - * receives an array of elements of type struct scic_controller_handler_methods - * where the array size is equivalent to the message_count parameter. The - * array is zero-relative where entry zero corresponds to message-vector - * zero, entry one corresponds to message-vector one, and so forth. - * - * Indicate if the handler retrieval operation was successful. SCI_SUCCESS This - * value is returned if retrieval succeeded. - * SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT This value is returned if the user - * supplied an unsupported number of MSI-X messages. For legacy line interrupts - * the only valid value is 0. - */ -enum sci_status scic_controller_get_handler_methods( - enum scic_interrupt_type interrupt_type, - u16 message_count, - struct scic_controller_handler_methods *handler_methods); /** * scic_controller_initialize() - This method will initialize the controller diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 7ea36624f568..53861ccbd593 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1564,340 +1564,6 @@ static void scic_sds_controller_process_completions( } -/** - * This method is a private routine for processing the completion queue entries. - * @this_controller: - * - */ -static void scic_sds_controller_transitioned_process_completions( - struct scic_sds_controller *this_controller) -{ - u32 completion_count = 0; - u32 completion_entry; - u32 get_index; - u32 get_cycle; - u32 event_index; - u32 event_cycle; - - dev_dbg(scic_to_dev(this_controller), - "%s: completion queue begining get:0x%08x\n", - __func__, - this_controller->completion_queue_get); - - /* Get the component parts of the completion queue */ - get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get); - get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get; - - event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get); - event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get; - - while ( - NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) - == COMPLETION_QUEUE_CYCLE_BIT( - this_controller->completion_queue[get_index]) - ) { - completion_count++; - - completion_entry = this_controller->completion_queue[get_index]; - INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle); - - dev_dbg(scic_to_dev(this_controller), - "%s: completion queue entry:0x%08x\n", - __func__, - completion_entry); - - switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { - case SCU_COMPLETION_TYPE_TASK: - scic_sds_controller_task_completion(this_controller, completion_entry); - break; - - case SCU_COMPLETION_TYPE_NOTIFY: - case SCU_COMPLETION_TYPE_EVENT: - /* - * Presently we do the same thing with a notify event that we - * do with the other event codes. */ - INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); - /* Fall-through */ - - case SCU_COMPLETION_TYPE_SDMA: - case SCU_COMPLETION_TYPE_UFI: - default: - dev_warn(scic_to_dev(this_controller), - "%s: SCIC Controller ignoring completion type " - "%x\n", - __func__, - completion_entry); - break; - } - } - - /* Update the get register if we completed one or more entries */ - if (completion_count > 0) { - this_controller->completion_queue_get = - SMU_CQGR_GEN_BIT(ENABLE) - | SMU_CQGR_GEN_BIT(EVENT_ENABLE) - | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) - | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); - - SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get); - } - - dev_dbg(scic_to_dev(this_controller), - "%s: completion queue ending get:0x%08x\n", - __func__, - this_controller->completion_queue_get); -} - -/* - * ****************************************************************************- - * * SCIC SDS Controller Interrupt and Completion functions - * ****************************************************************************- */ - -/** - * This method provides standard (common) processing of interrupts for polling - * and legacy based interrupts. - * @controller: - * @interrupt_status: - * - * This method returns a boolean (bool) indication as to whether an completions - * are pending to be processed. true if an interrupt is to be processed false - * if no interrupt was pending - */ -static bool scic_sds_controller_standard_interrupt_handler( - struct scic_sds_controller *this_controller, - u32 interrupt_status) -{ - bool is_completion_needed = false; - - if ((interrupt_status & SMU_ISR_QUEUE_ERROR) || - ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && - (!scic_sds_controller_completion_queue_has_entries( - this_controller)))) { - /* - * We have a fatal error on the read of the completion queue bar - * OR - * We have a fatal error there is nothing in the completion queue - * but we have a report from the hardware that the queue is full - * / @todo how do we request the a controller reset */ - is_completion_needed = true; - this_controller->encountered_fatal_error = true; - } - - if (scic_sds_controller_completion_queue_has_entries(this_controller)) { - is_completion_needed = true; - } - - return is_completion_needed; -} - -/** - * This is the method provided to handle polling for interrupts for the - * controller object. - * - * bool true if an interrupt is to be processed false if no interrupt was - * pending - */ -static bool scic_sds_controller_polling_interrupt_handler( - struct scic_sds_controller *scic) -{ - u32 interrupt_status; - - /* - * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the - * hardware indicates nothing is pending. Since we are not being - * called from a real interrupt, we don't want to confuse the hardware - * by servicing the completion queue before the hardware indicates it - * is ready. We'll simply wait for another polling interval and check - * again. - */ - interrupt_status = SMU_ISR_READ(scic); - if ((interrupt_status & - (SMU_ISR_COMPLETION | - SMU_ISR_QUEUE_ERROR | - SMU_ISR_QUEUE_SUSPEND)) == 0) { - return false; - } - - return scic_sds_controller_standard_interrupt_handler( - scic, interrupt_status); -} - -/** - * This is the method provided to handle completions when interrupt polling is - * in use. - */ -static void scic_sds_controller_polling_completion_handler( - struct scic_sds_controller *scic) -{ - if (scic->encountered_fatal_error == true) { - dev_err(scic_to_dev(scic), - "%s: SCIC Controller has encountered a fatal error.\n", - __func__); - - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); - } else if (scic_sds_controller_completion_queue_has_entries(scic)) { - if (scic->restrict_completions == false) - scic_sds_controller_process_completions(scic); - else - scic_sds_controller_transitioned_process_completions( - scic); - } - - /* - * The interrupt handler does not adjust the CQ's - * get pointer. So, SCU's INTx pin stays asserted during the - * interrupt handler even though it tries to clear the interrupt - * source. Therefore, the completion handler must ensure that the - * interrupt source is cleared. Otherwise, we get a spurious - * interrupt for which the interrupt handler will not issue a - * corresponding completion event. Also, we unmask interrupts. - */ - SMU_ISR_WRITE( - scic, - (u32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND) - ); -} - -/** - * This is the method provided to handle legacy interrupts for the controller - * object. - * - * bool true if an interrupt is processed false if no interrupt was processed - */ -static bool scic_sds_controller_legacy_interrupt_handler( - struct scic_sds_controller *scic) -{ - u32 interrupt_status; - bool is_completion_needed; - - interrupt_status = SMU_ISR_READ(scic); - is_completion_needed = scic_sds_controller_standard_interrupt_handler( - scic, interrupt_status); - - return is_completion_needed; -} - - -/** - * This is the method provided to handle legacy completions it is expected that - * the SCI User will call this completion handler anytime the interrupt - * handler reports that it has handled an interrupt. - */ -static void scic_sds_controller_legacy_completion_handler( - struct scic_sds_controller *scic) -{ - scic_sds_controller_polling_completion_handler(scic); - SMU_IMR_WRITE(scic, 0x00000000); -} - -/** - * This is the method provided to handle an MSIX interrupt message when there - * is just a single MSIX message being provided by the hardware. This mode - * of operation is single vector mode. - * - * bool true if an interrupt is processed false if no interrupt was processed - */ -static bool scic_sds_controller_single_vector_interrupt_handler( - struct scic_sds_controller *scic) -{ - u32 interrupt_status; - - /* - * Mask the interrupts - * There is a race in the hardware that could cause us not to be notified - * of an interrupt completion if we do not take this step. We will unmask - * the interrupts in the completion routine. */ - SMU_IMR_WRITE(scic, 0xFFFFFFFF); - - interrupt_status = SMU_ISR_READ(scic); - interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); - - if ((interrupt_status == 0) && - scic_sds_controller_completion_queue_has_entries(scic)) { - /* - * There is at least one completion queue entry to process so we can - * return a success and ignore for now the case of an error interrupt */ - SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); - return true; - } - - if (interrupt_status != 0) { - /* - * There is an error interrupt pending so let it through and handle - * in the callback */ - return true; - } - - /* - * Clear any offending interrupts since we could not find any to handle - * and unmask them all */ - SMU_ISR_WRITE(scic, 0x00000000); - SMU_IMR_WRITE(scic, 0x00000000); - - return false; -} - -/** - * This is the method provided to handle completions for a single MSIX message. - */ -static void scic_sds_controller_single_vector_completion_handler( - struct scic_sds_controller *scic) -{ - u32 interrupt_status; - - interrupt_status = SMU_ISR_READ(scic); - interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); - - if (interrupt_status & SMU_ISR_QUEUE_ERROR) { - dev_err(scic_to_dev(scic), - "%s: SCIC Controller has encountered a fatal error.\n", - __func__); - - /* - * We have a fatal condition and must reset the controller - * Leave the interrupt mask in place and get the controller reset */ - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); - return; - } - - if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && - !scic_sds_controller_completion_queue_has_entries(scic)) { - dev_err(scic_to_dev(scic), - "%s: SCIC Controller has encountered a fatal error.\n", - __func__); - - /* - * We have a fatal condtion and must reset the controller - * Leave the interrupt mask in place and get the controller reset */ - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); - return; - } - - if (scic_sds_controller_completion_queue_has_entries(scic)) { - scic_sds_controller_process_completions(scic); - - /* - * We dont care which interrupt got us to processing the completion queu - * so clear them both. */ - SMU_ISR_WRITE( - scic, - (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)); - } - - SMU_IMR_WRITE(scic, 0x00000000); -} - -/** - * This is the method provided to handle a MSIX message for a normal completion. - * - * bool true if an interrupt is processed false if no interrupt was processed - */ bool scic_sds_controller_isr(struct scic_sds_controller *scic) { if (scic_sds_controller_completion_queue_has_entries(scic)) { @@ -1920,10 +1586,6 @@ bool scic_sds_controller_isr(struct scic_sds_controller *scic) return false; } -/** - * This is the method provided to handle the completions for a normal MSIX - * message. - */ void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) { /* Empty out the completion queue */ @@ -1994,14 +1656,6 @@ void scic_sds_controller_error_handler(struct scic_sds_controller *scic) } -/* - * ****************************************************************************- - * * SCIC SDS Controller External Methods - * ****************************************************************************- */ - -/** - * This method returns the sizeof the SCIC SDS Controller Object - */ u32 scic_sds_controller_get_object_size(void) { return sizeof(struct scic_sds_controller); @@ -2535,72 +2189,6 @@ enum sci_status scic_controller_reset( return status; } -/* --------------------------------------------------------------------------- */ - -enum sci_status scic_controller_get_handler_methods( - enum scic_interrupt_type interrupt_type, - u16 message_count, - struct scic_controller_handler_methods *handler_methods) -{ - enum sci_status status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT; - - switch (interrupt_type) { - case SCIC_LEGACY_LINE_INTERRUPT_TYPE: - if (message_count == 0) { - handler_methods[0].interrupt_handler - = scic_sds_controller_legacy_interrupt_handler; - handler_methods[0].completion_handler - = scic_sds_controller_legacy_completion_handler; - - status = SCI_SUCCESS; - } - break; - - case SCIC_MSIX_INTERRUPT_TYPE: - if (message_count == 1) { - handler_methods[0].interrupt_handler - = scic_sds_controller_single_vector_interrupt_handler; - handler_methods[0].completion_handler - = scic_sds_controller_single_vector_completion_handler; - - status = SCI_SUCCESS; - } else if (message_count == 2) { - handler_methods[0].interrupt_handler - = scic_sds_controller_isr; - handler_methods[0].completion_handler - = scic_sds_controller_completion_handler; - - handler_methods[1].interrupt_handler - = scic_sds_controller_error_isr; - handler_methods[1].completion_handler - = scic_sds_controller_error_handler; - - status = SCI_SUCCESS; - } - break; - - case SCIC_NO_INTERRUPTS: - if (message_count == 0) { - - handler_methods[0].interrupt_handler - = scic_sds_controller_polling_interrupt_handler; - handler_methods[0].completion_handler - = scic_sds_controller_polling_completion_handler; - - status = SCI_SUCCESS; - } - break; - - default: - status = SCI_FAILURE_INVALID_PARAMETER_VALUE; - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - enum sci_io_status scic_controller_start_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index cce0da6a6a3d..3e0477d62a5b 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -335,19 +335,6 @@ struct scic_sds_controller { */ struct scic_sds_unsolicited_frame_control uf_control; - /** - * This field records the fact that the controller has encountered a fatal - * error and must be reset. - */ - bool encountered_fatal_error; - - /** - * This field specifies that the controller should ignore - * completion processing for non-fastpath events. This will - * cause the completions to be thrown away. - */ - bool restrict_completions; - /* Phy Startup Data */ /** * This field is the driver timer handle for controller phy request startup. diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h index ec4eb278cd5f..d1a3cb885bc7 100644 --- a/drivers/scsi/isci/core/scic_user_callback.h +++ b/drivers/scsi/isci/core/scic_user_callback.h @@ -86,9 +86,8 @@ struct scic_sds_controller; * occurs for the created timer. * * The "timer_callback" method should be executed in a mutually exlusive manner - * from the controller completion handler handler (refer to - * scic_controller_get_handler_methods()). This method returns a handle to a - * timer object created by the user. The handle will be utilized for all + * from the controller completion handler handler. This method returns a handle + * to a timer object created by the user. The handle will be utilized for all * further interactions relating to this timer. */ void *scic_cb_timer_create( -- cgit v1.2.3 From 92cd51153d5c18af027ddf42547d59ba4167873c Mon Sep 17 00:00:00 2001 From: Havard Skinnemoen Date: Fri, 18 Feb 2011 18:32:08 -0800 Subject: isci: Initialize proc_name field in scsi_host_template The proc_name field in struct scsi_host_template is exported through sysfs and allows userspace tools to identify the driver behind a particular SCSI host controller. Initialize this field so that userspace tools can easily identify isci host controllers through sysfs. Signed-off-by: Havard Skinnemoen Signed-off-by: Dan Williams --- drivers/scsi/isci/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 4d6decb6d08c..fda26292ba2b 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -113,6 +113,7 @@ static struct scsi_host_template isci_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .proc_name = DRV_NAME, .queuecommand = sas_queuecommand, .target_alloc = sas_target_alloc, .slave_configure = sas_slave_configure, -- cgit v1.2.3 From 858d4aa741c80fb7579cda3517853f0cffc73772 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 22 Feb 2011 01:27:03 -0800 Subject: isci: Move firmware loading to per PCI device Moved the firmware loading from per adapter to per PCI device. This should prevent firmware from being loaded twice becuase of 2 SCU controller per PCI device. We do have to do it per PCI device because request_firmware() requires a struct device passed in. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 201 ++++++++++------------------------------------- drivers/scsi/isci/init.c | 91 +++++++++++++++++++++ drivers/scsi/isci/isci.h | 1 + 3 files changed, 134 insertions(+), 159 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index cb2e3f9558e9..aa86615fa7a9 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -354,67 +354,6 @@ void isci_host_deinit(struct isci_host *ihost) scic_controller_reset(scic); } -static int isci_verify_firmware(const struct firmware *fw, - struct isci_firmware *isci_fw) -{ - const u8 *tmp; - - if (fw->size < ISCI_FIRMWARE_MIN_SIZE) - return -EINVAL; - - tmp = fw->data; - - /* 12th char should be the NULL terminate for the ID string */ - if (tmp[11] != '\0') - return -EINVAL; - - if (strncmp("#SCU MAGIC#", tmp, 11) != 0) - return -EINVAL; - - isci_fw->id = tmp; - isci_fw->version = fw->data[ISCI_FW_VER_OFS]; - isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS]; - - tmp = fw->data + ISCI_FW_DATA_OFS; - - while (*tmp != ISCI_FW_HDR_EOF) { - switch (*tmp) { - case ISCI_FW_HDR_PHYMASK: - tmp++; - isci_fw->phy_masks_size = *tmp; - tmp++; - isci_fw->phy_masks = (const u32 *)tmp; - tmp += sizeof(u32) * isci_fw->phy_masks_size; - break; - - case ISCI_FW_HDR_PHYGEN: - tmp++; - isci_fw->phy_gens_size = *tmp; - tmp++; - isci_fw->phy_gens = (const u32 *)tmp; - tmp += sizeof(u32) * isci_fw->phy_gens_size; - break; - - case ISCI_FW_HDR_SASADDR: - tmp++; - isci_fw->sas_addrs_size = *tmp; - tmp++; - isci_fw->sas_addrs = (const u64 *)tmp; - tmp += sizeof(u64) * isci_fw->sas_addrs_size; - break; - - default: - pr_err("bad field in firmware binary blob\n"); - return -EINVAL; - } - } - - pr_info("isci firmware v%u.%u loaded.\n", - isci_fw->version, isci_fw->subversion); - - return SCI_SUCCESS; -} - static void __iomem *scu_base(struct isci_host *isci_host) { struct pci_dev *pdev = isci_host->pdev; @@ -442,8 +381,6 @@ int isci_host_init(struct isci_host *isci_host) struct scic_sds_port *scic_port; union scic_oem_parameters scic_oem_params; union scic_user_parameters scic_user_params; - const struct firmware *fw = NULL; - struct isci_firmware *isci_fw = NULL; INIT_LIST_HEAD(&isci_host->timer_list_struct.timers); isci_timer_list_construct( @@ -454,9 +391,11 @@ int isci_host_init(struct isci_host *isci_host) controller = scic_controller_alloc(&isci_host->pdev->dev); if (!controller) { - err = -ENOMEM; - dev_err(&isci_host->pdev->dev, "%s: failed (%d)\n", __func__, err); - goto out; + dev_err(&isci_host->pdev->dev, + "%s: failed (%d)\n", + __func__, + err); + return -ENOMEM; } isci_host->core_controller = controller; @@ -476,8 +415,7 @@ int isci_host_init(struct isci_host *isci_host) "%s: scic_controller_construct failed - status = %x\n", __func__, status); - err = -ENODEV; - goto out; + return -ENODEV; } isci_host->sas_ha.dev = &isci_host->pdev->dev; @@ -487,93 +425,52 @@ int isci_host_init(struct isci_host *isci_host) * set association host adapter struct in core controller. */ sci_object_set_association(isci_host->core_controller, - (void *)isci_host - ); + (void *)isci_host); /* grab initial values stored in the controller object for OEM and USER * parameters */ scic_oem_parameters_get(controller, &scic_oem_params); scic_user_parameters_get(controller, &scic_user_params); - isci_fw = devm_kzalloc(&isci_host->pdev->dev, - sizeof(struct isci_firmware), - GFP_KERNEL); - if (!isci_fw) { - dev_warn(&isci_host->pdev->dev, - "allocating firmware struct failed\n"); - dev_warn(&isci_host->pdev->dev, - "Default OEM configuration being used:" - " 4 narrow ports, and default SAS Addresses\n"); - goto set_default_params; - } - - status = request_firmware(&fw, ISCI_FW_NAME, &isci_host->pdev->dev); - if (status) { - dev_warn(&isci_host->pdev->dev, - "Loading firmware failed, using default values\n"); - dev_warn(&isci_host->pdev->dev, - "Default OEM configuration being used:" - " 4 narrow ports, and default SAS Addresses\n"); - goto set_default_params; - } - else { - status = isci_verify_firmware(fw, isci_fw); - if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, - "firmware verification failed\n"); - dev_warn(&isci_host->pdev->dev, - "Default OEM configuration being used:" - " 4 narrow ports, and default SAS " - "Addresses\n"); - goto set_default_params; - } - - /* grab any OEM and USER parameters specified at module load */ + if (isci_firmware) { + /* grab any OEM and USER parameters specified in binary blob */ status = isci_parse_oem_parameters(&scic_oem_params, - isci_host->id, isci_fw); + isci_host->id, + isci_firmware); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, "parsing firmware oem parameters failed\n"); - err = -EINVAL; - goto out; + return -EINVAL; } status = isci_parse_user_parameters(&scic_user_params, - isci_host->id, isci_fw); + isci_host->id, + isci_firmware); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, "%s: isci_parse_user_parameters" " failed\n", __func__); - err = -EINVAL; - goto out; + return -EINVAL; + } + } else { + status = scic_oem_parameters_set(isci_host->core_controller, + &scic_oem_params); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: scic_oem_parameters_set failed\n", + __func__); + return -ENODEV; } - } - - set_default_params: - - status = scic_oem_parameters_set(isci_host->core_controller, - &scic_oem_params - ); - - if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, - "%s: scic_oem_parameters_set failed\n", - __func__); - err = -ENODEV; - goto out; - } - - status = scic_user_parameters_set(isci_host->core_controller, - &scic_user_params - ); - if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, - "%s: scic_user_parameters_set failed\n", - __func__); - err = -ENODEV; - goto out; + status = scic_user_parameters_set(isci_host->core_controller, + &scic_user_params); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: scic_user_parameters_set failed\n", + __func__); + return -ENODEV; + } } status = scic_controller_initialize(isci_host->core_controller); @@ -582,8 +479,7 @@ int isci_host_init(struct isci_host *isci_host) "%s: scic_controller_initialize failed -" " status = 0x%x\n", __func__, status); - err = -ENODEV; - goto out; + return -ENODEV; } tasklet_init(&isci_host->completion_tasklet, @@ -598,7 +494,7 @@ int isci_host_init(struct isci_host *isci_host) err = isci_host_mdl_allocate_coherent(isci_host); if (err) - goto err_out; + return err; /* * keep the pool alloc size around, will use it for a bounds checking @@ -610,40 +506,27 @@ int isci_host_init(struct isci_host *isci_host) isci_host->dma_pool_alloc_size, SLAB_HWCACHE_ALIGN, 0); - if (!isci_host->dma_pool) { - err = -ENOMEM; - goto req_obj_err_out; - } + if (!isci_host->dma_pool) + return -ENOMEM; - for (index = 0; index < SCI_MAX_PORTS; index++) { + for (index = 0; index < SCI_MAX_PORTS; index++) isci_port_init(&isci_host->isci_ports[index], - isci_host, index); - } + isci_host, + index); for (index = 0; index < SCI_MAX_PHYS; index++) isci_phy_init(&isci_host->phys[index], isci_host, index); /* Why are we doing this? Is this even necessary? */ - memcpy(&isci_host->sas_addr[0], &isci_host->phys[0].sas_addr[0], + memcpy(&isci_host->sas_addr[0], + &isci_host->phys[0].sas_addr[0], SAS_ADDR_SIZE); /* Start the ports */ for (index = 0; index < SCI_MAX_PORTS; index++) { - scic_controller_get_port_handle(controller, index, &scic_port); scic_port_start(scic_port); } - goto out; - -/* SPB_Debug: destroy request object cache */ - req_obj_err_out: -/* SPB_Debug: destroy remote object cache */ - err_out: -/* SPB_Debug: undo controller init, construct and alloc, remove from parent - * controller list. */ - out: - if (fw) - release_firmware(fw); - return err; + return 0; } diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index fda26292ba2b..6ca623aff051 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -82,6 +82,8 @@ static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { {} }; +struct isci_firmware *isci_firmware; + static int __devinit isci_pci_probe( struct pci_dev *pdev, const struct pci_device_id *device_id_p); @@ -519,11 +521,73 @@ static void check_si_rev(struct pci_dev *pdev) } +static int isci_verify_firmware(const struct firmware *fw, + struct isci_firmware *isci_fw) +{ + const u8 *tmp; + + if (fw->size < ISCI_FIRMWARE_MIN_SIZE) + return -EINVAL; + + tmp = fw->data; + + /* 12th char should be the NULL terminate for the ID string */ + if (tmp[11] != '\0') + return -EINVAL; + + if (strncmp("#SCU MAGIC#", tmp, 11) != 0) + return -EINVAL; + + isci_fw->id = tmp; + isci_fw->version = fw->data[ISCI_FW_VER_OFS]; + isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS]; + + tmp = fw->data + ISCI_FW_DATA_OFS; + + while (*tmp != ISCI_FW_HDR_EOF) { + switch (*tmp) { + case ISCI_FW_HDR_PHYMASK: + tmp++; + isci_fw->phy_masks_size = *tmp; + tmp++; + isci_fw->phy_masks = (const u32 *)tmp; + tmp += sizeof(u32) * isci_fw->phy_masks_size; + break; + + case ISCI_FW_HDR_PHYGEN: + tmp++; + isci_fw->phy_gens_size = *tmp; + tmp++; + isci_fw->phy_gens = (const u32 *)tmp; + tmp += sizeof(u32) * isci_fw->phy_gens_size; + break; + + case ISCI_FW_HDR_SASADDR: + tmp++; + isci_fw->sas_addrs_size = *tmp; + tmp++; + isci_fw->sas_addrs = (const u64 *)tmp; + tmp += sizeof(u64) * isci_fw->sas_addrs_size; + break; + + default: + pr_err("bad field in firmware binary blob\n"); + return -EINVAL; + } + } + + pr_info("isci firmware v%u.%u loaded.\n", + isci_fw->version, isci_fw->subversion); + + return SCI_SUCCESS; +} + static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct isci_pci_info *pci_info; int err, i; struct isci_host *isci_host; + const struct firmware *fw = NULL; check_si_rev(pdev); @@ -532,6 +596,33 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic return -ENOMEM; pci_set_drvdata(pdev, pci_info); + err = request_firmware(&fw, ISCI_FW_NAME, &pdev->dev); + if (err) { + dev_warn(&pdev->dev, + "Loading firmware failed, using default values\n"); + dev_warn(&pdev->dev, + "Default OEM configuration being used:" + " 4 narrow ports, and default SAS Addresses\n"); + } else { + isci_firmware = devm_kzalloc(&pdev->dev, + sizeof(struct isci_firmware), + GFP_KERNEL); + if (isci_firmware) { + err = isci_verify_firmware(fw, isci_firmware); + if (err != SCI_SUCCESS) { + dev_warn(&pdev->dev, + "firmware verification failed\n"); + dev_warn(&pdev->dev, + "Default OEM configuration being used:" + " 4 narrow ports, and default SAS " + "Addresses\n"); + devm_kfree(&pdev->dev, isci_firmware); + isci_firmware = NULL; + } + } + release_firmware(fw); + } + err = isci_pci_init(pdev); if (err) return err; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 39efd5f27200..6c79b29f3102 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -86,6 +86,7 @@ #include "sci_status.h" extern struct kmem_cache *isci_kmem_cache; +extern struct isci_firmware *isci_firmware; #define ISCI_FW_NAME "isci/isci_firmware.bin" -- cgit v1.2.3 From 8f31550c77849250ec49d1509b6bb63b4ddc59e4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Feb 2011 00:14:06 -0800 Subject: isci: phy state machine cleanup step1 c99 the struct initializers: 1/ allows grep to consistently show method name associations. The naming is mostly consistent (except when it isn't) so this guarantees coverage of present and future exception cases. 2/ let's the compiler guarantee that the state table array entry correlates with an actual state name and detect accidental reordering or deletion of states. / allows default handler's to be identified easily Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_phy.h | 15 +- drivers/scsi/isci/core/scic_sds_phy.c | 314 ++++++++++++++-------------------- drivers/scsi/isci/core/scic_sds_phy.h | 24 +-- 3 files changed, 145 insertions(+), 208 deletions(-) diff --git a/drivers/scsi/isci/core/sci_base_phy.h b/drivers/scsi/isci/core/sci_base_phy.h index 6c0d9bbbc95f..7e2c7e331437 100644 --- a/drivers/scsi/isci/core/sci_base_phy.h +++ b/drivers/scsi/isci/core/sci_base_phy.h @@ -115,9 +115,6 @@ enum sci_base_phy_states { * Simply the final state for the base phy state machine. */ SCI_BASE_PHY_STATE_FINAL, - - SCI_BASE_PHY_MAX_STATES - }; /** @@ -138,9 +135,7 @@ struct sci_base_phy { struct sci_base_state_machine state_machine; }; -typedef enum sci_status (*SCI_BASE_PHY_HANDLER_T)( - struct sci_base_phy * - ); +typedef enum sci_status (*sci_base_phy_handler_t)(struct sci_base_phy *); /** * struct sci_base_phy_state_handler - This structure contains all of the state @@ -155,25 +150,25 @@ struct sci_base_phy_state_handler { * The start_handler specifies the method invoked when there is an * attempt to start a phy. */ - SCI_BASE_PHY_HANDLER_T start_handler; + sci_base_phy_handler_t start_handler; /** * The stop_handler specifies the method invoked when there is an * attempt to stop a phy. */ - SCI_BASE_PHY_HANDLER_T stop_handler; + sci_base_phy_handler_t stop_handler; /** * The reset_handler specifies the method invoked when there is an * attempt to reset a phy. */ - SCI_BASE_PHY_HANDLER_T reset_handler; + sci_base_phy_handler_t reset_handler; /** * The destruct_handler specifies the method invoked when attempting to * destruct a phy. */ - SCI_BASE_PHY_HANDLER_T destruct_handler; + sci_base_phy_handler_t destruct_handler; }; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 743e5a6b7409..98e9179e227c 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -103,7 +103,7 @@ static enum sci_status scic_sds_phy_link_layer_initialization( this_phy->link_layer_registers = link_layer_registers; /* Set our IDENTIFY frame data */ - #define SCI_END_DEVICE 0x01 + #define SCI_END_DEVICE 0x01 SCU_SAS_TIID_WRITE( this_phy, @@ -1406,128 +1406,96 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_p /* --------------------------------------------------------------------------- */ -struct scic_sds_phy_state_handler -scic_sds_phy_starting_substate_handler_table[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] = -{ - /* SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_default_event_handler, - scic_sds_phy_default_consume_power_handler +const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = { + [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_starting_substate_await_ossp_event_handler, - scic_sds_phy_default_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, - scic_sds_phy_default_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, - scic_sds_phy_starting_substate_await_iaf_uf_event_handler, - scic_sds_phy_default_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_starting_substate_await_sas_power_event_handler, - scic_sds_phy_starting_substate_await_sas_power_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, + .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_starting_substate_await_sata_power_event_handler, - scic_sds_phy_starting_substate_await_sata_power_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, + .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_starting_substate_await_sata_phy_event_handler, - scic_sds_phy_default_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_starting_substate_await_sata_speed_event_handler, - scic_sds_phy_default_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_starting_substate_await_sig_fis_frame_handler, - scic_sds_phy_starting_substate_await_sig_fis_event_handler, - scic_sds_phy_default_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_default_event_handler, - scic_sds_phy_default_consume_power_handler + [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler } }; @@ -2344,80 +2312,60 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler( /* --------------------------------------------------------------------------- */ -struct scic_sds_phy_state_handler -scic_sds_phy_state_handler_table[SCI_BASE_PHY_MAX_STATES] = -{ - /* SCI_BASE_PHY_STATE_INITIAL */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_default_event_handler, - scic_sds_phy_default_consume_power_handler +const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { + [SCI_BASE_PHY_STATE_INITIAL] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCI_BASE_PHY_STATE_STOPPED */ - { - { - scic_sds_phy_stopped_state_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_stopped_state_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_default_event_handler, - scic_sds_phy_default_consume_power_handler + [SCI_BASE_PHY_STATE_STOPPED] = { + .parent.start_handler = scic_sds_phy_stopped_state_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_stopped_state_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCI_BASE_PHY_STATE_STARTING */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_default_event_handler, - scic_sds_phy_default_consume_power_handler + [SCI_BASE_PHY_STATE_STARTING] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCI_BASE_PHY_STATE_READY */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_ready_state_stop_handler, - scic_sds_phy_ready_state_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_ready_state_event_handler, - scic_sds_phy_default_consume_power_handler + [SCI_BASE_PHY_STATE_READY] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_ready_state_stop_handler, + .parent.reset_handler = scic_sds_phy_ready_state_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_ready_state_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCI_BASE_PHY_STATE_RESETTING */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_resetting_state_event_handler, - scic_sds_phy_default_consume_power_handler + [SCI_BASE_PHY_STATE_RESETTING] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_resetting_state_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, - /* SCI_BASE_PHY_STATE_FINAL */ - { - { - scic_sds_phy_default_start_handler, - scic_sds_phy_default_stop_handler, - scic_sds_phy_default_reset_handler, - scic_sds_phy_default_destroy_handler - }, - scic_sds_phy_default_frame_handler, - scic_sds_phy_default_event_handler, - scic_sds_phy_default_consume_power_handler + [SCI_BASE_PHY_STATE_FINAL] = { + .parent.start_handler = scic_sds_phy_default_start_handler, + .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.reset_handler = scic_sds_phy_default_reset_handler, + .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler } }; diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 3b88259d7c87..9ba09bb0c13d 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -146,11 +146,6 @@ enum SCIC_SDS_PHY_STARTING_SUBSTATES { * Exit state for this state machine */ SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL, - - /** - * Maximum number of substates for the STARTING state machine - */ - SCIC_SDS_PHY_STARTING_MAX_SUBSTATES }; struct scic_sds_port; @@ -248,7 +243,7 @@ struct scic_sds_phy { */ void *sata_timeout_timer; - struct scic_sds_phy_state_handler *state_handlers; + const struct scic_sds_phy_state_handler *state_handlers; struct sci_base_state_machine starting_substate_machine; @@ -260,9 +255,9 @@ struct scic_sds_phy { }; -typedef enum sci_status (*SCIC_SDS_PHY_EVENT_HANDLER_T)(struct scic_sds_phy *, u32); -typedef enum sci_status (*SCIC_SDS_PHY_FRAME_HANDLER_T)(struct scic_sds_phy *, u32); -typedef enum sci_status (*SCIC_SDS_PHY_POWER_HANDLER_T)(struct scic_sds_phy *); +typedef enum sci_status (*scic_sds_phy_event_handler_t)(struct scic_sds_phy *, u32); +typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u32); +typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); /** * struct scic_sds_phy_state_handler - @@ -278,25 +273,24 @@ struct scic_sds_phy_state_handler { /** * The state handler for unsolicited frames received from the SCU hardware. */ - SCIC_SDS_PHY_FRAME_HANDLER_T frame_handler; + scic_sds_phy_frame_handler_t frame_handler; /** * The state handler for events received from the SCU hardware. */ - SCIC_SDS_PHY_EVENT_HANDLER_T event_handler; + scic_sds_phy_event_handler_t event_handler; /** * The state handler for staggered spinup. */ - SCIC_SDS_PHY_POWER_HANDLER_T consume_power_handler; + scic_sds_phy_power_handler_t consume_power_handler; }; -extern struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[]; +extern const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[]; extern const struct sci_base_state scic_sds_phy_state_table[]; extern const struct sci_base_state scic_sds_phy_starting_substates[]; -extern struct scic_sds_phy_state_handler - scic_sds_phy_starting_substate_handler_table[]; +extern const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[]; /** -- cgit v1.2.3 From 06fdb3286270a45d05b15db46416b2fe2f52583a Mon Sep 17 00:00:00 2001 From: Tomasz Chudy Date: Wed, 23 Feb 2011 00:08:49 -0800 Subject: isci: fix "no outbound task timeout" default value The default should be 5us. The hardware encodes it in 256ns increments, so the value should be 20 to approximate a 5us timeout. Signed-off-by: Tomasz Chudy Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 53861ccbd593..1cbb91c0ead8 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1997,8 +1997,7 @@ static void scic_sds_controller_set_default_config_parameters( this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5; this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5; this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20; - this_controller->user_parameters.sds1.no_outbound_task_timeout = 5; - + this_controller->user_parameters.sds1.no_outbound_task_timeout = 20; } -- cgit v1.2.3 From 246214667f275a952b05a42b3c45a6fcb520bd28 Mon Sep 17 00:00:00 2001 From: Henryk Dembkowski Date: Wed, 23 Feb 2011 00:08:52 -0800 Subject: isci: Move transport layer registers from port to phy At init and RNC resume we need to touch every phy in a port to be sure we have initialized STP properties in the case where port_index != phy_index. Also add some missing __iomem annotations. Signed-off-by: Henryk Dembkowski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 2 +- drivers/scsi/isci/core/scic_sds_phy.c | 62 ++++++++++++++++-- drivers/scsi/isci/core/scic_sds_phy.h | 15 ++++- drivers/scsi/isci/core/scic_sds_phy_registers.h | 53 +++++++++++++++ drivers/scsi/isci/core/scic_sds_port.c | 58 ++++------------- drivers/scsi/isci/core/scic_sds_port.h | 18 ++--- drivers/scsi/isci/core/scic_sds_port_registers.h | 76 ---------------------- drivers/scsi/isci/core/scic_sds_remote_device.c | 10 --- .../scsi/isci/core/scic_sds_remote_node_context.c | 29 +++++---- 9 files changed, 161 insertions(+), 162 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 1cbb91c0ead8..e597c6b53eaa 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -2919,6 +2919,7 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler( index++) { result = scic_sds_phy_initialize( &this_controller->phy_table[index], + &this_controller->scu_registers->peg0.pe[index].tl, &this_controller->scu_registers->peg0.pe[index].ll ); } @@ -2932,7 +2933,6 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler( index++) { result = scic_sds_port_initialize( &this_controller->port_table[index], - &this_controller->scu_registers->peg0.pe[index].tl, &this_controller->scu_registers->peg0.ptsg.port[index], &this_controller->scu_registers->peg0.ptsg.protocol_engine, &this_controller->scu_registers->peg0.viit[index] diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 98e9179e227c..bd0a6ba17b18 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -62,6 +62,7 @@ #include "scic_sds_phy.h" #include "scic_sds_phy_registers.h" #include "scic_sds_port.h" +#include "scic_sds_remote_node_context.h" #include "scic_user_callback.h" #include "sci_environment.h" #include "sci_util.h" @@ -83,6 +84,31 @@ enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy) * * SCIC SDS PHY Internal Methods * ***************************************************************************** */ +/** + * This method will initialize the phy transport layer registers + * @this_phy: + * @transport_layer_registers + * + * enum sci_status + */ +static enum sci_status scic_sds_phy_transport_layer_initialization( + struct scic_sds_phy *this_phy, + struct scu_transport_layer_registers __iomem *transport_layer_registers) +{ + u32 tl_control; + + this_phy->transport_layer_registers = transport_layer_registers; + + SCU_STPTLDARNI_WRITE(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); + + /* Hardware team recommends that we enable the STP prefetch for all transports */ + tl_control = SCU_TLCR_READ(this_phy); + tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); + SCU_TLCR_WRITE(this_phy, tl_control); + + return SCI_SUCCESS; +} + /** * This method will initialize the phy link layer registers * @this_phy: @@ -92,7 +118,7 @@ enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy) */ static enum sci_status scic_sds_phy_link_layer_initialization( struct scic_sds_phy *this_phy, - struct scu_link_layer_registers *link_layer_registers) + struct scu_link_layer_registers __iomem *link_layer_registers) { u32 phy_configuration; struct sas_capabilities phy_capabilities; @@ -361,7 +387,8 @@ void scic_sds_phy_set_port( */ enum sci_status scic_sds_phy_initialize( struct scic_sds_phy *sci_phy, - struct scu_link_layer_registers *link_layer_registers) + struct scu_transport_layer_registers __iomem *transport_layer_registers, + struct scu_link_layer_registers __iomem *link_layer_registers) { /* Create the SIGNATURE FIS Timeout timer for this phy */ sci_phy->sata_timeout_timer = scic_cb_timer_create( @@ -370,6 +397,9 @@ enum sci_status scic_sds_phy_initialize( sci_phy ); + /* Perfrom the initialization of the TL hardware */ + scic_sds_phy_transport_layer_initialization(sci_phy, transport_layer_registers); + /* Perofrm the initialization of the PE hardware */ scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers); @@ -384,6 +414,31 @@ enum sci_status scic_sds_phy_initialize( return SCI_SUCCESS; } +/** + * This method assigns the direct attached device ID for this phy. + * + * @this_phy The phy for which the direct attached device id is to + * be assigned. + * @device_id The direct attached device ID to assign to the phy. + * This will either be the RNi for the device or an invalid RNi if there + * is no current device assigned to the phy. + */ +void scic_sds_phy_setup_transport( + struct scic_sds_phy *this_phy, + u32 device_id) +{ + u32 tl_control; + + SCU_STPTLDARNI_WRITE(this_phy, device_id); + + /* + * The read should guarantee that the first write gets posted + * before the next write + */ + tl_control = SCU_TLCR_READ(this_phy); + tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); + SCU_TLCR_WRITE(this_phy, tl_control); +} /** * @@ -398,10 +453,9 @@ void scic_sds_phy_suspend( u32 scu_sas_pcfg_value; scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); - scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); - SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + scic_sds_phy_setup_transport(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); } /** diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 9ba09bb0c13d..dc450c361d91 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -247,10 +247,16 @@ struct scic_sds_phy { struct sci_base_state_machine starting_substate_machine; + /** + * This field is the pointer to the transport layer register for the SCU + * hardware. + */ + struct scu_transport_layer_registers __iomem *transport_layer_registers; + /** * This field points to the link layer register set within the SCU. */ - struct scu_link_layer_registers *link_layer_registers; + struct scu_link_layer_registers __iomem *link_layer_registers; }; @@ -383,7 +389,8 @@ void scic_sds_phy_set_port( enum sci_status scic_sds_phy_initialize( struct scic_sds_phy *this_phy, - struct scu_link_layer_registers *link_layer_registers); + struct scu_transport_layer_registers __iomem *transport_layer_registers, + struct scu_link_layer_registers __iomem *link_layer_registers); enum sci_status scic_sds_phy_start( struct scic_sds_phy *this_phy); @@ -402,6 +409,10 @@ void scic_sds_phy_suspend( void scic_sds_phy_resume( struct scic_sds_phy *this_phy); +void scic_sds_phy_setup_transport( + struct scic_sds_phy *this_phy, + u32 device_id); + /* --------------------------------------------------------------------------- */ enum sci_status scic_sds_phy_event_handler( diff --git a/drivers/scsi/isci/core/scic_sds_phy_registers.h b/drivers/scsi/isci/core/scic_sds_phy_registers.h index 7883819035da..284217618031 100644 --- a/drivers/scsi/isci/core/scic_sds_phy_registers.h +++ b/drivers/scsi/isci/core/scic_sds_phy_registers.h @@ -65,6 +65,59 @@ #include "scic_sds_controller.h" +/* ************************************************************************** + * * SCU TRANSPORT LAYER REGISTER OPERATIONS + * ************************************************************************** */ + +/** + * Macro to read the transport layer register associated with this phy + * object. + */ +#define scu_transport_layer_read(phy, reg) \ + scu_register_read( \ + scic_sds_phy_get_controller(phy), \ + (phy)->transport_layer_registers->reg \ + ) + +/** + * Macro to write the transport layer register associated with this phy + * object. + */ +#define scu_transport_layer_write(phy, reg, value) \ + scu_register_write( \ + scic_sds_phy_get_controller(phy), \ + (phy)->transport_layer_registers->reg, \ + (value) \ + ) + +/* ************************************************************************** + * * Transport Layer registers controlled by the phy object + * ************************************************************************** */ + +/* This macro reads the Transport layer control register */ +#define SCU_TLCR_READ(phy) \ + scu_transport_layer_read(phy, control) + +/* This macro writes the Transport layer control register */ +#define SCU_TLCR_WRITE(phy, value) \ + scu_transport_layer_write(phy, control, value) + +/* This macro reads the Transport layer address translation register */ +#define SCU_TLADTR_READ(phy) \ + scu_transport_layer_read(phy, address_translation) + +/* This macro writes the Transport layer address translation register */ +#define SCU_TLADTR_WRITE(phy) \ + scu_transport_layer_write(phy, address_translation, value) + +/* This macro writes the STP Transport Layer Direct Attached RNi register */ +#define SCU_STPTLDARNI_WRITE(phy, index) \ + scu_transport_layer_write(phy, stp_rni, index) + +/* This macro reads the STP Transport Layer Direct Attached RNi register */ +#define SCU_STPTLDARNI_READ(phy) \ + scu_transport_layer_read(phy, stp_rni) + /* * ***************************************************************************** * * SCU LINK LAYER REGISTER OPERATIONS diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index ff06f8cb15b8..b8acc234a63d 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -531,7 +531,6 @@ void scic_sds_port_construct( this_port->timer_handle = NULL; - this_port->transport_layer_registers = NULL; this_port->port_task_scheduler_registers = NULL; for (index = 0; index < SCI_MAX_PHYS; index++) { @@ -553,30 +552,14 @@ void scic_sds_port_construct( */ enum sci_status scic_sds_port_initialize( struct scic_sds_port *this_port, - void *transport_layer_registers, - void *port_task_scheduler_registers, - void *port_configuration_regsiter, - void *viit_registers) + void __iomem *port_task_scheduler_registers, + void __iomem *port_configuration_regsiter, + void __iomem *viit_registers) { - u32 tl_control; - - this_port->transport_layer_registers = transport_layer_registers; this_port->port_task_scheduler_registers = port_task_scheduler_registers; this_port->port_pe_configuration_register = port_configuration_regsiter; this_port->viit_registers = viit_registers; - scic_sds_port_set_direct_attached_device_id( - this_port, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX - ); - - /* - * Hardware team recommends that we enable the STP prefetch - * for all ports */ - tl_control = SCU_TLCR_READ(this_port); - tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); - SCU_TLCR_WRITE(this_port, tl_control); - /* * If this is not the dummy port make the assignment of * the timer and start the state machine */ @@ -693,29 +676,25 @@ enum sci_status scic_port_hard_reset( } /** - * - * @this_port: The port for which the direct attached device id is to be - * assigned. - * * This method assigns the direct attached device ID for this port. + * + * @param[in] this_port The port for which the direct attached device id is to + * be assigned. + * @param[in] device_id The direct attached device ID to assign to the port. + * This will be the RNi for the device */ -void scic_sds_port_set_direct_attached_device_id( +void scic_sds_port_setup_transports( struct scic_sds_port *this_port, u32 device_id) { - u32 tl_control; - - SCU_STPTLDARNI_WRITE(this_port, device_id); + u8 index; - /* - * The read should guarntee that the first write gets posted - * before the next write */ - tl_control = SCU_TLCR_READ(this_port); - tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); - SCU_TLCR_WRITE(this_port, tl_control); + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (this_port->active_phy_mask & (1 << index)) + scic_sds_phy_setup_transport(this_port->phy_table[index], device_id); + } } - /** * * @this_port: This is the port on which the phy should be enabled. @@ -1550,16 +1529,12 @@ static void scic_sds_port_suspend_port_task_scheduler( struct scic_sds_port *this_port) { u32 pts_control_value; - u32 tl_control_value; pts_control_value = scu_port_task_scheduler_read(this_port, control); - tl_control_value = scu_transport_layer_read(this_port, control); pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND); - tl_control_value |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); scu_port_task_scheduler_write(this_port, control, pts_control_value); - scu_transport_layer_write(this_port, control, tl_control_value); } /** @@ -2624,11 +2599,6 @@ static void scic_sds_port_resetting_state_enter( scic_sds_port_set_base_state_handlers( this_port, SCI_BASE_PORT_STATE_RESETTING ); - - scic_sds_port_set_direct_attached_device_id( - this_port, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX - ); } /** diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 56c15fcbeb8d..3eb80cb2ea47 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -180,17 +180,12 @@ struct scic_sds_port { struct sci_base_state_machine ready_substate_machine; /* / Memory mapped hardware register space */ - /** - * This field is the pointer to the transport layer register for the SCU - * hardware. - */ - struct scu_transport_layer_registers *transport_layer_registers; /** * This field is the pointer to the port task scheduler registers for the SCU * hardware. */ - struct scu_port_task_scheduler_registers *port_task_scheduler_registers; + struct scu_port_task_scheduler_registers __iomem *port_task_scheduler_registers; /** * This field is identical for all port objects and points to the port task @@ -202,7 +197,7 @@ struct scic_sds_port { /** * This field is the VIIT register space for ths port object. */ - struct scu_viit_entry *viit_registers; + struct scu_viit_entry __iomem *viit_registers; }; @@ -345,10 +340,9 @@ void scic_sds_port_construct( enum sci_status scic_sds_port_initialize( struct scic_sds_port *this_port, - void *transport_layer_registers, - void *port_task_scheduler_registers, - void *port_configuration_regsiter, - void *viit_registers); + void __iomem *port_task_scheduler_registers, + void __iomem *port_configuration_regsiter, + void __iomem *viit_registers); /* --------------------------------------------------------------------------- */ @@ -360,7 +354,7 @@ enum sci_status scic_sds_port_remove_phy( struct scic_sds_port *this_port, struct scic_sds_phy *the_phy); -void scic_sds_port_set_direct_attached_device_id( +void scic_sds_port_setup_transports( struct scic_sds_port *this_port, u32 device_id); diff --git a/drivers/scsi/isci/core/scic_sds_port_registers.h b/drivers/scsi/isci/core/scic_sds_port_registers.h index cf8bc073b952..dbe82d864eac 100644 --- a/drivers/scsi/isci/core/scic_sds_port_registers.h +++ b/drivers/scsi/isci/core/scic_sds_port_registers.h @@ -63,29 +63,6 @@ * */ -/** - * scu_transport_layer_read() - - * - * Macro to read the transport layer register associated with this port object. - */ -#define scu_transport_layer_read(port, reg) \ - scu_register_read(\ - scic_sds_port_get_controller(port), \ - (port)->transport_layer_registers->reg \ - ) - -/** - * scu_transport_layer_write() - - * - * Macro to write the transport layer register associated with this port object. - */ -#define scu_transport_layer_write(port, reg, value) \ - scu_register_write(\ - scic_sds_port_get_controller(port), \ - (port)->transport_layer_registers->reg, \ - (value) \ - ) - /** * scu_port_task_scheduler_read() - * @@ -118,59 +95,6 @@ (value) \ ) -/* - * **************************************************************************** - * * Transport Layer registers controlled by the port object - * **************************************************************************** */ - -/** - * SCU_TLCR_READ() - - * - * This macro reads the Transport layer control register - */ -#define SCU_TLCR_READ(port) \ - scu_transport_layer_read(port, control) - -/** - * SCU_TLCR_WRITE() - - * - * This macro writes the Transport layer control register - */ -#define SCU_TLCR_WRITE(port, value) \ - scu_transport_layer_write(port, control, value) - -/** - * SCU_TLADTR_READ() - - * - * This macro reads the Transport layer address translation register - */ -#define SCU_TLADTR_READ(port) \ - scu_transport_layer_read(port, address_translation) - -/** - * SCU_TLADTR_WRITE() - - * - * This macro writes the Transport layer address translation register - */ -#define SCU_TLADTR_WRITE(port) \ - scu_transport_layer_write(port, address_translation, value) - -/** - * SCU_STPTLDARNI_WRITE() - - * - * This macro writes the STP Transport Layer Direct Attached RNi register. - */ -#define SCU_STPTLDARNI_WRITE(port, index) \ - scu_transport_layer_write(port, stp_rni, index) - -/** - * SCU_STPTLDARNI_READ() - - * - * This macro reads the STP Transport Layer Direct Attached RNi register. - */ -#define SCU_STPTLDARNI_READ(port) \ - scu_transport_layer_read(port, stp_rni) - /* * **************************************************************************** * * Port Task Scheduler registers controlled by the port object diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 643247f46a7e..cb1cf397b96f 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1210,11 +1210,6 @@ static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX ); - scic_sds_port_set_direct_attached_device_id( - this_device->owning_port, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX - ); - sci_base_state_machine_change_state( scic_sds_remote_device_get_base_state_machine(this_device), SCI_BASE_REMOTE_DEVICE_STATE_FINAL @@ -2018,11 +2013,6 @@ static void scic_sds_remote_device_resetting_state_exit( { struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; - scic_sds_port_set_direct_attached_device_id( - scic_sds_remote_device_get_port(this_device), - this_device->rnc->remote_node_index - ); - scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL); } diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c index 7fec322571ef..253b2d8aa23b 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.c +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c @@ -689,11 +689,6 @@ static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_ha } else if (protocols.u.bits.attached_stp_target == 1) { if (this_rnc->device->is_direct_attached) { /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ - scic_sds_port_set_direct_attached_device_id( - this_rnc->device->owning_port, - this_rnc->remote_node_index - ); - sci_base_state_machine_change_state( &this_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE @@ -986,7 +981,7 @@ static void scic_sds_remote_node_context_validate_context_buffer( ); if (this_rnc->device->is_direct_attached) { - scic_sds_port_set_direct_attached_device_id( + scic_sds_port_setup_transports( this_rnc->device->owning_port, this_rnc->remote_node_index ); @@ -1016,13 +1011,6 @@ static void scic_sds_remote_node_context_invalidate_context_buffer( this_rnc->device, SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE ); - - if (this_rnc->device->is_direct_attached) { - scic_sds_port_set_direct_attached_device_id( - this_rnc->device->owning_port, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX - ); - } } /* @@ -1112,6 +1100,7 @@ static void scic_sds_remote_node_context_resuming_state_enter( struct sci_base_object *object) { struct scic_sds_remote_node_context *rnc; + struct smp_discover_response_protocols protocols; rnc = (struct scic_sds_remote_node_context *)object; @@ -1121,6 +1110,20 @@ static void scic_sds_remote_node_context_resuming_state_enter( SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE ); + /* + * For direct attached SATA devices we need to clear the TLCR + * NCQ to TCi tag mapping on the phy and in cases where we + * resume because of a target reset we also need to update + * the STPTLDARNI register with the RNi of the device + */ + scic_remote_device_get_protocols(rnc->device, &protocols); + + if ((protocols.u.bits.attached_stp_target == 1) && + (rnc->device->is_direct_attached)) { + scic_sds_port_setup_transports( + rnc->device->owning_port, rnc->remote_node_index); + } + scic_sds_remote_device_post_request( rnc->device, SCU_CONTEXT_COMMAND_POST_RNC_RESUME -- cgit v1.2.3 From d9def184b39b966b7496dfbfad126808d3cd701b Mon Sep 17 00:00:00 2001 From: Jacek Danecki Date: Wed, 23 Feb 2011 00:08:58 -0800 Subject: isci: Add support for user parameters in SCIC layer Add support for the following parameters in SCIC: /** * This field specifies the NOTIFY (ENABLE SPIN UP) primitive * insertion frequency for this phy index. */ u32 notify_enable_spin_up_insertion_frequency; /** * This method specifies the number of transmitted DWORDs within which * to transmit a single ALIGN primitive. This value applies regardless * of what type of device is attached or connection state. A value of * 0 indicates that no ALIGN primitives will be inserted. */ u16 align_insertion_frequency; /** * This method specifies the number of transmitted DWORDs within which * to transmit 2 ALIGN primitives. This applies for SAS connections * only. A minimum value of 3 is required for this field. */ u16 in_connection_align_insertion_frequency; Signed-off-by: Krzysztof Wierzbicki Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 58 +++++++++++++++---------- drivers/scsi/isci/core/scic_sds_phy.c | 16 ++++++- drivers/scsi/isci/core/scic_sds_phy_registers.h | 8 ++++ drivers/scsi/isci/core/scu_registers.h | 7 +++ 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index e597c6b53eaa..d9fca9976889 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -616,7 +616,6 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) scu_afe_register_write(scic, afe_bias_control, 0x00005500); else scu_afe_register_write(scic, afe_bias_control, 0x00005A00); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); @@ -625,7 +624,7 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) scu_afe_register_write(scic, afe_pll_control0, 0x80040A08); else scu_afe_register_write(scic, afe_pll_control0, 0x80040908); - + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); /* Wait for the PLL to lock */ @@ -1962,17 +1961,16 @@ void scic_sds_controller_release_frame( * configuration parameters to their default values. * */ -static void scic_sds_controller_set_default_config_parameters( - struct scic_sds_controller *this_controller) +static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) { u16 index; /* Default to no SSC operation. */ - this_controller->oem_parameters.sds1.controller.do_enable_ssc = false; + scic->oem_parameters.sds1.controller.do_enable_ssc = false; /* Initialize all of the port parameter information to narrow ports. */ for (index = 0; index < SCI_MAX_PORTS; index++) { - this_controller->oem_parameters.sds1.ports[index].phy_mask = 0; + scic->oem_parameters.sds1.ports[index].phy_mask = 0; } /* Initialize all of the phy parameter information. */ @@ -1980,24 +1978,27 @@ static void scic_sds_controller_set_default_config_parameters( /* * Default to 3G (i.e. Gen 2) for now. User can override if * they choose. */ - this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2; + scic->user_parameters.sds1.phys[index].max_speed_generation = 2; + + /* the frequencies cannot be 0 */ + scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f; + scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff; + scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; /* * Previous Vitesse based expanders had a arbitration issue that * is worked around by having the upper 32-bits of SAS address * with a value greater then the Vitesse company identifier. * Hence, usage of 0x5FCFFFFF. */ - this_controller->oem_parameters.sds1.phys[index].sas_address.low - = 0x00000001; - this_controller->oem_parameters.sds1.phys[index].sas_address.high - = 0x5FCFFFFF; + scic->oem_parameters.sds1.phys[index].sas_address.low = 0x00000001; + scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF; } - this_controller->user_parameters.sds1.stp_inactivity_timeout = 5; - this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5; - this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5; - this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20; - this_controller->user_parameters.sds1.no_outbound_task_timeout = 20; + scic->user_parameters.sds1.stp_inactivity_timeout = 5; + scic->user_parameters.sds1.ssp_inactivity_timeout = 5; + scic->user_parameters.sds1.stp_max_occupancy_timeout = 5; + scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20; + scic->user_parameters.sds1.no_outbound_task_timeout = 20; } @@ -2103,9 +2104,9 @@ u32 scic_controller_get_suggested_start_timeout( * per interval - 1 (once OEM parameters are supported). * Currently we assume only 1 phy per interval. */ - return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT + return SCIC_SDS_SIGNATURE_FIS_TIMEOUT + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT - + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL)); + + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); } /* --------------------------------------------------------------------------- */ @@ -2489,16 +2490,29 @@ enum sci_status scic_user_parameters_set( * Validate the user parameters. If they are not legal, then * return a failure. */ for (index = 0; index < SCI_MAX_PHYS; index++) { - if (! - (scic_parms->sds1.phys[index].max_speed_generation + if (!(scic_parms->sds1.phys[index].max_speed_generation <= SCIC_SDS_PARM_MAX_SPEED && scic_parms->sds1.phys[index].max_speed_generation - > SCIC_SDS_PARM_NO_SPEED - ) + > SCIC_SDS_PARM_NO_SPEED)) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + + if (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + if ( + (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) || + (scic_parms->sds1.phys[index].align_insertion_frequency == 0) || + (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0) ) return SCI_FAILURE_INVALID_PARAMETER_VALUE; } + if ((scic_parms->sds1.stp_inactivity_timeout == 0) || + (scic_parms->sds1.ssp_inactivity_timeout == 0) || + (scic_parms->sds1.stp_max_occupancy_timeout == 0) || + (scic_parms->sds1.ssp_max_occupancy_timeout == 0) || + (scic_parms->sds1.no_outbound_task_timeout == 0)) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms)); return SCI_SUCCESS; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index bd0a6ba17b18..ecd7cc698ae6 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -125,6 +125,7 @@ static enum sci_status scic_sds_phy_link_layer_initialization( u32 parity_check = 0; u32 parity_count = 0; u32 link_layer_control; + u32 clksm_value = 0; this_phy->link_layer_registers = link_layer_registers; @@ -199,7 +200,20 @@ static enum sci_status scic_sds_phy_link_layer_initialization( SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all); /* Set the enable spinup period but disable the ability to send notify enable spinup */ - SCU_SAS_ENSPINUP_WRITE(this_phy, SCU_ENSPINUP_GEN_VAL(COUNT, 0x33)); + SCU_SAS_ENSPINUP_WRITE(this_phy, SCU_ENSPINUP_GEN_VAL(COUNT, + this_phy->owning_port->owning_controller->user_parameters.sds1. + phys[this_phy->phy_index].notify_enable_spin_up_insertion_frequency)); + + /* Write the ALIGN Insertion Ferequency for connected phy and inpendent of connected state */ + clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(CONNECTED, + this_phy->owning_port->owning_controller->user_parameters.sds1. + phys[this_phy->phy_index].in_connection_align_insertion_frequency); + + clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL, + this_phy->owning_port->owning_controller->user_parameters.sds1. + phys[this_phy->phy_index].align_insertion_frequency); + + SCU_SAS_CLKSM_WRITE(this_phy, clksm_value); #if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) || defined(CONFIG_PBG_HBA_BETA) /* / @todo Provide a way to write this register correctly */ diff --git a/drivers/scsi/isci/core/scic_sds_phy_registers.h b/drivers/scsi/isci/core/scic_sds_phy_registers.h index 284217618031..ddbb2361510d 100644 --- a/drivers/scsi/isci/core/scic_sds_phy_registers.h +++ b/drivers/scsi/isci/core/scic_sds_phy_registers.h @@ -217,6 +217,14 @@ #define SCU_SAS_ENSPINUP_WRITE(phy, value) \ scu_link_layer_register_write(phy, notify_enable_spinup_control, value) +/* This macro reads the CLKSM register */ +#define SCU_SAS_CLKSM_READ(phy) \ + scu_link_layer_register_read(phy, clock_skew_management) + +/* This macro writes the CLKSM register */ +#define SCU_SAS_CLKSM_WRITE(phy, value) \ + scu_link_layer_register_write(phy, clock_skew_management, value) + /* / This macro reads the PHY Capacity register */ #define SCU_SAS_PHYCAP_READ(phy) \ scu_link_layer_register_read(phy, phy_capabilities) diff --git a/drivers/scsi/isci/core/scu_registers.h b/drivers/scsi/isci/core/scu_registers.h index de2ce93b7836..05a141181844 100644 --- a/drivers/scsi/isci/core/scu_registers.h +++ b/drivers/scsi/isci/core/scu_registers.h @@ -611,6 +611,13 @@ #define SCU_SAS_PCFG_GEN_BIT(name) \ SCU_GEN_BIT(SCU_SAS_PHY_CONFIGURATION_ ## name) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_SHIFT (0) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_MASK (0x000007FF) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_SHIFT (16) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_MASK (0x00ff0000) + +#define SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_##name, value) #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_SHIFT (0) #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_MASK (0x0003FFFF) -- cgit v1.2.3 From 3c06c2839dac6db56a1e6bd11924db38eddfb2ed Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Feb 2011 00:09:01 -0800 Subject: isci: clean up remaining silicon revision ifdefs in phy init Use the dynamic revision detection code in scic_sds_phy_link_layer_initialization() and apply some coding style fixups (long deref chains). The compile time max link rate setting is removed in favor of honoring the user-parameter max. Reported-by: Krzysztof Wierzbicki Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_config_parameters.h | 4 +- drivers/scsi/isci/core/scic_sds_controller.c | 15 -- drivers/scsi/isci/core/scic_sds_phy.c | 173 ++++++++++-------------- drivers/scsi/isci/sci_environment.h | 14 ++ 4 files changed, 85 insertions(+), 121 deletions(-) diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index 8bd85605130c..485fefc08883 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -114,7 +114,7 @@ struct scic_sds_controller; * */ struct scic_sds_user_parameters { - struct { + struct sci_phy_user_params { /** * This field specifies the NOTIFY (ENABLE SPIN UP) primitive * insertion frequency for this phy index. @@ -250,7 +250,7 @@ struct scic_sds_oem_parameters { } ports[SCI_MAX_PORTS]; - struct { + struct sci_phy_oem_params { /** * This field specifies the SAS address to be transmitted on * for this phy index. diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index d9fca9976889..e8d09fd935ec 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -584,21 +584,6 @@ void scic_sds_controller_enable_port_task_scheduler( */ #define AFE_REGISTER_WRITE_DELAY 10 -static bool is_a0(void) -{ - return isci_si_rev == ISCI_SI_REVA0; -} - -static bool is_a2(void) -{ - return isci_si_rev == ISCI_SI_REVA2; -} - -static bool is_b0(void) -{ - return isci_si_rev > ISCI_SI_REVA2; -} - /* Initialize the AFE for this phy index. We need to read the AFE setup from * the OEM parameters none */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index ecd7cc698ae6..e8d5be73cd0b 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -111,62 +111,55 @@ static enum sci_status scic_sds_phy_transport_layer_initialization( /** * This method will initialize the phy link layer registers - * @this_phy: + * @sci_phy: * @link_layer_registers: * * enum sci_status */ -static enum sci_status scic_sds_phy_link_layer_initialization( - struct scic_sds_phy *this_phy, - struct scu_link_layer_registers __iomem *link_layer_registers) +static enum sci_status +scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, + struct scu_link_layer_registers __iomem *link_layer_registers) { + struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + int phy_idx = sci_phy->phy_index; + struct sci_phy_user_params *phy_user = &scic->user_parameters.sds1.phys[phy_idx]; + struct sci_phy_oem_params *phy_oem = &scic->oem_parameters.sds1.phys[phy_idx]; u32 phy_configuration; struct sas_capabilities phy_capabilities; u32 parity_check = 0; u32 parity_count = 0; - u32 link_layer_control; + u32 llctl, link_rate; u32 clksm_value = 0; - this_phy->link_layer_registers = link_layer_registers; + sci_phy->link_layer_registers = link_layer_registers; /* Set our IDENTIFY frame data */ #define SCI_END_DEVICE 0x01 - SCU_SAS_TIID_WRITE( - this_phy, - (SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) - | SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) - | SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) - | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) - | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE)) - ); + SCU_SAS_TIID_WRITE(sci_phy, (SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) | + SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE))); /* Write the device SAS Address */ - SCU_SAS_TIDNH_WRITE(this_phy, 0xFEDCBA98); - SCU_SAS_TIDNL_WRITE(this_phy, this_phy->phy_index); + SCU_SAS_TIDNH_WRITE(sci_phy, 0xFEDCBA98); + SCU_SAS_TIDNL_WRITE(sci_phy, phy_idx); /* Write the source SAS Address */ - SCU_SAS_TISSAH_WRITE( - this_phy, - this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[ - this_phy->phy_index].sas_address.high - ); - SCU_SAS_TISSAL_WRITE( - this_phy, - this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[ - this_phy->phy_index].sas_address.low - ); + SCU_SAS_TISSAH_WRITE(sci_phy, phy_oem->sas_address.high); + SCU_SAS_TISSAL_WRITE(sci_phy, phy_oem->sas_address.low); /* Clear and Set the PHY Identifier */ - SCU_SAS_TIPID_WRITE(this_phy, 0x00000000); - SCU_SAS_TIPID_WRITE(this_phy, SCU_SAS_TIPID_GEN_VALUE(ID, this_phy->phy_index)); + SCU_SAS_TIPID_WRITE(sci_phy, 0x00000000); + SCU_SAS_TIPID_WRITE(sci_phy, SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx)); /* Change the initial state of the phy configuration register */ - phy_configuration = SCU_SAS_PCFG_READ(this_phy); + phy_configuration = SCU_SAS_PCFG_READ(sci_phy); /* Hold OOB state machine in reset */ phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - SCU_SAS_PCFG_WRITE(this_phy, phy_configuration); + SCU_SAS_PCFG_WRITE(sci_phy, phy_configuration); /* Configure the SNW capabilities */ phy_capabilities.u.all = 0; @@ -174,8 +167,7 @@ static enum sci_status scic_sds_phy_link_layer_initialization( phy_capabilities.u.bits.gen3_without_ssc_supported = 1; phy_capabilities.u.bits.gen2_without_ssc_supported = 1; phy_capabilities.u.bits.gen1_without_ssc_supported = 1; - if (this_phy->owning_port->owning_controller->oem_parameters.sds1. - controller.do_enable_ssc == true) { + if (scic->oem_parameters.sds1.controller.do_enable_ssc == true) { phy_capabilities.u.bits.gen3_with_ssc_supported = 1; phy_capabilities.u.bits.gen2_with_ssc_supported = 1; phy_capabilities.u.bits.gen1_with_ssc_supported = 1; @@ -197,93 +189,66 @@ static enum sci_status scic_sds_phy_link_layer_initialization( if ((parity_count % 2) != 0) phy_capabilities.u.bits.parity = 1; - SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all); + SCU_SAS_PHYCAP_WRITE(sci_phy, phy_capabilities.u.all); - /* Set the enable spinup period but disable the ability to send notify enable spinup */ - SCU_SAS_ENSPINUP_WRITE(this_phy, SCU_ENSPINUP_GEN_VAL(COUNT, - this_phy->owning_port->owning_controller->user_parameters.sds1. - phys[this_phy->phy_index].notify_enable_spin_up_insertion_frequency)); + /* Set the enable spinup period but disable the ability to send + * notify enable spinup + */ + SCU_SAS_ENSPINUP_WRITE(sci_phy, SCU_ENSPINUP_GEN_VAL(COUNT, + phy_user->notify_enable_spin_up_insertion_frequency)); - /* Write the ALIGN Insertion Ferequency for connected phy and inpendent of connected state */ + /* Write the ALIGN Insertion Ferequency for connected phy and + * inpendent of connected state + */ clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(CONNECTED, - this_phy->owning_port->owning_controller->user_parameters.sds1. - phys[this_phy->phy_index].in_connection_align_insertion_frequency); + phy_user->in_connection_align_insertion_frequency); clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL, - this_phy->owning_port->owning_controller->user_parameters.sds1. - phys[this_phy->phy_index].align_insertion_frequency); - - SCU_SAS_CLKSM_WRITE(this_phy, clksm_value); - -#if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) || defined(CONFIG_PBG_HBA_BETA) - /* / @todo Provide a way to write this register correctly */ - scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421); -#else - /* / @todo Provide a way to write this register correctly */ - scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x0e739ce7); -#endif - - link_layer_control = SCU_SAS_LLCTL_GEN_VAL( - NO_OUTBOUND_TASK_TIMEOUT, - (u8)this_phy->owning_port->owning_controller-> - user_parameters.sds1.no_outbound_task_timeout - ); + phy_user->align_insertion_frequency); -/* #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 */ -/* #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 */ -#define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3 + SCU_SAS_CLKSM_WRITE(sci_phy, clksm_value); - if (this_phy->owning_port->owning_controller->user_parameters.sds1. - phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED) { - link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( - MAX_LINK_RATE, COMPILED_MAX_LINK_RATE - ); - } else if (this_phy->owning_port->owning_controller->user_parameters.sds1. - phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED) { - link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( - MAX_LINK_RATE, - min( - SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2, - COMPILED_MAX_LINK_RATE) - ); - } else { - link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( - MAX_LINK_RATE, - min( - SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1, - COMPILED_MAX_LINK_RATE) - ); - } + /* @todo Provide a way to write this register correctly */ + scu_link_layer_register_write(sci_phy, afe_lookup_table_control, 0x02108421); - scu_link_layer_register_write( - this_phy, link_layer_control, link_layer_control - ); + llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, + (u8)scic->user_parameters.sds1.no_outbound_task_timeout); - /* - * Program the max ARB time for the PHY to 700us so we inter-operate with - * the PMC expander which shuts down PHYs if the expander PHY generates too - * many breaks. This time value will guarantee that the initiator PHY will - * generate the break. */ -#if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) - scu_link_layer_register_write( - this_phy, - maximum_arbitration_wait_timer_timeout, - SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME - ); -#endif /* defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) */ + switch(phy_user->max_speed_generation) { + case SCIC_SDS_PARM_GEN3_SPEED: + link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3; + break; + case SCIC_SDS_PARM_GEN2_SPEED: + link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2; + break; + default: + link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1; + break; + } + llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate); + + scu_link_layer_register_write(sci_phy, link_layer_control, llctl); + + if (is_a0() || is_a2()) { + /* Program the max ARB time for the PHY to 700us so we inter-operate with + * the PMC expander which shuts down PHYs if the expander PHY generates too + * many breaks. This time value will guarantee that the initiator PHY will + * generate the break. + */ + scu_link_layer_register_write(sci_phy, + maximum_arbitration_wait_timer_timeout, + SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME); + } /* * Set the link layer hang detection to 500ms (0x1F4) from its default * value of 128ms. Max value is 511 ms. */ - scu_link_layer_register_write( - this_phy, link_layer_hang_detection_timeout, 0x1F4 - ); + scu_link_layer_register_write(sci_phy, link_layer_hang_detection_timeout, + 0x1F4); /* We can exit the initial state to the stopped state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), - SCI_BASE_PHY_STATE_STOPPED - ); + sci_base_state_machine_change_state(scic_sds_phy_get_base_state_machine(sci_phy), + SCI_BASE_PHY_STATE_STOPPED); return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index e1020ee6c38e..8d57f9552e28 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -108,5 +108,19 @@ enum { extern int isci_si_rev; +static inline bool is_a0(void) +{ + return isci_si_rev == ISCI_SI_REVA0; +} + +static inline bool is_a2(void) +{ + return isci_si_rev == ISCI_SI_REVA2; +} + +static inline bool is_b0(void) +{ + return isci_si_rev > ISCI_SI_REVA2; +} #endif -- cgit v1.2.3 From 52b957c80c3be9bab2748b0ac59ed3c3e8ffe196 Mon Sep 17 00:00:00 2001 From: Tomasz Chudy Date: Wed, 23 Feb 2011 00:09:04 -0800 Subject: isci: Add Support for new TC completion codes Update the SCI Core to comprehend the changes in the TC completion codes from A0 to B0. Specifically, there isnew R_ER code differences for command and data FISes. Changes are as follows: 1) 0x16 now additionally indicates an R_ERR received for a COMMAND FIS being sent to a SATA target. 0x16 for SSP still indicates a NAK received for a COMMAND frame. Fix is to retry TC to be compliant with SATA spec or ensure proper error handling of return value (not spec compliant I don't believe). 2) 0x1B was previously called DONE_BREAK_RCVD for STP and DONE_LL_ABORT_ERR for SSP. Now it is universally called DONE_LL_ABORT_ERR. This is purely a superficial change. 3) 0x32 is no longer a reserved code. Now it indicates DONE_CMD_SDMA_ERR for STP/SSP. There was a fatal error on the SDMA for a command IU (includes Raw frames). Consider retry, but at a minimum gracefully fail the request. 4) 0x33 is no longer a reserved code. Now it indicates DONE_CMD_LL_ABORT_ERR for SSP. There was a break receivd during transmission of a command IU. Consider retry, but at a minimum gracefully fail the request. Signed-off-by: Tomasz Chudy Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_stp_request.c | 2 ++ drivers/scsi/isci/core/scu_completion_codes.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 0b6b0552186a..6d280c0a2fc3 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -1602,9 +1602,11 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi /* * / @todo Check to see if any of these completion status need to wait for * / the device to host register fis. */ + /* / @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 */ case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): scic_sds_remote_device_suspend( this_request->parent.target_device, diff --git a/drivers/scsi/isci/core/scu_completion_codes.h b/drivers/scsi/isci/core/scu_completion_codes.h index 17ee4c8b9122..c8b329c695f9 100644 --- a/drivers/scsi/isci/core/scu_completion_codes.h +++ b/drivers/scsi/isci/core/scu_completion_codes.h @@ -228,6 +228,7 @@ #define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14) #define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15) #define SCU_TASK_DONE_NAK_CMD_ERR ((u32)0x16) +#define SCU_TASK_DONE_CMD_LL_R_ERR ((u32)0x16) #define SCU_TASK_DONE_LL_R_ERR ((u32)0x17) #define SCU_TASK_DONE_ACK_NAK_TO ((u32)0x17) #define SCU_TASK_DONE_LL_PERR ((u32)0x18) @@ -264,6 +265,8 @@ #define SCU_TASK_DONE_REG_ERR ((u32)0x2E) #define SCU_TASK_DONE_SDB_ERR ((u32)0x2F) #define SCU_TASK_DONE_TASK_ABORT ((u32)0x30) +#define SCU_TASK_DONE_CMD_SDMA_ERR ((U32)0x32) +#define SCU_TASK_DONE_CMD_LL_ABORT_ERR ((U32)0x33) #define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION ((u32)0x34) #define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1 ((u32)0x35) #define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2 ((u32)0x36) -- cgit v1.2.3 From b3824292cb93d4e45b87fe76d8774cbde9e43200 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Wed, 23 Feb 2011 00:09:14 -0800 Subject: isci: fix for asserts during aborts/resets to SAS/SATA in APC mode Sending aborts/resets to SAS/SATA targets in APC mode eventually causes an assert in scic_sds_apc_agent_link_up(). We need to handle the hard reset case for apc mode ports. Signed-off-by: Piotr Sawicki Signed-off-by: Dan Williams --- .../isci/core/scic_sds_port_configuration_agent.c | 38 ++++++++++++++-------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index dd2cdd4a6fe1..001472e75b8c 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -676,28 +676,40 @@ static void scic_sds_apc_agent_configure_ports( } /** - * - * @controller: This is the controller object that receives the link up + * scic_sds_apc_agent_link_up - handle apc link up events + * @scic: This is the controller object that receives the link up * notification. - * @port: This is the port object associated with the phy. If the is no + * @sci_port: This is the port object associated with the phy. If the is no * associated port this is an NULL. - * @phy: This is the phy object which has gone link up. + * @sci_phy: This is the phy object which has gone link up. * * This method handles the automatic port configuration for link up * notifications. Is it possible to get a link down notification from a phy * that has no assocoated port? */ -static void scic_sds_apc_agent_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *port, - struct scic_sds_phy *phy) +static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - BUG_ON(port != NULL); - - port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); + u8 phy_index = sci_phy->phy_index; - scic_sds_apc_agent_configure_ports(controller, port_agent, phy, true); + if (!sci_port) { + /* the phy is not the part of this port */ + port_agent->phy_ready_mask |= 1 << phy_index; + scic_sds_apc_agent_configure_ports(scic, port_agent, sci_phy, true); + } else { + /* the phy is already the part of the port */ + u32 port_state = sci_port->parent.state_machine.current_state_id; + + /* if the PORT'S state is resetting then the link up is from + * port hard reset in this case, we need to tell the port + * that link up is recieved + */ + BUG_ON(port_state != SCI_BASE_PORT_STATE_RESETTING); + port_agent->phy_ready_mask |= 1 << phy_index; + scic_sds_port_link_up(sci_port, sci_phy); + } } /** -- cgit v1.2.3 From f7885c8490717b010115d6413b339702c64d8a3b Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 22 Feb 2011 16:39:32 -0700 Subject: isci: Removed special macros that does 64bit address math These macros are not necessary. We can do 64bit math directly. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_util.h | 39 ------------ .../isci/core/scic_sds_unsolicited_frame_control.c | 73 ++++++++++++---------- 2 files changed, 39 insertions(+), 73 deletions(-) diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h index 8f2ba35d955f..9748c76df387 100644 --- a/drivers/scsi/isci/core/sci_util.h +++ b/drivers/scsi/isci/core/sci_util.h @@ -85,45 +85,6 @@ #define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) - -/** - * sci_physical_address_add() - - * - * This macro simply performs addition on an dma_addr_t type. The - * lower u32 value is "clipped" or "wrapped" back through 0. When this occurs - * the upper 32-bits are incremented by 1. - */ -#define sci_physical_address_add(physical_address, value) \ - { \ - u32 lower = lower_32_bits((physical_address)); \ - u32 upper = upper_32_bits((physical_address)); \ - \ - if (lower + (value) < lower) \ - upper += 1; \ - \ - lower += (value); \ - sci_cb_make_physical_address(physical_address, upper, lower); \ - } - -/** - * sci_physical_address_subtract() - - * - * This macro simply performs subtraction on an dma_addr_t type. The - * lower u32 value is "clipped" or "wrapped" back through 0. When this occurs - * the upper 32-bits are decremented by 1. - */ -#define sci_physical_address_subtract(physical_address, value) \ - { \ - u32 lower = lower_32_bits((physical_address)); \ - u32 upper = upper_32_bits((physical_address)); \ - \ - if (lower - (value) > lower) \ - upper -= 1; \ - \ - lower -= (value); \ - sci_cb_make_physical_address(physical_address, upper, lower); \ - } - /** * scic_word_copy_with_swap() - Copy the data from source to destination and * swap the bytes during the copy. diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c index 7ca2f1709f6d..7274812af507 100644 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c @@ -109,7 +109,7 @@ void scic_sds_unsolicited_frame_control_set_address_table_count( static void scic_sds_unsolicited_frame_control_construct_frames( struct scic_sds_unsolicited_frame_control *uf_control, dma_addr_t uf_buffer_phys_address, - unsigned long uf_buffer_virt_address, + void *uf_buffer_virt_address, u32 unused_uf_header_entries, u32 used_uf_header_entries) { @@ -118,7 +118,8 @@ static void scic_sds_unsolicited_frame_control_construct_frames( /* * Program the unused buffers into the UF address table and the - * controller's array of UFs. */ + * controller's array of UFs. + */ for (index = 0; index < unused_uf_header_entries; index++) { uf = &uf_control->buffers.array[index]; @@ -132,7 +133,8 @@ static void scic_sds_unsolicited_frame_control_construct_frames( /* * Program the actual used UF buffers into the UF address table and - * the controller's array of UFs. */ + * the controller's array of UFs. + */ for (index = unused_uf_header_entries; index < unused_uf_header_entries + used_uf_header_entries; index++) { @@ -140,17 +142,17 @@ static void scic_sds_unsolicited_frame_control_construct_frames( uf_control->address_table.array[index] = uf_buffer_phys_address; - uf->buffer = (void *)uf_buffer_virt_address; + uf->buffer = uf_buffer_virt_address; uf->header = &uf_control->headers.array[index]; uf->state = UNSOLICITED_FRAME_EMPTY; /* - * Increment the address of the physical and virtual memory pointers - * Everything is aligned on 1k boundary with an increment of 1k */ + * Increment the address of the physical and virtual memory + * pointers. Everything is aligned on 1k boundary with an + * increment of 1k. + */ uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; - sci_physical_address_add( - uf_buffer_phys_address, SCU_UNSOLICITED_FRAME_BUFFER_SIZE - ); + uf_buffer_phys_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; } } @@ -177,6 +179,7 @@ void scic_sds_unsolicited_frame_control_construct( u32 unused_uf_header_bytes; u32 used_uf_header_bytes; dma_addr_t uf_buffer_phys_address; + void *uf_buffer_virt_address; /* * Prepare all of the memory sizes for the UF headers, UF address @@ -193,9 +196,11 @@ void scic_sds_unsolicited_frame_control_construct( /* * The Unsolicited Frame buffers are set at the start of the UF - * memory descriptor entry. The headers and address table will be - * placed after the buffers. */ + * memory descriptor entry. The headers and address table will be + * placed after the buffers. + */ uf_buffer_phys_address = mde->physical_address; + uf_buffer_virt_address = mde->virtual_address; /* * Program the location of the UF header table into the SCU. @@ -205,34 +210,34 @@ void scic_sds_unsolicited_frame_control_construct( * - Program unused header entries to overlap with the last * unsolicited frame. The silicon will never DMA to these unused * headers, since we program the UF address table pointers to - * NULL. */ - uf_control->headers.physical_address = uf_buffer_phys_address; - sci_physical_address_add( - uf_control->headers.physical_address, used_uf_buffer_bytes); - sci_physical_address_subtract( - uf_control->headers.physical_address, unused_uf_header_bytes); - uf_control->headers.array - = (struct scu_unsolicited_frame_header *) - scic_cb_get_virtual_address( - controller, uf_control->headers.physical_address - ); + * NULL. + */ + uf_control->headers.physical_address = + uf_buffer_phys_address + + used_uf_buffer_bytes - + unused_uf_header_bytes; + + uf_control->headers.array = + uf_buffer_virt_address + + used_uf_buffer_bytes - + unused_uf_header_bytes; /* * Program the location of the UF address table into the SCU. * Notes: * - The address must align on a 64-bit boundary. Guaranteed to be on 64 * byte boundary already due to above programming headers being on a - * 64-bit boundary and headers are on a 64-bytes in size. */ - uf_control->address_table.physical_address = uf_buffer_phys_address; - sci_physical_address_add( - uf_control->address_table.physical_address, used_uf_buffer_bytes); - sci_physical_address_add( - uf_control->address_table.physical_address, used_uf_header_bytes); - uf_control->address_table.array - = (dma_addr_t *) - scic_cb_get_virtual_address( - controller, uf_control->address_table.physical_address - ); + * 64-bit boundary and headers are on a 64-bytes in size. + */ + uf_control->address_table.physical_address = + uf_buffer_phys_address + + used_uf_buffer_bytes + + used_uf_header_bytes; + + uf_control->address_table.array = + uf_buffer_virt_address + + used_uf_buffer_bytes + + used_uf_header_bytes; uf_control->get = 0; @@ -250,7 +255,7 @@ void scic_sds_unsolicited_frame_control_construct( scic_sds_unsolicited_frame_control_construct_frames( uf_control, uf_buffer_phys_address, - (unsigned long)mde->virtual_address, + mde->virtual_address, unused_uf_header_entries, used_uf_header_entries ); -- cgit v1.2.3 From 103a00c200ab3bb9e598923eb7ba3354fcb3de8d Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 23 Feb 2011 15:57:24 -0800 Subject: isci: Make the driver copy data directly from and to sg for PIO We can copy the data directly to and from sg for SATA PIO read operations. There is no reason to involve the hardware SGL. In the process we also need to kmap the sg because we don't know where that can come from. We also do to not call phys_to_virt(). The driver already has the information. We can just calculcate the appropriate offets. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_util.c | 16 +++ drivers/scsi/isci/core/sci_util.h | 9 +- drivers/scsi/isci/core/scic_sds_request.c | 9 -- drivers/scsi/isci/core/scic_sds_request.h | 8 ++ drivers/scsi/isci/core/scic_sds_stp_request.c | 148 +++++++++----------------- drivers/scsi/isci/core/scic_sds_stp_request.h | 2 +- drivers/scsi/isci/isci.h | 1 + 7 files changed, 84 insertions(+), 109 deletions(-) diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c index 5cdd96f29a9e..03f919ffb413 100644 --- a/drivers/scsi/isci/core/sci_util.c +++ b/drivers/scsi/isci/core/sci_util.c @@ -53,7 +53,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "sci_util.h" +#include "sci_environment.h" void scic_word_copy_with_swap( u32 *destination, @@ -68,3 +70,17 @@ void scic_word_copy_with_swap( } } +void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr) +{ + struct isci_request *ireq = sci_object_get_association(sci_req); + dma_addr_t offset; + + BUG_ON(phys_addr < ireq->request_daddr); + + offset = phys_addr - ireq->request_daddr; + + BUG_ON(offset >= ireq->request_alloc_size); + + return (char *)ireq + offset; +} + diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h index 9748c76df387..50c272ebcdef 100644 --- a/drivers/scsi/isci/core/sci_util.h +++ b/drivers/scsi/isci/core/sci_util.h @@ -57,6 +57,7 @@ #define _SCI_UTIL_H_ #include +#include "scic_sds_request.h" /** * SCIC_SWAP_DWORD() - @@ -96,9 +97,9 @@ * byte swap. * */ -void scic_word_copy_with_swap( - u32 *destination, - u32 *source, - u32 word_count); +void scic_word_copy_with_swap(u32 *destination, u32 *source, u32 word_count); + +void *scic_request_get_virt_addr(struct scic_sds_request *sds_request, + dma_addr_t phys_addr); #endif /* _SCI_UTIL_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 2bd47f49e536..9fa45cd0fc46 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -99,15 +99,6 @@ * * SCIC SDS IO REQUEST MACROS * **************************************************************************** */ -/** - * scic_sds_request_get_user_request() - - * - * This is a helper macro to return the os handle for this request object. - */ -#define scic_sds_request_get_user_request(request) \ - ((request)->user_request) - - /** * scic_ssp_io_request_get_object_size() - * diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 0691a7552a2a..60337e6981c7 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -400,6 +400,14 @@ extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_start (scu_sge).address_modifier = 0; \ } +/** + * scic_sds_request_get_user_request() - + * + * This is a helper macro to return the os handle for this request object. + */ +#define scic_sds_request_get_user_request(request) \ + ((request)->user_request) + /* * ***************************************************************************** * * CORE REQUEST PROTOTYPES diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 6d280c0a2fc3..10f160e6ab43 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -486,45 +486,34 @@ void *scic_stp_io_request_get_d2h_reg_address( * - if there are more SGL element pairs - advance to the next pair and return * element A struct scu_sgl_element* */ -struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl( - struct scic_sds_stp_request *this_request - ) { +struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) +{ struct scu_sgl_element *current_sgl; + struct scic_sds_request *sci_req = &stp_req->parent; + struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current; - if (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - if ( - (this_request->type.pio.request_current.sgl_pair->B.address_lower == 0) - && (this_request->type.pio.request_current.sgl_pair->B.address_upper == 0) - ) { + if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + if (pio_sgl->sgl_pair->B.address_lower == 0 && + pio_sgl->sgl_pair->B.address_upper == 0) { current_sgl = NULL; } else { - this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_B; - current_sgl = &(this_request->type.pio.request_current.sgl_pair->B); + pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B; + current_sgl = &pio_sgl->sgl_pair->B; } } else { - if ( - (this_request->type.pio.request_current.sgl_pair->next_pair_lower == 0) - && (this_request->type.pio.request_current.sgl_pair->next_pair_upper == 0) - ) { + if (pio_sgl->sgl_pair->next_pair_lower == 0 && + pio_sgl->sgl_pair->next_pair_upper == 0) { current_sgl = NULL; } else { - dma_addr_t physical_address; - - sci_cb_make_physical_address( - physical_address, - this_request->type.pio.request_current.sgl_pair->next_pair_upper, - this_request->type.pio.request_current.sgl_pair->next_pair_lower - ); + u64 phys_addr; - this_request->type.pio.request_current.sgl_pair = - (struct scu_sgl_element_pair *)scic_cb_get_virtual_address( - this_request->parent.owning_controller, - physical_address - ); + phys_addr = pio_sgl->sgl_pair->next_pair_upper; + phys_addr <<= 32; + phys_addr |= pio_sgl->sgl_pair->next_pair_lower; - this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; - - current_sgl = &(this_request->type.pio.request_current.sgl_pair->A); + pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr); + pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A; + current_sgl = &pio_sgl->sgl_pair->A; } } @@ -882,82 +871,51 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data( /** * - * @this_request: The request that is used for the SGL processing. + * @stp_request: The request that is used for the SGL processing. * @data_buffer: The buffer of data to be copied. * @length: The length of the data transfer. * * Copy the data from the buffer for the length specified to the IO reqeust SGL * specified data region. enum sci_status */ -static enum sci_status scic_sds_stp_request_pio_data_in_copy_data_buffer( - struct scic_sds_stp_request *this_request, - u8 *data_buffer, - u32 length) +static enum sci_status +scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req, + u8 *data_buf, u32 len) { - enum sci_status status; - struct scu_sgl_element *current_sgl; - u32 sgl_offset; - u32 data_offset; - u8 *source_address; - u8 *destination_address; - u32 copy_length; - - /* Initial setup to get the current working SGL and the offset within the buffer */ - current_sgl = - (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ? - &(this_request->type.pio.request_current.sgl_pair->A) : - &(this_request->type.pio.request_current.sgl_pair->B); - - sgl_offset = this_request->type.pio.request_current.sgl_offset; - - source_address = data_buffer; - data_offset = 0; - - status = SCI_SUCCESS; - - /* While we are still doing Ok and there is more data to transfer */ - while ( - (length > 0) - && (status == SCI_SUCCESS) - ) { - if (current_sgl->length == sgl_offset) { - /* This SGL has been exauhasted so we need to get the next SGL */ - current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request); - - if (current_sgl == NULL) - status = SCI_FAILURE; - else - sgl_offset = 0; - } else { - dma_addr_t physical_address; - - sci_cb_make_physical_address( - physical_address, - current_sgl->address_upper, - current_sgl->address_lower - ); - - destination_address = (u8 *)scic_cb_get_virtual_address( - this_request->parent.owning_controller, - physical_address - ); - - source_address += data_offset; - destination_address += sgl_offset; - - copy_length = min(length, current_sgl->length - sgl_offset); - - memcpy(destination_address, source_address, copy_length); - - length -= copy_length; - sgl_offset += copy_length; - data_offset += copy_length; + struct scic_sds_request *sci_req; + struct isci_request *ireq; + u8 *src_addr; + int copy_len; + struct sas_task *task; + struct scatterlist *sg; + void *kaddr; + int total_len = len; + + sci_req = &stp_req->parent; + ireq = scic_sds_request_get_user_request(sci_req); + task = isci_request_access_task(ireq); + src_addr = data_buf; + + if (task->num_scatter > 0) { + sg = task->scatter; + + while (total_len > 0) { + struct page *page = sg_page(sg); + + copy_len = min_t(int, total_len, sg_dma_len(sg)); + kaddr = kmap_atomic(page, KM_IRQ0); + memcpy(kaddr + sg->offset, src_addr, copy_len); + kunmap_atomic(kaddr, KM_IRQ0); + total_len -= copy_len; + src_addr += copy_len; + sg = sg_next(sg); } + } else { + BUG_ON(task->total_xfer_len < total_len); + memcpy(task->scatter, src_addr, total_len); } - this_request->type.pio.request_current.sgl_offset = sgl_offset; - - return status; + return SCI_SUCCESS; } /** diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index 4a4c68aa56de..c950bb33ee04 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -116,7 +116,7 @@ struct scic_sds_stp_request { */ u8 sat_protocol; - struct { + struct scic_sds_request_pio_sgl { struct scu_sgl_element_pair *sgl_pair; u8 sgl_set; u32 sgl_offset; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 6c79b29f3102..225764f9d935 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -84,6 +84,7 @@ #include "host.h" #include "timers.h" #include "sci_status.h" +#include "request.h" extern struct kmem_cache *isci_kmem_cache; extern struct isci_firmware *isci_firmware; -- cgit v1.2.3 From 6389a77596f36cf04ad8b1c7d43ec1d6cdfe89cb Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 23 Feb 2011 15:57:27 -0800 Subject: isci: have the driver use native SG calls and DMA-API Remove abstraction for SG building and get rid of callbacks for getting DMA memory mapping. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_util.c | 15 ++ drivers/scsi/isci/core/sci_util.h | 3 + drivers/scsi/isci/core/scic_sds_request.c | 208 +++++++++++---------- drivers/scsi/isci/core/scic_sds_request.h | 9 +- drivers/scsi/isci/core/scic_sds_smp_request.c | 119 ++++++------ .../scsi/isci/core/scic_sds_stp_packet_request.c | 20 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 99 +++++----- 7 files changed, 245 insertions(+), 228 deletions(-) diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c index 03f919ffb413..cb3e9f73828d 100644 --- a/drivers/scsi/isci/core/sci_util.c +++ b/drivers/scsi/isci/core/sci_util.c @@ -84,3 +84,18 @@ void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t ph return (char *)ireq + offset; } +dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request, + void *virt_addr) +{ + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sds_request); + + char *requested_addr = (char *)virt_addr; + char *base_addr = (char *)isci_request; + + BUG_ON(requested_addr < base_addr); + BUG_ON((requested_addr - base_addr) >= + isci_request->request_alloc_size); + + return isci_request->request_daddr + (requested_addr - base_addr); +} diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h index 50c272ebcdef..b6f43e27c615 100644 --- a/drivers/scsi/isci/core/sci_util.h +++ b/drivers/scsi/isci/core/sci_util.h @@ -102,4 +102,7 @@ void scic_word_copy_with_swap(u32 *destination, u32 *source, u32 word_count); void *scic_request_get_virt_addr(struct scic_sds_request *sds_request, dma_addr_t phys_addr); +dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request, + void *virt_addr); + #endif /* _SCI_UTIL_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 9fa45cd0fc46..3bad0bcdf840 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -259,56 +259,70 @@ static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( * the Scatter-Gather List. * */ -void scic_sds_request_build_sgl( - struct scic_sds_request *this_request) +void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) { - void *os_sge; - void *os_handle; - dma_addr_t physical_address; - u32 sgl_pair_index = 0; - struct scu_sgl_element_pair *scu_sgl_list = NULL; - struct scu_sgl_element_pair *previous_pair = NULL; - - os_handle = scic_sds_request_get_user_request(this_request); - scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge); - - while (os_sge != NULL) { - scu_sgl_list = - scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index); - - SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge); - - scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge); - - if (os_sge != NULL) { - SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge); - - scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge); - } else { - SCU_SGL_ZERO(scu_sgl_list->B); + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sds_request); + struct isci_host *isci_host = isci_request->isci_host; + struct sas_task *task = isci_request_access_task(isci_request); + struct scatterlist *sg = NULL; + dma_addr_t dma_addr; + u32 sg_idx = 0; + struct scu_sgl_element_pair *scu_sg = NULL; + struct scu_sgl_element_pair *prev_sg = NULL; + + if (task->num_scatter > 0) { + sg = task->scatter; + + while (sg) { + scu_sg = scic_sds_request_get_sgl_element_pair( + sds_request, + sg_idx); + + SCU_SGL_COPY(scu_sg->A, sg); + + sg = sg_next(sg); + + if (sg) { + SCU_SGL_COPY(scu_sg->B, sg); + sg = sg_next(sg); + } else + SCU_SGL_ZERO(scu_sg->B); + + if (prev_sg) { + dma_addr = + scic_io_request_get_dma_addr( + sds_request, + scu_sg); + + prev_sg->next_pair_upper = + upper_32_bits(dma_addr); + prev_sg->next_pair_lower = + lower_32_bits(dma_addr); + } + + prev_sg = scu_sg; + sg_idx++; } + } else { /* handle when no sg */ + scu_sg = scic_sds_request_get_sgl_element_pair(sds_request, + sg_idx); - if (previous_pair != NULL) { - scic_cb_io_request_get_physical_address( - scic_sds_request_get_controller(this_request), - this_request, - scu_sgl_list, - &physical_address - ); + dma_addr = dma_map_single(&isci_host->pdev->dev, + task->scatter, + task->total_xfer_len, + task->data_dir); - previous_pair->next_pair_upper = - upper_32_bits(physical_address); - previous_pair->next_pair_lower = - lower_32_bits(physical_address); - } + isci_request->zero_scatter_daddr = dma_addr; - previous_pair = scu_sgl_list; - sgl_pair_index++; + scu_sg->A.length = task->total_xfer_len; + scu_sg->A.address_upper = upper_32_bits(dma_addr); + scu_sg->A.address_lower = lower_32_bits(dma_addr); } - if (scu_sgl_list != NULL) { - scu_sgl_list->next_pair_upper = 0; - scu_sgl_list->next_pair_lower = 0; + if (scu_sg) { + scu_sg->next_pair_upper = 0; + scu_sg->next_pair_lower = 0; } } @@ -473,17 +487,17 @@ static void scic_sds_task_request_build_ssp_task_iu( * */ static void scu_ssp_reqeust_construct_task_context( - struct scic_sds_request *this_request, + struct scic_sds_request *sds_request, struct scu_task_context *task_context) { - dma_addr_t physical_address; - struct scic_sds_controller *owning_controller; + dma_addr_t dma_addr; + struct scic_sds_controller *controller; struct scic_sds_remote_device *target_device; struct scic_sds_port *target_port; - owning_controller = scic_sds_request_get_controller(this_request); - target_device = scic_sds_request_get_device(this_request); - target_port = scic_sds_request_get_port(this_request); + controller = scic_sds_request_get_controller(sds_request); + target_device = scic_sds_request_get_device(sds_request); + target_port = scic_sds_request_get_port(sds_request); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -492,7 +506,7 @@ static void scu_ssp_reqeust_construct_task_context( task_context->connection_rate = scic_remote_device_get_connection_rate(target_device); task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(owning_controller); + scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = scic_sds_port_get_index(target_port); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; @@ -500,7 +514,7 @@ static void scu_ssp_reqeust_construct_task_context( task_context->context_type = SCU_TASK_CONTEXT_TYPE; task_context->remote_node_index = - scic_sds_remote_device_get_index(this_request->target_device); + scic_sds_remote_device_get_index(sds_request->target_device); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -515,61 +529,55 @@ static void scu_ssp_reqeust_construct_task_context( /* task_context->type.ssp.tag = this_request->io_tag; */ task_context->task_phase = 0x01; - if (this_request->was_tag_assigned_by_user) { - /* Build the task context now since we have already read the data */ - this_request->post_context = ( - SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC - | ( - scic_sds_controller_get_protocol_engine_group(owning_controller) - << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT - ) - | ( - scic_sds_port_get_index(target_port) - << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT - ) - | scic_sds_io_tag_get_index(this_request->io_tag) - ); + if (sds_request->was_tag_assigned_by_user) { + /* + * Build the task context now since we have already read + * the data + */ + sds_request->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + scic_sds_io_tag_get_index(sds_request->io_tag)); } else { - /* Build the task context now since we have already read the data */ - this_request->post_context = ( - SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC - | ( - scic_sds_controller_get_protocol_engine_group(owning_controller) - << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT - ) - | ( - scic_sds_port_get_index(target_port) - << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT - ) - /* This is not assigned because we have to wait until we get a TCi */ - ); + /* + * Build the task context now since we have already read + * the data + * + * I/O tag index is not assigned because we have to wait + * until we get a TCi + */ + sds_request->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + owning_controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); } - /* Copy the physical address for the command buffer to the SCU Task Context */ - scic_cb_io_request_get_physical_address( - scic_sds_request_get_controller(this_request), - this_request, - this_request->command_buffer, - &physical_address - ); + /* + * Copy the physical address for the command buffer to the + * SCU Task Context + */ + dma_addr = scic_io_request_get_dma_addr(sds_request, + sds_request->command_buffer); - task_context->command_iu_upper = - upper_32_bits(physical_address); - task_context->command_iu_lower = - lower_32_bits(physical_address); + task_context->command_iu_upper = upper_32_bits(dma_addr); + task_context->command_iu_lower = lower_32_bits(dma_addr); - /* Copy the physical address for the response buffer to the SCU Task Context */ - scic_cb_io_request_get_physical_address( - scic_sds_request_get_controller(this_request), - this_request, - this_request->response_buffer, - &physical_address - ); + /* + * Copy the physical address for the response buffer to the + * SCU Task Context + */ + dma_addr = scic_io_request_get_dma_addr(sds_request, + sds_request->response_buffer); - task_context->response_iu_upper = - upper_32_bits(physical_address); - task_context->response_iu_lower = - lower_32_bits(physical_address); + task_context->response_iu_upper = upper_32_bits(dma_addr); + task_context->response_iu_lower = lower_32_bits(dma_addr); } /** diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 60337e6981c7..19b6feef373e 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -389,14 +389,13 @@ extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_start * This macro copys the SGL Element data from the host os to the hardware SGL * elment data */ -#define SCU_SGL_COPY(os_handle, scu_sge, os_sge) \ +#define SCU_SGL_COPY(scu_sge, os_sge) \ { \ - (scu_sge).length = \ - scic_cb_sge_get_length_field(os_handle, os_sge); \ + (scu_sge).length = sg_dma_len(sg); \ (scu_sge).address_upper = \ - upper_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \ + upper_32_bits(sg_dma_address(sg)); \ (scu_sge).address_lower = \ - lower_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \ + lower_32_bits(sg_dma_address(sg)); \ (scu_sge).address_modifier = 0; \ } diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 949d23e7452a..85c890630d60 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -234,37 +234,36 @@ enum sci_status scic_io_request_construct_smp( * */ static void scu_smp_request_construct_task_context( - struct scic_sds_request *this_request, + struct scic_sds_request *sds_request, struct smp_request *smp_request) { - dma_addr_t physical_address; - struct scic_sds_controller *owning_controller; + dma_addr_t dma_addr; + struct scic_sds_controller *controller; struct scic_sds_remote_device *target_device; struct scic_sds_port *target_port; struct scu_task_context *task_context; /* byte swap the smp request. */ - scic_word_copy_with_swap( - this_request->command_buffer, - (u32 *)smp_request, - sizeof(struct smp_request) / sizeof(u32) - ); + scic_word_copy_with_swap(sds_request->command_buffer, + (u32 *)smp_request, + sizeof(struct smp_request) / sizeof(u32)); - task_context = scic_sds_request_get_task_context(this_request); + task_context = scic_sds_request_get_task_context(sds_request); - owning_controller = scic_sds_request_get_controller(this_request); - target_device = scic_sds_request_get_device(this_request); - target_port = scic_sds_request_get_port(this_request); + controller = scic_sds_request_get_controller(sds_request); + target_device = scic_sds_request_get_device(sds_request); + target_port = scic_sds_request_get_port(sds_request); /* * Fill in the TC with the its required data - * 00h */ + * 00h + */ task_context->priority = 0; task_context->initiator_request = 1; task_context->connection_rate = scic_remote_device_get_connection_rate(target_device); task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(owning_controller); + scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = scic_sds_port_get_index(target_port); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; @@ -273,7 +272,8 @@ static void scu_smp_request_construct_task_context( task_context->context_type = SCU_TASK_CONTEXT_TYPE; /* 04h */ - task_context->remote_node_index = this_request->target_device->rnc->remote_node_index; + task_context->remote_node_index = + sds_request->target_device->rnc->remote_node_index; task_context->command_code = 0; task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; @@ -289,7 +289,8 @@ static void scu_smp_request_construct_task_context( task_context->address_modifier = 0; /* 10h */ - task_context->ssp_command_iu_length = smp_request->header.request_length; + task_context->ssp_command_iu_length = + smp_request->header.request_length; /* 14h */ task_context->transfer_length_bytes = 0; @@ -298,59 +299,57 @@ static void scu_smp_request_construct_task_context( * 18h ~ 30h, protocol specific * since commandIU has been build by framework at this point, we just * copy the frist DWord from command IU to this location. */ - memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(u32)); + memcpy((void *)(&task_context->type.smp), + sds_request->command_buffer, + sizeof(u32)); /* * 40h - * "For SMP you could program it to zero. We would prefer that way so that - * done code will be consistent." - Venki */ + * "For SMP you could program it to zero. We would prefer that way + * so that done code will be consistent." - Venki + */ task_context->task_phase = 0; - if (this_request->was_tag_assigned_by_user) { - /* Build the task context now since we have already read the data */ - this_request->post_context = ( - SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC - | ( - scic_sds_controller_get_protocol_engine_group(owning_controller) - << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT - ) - | ( - scic_sds_port_get_index(target_port) - << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT - ) - | scic_sds_io_tag_get_index(this_request->io_tag) - ); + if (sds_request->was_tag_assigned_by_user) { + /* + * Build the task context now since we have already read + * the data + */ + sds_request->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + scic_sds_io_tag_get_index(sds_request->io_tag)); } else { - /* Build the task context now since we have already read the data */ - this_request->post_context = ( - SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC - | ( - scic_sds_controller_get_protocol_engine_group(owning_controller) - << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT - ) - | ( - scic_sds_port_get_index(target_port) - << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT - ) - /* This is not assigned because we have to wait until we get a TCi */ - ); + /* + * Build the task context now since we have already read + * the data. + * I/O tag index is not assigned because we have to wait + * until we get a TCi. + */ + sds_request->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); } /* - * Copy the physical address for the command buffer to the SCU Task Context - * command buffer should not contain command header. */ - scic_cb_io_request_get_physical_address( - scic_sds_request_get_controller(this_request), - this_request, - ((char *)(this_request->command_buffer) + sizeof(u32)), - &physical_address - ); - - task_context->command_iu_upper = - upper_32_bits(physical_address); - task_context->command_iu_lower = - lower_32_bits(physical_address); - + * Copy the physical address for the command buffer to the SCU Task + * Context command buffer should not contain command header. + */ + dma_addr = scic_io_request_get_dma_addr(sds_request, + (char *) + (sds_request->command_buffer) + + sizeof(u32)); + + task_context->command_iu_upper = upper_32_bits(dma_addr); + task_context->command_iu_lower = lower_32_bits(dma_addr); /* SMP response comes as UF, so no need to set response IU address. */ task_context->response_iu_upper = 0; diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c index f52a8e32b48f..97dc9bfa7b9c 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c @@ -253,30 +253,26 @@ enum sci_status scic_sds_stp_packet_request_process_status_fis( * */ void scic_sds_stp_packet_internal_request_sense_build_sgl( - struct scic_sds_request *this_request) + struct scic_sds_request *sds_request) { void *sge; struct scu_sgl_element_pair *scu_sgl_list = NULL; struct scu_task_context *task_context; - dma_addr_t physical_address; + dma_addr_t dma_addr; struct sci_ssp_response_iu *rsp_iu = - (struct sci_ssp_response_iu *)this_request->response_buffer; + (struct sci_ssp_response_iu *)sds_request->response_buffer; sge = (void *)&rsp_iu->data[0]; - task_context = (struct scu_task_context *)this_request->task_context_buffer; + task_context = + (struct scu_task_context *)sds_request->task_context_buffer; scu_sgl_list = &task_context->sgl_pair_ab; - scic_cb_io_request_get_physical_address( - scic_sds_request_get_controller(this_request), - this_request, - ((char *)sge), - &physical_address - ); + dma_addr = scic_io_request_get_dma_addr(sds_request, sge); - scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address); - scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address); + scu_sgl_list->A.address_upper = upper_32_bits(dma_addr); + scu_sgl_list->A.address_lower = lower_32_bits(dma_addr); scu_sgl_list->A.length = task_context->transfer_length_bytes; scu_sgl_list->A.address_modifier = 0; diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 10f160e6ab43..0a07207c8412 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -175,17 +175,17 @@ void scic_sds_stp_request_assign_buffers( * determine what is common for SSP/SMP/STP task context structures. */ static void scu_sata_reqeust_construct_task_context( - struct scic_sds_request *this_request, + struct scic_sds_request *sds_request, struct scu_task_context *task_context) { - dma_addr_t physical_address; - struct scic_sds_controller *owning_controller; + dma_addr_t dma_addr; + struct scic_sds_controller *controller; struct scic_sds_remote_device *target_device; struct scic_sds_port *target_port; - owning_controller = scic_sds_request_get_controller(this_request); - target_device = scic_sds_request_get_device(this_request); - target_port = scic_sds_request_get_port(this_request); + controller = scic_sds_request_get_controller(sds_request); + target_device = scic_sds_request_get_device(sds_request); + target_port = scic_sds_request_get_port(sds_request); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -194,7 +194,7 @@ static void scu_sata_reqeust_construct_task_context( task_context->connection_rate = scic_remote_device_get_connection_rate(target_device); task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(owning_controller); + scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = scic_sds_port_get_index(target_port); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; @@ -202,7 +202,7 @@ static void scu_sata_reqeust_construct_task_context( task_context->context_type = SCU_TASK_CONTEXT_TYPE; task_context->remote_node_index = - scic_sds_remote_device_get_index(this_request->target_device); + scic_sds_remote_device_get_index(sds_request->target_device); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -219,53 +219,50 @@ static void scu_sata_reqeust_construct_task_context( (sizeof(struct sata_fis_reg_h2d) - sizeof(u32)) / sizeof(u32); /* Set the first word of the H2D REG FIS */ - task_context->type.words[0] = *(u32 *)this_request->command_buffer; - - if (this_request->was_tag_assigned_by_user) { - /* Build the task context now since we have already read the data */ - this_request->post_context = ( - SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC - | ( - scic_sds_controller_get_protocol_engine_group(owning_controller) - << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT - ) - | ( - scic_sds_port_get_index(target_port) - << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT - ) - | scic_sds_io_tag_get_index(this_request->io_tag) - ); + task_context->type.words[0] = *(u32 *)sds_request->command_buffer; + + if (sds_request->was_tag_assigned_by_user) { + /* + * Build the task context now since we have already read + * the data + */ + sds_request->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + scic_sds_io_tag_get_index(sds_request->io_tag)); } else { - /* Build the task context now since we have already read the data */ - this_request->post_context = ( - SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC - | ( - scic_sds_controller_get_protocol_engine_group(owning_controller) - << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT - ) - | ( - scic_sds_port_get_index(target_port) - << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT - ) - /* This is not assigned because we have to wait until we get a TCi */ - ); + /* + * Build the task context now since we have already read + * the data. + * I/O tag index is not assigned because we have to wait + * until we get a TCi. + */ + sds_request->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); } /* - * Copy the physical address for the command buffer to the SCU Task Context - * We must offset the command buffer by 4 bytes because the first 4 bytes are - * transfered in the body of the TC */ - scic_cb_io_request_get_physical_address( - scic_sds_request_get_controller(this_request), - this_request, - ((char *)this_request->command_buffer) + sizeof(u32), - &physical_address - ); - - task_context->command_iu_upper = - upper_32_bits(physical_address); - task_context->command_iu_lower = - lower_32_bits(physical_address); + * Copy the physical address for the command buffer to the SCU Task + * Context. We must offset the command buffer by 4 bytes because the + * first 4 bytes are transfered in the body of the TC. + */ + dma_addr = + scic_io_request_get_dma_addr(sds_request, + (char *)sds_request-> + command_buffer + + sizeof(u32)); + + task_context->command_iu_upper = upper_32_bits(dma_addr); + task_context->command_iu_lower = lower_32_bits(dma_addr); /* SATA Requests do not have a response buffer */ task_context->response_iu_upper = 0; -- cgit v1.2.3 From a1914059f1434b0cdf113ebf16df627fd85689d0 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 23 Feb 2011 15:57:30 -0800 Subject: isci: Change event notify calls from scic_cb_* to isci_event_* Renaming the callbacks to apparopriate event notify calls for the LLDD. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 24 +- drivers/scsi/isci/core/scic_sds_phy.c | 14 +- drivers/scsi/isci/core/scic_sds_port.c | 37 ++- .../isci/core/scic_sds_port_configuration_agent.c | 10 +- drivers/scsi/isci/core/scic_sds_remote_device.c | 10 +- drivers/scsi/isci/core/scic_sds_request.c | 4 +- .../scsi/isci/core/scic_sds_smp_remote_device.c | 4 +- .../scsi/isci/core/scic_sds_stp_remote_device.c | 6 +- drivers/scsi/isci/core/scic_user_callback.h | 315 ------------------ drivers/scsi/isci/events.c | 90 ++--- drivers/scsi/isci/events.h | 370 +++++++++++++++++++++ drivers/scsi/isci/isci.h | 1 + 12 files changed, 476 insertions(+), 409 deletions(-) create mode 100644 drivers/scsi/isci/events.h diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index e8d09fd935ec..b0f9221d1454 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -256,7 +256,7 @@ static void scic_sds_controller_phy_startup_timeout_handler( void scic_sds_controller_initialize_phy_startup( struct scic_sds_controller *this_controller) { - this_controller->phy_startup_timer = scic_cb_timer_create( + this_controller->phy_startup_timer = isci_event_timer_create( this_controller, scic_sds_controller_phy_startup_timeout_handler, this_controller @@ -275,7 +275,7 @@ void scic_sds_controller_initialize_phy_startup( void scic_sds_controller_initialize_power_control( struct scic_sds_controller *this_controller) { - this_controller->power_control.timer = scic_cb_timer_create( + this_controller->power_control.timer = isci_event_timer_create( this_controller, scic_sds_controller_power_control_timer_handler, this_controller @@ -734,7 +734,7 @@ static void scic_sds_controller_transition_to_ready( SCI_BASE_CONTROLLER_STATE_READY ); - scic_cb_controller_start_complete(this_controller, status); + isci_event_controller_start_complete(this_controller, status); } } @@ -757,7 +757,7 @@ void scic_sds_controller_timeout_handler( sci_base_state_machine_change_state( scic_sds_controller_get_base_state_machine(scic), SCI_BASE_CONTROLLER_STATE_FAILED); - scic_cb_controller_stop_complete(scic, SCI_FAILURE_TIMEOUT); + isci_event_controller_stop_complete(scic, SCI_FAILURE_TIMEOUT); } else /* / @todo Now what do we want to do in this case? */ dev_err(scic_to_dev(scic), "%s: Controller timer fired when controller was not " @@ -823,7 +823,7 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) static void scic_sds_controller_phy_timer_start( struct scic_sds_controller *this_controller) { - scic_cb_timer_start( + isci_event_timer_start( this_controller, this_controller->phy_startup_timer, SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT @@ -840,7 +840,7 @@ static void scic_sds_controller_phy_timer_start( void scic_sds_controller_phy_timer_stop( struct scic_sds_controller *this_controller) { - scic_cb_timer_stop( + isci_event_timer_stop( this_controller, this_controller->phy_startup_timer ); @@ -1041,7 +1041,7 @@ enum sci_status scic_sds_controller_stop_devices( static void scic_sds_controller_power_control_timer_start( struct scic_sds_controller *this_controller) { - scic_cb_timer_start( + isci_event_timer_start( this_controller, this_controller->power_control.timer, SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL ); @@ -2809,7 +2809,7 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler( SCI_BASE_CONTROLLER_STATE_INITIALIZING ); - this_controller->timeout_timer = scic_cb_timer_create( + this_controller->timeout_timer = isci_event_timer_create( this_controller, (void (*)(void *))scic_sds_controller_timeout_handler, (void (*)(void *))controller); @@ -3040,7 +3040,7 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( if (SCI_SUCCESS == result) { scic_sds_controller_start_next_phy(this_controller); - scic_cb_timer_start(this_controller, + isci_event_timer_start(this_controller, this_controller->timeout_timer, timeout); @@ -3130,7 +3130,7 @@ static enum sci_status scic_sds_controller_ready_state_stop_handler( this_controller = (struct scic_sds_controller *)controller; - scic_cb_timer_start(this_controller, + isci_event_timer_start(this_controller, this_controller->timeout_timer, timeout); @@ -3578,7 +3578,7 @@ static void scic_sds_controller_starting_state_exit( { struct scic_sds_controller *scic = (struct scic_sds_controller *)object; - scic_cb_timer_stop(scic, scic->timeout_timer); + isci_event_timer_stop(scic, scic->timeout_timer); } /** @@ -3660,7 +3660,7 @@ static void scic_sds_controller_stopping_state_exit( this_controller = (struct scic_sds_controller *)object; - scic_cb_timer_stop(this_controller, this_controller->timeout_timer); + isci_event_timer_stop(this_controller, this_controller->timeout_timer); } /** diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index e8d5be73cd0b..92a5d294809d 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -370,7 +370,7 @@ enum sci_status scic_sds_phy_initialize( struct scu_link_layer_registers __iomem *link_layer_registers) { /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = scic_cb_timer_create( + sci_phy->sata_timeout_timer = isci_event_timer_create( scic_sds_phy_get_controller(sci_phy), scic_sds_phy_sata_timeout, sci_phy @@ -1746,7 +1746,7 @@ static void scic_sds_phy_starting_await_sata_phy_substate_enter( this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN ); - scic_cb_timer_start( + isci_event_timer_start( scic_sds_phy_get_controller(this_phy), this_phy->sata_timeout_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT @@ -1768,7 +1768,7 @@ static void scic_sds_phy_starting_await_sata_phy_substate_exit( this_phy = (struct scic_sds_phy *)object; - scic_cb_timer_stop( + isci_event_timer_stop( scic_sds_phy_get_controller(this_phy), this_phy->sata_timeout_timer ); @@ -1793,7 +1793,7 @@ static void scic_sds_phy_starting_await_sata_speed_substate_enter( this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN ); - scic_cb_timer_start( + isci_event_timer_start( scic_sds_phy_get_controller(this_phy), this_phy->sata_timeout_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT @@ -1815,7 +1815,7 @@ static void scic_sds_phy_starting_await_sata_speed_substate_exit( this_phy = (struct scic_sds_phy *)object; - scic_cb_timer_stop( + isci_event_timer_stop( scic_sds_phy_get_controller(this_phy), this_phy->sata_timeout_timer ); @@ -1854,7 +1854,7 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter( * condition is cleared. */ scic_sds_phy_resume(this_phy); - scic_cb_timer_start( + isci_event_timer_start( scic_sds_phy_get_controller(this_phy), this_phy->sata_timeout_timer, SCIC_SDS_SIGNATURE_FIS_TIMEOUT @@ -1879,7 +1879,7 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( this_phy = (struct scic_sds_phy *)object; - scic_cb_timer_stop( + isci_event_timer_stop( scic_sds_phy_get_controller(this_phy), this_phy->sata_timeout_timer ); diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index b8acc234a63d..f31e6dc42524 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -565,7 +565,7 @@ enum sci_status scic_sds_port_initialize( * the timer and start the state machine */ if (this_port->physical_port_index != SCI_MAX_PORTS) { /* / @todo should we create the timer at create time? */ - this_port->timer_handle = scic_cb_timer_create( + this_port->timer_handle = isci_event_timer_create( scic_sds_port_get_controller(this_port), scic_sds_port_timeout_handler, this_port @@ -727,7 +727,9 @@ void scic_sds_port_activate_phy( scic_sds_controller_clear_invalid_phy(controller, the_phy); if (do_notify_user == true) - scic_cb_port_link_up(this_port->owning_controller, this_port, the_phy); + isci_event_port_link_up(this_port->owning_controller, + this_port, + the_phy); } /** @@ -735,7 +737,8 @@ void scic_sds_port_activate_phy( * @this_port: This is the port on which the phy should be deactivated. * @the_phy: This is the specific phy that is no longer active in the port. * @do_notify_user: This parameter specifies whether to inform the user (via - * scic_cb_port_link_down()) as to the fact that a new phy as become ready. + * isci_event_port_link_down()) as to the fact that a new phy as become + * ready. * * This method will deactivate the supplied phy in the port. none */ @@ -752,7 +755,9 @@ void scic_sds_port_deactivate_phy( SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index); if (do_notify_user == true) - scic_cb_port_link_down(this_port->owning_controller, this_port, the_phy); + isci_event_port_link_down(this_port->owning_controller, + this_port, + the_phy); } /** @@ -775,7 +780,7 @@ static void scic_sds_port_invalid_link_up( if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0) { scic_sds_controller_set_invalid_phy(controller, the_phy); - scic_cb_port_invalid_link_up(controller, this_port, the_phy); + isci_event_port_invalid_link_up(controller, this_port, the_phy); } } @@ -933,7 +938,7 @@ static void scic_sds_port_timeout_handler(void *port) this_port); } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { /* if the port is still stopping then the stop has not completed */ - scic_cb_port_stop_complete( + isci_event_port_stop_complete( scic_sds_port_get_controller(this_port), port, SCI_FAILURE_TIMEOUT @@ -1030,7 +1035,7 @@ void scic_sds_port_broadcast_change_received( struct scic_sds_phy *this_phy) { /* notify the user. */ - scic_cb_port_bc_change_primitive_received( + isci_event_port_bc_change_primitive_received( this_port->owning_controller, this_port, this_phy ); } @@ -1259,7 +1264,7 @@ static enum sci_status scic_sds_port_ready_operational_substate_reset_handler( status = scic_sds_phy_reset(selected_phy); if (status == SCI_SUCCESS) { - scic_cb_timer_start( + isci_event_timer_start( scic_sds_port_get_controller(this_port), this_port->timer_handle, timeout @@ -1610,7 +1615,7 @@ static void scic_sds_port_ready_substate_operational_enter( this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL ); - scic_cb_port_ready( + isci_event_port_ready( scic_sds_port_get_controller(this_port), this_port ); @@ -1640,7 +1645,7 @@ static void scic_sds_port_ready_substate_operational_exit( { struct scic_sds_port *this_port = (struct scic_sds_port *)object; - scic_cb_port_not_ready( + isci_event_port_not_ready( scic_sds_port_get_controller(this_port), this_port, this_port->not_ready_reason @@ -1670,7 +1675,7 @@ static void scic_sds_port_ready_substate_configuring_enter( ); if (this_port->active_phy_mask == 0) { - scic_cb_port_not_ready( + isci_event_port_not_ready( scic_sds_port_get_controller(this_port), this_port, SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS @@ -2544,14 +2549,14 @@ static void scic_sds_port_ready_state_enter( SCI_BASE_PORT_STATE_RESETTING == this_port->parent.state_machine.previous_state_id ) { - scic_cb_port_hard_reset_complete( + isci_event_port_hard_reset_complete( scic_sds_port_get_controller(this_port), this_port, SCI_SUCCESS ); } else { /* Notify the caller that the port is not yet ready */ - scic_cb_port_not_ready( + isci_event_port_not_ready( scic_sds_port_get_controller(this_port), this_port, SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS @@ -2615,7 +2620,7 @@ static void scic_sds_port_resetting_state_exit( this_port = (struct scic_sds_port *)object; - scic_cb_timer_stop( + isci_event_timer_stop( scic_sds_port_get_controller(this_port), this_port->timer_handle ); @@ -2655,7 +2660,7 @@ static void scic_sds_port_stopping_state_exit( this_port = (struct scic_sds_port *)object; - scic_cb_timer_stop( + isci_event_timer_stop( scic_sds_port_get_controller(this_port), this_port->timer_handle ); @@ -2681,7 +2686,7 @@ static void scic_sds_port_failed_state_enter( SCI_BASE_PORT_STATE_FAILED ); - scic_cb_port_hard_reset_complete( + isci_event_port_hard_reset_complete( scic_sds_port_get_controller(this_port), this_port, SCI_FAILURE_TIMEOUT diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index 001472e75b8c..e26a4e69b3ac 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -463,7 +463,7 @@ static void scic_sds_mpc_agent_link_down( ) { port_agent->timer_pending = true; - scic_cb_timer_start( + isci_event_timer_start( controller, port_agent->timer, SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT @@ -542,12 +542,12 @@ static void scic_sds_apc_agent_start_timer( u32 timeout) { if (port_agent->timer_pending) { - scic_cb_timer_stop(controller, port_agent->timer); + isci_event_timer_stop(controller, port_agent->timer); } port_agent->timer_pending = true; - scic_cb_timer_start(controller, port_agent->timer, timeout); + isci_event_timer_start(controller, port_agent->timer, timeout); } /** @@ -830,7 +830,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize( port_agent->link_up_handler = scic_sds_mpc_agent_link_up; port_agent->link_down_handler = scic_sds_mpc_agent_link_down; - port_agent->timer = scic_cb_timer_create( + port_agent->timer = isci_event_timer_create( controller, scic_sds_mpc_agent_timeout_handler, controller @@ -841,7 +841,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize( port_agent->link_up_handler = scic_sds_apc_agent_link_up; port_agent->link_down_handler = scic_sds_apc_agent_link_down; - port_agent->timer = scic_cb_timer_create( + port_agent->timer = isci_event_timer_create( controller, scic_sds_apc_agent_timeout_handler, controller diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index cb1cf397b96f..3a8d56364750 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1817,7 +1817,7 @@ static void scic_sds_remote_device_stopped_state_enter( * the stop operation has completed. */ if (this_device->parent.state_machine.previous_state_id == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) { - scic_cb_remote_device_stop_complete( + isci_event_remote_device_stop_complete( scic_sds_remote_device_get_controller(this_device), this_device, SCI_SUCCESS @@ -1848,7 +1848,7 @@ static void scic_sds_remote_device_starting_state_enter( SCI_BASE_REMOTE_DEVICE_STATE_STARTING ); - scic_cb_remote_device_not_ready( + isci_event_remote_device_not_ready( the_controller, this_device, SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED @@ -1871,7 +1871,7 @@ static void scic_sds_remote_device_starting_state_exit( /* * / @todo Check the device object for the proper return code for this * / callback */ - scic_cb_remote_device_start_complete( + isci_event_remote_device_start_complete( scic_sds_remote_device_get_controller(this_device), this_device, SCI_SUCCESS @@ -1905,7 +1905,7 @@ static void scic_sds_remote_device_ready_state_enter( if (this_device->has_ready_substate_machine) { sci_base_state_machine_start(&this_device->ready_substate_machine); } else { - scic_cb_remote_device_ready(the_controller, this_device); + isci_event_remote_device_ready(the_controller, this_device); } } @@ -1928,7 +1928,7 @@ static void scic_sds_remote_device_ready_state_exit( if (this_device->has_ready_substate_machine) { sci_base_state_machine_stop(&this_device->ready_substate_machine); } else { - scic_cb_remote_device_not_ready( + isci_event_remote_device_not_ready( the_controller, this_device, SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 3bad0bcdf840..909361f680f8 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -2078,14 +2078,14 @@ static void scic_sds_request_completed_state_enter( /* Tell the SCI_USER that the IO request is complete */ if (this_request->is_task_management_request == false) { - scic_cb_io_request_complete( + isci_event_io_request_complete( scic_sds_request_get_controller(this_request), scic_sds_request_get_device(this_request), this_request, this_request->sci_status ); } else { - scic_cb_task_request_complete( + isci_event_task_request_complete( scic_sds_request_get_controller(this_request), scic_sds_request_get_device(this_request), this_request, diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index ea608c1ad8cb..e90d46edd064 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -265,7 +265,7 @@ static void scic_sds_smp_remote_device_ready_idle_substate_enter( SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE ); - scic_cb_remote_device_ready( + isci_event_remote_device_ready( scic_sds_remote_device_get_controller(this_device), this_device); } @@ -291,7 +291,7 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter( SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD ); - scic_cb_remote_device_not_ready( + isci_event_remote_device_not_ready( scic_sds_remote_device_get_controller(this_device), this_device, SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index 880e0e5932c0..ce2cb7b4c7cf 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -667,7 +667,7 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl * the ready notification. */ if (this_device->ready_substate_machine.previous_state_id != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) { - scic_cb_remote_device_ready( + isci_event_remote_device_ready( scic_sds_remote_device_get_controller(this_device), this_device ); } @@ -741,7 +741,7 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter( SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD ); - scic_cb_remote_device_not_ready( + isci_event_remote_device_not_ready( scic_sds_remote_device_get_controller(this_device), this_device, SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED @@ -799,7 +799,7 @@ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( if (this_device->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) { - scic_cb_remote_device_not_ready( + isci_event_remote_device_not_ready( scic_sds_remote_device_get_controller(this_device), this_device, this_device->not_ready_reason diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h index d1a3cb885bc7..c097711c5f2c 100644 --- a/drivers/scsi/isci/core/scic_user_callback.h +++ b/drivers/scsi/isci/core/scic_user_callback.h @@ -73,62 +73,6 @@ struct scic_sds_port; struct scic_sds_remote_device; struct scic_sds_controller; -/** - * scic_cb_timer_create() - This callback method asks the user to create a - * timer and provide a handle for this timer for use in further timer - * interactions. - * @controller: This parameter specifies the controller with which this timer - * is to be associated. - * @timer_callback: This parameter specifies the callback method to be invoked - * whenever the timer expires. - * @cookie: This parameter specifies a piece of information that the user must - * retain. This cookie is to be supplied by the user anytime a timeout - * occurs for the created timer. - * - * The "timer_callback" method should be executed in a mutually exlusive manner - * from the controller completion handler handler. This method returns a handle - * to a timer object created by the user. The handle will be utilized for all - * further interactions relating to this timer. - */ -void *scic_cb_timer_create( - struct scic_sds_controller *controller, - void (*timer_callback)(void *), - void *cookie); - - -/** - * scic_cb_timer_start() - This callback method asks the user to start the - * supplied timer. - * @controller: This parameter specifies the controller with which this timer - * is to associated. - * @timer: This parameter specifies the timer to be started. - * @milliseconds: This parameter specifies the number of milliseconds for which - * to stall. The operating system driver is allowed to round this value up - * where necessary. - * - * All timers in the system started by the SCI Core are one shot timers. - * Therefore, the SCI user should make sure that it removes the timer from it's - * list when a timer actually fires. Additionally, SCI Core user's should be - * able to handle calls from the SCI Core to stop a timer that may already be - * stopped. none - */ -void scic_cb_timer_start( - struct scic_sds_controller *controller, - void *timer, - u32 milliseconds); - -/** - * scic_cb_timer_stop() - This callback method asks the user to stop the - * supplied timer. - * @controller: This parameter specifies the controller with which this timer - * is to associated. - * @timer: This parameter specifies the timer to be stopped. - * - */ -void scic_cb_timer_stop( - struct scic_sds_controller *controller, - void *timer); - /** * scic_cb_stall_execution() - This method is called when the core requires the * OS driver to stall execution. This method is utilized during @@ -142,67 +86,6 @@ void scic_cb_timer_stop( void scic_cb_stall_execution( u32 microseconds); -/** - * scic_cb_controller_start_complete() - This user callback will inform the - * user that the controller has finished the start process. - * @controller: This parameter specifies the controller that was started. - * @completion_status: This parameter specifies the results of the start - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void scic_cb_controller_start_complete( - struct scic_sds_controller *controller, - enum sci_status completion_status); - -/** - * scic_cb_controller_stop_complete() - This user callback will inform the user - * that the controller has finished the stop process. - * @controller: This parameter specifies the controller that was stopped. - * @completion_status: This parameter specifies the results of the stop - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void scic_cb_controller_stop_complete( - struct scic_sds_controller *controller, - enum sci_status completion_status); - -/** - * scic_cb_io_request_complete() - This user callback will inform the user that - * an IO request has completed. - * @controller: This parameter specifies the controller on which the IO is - * completing. - * @remote_device: This parameter specifies the remote device on which this IO - * request is completing. - * @io_request: This parameter specifies the IO request that has completed. - * @completion_status: This parameter specifies the results of the IO request - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void scic_cb_io_request_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *io_request, - enum sci_io_status completion_status); - -/** - * scic_cb_task_request_complete() - This user callback will inform the user - * that a task management request completed. - * @controller: This parameter specifies the controller on which the task - * management request is completing. - * @remote_device: This parameter specifies the remote device on which this - * task management request is completing. - * @task_request: This parameter specifies the task management request that has - * completed. - * @completion_status: This parameter specifies the results of the IO request - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void scic_cb_task_request_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *task_request, - enum sci_task_status completion_status); - #ifndef SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED /** * scic_cb_io_request_get_physical_address() - This callback method asks the @@ -508,204 +391,6 @@ void *scic_cb_get_virtual_address( struct scic_sds_controller *controller, dma_addr_t physical_address); -/** - * scic_cb_port_stop_complete() - This method informs the user when a stop - * operation on the port has completed. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @completion_status: This parameter specifies the status for the operation - * being completed. - * - */ -void scic_cb_port_stop_complete( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - enum sci_status completion_status); - -/** - * scic_cb_port_hard_reset_complete() - This method informs the user when a - * hard reset on the port has completed. This hard reset could have been - * initiated by the user or by the remote port. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @completion_status: This parameter specifies the status for the operation - * being completed. - * - */ -void scic_cb_port_hard_reset_complete( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - enum sci_status completion_status); - -/** - * scic_cb_port_ready() - This method informs the user that the port is now in - * a ready state and can be utilized to issue IOs. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * - */ -void scic_cb_port_ready( - struct scic_sds_controller *controller, - struct scic_sds_port *port); - -/** - * scic_cb_port_not_ready() - This method informs the user that the port is now - * not in a ready (i.e. busy) state and can't be utilized to issue IOs. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @reason_code: This parameter specifies the reason for the port not ready - * callback. - * - */ -void scic_cb_port_not_ready( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - u32 reason_code); - -/** - * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that - * a phy/link became ready, but the phy is not allowed in the port. In some - * situations the underlying hardware only allows for certain phy to port - * mappings. If these mappings are violated, then this API is invoked. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @phy: This parameter specifies the phy that came ready, but the phy can't be - * a valid member of the port. - * - */ -void scic_cb_port_invalid_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy); - -/** - * scic_cb_port_bc_change_primitive_received() - This callback method informs - * the user that a broadcast change primitive was received. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. For instances where the phy on which the primitive was - * received is not part of a port, this parameter will be - * NULL. - * @phy: This parameter specifies the phy on which the primitive was received. - * - */ -void scic_cb_port_bc_change_primitive_received( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy); - - - - -/** - * scic_cb_port_link_up() - This callback method informs the user that a phy - * has become operational and is capable of communicating with the remote - * end point. - * @controller: This parameter represents the controller associated with the - * phy. - * @port: This parameter specifies the port object for which the user callback - * is being invoked. There may be conditions where this parameter can be - * NULL - * @phy: This parameter specifies the phy object for which the user callback is - * being invoked. - * - */ -void scic_cb_port_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy); - -/** - * scic_cb_port_link_down() - This callback method informs the user that a phy - * is no longer operational and is not capable of communicating with the - * remote end point. - * @controller: This parameter represents the controller associated with the - * phy. - * @port: This parameter specifies the port object for which the user callback - * is being invoked. There may be conditions where this parameter can be - * NULL - * @phy: This parameter specifies the phy object for which the user callback is - * being invoked. - * - */ -void scic_cb_port_link_down( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy); - -/** - * scic_cb_remote_device_start_complete() - This user callback method will - * inform the user that a start operation has completed. - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the completion callback. - * @completion_status: This parameter specifies the completion status for the - * operation. - * - */ -void scic_cb_remote_device_start_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - enum sci_status completion_status); - -/** - * scic_cb_remote_device_stop_complete() - This user callback method will - * inform the user that a stop operation has completed. - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the completion callback. - * @completion_status: This parameter specifies the completion status for the - * operation. - * - */ -void scic_cb_remote_device_stop_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - enum sci_status completion_status); - -/** - * scic_cb_remote_device_ready() - This user callback method will inform the - * user that a remote device is now capable of handling IO requests. - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the callback. - * - */ -void scic_cb_remote_device_ready( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device); - -/** - * scic_cb_remote_device_not_ready() - This user callback method will inform - * the user that a remote device is no longer capable of handling IO - * requests (until a ready callback is invoked). - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the callback. - * @reason_code: This paramete specifies the reason the remote device is not - * ready. - * - */ -void scic_cb_remote_device_not_ready( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - u32 reason_code); - #if !defined(DISABLE_ATAPI) /** * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback gets diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c index 6911ea5d1937..8872f4ca6aaa 100644 --- a/drivers/scsi/isci/events.c +++ b/drivers/scsi/isci/events.c @@ -64,9 +64,10 @@ #include "request.h" #include "sata.h" #include "task.h" +#include "events.h" /** - * scic_cb_timer_create() - This callback method asks the user to create a + * isci_event_timer_create() - This callback method asks the user to create a * timer and provide a handle for this timer for use in further timer * interactions. The appropriate isci timer object function is called to * create a timer object. @@ -81,7 +82,7 @@ * This method returns a handle to a timer object created by the user. The * handle will be utilized for all further interactions relating to this timer. */ -void *scic_cb_timer_create( +void *isci_event_timer_create( struct scic_sds_controller *controller, void (*timer_callback)(void *), void *cookie) @@ -107,7 +108,7 @@ void *scic_cb_timer_create( /** - * scic_cb_timer_start() - This callback method asks the user to start the + * isci_event_timer_start() - This callback method asks the user to start the * supplied timer. The appropriate isci timer object function is called to * start the timer. * @controller: This parameter specifies the controller with which this timer @@ -118,7 +119,7 @@ void *scic_cb_timer_create( * where necessary. * */ -void scic_cb_timer_start( +void isci_event_timer_start( struct scic_sds_controller *controller, void *timer, u32 milliseconds) @@ -137,7 +138,7 @@ void scic_cb_timer_start( } /** - * scic_cb_timer_stop() - This callback method asks the user to stop the + * isci_event_timer_stop() - This callback method asks the user to stop the * supplied timer. The appropriate isci timer object function is called to * stop the timer. * @controller: This parameter specifies the controller with which this timer @@ -145,7 +146,7 @@ void scic_cb_timer_start( * @timer: This parameter specifies the timer to be stopped. * */ -void scic_cb_timer_stop( +void isci_event_timer_stop( struct scic_sds_controller *controller, void *timer) { @@ -162,7 +163,7 @@ void scic_cb_timer_stop( } /** - * scic_cb_controller_start_complete() - This user callback will inform the + * isci_event_controller_start_complete() - This user callback will inform the * user that the controller has finished the start process. The associated * isci host adapter's start_complete function is called. * @controller: This parameter specifies the controller that was started. @@ -170,7 +171,7 @@ void scic_cb_timer_stop( * operation. SCI_SUCCESS indicates successful completion. * */ -void scic_cb_controller_start_complete( +void isci_event_controller_start_complete( struct scic_sds_controller *controller, enum sci_status completion_status) { @@ -184,7 +185,7 @@ void scic_cb_controller_start_complete( } /** - * scic_cb_controller_stop_complete() - This user callback will inform the user + * isci_event_controller_stop_complete() - This user callback will inform the user * that the controller has finished the stop process. The associated isci * host adapter's start_complete function is called. * @controller: This parameter specifies the controller that was stopped. @@ -192,7 +193,7 @@ void scic_cb_controller_start_complete( * operation. SCI_SUCCESS indicates successful completion. * */ -void scic_cb_controller_stop_complete( +void isci_event_controller_stop_complete( struct scic_sds_controller *controller, enum sci_status completion_status) { @@ -205,7 +206,7 @@ void scic_cb_controller_stop_complete( } /** - * scic_cb_io_request_complete() - This user callback will inform the user that + * isci_event_io_request_complete() - This user callback will inform the user that * an IO request has completed. * @controller: This parameter specifies the controller on which the IO is * completing. @@ -216,7 +217,7 @@ void scic_cb_controller_stop_complete( * operation. SCI_SUCCESS indicates successful completion. * */ -void scic_cb_io_request_complete( +void isci_event_io_request_complete( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, struct scic_sds_request *scic_io_request, @@ -239,7 +240,7 @@ void scic_cb_io_request_complete( } /** - * scic_cb_task_request_complete() - This user callback will inform the user + * isci_event_task_request_complete() - This user callback will inform the user * that a task management request completed. * @controller: This parameter specifies the controller on which the task * management request is completing. @@ -251,7 +252,7 @@ void scic_cb_io_request_complete( * operation. SCI_SUCCESS indicates successful completion. * */ -void scic_cb_task_request_complete( +void isci_event_task_request_complete( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, struct scic_sds_request *scic_task_request, @@ -271,7 +272,7 @@ void scic_cb_task_request_complete( } /** - * scic_cb_port_stop_complete() - This method informs the user when a stop + * isci_event_port_stop_complete() - This method informs the user when a stop * operation on the port has completed. * @controller: This parameter represents the controller which contains the * port. @@ -281,17 +282,20 @@ void scic_cb_task_request_complete( * being completed. * */ -void scic_cb_port_stop_complete( +void isci_event_port_stop_complete( struct scic_sds_controller *controller, struct scic_sds_port *port, enum sci_status completion_status) { - pr_warn("%s:************************************************\n", - __func__); + struct isci_host *isci_host; + + isci_host = (struct isci_host *)sci_object_get_association(controller); + + dev_notice(&isci_host->pdev->dev, "Port stop complete\n"); } /** - * scic_cb_port_hard_reset_complete() - This method informs the user when a + * isci_event_port_hard_reset_complete() - This method informs the user when a * hard reset on the port has completed. This hard reset could have been * initiated by the user or by the remote port. * @controller: This parameter represents the controller which contains the @@ -302,7 +306,7 @@ void scic_cb_port_stop_complete( * being completed. * */ -void scic_cb_port_hard_reset_complete( +void isci_event_port_hard_reset_complete( struct scic_sds_controller *controller, struct scic_sds_port *port, enum sci_status completion_status) @@ -314,7 +318,7 @@ void scic_cb_port_hard_reset_complete( } /** - * scic_cb_port_ready() - This method informs the user that the port is now in + * isci_event_port_ready() - This method informs the user that the port is now in * a ready state and can be utilized to issue IOs. * @controller: This parameter represents the controller which contains the * port. @@ -322,7 +326,7 @@ void scic_cb_port_hard_reset_complete( * is being invoked. * */ -void scic_cb_port_ready( +void isci_event_port_ready( struct scic_sds_controller *controller, struct scic_sds_port *port) { @@ -342,7 +346,7 @@ void scic_cb_port_ready( } /** - * scic_cb_port_not_ready() - This method informs the user that the port is now + * isci_event_port_not_ready() - This method informs the user that the port is now * not in a ready (i.e. busy) state and can't be utilized to issue IOs. * @controller: This parameter represents the controller which contains the * port. @@ -350,7 +354,7 @@ void scic_cb_port_ready( * is being invoked. * */ -void scic_cb_port_not_ready( +void isci_event_port_not_ready( struct scic_sds_controller *controller, struct scic_sds_port *port, u32 reason_code) @@ -371,7 +375,7 @@ void scic_cb_port_not_ready( } /** - * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that + * isci_event_port_invalid_link_up() - This method informs the SCI Core user that * a phy/link became ready, but the phy is not allowed in the port. In some * situations the underlying hardware only allows for certain phy to port * mappings. If these mappings are violated, then this API is invoked. @@ -383,17 +387,19 @@ void scic_cb_port_not_ready( * a valid member of the port. * */ -void scic_cb_port_invalid_link_up( +void isci_event_port_invalid_link_up( struct scic_sds_controller *controller, struct scic_sds_port *port, struct scic_sds_phy *phy) { - pr_warn("%s:************************************************\n", - __func__); + struct isci_host *isci_host; + + isci_host = (struct isci_host *)sci_object_get_association(controller); + dev_warn(&isci_host->pdev->dev, "Invalid link up!\n"); } /** - * scic_cb_port_bc_change_primitive_received() - This callback method informs + * isci_event_port_bc_change_primitive_received() - This callback method informs * the user that a broadcast change primitive was received. * @controller: This parameter represents the controller which contains the * port. @@ -403,7 +409,7 @@ void scic_cb_port_invalid_link_up( * @phy: This parameter specifies the phy on which the primitive was received. * */ -void scic_cb_port_bc_change_primitive_received( +void isci_event_port_bc_change_primitive_received( struct scic_sds_controller *controller, struct scic_sds_port *port, struct scic_sds_phy *phy) @@ -422,7 +428,7 @@ void scic_cb_port_bc_change_primitive_received( /** - * scic_cb_port_link_up() - This callback method informs the user that a phy + * isci_event_port_link_up() - This callback method informs the user that a phy * has become operational and is capable of communicating with the remote * end point. * @controller: This parameter represents the controller associated with the @@ -435,7 +441,7 @@ void scic_cb_port_bc_change_primitive_received( * * none. */ -void scic_cb_port_link_up( +void isci_event_port_link_up( struct scic_sds_controller *controller, struct scic_sds_port *port, struct scic_sds_phy *phy) @@ -452,7 +458,7 @@ void scic_cb_port_link_up( } /** - * scic_cb_port_link_down() - This callback method informs the user that a phy + * isci_event_port_link_down() - This callback method informs the user that a phy * is no longer operational and is not capable of communicating with the * remote end point. * @controller: This parameter represents the controller associated with the @@ -465,7 +471,7 @@ void scic_cb_port_link_up( * * none. */ -void scic_cb_port_link_down( +void isci_event_port_link_down( struct scic_sds_controller *controller, struct scic_sds_port *port, struct scic_sds_phy *phy) @@ -490,7 +496,7 @@ void scic_cb_port_link_down( } /** - * scic_cb_remote_device_start_complete() - This user callback method will + * isci_event_remote_device_start_complete() - This user callback method will * inform the user that a start operation has completed. * @controller: This parameter specifies the core controller associated with * the completion callback. @@ -500,7 +506,7 @@ void scic_cb_port_link_down( * operation. * */ -void scic_cb_remote_device_start_complete( +void isci_event_remote_device_start_complete( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, enum sci_status completion_status) @@ -525,7 +531,7 @@ void scic_cb_remote_device_start_complete( } /** - * scic_cb_remote_device_stop_complete() - This user callback method will + * isci_event_remote_device_stop_complete() - This user callback method will * inform the user that a stop operation has completed. * @controller: This parameter specifies the core controller associated with * the completion callback. @@ -535,7 +541,7 @@ void scic_cb_remote_device_start_complete( * operation. * */ -void scic_cb_remote_device_stop_complete( +void isci_event_remote_device_stop_complete( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, enum sci_status completion_status) @@ -560,7 +566,7 @@ void scic_cb_remote_device_stop_complete( } /** - * scic_cb_remote_device_ready() - This user callback method will inform the + * isci_event_remote_device_ready() - This user callback method will inform the * user that a remote device is now capable of handling IO requests. * @controller: This parameter specifies the core controller associated with * the completion callback. @@ -568,7 +574,7 @@ void scic_cb_remote_device_stop_complete( * the callback. * */ -void scic_cb_remote_device_ready( +void isci_event_remote_device_ready( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device) { @@ -583,7 +589,7 @@ void scic_cb_remote_device_ready( } /** - * scic_cb_remote_device_not_ready() - This user callback method will inform + * isci_event_remote_device_not_ready() - This user callback method will inform * the user that a remote device is no longer capable of handling IO * requests (until a ready callback is invoked). * @controller: This parameter specifies the core controller associated with @@ -594,7 +600,7 @@ void scic_cb_remote_device_ready( * going to a not ready state. * */ -void scic_cb_remote_device_not_ready( +void isci_event_remote_device_not_ready( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, u32 reason_code) diff --git a/drivers/scsi/isci/events.h b/drivers/scsi/isci/events.h new file mode 100644 index 000000000000..98526e9fb14a --- /dev/null +++ b/drivers/scsi/isci/events.h @@ -0,0 +1,370 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ISCI_EVENT_H_ +#define _ISCI_EVENT_H_ + +/** + * isci_event_timer_create() - This callback method asks the user to create a + * timer and provide a handle for this timer for use in further timer + * interactions. + * @controller: This parameter specifies the controller with which this timer + * is to be associated. + * @timer_callback: This parameter specifies the callback method to be invoked + * whenever the timer expires. + * @cookie: This parameter specifies a piece of information that the user must + * retain. This cookie is to be supplied by the user anytime a timeout + * occurs for the created timer. + * + * The "timer_callback" method should be executed in a mutually exlusive manner + * from the controller completion handler handler. This method returns a handle + * to a timer object created by the user. The handle will be utilized for all + * further interactions relating to this timer. + */ +void *isci_event_timer_create( + struct scic_sds_controller *controller, + void (*timer_callback)(void *), + void *cookie); + +/** + * isci_event_timer_start() - This callback method asks the user to start the + * supplied timer. + * @controller: This parameter specifies the controller with which this timer + * is to associated. + * @timer: This parameter specifies the timer to be started. + * @milliseconds: This parameter specifies the number of milliseconds for which + * to stall. The operating system driver is allowed to round this value up + * where necessary. + * + * All timers in the system started by the SCI Core are one shot timers. + * Therefore, the SCI user should make sure that it removes the timer from it's + * list when a timer actually fires. Additionally, SCI Core user's should be + * able to handle calls from the SCI Core to stop a timer that may already be + * stopped. none + */ +void isci_event_timer_start( + struct scic_sds_controller *controller, + void *timer, + u32 milliseconds); + +/** + * isci_event_timer_stop() - This callback method asks the user to stop the + * supplied timer. + * @controller: This parameter specifies the controller with which this timer + * is to associated. + * @timer: This parameter specifies the timer to be stopped. + * + */ +void isci_event_timer_stop( + struct scic_sds_controller *controller, + void *timer); + +/** + * isci_event_controller_start_complete() - This user callback will inform the + * user that the controller has finished the start process. + * @controller: This parameter specifies the controller that was started. + * @completion_status: This parameter specifies the results of the start + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void isci_event_controller_start_complete( + struct scic_sds_controller *controller, + enum sci_status completion_status); + +/** + * isci_event_controller_stop_complete() - This user callback will inform the + * user that the controller has finished the stop process. + * @controller: This parameter specifies the controller that was stopped. + * @completion_status: This parameter specifies the results of the stop + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void isci_event_controller_stop_complete( + struct scic_sds_controller *controller, + enum sci_status completion_status); + +/** + * isci_event_io_request_complete() - This user callback will inform the user + * that an IO request has completed. + * @controller: This parameter specifies the controller on which the IO is + * completing. + * @remote_device: This parameter specifies the remote device on which this IO + * request is completing. + * @io_request: This parameter specifies the IO request that has completed. + * @completion_status: This parameter specifies the results of the IO request + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void isci_event_io_request_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *scic_io_request, + enum sci_io_status completion_status); + +/** + * isci_event_task_request_complete() - This user callback will inform the user + * that a task management request completed. + * @controller: This parameter specifies the controller on which the task + * management request is completing. + * @remote_device: This parameter specifies the remote device on which this + * task management request is completing. + * @task_request: This parameter specifies the task management request that has + * completed. + * @completion_status: This parameter specifies the results of the IO request + * operation. SCI_SUCCESS indicates successful completion. + * + */ +void isci_event_task_request_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *scic_task_request, + enum sci_task_status completion_status); + +/** + * isci_event_port_stop_complete() - This method informs the user when a stop + * operation on the port has completed. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @completion_status: This parameter specifies the status for the operation + * being completed. + * + */ +void isci_event_port_stop_complete( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + enum sci_status completion_status); + +/** + * isci_event_port_hard_reset_complete() - This method informs the user when a + * hard reset on the port has completed. This hard reset could have been + * initiated by the user or by the remote port. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @completion_status: This parameter specifies the status for the operation + * being completed. + * + */ +void isci_event_port_hard_reset_complete( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + enum sci_status completion_status); + +/** + * isci_event_port_ready() - This method informs the user that the port is now + * in a ready state and can be utilized to issue IOs. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * + */ +void isci_event_port_ready( + struct scic_sds_controller *controller, + struct scic_sds_port *port); + +/** + * isci_event_port_not_ready() - This method informs the user that the port is + * now not in a ready (i.e. busy) state and can't be utilized to issue IOs. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @reason_code: This parameter specifies the reason for the port not ready + * callback. + * + */ +void isci_event_port_not_ready( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + u32 reason_code); + +/** + * isci_event_port_invalid_link_up() - This method informs the SCI Core user + * that a phy/link became ready, but the phy is not allowed in the port. In + * some situations the underlying hardware only allows for certain phy to port + * mappings. If these mappings are violated, then this API is invoked. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @phy: This parameter specifies the phy that came ready, but the phy can't be + * a valid member of the port. + * + */ +void isci_event_port_invalid_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +/** + * isci_event_port_bc_change_primitive_received() - This callback method informs + * the user that a broadcast change primitive was received. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. For instances where the phy on which the primitive was + * received is not part of a port, this parameter will be + * NULL. + * @phy: This parameter specifies the phy on which the primitive was received. + * + */ +void isci_event_port_bc_change_primitive_received( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +/** + * isci_event_port_link_up() - This callback method informs the user that a phy + * has become operational and is capable of communicating with the remote + * end point. + * @controller: This parameter represents the controller associated with the + * phy. + * @port: This parameter specifies the port object for which the user callback + * is being invoked. There may be conditions where this parameter can be + * NULL + * @phy: This parameter specifies the phy object for which the user callback is + * being invoked. + * + */ +void isci_event_port_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +/** + * isci_event_port_link_down() - This callback method informs the user that a + * phy is no longer operational and is not capable of communicating with the + * remote end point. + * @controller: This parameter represents the controller associated with the + * phy. + * @port: This parameter specifies the port object for which the user callback + * is being invoked. There may be conditions where this parameter can be + * NULL + * @phy: This parameter specifies the phy object for which the user callback is + * being invoked. + * + */ +void isci_event_port_link_down( + struct scic_sds_controller *controller, + struct scic_sds_port *port, + struct scic_sds_phy *phy); + +/** + * isci_event_remote_device_start_complete() - This user callback method will + * inform the user that a start operation has completed. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the completion callback. + * @completion_status: This parameter specifies the completion status for the + * operation. + * + */ +void isci_event_remote_device_start_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + enum sci_status completion_status); + +/** + * isci_event_remote_device_stop_complete() - This user callback method will + * inform the user that a stop operation has completed. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the completion callback. + * @completion_status: This parameter specifies the completion status for the + * operation. + * + */ +void isci_event_remote_device_stop_complete( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + enum sci_status completion_status); + +/** + * isci_event_remote_device_ready() - This user callback method will inform the + * user that a remote device is now capable of handling IO requests. + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the callback. + * + */ +void isci_event_remote_device_ready( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device); + +/** + * isci_event_remote_device_not_ready() - This user callback method will inform + * the user that a remote device is no longer capable of handling IO + * requests (until a ready callback is invoked). + * @controller: This parameter specifies the core controller associated with + * the completion callback. + * @remote_device: This parameter specifies the remote device associated with + * the callback. + * @reason_code: This paramete specifies the reason the remote device is not + * ready. + * + */ +void isci_event_remote_device_not_ready( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device, + u32 reason_code); + +#endif diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 225764f9d935..9ec91f8e5fda 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -85,6 +85,7 @@ #include "timers.h" #include "sci_status.h" #include "request.h" +#include "events.h" extern struct kmem_cache *isci_kmem_cache; extern struct isci_firmware *isci_firmware; -- cgit v1.2.3 From 7392d27580df2d14b5c3b1a1d7989c06457a819d Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 23 Feb 2011 15:57:33 -0800 Subject: isci: Removing deprecated functions Removed all callbacks in the deprecated.c. Core will call the appropriate functions directly. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 2 +- drivers/scsi/isci/core/scic_sds_controller.c | 43 +- drivers/scsi/isci/core/scic_sds_phy.c | 1 - drivers/scsi/isci/core/scic_sds_port.c | 1 - drivers/scsi/isci/core/scic_sds_remote_device.c | 1 - drivers/scsi/isci/core/scic_sds_request.c | 93 ++-- .../scsi/isci/core/scic_sds_smp_remote_device.c | 1 - .../scsi/isci/core/scic_sds_stp_remote_device.c | 104 ++--- drivers/scsi/isci/core/scic_sds_stp_request.c | 1 - .../isci/core/scic_sds_unsolicited_frame_control.c | 1 - drivers/scsi/isci/core/scic_user_callback.h | 421 ------------------ drivers/scsi/isci/deprecated.c | 485 --------------------- drivers/scsi/isci/host.h | 1 - drivers/scsi/isci/isci.h | 2 + drivers/scsi/isci/remote_device.h | 1 - drivers/scsi/isci/sata.c | 2 +- 16 files changed, 130 insertions(+), 1030 deletions(-) delete mode 100644 drivers/scsi/isci/core/scic_user_callback.h delete mode 100644 drivers/scsi/isci/deprecated.c diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 34f7af3525f4..d402d679a316 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -8,7 +8,7 @@ EXTRA_CFLAGS += -DDISABLE_ATAPI EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ - remote_device.o port.o timers.o deprecated.o \ + remote_device.o port.o timers.o \ host.o task.o events.o \ core/scic_sds_controller.o \ core/scic_sds_remote_device.o \ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index b0f9221d1454..d642ff7be6db 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -66,7 +66,6 @@ #include "scic_sds_port.h" #include "scic_sds_remote_device.h" #include "scic_sds_request.h" -#include "scic_user_callback.h" #include "sci_environment.h" #include "sci_util.h" #include "scu_completion_codes.h" @@ -594,7 +593,7 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) /* Clear DFX Status registers */ scu_afe_register_write(scic, afe_dfx_master_control0, 0x0081000f); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); /* Configure bias currents to normal */ if (is_a0()) @@ -602,7 +601,7 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) else scu_afe_register_write(scic, afe_bias_control, 0x00005A00); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); /* Enable PLL */ if (is_b0()) @@ -610,35 +609,35 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) else scu_afe_register_write(scic, afe_pll_control0, 0x80040908); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); /* Wait for the PLL to lock */ do { afe_status = scu_afe_register_read( scic, afe_common_block_status); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); } while ((afe_status & 0x00001000) == 0); if (is_b0()) { /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ scu_afe_register_write(scic, afe_pmsn_master_control0, 0x7bcc96ad); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); } for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { if (is_b0()) { /* Configure transmitter SSC parameters */ scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); } else { /* * All defaults, except the Receive Word Alignament/Comma Detect * Enable....(0xe800) */ scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004512); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); scu_afe_txreg_write(scic, phy_id, afe_xcvr_control1, 0x0050100F); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); } /* @@ -651,26 +650,26 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) else { /* Power down TX and RX (PWRDNTX and PWRDNRX) */ scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d7); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); /* * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) * & increase TX int & ext bias 20%....(0xe85c) */ scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d4); } - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); if (is_a0() || is_a2()) { /* Enable TX equalization (0xe824) */ scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); } /* * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On), * RDD=0x0(RX Detect Enabled) ....(0xe800) */ scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004100); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); /* Leave DFE/FFE on */ if (is_a0()) @@ -679,28 +678,28 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F); else { scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); /* Enable TX equalization (0xe824) */ scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000); } - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, 0x000E7C03); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control1, 0x000E7C03); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control2, 0x000E7C03); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control3, 0x000E7C03); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); } /* Transfer control to the PEs */ scu_afe_register_write(scic, afe_dfx_master_control0, 0x00010f00); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); + udelay(AFE_REGISTER_WRITE_DELAY); } /* @@ -2446,7 +2445,7 @@ void scic_sds_controller_reset_hardware( SMU_SMUSRCR_WRITE(scic, 0xFFFFFFFF); /* Delay for 1ms to before clearing the CQP and UFQPR. */ - scic_cb_stall_execution(1000); + udelay(1000); /* The write to the CQGR clears the CQP */ SMU_CQGR_WRITE(scic, 0x00000000); @@ -2840,7 +2839,7 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler( while (terminate_loop-- && (result != SCI_SUCCESS)) { /* Loop until the hardware reports success */ - scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME); + udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME); status = SMU_SMUCSR_READ(this_controller); if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) { diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 92a5d294809d..d4a5e38aef65 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -63,7 +63,6 @@ #include "scic_sds_phy_registers.h" #include "scic_sds_port.h" #include "scic_sds_remote_node_context.h" -#include "scic_user_callback.h" #include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index f31e6dc42524..d374c7ac0b71 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -66,7 +66,6 @@ #include "scic_sds_remote_device.h" #include "scic_sds_remote_node_context.h" #include "scic_sds_request.h" -#include "scic_user_callback.h" #include "sci_environment.h" diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 3a8d56364750..a7cb4bc39a11 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -64,7 +64,6 @@ #include "scic_sds_remote_device.h" #include "scic_sds_remote_node_context.h" #include "scic_sds_request.h" -#include "scic_user_callback.h" #include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 909361f680f8..7b9ce1e878a7 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -70,7 +70,6 @@ #include "scic_sds_smp_request.h" #include "scic_sds_stp_request.h" #include "scic_sds_unsolicited_frame_control.h" -#include "scic_user_callback.h" #include "sci_environment.h" #include "sci_util.h" #include "scu_completion_codes.h" @@ -413,25 +412,26 @@ static void scic_sds_ssp_io_request_assign_buffers( * */ static void scic_sds_io_request_build_ssp_command_iu( - struct scic_sds_request *this_request) + struct scic_sds_request *sds_request) { struct sci_ssp_command_iu *command_frame; - void *os_handle; u32 cdb_length; u32 *cdb_buffer; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sds_request); command_frame = - (struct sci_ssp_command_iu *)this_request->command_buffer; - - os_handle = scic_sds_request_get_user_request(this_request); + (struct sci_ssp_command_iu *)sds_request->command_buffer; command_frame->lun_upper = 0; - command_frame->lun_lower = scic_cb_ssp_io_request_get_lun(os_handle); + command_frame->lun_lower = + isci_request_ssp_io_request_get_lun(isci_request); ((u32 *)command_frame)[2] = 0; - cdb_length = scic_cb_ssp_io_request_get_cdb_length(os_handle); - cdb_buffer = (u32 *)scic_cb_ssp_io_request_get_cdb_address(os_handle); + cdb_length = isci_request_ssp_io_request_get_cdb_length(isci_request); + cdb_buffer = (u32 *)isci_request_ssp_io_request_get_cdb_address( + isci_request); if (cdb_length > 16) { command_frame->additional_cdb_length = cdb_length - 16; @@ -446,9 +446,9 @@ static void scic_sds_io_request_build_ssp_command_iu( command_frame->enable_first_burst = 0; command_frame->task_priority = - scic_cb_ssp_io_request_get_command_priority(os_handle); + isci_request_ssp_io_request_get_command_priority(isci_request); command_frame->task_attribute = - scic_cb_ssp_io_request_get_task_attribute(os_handle); + isci_request_ssp_io_request_get_task_attribute(isci_request); } @@ -458,25 +458,26 @@ static void scic_sds_io_request_build_ssp_command_iu( * */ static void scic_sds_task_request_build_ssp_task_iu( - struct scic_sds_request *this_request) + struct scic_sds_request *sds_request) { struct sci_ssp_task_iu *command_frame; - void *os_handle; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sds_request); command_frame = - (struct sci_ssp_task_iu *)this_request->command_buffer; - - os_handle = scic_sds_request_get_user_request(this_request); + (struct sci_ssp_task_iu *)sds_request->command_buffer; command_frame->lun_upper = 0; - command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle); + command_frame->lun_lower = isci_request_ssp_io_request_get_lun( + isci_request); ((u32 *)command_frame)[2] = 0; command_frame->task_function = - scic_cb_ssp_task_request_get_function(os_handle); + isci_task_ssp_request_get_function(isci_request); command_frame->task_tag = - scic_cb_ssp_task_request_get_io_tag_to_manage(os_handle); + isci_task_ssp_request_get_io_tag_to_manage( + isci_request); } @@ -899,18 +900,15 @@ enum sci_status scic_task_request_construct( enum sci_status scic_io_request_construct_basic_ssp( struct scic_sds_request *sci_req) { - void *os_handle; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sci_req); sci_req->protocol = SCIC_SSP_PROTOCOL; - os_handle = scic_sds_request_get_user_request(sci_req); - scu_ssp_io_request_construct_task_context( sci_req, - scic_cb_io_request_get_data_direction(os_handle), - scic_cb_io_request_get_transfer_length(os_handle) - ); - + isci_request_io_request_get_data_direction(isci_request), + isci_request_io_request_get_transfer_length(isci_request)); scic_sds_io_request_build_ssp_command_iu(sci_req); @@ -941,7 +939,8 @@ enum sci_status scic_task_request_construct_ssp( } -enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_request *sci_req) +enum sci_status scic_io_request_construct_basic_sata( + struct scic_sds_request *sci_req) { enum sci_status status; struct scic_sds_stp_request *stp_req; @@ -949,15 +948,18 @@ enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_request *sc u32 len; enum dma_data_direction dir; bool copy = false; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sci_req); + struct sas_task *task = isci_request_access_task(isci_request); stp_req = container_of(sci_req, typeof(*stp_req), parent); sci_req->protocol = SCIC_STP_PROTOCOL; - len = scic_cb_io_request_get_transfer_length(sci_req->user_request); - dir = scic_cb_io_request_get_data_direction(sci_req->user_request); - proto = scic_cb_request_get_sat_protocol(sci_req->user_request); - copy = scic_cb_io_request_do_copy_rx_frames(stp_req->parent.user_request); + len = isci_request_io_request_get_transfer_length(isci_request); + dir = isci_request_io_request_get_data_direction(isci_request); + proto = isci_sata_get_sat_protocol(isci_request); + copy = (task->data_dir == DMA_NONE) ? false : true; status = scic_io_request_construct_sata(sci_req, proto, len, dir, copy); @@ -975,7 +977,11 @@ enum sci_status scic_task_request_construct_sata( struct scic_sds_request *sci_req) { enum sci_status status; - u8 sat_protocol = scic_cb_request_get_sat_protocol(sci_req->user_request); + u8 sat_protocol; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sci_req); + + sat_protocol = isci_sata_get_sat_protocol(isci_request); switch (sat_protocol) { case SAT_PROTOCOL_ATA_HARD_RESET: @@ -1172,27 +1178,28 @@ enum sci_status scic_sds_io_request_frame_handler( * the response data. * */ -void scic_sds_io_request_copy_response( - struct scic_sds_request *this_request) +void scic_sds_io_request_copy_response(struct scic_sds_request *sds_request) { void *response_buffer; u32 user_response_length; u32 core_response_length; struct sci_ssp_response_iu *ssp_response; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sds_request); - ssp_response = (struct sci_ssp_response_iu *)this_request->response_buffer; + ssp_response = + (struct sci_ssp_response_iu *)sds_request->response_buffer; - response_buffer = scic_cb_ssp_task_request_get_response_data_address( - this_request->user_request - ); + response_buffer = + isci_task_ssp_request_get_response_data_address( + isci_request); - user_response_length = scic_cb_ssp_task_request_get_response_data_length( - this_request->user_request - ); + user_response_length = + isci_task_ssp_request_get_response_data_length( + isci_request); core_response_length = sci_ssp_get_response_data_length( - ssp_response->response_data_length - ); + ssp_response->response_data_length); user_response_length = min(user_response_length, core_response_length); diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index e90d46edd064..93e6ab83b01d 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -58,7 +58,6 @@ #include "scic_sds_port.h" #include "scic_sds_remote_device.h" #include "scic_sds_request.h" -#include "scic_user_callback.h" #include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index ce2cb7b4c7cf..1d8d9013068f 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -62,7 +62,6 @@ #include "scic_sds_port.h" #include "scic_sds_remote_device.h" #include "scic_sds_request.h" -#include "scic_user_callback.h" #include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" @@ -217,52 +216,56 @@ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_h * @device: * @request: * - * If this is a softreset we may want to have a different substate. enum sci_status + * If this is a softreset we may want to have a different substate. + * enum sci_status */ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( - struct sci_base_remote_device *device, - struct sci_base_request *request) + struct sci_base_remote_device *base_device, + struct sci_base_request *base_request) { enum sci_status status; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - struct scic_sds_request *io_request = (struct scic_sds_request *)request; + struct scic_sds_remote_device *device = + (struct scic_sds_remote_device *)&base_device->parent; + struct scic_sds_request *sds_request = + (struct scic_sds_request *)&base_request->parent; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sds_request); /* Will the port allow the io request to start? */ - status = this_device->owning_port->state_handlers->start_io_handler( - this_device->owning_port, - this_device, - io_request - ); + status = device->owning_port->state_handlers->start_io_handler( + device->owning_port, + device, + sds_request); if (status == SCI_SUCCESS) { status = - scic_sds_remote_node_context_start_io(this_device->rnc, io_request); + scic_sds_remote_node_context_start_io(device->rnc, + sds_request); - if (status == SCI_SUCCESS) { - status = io_request->state_handlers->parent.start_handler(request); - } + if (status == SCI_SUCCESS) + status = + sds_request->state_handlers-> + parent.start_handler(base_request); if (status == SCI_SUCCESS) { - if ( - scic_cb_request_get_sat_protocol(io_request->user_request) - == SAT_PROTOCOL_FPDMA - ) { + if (isci_sata_get_sat_protocol(isci_request) == + SAT_PROTOCOL_FPDMA) sci_base_state_machine_change_state( - &this_device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ - ); - } else { - this_device->working_request = io_request; + &device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); + else { + device->working_request = sds_request; sci_base_state_machine_change_state( - &this_device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD - ); + &device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); } } - scic_sds_remote_device_start_request(this_device, io_request, status); + scic_sds_remote_device_start_request(device, + sds_request, + status); } return status; @@ -304,35 +307,38 @@ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_hand * ***************************************************************************** */ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( - struct sci_base_remote_device *device, - struct sci_base_request *request) + struct sci_base_remote_device *base_device, + struct sci_base_request *base_request) { enum sci_status status; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - struct scic_sds_request *io_request = (struct scic_sds_request *)request; - - if ( - scic_cb_request_get_sat_protocol(io_request->user_request) - == SAT_PROTOCOL_FPDMA - ) { - status = this_device->owning_port->state_handlers->start_io_handler( - this_device->owning_port, - this_device, - io_request - ); + struct scic_sds_remote_device *device = + (struct scic_sds_remote_device *)&base_device->parent; + struct scic_sds_request *sds_request = + (struct scic_sds_request *)&base_request->parent; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(sds_request); + + if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { + status = device->owning_port->state_handlers->start_io_handler( + device->owning_port, + device, + sds_request); if (status == SCI_SUCCESS) { - status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request); + status = scic_sds_remote_node_context_start_io( + device->rnc, + sds_request); - if (status == SCI_SUCCESS) { - status = io_request->state_handlers->parent.start_handler(request); - } + if (status == SCI_SUCCESS) + status = sds_request->state_handlers-> + parent.start_handler(base_request); - scic_sds_remote_device_start_request(this_device, io_request, status); + scic_sds_remote_device_start_request(device, + sds_request, + status); } - } else { + } else status = SCI_FAILURE_INVALID_STATE; - } return status; } diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 0a07207c8412..0f17a28dd196 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -67,7 +67,6 @@ #include "scic_sds_stp_pio_request.h" #include "scic_sds_stp_request.h" #include "scic_sds_unsolicited_frame_control.h" -#include "scic_user_callback.h" #include "sci_environment.h" #include "sci_util.h" #include "scu_completion_codes.h" diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c index 7274812af507..66be58b002d9 100644 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c @@ -64,7 +64,6 @@ #include "scic_sds_unsolicited_frame_control.h" #include "scu_registers.h" #include "scic_sds_controller.h" -#include "scic_user_callback.h" #include "sci_util.h" #include "sci_environment.h" diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h deleted file mode 100644 index c097711c5f2c..000000000000 --- a/drivers/scsi/isci/core/scic_user_callback.h +++ /dev/null @@ -1,421 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_USER_CALLBACK_H_ -#define _SCIC_USER_CALLBACK_H_ - -/** - * This file contains all of the interface methods/macros that must be - * implemented by an SCI Core user. - * - * - */ - - -#include "sci_status.h" -#include "scic_io_request.h" - -struct scic_sds_request; -struct scic_sds_phy; -struct scic_sds_port; -struct scic_sds_remote_device; -struct scic_sds_controller; - -/** - * scic_cb_stall_execution() - This method is called when the core requires the - * OS driver to stall execution. This method is utilized during - * initialization or non-performance paths only. - * @microseconds: This parameter specifies the number of microseconds for which - * to stall. The operating system driver is allowed to round this value up - * where necessary. - * - * none. - */ -void scic_cb_stall_execution( - u32 microseconds); - -#ifndef SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED -/** - * scic_cb_io_request_get_physical_address() - This callback method asks the - * user to provide the physical address for the supplied virtual address - * when building an io request object. - * @controller: This parameter is the core controller object handle. - * @io_request: This parameter is the io request object handle for which the - * physical address is being requested. - * @virtual_address: This paramter is the virtual address which is to be - * returned as a physical address. - * @physical_address: The physical address for the supplied virtual address. - * - * None. - */ -void scic_cb_io_request_get_physical_address( - struct scic_sds_controller *controller, - struct scic_sds_request *io_request, - void *virtual_address, - dma_addr_t *physical_address); -#endif /* SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED */ - -/** - * scic_cb_io_request_get_transfer_length() - This callback method asks the - * user to provide the number of bytes to be transfered as part of this - * request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the number of payload data bytes to be transfered for - * this IO request. - */ -u32 scic_cb_io_request_get_transfer_length( - void *scic_user_io_request); - -/** - * scic_cb_io_request_get_data_direction() - This callback method asks the user - * to provide the data direction for this request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - */ -enum dma_data_direction scic_cb_io_request_get_data_direction(void *req); - -#ifndef SCI_SGL_OPTIMIZATION_ENABLED -/** - * scic_cb_io_request_get_next_sge() - This callback method asks the user to - * provide the address to where the next Scatter-Gather Element is located. - * Details regarding usage: - Regarding the first SGE: the user should - * initialize an index, or a pointer, prior to construction of the request - * that will reference the very first scatter-gather element. This is - * important since this method is called for every scatter-gather element, - * including the first element. - Regarding the last SGE: the user should - * return NULL from this method when this method is called and the SGL has - * exhausted all elements. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * @current_sge_address: This parameter specifies the address for the current - * SGE (i.e. the one that has just processed). - * @next_sge: An address specifying the location for the next scatter gather - * element to be processed. - * - * None - */ -void scic_cb_io_request_get_next_sge( - void *scic_user_io_request, - void *current_sge_address, - void **next_sge); -#endif /* SCI_SGL_OPTIMIZATION_ENABLED */ - -/** - * scic_cb_sge_get_address_field() - This callback method asks the user to - * provide the contents of the "address" field in the Scatter-Gather Element. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * @sge_address: This parameter specifies the address for the SGE from which to - * retrieve the address field. - * - * A physical address specifying the contents of the SGE's address field. - */ -dma_addr_t scic_cb_sge_get_address_field( - void *scic_user_io_request, - void *sge_address); - -/** - * scic_cb_sge_get_length_field() - This callback method asks the user to - * provide the contents of the "length" field in the Scatter-Gather Element. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * @sge_address: This parameter specifies the address for the SGE from which to - * retrieve the address field. - * - * This method returns the length field specified inside the SGE referenced by - * the sge_address parameter. - */ -u32 scic_cb_sge_get_length_field( - void *scic_user_io_request, - void *sge_address); - -/** - * scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the - * user to provide the address for the command descriptor block (CDB) - * associated with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the virtual address of the CDB. - */ -void *scic_cb_ssp_io_request_get_cdb_address( - void *scic_user_io_request); - -/** - * scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user - * to provide the length of the command descriptor block (CDB) associated - * with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the length of the CDB. - */ -u32 scic_cb_ssp_io_request_get_cdb_length( - void *scic_user_io_request); - -/** - * scic_cb_ssp_io_request_get_lun() - This callback method asks the user to - * provide the Logical Unit (LUN) associated with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * The contents of the value returned from this callback are defined by the - * protocol standard (e.g. T10 SAS specification). Please refer to the - * transport command information unit description in the associated standard. - * This method returns the LUN associated with this request. This should be u64? - */ -u32 scic_cb_ssp_io_request_get_lun( - void *scic_user_io_request); - -/** - * scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the - * user to provide the task attribute associated with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * The contents of the value returned from this callback are defined by the - * protocol standard (e.g. T10 SAS specification). Please refer to the - * transport command information unit description in the associated standard. - * This method returns the task attribute associated with this IO request. - */ -u32 scic_cb_ssp_io_request_get_task_attribute( - void *scic_user_io_request); - -/** - * scic_cb_ssp_io_request_get_command_priority() - This callback method asks - * the user to provide the command priority associated with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * The contents of the value returned from this callback are defined by the - * protocol standard (e.g. T10 SAS specification). Please refer to the - * transport command information unit description in the associated standard. - * This method returns the command priority associated with this IO request. - */ -u32 scic_cb_ssp_io_request_get_command_priority( - void *scic_user_io_request); - -/** - * scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user - * if the received RX frame data is to be copied to the SGL or should be - * stored by the SCI core to be retrieved later with the - * scic_io_request_get_rx_frame(). - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns true if the SCI core should copy the received frame data - * to the SGL location or false if the SCI user wants to retrieve the frame - * data at a later time. - */ -bool scic_cb_io_request_do_copy_rx_frames( - void *scic_user_io_request); - -/** - * scic_cb_request_get_sat_protocol() - This callback method asks the user to - * return the SAT protocol definition for this IO request. This method is - * only called by the SCI core if the request type constructed is SATA. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns one of the sat.h defined protocols for the given io - * request. - */ -u8 scic_cb_request_get_sat_protocol( - void *scic_user_io_request); - - -/** - * scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to - * be utilized for this task management request. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * The contents of the value returned from this callback are defined by the - * protocol standard (e.g. T10 SAS specification). Please refer to the - * transport task information unit description in the associated standard. This - * method returns the LUN associated with this request. This should be u64? - */ -u32 scic_cb_ssp_task_request_get_lun( - void *scic_user_task_request); - -/** - * scic_cb_ssp_task_request_get_function() - This method returns the task - * management function to be utilized for this task request. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * The contents of the value returned from this callback are defined by the - * protocol standard (e.g. T10 SAS specification). Please refer to the - * transport task information unit description in the associated standard. This - * method returns an unsigned byte representing the task management function to - * be performed. - */ -u8 scic_cb_ssp_task_request_get_function( - void *scic_user_task_request); - -/** - * scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the - * task management IO tag to be managed. Depending upon the task management - * function the value returned from this method may be ignored. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns an unsigned 16-bit word depicting the IO tag to be - * managed. - */ -u16 scic_cb_ssp_task_request_get_io_tag_to_manage( - void *scic_user_task_request); - -/** - * scic_cb_ssp_task_request_get_response_data_address() - This callback method - * asks the user to provide the virtual address of the response data buffer - * for the supplied IO request. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the virtual address for the response data buffer - * associated with this IO request. - */ -void *scic_cb_ssp_task_request_get_response_data_address( - void *scic_user_task_request); - -/** - * scic_cb_ssp_task_request_get_response_data_length() - This callback method - * asks the user to provide the length of the response data buffer for the - * supplied IO request. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the length of the response buffer data associated with - * this IO request. - */ -u32 scic_cb_ssp_task_request_get_response_data_length( - void *scic_user_task_request); - -/** - * scic_cb_pci_get_bar() - In this method the user must return the base address - * register (BAR) value for the supplied base address register number. - * @controller: The controller for which to retrieve the bar number. - * @bar_number: This parameter depicts the BAR index/number to be read. - * - * Return a pointer value indicating the contents of the BAR. NULL indicates an - * invalid BAR index/number was specified. All other values indicate a valid - * VIRTUAL address from the BAR. - */ -void *scic_cb_pci_get_bar( - struct scic_sds_controller *controller, - u16 bar_number); - -/** - * scic_cb_get_virtual_address() - This callback method asks the user to - * provide the virtual address for the supplied physical address. - * @controller: This parameter is the core controller object handle. - * @physical_address: This parameter is the physical address which is to be - * returned as a virtual address. - * - * The method returns the virtual address for the supplied physical address. - */ -void *scic_cb_get_virtual_address( - struct scic_sds_controller *controller, - dma_addr_t physical_address); - -#if !defined(DISABLE_ATAPI) -/** - * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback gets - * from stp packet io's user request the CDB address. - * @scic_user_io_request: - * - * The cdb adress. - */ -void *scic_cb_stp_packet_io_request_get_cdb_address( - void *scic_user_io_request); - -/** - * scic_cb_stp_packet_io_request_get_cdb_length() - This user callback gets - * from stp packet io's user request the CDB length. - * @scic_user_io_request: - * - * The cdb length. - */ -u32 scic_cb_stp_packet_io_request_get_cdb_length( - void *scic_user_io_request); -#else /* !defined(DISABLE_ATAPI) */ -#define scic_cb_stp_packet_io_request_get_cdb_address(scic_user_io_request) NULL -#define scic_cb_stp_packet_io_request_get_cdb_length(scic_user_io_request) 0 -#endif /* !defined(DISABLE_ATAPI) */ - - -#endif /* _SCIC_USER_CALLBACK_H_ */ - diff --git a/drivers/scsi/isci/deprecated.c b/drivers/scsi/isci/deprecated.c deleted file mode 100644 index 0ee6679b8107..000000000000 --- a/drivers/scsi/isci/deprecated.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/** - * This file contains isci module object implementation. - * - * - */ - -#include "isci.h" -#include "request.h" -#include "sata.h" -#include "task.h" - - -/** - * scic_cb_stall_execution() - This method is called when the core requires the - * OS driver to stall execution. This method is utilized during - * initialization or non-performance paths only. - * @microseconds: This parameter specifies the number of microseconds for which - * to stall. The operating system driver is allowed to round this value up - * where necessary. - * - * none. - */ -void scic_cb_stall_execution( - u32 microseconds) -{ - udelay(microseconds); -} - - -/** - * scic_cb_io_request_get_physical_address() - This callback method asks the - * user to provide the physical address for the supplied virtual address - * when building an io request object. - * @controller: This parameter is the core controller object handle. - * @io_request: This parameter is the io request object handle for which the - * physical address is being requested. - * - * - */ -void scic_cb_io_request_get_physical_address( - struct scic_sds_controller *controller, - struct scic_sds_request *io_request, - void *virtual_address, - dma_addr_t *physical_address) -{ - struct isci_request *request = - (struct isci_request *)sci_object_get_association(io_request); - - char *requested_address = (char *)virtual_address; - char *base_address = (char *)request; - - BUG_ON(requested_address < base_address); - BUG_ON((requested_address - base_address) >= - request->request_alloc_size); - - *physical_address = request->request_daddr + - (requested_address - base_address); -} - -/** - * scic_cb_io_request_get_transfer_length() - This callback method asks the - * user to provide the number of bytes to be transfered as part of this - * request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the number of payload data bytes to be transfered for - * this IO request. - */ -u32 scic_cb_io_request_get_transfer_length( - void *scic_user_io_request) -{ - return isci_request_io_request_get_transfer_length( - scic_user_io_request - ); -} - - -/** - * scic_cb_io_request_get_data_direction() - This callback method asks the user - * to provide the data direction for this request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - */ -enum dma_data_direction scic_cb_io_request_get_data_direction(void *req) -{ - return isci_request_io_request_get_data_direction(req); -} - - -/** - * scic_cb_io_request_get_next_sge() - This callback method asks the user to - * provide the address to where the next Scatter-Gather Element is located. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * @current_sge_address: This parameter specifies the address for the current - * SGE (i.e. the one that has just processed). - * - * An address specifying the location for the next scatter gather element to be - * processed. - */ -void scic_cb_io_request_get_next_sge( - void *scic_user_io_request, - void *current_sge_address, - void **next_sge) -{ - *next_sge = isci_request_io_request_get_next_sge( - scic_user_io_request, - current_sge_address - ); -} - -/** - * scic_cb_sge_get_address_field() - This callback method asks the user to - * provide the contents of the "address" field in the Scatter-Gather Element. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * @sge_address: This parameter specifies the address for the SGE from which to - * retrieve the address field. - * - * A physical address specifying the contents of the SGE's address field. - */ -dma_addr_t scic_cb_sge_get_address_field( - void *scic_user_io_request, - void *sge_address) -{ - return isci_request_sge_get_address_field( - scic_user_io_request, - sge_address - ); -} - -/** - * scic_cb_sge_get_length_field() - This callback method asks the user to - * provide the contents of the "length" field in the Scatter-Gather Element. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * @sge_address: This parameter specifies the address for the SGE from which to - * retrieve the address field. - * - * This method returns the length field specified inside the SGE referenced by - * the sge_address parameter. - */ -u32 scic_cb_sge_get_length_field( - void *scic_user_io_request, - void *sge_address) -{ - return isci_request_sge_get_length_field( - scic_user_io_request, - sge_address - ); -} - -/** - * scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the - * user to provide the address for the command descriptor block (CDB) - * associated with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the virtual address of the CDB. - */ -void *scic_cb_ssp_io_request_get_cdb_address( - void *scic_user_io_request) -{ - return isci_request_ssp_io_request_get_cdb_address( - scic_user_io_request - ); -} - -/** - * scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user - * to provide the length of the command descriptor block (CDB) associated - * with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the length of the CDB. - */ -u32 scic_cb_ssp_io_request_get_cdb_length( - void *scic_user_io_request) -{ - return isci_request_ssp_io_request_get_cdb_length( - scic_user_io_request - ); -} - -/** - * scic_cb_ssp_io_request_get_lun() - This callback method asks the user to - * provide the Logical Unit (LUN) associated with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the LUN associated with this request. This should be u64? - */ -u32 scic_cb_ssp_io_request_get_lun( - void *scic_user_io_request) -{ - return isci_request_ssp_io_request_get_lun(scic_user_io_request); -} - -/** - * scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the - * user to provide the task attribute associated with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the task attribute associated with this IO request. - */ -u32 scic_cb_ssp_io_request_get_task_attribute( - void *scic_user_io_request) -{ - return isci_request_ssp_io_request_get_task_attribute( - scic_user_io_request - ); -} - -/** - * scic_cb_ssp_io_request_get_command_priority() - This callback method asks - * the user to provide the command priority associated with this IO request. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the command priority associated with this IO request. - */ -u32 scic_cb_ssp_io_request_get_command_priority( - void *scic_user_io_request) -{ - return isci_request_ssp_io_request_get_command_priority( - scic_user_io_request - ); -} - -/** - * scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to - * be utilized for this task management request. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the LUN associated with this request. This should be u64? - */ -u32 scic_cb_ssp_task_request_get_lun( - void *scic_user_task_request) -{ - return isci_task_ssp_request_get_lun( - (struct isci_request *)scic_user_task_request - ); -} - -/** - * scic_cb_ssp_task_request_get_function() - This method returns the task - * management function to be utilized for this task request. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns an unsigned byte representing the task management - * function to be performed. - */ -u8 scic_cb_ssp_task_request_get_function( - void *scic_user_task_request) -{ - return isci_task_ssp_request_get_function( - (struct isci_request *)scic_user_task_request - ); -} - -/** - * scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the - * task management IO tag to be managed. Depending upon the task management - * function the value returned from this method may be ignored. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns an unsigned 16-bit word depicting the IO tag to be - * managed. - */ -u16 scic_cb_ssp_task_request_get_io_tag_to_manage( - void *scic_user_task_request) -{ - return isci_task_ssp_request_get_io_tag_to_manage( - (struct isci_request *)scic_user_task_request - ); -} - -/** - * scic_cb_ssp_task_request_get_response_data_address() - This callback method - * asks the user to provide the virtual address of the response data buffer - * for the supplied IO request. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the virtual address for the response data buffer - * associated with this IO request. - */ -void *scic_cb_ssp_task_request_get_response_data_address( - void *scic_user_task_request) -{ - return isci_task_ssp_request_get_response_data_address( - (struct isci_request *)scic_user_task_request - ); -} - -/** - * scic_cb_ssp_task_request_get_response_data_length() - This callback method - * asks the user to provide the length of the response data buffer for the - * supplied IO request. - * @scic_user_task_request: This parameter points to the user's task request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns the length of the response buffer data associated with - * this IO request. - */ -u32 scic_cb_ssp_task_request_get_response_data_length( - void *scic_user_task_request) -{ - return isci_task_ssp_request_get_response_data_length( - (struct isci_request *)scic_user_task_request - ); -} - -#if !defined(DISABLE_ATAPI) -/** - * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback asks - * the user to provide stp packet io's the CDB address. - * @scic_user_io_request: - * - * The packet IO's cdb adress. - */ -void *scic_cb_stp_packet_io_request_get_cdb_address( - void *scic_user_io_request) -{ - return isci_request_stp_packet_io_request_get_cdb_address( - scic_user_io_request - ); -} - - -/** - * scic_cb_stp_packet_io_request_get_cdb_length() - This user callback asks the - * user to provide stp packet io's the CDB length. - * @scic_user_io_request: - * - * The packet IO's cdb length. - */ -u32 scic_cb_stp_packet_io_request_get_cdb_length( - void *scic_user_io_request) -{ - return isci_request_stp_packet_io_request_get_cdb_length( - scic_user_io_request - ); -} -#endif /* #if !defined(DISABLE_ATAPI) */ - - -/** - * scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user - * if the received RX frame data is to be copied to the SGL or should be - * stored by the SCI core to be retrieved later with the - * scic_io_request_get_rx_frame(). - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns true if the SCI core should copy the received frame data - * to the SGL location or false if the SCI user wants to retrieve the frame - * data at a later time. - */ -bool scic_cb_io_request_do_copy_rx_frames( - void *scic_user_io_request) -{ - struct sas_task *task - = isci_request_access_task( - (struct isci_request *)scic_user_io_request - ); - - return (task->data_dir == DMA_NONE) ? false : true; -} - -/** - * scic_cb_get_virtual_address() - This callback method asks the user to - * provide the virtual address for the supplied physical address. - * @controller: This parameter is the core controller object handle. - * @physical_address: This parameter is the physical address which is to be - * returned as a virtual address. - * - * The method returns the virtual address for the supplied physical address. - */ -void *scic_cb_get_virtual_address( - struct scic_sds_controller *controller, - dma_addr_t physical_address) -{ - void *virt_addr = (void *)phys_to_virt(physical_address); - - return virt_addr; -} - -/** - * scic_cb_request_get_sat_protocol() - This callback method asks the user to - * return the SAT protocol definition for this IO request. This method is - * only called by the SCI core if the request type constructed is SATA. - * @scic_user_io_request: This parameter points to the user's IO request - * object. It is a cookie that allows the user to provide the necessary - * information for this callback. - * - * This method returns one of the sat.h defined protocols for the given io - * request. - */ -u8 scic_cb_request_get_sat_protocol( - void *scic_user_io_request) -{ - return isci_sata_get_sat_protocol( - (struct isci_request *)scic_user_io_request - ); -} diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 26768c5bbe01..06154a625aec 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -61,7 +61,6 @@ /*#include "task.h"*/ #include "timers.h" #include "remote_device.h" -#include "scic_user_callback.h" #define DRV_NAME "isci" #define SCI_PCI_BAR_COUNT 2 diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 9ec91f8e5fda..9b9aa50954ce 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -86,6 +86,8 @@ #include "sci_status.h" #include "request.h" #include "events.h" +#include "task.h" +#include "sata.h" extern struct kmem_cache *isci_kmem_cache; extern struct isci_firmware *isci_firmware; diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index a208f81785eb..48e37cfef6fb 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -55,7 +55,6 @@ #if !defined(_ISCI_REMOTE_DEVICE_H_) #define _ISCI_REMOTE_DEVICE_H_ -#include "scic_user_callback.h" struct isci_host; struct scic_sds_remote_device; diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 19b0eea93ca7..6fbf15944b21 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -324,7 +324,7 @@ int isci_task_send_lu_reset_sata( /* Leave SRST high for a bit. */ #define ISCI_SRST_ASSERT_DELAY 100 /* usecs */ - scic_cb_stall_execution(ISCI_SRST_ASSERT_DELAY); + udelay(ISCI_SRST_ASSERT_DELAY); /* Deassert SRST. */ isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_low, -- cgit v1.2.3 From 150fc6fc725055b400a8865e6785dc8dd0a2225d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 25 Feb 2011 10:25:21 -0800 Subject: isci: fix sas address reporting Undo the open coded and incorrect translation of the oem parameter sas address to its libsas expected format. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 5 ----- drivers/scsi/isci/host.h | 1 - drivers/scsi/isci/init.c | 2 +- drivers/scsi/isci/phy.c | 32 +++++++++++--------------------- drivers/scsi/isci/port.c | 17 +++++++---------- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index aa86615fa7a9..d8d6f67bd69c 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -517,11 +517,6 @@ int isci_host_init(struct isci_host *isci_host) for (index = 0; index < SCI_MAX_PHYS; index++) isci_phy_init(&isci_host->phys[index], isci_host, index); - /* Why are we doing this? Is this even necessary? */ - memcpy(&isci_host->sas_addr[0], - &isci_host->phys[0].sas_addr[0], - SAS_ADDR_SIZE); - /* Start the ports */ for (index = 0; index < SCI_MAX_PORTS; index++) { scic_controller_get_port_handle(controller, index, &scic_port); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 06154a625aec..b794dfd0819e 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -105,7 +105,6 @@ struct isci_host { spinlock_t state_lock; struct pci_dev *pdev; - u8 sas_addr[SAS_ADDR_SIZE]; enum isci_status status; #define IHOST_START_PENDING 0 diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 6ca623aff051..d01c44f5be99 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -209,7 +209,7 @@ static int isci_register_sas_ha(struct isci_host *isci_host) sas_ha->sas_ha_name = DRV_NAME; sas_ha->lldd_module = THIS_MODULE; - sas_ha->sas_addr = &(isci_host->sas_addr[0]); + sas_ha->sas_addr = &isci_host->phys[0].sas_addr[0]; /* set the array of phy and port structs. */ for (i = 0; i < SCI_MAX_PHYS; i++) { diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index fbda570d25e1..1eefaaeb1141 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -75,14 +75,15 @@ void isci_phy_init( struct isci_host *isci_host, int index) { - struct scic_sds_controller *controller = isci_host->core_controller; + struct scic_sds_controller *scic = isci_host->core_controller; struct scic_sds_phy *scic_phy; - union scic_oem_parameters oem_parameters; + union scic_oem_parameters oem; enum sci_status status = SCI_SUCCESS; + u64 sas_addr; /*--------------- SCU_Phy Initialization Stuff -----------------------*/ - status = scic_controller_get_phy_handle(controller, index, &scic_phy); + status = scic_controller_get_phy_handle(scic, index, &scic_phy); if (status == SCI_SUCCESS) { sci_object_set_association(scic_phy, (void *)phy); phy->sci_phy_handle = scic_phy; @@ -90,24 +91,13 @@ void isci_phy_init( dev_err(&isci_host->pdev->dev, "failed scic_controller_get_phy_handle\n"); - scic_oem_parameters_get(controller, &oem_parameters); - - phy->sas_addr[0] = oem_parameters.sds1.phys[index].sas_address.low - & 0xFF; - phy->sas_addr[1] = (oem_parameters.sds1.phys[index].sas_address.low - >> 8) & 0xFF; - phy->sas_addr[2] = (oem_parameters.sds1.phys[index].sas_address.low - >> 16) & 0xFF; - phy->sas_addr[3] = (oem_parameters.sds1.phys[index].sas_address.low - >> 24) & 0xFF; - phy->sas_addr[4] = oem_parameters.sds1.phys[index].sas_address.high - & 0xFF; - phy->sas_addr[5] = (oem_parameters.sds1.phys[index].sas_address.high - >> 8) & 0xFF; - phy->sas_addr[6] = (oem_parameters.sds1.phys[index].sas_address.high - >> 16) & 0xFF; - phy->sas_addr[7] = (oem_parameters.sds1.phys[index].sas_address.high - >> 24) & 0xFF; + scic_oem_parameters_get(scic, &oem); + sas_addr = oem.sds1.phys[index].sas_address.high; + sas_addr <<= 32; + sas_addr |= oem.sds1.phys[index].sas_address.low; + swab64s(&sas_addr); + + memcpy(phy->sas_addr, &sas_addr, sizeof(sas_addr)); phy->isci_port = NULL; phy->sas_phy.enabled = 0; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 446da20521c9..30da3ec703e3 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -192,6 +192,7 @@ void isci_port_link_up( scic_port_get_properties(port, &properties); if (properties.remote.protocols.u.bits.stp_target) { + u64 attached_sas_address; struct scic_sata_phy_properties sata_phy_properties; @@ -220,17 +221,13 @@ void isci_port_link_up( * will not be the same as assigned to the PHY and needs * to be obtained from struct scic_port_properties properties. */ + attached_sas_address = properties.remote.sas_address.high; + attached_sas_address <<= 32; + attached_sas_address |= properties.remote.sas_address.low; + swab64s(&attached_sas_address); - BUG_ON(((size_t)SAS_ADDR_SIZE / 2) - != sizeof(properties.remote.sas_address.low)); - - memcpy(&isci_phy->sas_phy.attached_sas_addr[0], - &properties.remote.sas_address.low, - SAS_ADDR_SIZE / 2); - - memcpy(&isci_phy->sas_phy.attached_sas_addr[4], - &properties.remote.sas_address.high, - SAS_ADDR_SIZE / 2); + memcpy(&isci_phy->sas_phy.attached_sas_addr, + &attached_sas_address, sizeof(attached_sas_address)); } else if (properties.remote.protocols.u.bits.ssp_target || properties.remote.protocols.u.bits.smp_target) { -- cgit v1.2.3 From 7c40a8035815479c7c12ab0cdcea71e0f4c3a9c8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 2 Mar 2011 11:49:26 -0800 Subject: isci: rework timer api Prepare the timer api for the arrival of dynamic creation and destruction events from the core. It pretended to do this previously but the core to date only used it in a static init-time only fashion. This is an interim fix until a cleaner event queue can be developed. 1/ make all locking external to the api (add WARN_ONCE to verify) 2/ add a timer_destroy interface (to be used by the core) 3/ use del_timer_sync() prior to deallocating timer data 4/ delete the "timer_list" indirection, we only have timers allocated for the isci_host 5/ fix detection of timer list allocation errors Signed-off-by: Dan Williams --- drivers/scsi/isci/events.c | 49 ++++++------- drivers/scsi/isci/events.h | 3 + drivers/scsi/isci/host.c | 32 ++++----- drivers/scsi/isci/host.h | 2 +- drivers/scsi/isci/task.c | 17 +---- drivers/scsi/isci/timers.c | 173 +++++++++++++-------------------------------- drivers/scsi/isci/timers.h | 60 +++------------- 7 files changed, 104 insertions(+), 232 deletions(-) diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c index 8872f4ca6aaa..c5cbaedac041 100644 --- a/drivers/scsi/isci/events.c +++ b/drivers/scsi/isci/events.c @@ -75,35 +75,23 @@ * whenever the timer expires. * @controller: This parameter specifies the controller with which this timer * is to be associated. - * @cookie: This parameter specifies a piece of information that the user must - * retain. This cookie is to be supplied by the user anytime a timeout - * occurs for the created timer. + * @cb_param: opaque callback parameter * * This method returns a handle to a timer object created by the user. The * handle will be utilized for all further interactions relating to this timer. */ -void *isci_event_timer_create( - struct scic_sds_controller *controller, - void (*timer_callback)(void *), - void *cookie) +void *isci_event_timer_create(struct scic_sds_controller *scic, + void (*timer_callback)(void *), + void *cb_param) { - struct isci_host *isci_host; - struct isci_timer *timer = NULL; - - isci_host = (struct isci_host *)sci_object_get_association(controller); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_timer *itimer; - dev_dbg(&isci_host->pdev->dev, - "%s: isci_host = %p", - __func__, isci_host); - - timer = isci_timer_create(&isci_host->timer_list_struct, - isci_host, - cookie, - timer_callback); + itimer = isci_timer_create(ihost, cb_param, timer_callback); - dev_dbg(&isci_host->pdev->dev, "%s: timer = %p\n", __func__, timer); + dev_dbg(&ihost->pdev->dev, "%s: timer = %p\n", __func__, itimer); - return (void *)timer; + return itimer; } @@ -146,14 +134,9 @@ void isci_event_timer_start( * @timer: This parameter specifies the timer to be stopped. * */ -void isci_event_timer_stop( - struct scic_sds_controller *controller, - void *timer) +void isci_event_timer_stop(struct scic_sds_controller *controller, void *timer) { - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); + struct isci_host *isci_host = sci_object_get_association(controller); dev_dbg(&isci_host->pdev->dev, "%s: isci_host = %p, timer = %p\n", @@ -162,6 +145,16 @@ void isci_event_timer_stop( isci_timer_stop((struct isci_timer *)timer); } +void isci_event_timer_destroy(struct scic_sds_controller *scic, void *timer) +{ + struct isci_host *ihost = sci_object_get_association(scic); + + dev_dbg(&ihost->pdev->dev, "%s: ihost = %p, timer = %p\n", + __func__, ihost, timer); + + isci_del_timer(ihost, timer); +} + /** * isci_event_controller_start_complete() - This user callback will inform the * user that the controller has finished the start process. The associated diff --git a/drivers/scsi/isci/events.h b/drivers/scsi/isci/events.h index 98526e9fb14a..fa2f6aa1093c 100644 --- a/drivers/scsi/isci/events.h +++ b/drivers/scsi/isci/events.h @@ -111,6 +111,9 @@ void isci_event_timer_stop( struct scic_sds_controller *controller, void *timer); + +void isci_event_timer_destroy(struct scic_sds_controller *scic, void *timer); + /** * isci_event_controller_start_complete() - This user callback will inform the * user that the controller has finished the start process. diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index d8d6f67bd69c..1bc91f2b4f93 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -349,9 +349,14 @@ void isci_host_deinit(struct isci_host *ihost) } set_bit(IHOST_STOP_PENDING, &ihost->flags); + + spin_lock_irq(&ihost->scic_lock); scic_controller_stop(scic, SCIC_CONTROLLER_STOP_TIMEOUT); + spin_unlock_irq(&ihost->scic_lock); + wait_for_stop(ihost); scic_controller_reset(scic); + isci_timer_list_destroy(ihost); } static void __iomem *scu_base(struct isci_host *isci_host) @@ -370,8 +375,6 @@ static void __iomem *smu_base(struct isci_host *isci_host) return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; } -#define SCI_MAX_TIMER_COUNT 25 - int isci_host_init(struct isci_host *isci_host) { int err = 0; @@ -382,11 +385,7 @@ int isci_host_init(struct isci_host *isci_host) union scic_oem_parameters scic_oem_params; union scic_user_parameters scic_user_params; - INIT_LIST_HEAD(&isci_host->timer_list_struct.timers); - isci_timer_list_construct( - &isci_host->timer_list_struct, - SCI_MAX_TIMER_COUNT - ); + isci_timer_list_construct(isci_host); controller = scic_controller_alloc(&isci_host->pdev->dev); @@ -473,7 +472,17 @@ int isci_host_init(struct isci_host *isci_host) } } + tasklet_init(&isci_host->completion_tasklet, + isci_host_completion_routine, (unsigned long)isci_host); + + INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); + + INIT_LIST_HEAD(&isci_host->requests_to_complete); + INIT_LIST_HEAD(&isci_host->requests_to_abort); + + spin_lock_irq(&isci_host->scic_lock); status = scic_controller_initialize(isci_host->core_controller); + spin_unlock_irq(&isci_host->scic_lock); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, "%s: scic_controller_initialize failed -" @@ -482,17 +491,8 @@ int isci_host_init(struct isci_host *isci_host) return -ENODEV; } - tasklet_init(&isci_host->completion_tasklet, - isci_host_completion_routine, (unsigned long)isci_host); - - INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); - - INIT_LIST_HEAD(&isci_host->requests_to_complete); - INIT_LIST_HEAD(&isci_host->requests_to_abort); - /* populate mdl with dma memory. scu_mdl_allocate_coherent() */ err = isci_host_mdl_allocate_coherent(isci_host); - if (err) return err; diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index b794dfd0819e..ef3e7d1440b0 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -87,7 +87,7 @@ struct isci_host { union scic_oem_parameters oem_parameters; int id; /* unique within a given pci device */ - struct isci_timer_list timer_list_struct; + struct list_head timers; void *core_ctrl_memory; struct dma_pool *dma_pool; unsigned int dma_pool_alloc_size; diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 6f98f6c74efb..232125eab523 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -475,14 +475,8 @@ int isci_task_execute_tmf( } /* Allocate the TMF timeout timer. */ - tmf->timeout_timer = isci_timer_create( - &isci_host->timer_list_struct, - isci_host, - request, - isci_tmf_timeout_cb - ); - spin_lock_irqsave(&isci_host->scic_lock, flags); + tmf->timeout_timer = isci_timer_create(isci_host, request, isci_tmf_timeout_cb); /* Start the timer. */ if (tmf->timeout_timer) @@ -557,9 +551,7 @@ int isci_task_execute_tmf( /* Clean up the timer if needed. */ if (tmf->timeout_timer) { - isci_timer_stop(tmf->timeout_timer); - isci_timer_free(&isci_host->timer_list_struct, - tmf->timeout_timer); + isci_del_timer(isci_host, tmf->timeout_timer); tmf->timeout_timer = NULL; } @@ -1468,10 +1460,7 @@ void isci_task_request_complete( /* Manage the timer if it is still running. */ if (tmf->timeout_timer) { - - isci_timer_stop(tmf->timeout_timer); - isci_timer_free(&isci_host->timer_list_struct, - tmf->timeout_timer); + isci_del_timer(isci_host, tmf->timeout_timer); tmf->timeout_timer = NULL; } diff --git a/drivers/scsi/isci/timers.c b/drivers/scsi/isci/timers.c index ca723089ee88..f33eff00dc01 100644 --- a/drivers/scsi/isci/timers.c +++ b/drivers/scsi/isci/timers.c @@ -56,96 +56,59 @@ #include "isci.h" #include "timers.h" - /** * isci_timer_list_construct() - This method contrucst the SCI Timer List * object used by the SCI Module class. The construction process involves * creating isci_timer objects and adding them to the SCI Timer List * object's list member. The number of isci_timer objects is determined by * the timer_list_size parameter. - * @isci_timer_list: This parameter points to the SCI Timer List object being - * constructed. The calling routine is responsible for allocating the memory - * for isci_timer_list and initializing the timer list_head member of - * isci_timer_list. - * @timer_list_size: This parameter specifies the number of isci_timer objects - * contained by the SCI Timer List. which this timer is to be associated. + * @ihost: container of the timer list * * This method returns an error code indicating sucess or failure. The user * should check for possible memory allocation error return otherwise, a zero * indicates success. */ -int isci_timer_list_construct( - struct isci_timer_list *isci_timer_list, - int timer_list_size) +int isci_timer_list_construct(struct isci_host *ihost) { - struct isci_timer *isci_timer; - int i; - int err = 0; - + struct isci_timer *itimer; + int i, err = 0; - for (i = 0; i < timer_list_size; i++) { - - isci_timer = kzalloc(sizeof(*isci_timer), GFP_KERNEL); - - if (!isci_timer) { + INIT_LIST_HEAD(&ihost->timers); + for (i = 0; i < SCI_MAX_TIMER_COUNT; i++) { + itimer = devm_kzalloc(&ihost->pdev->dev, sizeof(*itimer), GFP_KERNEL); + if (!itimer) { err = -ENOMEM; break; } - isci_timer->used = 0; - isci_timer->stopped = 1; - isci_timer->parent = isci_timer_list; - list_add(&isci_timer->node, &isci_timer_list->timers); + init_timer(&itimer->timer); + itimer->used = 0; + itimer->stopped = 1; + list_add(&itimer->node, &ihost->timers); } - return 0; - + return err; } - /** * isci_timer_list_destroy() - This method destroys the SCI Timer List object * used by the SCI Module class. The destruction process involves freeing * memory allocated for isci_timer objects on the SCI Timer List object's * timers list_head member. If any isci_timer objects are mark as "in use", * they are not freed and the function returns an error code of -EBUSY. - * @isci_timer_list: This parameter points to the SCI Timer List object being - * destroyed. - * - * This method returns an error code indicating sucess or failure. The user - * should check for possible -EBUSY error return, in the event of one or more - * isci_timers still "in use", otherwise, a zero indicates success. + * @ihost: container of the list to be destroyed */ -int isci_timer_list_destroy( - struct isci_timer_list *isci_timer_list) +void isci_timer_list_destroy(struct isci_host *ihost) { - struct isci_timer *timer, *tmp; - - list_for_each_entry_safe(timer, tmp, &isci_timer_list->timers, node) { - isci_timer_free(isci_timer_list, timer); - list_del(&timer->node); - kfree(timer); - } - return 0; -} + struct isci_timer *timer; + LIST_HEAD(list); + spin_lock_irq(&ihost->scic_lock); + list_splice_init(&ihost->timers, &list); + spin_unlock_irq(&ihost->scic_lock); - -static void isci_timer_restart(struct isci_timer *isci_timer) -{ - struct timer_list *timer = - &isci_timer->timer; - unsigned long timeout; - - dev_dbg(&isci_timer->isci_host->pdev->dev, - "%s: isci_timer = %p\n", __func__, isci_timer); - - isci_timer->restart = 0; - isci_timer->stopped = 0; - timeout = isci_timer->timeout_value; - timeout = (timeout * HZ) / 1000; - timeout = timeout ? timeout : 1; - mod_timer(timer, jiffies + timeout); + list_for_each_entry(timer, &list, node) + del_timer_sync(&timer->timer); } /** @@ -169,7 +132,7 @@ static void isci_timer_restart(struct isci_timer *isci_timer) static void timer_function(unsigned long data) { - struct isci_timer *timer = (struct isci_timer *)data; + struct isci_timer *timer = (struct isci_timer *)data; struct isci_host *isci_host = timer->isci_host; unsigned long flags; @@ -185,89 +148,66 @@ static void timer_function(unsigned long data) if (!timer->stopped) { timer->stopped = 1; - timer->timer_callback(timer->cookie); - - if (timer->restart) - isci_timer_restart(timer); + timer->timer_callback(timer->cb_param); } spin_unlock_irqrestore(&isci_host->scic_lock, flags); } -struct isci_timer *isci_timer_create( - struct isci_timer_list *isci_timer_list, - struct isci_host *isci_host, - void *cookie, - void (*timer_callback)(void *)) +struct isci_timer *isci_timer_create(struct isci_host *ihost, void *cb_param, + void (*timer_callback)(void *)) { - struct timer_list *timer; struct isci_timer *isci_timer; - struct list_head *timer_list = - &isci_timer_list->timers; - unsigned long flags; + struct list_head *list = &ihost->timers; - spin_lock_irqsave(&isci_host->scic_lock, flags); + WARN_ONCE(!spin_is_locked(&ihost->scic_lock), + "%s: unlocked!\n", __func__); - if (list_empty(timer_list)) { - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + if (WARN_ONCE(list_empty(list), "%s: timer pool empty\n", __func__)) return NULL; - } - isci_timer = list_entry(timer_list->next, struct isci_timer, node); + isci_timer = list_entry(list->next, struct isci_timer, node); - if (isci_timer->used) { - spin_unlock_irqrestore(&isci_host->scic_lock, flags); - return NULL; - } isci_timer->used = 1; isci_timer->stopped = 1; - list_move_tail(&isci_timer->node, timer_list); - - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + /* FIXME: what!? we recycle the timer, rather than take it off + * the free list? + */ + list_move_tail(&isci_timer->node, list); timer = &isci_timer->timer; timer->data = (unsigned long)isci_timer; timer->function = timer_function; - isci_timer->cookie = cookie; + isci_timer->cb_param = cb_param; isci_timer->timer_callback = timer_callback; - isci_timer->isci_host = isci_host; + isci_timer->isci_host = ihost; - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: isci_timer = %p\n", __func__, isci_timer); return isci_timer; } -/** - * isci_timer_free() - This method frees the isci_timer, marking it "free to +/* isci_del_timer() - This method frees the isci_timer, marking it "free to * use", then places its back at the head of the timers list for the SCI * Timer List object specified. - * @isci_timer_list: This parameter points to the SCI Timer List from which the - * timer is reserved. - * @isci_timer: This parameter specifies the timer to be freed. - * */ -void isci_timer_free( - struct isci_timer_list *isci_timer_list, - struct isci_timer *isci_timer) +void isci_del_timer(struct isci_host *ihost, struct isci_timer *isci_timer) { - struct list_head *timer_list = &isci_timer_list->timers; + struct list_head *list = &ihost->timers; + + WARN_ONCE(!spin_is_locked(&ihost->scic_lock), + "%s unlocked!\n", __func__); dev_dbg(&isci_timer->isci_host->pdev->dev, "%s: isci_timer = %p\n", __func__, isci_timer); - if (list_empty(timer_list)) - return; - isci_timer->used = 0; - list_move(&isci_timer->node, timer_list); - - if (!isci_timer->stopped) { - del_timer(&isci_timer->timer); - isci_timer->stopped = 1; - } + list_move(&isci_timer->node, list); + del_timer(&isci_timer->timer); + isci_timer->stopped = 1; } /** @@ -278,26 +218,15 @@ void isci_timer_free( * the associated callback function will be called. * */ -void isci_timer_start( - struct isci_timer *isci_timer, - unsigned long timeout) +void isci_timer_start(struct isci_timer *isci_timer, unsigned long tmo) { struct timer_list *timer = &isci_timer->timer; dev_dbg(&isci_timer->isci_host->pdev->dev, "%s: isci_timer = %p\n", __func__, isci_timer); - isci_timer->timeout_value = timeout; - init_timer(timer); - timeout = (timeout * HZ) / 1000; - timeout = timeout ? timeout : 1; - - timer->expires = jiffies + timeout; - timer->data = (unsigned long)isci_timer; - timer->function = timer_function; isci_timer->stopped = 0; - isci_timer->restart = 0; - add_timer(timer); + mod_timer(timer, jiffies + msecs_to_jiffies(tmo)); } /** @@ -310,10 +239,6 @@ void isci_timer_stop(struct isci_timer *isci_timer) dev_dbg(&isci_timer->isci_host->pdev->dev, "%s: isci_timer = %p\n", __func__, isci_timer); - if (isci_timer->stopped) - return; - isci_timer->stopped = 1; - del_timer(&isci_timer->timer); } diff --git a/drivers/scsi/isci/timers.h b/drivers/scsi/isci/timers.h index ca5c2159a1c2..8d8a892ad7f2 100644 --- a/drivers/scsi/isci/timers.h +++ b/drivers/scsi/isci/timers.h @@ -59,68 +59,30 @@ #include #include -/*************************************************** - * isci_timer - *************************************************** - */ -/** - * struct isci_timer_list - This class is the container for all isci_timer - * objects - * - * - */ -struct isci_timer_list { - - struct list_head timers; -}; +#define SCI_MAX_TIMER_COUNT 25 /** * struct isci_timer - This class represents the timer object used by SCIC. It - * wraps the Linux timer_list object. - * + * wraps the Linux timer_list object, and (TODO) should be removed in favor + * of a delayed-workqueue style interface with simpler locking * */ struct isci_timer { int used; int stopped; - int restart; - int timeout_value; - void *cookie; + void *cb_param; void (*timer_callback)(void *); struct list_head node; struct timer_list timer; - struct isci_timer_list *parent; struct isci_host *isci_host; }; -#define to_isci_timer(t) \ - container_of(t, struct isci_timer, timer); - -int isci_timer_list_construct( - struct isci_timer_list *isci_timer_list, - int timer_list_size); - - -int isci_timer_list_destroy( - struct isci_timer_list *isci_timer_list); - -struct isci_timer *isci_timer_create( - struct isci_timer_list *isci_timer_list, - struct isci_host *isci_host, - void *cookie, - void (*timer_callback)(void *)); - -void isci_timer_free( - struct isci_timer_list *isci_timer_list, - struct isci_timer *isci_timer); - -void isci_timer_start( - struct isci_timer *isci_timer, - unsigned long timeout); - -void isci_timer_stop( - struct isci_timer *isci_timer); - +int isci_timer_list_construct(struct isci_host *ihost); +void isci_timer_list_destroy(struct isci_host *ihost); +struct isci_timer *isci_timer_create(struct isci_host *ihost, void *cb_param, + void (*timer_callback)(void *)); +void isci_del_timer(struct isci_host *ihost, struct isci_timer *itimer); +void isci_timer_start(struct isci_timer *isci_timer, unsigned long timeout); +void isci_timer_stop(struct isci_timer *isci_timer); #endif /* !defined (_SCI_TIMER_H_) */ - -- cgit v1.2.3 From a8d4b9fe911c7d48f7a75c37eb1bfa3273547d97 Mon Sep 17 00:00:00 2001 From: Tomasz Chudy Date: Fri, 25 Feb 2011 02:25:09 -0800 Subject: isci: workaround port task scheduler starvation issue There is a condition whereby TCs (task contexts) can jump to the head of the round robin queue causing indefinite starvation of pending tasks. Posting a TC to a suspended RNC (remote node context) causes the hardware to select that task first, but since the RNC is suspended the scheduler proceeds to the next task in the expected round robin fashion, restoring TC arbitration fairness. Signed-off-by: Tomasz Chudy Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_port.h | 17 -- drivers/scsi/isci/core/scic_sds_controller.c | 22 +- drivers/scsi/isci/core/scic_sds_port.c | 334 ++++++++++++++++++++++----- drivers/scsi/isci/core/scic_sds_port.h | 9 + drivers/scsi/isci/host.c | 7 - 5 files changed, 298 insertions(+), 91 deletions(-) diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h index e55abb68ff9a..8222443c9fd7 100644 --- a/drivers/scsi/isci/core/scic_port.h +++ b/drivers/scsi/isci/core/scic_port.h @@ -147,23 +147,6 @@ enum sci_status scic_port_get_properties( struct scic_sds_port *port, struct scic_port_properties *properties); - - -/** - * scic_port_start() - This method will make the port ready for operation. - * Prior to calling the start method IO operation is not possible. - * @port: This parameter specifies the port to be started. - * - * Indicate if the port was successfully started. SCI_SUCCESS This value is - * returned if the port was successfully started. SCI_WARNING_ALREADY_IN_STATE - * This value is returned if the port is in the process of starting. - * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port is not - * valid. SCI_FAILURE_INVALID_STATE This value is returned if a start operation - * can't be completed due to the state of port. - */ -enum sci_status scic_port_start( - struct scic_sds_port *port); - /** * scic_port_stop() - This method will make the port no longer ready for * operation. After invoking this method IO operation is not possible. diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index d642ff7be6db..5e26df7fcb3a 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -796,7 +796,11 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) enum sci_status status = SCI_SUCCESS; for (index = 0; index < scic->logical_port_entries; index++) { - port_status = scic_port_stop(&scic->port_table[index]); + struct scic_sds_port *sci_port = &scic->port_table[index]; + SCI_BASE_PORT_HANDLER_T stop; + + stop = sci_port->state_handlers->parent.stop_handler; + port_status = stop(&sci_port->parent); if ((port_status != SCI_SUCCESS) && (port_status != SCI_FAILURE_INVALID_STATE)) { @@ -806,7 +810,7 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) "%s: Controller stop operation failed to " "stop port %d because of status %d.\n", __func__, - scic->port_table[index].logical_port_index, + sci_port->logical_port_index, port_status); } } @@ -3003,7 +3007,7 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( scic_sds_controller_ram_initialization(this_controller); } - if (SCI_SUCCESS == result) { + if (result == SCI_SUCCESS) { /* Build the TCi free pool */ sci_pool_initialize(this_controller->tci_pool); for (index = 0; index < this_controller->task_context_entries; index++) { @@ -3017,7 +3021,7 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( ); } - if (SCI_SUCCESS == result) { + if (result == SCI_SUCCESS) { /* * Before anything else lets make sure we will not be interrupted * by the hardware. */ @@ -3036,7 +3040,15 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( scic_sds_controller_initialize_unsolicited_frame_queue(this_controller); } - if (SCI_SUCCESS == result) { + /* Start all of the ports on this controller */ + for (index = 0; index < this_controller->logical_port_entries && + result == SCI_SUCCESS; index++) { + struct scic_sds_port *sci_port = &this_controller->port_table[index]; + + result = sci_port->state_handlers->parent.start_handler(&sci_port->parent); + } + + if (result == SCI_SUCCESS) { scic_sds_controller_start_next_phy(this_controller); isci_event_timer_start(this_controller, diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index d374c7ac0b71..2a193d30c55d 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -67,6 +67,7 @@ #include "scic_sds_remote_node_context.h" #include "scic_sds_request.h" #include "sci_environment.h" +#include "scic_sds_controller_registers.h" static void scic_sds_port_invalid_link_up( @@ -78,6 +79,7 @@ static void scic_sds_port_timeout_handler( #define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) +#define SCU_DUMMY_INDEX (0xFFFF) void sci_base_port_construct( struct sci_base_port *base_port, @@ -474,67 +476,131 @@ void scic_sds_port_get_attached_protocols( } /** - * This method returns the amount of memory requred for a port object. + * scic_sds_port_construct_dummy_rnc() - create dummy rnc for si workaround * - * u32 - */ - -/** - * This method returns the minimum number of timers required for all port - * objects. + * @sci_port: logical port on which we need to create the remote node context + * @rni: remote node index for this remote node context. * - * u32 + * This routine will construct a dummy remote node context data structure + * This structure will be posted to the hardware to work around a scheduler + * error in the hardware. */ +void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni) +{ + union scu_remote_node_context *rnc; -/** - * This method returns the maximum number of timers required for all port - * objects. - * - * u32 - */ + rnc = &sci_port->owning_controller->remote_node_context_table[rni]; + + memset(rnc, 0, sizeof(union scu_remote_node_context)); + + rnc->ssp.remote_sas_address_hi = 0; + rnc->ssp.remote_sas_address_lo = 0; + + rnc->ssp.remote_node_index = rni; + rnc->ssp.remote_node_port_width = 1; + rnc->ssp.logical_port_index = sci_port->physical_port_index; + + rnc->ssp.nexus_loss_timer_enable = false; + rnc->ssp.check_bit = false; + rnc->ssp.is_valid = true; + rnc->ssp.is_remote_node_context = true; + rnc->ssp.function_number = 0; + rnc->ssp.arbitration_wait_time = 0; +} /** + * scic_sds_port_construct_dummy_task() - create dummy task for si workaround + * @sci_port The logical port on which we need to create the + * remote node context. + * context. + * @tci The remote node index for this remote node context. * - * @this_port: - * @port_index: - * + * This routine will construct a dummy task context data structure. This + * structure will be posted to the hardwre to work around a scheduler error + * in the hardware. * */ -void scic_sds_port_construct( - struct scic_sds_port *this_port, - u8 port_index, - struct scic_sds_controller *owning_controller) +void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci) +{ + struct scu_task_context *task_context; + + task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tci); + + memset(task_context, 0, sizeof(struct scu_task_context)); + + task_context->abort = 0; + task_context->priority = 0; + task_context->initiator_request = 1; + task_context->connection_rate = 1; + task_context->protocol_engine_index = 0; + task_context->logical_port_index = sci_port->physical_port_index; + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; + task_context->task_index = scic_sds_io_tag_get_index(tci); + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + task_context->remote_node_index = sci_port->reserved_rni; + task_context->command_code = 0; + + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 0; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + task_context->address_modifier = 0; + + task_context->task_phase = 0x01; +} + +void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + + if (sci_port->reserved_tci != SCU_DUMMY_INDEX) + scic_controller_free_io_tag(scic, sci_port->reserved_tci); + + if (sci_port->reserved_rni != SCU_DUMMY_INDEX) + scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes, + 1, sci_port->reserved_rni); + + sci_port->reserved_rni = SCU_DUMMY_INDEX; + sci_port->reserved_tci = SCU_DUMMY_INDEX; +} + +void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, + struct scic_sds_controller *scic) { u32 index; - sci_base_port_construct( - &this_port->parent, - scic_sds_port_state_table - ); + sci_base_port_construct(&sci_port->parent, scic_sds_port_state_table); sci_base_state_machine_construct( - scic_sds_port_get_ready_substate_machine(this_port), - &this_port->parent.parent, + scic_sds_port_get_ready_substate_machine(sci_port), + &sci_port->parent.parent, scic_sds_port_ready_substate_table, SCIC_SDS_PORT_READY_SUBSTATE_WAITING ); - this_port->logical_port_index = SCIC_SDS_DUMMY_PORT; - this_port->physical_port_index = port_index; - this_port->active_phy_mask = 0; + sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; + sci_port->physical_port_index = port_index; + sci_port->active_phy_mask = 0; - this_port->owning_controller = owning_controller; + sci_port->owning_controller = scic; - this_port->started_request_count = 0; - this_port->assigned_device_count = 0; + sci_port->started_request_count = 0; + sci_port->assigned_device_count = 0; - this_port->timer_handle = NULL; + sci_port->reserved_rni = SCU_DUMMY_INDEX; + sci_port->reserved_tci = SCU_DUMMY_INDEX; - this_port->port_task_scheduler_registers = NULL; + sci_port->timer_handle = NULL; - for (index = 0; index < SCI_MAX_PHYS; index++) { - this_port->phy_table[index] = NULL; - } + sci_port->port_task_scheduler_registers = NULL; + + for (index = 0; index < SCI_MAX_PHYS; index++) + sci_port->phy_table[index] = NULL; } /** @@ -634,19 +700,11 @@ void scic_sds_port_general_link_up_handler( } } - -enum sci_status scic_port_start(struct scic_sds_port *port) -{ - return port->state_handlers->parent.start_handler(&port->parent); -} - - enum sci_status scic_port_stop(struct scic_sds_port *port) { return port->state_handlers->parent.stop_handler(&port->parent); } - enum sci_status scic_port_get_properties( struct scic_sds_port *port, struct scic_port_properties *prop) @@ -1541,6 +1599,58 @@ static void scic_sds_port_suspend_port_task_scheduler( scu_port_task_scheduler_write(this_port, control, pts_control_value); } +/** + * scic_sds_port_post_dummy_request() - post dummy/workaround request + * @sci_port: port to post task + * + * Prevent the hardware scheduler from posting new requests to the front + * of the scheduler queue causing a starvation problem for currently + * ongoing requests. + * + */ +void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) +{ + u32 command; + struct scu_task_context *task_context; + struct scic_sds_controller *scic = sci_port->owning_controller; + u16 tci = sci_port->reserved_tci; + + task_context = scic_sds_controller_get_task_context_buffer(scic, tci); + + task_context->abort = 0; + + command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | + tci; + + scic_sds_controller_post_request(scic, command); +} + +/** + * This routine will abort the dummy request. This will alow the hardware to + * power down parts of the silicon to save power. + * + * @sci_port: The port on which the task must be aborted. + * + */ +void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + u16 tci = sci_port->reserved_tci; + struct scu_task_context *tc; + u32 command; + + tc = scic_sds_controller_get_task_context_buffer(scic, tci); + + tc->abort = 1; + + command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT | + sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | + tci; + + scic_sds_controller_post_request(scic, command); +} + /** * * @this_port: This is the struct scic_sds_port object to resume. @@ -1584,6 +1694,12 @@ static void scic_sds_port_ready_substate_waiting_enter( scic_sds_port_suspend_port_task_scheduler(this_port); + /* Kill the dummy task for this port if it has not yet posted + * the hardware will treat this as a NOP and just return abort + * complete. + */ + scic_sds_port_abort_dummy_request(this_port); + this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; if (this_port->active_phy_mask != 0) { @@ -1629,6 +1745,11 @@ static void scic_sds_port_ready_substate_operational_enter( scic_sds_port_update_viit_entry(this_port); scic_sds_port_resume_port_task_scheduler(this_port); + + /* Post the dummy task for the port so the hardware can schedule + * io correctly + */ + scic_sds_port_post_dummy_request(this_port); } /** @@ -2062,6 +2183,7 @@ static enum sci_status scic_sds_port_general_complete_io_handler( * **************************************************************************** */ /** + * scic_sds_port_stopped_state_start_handler() - stop a port from "started" * * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port * object. @@ -2075,13 +2197,14 @@ static enum sci_status scic_sds_port_general_complete_io_handler( * start request is successful and the struct scic_sds_port object has transitioned to * the SCI_BASE_PORT_STATE_READY. */ -static enum sci_status scic_sds_port_stopped_state_start_handler( - struct sci_base_port *port) +static enum sci_status scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port) { + struct scic_sds_port *sci_port = container_of(base_port, typeof(*sci_port), parent); + struct scic_sds_controller *scic = sci_port->owning_controller; + enum sci_status status = SCI_SUCCESS; u32 phy_mask; - struct scic_sds_port *this_port = (struct scic_sds_port *)port; - if (this_port->assigned_device_count > 0) { + if (sci_port->assigned_device_count > 0) { /* * / @todo This is a start failure operation because there are still * / devices assigned to this port. There must be no devices @@ -2089,22 +2212,56 @@ static enum sci_status scic_sds_port_stopped_state_start_handler( return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } - phy_mask = scic_sds_port_get_phys(this_port); + sci_port->timer_handle = isci_event_timer_create(scic, + scic_sds_port_timeout_handler, + sci_port); - /* - * There are one or more phys assigned to this port. Make sure - * the port's phy mask is in fact legal and supported by the - * silicon. */ - if (scic_sds_port_is_phy_mask_valid(this_port, phy_mask) == true) { - sci_base_state_machine_change_state( - scic_sds_port_get_base_state_machine(this_port), - SCI_BASE_PORT_STATE_READY - ); + if (!sci_port->timer_handle) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; - return SCI_SUCCESS; + if (sci_port->reserved_rni == SCU_DUMMY_INDEX) { + u16 rni = scic_sds_remote_node_table_allocate_remote_node(&scic->available_remote_nodes, 1); + + if (rni != SCU_DUMMY_INDEX) + scic_sds_port_construct_dummy_rnc(sci_port, rni); + else + status = SCI_FAILURE_INSUFFICIENT_RESOURCES; + sci_port->reserved_rni = rni; + } + + if (sci_port->reserved_tci == SCU_DUMMY_INDEX) { + /* Allocate a TCI and remove the sequence nibble */ + u16 tci = scic_controller_allocate_io_tag(scic); + + if (tci != SCU_DUMMY_INDEX) + scic_sds_port_construct_dummy_task(sci_port, tci); + else + status = SCI_FAILURE_INSUFFICIENT_RESOURCES; + sci_port->reserved_tci = tci; + } + + if (status == SCI_SUCCESS) { + phy_mask = scic_sds_port_get_phys(sci_port); + + /* + * There are one or more phys assigned to this port. Make sure + * the port's phy mask is in fact legal and supported by the + * silicon. + */ + if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { + sci_base_state_machine_change_state( + scic_sds_port_get_base_state_machine(sci_port), + SCI_BASE_PORT_STATE_READY); + + return SCI_SUCCESS; + } else + status = SCI_FAILURE; } - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + if (status != SCI_SUCCESS) + scic_sds_port_destroy_dummy_resources(sci_port); + + return status; } /** @@ -2467,6 +2624,52 @@ static void scic_sds_port_disable_port_task_scheduler( scu_port_task_scheduler_write(this_port, control, pts_control_value); } +void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + u8 phys_index = sci_port->physical_port_index; + union scu_remote_node_context *rnc; + u16 rni = sci_port->reserved_rni; + u32 command; + + rnc = &scic->remote_node_context_table[rni]; + rnc->ssp.is_valid = true; + + command = SCU_CONTEXT_COMMAND_POST_RNC_32 | + phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; + + scic_sds_controller_post_request(scic, command); + + /* ensure hardware has seen the post rnc command and give it + * ample time to act before sending the suspend + */ + SMU_ISR_READ(scic); /* flush */ + udelay(10); + + command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX | + phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; + + scic_sds_controller_post_request(scic, command); +} + +void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + u8 phys_index = sci_port->physical_port_index; + union scu_remote_node_context *rnc; + u16 rni = sci_port->reserved_rni; + u32 command; + + rnc = &scic->remote_node_context_table[rni]; + + rnc->ssp.is_valid = false; + + command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | + phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; + + scic_sds_controller_post_request(scic, command); +} + /* * ****************************************************************************** * * PORT STATE METHODS @@ -2562,6 +2765,9 @@ static void scic_sds_port_ready_state_enter( ); } + /* Post and suspend the dummy remote node context for this port. */ + scic_sds_port_post_dummy_remote_node(this_port); + /* Start the ready substate machine */ sci_base_state_machine_start( scic_sds_port_get_ready_substate_machine(this_port) @@ -2583,6 +2789,8 @@ static void scic_sds_port_ready_state_exit( this_port = (struct scic_sds_port *)object; sci_base_state_machine_stop(&this_port->ready_substate_machine); + + scic_sds_port_invalidate_dummy_remote_node(this_port); } /** @@ -2663,6 +2871,8 @@ static void scic_sds_port_stopping_state_exit( scic_sds_port_get_controller(this_port), this_port->timer_handle ); + + scic_sds_port_destroy_dummy_resources(this_port); } /** diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 3eb80cb2ea47..c98caefa7cf2 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -72,6 +72,12 @@ #define SCIC_SDS_DUMMY_PORT 0xFF +/** + * This constant defines the value utilized by SCI Components to indicate + * an invalid handle. + */ +#define SCI_INVALID_HANDLE 0x0 + /** * enum SCIC_SDS_PORT_READY_SUBSTATES - * @@ -134,6 +140,9 @@ struct scic_sds_port { */ u8 active_phy_mask; + u16 reserved_rni; + u16 reserved_tci; + /** * This field contains the count of the io requests started on this port * object. It is used to control controller shutdown. diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 1bc91f2b4f93..40614e9ab41b 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -381,7 +381,6 @@ int isci_host_init(struct isci_host *isci_host) int index = 0; enum sci_status status; struct scic_sds_controller *controller; - struct scic_sds_port *scic_port; union scic_oem_parameters scic_oem_params; union scic_user_parameters scic_user_params; @@ -517,11 +516,5 @@ int isci_host_init(struct isci_host *isci_host) for (index = 0; index < SCI_MAX_PHYS; index++) isci_phy_init(&isci_host->phys[index], isci_host, index); - /* Start the ports */ - for (index = 0; index < SCI_MAX_PORTS; index++) { - scic_controller_get_port_handle(controller, index, &scic_port); - scic_port_start(scic_port); - } - return 0; } -- cgit v1.2.3 From 3ff0121a704172aa4bca9c4026b419ddfe1921c8 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Fri, 25 Feb 2011 13:07:38 -0800 Subject: isci: handle cases where a d2h fis is used report an ncq error Observed that some devices return a d2h fis, treat like an sdb error fis. Signed-off-by: Piotr Sawicki Signed-off-by: Dan Williams --- .../scsi/isci/core/scic_sds_stp_remote_device.c | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index 1d8d9013068f..9a615f07cefe 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -367,10 +367,27 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl ); if (status == SCI_SUCCESS) { - if ( - (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS) - && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) - ) { + if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && + (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { + this_device->not_ready_reason = + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + + /* + * / @todo Check sactive and complete associated IO + * if any. + */ + + sci_base_state_machine_change_state( + &this_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR + ); + } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && + (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { + + /* + * Some devices return D2H FIS when an NCQ error is detected. + * Treat this like an SDB error FIS ready reason. + */ this_device->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; -- cgit v1.2.3 From c658b109d3a9444293700471a278a741a1e5033d Mon Sep 17 00:00:00 2001 From: Pawel Marek Date: Tue, 1 Mar 2011 12:31:06 -0800 Subject: isci: controller stop/start fixes Core reworks to support stopping and re-starting the controller, lays the groundwork for phy disable / re-enable and fixes other bugs around port/phy setup/teardown. Signed-off-by: Pawel Marek Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 129 ++++++++++++++++++++---- drivers/scsi/isci/core/scic_sds_controller.h | 29 +++++- drivers/scsi/isci/core/scic_sds_phy.c | 83 ++++++++++----- drivers/scsi/isci/core/scic_sds_phy.h | 3 + drivers/scsi/isci/core/scic_sds_port.c | 21 ---- drivers/scsi/isci/core/scic_sds_remote_device.c | 10 ++ 6 files changed, 206 insertions(+), 69 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 5e26df7fcb3a..deee7ebef033 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -252,7 +252,7 @@ static void scic_sds_controller_phy_startup_timeout_handler( * * This method initializes the phy startup operations for controller start. */ -void scic_sds_controller_initialize_phy_startup( +enum sci_status scic_sds_controller_initialize_phy_startup( struct scic_sds_controller *this_controller) { this_controller->phy_startup_timer = isci_event_timer_create( @@ -261,8 +261,14 @@ void scic_sds_controller_initialize_phy_startup( this_controller ); - this_controller->next_phy_to_start = 0; - this_controller->phy_startup_timer_pending = false; + if (this_controller->phy_startup_timer == NULL) { + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + } else { + this_controller->next_phy_to_start = 0; + this_controller->phy_startup_timer_pending = false; + } + + return SCI_SUCCESS; } /** @@ -305,7 +311,7 @@ void scic_sds_controller_initialize_power_control( * to build the memory table. * */ -static void scic_sds_controller_build_memory_descriptor_table( +void scic_sds_controller_build_memory_descriptor_table( struct scic_sds_controller *this_controller) { sci_base_mde_construct( @@ -1698,6 +1704,91 @@ void scic_sds_controller_link_down( scic))); } +/** + * This method is called by the remote device to inform the controller + * that this remote device has started. + * + */ + +void scic_sds_controller_remote_device_started( + struct scic_sds_controller *this_controller, + struct scic_sds_remote_device *the_device) +{ + u32 state; + scic_sds_controller_device_handler_t remote_device_started_handler; + + state = this_controller->parent.state_machine.current_state_id; + remote_device_started_handler = scic_sds_controller_state_handler_table[state].remote_device_started_handler; + + if (remote_device_started_handler != NULL) + remote_device_started_handler(this_controller, the_device); + else { + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller 0x%p remote device started event " + "from device 0x%p in unexpected state %d\n", + __func__, + this_controller, + the_device, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + this_controller))); + } +} + +/** + * This is a helper method to determine if any remote devices on this + * controller are still in the stopping state. + * + */ +bool scic_sds_controller_has_remote_devices_stopping( + struct scic_sds_controller *this_controller) +{ + u32 index; + + for (index = 0; index < this_controller->remote_node_entries; index++) { + if ((this_controller->device_table[index] != NULL) && + (this_controller->device_table[index]->parent.state_machine.current_state_id + == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING)) + return true; + } + + return false; +} + +/** + * This method is called by the remote device to inform the controller + * object that the remote device has stopped. + * + */ + +void scic_sds_controller_remote_device_stopped( + struct scic_sds_controller *this_controller, + struct scic_sds_remote_device *the_device) +{ + + u32 state; + scic_sds_controller_device_handler_t remote_device_stopped_handler; + + state = this_controller->parent.state_machine.current_state_id; + remote_device_stopped_handler = scic_sds_controller_state_handler_table[state].remote_device_stopped_handler; + + if (remote_device_stopped_handler != NULL) + remote_device_stopped_handler(this_controller, the_device); + else { + dev_warn(scic_to_dev(this_controller), + "%s: SCIC Controller 0x%p remote device stopped event " + "from device 0x%p in unexpected state %d\n", + __func__, + this_controller, + the_device, + sci_base_state_machine_get_state( + scic_sds_controller_get_base_state_machine( + this_controller))); + } +} + + + /** * This method will write to the SCU PCP register the request value. The method * is used to suspend/resume ports, devices, and phys. @@ -3461,23 +3552,22 @@ static enum sci_status scic_sds_controller_stopping_state_complete_io_handler( * struct scic_sds_controller object. * @remote_device: This is struct sci_base_remote_device which is cast to a * struct scic_sds_remote_device object. - * @io_request: This is the struct sci_base_request which is cast to a - * SCIC_SDS_IO_REQUEST object. * * This method is called when the struct scic_sds_controller is in a stopping state - * and the complete task handler is called. - This function is not yet - * implemented enum sci_status SCI_FAILURE - */ - -/* - * ***************************************************************************** - * * STOPPED STATE HANDLERS - * ***************************************************************************** */ - -/* - * ***************************************************************************** - * * FAILED STATE HANDLERS - * ***************************************************************************** */ + * and the remote device has stopped. + **/ +void scic_sds_controller_stopping_state_device_stopped_handler( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *remote_device +) +{ + if (!scic_sds_controller_has_remote_devices_stopping(controller)) { + sci_base_state_machine_change_state( + &controller->parent.state_machine, + SCI_BASE_CONTROLLER_STATE_STOPPED + ); + } +} const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[] = { [SCI_BASE_CONTROLLER_STATE_INITIAL] = { @@ -3537,6 +3627,7 @@ const struct scic_sds_controller_state_handler scic_sds_controller_state_handler .base.complete_io = scic_sds_controller_stopping_state_complete_io_handler, .base.continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, + .remote_device_stopped_handler = scic_sds_controller_stopping_state_device_stopped_handler, }, [SCI_BASE_CONTROLLER_STATE_STOPPED] = { .base.reset = scic_sds_controller_general_reset_handler, diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 3e0477d62a5b..9b8e55d62910 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -120,6 +120,7 @@ enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS { SCU_MAX_MDES }; + /** * * @@ -390,6 +391,11 @@ struct scic_sds_controller { typedef void (*scic_sds_controller_phy_handler_t)(struct scic_sds_controller *, struct scic_sds_port *, struct scic_sds_phy *); + +typedef void (*scic_sds_controller_device_handler_t)(struct scic_sds_controller *, + struct scic_sds_remote_device *); + + /** * struct scic_sds_controller_state_handler - * @@ -402,6 +408,8 @@ struct scic_sds_controller_state_handler { sci_base_controller_request_handler_t terminate_request; scic_sds_controller_phy_handler_t link_up; scic_sds_controller_phy_handler_t link_down; + scic_sds_controller_device_handler_t remote_device_started_handler; + scic_sds_controller_device_handler_t remote_device_stopped_handler; }; extern const struct scic_sds_controller_state_handler @@ -631,6 +639,23 @@ void scic_sds_controller_link_down( struct scic_sds_port *the_port, struct scic_sds_phy *the_phy); +/* + * ***************************************************************************** + * * CORE CONTROLLER REMOTE DEVICE MESSAGE PROCESSING + * ***************************************************************************** */ + +bool scic_sds_controller_has_remote_devices_stopping( + struct scic_sds_controller *this_controller); + +void scic_sds_controller_remote_device_started( + struct scic_sds_controller *this_controller, + struct scic_sds_remote_device *the_device); + +void scic_sds_controller_remote_device_stopped( + struct scic_sds_controller *this_controller, + struct scic_sds_remote_device *the_device); + + /* * ***************************************************************************** * * CORE CONTROLLER PRIVATE METHODS @@ -688,8 +713,10 @@ void scic_sds_controller_register_setup( void scic_sds_controller_reset_hardware( struct scic_sds_controller *this_controller); +enum sci_status scic_sds_controller_initialize_phy_startup( + struct scic_sds_controller *this_controller); -void scic_sds_controller_initialize_phy_startup( +void scic_sds_controller_build_memory_descriptor_table( struct scic_sds_controller *this_controller); #endif /* _SCIC_SDS_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index d4a5e38aef65..ba9e55756f26 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -257,7 +257,7 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, * restart the starting substate machine since we dont know what has actually * happening. */ -static void scic_sds_phy_sata_timeout(void *phy) +void scic_sds_phy_sata_timeout(void *phy) { struct scic_sds_phy *sci_phy = phy; @@ -303,6 +303,7 @@ void scic_sds_phy_construct( this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; this_phy->link_layer_registers = NULL; this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; + this_phy->sata_timeout_timer = NULL; /* Clear out the identification buffer data */ memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type)); @@ -365,8 +366,8 @@ void scic_sds_phy_set_port( */ enum sci_status scic_sds_phy_initialize( struct scic_sds_phy *sci_phy, - struct scu_transport_layer_registers __iomem *transport_layer_registers, - struct scu_link_layer_registers __iomem *link_layer_registers) + struct scu_transport_layer_registers __iomem *transport_layer_registers, + struct scu_link_layer_registers __iomem *link_layer_registers) { /* Create the SIGNATURE FIS Timeout timer for this phy */ sci_phy->sata_timeout_timer = isci_event_timer_create( @@ -757,6 +758,23 @@ static void scic_sds_phy_restart_starting_state( ); } +/* **************************************************************************** + * SCIC SDS PHY general handlers + ************************************************************************** */ +static enum sci_status scic_sds_phy_starting_substate_general_stop_handler( + struct sci_base_phy *phy) +{ + struct scic_sds_phy *this_phy; + this_phy = (struct scic_sds_phy *)phy; + + sci_base_state_machine_stop(&this_phy->starting_substate_machine); + + sci_base_state_machine_change_state(&phy->state_machine, + SCI_BASE_PHY_STATE_STOPPED); + + return SCI_SUCCESS; +} + /* * ***************************************************************************** * * SCIC SDS PHY EVENT_HANDLERS @@ -1436,12 +1454,10 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_p return SCI_SUCCESS; } -/* --------------------------------------------------------------------------- */ - const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = { [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1450,7 +1466,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1459,7 +1475,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1477,7 +1493,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1486,7 +1502,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1495,7 +1511,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1504,7 +1520,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1513,7 +1529,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, @@ -1522,7 +1538,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t }, [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, + .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .parent.reset_handler = scic_sds_phy_default_reset_handler, .parent.destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -2153,17 +2169,22 @@ enum sci_status scic_sds_phy_default_consume_power_handler( * start it. - The phy state machine is transitioned to the * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS */ -static enum sci_status scic_sds_phy_stopped_state_start_handler( - struct sci_base_phy *phy) +static enum sci_status scic_sds_phy_stopped_state_start_handler(struct sci_base_phy *phy) { struct scic_sds_phy *this_phy; this_phy = (struct scic_sds_phy *)phy; - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), - SCI_BASE_PHY_STATE_STARTING - ); + /* Create the SIGNATURE FIS Timeout timer for this phy */ + this_phy->sata_timeout_timer = isci_event_timer_create( + scic_sds_phy_get_controller(this_phy), + scic_sds_phy_sata_timeout, this_phy); + + if (this_phy->sata_timeout_timer != NULL) { + sci_base_state_machine_change_state( + scic_sds_phy_get_base_state_machine(this_phy), + SCI_BASE_PHY_STATE_STARTING); + } return SCI_SUCCESS; } @@ -2185,7 +2206,7 @@ static enum sci_status scic_sds_phy_stopped_state_destroy_handler( this_phy = (struct scic_sds_phy *)phy; - /* / @todo what do we actually need to do here? */ + /* @todo what do we actually need to do here? */ return SCI_SUCCESS; } @@ -2500,7 +2521,7 @@ static void scic_sds_phy_initial_state_enter( this_phy = (struct scic_sds_phy *)object; - scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED); + scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_INITIAL); } /** @@ -2512,18 +2533,24 @@ static void scic_sds_phy_initial_state_enter( * handlers for the phy object base state machine initial state. - The SCU * hardware is requested to stop the protocol engine. none */ -static void scic_sds_phy_stopped_state_enter( - struct sci_base_object *object) +static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; /* / @todo We need to get to the controller to place this PE in a reset state */ - scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED); + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STOPPED); - scu_link_layer_stop_protocol_engine(this_phy); + if (sci_phy->sata_timeout_timer != NULL) { + isci_event_timer_destroy(scic_sds_phy_get_controller(sci_phy), + sci_phy->sata_timeout_timer); + + sci_phy->sata_timeout_timer = NULL; + } + + scu_link_layer_stop_protocol_engine(sci_phy); } /** diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index dc450c361d91..b611e33180b2 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -401,6 +401,9 @@ enum sci_status scic_sds_phy_stop( enum sci_status scic_sds_phy_reset( struct scic_sds_phy *this_phy); +void scic_sds_phy_sata_timeout( + void *cookie); + /* --------------------------------------------------------------------------- */ void scic_sds_phy_suspend( diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 2a193d30c55d..410c9a104bc0 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -625,27 +625,6 @@ enum sci_status scic_sds_port_initialize( this_port->port_pe_configuration_register = port_configuration_regsiter; this_port->viit_registers = viit_registers; - /* - * If this is not the dummy port make the assignment of - * the timer and start the state machine */ - if (this_port->physical_port_index != SCI_MAX_PORTS) { - /* / @todo should we create the timer at create time? */ - this_port->timer_handle = isci_event_timer_create( - scic_sds_port_get_controller(this_port), - scic_sds_port_timeout_handler, - this_port - ); - - } else { - /* - * Force the dummy port into a condition where it rejects all requests - * as its in an invalid state for any operation. - * / @todo should we set a set of specical handlers for the dummy port? */ - scic_sds_port_set_base_state_handlers( - this_port, SCI_BASE_PORT_STATE_STOPPED - ); - } - return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index a7cb4bc39a11..0ac6ca0f3291 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1822,6 +1822,11 @@ static void scic_sds_remote_device_stopped_state_enter( SCI_SUCCESS ); } + + scic_sds_controller_remote_device_stopped( + scic_sds_remote_device_get_controller(this_device), + this_device + ); } /** @@ -1875,6 +1880,11 @@ static void scic_sds_remote_device_starting_state_exit( this_device, SCI_SUCCESS ); + + scic_sds_controller_remote_device_started( + scic_sds_remote_device_get_controller(this_device), + this_device + ); } /** -- cgit v1.2.3 From 4d07f7f367f2c2d5547684893e61a7a796c1547f Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 2 Mar 2011 12:31:24 -0800 Subject: isci: Adding support for phy enable and disable Adding support for PHY_FUNC_LINK_RESET and PHY_FUNC_DISABLE. This allow the sysfs knob enable (both 0 and 1) and link_reset to work properly. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_phy.c | 32 ++++++++++++------- drivers/scsi/isci/phy.c | 59 ++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index ba9e55756f26..6f00ff6aa6bf 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -537,27 +537,25 @@ void scic_sds_phy_get_attached_phy_protocols( /** * This method will attempt to start the phy object. This request is only valid * when the phy is in the stopped state - * @this_phy: + * @sci_phy: * * enum sci_status */ -enum sci_status scic_sds_phy_start( - struct scic_sds_phy *this_phy) +enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) { - return this_phy->state_handlers->parent.start_handler(&this_phy->parent); + return sci_phy->state_handlers->parent.start_handler(&sci_phy->parent); } /** * This method will attempt to stop the phy object. - * @this_phy: + * @sci_phy: * - * enum sci_status SCI_SUCCESS if the phy is going to stop SCI_INVALID_STATE if the - * phy is not in a valid state to stop + * enum sci_status SCI_SUCCESS if the phy is going to stop SCI_INVALID_STATE + * if the phy is not in a valid state to stop */ -enum sci_status scic_sds_phy_stop( - struct scic_sds_phy *this_phy) +enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) { - return this_phy->state_handlers->parent.stop_handler(&this_phy->parent); + return sci_phy->state_handlers->parent.stop_handler(&sci_phy->parent); } /** @@ -2526,7 +2524,8 @@ static void scic_sds_phy_initial_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state @@ -2539,7 +2538,10 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) sci_phy = (struct scic_sds_phy *)object; - /* / @todo We need to get to the controller to place this PE in a reset state */ + /* + * @todo We need to get to the controller to place this PE in a + * reset state + */ scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STOPPED); @@ -2551,6 +2553,12 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) } scu_link_layer_stop_protocol_engine(sci_phy); + + if (sci_phy->parent.state_machine.previous_state_id != + SCI_BASE_PHY_STATE_INITIAL) + scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy); } /** diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 1eefaaeb1141..decc0c05a3dd 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -58,6 +58,9 @@ #include "scic_port.h" #include "scic_config_parameters.h" +struct scic_sds_phy; +extern enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy); +extern enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy); /** * isci_phy_init() - This function is called by the probe function to @@ -127,42 +130,48 @@ void isci_phy_init( * * status, zero indicates success. */ -int isci_phy_control( - struct asd_sas_phy *phy, - enum phy_func func, - void *buf) +int isci_phy_control(struct asd_sas_phy *sas_phy, + enum phy_func func, + void *buf) { - int ret = TMF_RESP_FUNC_COMPLETE; - struct isci_phy *isci_phy_ptr = (struct isci_phy *)phy->lldd_phy; - struct isci_port *isci_port_ptr = NULL; - - if (isci_phy_ptr != NULL) - isci_port_ptr = isci_phy_ptr->isci_port; - - if ((isci_phy_ptr == NULL) || (isci_port_ptr == NULL)) { - pr_err("%s: asd_sas_phy %p: lldd_phy %p or " - "isci_port %p == NULL!\n", - __func__, phy, isci_phy_ptr, isci_port_ptr); - return TMF_RESP_FUNC_FAILED; - } + int ret = 0; + struct isci_phy *iphy = sas_phy->lldd_phy; + struct isci_port *iport = iphy->isci_port; + struct isci_host *ihost = sas_phy->ha->lldd_ha; + unsigned long flags; - pr_debug("%s: phy %p; func %d; buf %p; isci phy %p, port %p\n", - __func__, phy, func, buf, isci_phy_ptr, isci_port_ptr); + dev_dbg(&ihost->pdev->dev, + "%s: phy %p; func %d; buf %p; isci phy %p, port %p\n", + __func__, sas_phy, func, buf, iphy, iport); switch (func) { - case PHY_FUNC_HARD_RESET: + case PHY_FUNC_DISABLE: + spin_lock_irqsave(&ihost->scic_lock, flags); + scic_sds_phy_stop(iphy->sci_phy_handle); + spin_unlock_irqrestore(&ihost->scic_lock, flags); + break; + case PHY_FUNC_LINK_RESET: + spin_lock_irqsave(&ihost->scic_lock, flags); + scic_sds_phy_stop(iphy->sci_phy_handle); + scic_sds_phy_start(iphy->sci_phy_handle); + spin_unlock_irqrestore(&ihost->scic_lock, flags); + break; + + case PHY_FUNC_HARD_RESET: + if (!iport) + return -ENODEV; /* Perform the port reset. */ - ret = isci_port_perform_hard_reset(isci_port_ptr, isci_phy_ptr); + ret = isci_port_perform_hard_reset(iport, iphy); break; - case PHY_FUNC_DISABLE: default: - pr_debug("%s: phy %p; func %d NOT IMPLEMENTED!\n", - __func__, phy, func); - ret = TMF_RESP_FUNC_FAILED; + dev_dbg(&ihost->pdev->dev, + "%s: phy %p; func %d NOT IMPLEMENTED!\n", + __func__, sas_phy, func); + ret = -ENOSYS; break; } return ret; -- cgit v1.2.3 From d7628d052242d634dc1e2584c422e690578918a3 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 2 Mar 2011 13:10:45 -0800 Subject: isci: Cleanup warning messages for phy resets Moving some of the chattiness of warning messages to debug so only the Linux system messages are shown. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 65 +++++++++++----------------- drivers/scsi/isci/core/scic_sds_phy.c | 36 ++++++++------- drivers/scsi/isci/remote_device.c | 2 +- 3 files changed, 43 insertions(+), 60 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index deee7ebef033..180bb1e69012 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1669,7 +1669,7 @@ void scic_sds_controller_link_up( if (link_up) link_up(scic, sci_port, sci_phy); else - dev_warn(scic_to_dev(scic), + dev_dbg(scic_to_dev(scic), "%s: SCIC Controller linkup event from phy %d in " "unexpected state %d\n", __func__, @@ -1694,14 +1694,11 @@ void scic_sds_controller_link_down( if (link_down) link_down(scic, sci_port, sci_phy); else - dev_warn(scic_to_dev(scic), + dev_dbg(scic_to_dev(scic), "%s: SCIC Controller linkdown event from phy %d in " "unexpected state %d\n", __func__, - sci_phy->phy_index, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - scic))); + sci_phy->phy_index, state); } /** @@ -1710,28 +1707,22 @@ void scic_sds_controller_link_down( * */ -void scic_sds_controller_remote_device_started( - struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *the_device) +void scic_sds_controller_remote_device_started(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev) { u32 state; - scic_sds_controller_device_handler_t remote_device_started_handler; + scic_sds_controller_device_handler_t started; - state = this_controller->parent.state_machine.current_state_id; - remote_device_started_handler = scic_sds_controller_state_handler_table[state].remote_device_started_handler; + state = scic->parent.state_machine.current_state_id; + started = scic_sds_controller_state_handler_table[state].remote_device_started_handler; - if (remote_device_started_handler != NULL) - remote_device_started_handler(this_controller, the_device); + if (started) + started(scic, sci_dev); else { - dev_warn(scic_to_dev(this_controller), - "%s: SCIC Controller 0x%p remote device started event " - "from device 0x%p in unexpected state %d\n", - __func__, - this_controller, - the_device, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - this_controller))); + dev_dbg(scic_to_dev(scic), + "%s: SCIC Controller 0x%p remote device started event " + "from device 0x%p in unexpected state %d\n", + __func__, scic, sci_dev, state); } } @@ -1761,29 +1752,23 @@ bool scic_sds_controller_has_remote_devices_stopping( * */ -void scic_sds_controller_remote_device_stopped( - struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *the_device) +void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev) { u32 state; - scic_sds_controller_device_handler_t remote_device_stopped_handler; + scic_sds_controller_device_handler_t stopped; - state = this_controller->parent.state_machine.current_state_id; - remote_device_stopped_handler = scic_sds_controller_state_handler_table[state].remote_device_stopped_handler; + state = scic->parent.state_machine.current_state_id; + stopped = scic_sds_controller_state_handler_table[state].remote_device_stopped_handler; - if (remote_device_stopped_handler != NULL) - remote_device_stopped_handler(this_controller, the_device); + if (stopped) + stopped(scic, sci_dev); else { - dev_warn(scic_to_dev(this_controller), - "%s: SCIC Controller 0x%p remote device stopped event " - "from device 0x%p in unexpected state %d\n", - __func__, - this_controller, - the_device, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - this_controller))); + dev_dbg(scic_to_dev(scic), + "%s: SCIC Controller 0x%p remote device stopped event " + "from device 0x%p in unexpected state %d\n", + __func__, scic, sci_dev, state); } } diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 6f00ff6aa6bf..27174589a863 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -808,11 +808,11 @@ static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler( break; default: - dev_warn(sciphy_to_dev(this_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); + dev_dbg(sciphy_to_dev(this_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); result = SCI_FAILURE; break; @@ -2000,26 +2000,24 @@ enum sci_status scic_sds_phy_default_start_handler( /** * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. + * @phy: This is the struct sci_base_phy object which is cast into a + * struct scic_sds_phy object. * * This is the default method for phy a stop request. It will report a warning * and exit. enum sci_status SCI_FAILURE_INVALID_STATE */ -enum sci_status scic_sds_phy_default_stop_handler( - struct sci_base_phy *phy) +enum sci_status scic_sds_phy_default_stop_handler(struct sci_base_phy *base_phy) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)phy; + sci_phy = (struct scic_sds_phy *)base_phy; - dev_warn(sciphy_to_dev(this_phy), - "%s: SCIC Phy 0x%p requested to stop from invalid " - "state %d\n", - __func__, - this_phy, - sci_base_state_machine_get_state( - &this_phy->parent.state_machine)); + dev_dbg(sciphy_to_dev(sci_phy), + "%s: SCIC Phy 0x%p requested to stop from invalid state %d\n", + __func__, + sci_phy, + sci_base_state_machine_get_state( + &sci_phy->parent.state_machine)); return SCI_FAILURE_INVALID_STATE; } @@ -2119,7 +2117,7 @@ enum sci_status scic_sds_phy_default_event_handler( struct scic_sds_phy *this_phy, u32 event_code) { - dev_warn(sciphy_to_dev(this_phy), + dev_dbg(sciphy_to_dev(this_phy), "%s: SCIC Phy 0x%p received unexpected event status %x " "while in state %d\n", __func__, diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index dec9033d674d..e684a053189e 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -472,7 +472,7 @@ void isci_remote_device_gone( struct isci_remote_device *isci_device = isci_dev_from_domain_dev( domain_dev); - dev_err(&isci_device->isci_port->isci_host->pdev->dev, + dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, "%s: domain_device = %p, isci_device = %p, isci_port = %p\n", __func__, domain_dev, isci_device, isci_device->isci_port); -- cgit v1.2.3 From 27ce51df9a333ca7e05e09f6d25becf26ac1ff45 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 2 Mar 2011 16:45:18 -0800 Subject: isci: fix hang after target reset When aborting a task context we need to be sure that the hardware has acted on this request (retrieved the task context) before invalidating the remote node context. In the case of the "dummy" task context and remote node we do not have the full state machine that goes through the complete tc abort and rnc invalidate states. Instead we ensure the hardware has seen and acted on Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_port.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 410c9a104bc0..a41fe426ac26 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -1673,12 +1673,6 @@ static void scic_sds_port_ready_substate_waiting_enter( scic_sds_port_suspend_port_task_scheduler(this_port); - /* Kill the dummy task for this port if it has not yet posted - * the hardware will treat this as a NOP and just return abort - * complete. - */ - scic_sds_port_abort_dummy_request(this_port); - this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; if (this_port->active_phy_mask != 0) { @@ -1744,6 +1738,13 @@ static void scic_sds_port_ready_substate_operational_exit( { struct scic_sds_port *this_port = (struct scic_sds_port *)object; +/* + * Kill the dummy task for this port if it has not yet posted + * the hardware will treat this as a NOP and just return abort + * complete. + */ + scic_sds_port_abort_dummy_request(this_port); + isci_event_port_not_ready( scic_sds_port_get_controller(this_port), this_port, @@ -2643,6 +2644,13 @@ void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) rnc->ssp.is_valid = false; + /* ensure the preceding tc abort request has reached the + * controller and give it ample time to act before posting the rnc + * invalidate + */ + SMU_ISR_READ(scic); /* flush */ + udelay(10); + command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; -- cgit v1.2.3 From fe9a643157747cf85ecc07cd341e448c5849364f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Mar 2011 14:58:11 -0800 Subject: isci: pad stp and smp request sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ross says: "The memory allocation for these requests doesn’t take into account the additional memory needed when the code in scic_sds_s[mst]p_request_assign_buffers() shifts the struct scu_task_context so that it is cache line aligned: In an example from my machine, total buffer that I’ve given to SCIC goes from 0x410024566f84 to 0x410024567308. From this same example, this call shifts my task_context_buffer from 0x410024567208 to 0x410024567240. This means that the task_context_buffer that used to range from 0x410024567208 to 0x410024567308 instead now goes from 0x410024567240 to 0x410024567340. When the memset() call at the end of scic_task_request_construct() clears out this task_context_buffer, it does so from 0x410024567240 to 0x410024567340, effectively killing whatever buffer follows this allocation in memory." djbw: Use the kernel's PTR_ALIGN instead of scic_sds_request_align_task_context_buffer() and SMP_CACHE_BYTES instead of the local CACHE_LINE_SIZE definition. TODO: These allocations really want to be better defined in a union rather than opaque buffers carved up by macros. Reported-by: Ross Zwisler Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_request.c | 10 ++++--- drivers/scsi/isci/core/scic_sds_request.h | 22 ---------------- drivers/scsi/isci/core/scic_sds_smp_request.c | 5 ++-- drivers/scsi/isci/core/scic_sds_stp_request.c | 38 +++++++++++---------------- 4 files changed, 24 insertions(+), 51 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 7b9ce1e878a7..00bebb9c0692 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -222,7 +222,7 @@ static u32 scic_sds_ssp_request_get_object_size(void) return sizeof(struct scic_sds_request) + scic_ssp_io_request_get_object_size() + sizeof(struct scu_task_context) - + CACHE_LINE_SIZE + + SMP_CACHE_BYTES + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; } @@ -395,13 +395,15 @@ static void scic_sds_ssp_io_request_assign_buffers( this_request->sgl_element_pair_buffer = scic_sds_ssp_request_get_sgl_element_buffer(this_request); this_request->sgl_element_pair_buffer = - scic_sds_request_align_sgl_element_buffer(this_request->sgl_element_pair_buffer); + PTR_ALIGN(this_request->sgl_element_pair_buffer, + sizeof(struct scu_sgl_element_pair)); if (this_request->was_tag_assigned_by_user == false) { this_request->task_context_buffer = scic_sds_ssp_request_get_task_context_buffer(this_request); this_request->task_context_buffer = - scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); + PTR_ALIGN(this_request->task_context_buffer, + SMP_CACHE_BYTES); } } @@ -638,7 +640,7 @@ static void scic_sds_ssp_task_request_assign_buffers( this_request->task_context_buffer = scic_sds_ssp_task_request_get_task_context_buffer(this_request); this_request->task_context_buffer = - scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); + PTR_ALIGN(this_request->task_context_buffer, SMP_CACHE_BYTES); } } diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 19b6feef373e..06b53c3b0aa0 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -313,28 +313,6 @@ extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_start #define scic_sds_request_get_task_context(request) \ ((request)->task_context_buffer) -#define CACHE_LINE_SIZE (64) -#define scic_sds_request_align_task_context_buffer(address) \ - ((struct scu_task_context *)(\ - (((unsigned long)(address)) + (CACHE_LINE_SIZE - 1)) \ - & ~(CACHE_LINE_SIZE - 1) \ - )) - -/** - * scic_sds_request_align_sgl_element_buffer() - - * - * This macro will align the memory address so that it is correct for the SCU - * hardware to DMA the SGL element pairs. - */ -#define scic_sds_request_align_sgl_element_buffer(address) \ - ((struct scu_sgl_element_pair *)(\ - ((char *)(address)) \ - + (\ - ((~(unsigned long)(address)) + 1) \ - & (sizeof(struct scu_sgl_element_pair) - 1) \ - ) \ - )) - /** * scic_sds_request_set_status() - * diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 85c890630d60..962bd3994f10 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -80,7 +80,8 @@ u32 scic_sds_smp_request_get_object_size(void) return sizeof(struct scic_sds_request) + sizeof(struct smp_request) + sizeof(struct smp_response) - + sizeof(struct scu_task_context); + + sizeof(struct scu_task_context) + + SMP_CACHE_BYTES; } /** @@ -137,7 +138,7 @@ void scic_sds_smp_request_assign_buffers( this_request->task_context_buffer = scic_sds_smp_request_get_task_context_buffer(this_request); this_request->task_context_buffer = - scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); + PTR_ALIGN(this_request->task_context_buffer, SMP_CACHE_BYTES); } } diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 0f17a28dd196..8da309f81ac2 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -131,33 +131,25 @@ u32 scic_sds_stp_request_get_object_size(void) + sizeof(struct sata_fis_reg_h2d) + sizeof(struct sata_fis_reg_d2h) + sizeof(struct scu_task_context) + + SMP_CACHE_BYTES + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; } -/** - * - * - * - */ -void scic_sds_stp_request_assign_buffers( - struct scic_sds_request *request) +void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) { - struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; - - this_request->parent.command_buffer = - scic_sds_stp_request_get_h2d_reg_buffer(this_request); - this_request->parent.response_buffer = - scic_sds_stp_request_get_response_buffer(this_request); - this_request->parent.sgl_element_pair_buffer = - scic_sds_stp_request_get_sgl_element_buffer(this_request); - this_request->parent.sgl_element_pair_buffer = - scic_sds_request_align_sgl_element_buffer(this_request->parent.sgl_element_pair_buffer); - - if (this_request->parent.was_tag_assigned_by_user == false) { - this_request->parent.task_context_buffer = - scic_sds_stp_request_get_task_context_buffer(this_request); - this_request->parent.task_context_buffer = - scic_sds_request_align_task_context_buffer(this_request->parent.task_context_buffer); + struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + + sci_req->command_buffer = scic_sds_stp_request_get_h2d_reg_buffer(stp_req); + sci_req->response_buffer = scic_sds_stp_request_get_response_buffer(stp_req); + sci_req->sgl_element_pair_buffer = scic_sds_stp_request_get_sgl_element_buffer(stp_req); + sci_req->sgl_element_pair_buffer = PTR_ALIGN(sci_req->sgl_element_pair_buffer, + sizeof(struct scu_sgl_element_pair)); + + if (sci_req->was_tag_assigned_by_user == false) { + sci_req->task_context_buffer = + scic_sds_stp_request_get_task_context_buffer(stp_req); + sci_req->task_context_buffer = PTR_ALIGN(sci_req->task_context_buffer, + SMP_CACHE_BYTES); } } -- cgit v1.2.3 From 52bed8eab5d392183b77426b96551011f3521ef8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Mar 2011 17:59:25 -0800 Subject: isci: enable isci for dmar builds Now that phys_to_virt() and virt_to_phys() have been removed we are no longer violating the dma mapping (or kmap apis). Signed-off-by: Dan Williams --- drivers/scsi/Kconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3aa664fa892e..e18938bebcd3 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -833,10 +833,7 @@ config SCSI_GDTH config SCSI_ISCI tristate "Intel(R) C600 Series Chipset SAS Controller" depends on PCI && SCSI - # little endian host assumptions depends on X86 - # (temporary): dma api misuse - depends on !DMAR # (temporary): known alpha quality driver depends on EXPERIMENTAL select SCSI_SAS_LIBSAS -- cgit v1.2.3 From b329aff107543c3c4db26c1572405034c3baf906 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 7 Mar 2011 16:02:25 -0800 Subject: isci: kill isci_host list in favor of an array isci_host_by_id() should have been a clue that an array would have been a simpler approach. Reported-by: James Bottomley Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 3 ++- drivers/scsi/isci/host.h | 10 +++++----- drivers/scsi/isci/init.c | 25 +++++++------------------ 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 40614e9ab41b..da0c0da4198f 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -78,8 +78,9 @@ irqreturn_t isci_intx_isr(int vec, void *data) struct pci_dev *pdev = data; struct isci_host *ihost; irqreturn_t ret = IRQ_NONE; + int i; - for_each_isci_host(ihost, pdev) { + for_each_isci_host(i, ihost, pdev) { struct scic_sds_controller *scic = ihost->core_controller; if (scic_sds_controller_isr(scic)) { diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index ef3e7d1440b0..7c1f0b5cee7d 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -117,7 +117,6 @@ struct isci_host { struct list_head requests_to_complete; struct list_head requests_to_abort; spinlock_t scic_lock; - struct isci_host *next; }; @@ -131,7 +130,7 @@ struct isci_host { struct isci_pci_info { struct msix_entry msix_entries[SCI_MAX_MSIX_INT]; int core_lib_array_index; - struct isci_host *hosts; + struct isci_host *hosts[SCI_MAX_CONTROLLERS]; }; static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev) @@ -139,9 +138,10 @@ static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev) return pci_get_drvdata(pdev); } -#define for_each_isci_host(isci_host, pdev) \ - for (isci_host = to_pci_info(pdev)->hosts;\ - isci_host; isci_host = isci_host->next) +#define for_each_isci_host(id, ihost, pdev) \ + for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \ + id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \ + ihost = to_pci_info(pdev)->hosts[++id]) static inline enum isci_status isci_host_get_state( diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index d01c44f5be99..f1b8a51dd49f 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -285,16 +285,6 @@ static int __devinit isci_pci_init(struct pci_dev *pdev) return 0; } -static struct isci_host *isci_host_by_id(struct pci_dev *pdev, int id) -{ - struct isci_host *h; - - for_each_isci_host(h, pdev) - if (h->id == id) - return h; - return NULL; -} - static int num_controllers(struct pci_dev *pdev) { /* bar size alone can tell us if we are running with a dual controller @@ -332,7 +322,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev) for (i = 0; i < num_msix; i++) { int id = i / SCI_NUM_MSI_X_INT; struct msix_entry *msix = &pci_info->msix_entries[i]; - struct isci_host *isci_host = isci_host_by_id(pdev, id); + struct isci_host *isci_host = pci_info->hosts[id]; irq_handler_t isr; /* odd numbered vectors are error interrupts */ @@ -351,7 +341,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev) dev_info(&pdev->dev, "msix setup failed falling back to intx\n"); while (i--) { id = i / SCI_NUM_MSI_X_INT; - isci_host = isci_host_by_id(pdev, id); + isci_host = pci_info->hosts[id]; msix = &pci_info->msix_entries[i]; devm_free_irq(&pdev->dev, msix->vector, isci_host); } @@ -634,22 +624,20 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic err = -ENOMEM; goto err_host_alloc; } - - h->next = pci_info->hosts; - pci_info->hosts = h; + pci_info->hosts[i] = h; } err = isci_setup_interrupts(pdev); if (err) goto err_host_alloc; - for_each_isci_host(isci_host, pdev) + for_each_isci_host(i, isci_host, pdev) scsi_scan_host(isci_host->shost); return 0; err_host_alloc: - for_each_isci_host(isci_host, pdev) + for_each_isci_host(i, isci_host, pdev) isci_unregister_sas_ha(isci_host); return err; } @@ -657,8 +645,9 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic static void __devexit isci_pci_remove(struct pci_dev *pdev) { struct isci_host *isci_host; + int i; - for_each_isci_host(isci_host, pdev) { + for_each_isci_host(i, isci_host, pdev) { isci_unregister_sas_ha(isci_host); isci_host_deinit(isci_host); scic_controller_disable_interrupts(isci_host->core_controller); -- cgit v1.2.3 From 3a97eec6d7876c541950e23811efd40e0bcd04a0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 4 Mar 2011 11:51:43 -0800 Subject: isci: remove sci_device_handle It belies the fact that isci_remote_device and scic_sds_remote_device are one in same object with the same lifetime rules. Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 33 +++++++++------------------------ drivers/scsi/isci/remote_device.h | 7 ++++++- drivers/scsi/isci/request.c | 7 +++---- drivers/scsi/isci/sata.c | 2 +- drivers/scsi/isci/task.c | 15 +++++++-------- 5 files changed, 26 insertions(+), 38 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index e684a053189e..0eb5c7330fac 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -92,7 +92,7 @@ static void isci_remote_device_deconstruct( /* Remove all related references to this device and free * the cache object. */ - scic_remote_device_destruct(isci_device->sci_device_handle); + scic_remote_device_destruct(to_sci_dev(isci_device)); isci_device->domain_dev->lldd_dev = NULL; list_del(&isci_device->node); kmem_cache_free(isci_kmem_cache, isci_device); @@ -117,7 +117,7 @@ static enum sci_status isci_remote_device_construct( /* let the core do it's common constuction. */ scic_remote_device_construct(port->sci_port_handle, - isci_device->sci_device_handle); + to_sci_dev(isci_device)); /* let the core do it's device specific constuction. */ if (isci_device->domain_dev->parent && @@ -183,15 +183,11 @@ static enum sci_status isci_remote_device_construct( "%s: parent->dev_type = EDGE_DEV\n", __func__); - status = scic_remote_device_ea_construct( - isci_device->sci_device_handle, - (struct smp_response_discover *)&discover_response - ); + status = scic_remote_device_ea_construct(to_sci_dev(isci_device), + (struct smp_response_discover *)&discover_response); } else - status = scic_remote_device_da_construct( - isci_device->sci_device_handle - ); + status = scic_remote_device_da_construct(to_sci_dev(isci_device)); if (status != SCI_SUCCESS) { @@ -204,18 +200,13 @@ static enum sci_status isci_remote_device_construct( return status; } - sci_object_set_association( - isci_device->sci_device_handle, - isci_device - ); + sci_object_set_association(to_sci_dev(isci_device), isci_device); BUG_ON(port->isci_host == NULL); /* start the device. */ - status = scic_remote_device_start( - isci_device->sci_device_handle, - ISCI_REMOTE_DEVICE_START_TIMEOUT - ); + status = scic_remote_device_start(to_sci_dev(isci_device), + ISCI_REMOTE_DEVICE_START_TIMEOUT); if (status != SCI_SUCCESS) { dev_warn(&port->isci_host->pdev->dev, @@ -266,7 +257,6 @@ static struct isci_remote_device * isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port) { struct isci_remote_device *isci_device; - struct scic_sds_remote_device *sci_dev; isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL); @@ -275,8 +265,6 @@ isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port) return NULL; } - sci_dev = (struct scic_sds_remote_device *) &isci_device[1]; - isci_device->sci_device_handle = sci_dev; INIT_LIST_HEAD(&isci_device->reqs_in_process); INIT_LIST_HEAD(&isci_device->node); isci_device->host_quiesce = false; @@ -441,10 +429,7 @@ enum sci_status isci_remote_device_stop( spin_lock_irqsave(&isci_device->isci_port->isci_host->scic_lock, flags); - status = scic_remote_device_stop( - isci_device->sci_device_handle, - 50 - ); + status = scic_remote_device_stop(to_sci_dev(isci_device), 50); spin_unlock_irqrestore(&isci_device->isci_port->isci_host->scic_lock, flags); diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 48e37cfef6fb..cd43c15f009d 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -60,7 +60,6 @@ struct isci_host; struct scic_sds_remote_device; struct isci_remote_device { - struct scic_sds_remote_device *sci_device_handle; enum isci_status status; struct isci_port *isci_port; struct domain_device *domain_dev; @@ -73,6 +72,12 @@ struct isci_remote_device { bool host_quiesce; }; +static inline struct scic_sds_remote_device *to_sci_dev(struct isci_remote_device *idev) +{ + /* core data is an opaque buffer at the end of the idev */ + return (struct scic_sds_remote_device *) &idev[1]; +} + #define to_isci_remote_device(p) \ container_of(p, struct isci_remote_device, sci_remote_device); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 81a77335fdb3..6b0863e73f22 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -179,8 +179,7 @@ static enum sci_status isci_io_request_build( struct smp_discover_response_protocols dev_protocols; enum sci_status status = SCI_SUCCESS; struct sas_task *task = isci_request_access_task(request); - struct scic_sds_remote_device *sci_device = - isci_device->sci_device_handle; + struct scic_sds_remote_device *sci_device = to_sci_dev(isci_device); dev_dbg(&isci_host->pdev->dev, "%s: isci_device = 0x%p; request = %p, " @@ -408,7 +407,7 @@ int isci_request_execute( unsigned long flags; isci_device = isci_dev_from_domain_dev(task->dev); - sci_device = isci_device->sci_device_handle; + sci_device = to_sci_dev(isci_device); /* do common allocation and init of request object. */ ret = isci_request_alloc_io( @@ -1177,7 +1176,7 @@ void isci_request_io_request_complete( /* complete the io request to the core. */ scic_controller_complete_io( isci_host->core_controller, - isci_device->sci_device_handle, + to_sci_dev(isci_device), request->sci_request_handle ); /* NULL the request handle so it cannot be completed or diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 6fbf15944b21..7a1b58600ca0 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -348,7 +348,7 @@ int isci_task_send_lu_reset_sata( spin_lock_irqsave(&isci_host->scic_lock, flags); /* Resume the device. */ - scic_sds_remote_device_resume(isci_device->sci_device_handle); + scic_sds_remote_device_resume(to_sci_dev(isci_device)); spin_unlock_irqrestore(&isci_host->scic_lock, flags); diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 232125eab523..c637bbc215c6 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -285,7 +285,7 @@ static enum sci_status isci_task_request_build( "%s: isci_tmf = %p\n", __func__, isci_tmf); isci_device = isci_tmf->device; - sci_device = isci_device->sci_device_handle; + sci_device = to_sci_dev(isci_device); /* do common allocation and init of request object. */ status = isci_request_alloc_tmf( @@ -395,7 +395,7 @@ static void isci_tmf_timeout_cb(void *tmf_request_arg) /* Terminate the TMF transmit request. */ status = scic_controller_terminate_request( request->isci_host->core_controller, - request->isci_device->sci_device_handle, + to_sci_dev(request->isci_device), request->sci_request_handle ); @@ -456,7 +456,7 @@ int isci_task_execute_tmf( "%s: isci_device = %p\n", __func__, isci_device); - sci_device = isci_device->sci_device_handle; + sci_device = to_sci_dev(isci_device); /* Assign the pointer to the TMF's completion kernel wait structure. */ tmf->complete = &completion; @@ -728,7 +728,7 @@ static void isci_terminate_request_core( was_terminated = true; status = scic_controller_terminate_request( isci_host->core_controller, - isci_device->sci_device_handle, + to_sci_dev(isci_device), isci_request->sci_request_handle ); } @@ -1469,7 +1469,7 @@ void isci_task_request_complete( scic_controller_complete_task( isci_host->core_controller, - isci_device->sci_device_handle, + to_sci_dev(isci_device), request->sci_request_handle ); /* NULL the request handle to make sure it cannot be terminated @@ -1612,7 +1612,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) if (isci_host != NULL) spin_lock_irqsave(&isci_host->scic_lock, flags); - status = scic_remote_device_reset(isci_dev->sci_device_handle); + status = scic_remote_device_reset(to_sci_dev(isci_dev)); if (status != SCI_SUCCESS) { if (isci_host != NULL) @@ -1654,8 +1654,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) if (isci_host != NULL) spin_lock_irqsave(&isci_host->scic_lock, flags); - status - = scic_remote_device_reset_complete(isci_dev->sci_device_handle); + status = scic_remote_device_reset_complete(to_sci_dev(isci_dev)); if (isci_host != NULL) spin_unlock_irqrestore(&isci_host->scic_lock, flags); -- cgit v1.2.3 From 8acaec1593526f922ff46812d99abf9aab5c8b43 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 7 Mar 2011 14:47:35 -0800 Subject: isci: kill "host quiesce" mechanism The midlayer is already throttling i/o in the places where host_quiesce was trying to prevent further i/o to the device. It's also problematic in that it holds a lock over GFP_KERNEL allocations. Signed-off-by: Dan Williams --- drivers/scsi/isci/port.h | 1 - drivers/scsi/isci/remote_device.c | 27 ++------------------- drivers/scsi/isci/remote_device.h | 22 ------------------ drivers/scsi/isci/task.c | 49 +++++---------------------------------- 4 files changed, 8 insertions(+), 91 deletions(-) diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index b01b0c63e53f..b864d70363e7 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -73,7 +73,6 @@ enum isci_status { isci_ready_for_io = 0x03, isci_stopping = 0x04, isci_stopped = 0x05, - isci_host_quiesce = 0x06 }; /** diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 0eb5c7330fac..fc1f24449170 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -267,36 +267,13 @@ isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port) INIT_LIST_HEAD(&isci_device->reqs_in_process); INIT_LIST_HEAD(&isci_device->node); - isci_device->host_quiesce = false; spin_lock_init(&isci_device->state_lock); - spin_lock_init(&isci_device->host_quiesce_lock); isci_remote_device_change_state(isci_device, isci_freed); return isci_device; } -/** - * isci_device_set_host_quiesce_lock_state() - This function sets the host I/O - * quiesce lock state for the remote_device object. - * @isci_device,: This parameter points to the isci_remote_device object - * @isci_device: This parameter specifies the new quiesce state. - * - */ -void isci_device_set_host_quiesce_lock_state( - struct isci_remote_device *isci_device, - bool lock_state) -{ - unsigned long flags; - - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, - "%s: isci_device=%p, lock_state=%d\n", - __func__, isci_device, lock_state); - - spin_lock_irqsave(&isci_device->host_quiesce_lock, flags); - isci_device->host_quiesce = lock_state; - spin_unlock_irqrestore(&isci_device->host_quiesce_lock, flags); -} /** * isci_remote_device_ready() - This function is called by the scic when the @@ -314,8 +291,8 @@ void isci_remote_device_ready(struct isci_remote_device *isci_device) "%s: isci_device = %p\n", __func__, isci_device); /* device ready is actually a "ready for io" state. */ - if ((isci_starting == isci_remote_device_get_state(isci_device)) || - (isci_ready == isci_remote_device_get_state(isci_device))) { + if (isci_device->status == isci_starting || + isci_device->status == isci_ready) { spin_lock_irqsave(&isci_device->isci_port->remote_device_lock, flags); isci_remote_device_change_state(isci_device, isci_ready_for_io); diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index cd43c15f009d..af03039c12f1 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -68,8 +68,6 @@ struct isci_remote_device { struct list_head reqs_in_process; struct work_struct stop_work; spinlock_t state_lock; - spinlock_t host_quiesce_lock; - bool host_quiesce; }; static inline struct scic_sds_remote_device *to_sci_dev(struct isci_remote_device *idev) @@ -84,22 +82,6 @@ static inline struct scic_sds_remote_device *to_sci_dev(struct isci_remote_devic #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 -/** - * This function gets the status of the remote_device object. - * @isci_device: This parameter points to the isci_remote_device object - * - * status of the object as a isci_status enum. - */ -static inline -enum isci_status isci_remote_device_get_state( - struct isci_remote_device *isci_device) -{ - return (isci_device->host_quiesce) - ? isci_host_quiesce - : isci_device->status; -} - - /** * isci_dev_from_domain_dev() - This accessor retrieves the remote_device * object reference from the Linux domain_device reference. @@ -146,10 +128,6 @@ bool isci_device_is_reset_pending( void isci_device_clear_reset_pending( struct isci_remote_device *isci_device); -void isci_device_set_host_quiesce_lock_state( - struct isci_remote_device *isci_device, - bool lock_state); - void isci_remote_device_change_state( struct isci_remote_device *isci_device, enum isci_status status); diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c637bbc215c6..98204b031649 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -81,7 +81,6 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) struct isci_request *request = NULL; struct isci_remote_device *device; unsigned long flags; - unsigned long quiesce_flags = 0; int ret; enum sci_status status; @@ -151,21 +150,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) isci_host = isci_host_from_sas_ha(task->dev->port->ha); - /* check if the controller hasn't started or if the device - * is ready but not accepting IO. - */ - if (device) { - - spin_lock_irqsave(&device->host_quiesce_lock, - quiesce_flags); - } - /* From this point onward, any process that needs to guarantee - * that there is no kernel I/O being started will have to wait - * for the quiesce spinlock. - */ - - if ((device && ((isci_remote_device_get_state(device) == isci_ready) || - (isci_remote_device_get_state(device) == isci_host_quiesce)))) { + if (device && device->status == isci_ready) { /* Forces a retry from scsi mid layer. */ dev_warn(task->dev->port->ha->dev, @@ -179,8 +164,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) if (device) dev_dbg(task->dev->port->ha->dev, "%s: device->status = 0x%x\n", - __func__, - isci_remote_device_get_state(device)); + __func__, device->status); /* Indicate QUEUE_FULL so that the scsi midlayer * retries. @@ -194,7 +178,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) isci_host_can_dequeue(isci_host, 1); } /* the device is going down... */ - else if (!device || (isci_ready_for_io != isci_remote_device_get_state(device))) { + else if (!device || device->status != isci_ready_for_io) { dev_dbg(task->dev->port->ha->dev, "%s: task %p: isci_host->status = %d, " @@ -207,8 +191,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) if (device) dev_dbg(task->dev->port->ha->dev, "%s: device->status = 0x%x\n", - __func__, - isci_remote_device_get_state(device)); + __func__, device->status); /* Indicate SAS_TASK_UNDELIVERED, so that the scsi * midlayer removes the target. @@ -247,11 +230,6 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) isci_host_can_dequeue(isci_host, 1); } } - if (device) { - spin_unlock_irqrestore(&device->host_quiesce_lock, - quiesce_flags - ); - } task = list_entry(task->list.next, struct sas_task, list); } while (--num > 0); return 0; @@ -442,14 +420,11 @@ int isci_task_execute_tmf( /* sanity check, return TMF_RESP_FUNC_FAILED * if the device is not there and ready. */ - if (!isci_device || - ((isci_ready_for_io != isci_remote_device_get_state(isci_device)) && - (isci_host_quiesce != isci_remote_device_get_state(isci_device)))) { + if (!isci_device || isci_device->status != isci_ready_for_io) { dev_dbg(&isci_host->pdev->dev, "%s: isci_device = %p not ready (%d)\n", __func__, - isci_device, - isci_remote_device_get_state(isci_device)); + isci_device, isci_device->status); return TMF_RESP_FUNC_FAILED; } else dev_dbg(&isci_host->pdev->dev, @@ -986,9 +961,6 @@ int isci_task_lu_reset( return TMF_RESP_FUNC_FAILED; } - /* Stop I/O to the remote device. */ - isci_device_set_host_quiesce_lock_state(isci_device, true); - /* Send the task management part of the reset. */ if (sas_protocol_ata(domain_device->tproto)) { ret = isci_task_send_lu_reset_sata( @@ -1004,9 +976,6 @@ int isci_task_lu_reset( isci_device, terminating); - /* Resume I/O to the remote device. */ - isci_device_set_host_quiesce_lock_state(isci_device, false); - return ret; } @@ -1627,9 +1596,6 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) if (isci_host != NULL) spin_unlock_irqrestore(&isci_host->scic_lock, flags); - /* Stop I/O to the remote device. */ - isci_device_set_host_quiesce_lock_state(isci_dev, true); - /* Make sure all pending requests are able to be fully terminated. */ isci_device_clear_reset_pending(isci_dev); @@ -1671,8 +1637,5 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) "%s: cmd %p, isci_dev %p complete.\n", __func__, cmd, isci_dev); - /* Resume I/O to the remote device. */ - isci_device_set_host_quiesce_lock_state(isci_dev, false); - return TMF_RESP_FUNC_COMPLETE; } -- cgit v1.2.3 From 6ad31fec306d532031b2f778f8656385df1b9d8f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 4 Mar 2011 12:10:29 -0800 Subject: isci: replace isci_remote_device completion with event queue Replace the device completion infrastructure with the controller wide event queue. There was a potential for the stop and ready notifications to corrupt each other, now that cannot happen. The stop pending flag cannot be used until devices are statically allocated. We temporarily need to maintain a completion to handle waiting for an object that has disappeared, but we can at least stop scribbling on freed memory. A future change will also get rid of the "stopping" state as it should not be exposed to the rest of the driver. Signed-off-by: Dan Williams --- drivers/scsi/isci/events.c | 30 +++++------- drivers/scsi/isci/host.c | 2 +- drivers/scsi/isci/host.h | 13 ++++++ drivers/scsi/isci/remote_device.c | 98 +++++++++++++++------------------------ drivers/scsi/isci/remote_device.h | 11 +++-- 5 files changed, 69 insertions(+), 85 deletions(-) diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c index c5cbaedac041..9d58e458a37b 100644 --- a/drivers/scsi/isci/events.c +++ b/drivers/scsi/isci/events.c @@ -526,7 +526,7 @@ void isci_event_remote_device_start_complete( /** * isci_event_remote_device_stop_complete() - This user callback method will * inform the user that a stop operation has completed. - * @controller: This parameter specifies the core controller associated with + * @scic: This parameter specifies the core controller associated with * the completion callback. * @remote_device: This parameter specifies the remote device associated with * the completion callback. @@ -534,28 +534,20 @@ void isci_event_remote_device_start_complete( * operation. * */ -void isci_event_remote_device_stop_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - enum sci_status completion_status) +void isci_event_remote_device_stop_complete(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + enum sci_status completion_status) { - struct isci_host *isci_host; - struct isci_remote_device *isci_device; + struct isci_host *ihost; + struct isci_remote_device *idev; - isci_host = - (struct isci_host *)sci_object_get_association(controller); + ihost = sci_object_get_association(scic); + idev = sci_object_get_association(sci_dev); - isci_device = - (struct isci_remote_device *)sci_object_get_association( - remote_device - ); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); - - isci_remote_device_stop_complete( - isci_host, isci_device, completion_status); + dev_dbg(&ihost->pdev->dev, + "%s: idev = %p\n", __func__, idev); + isci_remote_device_stop_complete(ihost, idev, completion_status); } /** diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index da0c0da4198f..8d255666a657 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -345,7 +345,7 @@ void isci_host_deinit(struct isci_host *ihost) list_for_each_entry_safe(idev, d, &port->remote_dev_list, node) { isci_remote_device_change_state(idev, isci_stopping); - isci_remote_device_stop(idev); + isci_remote_device_stop(ihost, idev); } } diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 7c1f0b5cee7d..6a6304c06976 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -212,6 +212,19 @@ static inline void wait_for_stop(struct isci_host *ihost) wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags)); } +static inline void wait_for_device_start(struct isci_host *ihost, struct isci_remote_device *idev) +{ + wait_event(ihost->eventq, !test_bit(IDEV_START_PENDING, &idev->flags)); +} + +static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev) +{ + /* todo switch to: + * wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags)); + * once devices are statically allocated + */ + wait_for_completion(idev->cmp); +} /** * isci_host_from_sas_ha() - This accessor retrieves the isci_host object diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index fc1f24449170..db2259ce003f 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -95,6 +95,11 @@ static void isci_remote_device_deconstruct( scic_remote_device_destruct(to_sci_dev(isci_device)); isci_device->domain_dev->lldd_dev = NULL; list_del(&isci_device->node); + + clear_bit(IDEV_STOP_PENDING, &isci_device->flags); + clear_bit(IDEV_START_PENDING, &isci_device->flags); + wake_up(&isci_host->eventq); + complete(isci_device->cmp); kmem_cache_free(isci_kmem_cache, isci_device); } @@ -279,30 +284,22 @@ isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port) * isci_remote_device_ready() - This function is called by the scic when the * remote device is ready. We mark the isci device as ready and signal the * waiting proccess. - * @isci_host: This parameter specifies the isci host object. - * @isci_device: This parameter specifies the remote device + * @idev: This parameter specifies the remote device * */ -void isci_remote_device_ready(struct isci_remote_device *isci_device) +void isci_remote_device_ready(struct isci_remote_device *idev) { + struct isci_host *ihost = idev->isci_port->isci_host; unsigned long flags; - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); - - /* device ready is actually a "ready for io" state. */ - if (isci_device->status == isci_starting || - isci_device->status == isci_ready) { - spin_lock_irqsave(&isci_device->isci_port->remote_device_lock, - flags); - isci_remote_device_change_state(isci_device, isci_ready_for_io); - if (isci_device->completion) - complete(isci_device->completion); - spin_unlock_irqrestore( - &isci_device->isci_port->remote_device_lock, - flags); - } + dev_dbg(&ihost->pdev->dev, + "%s: isci_device = %p\n", __func__, idev); + spin_lock_irqsave(&idev->isci_port->remote_device_lock, flags); + isci_remote_device_change_state(idev, isci_ready_for_io); + if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags)) + wake_up(&ihost->eventq); + spin_unlock_irqrestore(&idev->isci_port->remote_device_lock, flags); } /** @@ -341,8 +338,6 @@ void isci_remote_device_stop_complete( struct isci_remote_device *isci_device, enum sci_status status) { - struct completion *completion = isci_device->completion; - dev_dbg(&isci_host->pdev->dev, "%s: complete isci_device = %p, status = 0x%x\n", __func__, @@ -354,9 +349,6 @@ void isci_remote_device_stop_complete( /* after stop, we can tear down resources. */ isci_remote_device_deconstruct(isci_host, isci_device); - /* notify interested parties. */ - if (completion) - complete(completion); } /** @@ -385,40 +377,33 @@ void isci_remote_device_start_complete( * * The status of the scic request to stop. */ -enum sci_status isci_remote_device_stop( - struct isci_remote_device *isci_device) +enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev) { enum sci_status status; unsigned long flags; - DECLARE_COMPLETION_ONSTACK(completion); - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); - - isci_remote_device_change_state(isci_device, isci_stopping); - - /* We need comfirmation that stop completed. */ - isci_device->completion = &completion; + dev_dbg(&ihost->pdev->dev, + "%s: isci_device = %p\n", __func__, idev); - BUG_ON(isci_device->isci_port == NULL); - BUG_ON(isci_device->isci_port->isci_host == NULL); + isci_remote_device_change_state(idev, isci_stopping); + set_bit(IDEV_STOP_PENDING, &idev->flags); + idev->cmp = &completion; - spin_lock_irqsave(&isci_device->isci_port->isci_host->scic_lock, flags); + spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_stop(to_sci_dev(isci_device), 50); + status = scic_remote_device_stop(to_sci_dev(idev), 50); - spin_unlock_irqrestore(&isci_device->isci_port->isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Wait for the stop complete callback. */ if (status == SCI_SUCCESS) - wait_for_completion(&completion); + wait_for_device_stop(ihost, idev); - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, - "%s: isci_device = %p - after completion wait\n", - __func__, isci_device); + dev_dbg(&ihost->pdev->dev, + "%s: idev = %p - after completion wait\n", + __func__, idev); - isci_device->completion = NULL; return status; } @@ -428,18 +413,16 @@ enum sci_status isci_remote_device_stop( * @domain_device: This parameter specifies the libsas domain device. * */ -void isci_remote_device_gone( - struct domain_device *domain_dev) +void isci_remote_device_gone(struct domain_device *dev) { - struct isci_remote_device *isci_device = isci_dev_from_domain_dev( - domain_dev); + struct isci_host *ihost = dev->port->ha->lldd_ha; + struct isci_remote_device *idev = dev->lldd_dev; - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: domain_device = %p, isci_device = %p, isci_port = %p\n", - __func__, domain_dev, isci_device, isci_device->isci_port); + __func__, dev, idev, idev->isci_port); - if (isci_device != NULL) - isci_remote_device_stop(isci_device); + isci_remote_device_stop(ihost, idev); } @@ -462,7 +445,6 @@ int isci_remote_device_found(struct domain_device *domain_dev) struct asd_sas_phy *sas_phy; struct isci_remote_device *isci_device; enum sci_status status; - DECLARE_COMPLETION_ONSTACK(completion); isci_host = isci_host_from_sas_ha(domain_dev->port->ha); @@ -498,17 +480,10 @@ int isci_remote_device_found(struct domain_device *domain_dev) spin_lock_irqsave(&isci_port->remote_device_lock, flags); list_add_tail(&isci_device->node, &isci_port->remote_dev_list); - /* for the device ready event. */ - isci_device->completion = &completion; - + set_bit(IDEV_START_PENDING, &isci_device->flags); status = isci_remote_device_construct(isci_port, isci_device); - spin_unlock_irqrestore(&isci_port->remote_device_lock, flags); - /* wait for the device ready callback. */ - wait_for_completion(isci_device->completion); - isci_device->completion = NULL; - dev_dbg(&isci_host->pdev->dev, "%s: isci_device = %p\n", __func__, isci_device); @@ -524,6 +499,9 @@ int isci_remote_device_found(struct domain_device *domain_dev) return -ENODEV; } + /* wait for the device ready callback. */ + wait_for_device_start(isci_host, isci_device); + return 0; } /** diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index af03039c12f1..3c22137c9f65 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -61,12 +61,14 @@ struct scic_sds_remote_device; struct isci_remote_device { enum isci_status status; + #define IDEV_START_PENDING 0 + #define IDEV_STOP_PENDING 1 + unsigned long flags; + struct completion *cmp; struct isci_port *isci_port; struct domain_device *domain_dev; - struct completion *completion; struct list_head node; struct list_head reqs_in_process; - struct work_struct stop_work; spinlock_t state_lock; }; @@ -102,9 +104,8 @@ void isci_remote_device_stop_complete( struct isci_remote_device *, enum sci_status); -enum sci_status isci_remote_device_stop( - struct isci_remote_device *isci_device); - +enum sci_status isci_remote_device_stop(struct isci_host *ihost, + struct isci_remote_device *idev); void isci_remote_device_nuke_requests( struct isci_remote_device *isci_device); -- cgit v1.2.3 From d9c37390c4f02153188a64a7a89fa6798dc3ffc2 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Mar 2011 17:59:32 -0800 Subject: isci: preallocate remote devices Until we synchronize against device removal this limits the damage of use after free bugs to the driver's own objects. Unless we implement reference counting we need to ensure at least a subset of a remote device is valid at all times. We follow the lead of other libsas drivers that also preallocate devices. This also enforces maximum remote device accounting at the lldd layer, but the core may still run out of RNC's before we hit this limit. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 21 ++++++----- drivers/scsi/isci/host.h | 17 ++++++--- drivers/scsi/isci/init.c | 27 ++++----------- drivers/scsi/isci/isci.h | 1 - drivers/scsi/isci/remote_device.c | 73 +++++++++++++++++++-------------------- drivers/scsi/isci/remote_device.h | 2 +- 6 files changed, 68 insertions(+), 73 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 8d255666a657..ae5d46022073 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -378,8 +378,7 @@ static void __iomem *smu_base(struct isci_host *isci_host) int isci_host_init(struct isci_host *isci_host) { - int err = 0; - int index = 0; + int err = 0, i; enum sci_status status; struct scic_sds_controller *controller; union scic_oem_parameters scic_oem_params; @@ -509,13 +508,19 @@ int isci_host_init(struct isci_host *isci_host) if (!isci_host->dma_pool) return -ENOMEM; - for (index = 0; index < SCI_MAX_PORTS; index++) - isci_port_init(&isci_host->isci_ports[index], - isci_host, - index); + for (i = 0; i < SCI_MAX_PORTS; i++) + isci_port_init(&isci_host->isci_ports[i], isci_host, i); - for (index = 0; index < SCI_MAX_PHYS; index++) - isci_phy_init(&isci_host->phys[index], isci_host, index); + for (i = 0; i < SCI_MAX_PHYS; i++) + isci_phy_init(&isci_host->phys[i], isci_host, i); + + for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { + struct isci_remote_device *idev = idev_by_id(isci_host, i); + + INIT_LIST_HEAD(&idev->reqs_in_process); + INIT_LIST_HEAD(&idev->node); + spin_lock_init(&idev->state_lock); + } return 0; } diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 6a6304c06976..3c69f1ffb1c3 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -61,6 +61,7 @@ /*#include "task.h"*/ #include "timers.h" #include "remote_device.h" +#include "scic_remote_device.h" #define DRV_NAME "isci" #define SCI_PCI_BAR_COUNT 2 @@ -117,8 +118,18 @@ struct isci_host { struct list_head requests_to_complete; struct list_head requests_to_abort; spinlock_t scic_lock; + + /* careful only access this via idev_by_id */ + struct isci_remote_device devices[0]; }; +static inline struct isci_remote_device *idev_by_id(struct isci_host *ihost, int i) +{ + void *p = ihost->devices; + + return p + i * (sizeof(struct isci_remote_device) + + scic_remote_device_get_object_size()); +} /** * struct isci_pci_info - This class represents the pci function containing the @@ -219,11 +230,7 @@ static inline void wait_for_device_start(struct isci_host *ihost, struct isci_re static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev) { - /* todo switch to: - * wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags)); - * once devices are statically allocated - */ - wait_for_completion(idev->cmp); + wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags)); } /** diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index f1b8a51dd49f..2838beff43b8 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -64,7 +64,6 @@ #include "sci_environment.h" static struct scsi_transport_template *isci_transport_template; -struct kmem_cache *isci_kmem_cache; static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { { PCI_VDEVICE(INTEL, 0x1D61),}, @@ -443,7 +442,10 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) struct Scsi_Host *shost; int err; - isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); + isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host) + + SCI_MAX_REMOTE_DEVICES * + (sizeof(struct isci_remote_device) + + scic_remote_device_get_object_size()), GFP_KERNEL); if (!isci_host) return NULL; @@ -656,31 +658,17 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev) static __init int isci_init(void) { - int err = -ENOMEM; + int err; pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME); - isci_kmem_cache = kmem_cache_create(DRV_NAME, - sizeof(struct isci_remote_device) + - scic_remote_device_get_object_size(), - 0, 0, NULL); - if (!isci_kmem_cache) - return err; - isci_transport_template = sas_domain_attach_transport(&isci_transport_ops); if (!isci_transport_template) - goto err_kmem; + return -ENOMEM; err = pci_register_driver(&isci_pci_driver); if (err) - goto err_sas; - - return 0; - - err_sas: - sas_release_transport(isci_transport_template); - err_kmem: - kmem_cache_destroy(isci_kmem_cache); + sas_release_transport(isci_transport_template); return err; } @@ -689,7 +677,6 @@ static __exit void isci_exit(void) { pci_unregister_driver(&isci_pci_driver); sas_release_transport(isci_transport_template); - kmem_cache_destroy(isci_kmem_cache); } MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 9b9aa50954ce..24c67b039d4a 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -89,7 +89,6 @@ #include "task.h" #include "sata.h" -extern struct kmem_cache *isci_kmem_cache; extern struct isci_firmware *isci_firmware; #define ISCI_FW_NAME "isci/isci_firmware.bin" diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index db2259ce003f..48556e47bb9d 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -67,40 +67,35 @@ /** * isci_remote_device_deconstruct() - This function frees an isci_remote_device. - * @isci_host: This parameter specifies the isci host object. - * @isci_device: This parameter specifies the remote device to be freed. + * @ihost: This parameter specifies the isci host object. + * @idev: This parameter specifies the remote device to be freed. * */ -static void isci_remote_device_deconstruct( - struct isci_host *isci_host, - struct isci_remote_device *isci_device) +static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_remote_device *idev) { - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); + dev_dbg(&ihost->pdev->dev, + "%s: isci_device = %p\n", __func__, idev); /* There should not be any outstanding io's. All paths to * here should go through isci_remote_device_nuke_requests. * If we hit this condition, we will need a way to complete * io requests in process */ - while (!list_empty(&isci_device->reqs_in_process)) { + while (!list_empty(&idev->reqs_in_process)) { - dev_err(&isci_host->pdev->dev, + dev_err(&ihost->pdev->dev, "%s: ** request list not empty! **\n", __func__); BUG(); } - /* Remove all related references to this device and free - * the cache object. - */ - scic_remote_device_destruct(to_sci_dev(isci_device)); - isci_device->domain_dev->lldd_dev = NULL; - list_del(&isci_device->node); - - clear_bit(IDEV_STOP_PENDING, &isci_device->flags); - clear_bit(IDEV_START_PENDING, &isci_device->flags); - wake_up(&isci_host->eventq); - complete(isci_device->cmp); - kmem_cache_free(isci_kmem_cache, isci_device); + scic_remote_device_destruct(to_sci_dev(idev)); + idev->domain_dev->lldd_dev = NULL; + idev->domain_dev = NULL; + idev->isci_port = NULL; + list_del_init(&idev->node); + + clear_bit(IDEV_START_PENDING, &idev->flags); + clear_bit(IDEV_STOP_PENDING, &idev->flags); + wake_up(&ihost->eventq); } @@ -259,25 +254,27 @@ void isci_remote_device_nuke_requests( * pointer to new isci_remote_device. */ static struct isci_remote_device * -isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port) +isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) { - struct isci_remote_device *isci_device; + struct isci_remote_device *idev; + int i; - isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL); + for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { + idev = idev_by_id(ihost, i); + if (!test_and_set_bit(IDEV_ALLOCATED, &idev->flags)) + break; + } - if (!isci_device) { - dev_warn(&isci_host->pdev->dev, "%s: failed\n", __func__); + if (i >= SCI_MAX_REMOTE_DEVICES) { + dev_warn(&ihost->pdev->dev, "%s: failed\n", __func__); return NULL; } - INIT_LIST_HEAD(&isci_device->reqs_in_process); - INIT_LIST_HEAD(&isci_device->node); - - spin_lock_init(&isci_device->state_lock); - isci_remote_device_change_state(isci_device, isci_freed); - - return isci_device; + BUG_ON(!list_empty(&idev->reqs_in_process)); + BUG_ON(!list_empty(&idev->node)); + isci_remote_device_change_state(idev, isci_freed); + return idev; } /** @@ -381,24 +378,22 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem { enum sci_status status; unsigned long flags; - DECLARE_COMPLETION_ONSTACK(completion); dev_dbg(&ihost->pdev->dev, "%s: isci_device = %p\n", __func__, idev); isci_remote_device_change_state(idev, isci_stopping); set_bit(IDEV_STOP_PENDING, &idev->flags); - idev->cmp = &completion; spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_stop(to_sci_dev(idev), 50); - spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Wait for the stop complete callback. */ - if (status == SCI_SUCCESS) + if (status == SCI_SUCCESS) { wait_for_device_stop(ihost, idev); + clear_bit(IDEV_ALLOCATED, &idev->flags); + } dev_dbg(&ihost->pdev->dev, "%s: idev = %p - after completion wait\n", @@ -469,6 +464,8 @@ int isci_remote_device_found(struct domain_device *domain_dev) return -ENODEV; isci_device = isci_remote_device_alloc(isci_host, isci_port); + if (!isci_device) + return -ENODEV; INIT_LIST_HEAD(&isci_device->node); domain_dev->lldd_dev = isci_device; diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 3c22137c9f65..f45a5f064fce 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -63,8 +63,8 @@ struct isci_remote_device { enum isci_status status; #define IDEV_START_PENDING 0 #define IDEV_STOP_PENDING 1 + #define IDEV_ALLOCATED 2 unsigned long flags; - struct completion *cmp; struct isci_port *isci_port; struct domain_device *domain_dev; struct list_head node; -- cgit v1.2.3 From 1a38045ba88ed3bee6c57444670fb639c8b61be7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 3 Mar 2011 18:01:43 -0800 Subject: isci: replace remote_device_lock with scic_lock The remote_device_lock is currently used to protect a controller global resource (RNCs), but the remote_device_lock is per-port. Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 1 - drivers/scsi/isci/port.h | 1 - drivers/scsi/isci/remote_device.c | 14 +++++--------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 30da3ec703e3..a5b2565ac5af 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -94,7 +94,6 @@ void isci_port_init( INIT_LIST_HEAD(&isci_port->remote_dev_list); INIT_LIST_HEAD(&isci_port->domain_dev_list); - spin_lock_init(&isci_port->remote_device_lock); spin_lock_init(&isci_port->state_lock); init_completion(&isci_port->start_complete); isci_port->isci_host = isci_host; diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index b864d70363e7..b7a7dd7dca69 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -90,7 +90,6 @@ struct isci_port { struct isci_host *isci_host; struct asd_sas_port sas_port; struct list_head remote_dev_list; - spinlock_t remote_device_lock; spinlock_t state_lock; struct list_head domain_dev_list; struct completion start_complete; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 48556e47bb9d..1dae2184b9e9 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -287,16 +287,13 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) void isci_remote_device_ready(struct isci_remote_device *idev) { struct isci_host *ihost = idev->isci_port->isci_host; - unsigned long flags; dev_dbg(&ihost->pdev->dev, - "%s: isci_device = %p\n", __func__, idev); + "%s: idev = %p\n", __func__, idev); - spin_lock_irqsave(&idev->isci_port->remote_device_lock, flags); isci_remote_device_change_state(idev, isci_ready_for_io); if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags)) wake_up(&ihost->eventq); - spin_unlock_irqrestore(&idev->isci_port->remote_device_lock, flags); } /** @@ -432,7 +429,6 @@ void isci_remote_device_gone(struct domain_device *dev) */ int isci_remote_device_found(struct domain_device *domain_dev) { - unsigned long flags; struct isci_host *isci_host; struct isci_port *isci_port; struct isci_phy *isci_phy; @@ -474,12 +470,12 @@ int isci_remote_device_found(struct domain_device *domain_dev) isci_remote_device_change_state(isci_device, isci_starting); - spin_lock_irqsave(&isci_port->remote_device_lock, flags); + spin_lock_irq(&isci_host->scic_lock); list_add_tail(&isci_device->node, &isci_port->remote_dev_list); set_bit(IDEV_START_PENDING, &isci_device->flags); status = isci_remote_device_construct(isci_port, isci_device); - spin_unlock_irqrestore(&isci_port->remote_device_lock, flags); + spin_unlock_irq(&isci_host->scic_lock); dev_dbg(&isci_host->pdev->dev, "%s: isci_device = %p\n", @@ -487,12 +483,12 @@ int isci_remote_device_found(struct domain_device *domain_dev) if (status != SCI_SUCCESS) { - spin_lock_irqsave(&isci_port->remote_device_lock, flags); + spin_lock_irq(&isci_host->scic_lock); isci_remote_device_deconstruct( isci_host, isci_device ); - spin_unlock_irqrestore(&isci_port->remote_device_lock, flags); + spin_unlock_irq(&isci_host->scic_lock); return -ENODEV; } -- cgit v1.2.3 From 5409bc3a20b239d1b3919db451ee4f6513e64ed1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 8 Mar 2011 21:30:28 -0800 Subject: isci: cleanup debug leftovers in isci.h Reported-by: James Bottomley Signed-off-by: Dan Williams --- drivers/scsi/isci/isci.h | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 24c67b039d4a..b3f63f1a46cf 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -53,21 +53,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the isci_module object definition. - * - * isci.h - */ - -#if !defined(_SCI_MODULE_H_) -#define _SCI_MODULE_H_ - -/** - * This file contains the SCI low level driver interface to the SCI and Libsas - * Libraries. - * - * isci.h - */ +#ifndef __ISCI_H__ +#define __ISCI_H__ #include #include @@ -136,11 +123,4 @@ enum sci_status isci_parse_user_parameters( int scu_index, struct isci_firmware *fw); -#ifdef ISCI_SLAVE_ALLOC -extern int ISCI_SLAVE_ALLOC(struct scsi_device *scsi_dev); -#endif /* ISCI_SLAVE_ALLOC */ - -#ifdef ISCI_SLAVE_DESTROY -extern void ISCI_SLAVE_DESTROY(struct scsi_device *scsi_dev); -#endif /* ISCI_SLAVE_DESTROY */ -#endif /* !defined(_SCI_MODULE_H_) */ +#endif /* __ISCI_H__ */ -- cgit v1.2.3 From 18d3d72a42a846d46b71131982c51d63eba2b7b3 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:38 -0800 Subject: isci: isci_request_cleanup_completed_loiterer checks task before task_done In the condition where outstanding I/Os are being cleaned from the device requests in process list, the cleanup function needs to check that the request is actually a sas-task and not a task management function. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 98204b031649..779f6cfba6be 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -631,13 +631,16 @@ static void isci_request_cleanup_completed_loiterer( struct isci_remote_device *isci_device, struct isci_request *isci_request) { - struct sas_task *task = isci_request_access_task(isci_request); - unsigned long flags; + struct sas_task *task; + unsigned long flags; + + task = (isci_request->ttype == io_task) + ? isci_request_access_task(isci_request) + : NULL; dev_dbg(&isci_host->pdev->dev, "%s: isci_device=%p, request=%p, task=%p\n", - __func__, isci_device, isci_request, - isci_request->ttype_ptr.io_task_ptr); + __func__, isci_device, isci_request, task); spin_lock_irqsave(&isci_host->scic_lock, flags); list_del_init(&isci_request->dev_node); -- cgit v1.2.3 From 11b00c194cfbd0eb0d90f32c096508b2bb8be6ec Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:40 -0800 Subject: isci: Changes in isci_host_completion_routine Changes to move management of the reqs_in_process entry for the request here. Made changes to note when the task is already in the abort path and cannot be completed through callbacks. Signed-off-by: Jeff Skirvin Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 75 ++++++++++++++++++++++++++++++++++++--------- drivers/scsi/isci/host.h | 2 +- drivers/scsi/isci/request.c | 12 ++------ 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index ae5d46022073..153f419f1618 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -270,27 +270,40 @@ static int isci_host_mdl_allocate_coherent( static void isci_host_completion_routine(unsigned long data) { struct isci_host *isci_host = (struct isci_host *)data; - struct list_head completed_request_list; - struct list_head aborted_request_list; - struct list_head *current_position; - struct list_head *next_position; + struct list_head completed_request_list; + struct list_head errored_request_list; + struct list_head *current_position; + struct list_head *next_position; struct isci_request *request; struct isci_request *next_request; - struct sas_task *task; + struct sas_task *task; INIT_LIST_HEAD(&completed_request_list); - INIT_LIST_HEAD(&aborted_request_list); + INIT_LIST_HEAD(&errored_request_list); spin_lock_irq(&isci_host->scic_lock); scic_sds_controller_completion_handler(isci_host->core_controller); /* Take the lists of completed I/Os from the host. */ + list_splice_init(&isci_host->requests_to_complete, &completed_request_list); - list_splice_init(&isci_host->requests_to_abort, - &aborted_request_list); + /* While holding the scic_lock take all of the normally completed + * I/Os off of the device's pending lists. + */ + list_for_each_entry(request, &completed_request_list, completed_node) { + + /* Remove the request from the remote device's list + * of pending requests. + */ + list_del_init(&request->dev_node); + } + + /* Take the list of errored I/Os from the host. */ + list_splice_init(&isci_host->requests_to_errorback, + &errored_request_list); spin_unlock_irq(&isci_host->scic_lock); @@ -309,13 +322,22 @@ static void isci_host_completion_routine(unsigned long data) request, task); - task->task_done(task); - task->lldd_task = NULL; + /* Return the task to libsas */ + if (task != NULL) { + + task->lldd_task = NULL; + if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { + /* If the task is already in the abort path, + * the task_done callback cannot be called. + */ + task->task_done(task); + } + } /* Free the request object. */ isci_request_free(isci_host, request); } - list_for_each_entry_safe(request, next_request, &aborted_request_list, + list_for_each_entry_safe(request, next_request, &errored_request_list, completed_node) { task = isci_request_access_task(request); @@ -327,8 +349,33 @@ static void isci_host_completion_routine(unsigned long data) request, task); - /* Put the task into the abort path. */ - sas_task_abort(task); + if (task != NULL) { + + /* Put the task into the abort path if it's not there + * already. + */ + if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) + sas_task_abort(task); + + } else { + /* This is a case where the request has completed with a + * status such that it needed further target servicing, + * but the sas_task reference has already been removed + * from the request. Since it was errored, it was not + * being aborted, so there is nothing to do except free + * it. + */ + + spin_lock_irq(&isci_host->scic_lock); + /* Remove the request from the remote device's list + * of pending requests. + */ + list_del_init(&request->dev_node); + spin_unlock_irq(&isci_host->scic_lock); + + /* Free the request object. */ + isci_request_free(isci_host, request); + } } } @@ -477,7 +524,7 @@ int isci_host_init(struct isci_host *isci_host) INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); INIT_LIST_HEAD(&isci_host->requests_to_complete); - INIT_LIST_HEAD(&isci_host->requests_to_abort); + INIT_LIST_HEAD(&isci_host->requests_to_errorback); spin_lock_irq(&isci_host->scic_lock); status = scic_controller_initialize(isci_host->core_controller); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 3c69f1ffb1c3..889a7850255a 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -116,7 +116,7 @@ struct isci_host { struct tasklet_struct completion_tasklet; struct list_head mdl_struct_list; struct list_head requests_to_complete; - struct list_head requests_to_abort; + struct list_head requests_to_errorback; spinlock_t scic_lock; /* careful only access this via idev_by_id */ diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 6b0863e73f22..8039f1c72f72 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -836,7 +836,7 @@ static void isci_task_save_for_upper_layer_completion( status); /* Add to the aborted list. */ list_add(&request->completed_node, - &host->requests_to_abort); + &host->requests_to_errorback); break; default: @@ -849,7 +849,7 @@ static void isci_task_save_for_upper_layer_completion( /* Add to the aborted list. */ list_add(&request->completed_node, - &host->requests_to_abort); + &host->requests_to_errorback); break; } } @@ -1185,14 +1185,6 @@ void isci_request_io_request_complete( */ request->sci_request_handle = NULL; - /* Only remove the request from the remote device list - * of pending requests if we have not requested error - * handling on this request. - */ - if (complete_to_host != isci_perform_error_io_completion) - list_del_init(&request->dev_node); - - /* Save possible completion ptr. */ io_request_completion = request->io_request_completion; -- cgit v1.2.3 From a5fde225364df30507ba1a5aafeec85e595000d3 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:42 -0800 Subject: isci: fix completion / abort path. Corrected use of the request state_lock in the completion callback. In the case where an abort (or reset) thread is trying to terminate an I/O request, it sets the request state to "aborting" (or "terminating") if the state is still "starting". One of the bugs was to never set the state to "completed". Another was to not correctly recognize the situation where the I/O had completed but the sas_task was still pending callback to task_done - this was typically a problem in the LUN and device reset cases. It is now possible that we leave isci_task_abort_task() with request->io_request_completion pointing to localy allocated aborted_io_completion struct. It may result in a system crash. Signed-off-by: Jeff Skirvin Signed-off-by: Maciej Trela Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 52 +++++----- drivers/scsi/isci/task.c | 230 +++++++++++++++++++------------------------- 2 files changed, 129 insertions(+), 153 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 8039f1c72f72..c88e270b2b40 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -814,9 +814,8 @@ static void isci_task_save_for_upper_layer_completion( break; case isci_perform_aborted_io_completion: - /* - * No notification because this request is already - * in the abort path. + /* No notification to libsas because this request is + * already in the abort path. */ dev_warn(&host->pdev->dev, "%s: Aborted - task = %p, response=%d, status=%d\n", @@ -824,6 +823,19 @@ static void isci_task_save_for_upper_layer_completion( task, response, status); + + /* Wake up whatever process was waiting for this + * request to complete. + */ + WARN_ON(request->io_request_completion == NULL); + + if (request->io_request_completion != NULL) { + + /* Signal whoever is waiting that this + * request is complete. + */ + complete(request->io_request_completion); + } break; case isci_perform_error_io_completion: @@ -847,7 +859,7 @@ static void isci_task_save_for_upper_layer_completion( response, status); - /* Add to the aborted list. */ + /* Add to the error to libsas list. */ list_add(&request->completed_node, &host->requests_to_errorback); break; @@ -873,8 +885,6 @@ void isci_request_io_request_complete( struct ssp_response_iu *resp_iu; void *resp_buf; unsigned long task_flags; - unsigned long state_flags; - struct completion *io_request_completion; struct isci_remote_device *isci_device = request->isci_device; enum service_response response = SAS_TASK_UNDELIVERED; enum exec_status status = SAS_ABORTED_TASK; @@ -891,9 +901,8 @@ void isci_request_io_request_complete( task->data_dir, completion_status); - spin_lock_irqsave(&request->state_lock, state_flags); + spin_lock(&request->state_lock); request_status = isci_request_get_state(request); - spin_unlock_irqrestore(&request->state_lock, state_flags); /* Decode the request status. Note that if the request has been * aborted by a task management function, we don't care @@ -928,6 +937,8 @@ void isci_request_io_request_complete( complete_to_host = isci_perform_aborted_io_completion; /* This was an aborted request. */ + + spin_unlock(&request->state_lock); break; case aborting: @@ -955,6 +966,8 @@ void isci_request_io_request_complete( complete_to_host = isci_perform_aborted_io_completion; /* This was an aborted request. */ + + spin_unlock(&request->state_lock); break; case terminating: @@ -977,13 +990,20 @@ void isci_request_io_request_complete( else status = SAS_ABORTED_TASK; - complete_to_host = isci_perform_normal_io_completion; + complete_to_host = isci_perform_aborted_io_completion; /* This was a terminated request. */ + + spin_unlock(&request->state_lock); break; default: + /* The request is done from an SCU HW perspective. */ + request->status = completed; + + spin_unlock(&request->state_lock); + /* This is an active request being completed from the core. */ switch (completion_status) { @@ -1185,20 +1205,6 @@ void isci_request_io_request_complete( */ request->sci_request_handle = NULL; - /* Save possible completion ptr. */ - io_request_completion = request->io_request_completion; - - if (io_request_completion) { - - /* This is inherantly a regular I/O request, - * since we are currently in the regular - * I/O completion callback function. - * Signal whoever is waiting that this - * request is complete. - */ - complete(io_request_completion); - } - isci_host_can_dequeue(isci_host, 1); } diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 779f6cfba6be..02c40c00cb8b 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -618,9 +618,6 @@ static enum isci_request_status isci_task_validate_request_to_abort( old_state = isci_request_change_started_to_aborted( isci_request, aborted_io_completion); - /* Only abort requests in the started state. */ - if (old_state != started) - old_state = unallocated; } return old_state; @@ -644,10 +641,23 @@ static void isci_request_cleanup_completed_loiterer( spin_lock_irqsave(&isci_host->scic_lock, flags); list_del_init(&isci_request->dev_node); - if (task != NULL) - task->lldd_task = NULL; spin_unlock_irqrestore(&isci_host->scic_lock, flags); + if (task != NULL) { + + spin_lock_irqsave(&task->task_state_lock, flags); + task->lldd_task = NULL; + + isci_set_task_doneflags(task); + + /* If this task is not in the abort path, call task_done. */ + if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { + + spin_unlock_irqrestore(&task->task_state_lock, flags); + task->task_done(task); + } else + spin_unlock_irqrestore(&task->task_state_lock, flags); + } isci_request_free(isci_host, isci_request); } /** @@ -684,17 +694,20 @@ static void isci_terminate_request_core( spin_lock_irqsave(&isci_request->state_lock, flags); request_status = isci_request_get_state(isci_request); - /* TMFs are in their own thread */ - if ((isci_request->ttype == io_task) && - ((request_status == aborted) || - (request_status == aborting) || - (request_status == terminating))) + if ((isci_request->ttype == io_task) /* TMFs are in their own thread */ + && ((request_status == aborted) + || (request_status == aborting) + || (request_status == terminating) + || (request_status == completed) + ) + ) { + /* The completion routine won't free a request in * the aborted/aborting/terminating state, so we do * it here. */ needs_cleanup_handling = true; - + } spin_unlock_irqrestore(&isci_request->state_lock, flags); spin_lock_irqsave(&isci_host->scic_lock, flags); @@ -765,10 +778,10 @@ static void isci_terminate_request( new_request_state ); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + if ((old_state == started) || (old_state == completed)) { - if (old_state == started) - /* This request was not already being aborted. If it had been, + /* If the old_state is started: + * This request was not already being aborted. If it had been, * then the aborting I/O (ie. the TMF request) would not be in * the aborting state, and thus would be terminated here. Note * that since the TMF completion's call to the kernel function @@ -777,9 +790,15 @@ static void isci_terminate_request( * special wait here for already aborting requests - the * termination of the TMF request will force the request * to finish it's already started terminate. + * + * If old_state == completed: + * This request completed from the SCU hardware perspective + * and now just needs cleaning up in terms of freeing the + * request and potentially calling up to libsas. */ isci_terminate_request_core(isci_host, isci_device, isci_request, &request_completion); + } } /** @@ -863,10 +882,6 @@ void isci_terminate_pending_requests( isci_terminate_request(isci_host, isci_device, isci_request, new_request_state ); - - /* Set the 'done' state on the task. */ - if (task) - isci_task_all_done(task); } } while (!done); } @@ -1067,13 +1082,15 @@ static void isci_abort_task_process_cb( int isci_task_abort_task(struct sas_task *task) { DECLARE_COMPLETION_ONSTACK(aborted_io_completion); - struct isci_request *old_request = NULL; + struct isci_request *old_request = NULL; + enum isci_request_status old_state; struct isci_remote_device *isci_device = NULL; - struct isci_host *isci_host = NULL; - struct isci_tmf tmf; - int ret = TMF_RESP_FUNC_FAILED; - unsigned long flags; - bool any_dev_reset, device_stopping; + struct isci_host *isci_host = NULL; + struct isci_tmf tmf; + int ret = TMF_RESP_FUNC_FAILED; + unsigned long flags; + bool any_dev_reset = false; + bool device_stopping; /* Get the isci_request reference from the task. Note that * this check does not depend on the pending request list @@ -1093,21 +1110,6 @@ int isci_task_abort_task(struct sas_task *task) device_stopping = (isci_device->status == isci_stopping) || (isci_device->status == isci_stopped); -#ifdef NOMORE - /* This abort task function is the first stop of the libsas error - * handler thread. Since libsas is executing in a thread with a - * referernce to the "task" parameter, that task cannot be completed - * directly back to the upper layers. In order to make sure that - * the task is managed correctly if this abort task fails, set the - * "SAS_TASK_STATE_ABORTED" bit now such that completions up the - * stack will be intercepted and only allowed to happen in the - * libsas SCSI error handler thread. - */ - spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags |= SAS_TASK_STATE_ABORTED; - spin_unlock_irqrestore(&task->task_state_lock, flags); -#endif /* NOMORE */ - /* This version of the driver will fail abort requests for * SATA/STP. Failing the abort request this way will cause the * SCSI error handler thread to escalate to LUN reset @@ -1123,35 +1125,27 @@ int isci_task_abort_task(struct sas_task *task) dev_dbg(&isci_host->pdev->dev, "%s: old_request == %p\n", __func__, old_request); + if (!device_stopping) + any_dev_reset = isci_device_is_reset_pending(isci_host,isci_device); + spin_lock_irqsave(&task->task_state_lock, flags); /* Don't do resets to stopping devices. */ - if (device_stopping) - task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; + if (device_stopping) { - /* See if there is a pending device reset for this device. */ - any_dev_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; - - spin_unlock_irqrestore(&task->task_state_lock, flags); + task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; + any_dev_reset = false; - if ((isci_device != NULL) && !device_stopping) + } else /* See if there is a pending device reset for this device. */ any_dev_reset = any_dev_reset - || isci_device_is_reset_pending(isci_host, - isci_device - ); + || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET); /* If the extraction of the request reference from the task * failed, then the request has been completed (or if there is a * pending reset then this abort request function must be failed * in order to escalate to the target reset). */ - if ((old_request == NULL) || - ((old_request != NULL) && - (old_request->sci_request_handle == NULL) && - (old_request->complete_in_target)) || - any_dev_reset) { - - spin_lock_irqsave(&task->task_state_lock, flags); + if ((old_request == NULL) || any_dev_reset) { /* If the device reset task flag is set, fail the task * management request. Otherwise, the original request @@ -1164,6 +1158,11 @@ int isci_task_abort_task(struct sas_task *task) */ task->task_state_flags &= ~SAS_TASK_STATE_DONE; + /* Make the reset happen as soon as possible. */ + task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + + spin_unlock_irqrestore(&task->task_state_lock, flags); + /* Fail the task management request in order to * escalate to the target reset. */ @@ -1176,13 +1175,8 @@ int isci_task_abort_task(struct sas_task *task) "task %p on dev %p\n", __func__, task, isci_device); - } else { - ret = TMF_RESP_FUNC_COMPLETE; - - dev_dbg(&isci_host->pdev->dev, - "%s: abort task not needed for %p\n", - __func__, task); + } else { /* The request has already completed and there * is nothing to do here other than to set the task * done bit, and indicate that the task abort function @@ -1190,89 +1184,65 @@ int isci_task_abort_task(struct sas_task *task) */ isci_set_task_doneflags(task); - /* Set the abort bit to make sure that libsas sticks the - * task in the completed task queue. - */ -/* task->task_state_flags |= SAS_TASK_STATE_ABORTED; */ + spin_unlock_irqrestore(&task->task_state_lock, flags); - /* Check for the situation where the request was - * left around on the device list but the - * request already completed. - */ - if (old_request && !old_request->sci_request_handle) { + ret = TMF_RESP_FUNC_COMPLETE; - isci_request_cleanup_completed_loiterer( - isci_host, isci_device, old_request - ); - } + dev_dbg(&isci_host->pdev->dev, + "%s: abort task not needed for %p\n", + __func__, task); } - spin_unlock_irqrestore(&task->task_state_lock, flags); return ret; } + else + spin_unlock_irqrestore(&task->task_state_lock, flags); spin_lock_irqsave(&isci_host->scic_lock, flags); - /* Sanity check the request status, and set the I/O kernel completion + /* Check the request status and change to "aborting" if currently + * "starting"; if true then set the I/O kernel completion * struct that will be triggered when the request completes. */ - if (isci_task_validate_request_to_abort( - old_request, - isci_host, - isci_device, - &aborted_io_completion) - == unallocated) { - dev_dbg(&isci_host->pdev->dev, - "%s: old_request not valid for device = %p\n", - __func__, - isci_device); - old_request = NULL; - } - - if (!old_request) { - - /* There is no isci_request attached to the sas_task. - * It must have been completed and detached. - */ - dev_dbg(&isci_host->pdev->dev, - "%s: old_request == NULL\n", - __func__); + old_state = isci_task_validate_request_to_abort( + old_request, isci_host, isci_device, + &aborted_io_completion); + if ((old_state != started) && (old_state != completed)) { spin_unlock_irqrestore(&isci_host->scic_lock, flags); - /* Set the state on the task. */ - isci_task_all_done(task); + /* The request was already being handled by someone else (because + * they got to set the state away from started). + */ + dev_dbg(&isci_host->pdev->dev, + "%s: device = %p; old_request %p already being aborted\n", + __func__, + isci_device, old_request); return TMF_RESP_FUNC_COMPLETE; } - if (task->task_proto == SAS_PROTOCOL_SMP || device_stopping) { - - if (device_stopping) - dev_dbg(&isci_host->pdev->dev, - "%s: device is stopping, thus no TMF\n", - __func__); - else - dev_dbg(&isci_host->pdev->dev, - "%s: request is SMP, thus no TMF\n", - __func__); - - old_request->complete_in_target = true; + if ((task->task_proto == SAS_PROTOCOL_SMP) + || device_stopping + || old_request->complete_in_target + ) { spin_unlock_irqrestore(&isci_host->scic_lock, flags); + dev_dbg(&isci_host->pdev->dev, + "%s: SMP request (%d)" + " or device is stopping (%d)" + " or complete_in_target (%d), thus no TMF\n", + __func__, (task->task_proto == SAS_PROTOCOL_SMP), + device_stopping, old_request->complete_in_target); + /* Set the state on the task. */ isci_task_all_done(task); ret = TMF_RESP_FUNC_COMPLETE; /* Stopping and SMP devices are not sent a TMF, and are not - * reset, but the outstanding I/O request is terminated here. - * - * Clean up the request on our side, and wait for the aborted - * I/O to complete. + * reset, but the outstanding I/O request is terminated below. */ - isci_terminate_request_core(isci_host, isci_device, old_request, - &aborted_io_completion); } else { /* Fill in the tmf stucture */ isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_task_abort, @@ -1288,23 +1258,23 @@ int isci_task_abort_task(struct sas_task *task) ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_ABORT_TASK_TIMEOUT_MS); - if (ret == TMF_RESP_FUNC_COMPLETE) { - old_request->complete_in_target = true; - - /* Clean up the request on our side, and wait for the aborted I/O to - * complete. - */ - isci_terminate_request_core(isci_host, isci_device, old_request, - &aborted_io_completion); - - /* Set the state on the task. */ - isci_task_all_done(task); - } else + if (ret != TMF_RESP_FUNC_COMPLETE) dev_err(&isci_host->pdev->dev, "%s: isci_task_send_tmf failed\n", __func__); } + if (ret == TMF_RESP_FUNC_COMPLETE) { + old_request->complete_in_target = true; + + /* Clean up the request on our side, and wait for the aborted I/O to + * complete. + */ + isci_terminate_request_core(isci_host, isci_device, old_request, + &aborted_io_completion); + } + /* Make sure we do not leave a reference to aborted_io_completion */ + old_request->io_request_completion = NULL; return ret; } -- cgit v1.2.3 From ec6c9638b0d0537430f78a3e20503b5e68a537b6 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:44 -0800 Subject: isci: Any reset indicated on an I/O completion escalates it to the error path. If there is a pending device reset, the I/O is used to accomplish the reset by setting the RESET bit in the task status, and then putting the task into the error handler path using sas abort task. Signed-off-by: Jeff Skirvin Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 11 ---------- drivers/scsi/isci/request.c | 9 +++++--- drivers/scsi/isci/task.h | 53 ++++++++++++++++++++++++++++++++++----------- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 153f419f1618..dc231c22ea93 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -290,17 +290,6 @@ static void isci_host_completion_routine(unsigned long data) list_splice_init(&isci_host->requests_to_complete, &completed_request_list); - /* While holding the scic_lock take all of the normally completed - * I/Os off of the device's pending lists. - */ - list_for_each_entry(request, &completed_request_list, completed_node) { - - /* Remove the request from the remote device's list - * of pending requests. - */ - list_del_init(&request->dev_node); - } - /* Take the list of errored I/Os from the host. */ list_splice_init(&isci_host->requests_to_errorback, &errored_request_list); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c88e270b2b40..6cd80bbdae15 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -790,9 +790,9 @@ static void isci_task_save_for_upper_layer_completion( { struct sas_task *task = isci_request_access_task(request); - isci_task_set_completion_status(task, response, status, - task_notification_selection); - + task_notification_selection + = isci_task_set_completion_status(task, response, status, + task_notification_selection); /* Tasks aborted specifically by a call to the lldd_abort_task * function should not be completed to the host in the regular path. @@ -811,6 +811,9 @@ static void isci_task_save_for_upper_layer_completion( /* Add to the completed list. */ list_add(&request->completed_node, &host->requests_to_complete); + + /* Take the request off the device's pending request list. */ + list_del_init(&request->dev_node); break; case isci_perform_aborted_io_completion: diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index ced6a8be1b31..68d8e5e65a73 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -280,9 +280,10 @@ static inline void isci_task_all_done( * @response: This parameter is the response code for the completed task. * @status: This parameter is the status code for the completed task. * - * none. - */ -static inline void isci_task_set_completion_status( +* @return The new notification mode for the request. +*/ +static inline enum isci_completion_selection +isci_task_set_completion_status( struct sas_task *task, enum service_response response, enum exec_status status, @@ -295,15 +296,41 @@ static inline void isci_task_set_completion_status( task->task_status.resp = response; task->task_status.stat = status; - /* Don't set DONE (or clear AT_INITIATOR) for any task going into the - * error path, because the EH interprets that as a handled error condition. - * Also don't take action if there is a reset pending. - */ - if ((task_notification_selection != isci_perform_error_io_completion) - && !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET)) - isci_set_task_doneflags(task); + /* If a device reset is being indicated, make sure the I/O + * is in the error path. + */ + if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) + task_notification_selection = isci_perform_error_io_completion; + + switch (task_notification_selection) { + + case isci_perform_aborted_io_completion: + /* This path can occur with task-managed requests as well as + * requests terminated because of LUN or device resets. + */ + /* Fall through to the normal case... */ + + case isci_perform_normal_io_completion: + /* Normal notification (task_done) */ + isci_set_task_doneflags(task); + break; + + default: + WARN_ON(FALSE); + /* Fall through to the error case... */ + + case isci_perform_error_io_completion: + /* Use sas_task_abort */ + /* Leave SAS_TASK_STATE_DONE clear + * Leave SAS_TASK_AT_INITIATOR set. + */ + break; + } spin_unlock_irqrestore(&task->task_state_lock, flags); + + return task_notification_selection; + } /** * isci_task_complete_for_upper_layer() - This function completes the request @@ -322,9 +349,9 @@ static inline void isci_task_complete_for_upper_layer( enum exec_status status, enum isci_completion_selection task_notification_selection) { - isci_task_set_completion_status(task, response, status, - task_notification_selection); - + task_notification_selection + = isci_task_set_completion_status(task, response, status, + task_notification_selection); /* Tasks aborted specifically by a call to the lldd_abort_task * function should not be completed to the host in the regular path. -- cgit v1.2.3 From 1fad9e934a43407c1ba397b1b6b8882aa8a2cafd Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:46 -0800 Subject: isci: save the i/o tag outside the scic request structure. The pointer to the core representation of a request is marked NULL at completion, but we need to save the i/o tag for task management. Signed-off-by: Jeff Skirvin Signed-off-by: Jacek Danecki [revise changelog] Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 6 ++++++ drivers/scsi/isci/task.c | 10 ++++------ drivers/scsi/isci/task.h | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 6cd80bbdae15..f19a952754b9 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -463,6 +463,12 @@ int isci_request_execute( */ status = SCI_SUCCESS; } + else + /* Save the tag for possible task mgmt later. */ + request->io_tag = scic_io_request_get_io_tag( + request->sci_request_handle); + + } else dev_warn(&isci_host->pdev->dev, "%s: failed request start\n", diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 02c40c00cb8b..e9bfc22d91d0 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -544,7 +544,7 @@ void isci_task_build_tmf( void (*tmf_sent_cb)(enum isci_tmf_cb_state, struct isci_tmf *, void *), - void *cb_data) + struct isci_request *old_request) { dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, "%s: isci_device = %p\n", __func__, isci_device); @@ -555,7 +555,9 @@ void isci_task_build_tmf( tmf->tmf_code = code; tmf->timeout_timer = NULL; tmf->cb_state_func = tmf_sent_cb; - tmf->cb_data = cb_data; + tmf->cb_data = old_request; + tmf->io_tag = old_request->io_tag; + } static struct isci_request *isci_task_get_request_from_task( @@ -1248,10 +1250,6 @@ int isci_task_abort_task(struct sas_task *task) isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_task_abort, isci_abort_task_process_cb, old_request); - tmf.io_tag = scic_io_request_get_io_tag( - old_request->sci_request_handle - ); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */ diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index 68d8e5e65a73..5a5a4ec2dc90 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -224,7 +224,7 @@ void isci_task_build_tmf( void (*tmf_sent_cb)( enum isci_tmf_cb_state, struct isci_tmf *, void *), - void *cb_data); + struct isci_request *old_request); int isci_task_execute_tmf( struct isci_host *isci_host, -- cgit v1.2.3 From f0846c68912545d70da16b2fbedded37ea4394d8 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Tue, 8 Mar 2011 19:22:07 -0700 Subject: isci: Cleaning up task execute path. Made sure the device ready check accounts for all states. Moved the aborted task check into the loop of pulling task requests off of the submitted list. Signed-off-by: Jeff Skirvin Signed-off-by: Jacek Danecki [remove host and device starting state checks] Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 141 ++++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index e9bfc22d91d0..3dc9ef3f305b 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -83,21 +83,10 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) unsigned long flags; int ret; enum sci_status status; - + enum isci_status device_status; dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num); - if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { - - isci_task_complete_for_upper_layer( - task, - SAS_TASK_UNDELIVERED, - SAM_STAT_TASK_ABORTED, - isci_perform_normal_io_completion - ); - - return 0; /* The I/O was accepted (and failed). */ - } if ((task->dev == NULL) || (task->dev->port == NULL)) { /* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer @@ -143,93 +132,105 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) /* We don't have a valid host reference, so we * can't control the host queueing condition. */ - continue; + goto next_task; } device = isci_dev_from_domain_dev(task->dev); isci_host = isci_host_from_sas_ha(task->dev->port->ha); - if (device && device->status == isci_ready) { + if (device) + device_status = device->status; + else + device_status = isci_freed; + + /* From this point onward, any process that needs to guarantee + * that there is no kernel I/O being started will have to wait + * for the quiesce spinlock. + */ + + if (device_status != isci_ready_for_io) { /* Forces a retry from scsi mid layer. */ dev_warn(task->dev->port->ha->dev, "%s: task %p: isci_host->status = %d, " - "device = %p\n", + "device = %p; device_status = 0x%x\n\n", __func__, task, isci_host_get_state(isci_host), - device); - - if (device) - dev_dbg(task->dev->port->ha->dev, - "%s: device->status = 0x%x\n", - __func__, device->status); + device, device_status); - /* Indicate QUEUE_FULL so that the scsi midlayer - * retries. - */ - isci_task_complete_for_upper_layer( - task, - SAS_TASK_COMPLETE, - SAS_QUEUE_FULL, - isci_perform_normal_io_completion - ); + if (device_status == isci_ready) { + /* Indicate QUEUE_FULL so that the scsi midlayer + * retries. + */ + isci_task_complete_for_upper_layer( + task, + SAS_TASK_COMPLETE, + SAS_QUEUE_FULL, + isci_perform_normal_io_completion + ); + } else { + /* Else, the device is going down. */ + isci_task_complete_for_upper_layer( + task, + SAS_TASK_UNDELIVERED, + SAS_DEVICE_UNKNOWN, + isci_perform_normal_io_completion + ); + } isci_host_can_dequeue(isci_host, 1); - } - /* the device is going down... */ - else if (!device || device->status != isci_ready_for_io) { + } else { + /* There is a device and it's ready for I/O. */ + spin_lock_irqsave(&task->task_state_lock, flags); - dev_dbg(task->dev->port->ha->dev, - "%s: task %p: isci_host->status = %d, " - "device = %p\n", - __func__, - task, - isci_host_get_state(isci_host), - device); + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { - if (device) - dev_dbg(task->dev->port->ha->dev, - "%s: device->status = 0x%x\n", - __func__, device->status); + spin_unlock_irqrestore(&task->task_state_lock, + flags); - /* Indicate SAS_TASK_UNDELIVERED, so that the scsi - * midlayer removes the target. - */ - isci_task_complete_for_upper_layer( - task, - SAS_TASK_UNDELIVERED, - SAS_DEVICE_UNKNOWN, - isci_perform_normal_io_completion - ); - isci_host_can_dequeue(isci_host, 1); + isci_task_complete_for_upper_layer( + task, + SAS_TASK_UNDELIVERED, + SAM_STAT_TASK_ABORTED, + isci_perform_normal_io_completion + ); - } else { - /* build and send the request. */ - status = isci_request_execute(isci_host, task, &request, - gfp_flags); + /* The I/O was aborted. */ - if (status == SCI_SUCCESS) { - spin_lock_irqsave(&task->task_state_lock, flags); + } else { task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); - } else { - /* Indicate QUEUE_FULL so that the scsi - * midlayer retries. if the request - * failed for remote device reasons, - * it gets returned as - * SAS_TASK_UNDELIVERED next time - * through. - */ - isci_task_complete_for_upper_layer( + + /* build and send the request. */ + status = isci_request_execute(isci_host, task, &request, + gfp_flags); + + if (status != SCI_SUCCESS) { + + spin_lock_irqsave(&task->task_state_lock, flags); + /* Did not really start this command. */ + task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + /* Indicate QUEUE_FULL so that the scsi + * midlayer retries. if the request + * failed for remote device reasons, + * it gets returned as + * SAS_TASK_UNDELIVERED next time + * through. + */ + isci_task_complete_for_upper_layer( task, SAS_TASK_COMPLETE, SAS_QUEUE_FULL, isci_perform_normal_io_completion ); - isci_host_can_dequeue(isci_host, 1); + isci_host_can_dequeue(isci_host, 1); + } } } +next_task: task = list_entry(task->list.next, struct sas_task, list); } while (--num > 0); return 0; -- cgit v1.2.3 From cbb65c665b341e560b7a3b37cc616376031b3ee5 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:50 -0800 Subject: isci: Code review change for completion pointer cleanup. Since the request structure contains a pointer to the completion to be used if the request is being aborted or terminated, there is no reason to pass the completion as a pointer to isci_terminate_request_core(). Signed-off-by: Jeff Skirvin Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 3dc9ef3f305b..5e80e8449223 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -677,10 +677,9 @@ static void isci_request_cleanup_completed_loiterer( static void isci_terminate_request_core( struct isci_host *isci_host, struct isci_remote_device *isci_device, - struct isci_request *isci_request, - struct completion *request_completion) + struct isci_request *isci_request) { - enum sci_status status = SCI_SUCCESS; + enum sci_status status = SCI_SUCCESS; bool was_terminated = false; bool needs_cleanup_handling = false; enum isci_request_status request_status; @@ -720,6 +719,7 @@ static void isci_terminate_request_core( */ if (isci_request->sci_request_handle != NULL) { was_terminated = true; + needs_cleanup_handling = true; status = scic_controller_terminate_request( isci_host->core_controller, to_sci_dev(isci_device), @@ -744,15 +744,15 @@ static void isci_terminate_request_core( dev_dbg(&isci_host->pdev->dev, "%s: before completion wait (%p)\n", __func__, - request_completion); + isci_request->io_request_completion); /* Wait here for the request to complete. */ - wait_for_completion(request_completion); + wait_for_completion(isci_request->io_request_completion); dev_dbg(&isci_host->pdev->dev, "%s: after completion wait (%p)\n", __func__, - request_completion); + isci_request->io_request_completion); } if (needs_cleanup_handling) @@ -760,7 +760,10 @@ static void isci_terminate_request_core( isci_host, isci_device, isci_request ); } + /* Clear the completion pointer from the request. */ + isci_request->io_request_completion = NULL; } + static void isci_terminate_request( struct isci_host *isci_host, struct isci_remote_device *isci_device, @@ -800,7 +803,7 @@ static void isci_terminate_request( * request and potentially calling up to libsas. */ isci_terminate_request_core(isci_host, isci_device, - isci_request, &request_completion); + isci_request); } } @@ -1268,8 +1271,7 @@ int isci_task_abort_task(struct sas_task *task) /* Clean up the request on our side, and wait for the aborted I/O to * complete. */ - isci_terminate_request_core(isci_host, isci_device, old_request, - &aborted_io_completion); + isci_terminate_request_core(isci_host, isci_device, old_request); } /* Make sure we do not leave a reference to aborted_io_completion */ -- cgit v1.2.3 From 4dc043c41037fc6e369270daaa626465a8766565 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:52 -0800 Subject: isci: Termination handling cleanup, added termination timeouts. Added a request "dead" state for use when a termination wait times-out. isci_terminate_pending_requests now detaches the device's pending list and terminates each entry on the detached list. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.h | 3 +- drivers/scsi/isci/task.c | 233 +++++++++++++++++++++++++++----------------- 2 files changed, 143 insertions(+), 93 deletions(-) diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 166295ee8cfd..b45c0f1f057f 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -71,7 +71,8 @@ enum isci_request_status { completed = 0x03, aborting = 0x04, aborted = 0x05, - terminating = 0x06 + terminating = 0x06, + dead = 0x07 }; enum task_type { diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 5e80e8449223..c781a4ab4a50 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -663,6 +663,59 @@ static void isci_request_cleanup_completed_loiterer( } isci_request_free(isci_host, isci_request); } + +/** +* @isci_termination_timed_out(): this function will deal with a request for +* which the wait for termination has timed-out. +* +* @isci_host This SCU. +* @isci_request The I/O request being terminated. +*/ +static void +isci_termination_timed_out( + struct isci_host * host, + struct isci_request * request + ) +{ + unsigned long state_flags; + + dev_warn(&host->pdev->dev, + "%s: host = %p; request = %p\n", + __func__, host, request); + + /* At this point, the request to terminate + * has timed out. The best we can do is to + * have the request die a silent death + * if it ever completes. + */ + spin_lock_irqsave(&request->state_lock, state_flags); + + if (request->status == started) { + + /* Set the request state to "dead", + * and clear the task pointer so that an actual + * completion event callback doesn't do + * anything. + */ + request->status = dead; + + /* Clear the timeout completion event pointer.*/ + request->io_request_completion = NULL; + + if (request->ttype == io_task) { + + /* Break links with the sas_task. */ + if (request->ttype_ptr.io_task_ptr != NULL) { + + request->ttype_ptr.io_task_ptr->lldd_task = NULL; + request->ttype_ptr.io_task_ptr = NULL; + } + } + } + spin_unlock_irqrestore(&request->state_lock, state_flags); +} + + /** * isci_terminate_request_core() - This function will terminate the given * request, and wait for it to complete. This function must only be called @@ -684,35 +737,20 @@ static void isci_terminate_request_core( bool needs_cleanup_handling = false; enum isci_request_status request_status; unsigned long flags; + unsigned long timeout_remaining; + dev_dbg(&isci_host->pdev->dev, "%s: device = %p; request = %p\n", __func__, isci_device, isci_request); - /* Peek at the current status of the request. This will tell - * us if there was special handling on the request such that it - * needs to be detached and freed here. - */ - spin_lock_irqsave(&isci_request->state_lock, flags); - request_status = isci_request_get_state(isci_request); - - if ((isci_request->ttype == io_task) /* TMFs are in their own thread */ - && ((request_status == aborted) - || (request_status == aborting) - || (request_status == terminating) - || (request_status == completed) - ) - ) { + spin_lock_irqsave(&isci_host->scic_lock, flags); - /* The completion routine won't free a request in - * the aborted/aborting/terminating state, so we do - * it here. - */ - needs_cleanup_handling = true; - } - spin_unlock_irqrestore(&isci_request->state_lock, flags); + /* Note that we are not going to control + * the target to abort the request. + */ + isci_request->complete_in_target = true; - spin_lock_irqsave(&isci_host->scic_lock, flags); /* Make sure the request wasn't just sitting around signalling * device condition (if the request handle is NULL, then the * request completed but needed additional handling here). @@ -733,13 +771,16 @@ static void isci_terminate_request_core( * fail is when the io request is completed and * being aborted. */ - if (status != SCI_SUCCESS) + if (status != SCI_SUCCESS) { dev_err(&isci_host->pdev->dev, "%s: scic_controller_terminate_request" " returned = 0x%x\n", __func__, status); - else { + /* Clear the completion pointer from the request. */ + isci_request->io_request_completion = NULL; + + } else { if (was_terminated) { dev_dbg(&isci_host->pdev->dev, "%s: before completion wait (%p)\n", @@ -747,21 +788,62 @@ static void isci_terminate_request_core( isci_request->io_request_completion); /* Wait here for the request to complete. */ - wait_for_completion(isci_request->io_request_completion); + #define TERMINATION_TIMEOUT_MSEC 50 + timeout_remaining + = wait_for_completion_timeout( + isci_request->io_request_completion, + msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC)); + + if (!timeout_remaining) { + + isci_termination_timed_out(isci_host, + isci_request); + + dev_err(&isci_host->pdev->dev, + "%s: *** Timeout waiting for " + "termination(%p/%p)\n", + __func__, + isci_request->io_request_completion, + isci_request); + + } else + dev_dbg(&isci_host->pdev->dev, + "%s: after completion wait (%p)\n", + __func__, + isci_request->io_request_completion); + } + /* Clear the completion pointer from the request. */ + isci_request->io_request_completion = NULL; - dev_dbg(&isci_host->pdev->dev, - "%s: after completion wait (%p)\n", - __func__, - isci_request->io_request_completion); + /* Peek at the status of the request. This will tell + * us if there was special handling on the request such that it + * needs to be detached and freed here. + */ + spin_lock_irqsave(&isci_request->state_lock, flags); + request_status = isci_request_get_state(isci_request); + + if ((isci_request->ttype == io_task) /* TMFs are in their own thread */ + && ((request_status == aborted) + || (request_status == aborting) + || (request_status == terminating) + || (request_status == completed) + || (request_status == dead) + ) + ) { + + /* The completion routine won't free a request in + * the aborted/aborting/etc. states, so we do + * it here. + */ + needs_cleanup_handling = true; } + spin_unlock_irqrestore(&isci_request->state_lock, flags); if (needs_cleanup_handling) isci_request_cleanup_completed_loiterer( isci_host, isci_device, isci_request ); } - /* Clear the completion pointer from the request. */ - isci_request->io_request_completion = NULL; } static void isci_terminate_request( @@ -771,11 +853,7 @@ static void isci_terminate_request( enum isci_request_status new_request_state) { enum isci_request_status old_state; - DECLARE_COMPLETION_ONSTACK(request_completion); - unsigned long flags; - - spin_lock_irqsave(&isci_host->scic_lock, flags); /* Change state to "new_request_state" if it is currently "started" */ old_state = isci_request_change_started_to_newstate( @@ -823,73 +901,44 @@ void isci_terminate_pending_requests( struct isci_remote_device *isci_device, enum isci_request_status new_request_state) { - struct isci_request *isci_request; - struct sas_task *task; - bool done = false; - unsigned long flags; + struct isci_request *request; + struct isci_request *next_request; + unsigned long flags; + struct list_head aborted_request_list; + + INIT_LIST_HEAD(&aborted_request_list); dev_dbg(&isci_host->pdev->dev, "%s: isci_device = %p (new request state = %d)\n", __func__, isci_device, new_request_state); - #define ISCI_TERMINATE_SHOW_PENDING_REQUESTS - #ifdef ISCI_TERMINATE_SHOW_PENDING_REQUESTS - { - struct isci_request *request; - - /* Only abort the task if it's in the - * device's request_in_process list - */ - list_for_each_entry(request, - &isci_device->reqs_in_process, - dev_node) - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p; request is on " - "reqs_in_process list: %p\n", - __func__, isci_device, request); - } - #endif /* ISCI_TERMINATE_SHOW_PENDING_REQUESTS */ - - /* Clean up all pending requests. */ - do { - spin_lock_irqsave(&isci_host->scic_lock, flags); - - if (list_empty(&isci_device->reqs_in_process)) { - - done = true; - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_lock_irqsave(&isci_host->scic_lock, flags); - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p; done.\n", - __func__, isci_device); - } else { - /* The list was not empty - grab the first request. */ - isci_request = list_first_entry( - &isci_device->reqs_in_process, - struct isci_request, dev_node - ); - /* Note that we are not expecting to have to control - * the target to abort the request. - */ - isci_request->complete_in_target = true; + /* Move all of the pending requests off of the device list. */ + list_splice_init(&isci_device->reqs_in_process, + &aborted_request_list); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); - /* Get the libsas task reference. */ - task = isci_request_access_task(isci_request); + /* Iterate through the now-local list. */ + list_for_each_entry_safe(request, next_request, + &aborted_request_list, dev_node) { - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device=%p request=%p; task=%p\n", - __func__, isci_device, isci_request, task); + dev_warn(&isci_host->pdev->dev, + "%s: isci_device=%p request=%p; task=%p\n", + __func__, + isci_device, request, + ((request->ttype == io_task) + ? isci_request_access_task(request) + : NULL)); - /* Mark all still pending I/O with the selected next - * state. - */ - isci_terminate_request(isci_host, isci_device, - isci_request, new_request_state - ); - } - } while (!done); + /* Mark all still pending I/O with the selected next + * state, terminate and free it. + */ + isci_terminate_request(isci_host, isci_device, + request, new_request_state + ); + } } /** -- cgit v1.2.3 From c3f42feb0c3d20dc7007336e7de949408b93afef Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:56 -0800 Subject: isci: Fix TMF build for SAS/SATA LUN reset cases. In the case where a SAS or SATA LUN reset TMF is built a NULL pointer dereference occurred because of the (unused) callback data pointer. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams Signed-off-by: Jacek Danecki --- drivers/scsi/isci/task.c | 24 +++++++++++++++++++----- drivers/scsi/isci/task.h | 9 +++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c781a4ab4a50..c2d74c3929fb 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -545,7 +545,7 @@ void isci_task_build_tmf( void (*tmf_sent_cb)(enum isci_tmf_cb_state, struct isci_tmf *, void *), - struct isci_request *old_request) + void *cb_data) { dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, "%s: isci_device = %p\n", __func__, isci_device); @@ -556,9 +556,21 @@ void isci_task_build_tmf( tmf->tmf_code = code; tmf->timeout_timer = NULL; tmf->cb_state_func = tmf_sent_cb; - tmf->cb_data = old_request; - tmf->io_tag = old_request->io_tag; + tmf->cb_data = cb_data; +} +void isci_task_build_abort_task_tmf( + struct isci_tmf *tmf, + struct isci_remote_device *isci_device, + enum isci_tmf_function_codes code, + void (*tmf_sent_cb)(enum isci_tmf_cb_state, + struct isci_tmf *, + void *), + struct isci_request *old_request) +{ + isci_task_build_tmf(tmf, isci_device, code, tmf_sent_cb, + (void *)old_request); + tmf->io_tag = old_request->io_tag; } static struct isci_request *isci_task_get_request_from_task( @@ -1300,8 +1312,10 @@ int isci_task_abort_task(struct sas_task *task) */ } else { /* Fill in the tmf stucture */ - isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_task_abort, - isci_abort_task_process_cb, old_request); + isci_task_build_abort_task_tmf(&tmf, isci_device, + isci_tmf_ssp_task_abort, + isci_abort_task_process_cb, + old_request); spin_unlock_irqrestore(&isci_host->scic_lock, flags); diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index 5a5a4ec2dc90..4c2a27eede49 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -218,6 +218,15 @@ int isci_queuecommand( int isci_bus_reset_handler(struct scsi_cmnd *cmd); void isci_task_build_tmf( + struct isci_tmf *tmf, + struct isci_remote_device *isci_device, + enum isci_tmf_function_codes code, + void (*tmf_sent_cb)(enum isci_tmf_cb_state, + struct isci_tmf *, + void *), + void *cb_data); + +void isci_task_build_abort_task_tmf( struct isci_tmf *tmf, struct isci_remote_device *isci_device, enum isci_tmf_function_codes code, -- cgit v1.2.3 From 70957a94d70cb82459bd3aea171c54d0a5cd6dbb Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 4 Mar 2011 14:06:58 -0800 Subject: isci: Fixed BUG_ON in isci_abort_task_process_cb callback. The request may be in the "aborted" or the "completed" state when performing a task management operation on it. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c2d74c3929fb..a1234e42937e 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1116,7 +1116,8 @@ static void isci_abort_task_process_cb( * request state was already set to "aborted" by the abort * task function. */ - BUG_ON(old_request->status != aborted); + BUG_ON((old_request->status != aborted) + && (old_request->status != completed)); break; case isci_tmf_timed_out: -- cgit v1.2.3 From 50e7f9b5a9ae4a763b2c27500807cf237faca9b0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 9 Mar 2011 21:27:46 -0800 Subject: isci: Errors in the submit path for SATA devices manage the ap lock. Since libsas takes the domain device sata_dev.ap->lock before submitting a task, error completions in the submit path for SATA devices must unlock/relock when completing the sas_task back to libsas. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/isci/task.h | 59 -------------------------------- 2 files changed, 87 insertions(+), 59 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index a1234e42937e..d00b4c97b85b 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -54,6 +54,8 @@ */ #include +#include +#include #include "scic_task_request.h" #include "scic_remote_device.h" #include "scic_io_request.h" @@ -64,6 +66,91 @@ #include "sata.h" #include "task.h" +/** +* isci_task_complete_for_upper_layer() - This function completes the request +* to the upper layer driver in the case where an I/O needs to be completed +* back in the submit path. +* @host: This parameter is a pointer to the host on which the the request +* should be queued (either as an error or success). +* @task: This parameter is the completed request. +* @response: This parameter is the response code for the completed task. +* @status: This parameter is the status code for the completed task. +* +* none. +*/ +static void isci_task_complete_for_upper_layer(struct sas_task *task, + enum service_response response, + enum exec_status status, + enum isci_completion_selection task_notification_selection) +{ + unsigned long flags = 0; + struct Scsi_Host *host = NULL; + + task_notification_selection + = isci_task_set_completion_status(task, response, status, + task_notification_selection); + + /* Tasks aborted specifically by a call to the lldd_abort_task + * function should not be completed to the host in the regular path. + */ + switch (task_notification_selection) { + case isci_perform_normal_io_completion: + /* Normal notification (task_done) */ + dev_dbg(task->dev->port->ha->dev, + "%s: Normal - task = %p, response=%d, status=%d\n", + __func__, task, response, status); + + if (dev_is_sata(task->dev)) { + /* Since we are still in the submit path, and since + * libsas takes the host lock on behalf of SATA + * devices before I/O starts, we need to unlock + * before we can call back and report the I/O + * submission error. + */ + if (task->dev + && task->dev->port + && task->dev->port->ha) { + + host = task->dev->port->ha->core.shost; + raw_local_irq_save(flags); + spin_unlock(host->host_lock); + } + task->task_done(task); + if (host) { + spin_lock(host->host_lock); + raw_local_irq_restore(flags); + } + } else + task->task_done(task); + + task->lldd_task = NULL; + break; + + case isci_perform_aborted_io_completion: + /* No notification because this request is already in the + * abort path. + */ + dev_warn(task->dev->port->ha->dev, + "%s: Aborted - task = %p, response=%d, status=%d\n", + __func__, task, response, status); + break; + + case isci_perform_error_io_completion: + /* Use sas_task_abort */ + dev_warn(task->dev->port->ha->dev, + "%s: Error - task = %p, response=%d, status=%d\n", + __func__, task, response, status); + sas_task_abort(task); + break; + + default: + dev_warn(task->dev->port->ha->dev, + "%s: isci task notification default case!", + __func__); + sas_task_abort(task); + break; + } +} /** * isci_task_execute_task() - This function is one of the SAS Domain Template diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index 4c2a27eede49..e1c9c8f04050 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -341,64 +341,5 @@ isci_task_set_completion_status( return task_notification_selection; } -/** - * isci_task_complete_for_upper_layer() - This function completes the request - * to the upper layer driver. - * @host: This parameter is a pointer to the host on which the the request - * should be queued (either as an error or success). - * @request: This parameter is the completed request. - * @response: This parameter is the response code for the completed task. - * @status: This parameter is the status code for the completed task. - * - * none. - */ -static inline void isci_task_complete_for_upper_layer( - struct sas_task *task, - enum service_response response, - enum exec_status status, - enum isci_completion_selection task_notification_selection) -{ - task_notification_selection - = isci_task_set_completion_status(task, response, status, - task_notification_selection); - - /* Tasks aborted specifically by a call to the lldd_abort_task - * function should not be completed to the host in the regular path. - */ - switch (task_notification_selection) { - case isci_perform_normal_io_completion: - /* Normal notification (task_done) */ - dev_dbg(task->dev->port->ha->dev, - "%s: Normal - task = %p, response=%d, status=%d\n", - __func__, task, response, status); - task->task_done(task); - task->lldd_task = NULL; - break; - - case isci_perform_aborted_io_completion: - /* No notification because this request is already in the - * abort path. - */ - dev_warn(task->dev->port->ha->dev, - "%s: Aborted - task = %p, response=%d, status=%d\n", - __func__, task, response, status); - break; - - case isci_perform_error_io_completion: - /* Use sas_task_abort */ - dev_warn(task->dev->port->ha->dev, - "%s: Error - task = %p, response=%d, status=%d\n", - __func__, task, response, status); - sas_task_abort(task); - break; - - default: - dev_warn(task->dev->port->ha->dev, - "%s: isci task notification default case!", - __func__); - sas_task_abort(task); - break; - } -} #endif /* !defined(_SCI_TASK_H_) */ -- cgit v1.2.3 From aa14510295d3d87431c915c0b2bc5dd3af7f2c35 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Mon, 7 Mar 2011 16:40:47 -0700 Subject: isci: Always set response/status for requests going into the error path. In the case of I/O requests being failed because of a required device reset condition, set the response and status to indicate an I/O failure. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 28 ++++++++++++++++------------ drivers/scsi/isci/task.h | 13 +++++++++---- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index f19a952754b9..015643104311 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -809,11 +809,11 @@ static void isci_task_save_for_upper_layer_completion( /* Normal notification (task_done) */ dev_dbg(&host->pdev->dev, - "%s: Normal - task = %p, response=%d, status=%d\n", + "%s: Normal - task = %p, response=%d (%d), status=%d (%d)\n", __func__, task, - response, - status); + task->task_status.resp, response, + task->task_status.stat, status); /* Add to the completed list. */ list_add(&request->completed_node, &host->requests_to_complete); @@ -827,11 +827,11 @@ static void isci_task_save_for_upper_layer_completion( * already in the abort path. */ dev_warn(&host->pdev->dev, - "%s: Aborted - task = %p, response=%d, status=%d\n", + "%s: Aborted - task = %p, response=%d (%d), status=%d (%d)\n", __func__, task, - response, - status); + task->task_status.resp, response, + task->task_status.stat, status); /* Wake up whatever process was waiting for this * request to complete. @@ -850,11 +850,11 @@ static void isci_task_save_for_upper_layer_completion( case isci_perform_error_io_completion: /* Use sas_task_abort */ dev_warn(&host->pdev->dev, - "%s: Error - task = %p, response=%d, status=%d\n", + "%s: Error - task = %p, response=%d (%d), status=%d (%d)\n", __func__, task, - response, - status); + task->task_status.resp, response, + task->task_status.stat, status); /* Add to the aborted list. */ list_add(&request->completed_node, &host->requests_to_errorback); @@ -862,11 +862,11 @@ static void isci_task_save_for_upper_layer_completion( default: dev_warn(&host->pdev->dev, - "%s: Unknown - task = %p, response=%d, status=%d\n", + "%s: Unknown - task = %p, response=%d (%d), status=%d (%d)\n", __func__, task, - response, - status); + task->task_status.resp, response, + task->task_status.stat, status); /* Add to the error to libsas list. */ list_add(&request->completed_node, @@ -1165,6 +1165,10 @@ void isci_request_io_request_complete( task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; spin_unlock_irqrestore(&task->task_state_lock, task_flags); + /* Fail the I/O. */ + response = SAS_TASK_UNDELIVERED; + status = SAM_STAT_TASK_ABORTED; + complete_to_host = isci_perform_error_io_completion; request->complete_in_target = false; break; diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index e1c9c8f04050..b84bedd94601 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -302,14 +302,19 @@ isci_task_set_completion_status( spin_lock_irqsave(&task->task_state_lock, flags); - task->task_status.resp = response; - task->task_status.stat = status; - /* If a device reset is being indicated, make sure the I/O * is in the error path. */ - if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) + if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) { + + /* Fail the I/O to make sure it goes into the error path. */ + response = SAS_TASK_UNDELIVERED; + status = SAM_STAT_TASK_ABORTED; + task_notification_selection = isci_perform_error_io_completion; + } + task->task_status.resp = response; + task->task_status.stat = status; switch (task_notification_selection) { -- cgit v1.2.3 From 6e2802a7fc246b53f919efbf1c011da2d0a4ff30 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Tue, 8 Mar 2011 20:32:16 -0700 Subject: isci: All pending requests are terminated before stopping the device. Make sure all pending I/O including any in the libsas error handler process is cleaned-up. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 1dae2184b9e9..6fe6815e4b74 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -380,6 +380,10 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem "%s: isci_device = %p\n", __func__, idev); isci_remote_device_change_state(idev, isci_stopping); + + /* Kill all outstanding requests. */ + isci_remote_device_nuke_requests(idev); + set_bit(IDEV_STOP_PENDING, &idev->flags); spin_lock_irqsave(&ihost->scic_lock, flags); -- cgit v1.2.3 From 34cad85d18d6da1cc11e410046d7572e65b19fcf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 10 Mar 2011 00:01:43 -0800 Subject: isci: add "isci_id" attribute Allow each controller to be identified via sysfs. # cat /sys/class/scsi_host/host13/isci_id 1 Signed-off-by: Dan Williams --- drivers/scsi/isci/init.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 2838beff43b8..3f2bb137bcb1 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -229,12 +229,28 @@ static int isci_register_sas_ha(struct isci_host *isci_host) return 0; } -static void isci_unregister_sas_ha(struct isci_host *isci_host) +static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf) { + struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev); + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); + struct isci_host *ihost = container_of(sas_ha, typeof(*ihost), sas_ha); + + return snprintf(buf, PAGE_SIZE, "%d\n", ihost->id); +} + +static DEVICE_ATTR(isci_id, S_IRUGO, isci_show_id, NULL); + +static void isci_unregister(struct isci_host *isci_host) +{ + struct Scsi_Host *shost; + if (!isci_host) return; - sas_unregister_ha(&(isci_host->sas_ha)); + shost = isci_host->shost; + device_remove_file(&shost->shost_dev, &dev_attr_isci_id); + + sas_unregister_ha(&isci_host->sas_ha); sas_remove_host(isci_host->shost); scsi_remove_host(isci_host->shost); @@ -477,8 +493,14 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) if (err) goto err_shost_remove; + err = device_create_file(&shost->shost_dev, &dev_attr_isci_id); + if (err) + goto err_unregister_ha; + return isci_host; + err_unregister_ha: + sas_unregister_ha(&(isci_host->sas_ha)); err_shost_remove: scsi_remove_host(shost); err_shost: @@ -640,7 +662,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic err_host_alloc: for_each_isci_host(i, isci_host, pdev) - isci_unregister_sas_ha(isci_host); + isci_unregister(isci_host); return err; } @@ -650,7 +672,7 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev) int i; for_each_isci_host(i, isci_host, pdev) { - isci_unregister_sas_ha(isci_host); + isci_unregister(isci_host); isci_host_deinit(isci_host); scic_controller_disable_interrupts(isci_host->core_controller); } -- cgit v1.2.3 From 1077a574103177bff22b7cdd155d960f46ac1e8f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 11 Mar 2011 10:13:51 -0800 Subject: isci: fix incorrect assumptions about task->dev and task->dev->port being NULL A domain_device has the same lifetime as its related scsi_target. The scsi_target is reference counted based on outstanding commands, therefore it is safe to assume that if we have a valid sas_task that the ->dev pointer is also valid. The asd_sas_port of a domain_device has the same lifetime as the driver so it can also never be NULL as long as the sas_task is valid and the driver is loaded. This also cleans up isci_task_complete_for_upper_layer(), renames it to isci_task_refuse() and notices that the isci_completion_selection parameter was set to isci_perform_normal_io_completion by all callers. Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 168 ++++++++++++++++------------------------------- 1 file changed, 55 insertions(+), 113 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index d00b4c97b85b..d48368002504 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -67,39 +67,36 @@ #include "task.h" /** -* isci_task_complete_for_upper_layer() - This function completes the request -* to the upper layer driver in the case where an I/O needs to be completed -* back in the submit path. -* @host: This parameter is a pointer to the host on which the the request -* should be queued (either as an error or success). -* @task: This parameter is the completed request. -* @response: This parameter is the response code for the completed task. -* @status: This parameter is the status code for the completed task. +* isci_task_refuse() - complete the request to the upper layer driver in +* the case where an I/O needs to be completed back in the submit path. +* @ihost: host on which the the request was queued +* @task: request to complete +* @response: response code for the completed task. +* @status: status code for the completed task. * -* none. */ -static void isci_task_complete_for_upper_layer(struct sas_task *task, - enum service_response response, - enum exec_status status, - enum isci_completion_selection task_notification_selection) +static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, + enum service_response response, + enum exec_status status) + { - unsigned long flags = 0; - struct Scsi_Host *host = NULL; + enum isci_completion_selection disposition; - task_notification_selection - = isci_task_set_completion_status(task, response, status, - task_notification_selection); + disposition = isci_perform_normal_io_completion; + disposition = isci_task_set_completion_status(task, response, status, + disposition); /* Tasks aborted specifically by a call to the lldd_abort_task - * function should not be completed to the host in the regular path. - */ - switch (task_notification_selection) { + * function should not be completed to the host in the regular path. + */ + switch (disposition) { case isci_perform_normal_io_completion: /* Normal notification (task_done) */ - dev_dbg(task->dev->port->ha->dev, + dev_dbg(&ihost->pdev->dev, "%s: Normal - task = %p, response=%d, status=%d\n", __func__, task, response, status); + task->lldd_task = NULL; if (dev_is_sata(task->dev)) { /* Since we are still in the submit path, and since * libsas takes the host lock on behalf of SATA @@ -107,44 +104,36 @@ static void isci_task_complete_for_upper_layer(struct sas_task *task, * before we can call back and report the I/O * submission error. */ - if (task->dev - && task->dev->port - && task->dev->port->ha) { + unsigned long flags; - host = task->dev->port->ha->core.shost; - raw_local_irq_save(flags); - spin_unlock(host->host_lock); - } + raw_local_irq_save(flags); + spin_unlock(ihost->shost->host_lock); task->task_done(task); - if (host) { - spin_lock(host->host_lock); - raw_local_irq_restore(flags); - } + spin_lock(ihost->shost->host_lock); + raw_local_irq_restore(flags); } else task->task_done(task); - - task->lldd_task = NULL; break; case isci_perform_aborted_io_completion: /* No notification because this request is already in the * abort path. */ - dev_warn(task->dev->port->ha->dev, + dev_warn(&ihost->pdev->dev, "%s: Aborted - task = %p, response=%d, status=%d\n", __func__, task, response, status); break; case isci_perform_error_io_completion: /* Use sas_task_abort */ - dev_warn(task->dev->port->ha->dev, + dev_warn(&ihost->pdev->dev, "%s: Error - task = %p, response=%d, status=%d\n", __func__, task, response, status); sas_task_abort(task); break; default: - dev_warn(task->dev->port->ha->dev, + dev_warn(&ihost->pdev->dev, "%s: isci task notification default case!", __func__); sas_task_abort(task); @@ -152,6 +141,10 @@ static void isci_task_complete_for_upper_layer(struct sas_task *task, } } +#define for_each_sas_task(num, task) \ + for (; num > 0; num--,\ + task = list_entry(task->list.next, struct sas_task, list)) + /** * isci_task_execute_task() - This function is one of the SAS Domain Template * functions. This function is called by libsas to send a task down to @@ -164,7 +157,7 @@ static void isci_task_complete_for_upper_layer(struct sas_task *task, */ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) { - struct isci_host *isci_host; + struct isci_host *ihost = task->dev->port->ha->lldd_ha; struct isci_request *request = NULL; struct isci_remote_device *device; unsigned long flags; @@ -172,60 +165,23 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) enum sci_status status; enum isci_status device_status; - dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num); - - if ((task->dev == NULL) || (task->dev->port == NULL)) { - - /* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer - * removes the target. - */ - isci_task_complete_for_upper_layer( - task, - SAS_TASK_UNDELIVERED, - SAS_DEVICE_UNKNOWN, - isci_perform_normal_io_completion - ); - return 0; /* The I/O was accepted (and failed). */ - } - isci_host = isci_host_from_sas_ha(task->dev->port->ha); + dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num); /* Check if we have room for more tasks */ - ret = isci_host_can_queue(isci_host, num); + ret = isci_host_can_queue(ihost, num); if (ret) { - dev_warn(task->dev->port->ha->dev, "%s: queue full\n", __func__); + dev_warn(&ihost->pdev->dev, "%s: queue full\n", __func__); return ret; } - do { - dev_dbg(task->dev->port->ha->dev, + for_each_sas_task(num, task) { + dev_dbg(&ihost->pdev->dev, "task = %p, num = %d; dev = %p; cmd = %p\n", task, num, task->dev, task->uldd_task); - if ((task->dev == NULL) || (task->dev->port == NULL)) { - dev_warn(task->dev->port->ha->dev, - "%s: task %p's port or dev == NULL!\n", - __func__, task); - - /* Indicate SAS_TASK_UNDELIVERED, so that the scsi - * midlayer removes the target. - */ - isci_task_complete_for_upper_layer( - task, - SAS_TASK_UNDELIVERED, - SAS_DEVICE_UNKNOWN, - isci_perform_normal_io_completion - ); - /* We don't have a valid host reference, so we - * can't control the host queueing condition. - */ - goto next_task; - } - device = isci_dev_from_domain_dev(task->dev); - isci_host = isci_host_from_sas_ha(task->dev->port->ha); - if (device) device_status = device->status; else @@ -239,34 +195,28 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) if (device_status != isci_ready_for_io) { /* Forces a retry from scsi mid layer. */ - dev_warn(task->dev->port->ha->dev, + dev_warn(&ihost->pdev->dev, "%s: task %p: isci_host->status = %d, " "device = %p; device_status = 0x%x\n\n", __func__, task, - isci_host_get_state(isci_host), + isci_host_get_state(ihost), device, device_status); if (device_status == isci_ready) { /* Indicate QUEUE_FULL so that the scsi midlayer * retries. */ - isci_task_complete_for_upper_layer( - task, - SAS_TASK_COMPLETE, - SAS_QUEUE_FULL, - isci_perform_normal_io_completion - ); + isci_task_refuse(ihost, task, + SAS_TASK_COMPLETE, + SAS_QUEUE_FULL); } else { /* Else, the device is going down. */ - isci_task_complete_for_upper_layer( - task, - SAS_TASK_UNDELIVERED, - SAS_DEVICE_UNKNOWN, - isci_perform_normal_io_completion - ); + isci_task_refuse(ihost, task, + SAS_TASK_UNDELIVERED, + SAS_DEVICE_UNKNOWN); } - isci_host_can_dequeue(isci_host, 1); + isci_host_can_dequeue(ihost, 1); } else { /* There is a device and it's ready for I/O. */ spin_lock_irqsave(&task->task_state_lock, flags); @@ -276,12 +226,9 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) spin_unlock_irqrestore(&task->task_state_lock, flags); - isci_task_complete_for_upper_layer( - task, - SAS_TASK_UNDELIVERED, - SAM_STAT_TASK_ABORTED, - isci_perform_normal_io_completion - ); + isci_task_refuse(ihost, task, + SAS_TASK_UNDELIVERED, + SAM_STAT_TASK_ABORTED); /* The I/O was aborted. */ @@ -290,7 +237,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) spin_unlock_irqrestore(&task->task_state_lock, flags); /* build and send the request. */ - status = isci_request_execute(isci_host, task, &request, + status = isci_request_execute(ihost, task, &request, gfp_flags); if (status != SCI_SUCCESS) { @@ -307,19 +254,14 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) * SAS_TASK_UNDELIVERED next time * through. */ - isci_task_complete_for_upper_layer( - task, - SAS_TASK_COMPLETE, - SAS_QUEUE_FULL, - isci_perform_normal_io_completion - ); - isci_host_can_dequeue(isci_host, 1); + isci_task_refuse(ihost, task, + SAS_TASK_COMPLETE, + SAS_QUEUE_FULL); + isci_host_can_dequeue(ihost, 1); } } } -next_task: - task = list_entry(task->list.next, struct sas_task, list); - } while (--num > 0); + } return 0; } -- cgit v1.2.3 From c4b9e24c4be67aeed44cd46ef5ea92948d02a426 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Wed, 16 Mar 2011 09:41:59 -0700 Subject: isci: don't hold scic_lock over calls to sas_task_abort() In the case where submitted I/Os fail with the status code SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, the execute function now waits until scic_lock is cleared before calling the helper function "isci_request_signal_device_reset" which sets the flag for the pending reset condition on the I/O. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 015643104311..eba8e0b3c873 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -449,26 +449,11 @@ int isci_request_execute( list_add(&request->dev_node, &isci_device->reqs_in_process); - if (status == - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - /* Signal libsas that we need the SCSI error - * handler thread to work on this I/O and that - * we want a device reset. - */ - isci_request_signal_device_reset(request); - - /* Change the status, since we are holding - * the I/O until it is managed by the SCSI - * error handler. - */ - status = SCI_SUCCESS; - } - else + if (status == SCI_SUCCESS) { /* Save the tag for possible task mgmt later. */ request->io_tag = scic_io_request_get_io_tag( request->sci_request_handle); - - + } } else dev_warn(&isci_host->pdev->dev, "%s: failed request start\n", @@ -476,6 +461,21 @@ int isci_request_execute( spin_unlock_irqrestore(&isci_host->scic_lock, flags); + if (status == + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + /* Signal libsas that we need the SCSI error + * handler thread to work on this I/O and that + * we want a device reset. + */ + isci_request_signal_device_reset(request); + + /* Change the status, since we are holding + * the I/O until it is managed by the SCSI + * error handler. + */ + status = SCI_SUCCESS; + } + } else dev_warn(&isci_host->pdev->dev, "%s: request_construct failed - status = 0x%x\n", -- cgit v1.2.3 From ce0b89f35636f3a69fbde851aff8a284c4b4c22b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Mar 2011 08:04:43 -0700 Subject: isci: task.h compile and checkpatch fixes A usage of "FALSE" leaked in as well as some checkpatch escapes. Signed-off-by: Dan Williams --- drivers/scsi/isci/task.h | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index b84bedd94601..9754b43f5b0b 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -306,7 +306,6 @@ isci_task_set_completion_status( * is in the error path. */ if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) { - /* Fail the I/O to make sure it goes into the error path. */ response = SAS_TASK_UNDELIVERED; status = SAM_STAT_TASK_ABORTED; @@ -317,28 +316,25 @@ isci_task_set_completion_status( task->task_status.stat = status; switch (task_notification_selection) { - - case isci_perform_aborted_io_completion: - /* This path can occur with task-managed requests as well as - * requests terminated because of LUN or device resets. - */ - /* Fall through to the normal case... */ - - case isci_perform_normal_io_completion: - /* Normal notification (task_done) */ - isci_set_task_doneflags(task); - break; - - default: - WARN_ON(FALSE); - /* Fall through to the error case... */ - - case isci_perform_error_io_completion: - /* Use sas_task_abort */ - /* Leave SAS_TASK_STATE_DONE clear - * Leave SAS_TASK_AT_INITIATOR set. - */ - break; + case isci_perform_aborted_io_completion: + /* This path can occur with task-managed requests as well as + * requests terminated because of LUN or device resets. + */ + /* Fall through to the normal case... */ + case isci_perform_normal_io_completion: + /* Normal notification (task_done) */ + isci_set_task_doneflags(task); + break; + default: + WARN_ONCE(1, "unknown task_notification_selection: %d\n", + task_notification_selection); + /* Fall through to the error case... */ + case isci_perform_error_io_completion: + /* Use sas_task_abort */ + /* Leave SAS_TASK_STATE_DONE clear + * Leave SAS_TASK_AT_INITIATOR set. + */ + break; } spin_unlock_irqrestore(&task->task_state_lock, flags); -- cgit v1.2.3 From 9affa289e2f9ef4721e85edbde86466524bfe957 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Mar 2011 17:31:27 -0700 Subject: isci: reset hardware at init Don't assume the hardware is in a known state at init. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 180bb1e69012..799a04bc0938 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -2116,7 +2116,7 @@ enum sci_status scic_controller_construct(struct scic_sds_controller *controller /* Initialize the User and OEM parameters to default values. */ scic_sds_controller_set_default_config_parameters(controller); - return SCI_SUCCESS; + return scic_controller_reset(controller); } /* --------------------------------------------------------------------------- */ @@ -3562,6 +3562,7 @@ const struct scic_sds_controller_state_handler scic_sds_controller_state_handler .terminate_request = scic_sds_controller_default_request_handler, }, [SCI_BASE_CONTROLLER_STATE_RESET] = { + .base.reset = scic_sds_controller_general_reset_handler, .base.initialize = scic_sds_controller_reset_state_initialize_handler, .base.start_io = scic_sds_controller_default_start_operation_handler, .base.complete_io = scic_sds_controller_default_request_handler, -- cgit v1.2.3 From d044af17aacd03a1f4fced1af4b7570d205c8fd9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 8 Mar 2011 09:52:49 -0800 Subject: isci: Add support for probing OROM for OEM params We need to scan the OROM for signature and grab the OEM parameters. We also need to do the same for EFI. If all fails then we resort to user binary blob, and if that fails then we go to the defaults. Share the format with the create_fw utility so that all possible sources of the parameters are in-sync. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 2 +- drivers/scsi/isci/core/scic_config_parameters.h | 41 +---- drivers/scsi/isci/core/scic_sds_controller.c | 6 +- drivers/scsi/isci/firmware/create_fw.c | 197 +++++++----------------- drivers/scsi/isci/firmware/create_fw.h | 67 ++++++++ drivers/scsi/isci/host.c | 47 +++--- drivers/scsi/isci/host.h | 2 +- drivers/scsi/isci/init.c | 191 ++++------------------- drivers/scsi/isci/isci.h | 39 ----- drivers/scsi/isci/probe_roms.c | 133 ++++++++++++++++ drivers/scsi/isci/probe_roms.h | 130 ++++++++++++++++ firmware/isci/isci_firmware.bin.ihex | 25 +-- 12 files changed, 453 insertions(+), 427 deletions(-) create mode 100644 drivers/scsi/isci/firmware/create_fw.h create mode 100644 drivers/scsi/isci/probe_roms.c create mode 100644 drivers/scsi/isci/probe_roms.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index d402d679a316..1252d768c42d 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -9,7 +9,7 @@ EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ remote_device.o port.o timers.o \ - host.o task.o events.o \ + host.o task.o events.o probe_roms.o \ core/scic_sds_controller.o \ core/scic_sds_remote_device.o \ core/scic_sds_request.o \ diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index 485fefc08883..5e1345daf014 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -68,6 +68,7 @@ #include "sci_status.h" #include "intel_sas.h" #include "sci_controller_constants.h" +#include "probe_roms.h" struct scic_sds_controller; @@ -223,44 +224,6 @@ union scic_user_parameters { */ #define SCIC_SDS_PARM_PHY_MASK_MAX 0xF -/** - * struct scic_sds_oem_parameters - This structure delineates the various OEM - * parameters that must be set the core user. - * - * - */ -struct scic_sds_oem_parameters { - struct { - /** - * This field indicates whether Spread Spectrum Clocking (SSC) - * should be enabled or disabled. - */ - bool do_enable_ssc; - - } controller; - - struct { - /** - * This field specifies the phys to be contained inside a port. - * The bit position in the mask specifies the index of the phy - * to be contained in the port. Multiple bits (i.e. phys) - * can be contained in a single port. - */ - u8 phy_mask; - - } ports[SCI_MAX_PORTS]; - - struct sci_phy_oem_params { - /** - * This field specifies the SAS address to be transmitted on - * for this phy index. - */ - struct sci_sas_address sas_address; - - } phys[SCI_MAX_PHYS]; - -}; - /** * This structure/union specifies the various different OEM parameter sets * available. Each type is specific to a hardware controller version. @@ -273,7 +236,7 @@ union scic_oem_parameters { * Storage Controller Unit (SCU) Driver Standard (SDS) version * 1. */ - struct scic_sds_oem_parameters sds1; + struct scic_sds_oem_params sds1; }; diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 799a04bc0938..e7f3711b4afc 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -2039,10 +2039,8 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co /* Initialize all of the phy parameter information. */ for (index = 0; index < SCI_MAX_PHYS; index++) { - /* - * Default to 3G (i.e. Gen 2) for now. User can override if - * they choose. */ - scic->user_parameters.sds1.phys[index].max_speed_generation = 2; + /* Default to 6G (i.e. Gen 3) for now. */ + scic->user_parameters.sds1.phys[index].max_speed_generation = 3; /* the frequencies cannot be 0 */ scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f; diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c index 442caac9675d..f8f96d6eb7df 100644 --- a/drivers/scsi/isci/firmware/create_fw.c +++ b/drivers/scsi/isci/firmware/create_fw.c @@ -6,157 +6,30 @@ #include #include #include +#include +#include +#include -char blob_name[] = "isci_firmware.bin"; -char id[] = "#SCU MAGIC#"; -unsigned char version = 1; -unsigned char sub_version = 0; - - -/* - * For all defined arrays: - * elements 0-3 are for SCU0, ports 0-3 - * elements 4-7 are for SCU1, ports 0-3 - * - * valid configurations for one SCU are: - * P0 P1 P2 P3 - * ---------------- - * 0xF,0x0,0x0,0x0 # 1 x4 port - * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1 - * # ports - * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2 - * # port - * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port - * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration) - * - * if there is a port/phy on which you do not wish to override the default - * values, use the value assigned to UNINIT_PARAM (255). - */ -unsigned int phy_mask[] = { 1, 2, 4, 8, 1, 2, 4, 8 }; - - -/* denotes SAS generation. i.e. 3: SAS Gen 3 6G */ -unsigned int phy_gen[] = { 3, 3, 3, 3, 3, 3, 3, 3 }; - -/* - * if there is a port/phy on which you do not wish to override the default - * values, use the value "0000000000000000". SAS address of zero's is - * considered invalid and will not be used. - */ -unsigned long long sas_addr[] = { 0x5FCFFFFFF0000000ULL, - 0x5FCFFFFFF1000000ULL, - 0x5FCFFFFFF2000000ULL, - 0x5FCFFFFFF3000000ULL, - 0x5FCFFFFFF4000000ULL, - 0x5FCFFFFFF5000000ULL, - 0x5FCFFFFFF6000000ULL, - 0x5FCFFFFFF7000000ULL }; - -int write_blob(void) +#include "create_fw.h" +#include "../probe_roms.h" + +int write_blob(struct isci_orom *isci_orom) { FILE *fd; int err; + size_t count; fd = fopen(blob_name, "w+"); if (!fd) { perror("Open file for write failed"); + fclose(fd); return -EIO; } - /* write id */ - err = fwrite((void *)id, sizeof(char), strlen(id)+1, fd); - if (err == 0) { - perror("write id failed"); - return err; - } - - /* write version */ - err = fwrite((void *)&version, sizeof(version), 1, fd); - if (err == 0) { - perror("write version failed"); - return err; - } - - /* write sub version */ - err = fwrite((void *)&sub_version, sizeof(sub_version), 1, fd); - if (err == 0) { - perror("write subversion failed"); - return err; - } - - /* write phy mask header */ - err = fputc(0x1, fd); - if (err == EOF) { - perror("write phy mask header failed"); - return -EIO; - } - - /* write size */ - err = fputc(8, fd); - if (err == EOF) { - perror("write phy mask size failed"); - return -EIO; - } - - /* write phy masks */ - err = fwrite((void *)phy_mask, 1, sizeof(phy_mask), fd); - if (err == 0) { - perror("write phy_mask failed"); - return err; - } - - /* write phy gen header */ - err = fputc(0x2, fd); - if (err == EOF) { - perror("write phy gen header failed"); - return -EIO; - } - - /* write size */ - err = fputc(8, fd); - if (err == EOF) { - perror("write phy gen size failed"); - return -EIO; - } - - /* write phy_gen */ - err = fwrite((void *)phy_gen, - 1, - sizeof(phy_gen), - fd); - if (err == 0) { - perror("write phy_gen failed"); - return err; - } - - /* write phy gen header */ - err = fputc(0x3, fd); - if (err == EOF) { - perror("write sas addr header failed"); - return -EIO; - } - - /* write size */ - err = fputc(8, fd); - if (err == EOF) { - perror("write sas addr size failed"); - return -EIO; - } - - /* write sas_addr */ - err = fwrite((void *)sas_addr, - 1, - sizeof(sas_addr), - fd); - if (err == 0) { - perror("write sas_addr failed"); - return err; - } - - /* write end header */ - err = fputc(0xff, fd); - if (err == EOF) { - perror("write end header failed"); + count = fwrite(isci_orom, sizeof(struct isci_orom), 1, fd); + if (count != 1) { + perror("Write data failed"); + fclose(fd); return -EIO; } @@ -165,13 +38,53 @@ int write_blob(void) return 0; } +void set_binary_values(struct isci_orom *isci_orom) +{ + int ctrl_idx, phy_idx, port_idx; + + /* setting OROM signature */ + strncpy(isci_orom->hdr.signature, sig, strlen(sig)); + isci_orom->hdr.version = 0x10; + isci_orom->hdr.total_block_length = sizeof(struct isci_orom); + isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr); + isci_orom->hdr.num_elements = num_elements; + + for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) { + isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type; + isci_orom->ctrl[ctrl_idx].controller.max_concurrent_dev_spin_up = + max_num_concurrent_dev_spin_up; + isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc = + enable_ssc; + + for (port_idx = 0; port_idx < 4; port_idx++) + isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask = + phy_mask[ctrl_idx][port_idx]; + + for (phy_idx = 0; phy_idx < 4; phy_idx++) { + isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high = + (__u32)(sas_addr[ctrl_idx][phy_idx] >> 32); + isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low = + (__u32)(sas_addr[ctrl_idx][phy_idx]); + } + } +} + int main(void) { int err; + struct isci_orom *isci_orom; + + isci_orom = malloc(sizeof(struct isci_orom)); + memset(isci_orom, 0, sizeof(struct isci_orom)); - err = write_blob(); - if (err < 0) + set_binary_values(isci_orom); + + err = write_blob(isci_orom); + if (err < 0) { + free(isci_orom); return err; + } + free(isci_orom); return 0; } diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h new file mode 100644 index 000000000000..bedbe4fad181 --- /dev/null +++ b/drivers/scsi/isci/firmware/create_fw.h @@ -0,0 +1,67 @@ +#ifndef _CREATE_FW_H_ +#define _CREATE_FW_H_ + + +/* we are configuring for 2 SCUs */ +static const int num_elements = 2; + +/* + * For all defined arrays: + * elements 0-3 are for SCU0, ports 0-3 + * elements 4-7 are for SCU1, ports 0-3 + * + * valid configurations for one SCU are: + * P0 P1 P2 P3 + * ---------------- + * 0xF,0x0,0x0,0x0 # 1 x4 port + * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1 + * # ports + * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2 + * # port + * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port + * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration) + * + * if there is a port/phy on which you do not wish to override the default + * values, use the value assigned to UNINIT_PARAM (255). + */ +#ifdef MPC +static const __u8 phy_mask[2][4] = { {1, 2, 4, 8}, + {1, 2, 4, 8} }; +#else /* APC (default) */ +static const __u8 phy_mask[2][4]; +#endif + +/* discovery mode type (port auto config mode by default ) */ +static const int mode_type; + +/* Maximum number of concurrent device spin up */ +static const int max_num_concurrent_dev_spin_up = 1; + +/* enable of ssc operation */ +static const int enable_ssc; + +/* AFE_TX_AMP_CONTROL */ +static const unsigned int afe_tx_amp_control0 = 0x000e7c03; +static const unsigned int afe_tx_amp_control1 = 0x000e7c03; +static const unsigned int afe_tx_amp_control2 = 0x000e7c03; +static const unsigned int afe_tx_amp_control3 = 0x000e7c03; + +/* + * if there is a port/phy on which you do not wish to override the default + * values, use the value "0000000000000000". SAS address of zero's is + * considered invalid and will not be used. + */ +static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000000ULL, + 0x5FCFFFFFF1000000ULL, + 0x5FCFFFFFF2000000ULL, + 0x5FCFFFFFF3000000ULL }, + { 0x5FCFFFFFF4000000ULL, + 0x5FCFFFFFF5000000ULL, + 0x5FCFFFFFF6000000ULL, + 0x5FCFFFFFF7000000ULL } }; + +static const char blob_name[] = "isci_firmware.bin"; +static const char sig[] = "ISCUOEMB"; +static const unsigned char version = 1; + +#endif diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index dc231c22ea93..bb5b54d361b0 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -61,6 +61,7 @@ #include "port.h" #include "request.h" #include "host.h" +#include "probe_roms.h" irqreturn_t isci_msix_isr(int vec, void *data) { @@ -419,6 +420,7 @@ int isci_host_init(struct isci_host *isci_host) struct scic_sds_controller *controller; union scic_oem_parameters scic_oem_params; union scic_user_parameters scic_user_params; + struct isci_pci_info *pci_info = to_pci_info(isci_host->pdev); isci_timer_list_construct(isci_host); @@ -461,31 +463,32 @@ int isci_host_init(struct isci_host *isci_host) sci_object_set_association(isci_host->core_controller, (void *)isci_host); - /* grab initial values stored in the controller object for OEM and USER - * parameters */ - scic_oem_parameters_get(controller, &scic_oem_params); + /* + * grab initial values stored in the controller object for OEM and USER + * parameters + */ scic_user_parameters_get(controller, &scic_user_params); + status = scic_user_parameters_set(isci_host->core_controller, + &scic_user_params); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: scic_user_parameters_set failed\n", + __func__); + return -ENODEV; + } + + scic_oem_parameters_get(controller, &scic_oem_params); - if (isci_firmware) { - /* grab any OEM and USER parameters specified in binary blob */ + /* grab any OEM parameters specified in orom */ + if (pci_info->orom) { status = isci_parse_oem_parameters(&scic_oem_params, - isci_host->id, - isci_firmware); + pci_info->orom, + isci_host->id); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, "parsing firmware oem parameters failed\n"); return -EINVAL; } - - status = isci_parse_user_parameters(&scic_user_params, - isci_host->id, - isci_firmware); - if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, - "%s: isci_parse_user_parameters" - " failed\n", __func__); - return -EINVAL; - } } else { status = scic_oem_parameters_set(isci_host->core_controller, &scic_oem_params); @@ -495,16 +498,6 @@ int isci_host_init(struct isci_host *isci_host) __func__); return -ENODEV; } - - - status = scic_user_parameters_set(isci_host->core_controller, - &scic_user_params); - if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, - "%s: scic_user_parameters_set failed\n", - __func__); - return -ENODEV; - } } tasklet_init(&isci_host->completion_tasklet, diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 889a7850255a..d012b69d8d61 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -140,8 +140,8 @@ static inline struct isci_remote_device *idev_by_id(struct isci_host *ihost, int struct isci_pci_info { struct msix_entry msix_entries[SCI_MAX_MSIX_INT]; - int core_lib_array_index; struct isci_host *hosts[SCI_MAX_CONTROLLERS]; + struct isci_orom *orom; }; static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 3f2bb137bcb1..65519321e1cc 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -56,12 +56,15 @@ #include #include #include +#include +#include #include #include "isci.h" #include "task.h" #include "sci_controller_constants.h" #include "scic_remote_device.h" #include "sci_environment.h" +#include "probe_roms.h" static struct scsi_transport_template *isci_transport_template; @@ -373,85 +376,6 @@ static int isci_setup_interrupts(struct pci_dev *pdev) return err; } -/** - * isci_parse_oem_parameters() - This method will take OEM parameters - * from the module init parameters and copy them to oem_params. This will - * only copy values that are not set to the module parameter default values - * @oem_parameters: This parameter specifies the controller default OEM - * parameters. It is expected that this has been initialized to the default - * parameters for the controller - * - * - */ -enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, - int scu_index, - struct isci_firmware *fw) -{ - int i; - - /* check for valid inputs */ - if (!(scu_index >= 0 - && scu_index < SCI_MAX_CONTROLLERS - && oem_params != NULL)) { - return SCI_FAILURE; - } - - for (i = 0; i < SCI_MAX_PHYS; i++) { - int array_idx = i + (SCI_MAX_PHYS * scu_index); - u64 sas_addr = fw->sas_addrs[array_idx]; - - if (sas_addr != 0) { - oem_params->sds1.phys[i].sas_address.low = - (u32)(sas_addr & 0xffffffff); - oem_params->sds1.phys[i].sas_address.high = - (u32)((sas_addr >> 32) & 0xffffffff); - } - } - - for (i = 0; i < SCI_MAX_PORTS; i++) { - int array_idx = i + (SCI_MAX_PORTS * scu_index); - u32 pmask = fw->phy_masks[array_idx]; - - oem_params->sds1.ports[i].phy_mask = pmask; - } - - return SCI_SUCCESS; -} - -/** - * isci_parse_user_parameters() - This method will take user parameters - * from the module init parameters and copy them to user_params. This will - * only copy values that are not set to the module parameter default values - * @user_parameters: This parameter specifies the controller default user - * parameters. It is expected that this has been initialized to the default - * parameters for the controller - * - * - */ -enum sci_status isci_parse_user_parameters( - union scic_user_parameters *user_params, - int scu_index, - struct isci_firmware *fw) -{ - int i; - - if (!(scu_index >= 0 - && scu_index < SCI_MAX_CONTROLLERS - && user_params != NULL)) { - return SCI_FAILURE; - } - - for (i = 0; i < SCI_MAX_PORTS; i++) { - int array_idx = i + (SCI_MAX_PORTS * scu_index); - u32 gen = fw->phy_gens[array_idx]; - - user_params->sds1.phys[i].max_speed_generation = gen; - - } - - return SCI_SUCCESS; -} - static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) { struct isci_host *isci_host; @@ -535,73 +459,13 @@ static void check_si_rev(struct pci_dev *pdev) } -static int isci_verify_firmware(const struct firmware *fw, - struct isci_firmware *isci_fw) -{ - const u8 *tmp; - - if (fw->size < ISCI_FIRMWARE_MIN_SIZE) - return -EINVAL; - - tmp = fw->data; - - /* 12th char should be the NULL terminate for the ID string */ - if (tmp[11] != '\0') - return -EINVAL; - - if (strncmp("#SCU MAGIC#", tmp, 11) != 0) - return -EINVAL; - - isci_fw->id = tmp; - isci_fw->version = fw->data[ISCI_FW_VER_OFS]; - isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS]; - - tmp = fw->data + ISCI_FW_DATA_OFS; - - while (*tmp != ISCI_FW_HDR_EOF) { - switch (*tmp) { - case ISCI_FW_HDR_PHYMASK: - tmp++; - isci_fw->phy_masks_size = *tmp; - tmp++; - isci_fw->phy_masks = (const u32 *)tmp; - tmp += sizeof(u32) * isci_fw->phy_masks_size; - break; - - case ISCI_FW_HDR_PHYGEN: - tmp++; - isci_fw->phy_gens_size = *tmp; - tmp++; - isci_fw->phy_gens = (const u32 *)tmp; - tmp += sizeof(u32) * isci_fw->phy_gens_size; - break; - - case ISCI_FW_HDR_SASADDR: - tmp++; - isci_fw->sas_addrs_size = *tmp; - tmp++; - isci_fw->sas_addrs = (const u64 *)tmp; - tmp += sizeof(u64) * isci_fw->sas_addrs_size; - break; - - default: - pr_err("bad field in firmware binary blob\n"); - return -EINVAL; - } - } - - pr_info("isci firmware v%u.%u loaded.\n", - isci_fw->version, isci_fw->subversion); - - return SCI_SUCCESS; -} - static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct isci_pci_info *pci_info; int err, i; struct isci_host *isci_host; const struct firmware *fw = NULL; + struct isci_orom *orom; check_si_rev(pdev); @@ -610,33 +474,32 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic return -ENOMEM; pci_set_drvdata(pdev, pci_info); - err = request_firmware(&fw, ISCI_FW_NAME, &pdev->dev); - if (err) { - dev_warn(&pdev->dev, - "Loading firmware failed, using default values\n"); - dev_warn(&pdev->dev, - "Default OEM configuration being used:" - " 4 narrow ports, and default SAS Addresses\n"); - } else { - isci_firmware = devm_kzalloc(&pdev->dev, - sizeof(struct isci_firmware), - GFP_KERNEL); - if (isci_firmware) { - err = isci_verify_firmware(fw, isci_firmware); - if (err != SCI_SUCCESS) { - dev_warn(&pdev->dev, - "firmware verification failed\n"); - dev_warn(&pdev->dev, - "Default OEM configuration being used:" - " 4 narrow ports, and default SAS " - "Addresses\n"); - devm_kfree(&pdev->dev, isci_firmware); - isci_firmware = NULL; - } + if (efi_enabled) { + /* do EFI parsing here */ + orom = NULL; + } else + orom = isci_request_oprom(pdev); + + if (!orom) { + orom = isci_request_firmware(pdev, fw); + if (!orom) { + /* TODO convert this to WARN_TAINT_ONCE once the + * orom/efi parameter support is widely available + */ + dev_warn(&pdev->dev, + "Loading user firmware failed, using default " + "values\n"); + dev_warn(&pdev->dev, + "Default OEM configuration being used: 4 " + "narrow ports, and default SAS Addresses\n"); } - release_firmware(fw); } + if (orom) + dev_info(&pdev->dev, "sas parameters (version: %#x) loaded\n", + orom->hdr.version); + pci_info->orom = orom; + err = isci_pci_init(pdev); if (err) return err; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index b3f63f1a46cf..83422d43c1d3 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include @@ -76,34 +75,6 @@ #include "task.h" #include "sata.h" -extern struct isci_firmware *isci_firmware; - -#define ISCI_FW_NAME "isci/isci_firmware.bin" - -#define ISCI_FIRMWARE_MIN_SIZE 149 - -#define ISCI_FW_IDSIZE 12 -#define ISCI_FW_VER_OFS ISCI_FW_IDSIZE -#define ISCI_FW_SUBVER_OFS ISCI_FW_VER_OFS + 1 -#define ISCI_FW_DATA_OFS ISCI_FW_SUBVER_OFS + 1 - -#define ISCI_FW_HDR_PHYMASK 0x1 -#define ISCI_FW_HDR_PHYGEN 0x2 -#define ISCI_FW_HDR_SASADDR 0x3 -#define ISCI_FW_HDR_EOF 0xff - -struct isci_firmware { - const u8 *id; - u8 version; - u8 subversion; - const u32 *phy_masks; - u8 phy_masks_size; - const u32 *phy_gens; - u8 phy_gens_size; - const u64 *sas_addrs; - u8 sas_addrs_size; -}; - irqreturn_t isci_msix_isr(int vec, void *data); irqreturn_t isci_intx_isr(int vec, void *data); irqreturn_t isci_error_isr(int vec, void *data); @@ -113,14 +84,4 @@ void scic_sds_controller_completion_handler(struct scic_sds_controller *scic); bool scic_sds_controller_error_isr(struct scic_sds_controller *scic); void scic_sds_controller_error_handler(struct scic_sds_controller *scic); -enum sci_status isci_parse_oem_parameters( - union scic_oem_parameters *oem_params, - int scu_index, - struct isci_firmware *fw); - -enum sci_status isci_parse_user_parameters( - union scic_user_parameters *user_params, - int scu_index, - struct isci_firmware *fw); - #endif /* __ISCI_H__ */ diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c new file mode 100644 index 000000000000..0b90e7c546c0 --- /dev/null +++ b/drivers/scsi/isci/probe_roms.c @@ -0,0 +1,133 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + */ + +/* probe_roms - scan for oem parameters */ + +#include +#include +#include +#include + +#include "isci.h" +#include "task.h" +#include "sci_controller_constants.h" +#include "scic_remote_device.h" +#include "sci_environment.h" +#include "probe_roms.h" + +struct isci_orom *isci_request_oprom(struct pci_dev *pdev) +{ + void __iomem *oprom = pci_map_biosrom(pdev); + struct isci_orom *rom = NULL; + size_t len, i; + + if (!oprom) + return NULL; + + len = pci_biosrom_size(pdev); + rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); + + for (i = 0; i < len && rom; i += ISCI_ROM_SIG_SIZE) { + memcpy_fromio(rom->hdr.signature, oprom + i, ISCI_ROM_SIG_SIZE); + if (memcmp(rom->hdr.signature, ISCI_ROM_SIG, + ISCI_ROM_SIG_SIZE) == 0) { + size_t copy_len = min(len - i, sizeof(*rom)); + + memcpy_fromio(rom, oprom + i, copy_len); + break; + } + } + + if (i >= len) { + dev_err(&pdev->dev, "oprom parse error\n"); + devm_kfree(&pdev->dev, rom); + rom = NULL; + } + pci_unmap_biosrom(oprom); + + return rom; +} + +/** + * isci_parse_oem_parameters() - This method will take OEM parameters + * from the module init parameters and copy them to oem_params. This will + * only copy values that are not set to the module parameter default values + * @oem_parameters: This parameter specifies the controller default OEM + * parameters. It is expected that this has been initialized to the default + * parameters for the controller + * + * + */ +enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, + struct isci_orom *orom, int scu_index) +{ + int i; + + /* check for valid inputs */ + if (!(scu_index >= 0 + && scu_index < SCI_MAX_CONTROLLERS + && oem_params != NULL)) + return -EINVAL; + + for (i = 0; i < SCI_MAX_PHYS; i++) { + oem_params->sds1.phys[i].sas_address.low = + orom->ctrl[scu_index].phys[i].sas_address.low; + oem_params->sds1.phys[i].sas_address.high = + orom->ctrl[scu_index].phys[i].sas_address.high; + } + + for (i = 0; i < SCI_MAX_PORTS; i++) + oem_params->sds1.ports[i].phy_mask = + orom->ctrl[scu_index].ports[i].phy_mask; + + return 0; +} + +struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw) +{ + struct isci_orom *orom = NULL, *data; + + if (request_firmware(&fw, ISCI_FW_NAME, &pdev->dev) != 0) + return NULL; + + if (fw->size < sizeof(*orom)) + goto out; + + data = (struct isci_orom *)fw->data; + + if (strncmp(ISCI_ROM_SIG, data->hdr.signature, + strlen(ISCI_ROM_SIG)) != 0) + goto out; + + orom = devm_kzalloc(&pdev->dev, fw->size, GFP_KERNEL); + if (!orom) + goto out; + + memcpy(orom, fw->data, fw->size); + + out: + release_firmware(fw); + + return orom; +} diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h new file mode 100644 index 000000000000..76651c01895a --- /dev/null +++ b/drivers/scsi/isci/probe_roms.h @@ -0,0 +1,130 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _ISCI_PROBE_ROMS_H_ +#define _ISCI_PROBE_ROMS_H_ + +#ifdef __KERNEL__ +#include +#include + +struct isci_orom *isci_request_oprom(struct pci_dev *pdev); + +union scic_oem_parameters; +struct isci_orom; + +enum sci_status isci_parse_oem_parameters( + union scic_oem_parameters *oem_params, + struct isci_orom *orom, + int scu_index); +struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); +int isci_get_efi_var(struct pci_dev *pdev); +#else +#define SCI_MAX_PORTS 4 +#define SCI_MAX_PHYS 4 +#endif + +#define ISCI_FW_NAME "isci/isci_firmware.bin" + +#define ROMSIGNATURE 0xaa55 + +#define ISCI_ROM_SIG "ISCUOEMB" +#define ISCI_ROM_SIG_SIZE 8 + +#define ISCI_EFI_VENDOR_GUID NULL_GUID +#define ISCI_EFI_ATTRIBUTES 0 +#define ISCI_EFI_VAR_NAME "isci_oemb" + +struct sci_bios_oem_param_block_hdr { + uint8_t signature[ISCI_ROM_SIG_SIZE]; + uint16_t total_block_length; + uint8_t hdr_length; + uint8_t version; + uint8_t preboot_source; + uint8_t num_elements; + uint8_t element_length; + uint8_t reserved[8]; +} __attribute__ ((packed)); + +struct scic_sds_oem_params { + struct { + uint8_t mode_type; + uint8_t max_concurrent_dev_spin_up; + uint8_t do_enable_ssc; + uint8_t reserved; + } controller; + + struct { + uint8_t phy_mask; + } ports[SCI_MAX_PORTS]; + + struct sci_phy_oem_params { + struct { + uint32_t high; + uint32_t low; + } sas_address; + + uint32_t afe_tx_amp_control0; + uint32_t afe_tx_amp_control1; + uint32_t afe_tx_amp_control2; + uint32_t afe_tx_amp_control3; + } phys[SCI_MAX_PHYS]; +} __attribute__ ((packed)); + +struct isci_orom { + struct sci_bios_oem_param_block_hdr hdr; + struct scic_sds_oem_params ctrl[2]; +} __attribute__ ((packed)); + +#endif diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex index 9fc9e60f399c..7f12b39e7910 100644 --- a/firmware/isci/isci_firmware.bin.ihex +++ b/firmware/isci/isci_firmware.bin.ihex @@ -1,11 +1,16 @@ -:1000000023534355204D4147494323000100010834 -:1000100001000000020000000400000008000000D1 -:1000200001000000020000000400000008000000C1 -:1000300002080300000003000000030000000300AA -:1000400000000300000003000000030000000300A4 -:1000500000000308000000F0FFFFCF5F000000F188 -:10006000FFFFCF5F000000F2FFFFCF5F000000F353 -:10007000FFFFCF5F000000F4FFFFCF5F000000F53F -:10008000FFFFCF5F000000F6FFFFCF5F000000F72B -:05009000FFFFCF5FFF40 +:10000000495343554F454D42E70017100002000089 +:10001000000000000000000001000000000000FFE0 +:10002000FFCF5F000000F0000000000000000000B3 +:1000300000000000000000FFFFCF5F000000F100A3 +:10004000000000000000000000000000000000FFB1 +:10005000FFCF5F000000F200000000000000000081 +:1000600000000000000000FFFFCF5F000000F30071 +:100070000000000000000000000000000000000080 +:1000800001000000000000FFFFCF5F000000F4004F +:10009000000000000000000000000000000000FF61 +:1000A000FFCF5F000000F50000000000000000002E +:1000B00000000000000000FFFFCF5F000000F6001E +:1000C000000000000000000000000000000000FF31 +:1000D000FFCF5F000000F7000000000000000000FC +:0700E0000000000000000019 :00000001FF -- cgit v1.2.3 From 8db37aabaceb3dcd18754c1e782d4474e4052c81 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 23 Feb 2011 00:02:24 -0800 Subject: isci: Adding EFI variable skeletal support Adding EFI variable retrieving for OEM parameters. Still need GUID and variable name. Also updated the data struct for oem parameters and hex file for firmware Signed-off-by: Dave Jiang [fix CONFIG_EFI=n compile error] Signed-off-by: Dan Williams --- drivers/scsi/isci/init.c | 7 ++--- drivers/scsi/isci/probe_roms.c | 64 ++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/isci/probe_roms.h | 2 +- 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 65519321e1cc..13105294fbea 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -474,10 +474,9 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic return -ENOMEM; pci_set_drvdata(pdev, pci_info); - if (efi_enabled) { - /* do EFI parsing here */ - orom = NULL; - } else + if (efi_enabled) + orom = isci_get_efi_var(pdev); + else orom = isci_request_oprom(pdev); if (!orom) { diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 0b90e7c546c0..927feaddc04d 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "isci.h" @@ -36,6 +37,15 @@ #include "sci_environment.h" #include "probe_roms.h" +struct efi_variable { + efi_char16_t VariableName[1024/sizeof(efi_char16_t)]; + efi_guid_t VendorGuid; + unsigned long DataSize; + __u8 Data[1024]; + efi_status_t Status; + __u32 Attributes; +} __attribute__((packed)); + struct isci_orom *isci_request_oprom(struct pci_dev *pdev) { void __iomem *oprom = pci_map_biosrom(pdev); @@ -131,3 +141,57 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw return orom; } + +static struct efi *get_efi(void) +{ + #ifdef CONFIG_EFI + return &efi; + #else + return NULL; + #endif +} + +struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) +{ + struct efi_variable *evar; + efi_status_t status; + struct isci_orom *orom = NULL; + + evar = devm_kzalloc(&pdev->dev, + sizeof(struct efi_variable), + GFP_KERNEL); + if (!evar) { + dev_warn(&pdev->dev, + "Unable to allocate memory for EFI var\n"); + return NULL; + } + + evar->DataSize = 1024; + evar->VendorGuid = ISCI_EFI_VENDOR_GUID; + evar->Attributes = ISCI_EFI_ATTRIBUTES; + + if (get_efi()) + status = get_efi()->get_variable(evar->VariableName, + &evar->VendorGuid, + &evar->Attributes, + &evar->DataSize, + evar->Data); + else + status = EFI_NOT_FOUND; + + if (status == EFI_SUCCESS) + orom = (struct isci_orom *)evar->Data; + else + dev_warn(&pdev->dev, + "Unable to obtain EFI variable for OEM parms\n"); + + if (orom && memcmp(orom->hdr.signature, ISCI_ROM_SIG, + strlen(ISCI_ROM_SIG)) != 0) + dev_warn(&pdev->dev, + "Verifying OROM signature failed\n"); + + if (!orom) + devm_kfree(&pdev->dev, evar); + + return orom; +} diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 76651c01895a..96d8b9212457 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -69,7 +69,7 @@ enum sci_status isci_parse_oem_parameters( struct isci_orom *orom, int scu_index); struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); -int isci_get_efi_var(struct pci_dev *pdev); +struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); #else #define SCI_MAX_PORTS 4 #define SCI_MAX_PHYS 4 -- cgit v1.2.3 From 07373a5caa29e4159ef1ea5e72985ddaf013519a Mon Sep 17 00:00:00 2001 From: Henryk Dembkowski Date: Wed, 23 Feb 2011 16:55:11 -0800 Subject: isci: add support for 2 more oem parmeters 1/ add OEM paramater support for mode_type (MPC vs APC) 2/ add OEM parameter support for max_number_concurrent_device_spin_up 3/ cleanup scic_sds_controller_start_next_phy todo: hook up the amp control afe parameters into the afe init code Signed-off-by: Henryk Dembkowski Signed-off-by: Jacek Danecki [cleaned up scic_sds_controller_start_next_phy] Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_config_parameters.h | 3 +- drivers/scsi/isci/core/scic_sds_controller.c | 271 +++++++++++---------- drivers/scsi/isci/core/scic_sds_controller.h | 30 +-- .../isci/core/scic_sds_port_configuration_agent.c | 2 +- drivers/scsi/isci/firmware/create_fw.h | 7 +- drivers/scsi/isci/probe_roms.h | 14 ++ firmware/isci/isci_firmware.bin.ihex | 4 +- 7 files changed, 176 insertions(+), 155 deletions(-) diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index 5e1345daf014..f64f24fad5a3 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -224,6 +224,8 @@ union scic_user_parameters { */ #define SCIC_SDS_PARM_PHY_MASK_MAX 0xF +#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4 + /** * This structure/union specifies the various different OEM parameter sets * available. Each type is specific to a hardware controller version. @@ -237,7 +239,6 @@ union scic_oem_parameters { * 1. */ struct scic_sds_oem_params sds1; - }; /** diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index e7f3711b4afc..12b2ad5a28b0 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -293,6 +293,7 @@ void scic_sds_controller_initialize_power_control( ); this_controller->power_control.phys_waiting = 0; + this_controller->power_control.phys_granted_power = 0; } /* --------------------------------------------------------------------------- */ @@ -770,31 +771,6 @@ void scic_sds_controller_timeout_handler( __func__); } -/** - * scic_sds_controller_get_port_configuration_mode - * @this_controller: This is the controller to use to determine if we are using - * manual or automatic port configuration. - * - * SCIC_PORT_CONFIGURATION_MODE - */ -enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode( - struct scic_sds_controller *this_controller) -{ - u32 index; - enum SCIC_PORT_CONFIGURATION_MODE mode; - - mode = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; - - for (index = 0; index < SCI_MAX_PORTS; index++) { - if (this_controller->oem_parameters.sds1.ports[index].phy_mask != 0) { - mode = SCIC_PORT_MANUAL_CONFIGURATION_MODE; - break; - } - } - - return mode; -} - enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) { u32 index; @@ -859,7 +835,7 @@ void scic_sds_controller_phy_timer_stop( /** * This method is called internally by the controller object to start the next - * phy on the controller. If all the phys have been starte, then this + * phy on the controller. If all the phys have been started, then this * method will attempt to transition the controller to the READY state and * inform the user (scic_cb_controller_start_complete()). * @this_controller: This parameter specifies the controller object for which @@ -867,101 +843,88 @@ void scic_sds_controller_phy_timer_stop( * * enum sci_status */ -enum sci_status scic_sds_controller_start_next_phy( - struct scic_sds_controller *this_controller) +enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic) { + struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; + struct scic_sds_phy *sci_phy; enum sci_status status; status = SCI_SUCCESS; - if (this_controller->phy_startup_timer_pending == false) { - if (this_controller->next_phy_to_start == SCI_MAX_PHYS) { - bool is_controller_start_complete = true; - struct scic_sds_phy *the_phy; - u8 index; + if (scic->phy_startup_timer_pending) + return status; - for (index = 0; index < SCI_MAX_PHYS; index++) { - the_phy = &this_controller->phy_table[index]; - - if (scic_sds_phy_get_port(the_phy) != NULL) { - /** - * The controller start operation is complete if and only - * if: - * - all links have been given an opportunity to start - * - have no indication of a connected device - * - have an indication of a connected device and it has - * finished the link training process. - */ - if ( - ( - (the_phy->is_in_link_training == false) - && (the_phy->parent.state_machine.current_state_id - == SCI_BASE_PHY_STATE_INITIAL) - ) - || ( - (the_phy->is_in_link_training == false) - && (the_phy->parent.state_machine.current_state_id - == SCI_BASE_PHY_STATE_STOPPED) - ) - || ( - (the_phy->is_in_link_training == true) - && (the_phy->parent.state_machine.current_state_id - == SCI_BASE_PHY_STATE_STARTING) - ) - ) { - is_controller_start_complete = false; - break; - } - } - } + if (scic->next_phy_to_start >= SCI_MAX_PHYS) { + bool is_controller_start_complete = true; + u32 state; + u8 index; - /* - * The controller has successfully finished the start process. - * Inform the SCI Core user and transition to the READY state. */ - if (is_controller_start_complete == true) { - scic_sds_controller_transition_to_ready( - this_controller, SCI_SUCCESS - ); - scic_sds_controller_phy_timer_stop(this_controller); + for (index = 0; index < SCI_MAX_PHYS; index++) { + sci_phy = &scic->phy_table[index]; + state = sci_phy->parent.state_machine.current_state_id; + + if (!scic_sds_phy_get_port(sci_phy)) + continue; + + /* The controller start operation is complete iff: + * - all links have been given an opportunity to start + * - have no indication of a connected device + * - have an indication of a connected device and it has + * finished the link training process. + */ + if ((sci_phy->is_in_link_training == false && + state == SCI_BASE_PHY_STATE_INITIAL) || + (sci_phy->is_in_link_training == false && + state == SCI_BASE_PHY_STATE_STOPPED) || + (sci_phy->is_in_link_training == true && + state == SCI_BASE_PHY_STATE_STARTING)) { + is_controller_start_complete = false; + break; } - } else { - struct scic_sds_phy *the_phy; - - the_phy = &this_controller->phy_table[this_controller->next_phy_to_start]; + } - if ( - scic_sds_controller_get_port_configuration_mode(this_controller) - == SCIC_PORT_MANUAL_CONFIGURATION_MODE - ) { - if (scic_sds_phy_get_port(the_phy) == NULL) { - this_controller->next_phy_to_start++; - - /* - * Caution recursion ahead be forwarned - * - * The PHY was never added to a PORT in MPC mode so start the next phy in sequence - * This phy will never go link up and will not draw power the OEM parameters either - * configured the phy incorrectly for the PORT or it was never assigned to a PORT */ - return scic_sds_controller_start_next_phy(this_controller); - } + /* + * The controller has successfully finished the start process. + * Inform the SCI Core user and transition to the READY state. */ + if (is_controller_start_complete == true) { + scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS); + scic_sds_controller_phy_timer_stop(scic); + } + } else { + sci_phy = &scic->phy_table[scic->next_phy_to_start]; + + if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { + if (scic_sds_phy_get_port(sci_phy) == NULL) { + scic->next_phy_to_start++; + + /* Caution recursion ahead be forwarned + * + * The PHY was never added to a PORT in MPC mode + * so start the next phy in sequence This phy + * will never go link up and will not draw power + * the OEM parameters either configured the phy + * incorrectly for the PORT or it was never + * assigned to a PORT + */ + return scic_sds_controller_start_next_phy(scic); } + } - status = scic_sds_phy_start(the_phy); + status = scic_sds_phy_start(sci_phy); - if (status == SCI_SUCCESS) { - scic_sds_controller_phy_timer_start(this_controller); - } else { - dev_warn(scic_to_dev(this_controller), - "%s: Controller stop operation failed " - "to stop phy %d because of status " - "%d.\n", - __func__, - this_controller->phy_table[this_controller->next_phy_to_start].phy_index, - status); - } - - this_controller->next_phy_to_start++; + if (status == SCI_SUCCESS) { + scic_sds_controller_phy_timer_start(scic); + } else { + dev_warn(scic_to_dev(scic), + "%s: Controller stop operation failed " + "to stop phy %d because of status " + "%d.\n", + __func__, + scic->phy_table[scic->next_phy_to_start].phy_index, + status); } + + scic->next_phy_to_start++; } return status; @@ -1058,6 +1021,31 @@ static void scic_sds_controller_power_control_timer_start( this_controller->power_control.timer_started = true; } +/** + * This method stops the power control timer for this controller object. + * + * @param scic + */ +void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic) +{ + if (scic->power_control.timer_started) { + isci_event_timer_stop(scic, scic->power_control.timer); + scic->power_control.timer_started = false; + } +} + +/** + * This method stops and starts the power control timer for this controller object. + * + * @param scic + */ +void scic_sds_controller_power_control_timer_restart( + struct scic_sds_controller *scic) +{ + scic_sds_controller_power_control_timer_stop(scic); + scic_sds_controller_power_control_timer_start(scic); +} + /** * * @@ -1070,6 +1058,8 @@ static void scic_sds_controller_power_control_timer_handler( this_controller = (struct scic_sds_controller *)controller; + this_controller->power_control.phys_granted_power = 0; + if (this_controller->power_control.phys_waiting == 0) { this_controller->power_control.timer_started = false; } else { @@ -1081,19 +1071,24 @@ static void scic_sds_controller_power_control_timer_handler( && (this_controller->power_control.phys_waiting != 0); i++) { if (this_controller->power_control.requesters[i] != NULL) { - the_phy = this_controller->power_control.requesters[i]; - this_controller->power_control.requesters[i] = NULL; - this_controller->power_control.phys_waiting--; - break; + if (this_controller->power_control.phys_granted_power < + this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { + the_phy = this_controller->power_control.requesters[i]; + this_controller->power_control.requesters[i] = NULL; + this_controller->power_control.phys_waiting--; + this_controller->power_control.phys_granted_power++; + scic_sds_phy_consume_power_handler(the_phy); + } else { + break; + } } } /* * It doesn't matter if the power list is empty, we need to start the - * timer in case another phy becomes ready. */ + * timer in case another phy becomes ready. + */ scic_sds_controller_power_control_timer_start(this_controller); - - scic_sds_phy_consume_power_handler(the_phy); } } @@ -1109,15 +1104,20 @@ void scic_sds_controller_power_control_queue_insert( { BUG_ON(the_phy == NULL); - if ( - (this_controller->power_control.timer_started) - && (this_controller->power_control.requesters[the_phy->phy_index] == NULL) - ) { + if (this_controller->power_control.phys_granted_power < + this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { + this_controller->power_control.phys_granted_power++; + scic_sds_phy_consume_power_handler(the_phy); + + /* + * stop and start the power_control timer. When the timer fires, the + * no_of_phys_granted_power will be set to 0 + */ + scic_sds_controller_power_control_timer_restart(this_controller); + } else { + /* Add the phy in the waiting list */ this_controller->power_control.requesters[the_phy->phy_index] = the_phy; this_controller->power_control.phys_waiting++; - } else { - scic_sds_controller_power_control_timer_start(this_controller); - scic_sds_phy_consume_power_handler(the_phy); } } @@ -2021,7 +2021,7 @@ void scic_sds_controller_release_frame( * This method sets user parameters and OEM parameters to default values. * Users can override these values utilizing the scic_user_parameters_set() * and scic_oem_parameters_set() methods. - * @controller: This parameter specifies the controller for which to set the + * @scic: This parameter specifies the controller for which to set the * configuration parameters to their default values. * */ @@ -2029,6 +2029,12 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co { u16 index; + /* Default to APC mode. */ + scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; + + /* Default to APC mode. */ + scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1; + /* Default to no SSC operation. */ scic->oem_parameters.sds1.controller.do_enable_ssc = false; @@ -2607,6 +2613,7 @@ enum sci_status scic_oem_parameters_set( == SCI_BASE_CONTROLLER_STATE_INITIALIZED) ) { u16 index; + u8 combined_phy_mask = 0; /* * Validate the oem parameters. If they are not legal, then @@ -2626,6 +2633,24 @@ enum sci_status scic_oem_parameters_set( } } + if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) { + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (scic_parms->sds1.ports[index].phy_mask != 0) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } + } else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { + for (index = 0; index < SCI_MAX_PHYS; index++) + combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask; + + if (combined_phy_mask == 0) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } else { + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } + + if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms)); return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 9b8e55d62910..6386a64896c0 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -121,23 +121,6 @@ enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS { }; -/** - * - * - * Allowed PORT configuration modes APC Automatic PORT configuration mode is - * defined by the OEM configuration parameters providing no PHY_MASK parameters - * for any PORT. i.e. There are no phys assigned to any of the ports at start. - * MPC Manual PORT configuration mode is defined by the OEM configuration - * parameters providing a PHY_MASK value for any PORT. It is assumed that any - * PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned. - * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs - * being assigned is sufficient to declare manual PORT configuration. - */ -enum SCIC_PORT_CONFIGURATION_MODE { - SCIC_PORT_MANUAL_CONFIGURATION_MODE, - SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE -}; - /** * struct scic_power_control - * @@ -163,6 +146,11 @@ struct scic_power_control { */ u8 phys_waiting; + /** + * This field is used to keep track of how many phys have been granted to consume power + */ + u8 phys_granted_power; + /** * This field is an array of phys that we are waiting on. The phys are direct * mapped into requesters via struct scic_sds_phy.phy_index @@ -560,14 +548,6 @@ u32 scic_sds_controller_get_object_size(void); /* --------------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------------- */ - -enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode( - struct scic_sds_controller *this_controller); - -/* --------------------------------------------------------------------------- */ - void scic_sds_controller_post_request( struct scic_sds_controller *this_controller, u32 request); diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index e26a4e69b3ac..7c9521049ae7 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -822,7 +822,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize( enum sci_status status = SCI_SUCCESS; enum SCIC_PORT_CONFIGURATION_MODE mode; - mode = scic_sds_controller_get_port_configuration_mode(controller); + mode = controller->oem_parameters.sds1.controller.mode_type; if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent); diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h index bedbe4fad181..788a8de0c2bc 100644 --- a/drivers/scsi/isci/firmware/create_fw.h +++ b/drivers/scsi/isci/firmware/create_fw.h @@ -1,5 +1,6 @@ #ifndef _CREATE_FW_H_ #define _CREATE_FW_H_ +#include "../probe_roms.h" /* we are configuring for 2 SCUs */ @@ -24,16 +25,16 @@ static const int num_elements = 2; * if there is a port/phy on which you do not wish to override the default * values, use the value assigned to UNINIT_PARAM (255). */ +/* discovery mode type (port auto config mode by default ) */ #ifdef MPC +static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE; static const __u8 phy_mask[2][4] = { {1, 2, 4, 8}, {1, 2, 4, 8} }; #else /* APC (default) */ +static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; static const __u8 phy_mask[2][4]; #endif -/* discovery mode type (port auto config mode by default ) */ -static const int mode_type; - /* Maximum number of concurrent device spin up */ static const int max_num_concurrent_dev_spin_up = 1; diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 96d8b9212457..69526ffa8474 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -86,6 +86,20 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); #define ISCI_EFI_ATTRIBUTES 0 #define ISCI_EFI_VAR_NAME "isci_oemb" +/* Allowed PORT configuration modes APC Automatic PORT configuration mode is + * defined by the OEM configuration parameters providing no PHY_MASK parameters + * for any PORT. i.e. There are no phys assigned to any of the ports at start. + * MPC Manual PORT configuration mode is defined by the OEM configuration + * parameters providing a PHY_MASK value for any PORT. It is assumed that any + * PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned. + * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs + * being assigned is sufficient to declare manual PORT configuration. + */ +enum SCIC_PORT_CONFIGURATION_MODE { + SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0, + SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1 +}; + struct sci_bios_oem_param_block_hdr { uint8_t signature[ISCI_ROM_SIG_SIZE]; uint16_t total_block_length; diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex index 7f12b39e7910..b1bb5cf4499c 100644 --- a/firmware/isci/isci_firmware.bin.ihex +++ b/firmware/isci/isci_firmware.bin.ihex @@ -1,11 +1,11 @@ :10000000495343554F454D42E70017100002000089 -:10001000000000000000000001000000000000FFE0 +:10001000000000000000000101000000000000FFDF :10002000FFCF5F000000F0000000000000000000B3 :1000300000000000000000FFFFCF5F000000F100A3 :10004000000000000000000000000000000000FFB1 :10005000FFCF5F000000F200000000000000000081 :1000600000000000000000FFFFCF5F000000F30071 -:100070000000000000000000000000000000000080 +:10007000000000000000000000000000000000017F :1000800001000000000000FFFFCF5F000000F4004F :10009000000000000000000000000000000000FF61 :1000A000FFCF5F000000F50000000000000000002E -- cgit v1.2.3 From ca507b98e65f539e0b3866b6aa8efd76c13be285 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Thu, 24 Feb 2011 13:09:39 -0700 Subject: isci: update efi variable name and guid These are the finalized values that the driver can expect to see in production. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/probe_roms.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 69526ffa8474..02940e709f97 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -73,6 +73,7 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); #else #define SCI_MAX_PORTS 4 #define SCI_MAX_PHYS 4 +#define SCI_MAX_CONTROLLERS 2 #endif #define ISCI_FW_NAME "isci/isci_firmware.bin" @@ -82,9 +83,11 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); #define ISCI_ROM_SIG "ISCUOEMB" #define ISCI_ROM_SIG_SIZE 8 -#define ISCI_EFI_VENDOR_GUID NULL_GUID +#define ISCI_EFI_VENDOR_GUID \ + EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \ + 0x1a, 0x04, 0xc6) #define ISCI_EFI_ATTRIBUTES 0 -#define ISCI_EFI_VAR_NAME "isci_oemb" +#define ISCI_EFI_VAR_NAME "RST_SCU_OEM" /* Allowed PORT configuration modes APC Automatic PORT configuration mode is * defined by the OEM configuration parameters providing no PHY_MASK parameters @@ -138,7 +141,7 @@ struct scic_sds_oem_params { struct isci_orom { struct sci_bios_oem_param_block_hdr hdr; - struct scic_sds_oem_params ctrl[2]; + struct scic_sds_oem_params ctrl[SCI_MAX_CONTROLLERS]; } __attribute__ ((packed)); #endif -- cgit v1.2.3 From 02839a8b51002d90e4b7c52bf37531834b063f71 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Thu, 24 Feb 2011 17:45:57 -0800 Subject: isci: copy the oem parameters instead of assign Since the data structure for oem from orom/efi/firmware is the same as what the core uses, we can just do a direct copy instead of assignment. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/probe_roms.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 927feaddc04d..822240578115 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -92,24 +92,14 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, struct isci_orom *orom, int scu_index) { - int i; - /* check for valid inputs */ - if (!(scu_index >= 0 - && scu_index < SCI_MAX_CONTROLLERS - && oem_params != NULL)) + if (scu_index < 0 || scu_index > SCI_MAX_CONTROLLERS || + scu_index > orom->hdr.num_elements || !oem_params) return -EINVAL; - for (i = 0; i < SCI_MAX_PHYS; i++) { - oem_params->sds1.phys[i].sas_address.low = - orom->ctrl[scu_index].phys[i].sas_address.low; - oem_params->sds1.phys[i].sas_address.high = - orom->ctrl[scu_index].phys[i].sas_address.high; - } - - for (i = 0; i < SCI_MAX_PORTS; i++) - oem_params->sds1.ports[i].phy_mask = - orom->ctrl[scu_index].ports[i].phy_mask; + memcpy(oem_params, + &orom->ctrl[scu_index], + sizeof(struct scic_sds_oem_params)); return 0; } -- cgit v1.2.3 From 3b67c1f376acb24b7c6679f75275ac5a96792986 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 8 Mar 2011 09:53:51 -0800 Subject: isci: fixup with testing from isci OROM in BIOS Added fixups for the OROM parsing code after testing with BIOS OROM Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/init.c | 7 ++++-- drivers/scsi/isci/probe_roms.c | 48 ++++++++++++++++++++++++++++++++++++------ drivers/scsi/isci/probe_roms.h | 13 ++++++++++++ 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 13105294fbea..ef0c49a0c0a0 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -495,8 +495,11 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic } if (orom) - dev_info(&pdev->dev, "sas parameters (version: %#x) loaded\n", - orom->hdr.version); + dev_info(&pdev->dev, + "OEM SAS parameters (version: %u.%u) loaded\n", + (orom->hdr.version & 0xf0) >> 4, + (orom->hdr.version & 0xf)); + pci_info->orom = orom; err = isci_pci_init(pdev); diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 822240578115..64e9a808c814 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -51,6 +51,10 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) void __iomem *oprom = pci_map_biosrom(pdev); struct isci_orom *rom = NULL; size_t len, i; + int j; + char oem_sig[4]; + struct isci_oem_hdr oem_hdr; + u8 *tmp, sum; if (!oprom) return NULL; @@ -58,13 +62,45 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) len = pci_biosrom_size(pdev); rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); - for (i = 0; i < len && rom; i += ISCI_ROM_SIG_SIZE) { - memcpy_fromio(rom->hdr.signature, oprom + i, ISCI_ROM_SIG_SIZE); - if (memcmp(rom->hdr.signature, ISCI_ROM_SIG, - ISCI_ROM_SIG_SIZE) == 0) { - size_t copy_len = min(len - i, sizeof(*rom)); + for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) { + memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE); - memcpy_fromio(rom, oprom + i, copy_len); + /* we think we found the OEM table */ + if (memcmp(oem_sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) == 0) { + size_t copy_len; + + memcpy_fromio(&oem_hdr, oprom + i, sizeof(oem_hdr)); + + copy_len = min(oem_hdr.len - sizeof(oem_hdr), + sizeof(*rom)); + + memcpy_fromio(rom, + oprom + i + sizeof(oem_hdr), + copy_len); + + /* calculate checksum */ + tmp = (u8 *)&oem_hdr; + for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++) + sum += *tmp; + + tmp = (u8 *)rom; + for (j = 0; j < sizeof(*rom); j++, tmp++) + sum += *tmp; + + if (sum != 0) { + dev_warn(&pdev->dev, + "OEM table checksum failed\n"); + continue; + } + + /* keep going if that's not the oem param table */ + if (memcmp(rom->hdr.signature, + ISCI_ROM_SIG, + ISCI_ROM_SIG_SIZE) != 0) + continue; + + dev_info(&pdev->dev, + "OEM parameter table found in OROM\n"); break; } } diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 02940e709f97..0449239dae45 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -70,6 +70,17 @@ enum sci_status isci_parse_oem_parameters( int scu_index); struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); + +struct isci_oem_hdr { + u8 sig[4]; + u8 rev_major; + u8 rev_minor; + u16 len; + u8 checksum; + u8 reserved1; + u16 reserved2; +} __attribute__ ((packed)); + #else #define SCI_MAX_PORTS 4 #define SCI_MAX_PHYS 4 @@ -80,6 +91,8 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); #define ROMSIGNATURE 0xaa55 +#define ISCI_OEM_SIG "$OEM" +#define ISCI_OEM_SIG_SIZE 4 #define ISCI_ROM_SIG "ISCUOEMB" #define ISCI_ROM_SIG_SIZE 8 -- cgit v1.2.3 From 2e8320f751030a12efc3e64ee857bfa4647f81fe Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Fri, 11 Mar 2011 14:04:43 -0800 Subject: isci: Fixup for OEM parameter EFI variable retrieval Updating the EFI variable OEM parameter retrieval after examining the EFI variable exported via sysfs. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/probe_roms.c | 68 +++++++++++++++++++++++++++++++++++------- drivers/scsi/isci/probe_roms.h | 2 +- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 64e9a808c814..0d968d3b334b 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -61,6 +61,11 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) len = pci_biosrom_size(pdev); rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); + if (!rom) { + dev_warn(&pdev->dev, + "Unable to allocate memory for orom\n"); + return NULL; + } for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) { memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE); @@ -181,7 +186,11 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) { struct efi_variable *evar; efi_status_t status; - struct isci_orom *orom = NULL; + struct isci_orom *rom = NULL; + struct isci_oem_hdr *oem_hdr; + u8 *tmp, sum; + int j; + size_t copy_len; evar = devm_kzalloc(&pdev->dev, sizeof(struct efi_variable), @@ -192,6 +201,16 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) return NULL; } + rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); + if (!rom) { + dev_warn(&pdev->dev, + "Unable to allocate memory for orom\n"); + return NULL; + } + + for (j = 0; j < strlen(ISCI_EFI_VAR_NAME) + 1; j++) + evar->VariableName[j] = ISCI_EFI_VAR_NAME[j]; + evar->DataSize = 1024; evar->VendorGuid = ISCI_EFI_VENDOR_GUID; evar->Attributes = ISCI_EFI_ATTRIBUTES; @@ -205,19 +224,48 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) else status = EFI_NOT_FOUND; - if (status == EFI_SUCCESS) - orom = (struct isci_orom *)evar->Data; - else + if (status != EFI_SUCCESS) { dev_warn(&pdev->dev, "Unable to obtain EFI variable for OEM parms\n"); + return NULL; + } + + oem_hdr = (struct isci_oem_hdr *)evar->Data; - if (orom && memcmp(orom->hdr.signature, ISCI_ROM_SIG, - strlen(ISCI_ROM_SIG)) != 0) + if (memcmp(oem_hdr->sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) != 0) { dev_warn(&pdev->dev, - "Verifying OROM signature failed\n"); + "Invalid OEM header signature\n"); + return NULL; + } - if (!orom) - devm_kfree(&pdev->dev, evar); + /* calculate checksum */ + tmp = (u8 *)oem_hdr; + for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++) + sum += *tmp; - return orom; + tmp = (u8 *)rom; + for (j = 0; j < sizeof(*rom); j++, tmp++) + sum += *tmp; + + if (sum != 0) { + dev_warn(&pdev->dev, + "OEM table checksum failed\n"); + return NULL; + } + + copy_len = min(evar->DataSize, + min(oem_hdr->len - sizeof(*oem_hdr), + sizeof(*rom))); + + memcpy(rom, (char *)evar->Data + sizeof(*oem_hdr), copy_len); + + if (memcmp(rom->hdr.signature, + ISCI_ROM_SIG, + ISCI_ROM_SIG_SIZE) != 0) { + dev_warn(&pdev->dev, + "Invalid OEM table signature\n"); + return NULL; + } + + return rom; } diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 0449239dae45..c2162cf12056 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -100,7 +100,7 @@ struct isci_oem_hdr { EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \ 0x1a, 0x04, 0xc6) #define ISCI_EFI_ATTRIBUTES 0 -#define ISCI_EFI_VAR_NAME "RST_SCU_OEM" +#define ISCI_EFI_VAR_NAME "RstScuO" /* Allowed PORT configuration modes APC Automatic PORT configuration mode is * defined by the OEM configuration parameters providing no PHY_MASK parameters -- cgit v1.2.3 From 4711ba10b13891edf228944a9d0a21dfe7fe90f0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 11 Mar 2011 10:43:57 -0800 Subject: isci: fix oem parameter initialization and mode detection 1/ Since commit 858d4aa7 "isci: Move firmware loading to per PCI device" we have been silently falling back to built-in defaults for the parameter settings by skipping the call to scic_oem_parameters_set(). 2/ The afe parameters from the firmware were not being honored 3/ The latest oem parameter definition flips the mode_type values which are now 0: for APC 1: for MPC. For APC we need to make sure all the phys default to the same address otherwise strict_wide_ports will cause duplicate domains. 4/ Fix up the driver announcement to indicate the source of the parameters. 5/ Fix up the sas addresses to be unique per controller (in the fallback case) Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_controller.h | 2 -- drivers/scsi/isci/core/scic_sds_controller.c | 30 +++++++++++---------- drivers/scsi/isci/firmware/create_fw.c | 11 +++++++- drivers/scsi/isci/firmware/create_fw.h | 39 +++++++++++++++++----------- drivers/scsi/isci/host.c | 30 +++++++++------------ drivers/scsi/isci/init.c | 6 +++-- drivers/scsi/isci/probe_roms.c | 5 +--- drivers/scsi/isci/probe_roms.h | 8 ++++-- firmware/isci/isci_firmware.bin.ihex | 28 ++++++++++---------- 9 files changed, 87 insertions(+), 72 deletions(-) diff --git a/drivers/scsi/isci/core/sci_base_controller.h b/drivers/scsi/isci/core/sci_base_controller.h index 36c53406ea5a..8e0c46f8b221 100644 --- a/drivers/scsi/isci/core/sci_base_controller.h +++ b/drivers/scsi/isci/core/sci_base_controller.h @@ -289,8 +289,6 @@ static inline void sci_base_controller_construct( u32 mde_count, struct sci_base_memory_descriptor_list *next_mdl) { - scic_base->parent.private = NULL; - sci_base_state_machine_construct( &scic_base->state_machine, &scic_base->parent, diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 12b2ad5a28b0..b0edd8408fe7 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -595,6 +595,7 @@ void scic_sds_controller_enable_port_task_scheduler( */ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) { + const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; u32 afe_status; u32 phy_id; @@ -632,6 +633,8 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) } for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { + const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id]; + if (is_b0()) { /* Configure transmitter SSC parameters */ scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000); @@ -691,16 +694,16 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) } udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, 0x000E7C03); + scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control0); udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control1, 0x000E7C03); + scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control1); udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control2, 0x000E7C03); + scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control2); udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control3, 0x000E7C03); + scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control3); udelay(AFE_REGISTER_WRITE_DELAY); } @@ -2027,6 +2030,7 @@ void scic_sds_controller_release_frame( */ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) { + struct isci_host *ihost = sci_object_get_association(scic); u16 index; /* Default to APC mode. */ @@ -2058,7 +2062,7 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co * is worked around by having the upper 32-bits of SAS address * with a value greater then the Vitesse company identifier. * Hence, usage of 0x5FCFFFFF. */ - scic->oem_parameters.sds1.phys[index].sas_address.low = 0x00000001; + scic->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id; scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF; } @@ -2604,14 +2608,11 @@ enum sci_status scic_oem_parameters_set( struct scic_sds_controller *scic, union scic_oem_parameters *scic_parms) { - if ( - (scic->parent.state_machine.current_state_id - == SCI_BASE_CONTROLLER_STATE_RESET) - || (scic->parent.state_machine.current_state_id - == SCI_BASE_CONTROLLER_STATE_INITIALIZING) - || (scic->parent.state_machine.current_state_id - == SCI_BASE_CONTROLLER_STATE_INITIALIZED) - ) { + u32 state = scic->parent.state_machine.current_state_id; + + if (state == SCI_BASE_CONTROLLER_STATE_RESET || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { u16 index; u8 combined_phy_mask = 0; @@ -2651,7 +2652,8 @@ enum sci_status scic_oem_parameters_set( if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms)); + scic->oem_parameters.sds1 = scic_parms->sds1; + return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c index f8f96d6eb7df..c7a2887a7e95 100644 --- a/drivers/scsi/isci/firmware/create_fw.c +++ b/drivers/scsi/isci/firmware/create_fw.c @@ -44,7 +44,7 @@ void set_binary_values(struct isci_orom *isci_orom) /* setting OROM signature */ strncpy(isci_orom->hdr.signature, sig, strlen(sig)); - isci_orom->hdr.version = 0x10; + isci_orom->hdr.version = version; isci_orom->hdr.total_block_length = sizeof(struct isci_orom); isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr); isci_orom->hdr.num_elements = num_elements; @@ -65,6 +65,15 @@ void set_binary_values(struct isci_orom *isci_orom) (__u32)(sas_addr[ctrl_idx][phy_idx] >> 32); isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low = (__u32)(sas_addr[ctrl_idx][phy_idx]); + + isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 = + afe_tx_amp_control0; + isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 = + afe_tx_amp_control1; + isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 = + afe_tx_amp_control2; + isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 = + afe_tx_amp_control3; } } } diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h index 788a8de0c2bc..9f9afbd97d69 100644 --- a/drivers/scsi/isci/firmware/create_fw.h +++ b/drivers/scsi/isci/firmware/create_fw.h @@ -25,14 +25,37 @@ static const int num_elements = 2; * if there is a port/phy on which you do not wish to override the default * values, use the value assigned to UNINIT_PARAM (255). */ + /* discovery mode type (port auto config mode by default ) */ + +/* + * if there is a port/phy on which you do not wish to override the default + * values, use the value "0000000000000000". SAS address of zero's is + * considered invalid and will not be used. + */ #ifdef MPC static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE; static const __u8 phy_mask[2][4] = { {1, 2, 4, 8}, {1, 2, 4, 8} }; +static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000001ULL, + 0x5FCFFFFFF0000002ULL, + 0x5FCFFFFFF0000003ULL, + 0x5FCFFFFFF0000004ULL }, + { 0x5FCFFFFFF0000005ULL, + 0x5FCFFFFFF0000006ULL, + 0x5FCFFFFFF0000007ULL, + 0x5FCFFFFFF0000008ULL } }; #else /* APC (default) */ static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; static const __u8 phy_mask[2][4]; +static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL, + 0x5FCFFFFF00000001ULL, + 0x5FCFFFFF00000001ULL, + 0x5FCFFFFF00000001ULL }, + { 0x5FCFFFFF00000002ULL, + 0x5FCFFFFF00000002ULL, + 0x5FCFFFFF00000002ULL, + 0x5FCFFFFF00000002ULL } }; #endif /* Maximum number of concurrent device spin up */ @@ -47,22 +70,8 @@ static const unsigned int afe_tx_amp_control1 = 0x000e7c03; static const unsigned int afe_tx_amp_control2 = 0x000e7c03; static const unsigned int afe_tx_amp_control3 = 0x000e7c03; -/* - * if there is a port/phy on which you do not wish to override the default - * values, use the value "0000000000000000". SAS address of zero's is - * considered invalid and will not be used. - */ -static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000000ULL, - 0x5FCFFFFFF1000000ULL, - 0x5FCFFFFFF2000000ULL, - 0x5FCFFFFFF3000000ULL }, - { 0x5FCFFFFFF4000000ULL, - 0x5FCFFFFFF5000000ULL, - 0x5FCFFFFFF6000000ULL, - 0x5FCFFFFFF7000000ULL } }; - static const char blob_name[] = "isci_firmware.bin"; static const char sig[] = "ISCUOEMB"; -static const unsigned char version = 1; +static const unsigned char version = 0x10; #endif diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index bb5b54d361b0..d6e2a73e797a 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -418,7 +418,7 @@ int isci_host_init(struct isci_host *isci_host) int err = 0, i; enum sci_status status; struct scic_sds_controller *controller; - union scic_oem_parameters scic_oem_params; + union scic_oem_parameters oem; union scic_user_parameters scic_user_params; struct isci_pci_info *pci_info = to_pci_info(isci_host->pdev); @@ -435,6 +435,7 @@ int isci_host_init(struct isci_host *isci_host) } isci_host->core_controller = controller; + sci_object_set_association(isci_host->core_controller, isci_host); spin_lock_init(&isci_host->state_lock); spin_lock_init(&isci_host->scic_lock); spin_lock_init(&isci_host->queue_lock); @@ -457,12 +458,6 @@ int isci_host_init(struct isci_host *isci_host) isci_host->sas_ha.dev = &isci_host->pdev->dev; isci_host->sas_ha.lldd_ha = isci_host; - /*----------- SCIC controller Initialization Stuff ------------------ - * set association host adapter struct in core controller. - */ - sci_object_set_association(isci_host->core_controller, - (void *)isci_host); - /* * grab initial values stored in the controller object for OEM and USER * parameters @@ -477,11 +472,11 @@ int isci_host_init(struct isci_host *isci_host) return -ENODEV; } - scic_oem_parameters_get(controller, &scic_oem_params); + scic_oem_parameters_get(controller, &oem); /* grab any OEM parameters specified in orom */ if (pci_info->orom) { - status = isci_parse_oem_parameters(&scic_oem_params, + status = isci_parse_oem_parameters(&oem, pci_info->orom, isci_host->id); if (status != SCI_SUCCESS) { @@ -489,15 +484,14 @@ int isci_host_init(struct isci_host *isci_host) "parsing firmware oem parameters failed\n"); return -EINVAL; } - } else { - status = scic_oem_parameters_set(isci_host->core_controller, - &scic_oem_params); - if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, - "%s: scic_oem_parameters_set failed\n", - __func__); - return -ENODEV; - } + } + + status = scic_oem_parameters_set(isci_host->core_controller, &oem); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: scic_oem_parameters_set failed\n", + __func__); + return -ENODEV; } tasklet_init(&isci_host->completion_tasklet, diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index ef0c49a0c0a0..51a7bce20dae 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -466,6 +466,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic struct isci_host *isci_host; const struct firmware *fw = NULL; struct isci_orom *orom; + char *source = "(platform)"; check_si_rev(pdev); @@ -480,6 +481,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic orom = isci_request_oprom(pdev); if (!orom) { + source = "(firmware)"; orom = isci_request_firmware(pdev, fw); if (!orom) { /* TODO convert this to WARN_TAINT_ONCE once the @@ -496,9 +498,9 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic if (orom) dev_info(&pdev->dev, - "OEM SAS parameters (version: %u.%u) loaded\n", + "OEM SAS parameters (version: %u.%u) loaded %s\n", (orom->hdr.version & 0xf0) >> 4, - (orom->hdr.version & 0xf)); + (orom->hdr.version & 0xf), source); pci_info->orom = orom; diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 0d968d3b334b..1697487f908c 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -138,10 +138,7 @@ enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, scu_index > orom->hdr.num_elements || !oem_params) return -EINVAL; - memcpy(oem_params, - &orom->ctrl[scu_index], - sizeof(struct scic_sds_oem_params)); - + oem_params->sds1 = orom->ctrl[scu_index]; return 0; } diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index c2162cf12056..1b444838779f 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -96,6 +96,10 @@ struct isci_oem_hdr { #define ISCI_ROM_SIG "ISCUOEMB" #define ISCI_ROM_SIG_SIZE 8 +#define ISCI_PREBOOT_SOURCE_INIT (0x00) +#define ISCI_PREBOOT_SOURCE_OROM (0x80) +#define ISCI_PREBOOT_SOURCE_EFI (0x81) + #define ISCI_EFI_VENDOR_GUID \ EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \ 0x1a, 0x04, 0xc6) @@ -112,8 +116,8 @@ struct isci_oem_hdr { * being assigned is sufficient to declare manual PORT configuration. */ enum SCIC_PORT_CONFIGURATION_MODE { - SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0, - SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1 + SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 0, + SCIC_PORT_MANUAL_CONFIGURATION_MODE = 1 }; struct sci_bios_oem_param_block_hdr { diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex index b1bb5cf4499c..4f8767cc60f6 100644 --- a/firmware/isci/isci_firmware.bin.ihex +++ b/firmware/isci/isci_firmware.bin.ihex @@ -1,16 +1,16 @@ :10000000495343554F454D42E70017100002000089 -:10001000000000000000000101000000000000FFDF -:10002000FFCF5F000000F0000000000000000000B3 -:1000300000000000000000FFFFCF5F000000F100A3 -:10004000000000000000000000000000000000FFB1 -:10005000FFCF5F000000F200000000000000000081 -:1000600000000000000000FFFFCF5F000000F30071 -:10007000000000000000000000000000000000017F -:1000800001000000000000FFFFCF5F000000F4004F -:10009000000000000000000000000000000000FF61 -:1000A000FFCF5F000000F50000000000000000002E -:1000B00000000000000000FFFFCF5F000000F6001E -:1000C000000000000000000000000000000000FF31 -:1000D000FFCF5F000000F7000000000000000000FC -:0700E0000000000000000019 +:10001000000000000000000001000000000000FFE0 +:10002000FFCF5F01000000037C0E00037C0E000385 +:100030007C0E00037C0E00FFFFCF5F010000000379 +:100040007C0E00037C0E00037C0E00037C0E00FF80 +:10005000FFCF5F01000000037C0E00037C0E000355 +:100060007C0E00037C0E00FFFFCF5F010000000349 +:100070007C0E00037C0E00037C0E00037C0E00004F +:1000800001000000000000FFFFCF5F02000000033E +:100090007C0E00037C0E00037C0E00037C0E00FF30 +:1000A000FFCF5F02000000037C0E00037C0E000304 +:1000B0007C0E00037C0E00FFFFCF5F0200000003F8 +:1000C0007C0E00037C0E00037C0E00037C0E00FF00 +:1000D000FFCF5F02000000037C0E00037C0E0003D4 +:0700E0007C0E00037C0E0002 :00000001FF -- cgit v1.2.3 From b5f18a201ed82ed3776c9950646689b93713ae57 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 16 Mar 2011 14:57:23 -0700 Subject: isci: exposing user parameters via module params Exposing the user config parameters through the kernel module parameters. The kernel module params will have the default values set and we will no longer pulling the default values for user params from the core. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 73 +++++++++++++++------------- drivers/scsi/isci/host.c | 28 ++++++++++- drivers/scsi/isci/init.c | 30 +++++++++++- drivers/scsi/isci/isci.h | 8 +++ 4 files changed, 102 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index b0edd8408fe7..cd31cba28f88 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -2548,41 +2548,46 @@ enum sci_status scic_user_parameters_set( struct scic_sds_controller *scic, union scic_user_parameters *scic_parms) { - if ( - (scic->parent.state_machine.current_state_id - == SCI_BASE_CONTROLLER_STATE_RESET) - || (scic->parent.state_machine.current_state_id - == SCI_BASE_CONTROLLER_STATE_INITIALIZING) - || (scic->parent.state_machine.current_state_id - == SCI_BASE_CONTROLLER_STATE_INITIALIZED) - ) { + u32 state = scic->parent.state_machine.current_state_id; + + if (state == SCI_BASE_CONTROLLER_STATE_RESET || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { u16 index; /* * Validate the user parameters. If they are not legal, then - * return a failure. */ + * return a failure. + */ for (index = 0; index < SCI_MAX_PHYS; index++) { - if (!(scic_parms->sds1.phys[index].max_speed_generation - <= SCIC_SDS_PARM_MAX_SPEED - && scic_parms->sds1.phys[index].max_speed_generation - > SCIC_SDS_PARM_NO_SPEED)) + struct sci_phy_user_params *user_phy; + + user_phy = &scic_parms->sds1.phys[index]; + + if (!((user_phy->max_speed_generation <= + SCIC_SDS_PARM_MAX_SPEED) && + (user_phy->max_speed_generation > + SCIC_SDS_PARM_NO_SPEED))) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - if (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) + if (user_phy->in_connection_align_insertion_frequency < + 3) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - if ( - (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) || - (scic_parms->sds1.phys[index].align_insertion_frequency == 0) || - (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0) - ) + + if ((user_phy->in_connection_align_insertion_frequency < + 3) || + (user_phy->align_insertion_frequency == 0) || + (user_phy-> + notify_enable_spin_up_insertion_frequency == + 0)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; } if ((scic_parms->sds1.stp_inactivity_timeout == 0) || - (scic_parms->sds1.ssp_inactivity_timeout == 0) || - (scic_parms->sds1.stp_max_occupancy_timeout == 0) || - (scic_parms->sds1.ssp_max_occupancy_timeout == 0) || - (scic_parms->sds1.no_outbound_task_timeout == 0)) + (scic_parms->sds1.ssp_inactivity_timeout == 0) || + (scic_parms->sds1.stp_max_occupancy_timeout == 0) || + (scic_parms->sds1.ssp_max_occupancy_timeout == 0) || + (scic_parms->sds1.no_outbound_task_timeout == 0)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms)); @@ -2620,36 +2625,34 @@ enum sci_status scic_oem_parameters_set( * Validate the oem parameters. If they are not legal, then * return a failure. */ for (index = 0; index < SCI_MAX_PORTS; index++) { - if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) { + if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } } for (index = 0; index < SCI_MAX_PHYS; index++) { - if ( - scic_parms->sds1.phys[index].sas_address.high == 0 - && scic_parms->sds1.phys[index].sas_address.low == 0 - ) { + if ((scic_parms->sds1.phys[index].sas_address.high == 0) && + (scic_parms->sds1.phys[index].sas_address.low == 0)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } } - if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) { + if (scic_parms->sds1.controller.mode_type == + SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) { for (index = 0; index < SCI_MAX_PHYS; index++) { if (scic_parms->sds1.ports[index].phy_mask != 0) return SCI_FAILURE_INVALID_PARAMETER_VALUE; } - } else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { + } else if (scic_parms->sds1.controller.mode_type == + SCIC_PORT_MANUAL_CONFIGURATION_MODE) { for (index = 0; index < SCI_MAX_PHYS; index++) combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask; if (combined_phy_mask == 0) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } else { + } else return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } - if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT) + if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > + MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT) return SCI_FAILURE_INVALID_PARAMETER_VALUE; scic->oem_parameters.sds1 = scic_parms->sds1; diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index d6e2a73e797a..79515be5f7c1 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -413,6 +413,32 @@ static void __iomem *smu_base(struct isci_host *isci_host) return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; } +static void isci_user_parameters_get( + struct isci_host *isci_host, + union scic_user_parameters *scic_user_params) +{ + struct scic_sds_user_parameters *u = &scic_user_params->sds1; + int i; + + for (i = 0; i < SCI_MAX_PHYS; i++) { + struct sci_phy_user_params *u_phy = &u->phys[i]; + + u_phy->max_speed_generation = phy_gen; + + /* we are not exporting these for now */ + u_phy->align_insertion_frequency = 0x7f; + u_phy->in_connection_align_insertion_frequency = 0xff; + u_phy->notify_enable_spin_up_insertion_frequency = 0x33; + } + + u->stp_inactivity_timeout = stp_inactive_to; + u->ssp_inactivity_timeout = ssp_inactive_to; + u->stp_max_occupancy_timeout = stp_max_occ_to; + u->ssp_max_occupancy_timeout = ssp_max_occ_to; + u->no_outbound_task_timeout = no_outbound_task_to; + u->max_number_concurrent_device_spin_up = max_concurr_spinup; +} + int isci_host_init(struct isci_host *isci_host) { int err = 0, i; @@ -462,7 +488,7 @@ int isci_host_init(struct isci_host *isci_host) * grab initial values stored in the controller object for OEM and USER * parameters */ - scic_user_parameters_get(controller, &scic_user_params); + isci_user_parameters_get(isci_host, &scic_user_params); status = scic_user_parameters_set(isci_host->core_controller, &scic_user_params); if (status != SCI_SUCCESS) { diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 51a7bce20dae..1b04b9c117a4 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -110,9 +110,37 @@ int isci_si_rev = ISCI_SI_REVA2; #else int isci_si_rev = ISCI_SI_REVB0; #endif -module_param(isci_si_rev, int, S_IRUGO | S_IWUSR); +module_param(isci_si_rev, int, 0); MODULE_PARM_DESC(isci_si_rev, "override default si rev (0: A0 1: A2 2: B0)"); +unsigned char no_outbound_task_to = 20; +module_param(no_outbound_task_to, byte, 0); +MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)"); + +u16 ssp_max_occ_to = 20; +module_param(ssp_max_occ_to, ushort, 0); +MODULE_PARM_DESC(ssp_max_occ_to, "SSP Max occupancy timeout (100us incr)"); + +u16 stp_max_occ_to = 5; +module_param(stp_max_occ_to, ushort, 0); +MODULE_PARM_DESC(stp_max_occ_to, "STP Max occupancy timeout (100us incr)"); + +u16 ssp_inactive_to = 5; +module_param(ssp_inactive_to, ushort, 0); +MODULE_PARM_DESC(ssp_inactive_to, "SSP inactivity timeout (100us incr)"); + +u16 stp_inactive_to = 5; +module_param(stp_inactive_to, ushort, 0); +MODULE_PARM_DESC(stp_inactive_to, "STP inactivity timeout (100us incr)"); + +unsigned char phy_gen = 3; +module_param(phy_gen, byte, 0); +MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)"); + +unsigned char max_concurr_spinup = 1; +module_param(max_concurr_spinup, byte, 0); +MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup"); + static struct scsi_host_template isci_sht = { .module = THIS_MODULE, diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 83422d43c1d3..a2df59c9e06d 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -75,6 +75,14 @@ #include "task.h" #include "sata.h" +extern unsigned char no_outbound_task_to; +extern u16 ssp_max_occ_to; +extern u16 stp_max_occ_to; +extern u16 ssp_inactive_to; +extern u16 stp_inactive_to; +extern unsigned char phy_gen; +extern unsigned char max_concurr_spinup; + irqreturn_t isci_msix_isr(int vec, void *data); irqreturn_t isci_intx_isr(int vec, void *data); irqreturn_t isci_error_isr(int vec, void *data); -- cgit v1.2.3 From 4eefd2518aa04e1c69118252dc23e3444e694bc1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 25 Mar 2011 09:58:15 -0700 Subject: isci: fix apc mode definition The original apc mode definition is the correct one, the fix from commit 4711ba10 "isci: fix oem parameter initialization and mode detection" was based on a typo from a specification update. Signed-off-by: Dan Williams --- drivers/scsi/isci/probe_roms.h | 8 ++------ firmware/isci/isci_firmware.bin.ihex | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 1b444838779f..c2162cf12056 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -96,10 +96,6 @@ struct isci_oem_hdr { #define ISCI_ROM_SIG "ISCUOEMB" #define ISCI_ROM_SIG_SIZE 8 -#define ISCI_PREBOOT_SOURCE_INIT (0x00) -#define ISCI_PREBOOT_SOURCE_OROM (0x80) -#define ISCI_PREBOOT_SOURCE_EFI (0x81) - #define ISCI_EFI_VENDOR_GUID \ EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \ 0x1a, 0x04, 0xc6) @@ -116,8 +112,8 @@ struct isci_oem_hdr { * being assigned is sufficient to declare manual PORT configuration. */ enum SCIC_PORT_CONFIGURATION_MODE { - SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 0, - SCIC_PORT_MANUAL_CONFIGURATION_MODE = 1 + SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0, + SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1 }; struct sci_bios_oem_param_block_hdr { diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex index 4f8767cc60f6..31b5ecf1bddb 100644 --- a/firmware/isci/isci_firmware.bin.ihex +++ b/firmware/isci/isci_firmware.bin.ihex @@ -1,11 +1,11 @@ :10000000495343554F454D42E70017100002000089 -:10001000000000000000000001000000000000FFE0 +:10001000000000000000000101000000000000FFDF :10002000FFCF5F01000000037C0E00037C0E000385 :100030007C0E00037C0E00FFFFCF5F010000000379 :100040007C0E00037C0E00037C0E00037C0E00FF80 :10005000FFCF5F01000000037C0E00037C0E000355 :100060007C0E00037C0E00FFFFCF5F010000000349 -:100070007C0E00037C0E00037C0E00037C0E00004F +:100070007C0E00037C0E00037C0E00037C0E00014E :1000800001000000000000FFFFCF5F02000000033E :100090007C0E00037C0E00037C0E00037C0E00FF30 :1000A000FFCF5F02000000037C0E00037C0E000304 -- cgit v1.2.3 From 52ae18ac80fbdd268720b0daa27ac797a801500c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 25 Mar 2011 10:05:58 -0700 Subject: isci: fix a build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use min_t to address: drivers/scsi/isci/probe_roms.c: In function ‘isci_get_efi_var’: drivers/scsi/isci/probe_roms.c:241: warning: comparison of distinct pointer types lacks a cast Reported-by: David Milburn Signed-off-by: Dan Williams --- drivers/scsi/isci/probe_roms.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 1697487f908c..2df8d8e5d5ea 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -250,9 +250,8 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) return NULL; } - copy_len = min(evar->DataSize, - min(oem_hdr->len - sizeof(*oem_hdr), - sizeof(*rom))); + copy_len = min_t(u16, evar->DataSize, + min_t(u16, oem_hdr->len - sizeof(*oem_hdr), sizeof(*rom))); memcpy(rom, (char *)evar->Data + sizeof(*oem_hdr), copy_len); -- cgit v1.2.3 From 09d7da135b34bc74a7996b5db373521557ddf3d4 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Sat, 26 Mar 2011 16:11:51 -0700 Subject: isci: Remove event_* calls as they are just wrappers Removed isci_event_* calls and call those functions directly. Reported-by: Christoph Hellwig Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 2 +- drivers/scsi/isci/core/scic_sds_controller.c | 400 +++++++------- drivers/scsi/isci/core/scic_sds_controller.h | 3 +- drivers/scsi/isci/core/scic_sds_phy.c | 201 ++++--- drivers/scsi/isci/core/scic_sds_port.c | 444 ++++++++------- .../isci/core/scic_sds_port_configuration_agent.c | 97 ++-- drivers/scsi/isci/core/scic_sds_remote_device.c | 142 +++-- drivers/scsi/isci/core/scic_sds_request.c | 36 +- .../scsi/isci/core/scic_sds_smp_remote_device.c | 42 +- .../scsi/isci/core/scic_sds_stp_remote_device.c | 74 ++- drivers/scsi/isci/events.c | 609 --------------------- drivers/scsi/isci/events.h | 373 ------------- drivers/scsi/isci/isci.h | 1 - drivers/scsi/isci/port.c | 51 +- drivers/scsi/isci/port.h | 10 + 15 files changed, 734 insertions(+), 1751 deletions(-) delete mode 100644 drivers/scsi/isci/events.c delete mode 100644 drivers/scsi/isci/events.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 1252d768c42d..a65c0ae9d2c4 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -9,7 +9,7 @@ EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ remote_device.o port.o timers.o \ - host.o task.o events.o probe_roms.o \ + host.o task.o probe_roms.o \ core/scic_sds_controller.o \ core/scic_sds_remote_device.o \ core/scic_sds_request.o \ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index cd31cba28f88..eaaa4cc89a85 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -253,19 +253,19 @@ static void scic_sds_controller_phy_startup_timeout_handler( * This method initializes the phy startup operations for controller start. */ enum sci_status scic_sds_controller_initialize_phy_startup( - struct scic_sds_controller *this_controller) + struct scic_sds_controller *scic) { - this_controller->phy_startup_timer = isci_event_timer_create( - this_controller, - scic_sds_controller_phy_startup_timeout_handler, - this_controller - ); + struct isci_host *ihost = sci_object_get_association(scic); - if (this_controller->phy_startup_timer == NULL) { + scic->phy_startup_timer = isci_timer_create(ihost, + scic, + scic_sds_controller_phy_startup_timeout_handler); + + if (scic->phy_startup_timer == NULL) return SCI_FAILURE_INSUFFICIENT_RESOURCES; - } else { - this_controller->next_phy_to_start = 0; - this_controller->phy_startup_timer_pending = false; + else { + scic->next_phy_to_start = 0; + scic->phy_startup_timer_pending = false; } return SCI_SUCCESS; @@ -278,22 +278,20 @@ enum sci_status scic_sds_controller_initialize_phy_startup( * object. */ void scic_sds_controller_initialize_power_control( - struct scic_sds_controller *this_controller) + struct scic_sds_controller *scic) { - this_controller->power_control.timer = isci_event_timer_create( - this_controller, - scic_sds_controller_power_control_timer_handler, - this_controller - ); + struct isci_host *ihost = sci_object_get_association(scic); + scic->power_control.timer = isci_timer_create( + ihost, + scic, + scic_sds_controller_power_control_timer_handler); - memset( - this_controller->power_control.requesters, - 0, - sizeof(this_controller->power_control.requesters) - ); + memset(scic->power_control.requesters, + 0, + sizeof(scic->power_control.requesters)); - this_controller->power_control.phys_waiting = 0; - this_controller->power_control.phys_granted_power = 0; + scic->power_control.phys_waiting = 0; + scic->power_control.phys_granted_power = 0; } /* --------------------------------------------------------------------------- */ @@ -730,30 +728,29 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) * none. */ static void scic_sds_controller_transition_to_ready( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, enum sci_status status) { - if (this_controller->parent.state_machine.current_state_id - == SCI_BASE_CONTROLLER_STATE_STARTING) { + struct isci_host *ihost = sci_object_get_association(scic); + + if (scic->parent.state_machine.current_state_id == + SCI_BASE_CONTROLLER_STATE_STARTING) { /* * We move into the ready state, because some of the phys/ports - * may be up and operational. */ + * may be up and operational. + */ sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(this_controller), - SCI_BASE_CONTROLLER_STATE_READY - ); + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_READY); - isci_event_controller_start_complete(this_controller, status); + isci_host_start_complete(ihost, status); } } -/** - * This method is the general timeout handler for the controller. It will take - * the correct timetout action based on the current controller state - */ -void scic_sds_controller_timeout_handler( - struct scic_sds_controller *scic) +void scic_sds_controller_timeout_handler(void *_scic) { + struct scic_sds_controller *scic = _scic; + struct isci_host *ihost = sci_object_get_association(scic); enum sci_base_controller_states current_state; current_state = sci_base_state_machine_get_state( @@ -766,7 +763,7 @@ void scic_sds_controller_timeout_handler( sci_base_state_machine_change_state( scic_sds_controller_get_base_state_machine(scic), SCI_BASE_CONTROLLER_STATE_FAILED); - isci_event_controller_stop_complete(scic, SCI_FAILURE_TIMEOUT); + isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); } else /* / @todo Now what do we want to do in this case? */ dev_err(scic_to_dev(scic), "%s: Controller timer fired when controller was not " @@ -803,37 +800,21 @@ enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) return status; } -/** - * - * - * - */ -static void scic_sds_controller_phy_timer_start( - struct scic_sds_controller *this_controller) +static inline void scic_sds_controller_phy_timer_start( + struct scic_sds_controller *scic) { - isci_event_timer_start( - this_controller, - this_controller->phy_startup_timer, - SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT - ); + isci_timer_start(scic->phy_startup_timer, + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT); - this_controller->phy_startup_timer_pending = true; + scic->phy_startup_timer_pending = true; } -/** - * - * - * - */ -void scic_sds_controller_phy_timer_stop( - struct scic_sds_controller *this_controller) +inline void scic_sds_controller_phy_timer_stop( + struct scic_sds_controller *scic) { - isci_event_timer_stop( - this_controller, - this_controller->phy_startup_timer - ); + isci_timer_stop(scic->phy_startup_timer); - this_controller->phy_startup_timer_pending = false; + scic->phy_startup_timer_pending = false; } /** @@ -1009,19 +990,17 @@ enum sci_status scic_sds_controller_stop_devices( * ****************************************************************************- */ /** + * This function starts the power control timer for this controller object. * - * - * This method starts the power control timer for this controller object. + * @param scic */ -static void scic_sds_controller_power_control_timer_start( - struct scic_sds_controller *this_controller) +static inline void scic_sds_controller_power_control_timer_start( + struct scic_sds_controller *scic) { - isci_event_timer_start( - this_controller, this_controller->power_control.timer, - SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL - ); + isci_timer_start(scic->power_control.timer, + SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); - this_controller->power_control.timer_started = true; + scic->power_control.timer_started = true; } /** @@ -1029,20 +1008,22 @@ static void scic_sds_controller_power_control_timer_start( * * @param scic */ -void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic) +static inline void scic_sds_controller_power_control_timer_stop( + struct scic_sds_controller *scic) { if (scic->power_control.timer_started) { - isci_event_timer_stop(scic, scic->power_control.timer); + isci_timer_stop(scic->power_control.timer); scic->power_control.timer_started = false; } } /** - * This method stops and starts the power control timer for this controller object. + * This method stops and starts the power control timer for this controller + * object. * * @param scic */ -void scic_sds_controller_power_control_timer_restart( +static inline void scic_sds_controller_power_control_timer_restart( struct scic_sds_controller *scic) { scic_sds_controller_power_control_timer_stop(scic); @@ -2893,51 +2874,41 @@ static enum sci_status scic_sds_controller_general_reset_handler( * * RESET STATE HANDLERS * ***************************************************************************** */ -/** - * - * @controller: This is the struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * - * This method is the struct scic_sds_controller initialize handler for the reset - * state. - Currently this function does nothing enum sci_status SCI_FAILURE This - * function is not yet implemented and is a valid request from the reset state. - */ -static enum sci_status scic_sds_controller_reset_state_initialize_handler( - struct sci_base_controller *controller) +static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct sci_base_controller *base_scic) { - u32 index; enum sci_status result = SCI_SUCCESS; - struct scic_sds_controller *this_controller; + struct scic_sds_controller *scic; + struct isci_host *ihost; + u32 index; - this_controller = (struct scic_sds_controller *)controller; + scic = container_of(base_scic, typeof(*scic), parent); + ihost = sci_object_get_association(scic); sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(this_controller), - SCI_BASE_CONTROLLER_STATE_INITIALIZING - ); + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_INITIALIZING); - this_controller->timeout_timer = isci_event_timer_create( - this_controller, - (void (*)(void *))scic_sds_controller_timeout_handler, - (void (*)(void *))controller); + scic->timeout_timer = isci_timer_create(ihost, + scic, + scic_sds_controller_timeout_handler); - scic_sds_controller_initialize_phy_startup(this_controller); + scic_sds_controller_initialize_phy_startup(scic); - scic_sds_controller_initialize_power_control(this_controller); + scic_sds_controller_initialize_power_control(scic); /* * There is nothing to do here for B0 since we do not have to * program the AFE registers. * / @todo The AFE settings are supposed to be correct for the B0 but * / presently they seem to be wrong. */ - scic_sds_controller_afe_initialization(this_controller); + scic_sds_controller_afe_initialization(scic); - if (SCI_SUCCESS == result) { + if (result == SCI_SUCCESS) { u32 status; u32 terminate_loop; /* Take the hardware out of reset */ - SMU_SMUSRCR_WRITE(this_controller, 0x00000000); + SMU_SMUSRCR_WRITE(scic, 0x00000000); /* * / @todo Provide meaningfull error code for hardware failure @@ -2948,11 +2919,11 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler( while (terminate_loop-- && (result != SCI_SUCCESS)) { /* Loop until the hardware reports success */ udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME); - status = SMU_SMUCSR_READ(this_controller); + status = SMU_SMUCSR_READ(scic); - if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) { + if ((status & SCU_RAM_INIT_COMPLETED) == + SCU_RAM_INIT_COMPLETED) result = SCI_SUCCESS; - } } } @@ -2965,39 +2936,42 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler( /* * Determine what are the actaul device capacities that the * hardware will support */ - device_context_capacity = SMU_DCC_READ(this_controller); + device_context_capacity = SMU_DCC_READ(scic); - max_supported_ports = - smu_dcc_get_max_ports(device_context_capacity); - max_supported_devices = - smu_dcc_get_max_remote_node_context(device_context_capacity); - max_supported_io_requests = - smu_dcc_get_max_task_context(device_context_capacity); + max_supported_ports = smu_dcc_get_max_ports(device_context_capacity); + max_supported_devices = smu_dcc_get_max_remote_node_context(device_context_capacity); + max_supported_io_requests = smu_dcc_get_max_task_context(device_context_capacity); - /* Make all PEs that are unassigned match up with the logical ports */ + /* + * Make all PEs that are unassigned match up with the + * logical ports + */ for (index = 0; index < max_supported_ports; index++) { - scu_register_write( - this_controller, - this_controller->scu_registers->peg0.ptsg.protocol_engine[index], - index - ); + struct scu_port_task_scheduler_group_registers *ptsg = + &scic->scu_registers->peg0.ptsg; + + scu_register_write(scic, + ptsg->protocol_engine[index], + index); } /* Record the smaller of the two capacity values */ - this_controller->logical_port_entries = - min(max_supported_ports, this_controller->logical_port_entries); + scic->logical_port_entries = + min(max_supported_ports, scic->logical_port_entries); - this_controller->task_context_entries = - min(max_supported_io_requests, this_controller->task_context_entries); + scic->task_context_entries = + min(max_supported_io_requests, + scic->task_context_entries); - this_controller->remote_node_entries = - min(max_supported_devices, this_controller->remote_node_entries); + scic->remote_node_entries = + min(max_supported_devices, scic->remote_node_entries); /* * Now that we have the correct hardware reported minimum values * build the MDL for the controller. Default to a performance - * configuration. */ - scic_controller_set_mode(this_controller, SCI_MODE_SPEED); + * configuration. + */ + scic_controller_set_mode(scic, SCI_MODE_SPEED); } /* Initialize hardware PCI Relaxed ordering in DMA engines */ @@ -3005,66 +2979,62 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler( u32 dma_configuration; /* Configure the payload DMA */ - dma_configuration = SCU_PDMACR_READ(this_controller); - dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - SCU_PDMACR_WRITE(this_controller, dma_configuration); + dma_configuration = SCU_PDMACR_READ(scic); + dma_configuration |= + SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); + SCU_PDMACR_WRITE(scic, dma_configuration); /* Configure the control DMA */ - dma_configuration = SCU_CDMACR_READ(this_controller); - dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - SCU_CDMACR_WRITE(this_controller, dma_configuration); + dma_configuration = SCU_CDMACR_READ(scic); + dma_configuration |= + SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); + SCU_CDMACR_WRITE(scic, dma_configuration); } /* * Initialize the PHYs before the PORTs because the PHY registers - * are accessed during the port initialization. */ + * are accessed during the port initialization. + */ if (result == SCI_SUCCESS) { /* Initialize the phys */ for (index = 0; (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS); index++) { result = scic_sds_phy_initialize( - &this_controller->phy_table[index], - &this_controller->scu_registers->peg0.pe[index].tl, - &this_controller->scu_registers->peg0.pe[index].ll - ); + &scic->phy_table[index], + &scic->scu_registers->peg0.pe[index].tl, + &scic->scu_registers->peg0.pe[index].ll); } } if (result == SCI_SUCCESS) { /* Initialize the logical ports */ for (index = 0; - (index < this_controller->logical_port_entries) - && (result == SCI_SUCCESS); + (index < scic->logical_port_entries) && + (result == SCI_SUCCESS); index++) { result = scic_sds_port_initialize( - &this_controller->port_table[index], - &this_controller->scu_registers->peg0.ptsg.port[index], - &this_controller->scu_registers->peg0.ptsg.protocol_engine, - &this_controller->scu_registers->peg0.viit[index] - ); + &scic->port_table[index], + &scic->scu_registers->peg0.ptsg.port[index], + &scic->scu_registers->peg0.ptsg.protocol_engine, + &scic->scu_registers->peg0.viit[index]); } } - if (SCI_SUCCESS == result) { + if (result == SCI_SUCCESS) result = scic_sds_port_configuration_agent_initialize( - this_controller, - &this_controller->port_agent - ); - } + scic, + &scic->port_agent); /* Advance the controller state machine */ - if (result == SCI_SUCCESS) { + if (result == SCI_SUCCESS) sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(this_controller), - SCI_BASE_CONTROLLER_STATE_INITIALIZED - ); - } else { + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_INITIALIZED); + else sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(this_controller), - SCI_BASE_CONTROLLER_STATE_FAILED - ); - } + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_FAILED); return result; } @@ -3076,13 +3046,14 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler( /** * - * @controller: This is the struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. + * @controller: This is the struct sci_base_controller object which is cast + * into a struct scic_sds_controller object. * @timeout: This is the allowed time for the controller object to reach the * started state. * - * This method is the struct scic_sds_controller start handler for the initialized - * state. - Validate we have a good memory descriptor table - Initialze the + * This function is the struct scic_sds_controller start handler for the + * initialized state. + * - Validate we have a good memory descriptor table - Initialze the * physical memory before programming the hardware - Program the SCU hardware * with the physical memory addresses passed in the memory descriptor table. - * Initialzie the TCi pool - Initialize the RNi pool - Initialize the @@ -3099,70 +3070,74 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( { u16 index; enum sci_status result; - struct scic_sds_controller *this_controller; + struct scic_sds_controller *scic; - this_controller = (struct scic_sds_controller *)controller; + scic = (struct scic_sds_controller *)controller; - /* Make sure that the SCI User filled in the memory descriptor table correctly */ - result = scic_sds_controller_validate_memory_descriptor_table(this_controller); + /* + * Make sure that the SCI User filled in the memory descriptor + * table correctly + */ + result = scic_sds_controller_validate_memory_descriptor_table(scic); if (result == SCI_SUCCESS) { - /* The memory descriptor list looks good so program the hardware */ - scic_sds_controller_ram_initialization(this_controller); + /* + * The memory descriptor list looks good so program the + * hardware + */ + scic_sds_controller_ram_initialization(scic); } if (result == SCI_SUCCESS) { /* Build the TCi free pool */ - sci_pool_initialize(this_controller->tci_pool); - for (index = 0; index < this_controller->task_context_entries; index++) { - sci_pool_put(this_controller->tci_pool, index); - } + sci_pool_initialize(scic->tci_pool); + for (index = 0; index < scic->task_context_entries; index++) + sci_pool_put(scic->tci_pool, index); /* Build the RNi free pool */ scic_sds_remote_node_table_initialize( - &this_controller->available_remote_nodes, - this_controller->remote_node_entries - ); + &scic->available_remote_nodes, + scic->remote_node_entries); } if (result == SCI_SUCCESS) { /* - * Before anything else lets make sure we will not be interrupted - * by the hardware. */ - scic_controller_disable_interrupts(this_controller); + * Before anything else lets make sure we will not be + * interrupted by the hardware. + */ + scic_controller_disable_interrupts(scic); /* Enable the port task scheduler */ - scic_sds_controller_enable_port_task_scheduler(this_controller); + scic_sds_controller_enable_port_task_scheduler(scic); - /* Assign all the task entries to this controller physical function */ - scic_sds_controller_assign_task_entries(this_controller); + /* Assign all the task entries to scic physical function */ + scic_sds_controller_assign_task_entries(scic); /* Now initialze the completion queue */ - scic_sds_controller_initialize_completion_queue(this_controller); + scic_sds_controller_initialize_completion_queue(scic); /* Initialize the unsolicited frame queue for use */ - scic_sds_controller_initialize_unsolicited_frame_queue(this_controller); + scic_sds_controller_initialize_unsolicited_frame_queue(scic); } /* Start all of the ports on this controller */ - for (index = 0; index < this_controller->logical_port_entries && - result == SCI_SUCCESS; index++) { - struct scic_sds_port *sci_port = &this_controller->port_table[index]; + for (index = 0; + (index < scic->logical_port_entries) && (result == SCI_SUCCESS); + index++) { + struct scic_sds_port *sci_port = &scic->port_table[index]; - result = sci_port->state_handlers->parent.start_handler(&sci_port->parent); + result = sci_port->state_handlers->parent.start_handler( + &sci_port->parent); } if (result == SCI_SUCCESS) { - scic_sds_controller_start_next_phy(this_controller); + scic_sds_controller_start_next_phy(scic); - isci_event_timer_start(this_controller, - this_controller->timeout_timer, - timeout); + isci_timer_start(scic->timeout_timer, timeout); sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(this_controller), - SCI_BASE_CONTROLLER_STATE_STARTING - ); + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_STARTING); } return result; @@ -3241,18 +3216,14 @@ static enum sci_status scic_sds_controller_ready_state_stop_handler( struct sci_base_controller *controller, u32 timeout) { - struct scic_sds_controller *this_controller; - - this_controller = (struct scic_sds_controller *)controller; + struct scic_sds_controller *scic = + (struct scic_sds_controller *)controller; - isci_event_timer_start(this_controller, - this_controller->timeout_timer, - timeout); + isci_timer_start(scic->timeout_timer, timeout); sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(this_controller), - SCI_BASE_CONTROLLER_STATE_STOPPING - ); + scic_sds_controller_get_base_state_machine(scic), + SCI_BASE_CONTROLLER_STATE_STOPPING); return SCI_SUCCESS; } @@ -3689,12 +3660,12 @@ static void scic_sds_controller_initial_state_enter( * from the SCI_BASE_CONTROLLER_STATE_STARTING. - This function stops the * controller starting timeout timer. none */ -static void scic_sds_controller_starting_state_exit( +static inline void scic_sds_controller_starting_state_exit( struct sci_base_object *object) { struct scic_sds_controller *scic = (struct scic_sds_controller *)object; - isci_event_timer_stop(scic, scic->timeout_timer); + isci_timer_stop(scic->timeout_timer); } /** @@ -3762,21 +3733,20 @@ static void scic_sds_controller_stopping_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller - * object. + * @object: This is the struct sci_base_object which is cast to a struct + * scic_sds_controller object. * - * This method implements the actions taken by the struct scic_sds_controller on exit - * from the SCI_BASE_CONTROLLER_STATE_STOPPING. - This function stops the - * controller stopping timeout timer. none + * This funciton implements the actions taken by the struct scic_sds_controller + * on exit from the SCI_BASE_CONTROLLER_STATE_STOPPING. - + * This function stops the controller stopping timeout timer. */ -static void scic_sds_controller_stopping_state_exit( +static inline void scic_sds_controller_stopping_state_exit( struct sci_base_object *object) { - struct scic_sds_controller *this_controller; - - this_controller = (struct scic_sds_controller *)object; + struct scic_sds_controller *scic = + (struct scic_sds_controller *)object; - isci_event_timer_stop(this_controller, this_controller->timeout_timer); + isci_timer_stop(scic->timeout_timer); } /** diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 6386a64896c0..f426324bf3a9 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -681,8 +681,7 @@ void scic_sds_controller_copy_task_context( struct scic_sds_controller *this_controller, struct scic_sds_request *this_request); -void scic_sds_controller_timeout_handler( - struct scic_sds_controller *controller); +void scic_sds_controller_timeout_handler(void *controller); void scic_sds_controller_initialize_power_control( struct scic_sds_controller *this_controller); diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 27174589a863..225e67a9e7b1 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -366,18 +366,23 @@ void scic_sds_phy_set_port( */ enum sci_status scic_sds_phy_initialize( struct scic_sds_phy *sci_phy, - struct scu_transport_layer_registers __iomem *transport_layer_registers, - struct scu_link_layer_registers __iomem *link_layer_registers) + struct scu_transport_layer_registers __iomem *transport_layer_registers, + struct scu_link_layer_registers __iomem *link_layer_registers) { + struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); + struct isci_host *ihost = sci_object_get_association(scic); + /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = isci_event_timer_create( - scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_sata_timeout, - sci_phy - ); + sci_phy->sata_timeout_timer = + isci_timer_create( + ihost, + sci_phy, + scic_sds_phy_sata_timeout); /* Perfrom the initialization of the TL hardware */ - scic_sds_phy_transport_layer_initialization(sci_phy, transport_layer_registers); + scic_sds_phy_transport_layer_initialization( + sci_phy, + transport_layer_registers); /* Perofrm the initialization of the PE hardware */ scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers); @@ -387,8 +392,7 @@ enum sci_status scic_sds_phy_initialize( * transition to the stopped state. */ sci_base_state_machine_change_state( scic_sds_phy_get_base_state_machine(sci_phy), - SCI_BASE_PHY_STATE_STOPPED - ); + SCI_BASE_PHY_STATE_STOPPED); return SCI_SUCCESS; } @@ -1742,49 +1746,42 @@ static void scic_sds_phy_starting_await_sata_power_substate_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_phy object. * - * This method will perform the actions required by the struct scic_sds_phy on + * This function will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - Set the * struct scic_sds_phy object state handlers for this state. none */ static void scic_sds_phy_starting_await_sata_phy_substate_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN - ); + sci_phy, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); - isci_event_timer_start( - scic_sds_phy_get_controller(this_phy), - this_phy->sata_timeout_timer, - SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT - ); + isci_timer_start(sci_phy->sata_timeout_timer, + SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_phy object. * - * This method will perform the actions required by the struct scic_sds_phy on exiting + * This method will perform the actions required by the struct scic_sds_phy + * on exiting * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer * that was started on entry to await sata phy event notification none */ -static void scic_sds_phy_starting_await_sata_phy_substate_exit( +static inline void scic_sds_phy_starting_await_sata_phy_substate_exit( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; - this_phy = (struct scic_sds_phy *)object; - - isci_event_timer_stop( - scic_sds_phy_get_controller(this_phy), - this_phy->sata_timeout_timer - ); + isci_timer_stop(sci_phy->sata_timeout_timer); } /** @@ -1798,104 +1795,92 @@ static void scic_sds_phy_starting_await_sata_phy_substate_exit( static void scic_sds_phy_starting_await_sata_speed_substate_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN - ); + sci_phy, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); - isci_event_timer_start( - scic_sds_phy_get_controller(this_phy), - this_phy->sata_timeout_timer, - SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT - ); + isci_timer_start(sci_phy->sata_timeout_timer, + SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_phy object. * - * This method will perform the actions required by the struct scic_sds_phy on exiting + * This function will perform the actions required by the + * struct scic_sds_phy on exiting * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer * that was started on entry to await sata phy event notification none */ -static void scic_sds_phy_starting_await_sata_speed_substate_exit( +static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; - this_phy = (struct scic_sds_phy *)object; - - isci_event_timer_stop( - scic_sds_phy_get_controller(this_phy), - this_phy->sata_timeout_timer - ); + isci_timer_stop(sci_phy->sata_timeout_timer); } /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_phy object. * - * This method will perform the actions required by the struct scic_sds_phy on + * This function will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Set the - * struct scic_sds_phy object state handlers for this state. - Start the SIGNATURE FIS + * struct scic_sds_phy object state handlers for this state. + * - Start the SIGNATURE FIS * timeout timer none */ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter( struct sci_base_object *object) { bool continue_to_ready_state; - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF - ); + sci_phy, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); continue_to_ready_state = scic_sds_port_link_detected( - this_phy->owning_port, - this_phy - ); + sci_phy->owning_port, + sci_phy); if (continue_to_ready_state) { /* - * Clear the PE suspend condition so we can actually receive SIG FIS - * The hardware will not respond to the XRDY until the PE suspend - * condition is cleared. */ - scic_sds_phy_resume(this_phy); + * Clear the PE suspend condition so we can actually + * receive SIG FIS + * The hardware will not respond to the XRDY until the PE + * suspend condition is cleared. + */ + scic_sds_phy_resume(sci_phy); - isci_event_timer_start( - scic_sds_phy_get_controller(this_phy), - this_phy->sata_timeout_timer, - SCIC_SDS_SIGNATURE_FIS_TIMEOUT - ); - } else { - this_phy->is_in_link_training = false; - } + isci_timer_start(sci_phy->sata_timeout_timer, + SCIC_SDS_SIGNATURE_FIS_TIMEOUT); + } else + sci_phy->is_in_link_training = false; } /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_phy object. * - * This method will perform the actions required by the struct scic_sds_phy on exiting + * This function will perform the actions required by the + * struct scic_sds_phy on exiting * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Stop the SIGNATURE * FIS timeout timer. none */ -static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( +static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; - isci_event_timer_stop( - scic_sds_phy_get_controller(this_phy), - this_phy->sata_timeout_timer - ); + isci_timer_stop(sci_phy->sata_timeout_timer); } /** @@ -2158,27 +2143,30 @@ enum sci_status scic_sds_phy_default_consume_power_handler( /** * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. + * @phy: This is the struct sci_base_phy object which is cast into a + * struct scic_sds_phy object. * - * This method takes the struct scic_sds_phy from a stopped state and attempts to - * start it. - The phy state machine is transitioned to the + * This method takes the struct scic_sds_phy from a stopped state and + * attempts to start it. - The phy state machine is transitioned to the * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS */ -static enum sci_status scic_sds_phy_stopped_state_start_handler(struct sci_base_phy *phy) +static enum sci_status scic_sds_phy_stopped_state_start_handler( + struct sci_base_phy *phy) { - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)phy; + struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)phy; + struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); + struct isci_host *ihost = sci_object_get_association(scic); /* Create the SIGNATURE FIS Timeout timer for this phy */ - this_phy->sata_timeout_timer = isci_event_timer_create( - scic_sds_phy_get_controller(this_phy), - scic_sds_phy_sata_timeout, this_phy); + sci_phy->sata_timeout_timer = + isci_timer_create( + ihost, + sci_phy, + scic_sds_phy_sata_timeout); - if (this_phy->sata_timeout_timer != NULL) { + if (sci_phy->sata_timeout_timer != NULL) { sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), + scic_sds_phy_get_base_state_machine(sci_phy), SCI_BASE_PHY_STATE_STARTING); } @@ -2525,14 +2513,16 @@ static void scic_sds_phy_initial_state_enter( * @object: This is the struct sci_base_object which is cast to a * struct scic_sds_phy object. * - * This method will perform the actions required by the struct scic_sds_phy on + * This function will perform the actions required by the struct scic_sds_phy on * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state * handlers for the phy object base state machine initial state. - The SCU * hardware is requested to stop the protocol engine. none */ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) { - struct scic_sds_phy *sci_phy; + struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); + struct isci_host *ihost = sci_object_get_association(scic); sci_phy = (struct scic_sds_phy *)object; @@ -2541,11 +2531,11 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) * reset state */ - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STOPPED); + scic_sds_phy_set_base_state_handlers(sci_phy, + SCI_BASE_PHY_STATE_STOPPED); if (sci_phy->sata_timeout_timer != NULL) { - isci_event_timer_destroy(scic_sds_phy_get_controller(sci_phy), - sci_phy->sata_timeout_timer); + isci_del_timer(ihost, sci_phy->sata_timeout_timer); sci_phy->sata_timeout_timer = NULL; } @@ -2554,9 +2544,10 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) if (sci_phy->parent.state_machine.previous_state_id != SCI_BASE_PHY_STATE_INITIAL) - scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), - sci_phy); + scic_sds_controller_link_down( + scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy); } /** diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index a41fe426ac26..3ae0f0d80f1f 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -738,34 +738,32 @@ void scic_sds_port_setup_transports( * @do_notify_user: This parameter specifies whether to inform the user (via * scic_cb_port_link_up()) as to the fact that a new phy as become ready. * - * This method will activate the phy in the port. Activation includes: - adding + * This function will activate the phy in the port. + * Activation includes: - adding * the phy to the port - enabling the Protocol Engine in the silicon. - * notifying the user that the link is up. none */ -void scic_sds_port_activate_phy( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy, - bool do_notify_user) +void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user) { - struct scic_sds_controller *controller; + struct scic_sds_controller *scic = + scic_sds_port_get_controller(sci_port); struct sci_sas_identify_address_frame_protocols protocols; + struct isci_host *ihost = sci_object_get_association(scic); - controller = scic_sds_port_get_controller(this_port); - scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols); + scic_sds_phy_get_attached_phy_protocols(sci_phy, &protocols); /* If this is sata port then the phy has already been resumed */ - if (!protocols.u.bits.stp_target) { - scic_sds_phy_resume(the_phy); - } + if (!protocols.u.bits.stp_target) + scic_sds_phy_resume(sci_phy); - this_port->active_phy_mask |= 1 << the_phy->phy_index; + sci_port->active_phy_mask |= 1 << sci_phy->phy_index; - scic_sds_controller_clear_invalid_phy(controller, the_phy); + scic_sds_controller_clear_invalid_phy(scic, sci_phy); if (do_notify_user == true) - isci_event_port_link_up(this_port->owning_controller, - this_port, - the_phy); + isci_port_link_up(ihost, sci_port, sci_phy); } /** @@ -773,27 +771,30 @@ void scic_sds_port_activate_phy( * @this_port: This is the port on which the phy should be deactivated. * @the_phy: This is the specific phy that is no longer active in the port. * @do_notify_user: This parameter specifies whether to inform the user (via - * isci_event_port_link_down()) as to the fact that a new phy as become + * isci_port_link_down()) as to the fact that a new phy as become * ready. * - * This method will deactivate the supplied phy in the port. none + * This function will deactivate the supplied phy in the port. none */ -void scic_sds_port_deactivate_phy( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy, - bool do_notify_user) +void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user) { - this_port->active_phy_mask &= ~(1 << the_phy->phy_index); + struct scic_sds_controller *scic = + scic_sds_port_get_controller(sci_port); + struct isci_port *iport = sci_object_get_association(sci_port); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_phy *iphy = sci_object_get_association(sci_phy); + + sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); - the_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; + sci_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; /* Re-assign the phy back to the LP as if it were a narrow port */ - SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index); + SCU_PCSPExCR_WRITE(sci_port, sci_phy->phy_index, sci_phy->phy_index); if (do_notify_user == true) - isci_event_port_link_down(this_port->owning_controller, - this_port, - the_phy); + isci_port_link_down(ihost, iphy, iport); } /** @@ -801,22 +802,24 @@ void scic_sds_port_deactivate_phy( * @this_port: This is the port on which the phy should be disabled. * @the_phy: This is the specific phy which to disabled. * - * This method will disable the phy and report that the phy is not valid for + * This function will disable the phy and report that the phy is not valid for * this port object. None */ static void scic_sds_port_invalid_link_up( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - struct scic_sds_controller *controller = scic_sds_port_get_controller(this_port); + struct scic_sds_controller *scic = + scic_sds_port_get_controller(sci_port); /* - * Check to see if we have alreay reported this link as bad and if not go - * ahead and tell the SCI_USER that we have discovered an invalid link. */ - if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0) { - scic_sds_controller_set_invalid_phy(controller, the_phy); - - isci_event_port_invalid_link_up(controller, this_port, the_phy); + * Check to see if we have alreay reported this link as bad and if + * not go ahead and tell the SCI_USER that we have discovered an + * invalid link. + */ + if ((scic->invalid_phy_mask & (1 << sci_phy->phy_index)) == 0) { + scic_sds_controller_set_invalid_phy(scic, sci_phy); + isci_port_invalid_link_up(scic, sci_port, sci_phy); } } @@ -950,44 +953,48 @@ enum sci_status scic_sds_port_complete_io( */ static void scic_sds_port_timeout_handler(void *port) { - struct scic_sds_port *this_port = port; + struct scic_sds_port *sci_port = port; u32 current_state; current_state = sci_base_state_machine_get_state( - &this_port->parent.state_machine); + &sci_port->parent.state_machine); if (current_state == SCI_BASE_PORT_STATE_RESETTING) { /* - * if the port is still in the resetting state then the timeout fired - * before the reset completed. */ + * if the port is still in the resetting state then the + * timeout fired before the reset completed. + */ sci_base_state_machine_change_state( - &this_port->parent.state_machine, - SCI_BASE_PORT_STATE_FAILED - ); + &sci_port->parent.state_machine, + SCI_BASE_PORT_STATE_FAILED); } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { /* * if the port is stopped then the start request failed - * In this case stay in the stopped state. */ - dev_err(sciport_to_dev(this_port), + * In this case stay in the stopped state. + */ + dev_err(sciport_to_dev(sci_port), "%s: SCIC Port 0x%p failed to stop before tiemout.\n", __func__, - this_port); + sci_port); } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { - /* if the port is still stopping then the stop has not completed */ - isci_event_port_stop_complete( - scic_sds_port_get_controller(this_port), - port, - SCI_FAILURE_TIMEOUT - ); + /* + * if the port is still stopping then the stop has not + * completed + */ + isci_port_stop_complete( + scic_sds_port_get_controller(sci_port), + sci_port, + SCI_FAILURE_TIMEOUT); } else { /* - * The port is in the ready state and we have a timer reporting a timeout - * this should not happen. */ - dev_err(sciport_to_dev(this_port), + * The port is in the ready state and we have a timer + * reporting a timeout this should not happen. + */ + dev_err(sciport_to_dev(sci_port), "%s: SCIC Port 0x%p is processing a timeout operation " "in state %d.\n", __func__, - this_port, + sci_port, current_state); } } @@ -1067,13 +1074,14 @@ enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( * */ void scic_sds_port_broadcast_change_received( - struct scic_sds_port *this_port, - struct scic_sds_phy *this_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = sci_object_get_association(scic); + /* notify the user. */ - isci_event_port_bc_change_primitive_received( - this_port->owning_controller, this_port, this_phy - ); + isci_port_bc_change_received(ihost, sci_port, sci_phy); } @@ -1267,30 +1275,29 @@ static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( * * This method will casue the port to reset. enum sci_status SCI_SUCCESS */ -static enum sci_status scic_sds_port_ready_operational_substate_reset_handler( - struct sci_base_port *port, - u32 timeout) +static enum +sci_status scic_sds_port_ready_operational_substate_reset_handler( + struct sci_base_port *port, + u32 timeout) { enum sci_status status = SCI_FAILURE_INVALID_PHY; u32 phy_index; - struct scic_sds_port *this_port = (struct scic_sds_port *)port; + struct scic_sds_port *sci_port = (struct scic_sds_port *)port; struct scic_sds_phy *selected_phy = NULL; /* Select a phy on which we can send the hard reset request. */ - for ( - phy_index = 0; - (phy_index < SCI_MAX_PHYS) - && (selected_phy == NULL); - phy_index++ - ) { - selected_phy = this_port->phy_table[phy_index]; - - if ( - (selected_phy != NULL) - && !scic_sds_port_active_phy(this_port, selected_phy) - ) { - /* We found a phy but it is not ready select different phy */ + for (phy_index = 0; + (phy_index < SCI_MAX_PHYS) && (selected_phy == NULL); + phy_index++) { + selected_phy = sci_port->phy_table[phy_index]; + + if ((selected_phy != NULL) && + !scic_sds_port_active_phy(sci_port, selected_phy)) { + /* + * We found a phy but it is not ready select + * different phy + */ selected_phy = NULL; } } @@ -1300,18 +1307,13 @@ static enum sci_status scic_sds_port_ready_operational_substate_reset_handler( status = scic_sds_phy_reset(selected_phy); if (status == SCI_SUCCESS) { - isci_event_timer_start( - scic_sds_port_get_controller(this_port), - this_port->timer_handle, - timeout - ); - - this_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; + isci_timer_start(sci_port->timer_handle, timeout); + sci_port->not_ready_reason = + SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; sci_base_state_machine_change_state( - &this_port->parent.state_machine, - SCI_BASE_PORT_STATE_RESETTING - ); + &sci_port->parent.state_machine, + SCI_BASE_PORT_STATE_RESETTING); } } @@ -1686,10 +1688,11 @@ static void scic_sds_port_ready_substate_waiting_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_port object. * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets + * This function will perform the actions required by the struct scic_sds_port + * on entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets * the state handlers for the port object, notifies the SCI User that the port * is ready, and resumes port operations. none */ @@ -1697,32 +1700,34 @@ static void scic_sds_port_ready_substate_operational_enter( struct sci_base_object *object) { u32 index; - struct scic_sds_port *this_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_controller *scic = + scic_sds_port_get_controller(sci_port); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_port *iport = sci_object_get_association(sci_port); scic_sds_port_set_ready_state_handlers( - this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL - ); + sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); - isci_event_port_ready( - scic_sds_port_get_controller(this_port), this_port - ); + isci_port_ready(ihost, iport); for (index = 0; index < SCI_MAX_PHYS; index++) { - if (this_port->phy_table[index] != NULL) { + if (sci_port->phy_table[index] != NULL) scic_sds_port_write_phy_assignment( - this_port, this_port->phy_table[index] - ); - } + sci_port, + sci_port->phy_table[index]); } - scic_sds_port_update_viit_entry(this_port); + scic_sds_port_update_viit_entry(sci_port); - scic_sds_port_resume_port_task_scheduler(this_port); + scic_sds_port_resume_port_task_scheduler(sci_port); - /* Post the dummy task for the port so the hardware can schedule + /* + * Post the dummy task for the port so the hardware can schedule * io correctly */ - scic_sds_port_post_dummy_request(this_port); + scic_sds_port_post_dummy_request(sci_port); } /** @@ -1736,20 +1741,20 @@ static void scic_sds_port_ready_substate_operational_enter( static void scic_sds_port_ready_substate_operational_exit( struct sci_base_object *object) { - struct scic_sds_port *this_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_controller *scic = + scic_sds_port_get_controller(sci_port); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_port *iport = sci_object_get_association(sci_port); -/* - * Kill the dummy task for this port if it has not yet posted - * the hardware will treat this as a NOP and just return abort - * complete. - */ - scic_sds_port_abort_dummy_request(this_port); + /* + * Kill the dummy task for this port if it has not yet posted + * the hardware will treat this as a NOP and just return abort + * complete. + */ + scic_sds_port_abort_dummy_request(sci_port); - isci_event_port_not_ready( - scic_sds_port_get_controller(this_port), - this_port, - this_port->not_ready_reason - ); + isci_port_not_ready(ihost, iport); } /* @@ -1759,7 +1764,8 @@ static void scic_sds_port_ready_substate_operational_exit( /** * scic_sds_port_ready_substate_configuring_enter() - - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports @@ -1768,29 +1774,26 @@ static void scic_sds_port_ready_substate_operational_exit( static void scic_sds_port_ready_substate_configuring_enter( struct sci_base_object *object) { - struct scic_sds_port *this_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_controller *scic = + scic_sds_port_get_controller(sci_port); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_port *iport = sci_object_get_association(sci_port); scic_sds_port_set_ready_state_handlers( - this_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); + sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); - if (this_port->active_phy_mask == 0) { - isci_event_port_not_ready( - scic_sds_port_get_controller(this_port), - this_port, - SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS - ); + if (sci_port->active_phy_mask == 0) { + isci_port_not_ready(ihost, iport); sci_base_state_machine_change_state( - &this_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING - ); - } else if (this_port->started_request_count == 0) { + &sci_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + } else if (sci_port->started_request_count == 0) sci_base_state_machine_change_state( - &this_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL - ); - } + &sci_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); } static void scic_sds_port_ready_substate_configuring_exit( @@ -2165,42 +2168,52 @@ static enum sci_status scic_sds_port_general_complete_io_handler( /** * scic_sds_port_stopped_state_start_handler() - stop a port from "started" * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. + * @port: This is the struct sci_base_port object which is cast into a + * struct scic_sds_port object. * - * This method takes the struct scic_sds_port from a stopped state and attempts to - * start it. To start a port it must have no assiged devices and it must have - * at least one phy assigned to it. If those conditions are met then the port - * can transition to the ready state. enum sci_status - * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This struct scic_sds_port object could - * not be started because the port configuration is not valid. SCI_SUCCESS the - * start request is successful and the struct scic_sds_port object has transitioned to - * the SCI_BASE_PORT_STATE_READY. + * This function takes the struct scic_sds_port from a stopped state and + * attempts to start it. To start a port it must have no assiged devices and + * it must have at least one phy assigned to it. If those conditions are + * met then the port can transition to the ready state. + * enum sci_status + * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION + * This struct scic_sds_port object could not be started because the port + * configuration is not valid. + * SCI_SUCCESS + * the start request is successful and the struct scic_sds_port object + * has transitioned to the SCI_BASE_PORT_STATE_READY. */ -static enum sci_status scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port) +static enum sci_status +scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port) { - struct scic_sds_port *sci_port = container_of(base_port, typeof(*sci_port), parent); + struct scic_sds_port *sci_port = + container_of(base_port, typeof(*sci_port), parent); struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = sci_object_get_association(scic); enum sci_status status = SCI_SUCCESS; u32 phy_mask; if (sci_port->assigned_device_count > 0) { /* - * / @todo This is a start failure operation because there are still - * / devices assigned to this port. There must be no devices - * / assigned to a port on a start operation. */ + * @todo This is a start failure operation because + * there are still devices assigned to this port. + * There must be no devices assigned to a port on a + * start operation. + */ return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } - sci_port->timer_handle = isci_event_timer_create(scic, - scic_sds_port_timeout_handler, - sci_port); + sci_port->timer_handle = + isci_timer_create(ihost, + sci_port, + scic_sds_port_timeout_handler); if (!sci_port->timer_handle) return SCI_FAILURE_INSUFFICIENT_RESOURCES; if (sci_port->reserved_rni == SCU_DUMMY_INDEX) { - u16 rni = scic_sds_remote_node_table_allocate_remote_node(&scic->available_remote_nodes, 1); + u16 rni = scic_sds_remote_node_table_allocate_remote_node( + &scic->available_remote_nodes, 1); if (rni != SCU_DUMMY_INDEX) scic_sds_port_construct_dummy_rnc(sci_port, rni); @@ -2715,50 +2728,41 @@ static void scic_sds_port_stopped_state_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state - * handlers for the struct scic_sds_port object, reports the port object as not ready - * and starts the ready substate machine. none + * handlers for the struct scic_sds_port object, reports the port object as + * not ready and starts the ready substate machine. none */ -static void scic_sds_port_ready_state_enter( - struct sci_base_object *object) +static void scic_sds_port_ready_state_enter(struct sci_base_object *object) { - struct scic_sds_port *this_port; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct isci_port *iport = sci_object_get_association(sci_port); + struct scic_sds_controller *scic = + scic_sds_port_get_controller(sci_port); + struct isci_host *ihost = sci_object_get_association(scic); - this_port = (struct scic_sds_port *)object; + /* + * Put the ready state handlers in place though they will not be + * there long + */ + scic_sds_port_set_base_state_handlers(sci_port, + SCI_BASE_PORT_STATE_READY); - /* Put the ready state handlers in place though they will not be there long */ - scic_sds_port_set_base_state_handlers( - this_port, SCI_BASE_PORT_STATE_READY - ); - - if ( - SCI_BASE_PORT_STATE_RESETTING - == this_port->parent.state_machine.previous_state_id - ) { - isci_event_port_hard_reset_complete( - scic_sds_port_get_controller(this_port), - this_port, - SCI_SUCCESS - ); - } else { - /* Notify the caller that the port is not yet ready */ - isci_event_port_not_ready( - scic_sds_port_get_controller(this_port), - this_port, - SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS - ); - } + if (sci_port->parent.state_machine.previous_state_id == + SCI_BASE_PORT_STATE_RESETTING) + isci_port_hard_reset_complete(iport, SCI_SUCCESS); + else /* Notify the caller that the port is not yet ready */ + isci_port_not_ready(ihost, iport); /* Post and suspend the dummy remote node context for this port. */ - scic_sds_port_post_dummy_remote_node(this_port); + scic_sds_port_post_dummy_remote_node(sci_port); /* Start the ready substate machine */ sci_base_state_machine_start( - scic_sds_port_get_ready_substate_machine(this_port) - ); + scic_sds_port_get_ready_substate_machine(sci_port)); } /** @@ -2802,22 +2806,19 @@ static void scic_sds_port_resetting_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_port object. * - * This method will perform the actions required by the struct scic_sds_port on + * This function will perform the actions required by the + * struct scic_sds_port on * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none */ -static void scic_sds_port_resetting_state_exit( +static inline void scic_sds_port_resetting_state_exit( struct sci_base_object *object) { - struct scic_sds_port *this_port; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; - this_port = (struct scic_sds_port *)object; - - isci_event_timer_stop( - scic_sds_port_get_controller(this_port), - this_port->timer_handle - ); + isci_timer_stop(sci_port->timer_handle); } /** @@ -2842,51 +2843,42 @@ static void scic_sds_port_stopping_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_port object. * - * This method will perform the actions required by the struct scic_sds_port on + * This function will perform the actions required by the + * struct scic_sds_port on * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none */ -static void scic_sds_port_stopping_state_exit( - struct sci_base_object *object) +static inline void +scic_sds_port_stopping_state_exit(struct sci_base_object *object) { - struct scic_sds_port *this_port; - - this_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; - isci_event_timer_stop( - scic_sds_port_get_controller(this_port), - this_port->timer_handle - ); + isci_timer_stop(sci_port->timer_handle); - scic_sds_port_destroy_dummy_resources(this_port); + scic_sds_port_destroy_dummy_resources(sci_port); } /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the struct sci_base_object which is cast to a + * struct scic_sds_port object. * - * This method will perform the actions required by the struct scic_sds_port on + * This function will perform the actions required by the + * struct scic_sds_port on * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping * state handlers for the struct scic_sds_port object. none */ -static void scic_sds_port_failed_state_enter( - struct sci_base_object *object) +static void scic_sds_port_failed_state_enter(struct sci_base_object *object) { - struct scic_sds_port *this_port; - - this_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct isci_port *iport = sci_object_get_association(sci_port); - scic_sds_port_set_base_state_handlers( - this_port, - SCI_BASE_PORT_STATE_FAILED - ); + scic_sds_port_set_base_state_handlers(sci_port, + SCI_BASE_PORT_STATE_FAILED); - isci_event_port_hard_reset_complete( - scic_sds_port_get_controller(this_port), - this_port, - SCI_FAILURE_TIMEOUT - ); + isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); } /* --------------------------------------------------------------------------- */ diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index 7c9521049ae7..d2d3f5293b2c 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -431,46 +431,47 @@ static void scic_sds_mpc_agent_link_up( * assigned port. * @phy: This is the phy object which has gone link down. * - * This method handles the manual port configuration link down notifications. + * This function handles the manual port configuration link down notifications. * Since all ports and phys are associated at initialization time we just turn * around and notifiy the port object of the link down event. If this PHY is * not associated with a port there is no action taken. Is it possible to get a * link down notification from a phy that has no assocoated port? */ static void scic_sds_mpc_agent_link_down( - struct scic_sds_controller *controller, + struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *port, - struct scic_sds_phy *phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - if (port != NULL) { + if (sci_port != NULL) { /* - * If we can form a new port from the remainder of the phys then we want - * to start the timer to allow the SCI User to cleanup old devices and - * rediscover the port before rebuilding the port with the phys that - * remain in the ready state. */ - port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); - port_agent->phy_configured_mask &= ~(1 << scic_sds_phy_get_index(phy)); + * If we can form a new port from the remainder of the phys + * then we want to start the timer to allow the SCI User to + * cleanup old devices and rediscover the port before + * rebuilding the port with the phys that remain in the ready + * state. + */ + port_agent->phy_ready_mask &= + ~(1 << scic_sds_phy_get_index(sci_phy)); + port_agent->phy_configured_mask &= + ~(1 << scic_sds_phy_get_index(sci_phy)); /* - * Check to see if there are more phys waiting to be configured into a port. - * If there are allow the SCI User to tear down this port, if necessary, and - * then reconstruc the port after the timeout. */ - if ( - (port_agent->phy_configured_mask == 0x0000) - && (port_agent->phy_ready_mask != 0x0000) - && !port_agent->timer_pending - ) { + * Check to see if there are more phys waiting to be + * configured into a port. If there are allow the SCI User + * to tear down this port, if necessary, and then reconstruct + * the port after the timeout. + */ + if ((port_agent->phy_configured_mask == 0x0000) && + (port_agent->phy_ready_mask != 0x0000) && + !port_agent->timer_pending) { port_agent->timer_pending = true; - isci_event_timer_start( - controller, - port_agent->timer, - SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT - ); + isci_timer_start(port_agent->timer, + SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT); } - scic_sds_port_link_down(port, phy); + scic_sds_port_link_down(sci_port, sci_phy); } } @@ -535,19 +536,18 @@ static enum sci_status scic_sds_apc_agent_validate_phy_configuration( * the next time period. This could be caused by either a link down event or a * link up event where we can not yet tell to which port a phy belongs. */ -static void scic_sds_apc_agent_start_timer( - struct scic_sds_controller *controller, +static inline void scic_sds_apc_agent_start_timer( + struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_phy *phy, + struct scic_sds_phy *sci_phy, u32 timeout) { - if (port_agent->timer_pending) { - isci_event_timer_stop(controller, port_agent->timer); - } + if (port_agent->timer_pending) + isci_timer_stop(port_agent->timer); port_agent->timer_pending = true; - isci_event_timer_start(controller, port_agent->timer, timeout); + isci_timer_start(port_agent->timer, timeout); } /** @@ -816,45 +816,46 @@ void scic_sds_port_configuration_agent_construct( * This method will construct the port configuration agent for this controller. */ enum sci_status scic_sds_port_configuration_agent_initialize( - struct scic_sds_controller *controller, + struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent) { enum sci_status status = SCI_SUCCESS; enum SCIC_PORT_CONFIGURATION_MODE mode; + struct isci_host *ihost = sci_object_get_association(scic); - mode = controller->oem_parameters.sds1.controller.mode_type; + mode = scic->oem_parameters.sds1.controller.mode_type; if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { - status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent); + status = scic_sds_mpc_agent_validate_phy_configuration( + scic, port_agent); port_agent->link_up_handler = scic_sds_mpc_agent_link_up; port_agent->link_down_handler = scic_sds_mpc_agent_link_down; - port_agent->timer = isci_event_timer_create( - controller, - scic_sds_mpc_agent_timeout_handler, - controller - ); + port_agent->timer = isci_timer_create( + ihost, + scic, + scic_sds_mpc_agent_timeout_handler); } else { - status = scic_sds_apc_agent_validate_phy_configuration(controller, port_agent); + status = scic_sds_apc_agent_validate_phy_configuration( + scic, port_agent); port_agent->link_up_handler = scic_sds_apc_agent_link_up; port_agent->link_down_handler = scic_sds_apc_agent_link_down; - port_agent->timer = isci_event_timer_create( - controller, - scic_sds_apc_agent_timeout_handler, - controller - ); + port_agent->timer = isci_timer_create( + ihost, + scic, + scic_sds_apc_agent_timeout_handler); } /* Make sure we have actually gotten a timer */ if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) { - dev_err(scic_to_dev(controller), + dev_err(scic_to_dev(scic), "%s: Controller 0x%p automatic port configuration " "agent could not get timer.\n", __func__, - controller); + scic); status = SCI_FAILURE; } diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 0ac6ca0f3291..f722678eed8e 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1795,7 +1795,7 @@ static void scic_sds_remote_device_initial_state_enter( * @object: This is the struct sci_base_object that is cast into a * struct scic_sds_remote_device. * - * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it + * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it * sets the stopped state handlers and if this state is entered from the * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that the * device stop is complete. none @@ -1803,30 +1803,29 @@ static void scic_sds_remote_device_initial_state_enter( static void scic_sds_remote_device_stopped_state_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)object; + struct scic_sds_controller *scic = + scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = + sci_object_get_association(sci_dev); - SET_STATE_HANDLER( - this_device, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED - ); + SET_STATE_HANDLER(sci_dev, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); /* * If we are entering from the stopping state let the SCI User know that - * the stop operation has completed. */ - if (this_device->parent.state_machine.previous_state_id - == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) { - isci_event_remote_device_stop_complete( - scic_sds_remote_device_get_controller(this_device), - this_device, - SCI_SUCCESS - ); - } + * the stop operation has completed. + */ + if (sci_dev->parent.state_machine.previous_state_id == + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) + isci_remote_device_stop_complete(ihost, idev, SCI_SUCCESS); scic_sds_controller_remote_device_stopped( - scic_sds_remote_device_get_controller(this_device), - this_device - ); + scic_sds_remote_device_get_controller(sci_dev), + sci_dev); } /** @@ -1834,29 +1833,28 @@ static void scic_sds_remote_device_stopped_state_enter( * @object: This is the struct sci_base_object that is cast into a * struct scic_sds_remote_device. * - * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it + * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it * sets the starting state handlers, sets the device not ready, and posts the * remote node context to the hardware. none */ static void scic_sds_remote_device_starting_state_enter( struct sci_base_object *object) { - struct scic_sds_controller *the_controller; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_controller *scic; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)object; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); - the_controller = scic_sds_remote_device_get_controller(this_device); + scic = scic_sds_remote_device_get_controller(sci_dev); SET_STATE_HANDLER( - this_device, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STARTING - ); + sci_dev, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STARTING); - isci_event_remote_device_not_ready( - the_controller, - this_device, - SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED - ); + isci_remote_device_not_ready( + idev, + SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); } /** @@ -1864,27 +1862,29 @@ static void scic_sds_remote_device_starting_state_enter( * @object: This is the struct sci_base_object that is cast into a * struct scic_sds_remote_device. * - * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it + * This is the exit function for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it * reports that the device start is complete. none */ static void scic_sds_remote_device_starting_state_exit( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)object; + struct scic_sds_controller *scic = + scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + /* - * / @todo Check the device object for the proper return code for this - * / callback */ - isci_event_remote_device_start_complete( - scic_sds_remote_device_get_controller(this_device), - this_device, - SCI_SUCCESS - ); + * @todo Check the device object for the proper return code for this + * callback + */ + isci_remote_device_start_complete(ihost, idev, SCI_SUCCESS); scic_sds_controller_remote_device_started( - scic_sds_remote_device_get_controller(this_device), - this_device - ); + scic_sds_remote_device_get_controller(sci_dev), + sci_dev); } /** @@ -1892,30 +1892,28 @@ static void scic_sds_remote_device_starting_state_exit( * @object: This is the struct sci_base_object that is cast into a * struct scic_sds_remote_device. * - * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets + * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets * the ready state handlers, and starts the ready substate machine. none */ static void scic_sds_remote_device_ready_state_enter( struct sci_base_object *object) { - struct scic_sds_controller *the_controller; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; - - the_controller = scic_sds_remote_device_get_controller(this_device); + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)object; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct scic_sds_controller *scic + = scic_sds_remote_device_get_controller(sci_dev); - SET_STATE_HANDLER( - this_device, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_READY - ); + SET_STATE_HANDLER(sci_dev, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_READY); - the_controller->remote_device_sequence[this_device->rnc->remote_node_index]++; + scic->remote_device_sequence[sci_dev->rnc->remote_node_index]++; - if (this_device->has_ready_substate_machine) { - sci_base_state_machine_start(&this_device->ready_substate_machine); - } else { - isci_event_remote_device_ready(the_controller, this_device); - } + if (sci_dev->has_ready_substate_machine) + sci_base_state_machine_start(&sci_dev->ready_substate_machine); + else + isci_remote_device_ready(idev); } /** @@ -1923,26 +1921,22 @@ static void scic_sds_remote_device_ready_state_enter( * @object: This is the struct sci_base_object that is cast into a * struct scic_sds_remote_device. * - * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does + * This is the exit function for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does * nothing. none */ static void scic_sds_remote_device_ready_state_exit( struct sci_base_object *object) { - struct scic_sds_controller *the_controller; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)object; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); - the_controller = scic_sds_remote_device_get_controller(this_device); - - if (this_device->has_ready_substate_machine) { - sci_base_state_machine_stop(&this_device->ready_substate_machine); - } else { - isci_event_remote_device_not_ready( - the_controller, - this_device, - SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED - ); - } + if (sci_dev->has_ready_substate_machine) + sci_base_state_machine_stop(&sci_dev->ready_substate_machine); + else + isci_remote_device_not_ready( + idev, + SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); } /** diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 00bebb9c0692..4542f4e75f7f 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -2077,30 +2077,24 @@ static void scic_sds_request_started_state_exit( static void scic_sds_request_completed_state_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_controller *scic = + scic_sds_request_get_controller(sci_req); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_request *ireq = sci_object_get_association(sci_req); - SET_STATE_HANDLER( - this_request, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + + SET_STATE_HANDLER(sci_req, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_COMPLETED); /* Tell the SCI_USER that the IO request is complete */ - if (this_request->is_task_management_request == false) { - isci_event_io_request_complete( - scic_sds_request_get_controller(this_request), - scic_sds_request_get_device(this_request), - this_request, - this_request->sci_status - ); - } else { - isci_event_task_request_complete( - scic_sds_request_get_controller(this_request), - scic_sds_request_get_device(this_request), - this_request, - this_request->sci_status - ); - } + if (sci_req->is_task_management_request == false) + isci_request_io_request_complete(ihost, + ireq, + sci_req->sci_status); + else + isci_task_request_complete(ihost, ireq, sci_req->sci_status); } /** diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index 93e6ab83b01d..fb832ef544e5 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -250,22 +250,23 @@ const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_rea * struct scic_sds_remote_device. * * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. - * This method sets the ready cmd substate handlers and reports the device as + * This function sets the ready cmd substate handlers and reports the device as * ready. none */ -static void scic_sds_smp_remote_device_ready_idle_substate_enter( +static inline void scic_sds_smp_remote_device_ready_idle_substate_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)object; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + SET_STATE_HANDLER( - this_device, - scic_sds_smp_remote_device_ready_substate_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE - ); + sci_dev, + scic_sds_smp_remote_device_ready_substate_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - isci_event_remote_device_ready( - scic_sds_remote_device_get_controller(this_device), this_device); + isci_remote_device_ready(idev); } /** @@ -274,27 +275,26 @@ static void scic_sds_smp_remote_device_ready_idle_substate_enter( * struct scic_sds_remote_device. * * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This - * method sets the remote device objects ready cmd substate handlers, and + * function sets the remote device objects ready cmd substate handlers, and * notify core user that the device is not ready. none */ static void scic_sds_smp_remote_device_ready_cmd_substate_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)object; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); - BUG_ON(this_device->working_request == NULL); + BUG_ON(sci_dev->working_request == NULL); SET_STATE_HANDLER( - this_device, - scic_sds_smp_remote_device_ready_substate_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD - ); + sci_dev, + scic_sds_smp_remote_device_ready_substate_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - isci_event_remote_device_not_ready( - scic_sds_remote_device_get_controller(this_device), - this_device, - SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED - ); + isci_remote_device_not_ready( + idev, + SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); } /** diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index 9a615f07cefe..cb396d127773 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -677,23 +677,22 @@ const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_rea * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS * ***************************************************************************** */ -static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( - void *user_cookie) +static inline void +scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( + void *user_cookie) { - struct scic_sds_remote_device *this_device; - - this_device = (struct scic_sds_remote_device *)user_cookie; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)user_cookie; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); /* * For NCQ operation we do not issue a * scic_cb_remote_device_not_ready(). As a result, avoid sending - * the ready notification. */ - if (this_device->ready_substate_machine.previous_state_id - != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) { - isci_event_remote_device_ready( - scic_sds_remote_device_get_controller(this_device), this_device - ); - } + * the ready notification. + */ + if (sci_dev->ready_substate_machine.previous_state_id != + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) + isci_remote_device_ready(idev); } /* @@ -749,26 +748,23 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter( * struct scic_sds_remote_device object. * */ -static void scic_sds_stp_remote_device_ready_cmd_substate_enter( +static inline void scic_sds_stp_remote_device_ready_cmd_substate_enter( struct sci_base_object *device) { - struct scic_sds_remote_device *this_device; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)device; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); - this_device = (struct scic_sds_remote_device *)device; - - BUG_ON(this_device->working_request == NULL); + BUG_ON(sci_dev->working_request == NULL); SET_STATE_HANDLER( - this_device, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD - ); + sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - isci_event_remote_device_not_ready( - scic_sds_remote_device_get_controller(this_device), - this_device, - SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED - ); + isci_remote_device_not_ready( + idev, + SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } /* @@ -807,27 +803,21 @@ static void scic_sds_stp_remote_device_ready_ncq_substate_enter( * struct scic_sds_remote_device object. * */ -static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( +static inline void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( struct sci_base_object *device) { - struct scic_sds_remote_device *this_device; - - this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_remote_device *sci_dev = + (struct scic_sds_remote_device *)device; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); SET_STATE_HANDLER( - this_device, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR - ); + sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); - if (this_device->not_ready_reason == - SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) { - isci_event_remote_device_not_ready( - scic_sds_remote_device_get_controller(this_device), - this_device, - this_device->not_ready_reason - ); - } + if (sci_dev->not_ready_reason == + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) + isci_remote_device_not_ready(idev, sci_dev->not_ready_reason); } /* diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c deleted file mode 100644 index 9d58e458a37b..000000000000 --- a/drivers/scsi/isci/events.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/** - * This file contains isci module object implementation. - * - * - */ - -#include "isci.h" -#include "request.h" -#include "sata.h" -#include "task.h" -#include "events.h" - -/** - * isci_event_timer_create() - This callback method asks the user to create a - * timer and provide a handle for this timer for use in further timer - * interactions. The appropriate isci timer object function is called to - * create a timer object. - * @timer_callback: This parameter specifies the callback method to be invoked - * whenever the timer expires. - * @controller: This parameter specifies the controller with which this timer - * is to be associated. - * @cb_param: opaque callback parameter - * - * This method returns a handle to a timer object created by the user. The - * handle will be utilized for all further interactions relating to this timer. - */ -void *isci_event_timer_create(struct scic_sds_controller *scic, - void (*timer_callback)(void *), - void *cb_param) -{ - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_timer *itimer; - - itimer = isci_timer_create(ihost, cb_param, timer_callback); - - dev_dbg(&ihost->pdev->dev, "%s: timer = %p\n", __func__, itimer); - - return itimer; -} - - -/** - * isci_event_timer_start() - This callback method asks the user to start the - * supplied timer. The appropriate isci timer object function is called to - * start the timer. - * @controller: This parameter specifies the controller with which this timer - * is to associated. - * @timer: This parameter specifies the timer to be started. - * @milliseconds: This parameter specifies the number of milliseconds for which - * to stall. The operating system driver is allowed to round this value up - * where necessary. - * - */ -void isci_event_timer_start( - struct scic_sds_controller *controller, - void *timer, - u32 milliseconds) -{ - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_host = %p, timer = %p, milliseconds = %d\n", - __func__, isci_host, timer, milliseconds); - - isci_timer_start((struct isci_timer *)timer, milliseconds); - -} - -/** - * isci_event_timer_stop() - This callback method asks the user to stop the - * supplied timer. The appropriate isci timer object function is called to - * stop the timer. - * @controller: This parameter specifies the controller with which this timer - * is to associated. - * @timer: This parameter specifies the timer to be stopped. - * - */ -void isci_event_timer_stop(struct scic_sds_controller *controller, void *timer) -{ - struct isci_host *isci_host = sci_object_get_association(controller); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_host = %p, timer = %p\n", - __func__, isci_host, timer); - - isci_timer_stop((struct isci_timer *)timer); -} - -void isci_event_timer_destroy(struct scic_sds_controller *scic, void *timer) -{ - struct isci_host *ihost = sci_object_get_association(scic); - - dev_dbg(&ihost->pdev->dev, "%s: ihost = %p, timer = %p\n", - __func__, ihost, timer); - - isci_del_timer(ihost, timer); -} - -/** - * isci_event_controller_start_complete() - This user callback will inform the - * user that the controller has finished the start process. The associated - * isci host adapter's start_complete function is called. - * @controller: This parameter specifies the controller that was started. - * @completion_status: This parameter specifies the results of the start - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void isci_event_controller_start_complete( - struct scic_sds_controller *controller, - enum sci_status completion_status) -{ - struct isci_host *isci_host = - (struct isci_host *)sci_object_get_association(controller); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_host = %p\n", __func__, isci_host); - - isci_host_start_complete(isci_host, completion_status); -} - -/** - * isci_event_controller_stop_complete() - This user callback will inform the user - * that the controller has finished the stop process. The associated isci - * host adapter's start_complete function is called. - * @controller: This parameter specifies the controller that was stopped. - * @completion_status: This parameter specifies the results of the stop - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void isci_event_controller_stop_complete( - struct scic_sds_controller *controller, - enum sci_status completion_status) -{ - struct isci_host *isci_host = - (struct isci_host *)sci_object_get_association(controller); - - dev_dbg(&isci_host->pdev->dev, - "%s: status = 0x%x\n", __func__, completion_status); - isci_host_stop_complete(isci_host, completion_status); -} - -/** - * isci_event_io_request_complete() - This user callback will inform the user that - * an IO request has completed. - * @controller: This parameter specifies the controller on which the IO is - * completing. - * @remote_device: This parameter specifies the remote device on which this IO - * request is completing. - * @io_request: This parameter specifies the IO request that has completed. - * @completion_status: This parameter specifies the results of the IO request - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void isci_event_io_request_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *scic_io_request, - enum sci_io_status completion_status) -{ - struct isci_request *request; - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - request = - (struct isci_request *)sci_object_get_association( - scic_io_request - ); - - isci_request_io_request_complete(isci_host, - request, - completion_status); -} - -/** - * isci_event_task_request_complete() - This user callback will inform the user - * that a task management request completed. - * @controller: This parameter specifies the controller on which the task - * management request is completing. - * @remote_device: This parameter specifies the remote device on which this - * task management request is completing. - * @task_request: This parameter specifies the task management request that has - * completed. - * @completion_status: This parameter specifies the results of the IO request - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void isci_event_task_request_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *scic_task_request, - enum sci_task_status completion_status) -{ - struct isci_request *request; - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - request = - (struct isci_request *)sci_object_get_association( - scic_task_request); - - isci_task_request_complete(isci_host, request, completion_status); -} - -/** - * isci_event_port_stop_complete() - This method informs the user when a stop - * operation on the port has completed. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @completion_status: This parameter specifies the status for the operation - * being completed. - * - */ -void isci_event_port_stop_complete( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - enum sci_status completion_status) -{ - struct isci_host *isci_host; - - isci_host = (struct isci_host *)sci_object_get_association(controller); - - dev_notice(&isci_host->pdev->dev, "Port stop complete\n"); -} - -/** - * isci_event_port_hard_reset_complete() - This method informs the user when a - * hard reset on the port has completed. This hard reset could have been - * initiated by the user or by the remote port. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @completion_status: This parameter specifies the status for the operation - * being completed. - * - */ -void isci_event_port_hard_reset_complete( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - enum sci_status completion_status) -{ - struct isci_port *isci_port - = (struct isci_port *)sci_object_get_association(port); - - isci_port_hard_reset_complete(isci_port, completion_status); -} - -/** - * isci_event_port_ready() - This method informs the user that the port is now in - * a ready state and can be utilized to issue IOs. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * - */ -void isci_event_port_ready( - struct scic_sds_controller *controller, - struct scic_sds_port *port) -{ - struct isci_port *isci_port; - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - isci_port = - (struct isci_port *)sci_object_get_association(port); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_port = %p\n", __func__, isci_port); - - isci_port_ready(isci_host, isci_port); -} - -/** - * isci_event_port_not_ready() - This method informs the user that the port is now - * not in a ready (i.e. busy) state and can't be utilized to issue IOs. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * - */ -void isci_event_port_not_ready( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - u32 reason_code) -{ - struct isci_port *isci_port; - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - isci_port = - (struct isci_port *)sci_object_get_association(port); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_port = %p\n", __func__, isci_port); - - isci_port_not_ready(isci_host, isci_port); -} - -/** - * isci_event_port_invalid_link_up() - This method informs the SCI Core user that - * a phy/link became ready, but the phy is not allowed in the port. In some - * situations the underlying hardware only allows for certain phy to port - * mappings. If these mappings are violated, then this API is invoked. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @phy: This parameter specifies the phy that came ready, but the phy can't be - * a valid member of the port. - * - */ -void isci_event_port_invalid_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - struct isci_host *isci_host; - - isci_host = (struct isci_host *)sci_object_get_association(controller); - dev_warn(&isci_host->pdev->dev, "Invalid link up!\n"); -} - -/** - * isci_event_port_bc_change_primitive_received() - This callback method informs - * the user that a broadcast change primitive was received. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. For instances where the phy on which the primitive was - * received is not part of a port, this parameter will be NULL. - * @phy: This parameter specifies the phy on which the primitive was received. - * - */ -void isci_event_port_bc_change_primitive_received( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - dev_dbg(&isci_host->pdev->dev, - "%s: port = %p, phy = %p\n", __func__, port, phy); - isci_port_bc_change_received(isci_host, port, phy); -} - - - - -/** - * isci_event_port_link_up() - This callback method informs the user that a phy - * has become operational and is capable of communicating with the remote - * end point. - * @controller: This parameter represents the controller associated with the - * phy. - * @port: This parameter specifies the port object for which the user callback - * is being invoked. There may be conditions where this parameter can be - * NULL - * @phy: This parameter specifies the phy object for which the user callback is - * being invoked. - * - * none. - */ -void isci_event_port_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - dev_dbg(&isci_host->pdev->dev, - "%s: phy = %p\n", __func__, phy); - - isci_port_link_up(isci_host, port, phy); -} - -/** - * isci_event_port_link_down() - This callback method informs the user that a phy - * is no longer operational and is not capable of communicating with the - * remote end point. - * @controller: This parameter represents the controller associated with the - * phy. - * @port: This parameter specifies the port object for which the user callback - * is being invoked. There may be conditions where this parameter can be - * NULL - * @phy: This parameter specifies the phy object for which the user callback is - * being invoked. - * - * none. - */ -void isci_event_port_link_down( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - struct isci_host *isci_host; - struct isci_phy *isci_phy; - struct isci_port *isci_port; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - isci_phy = - (struct isci_phy *)sci_object_get_association(phy); - - isci_port = - (struct isci_port *)sci_object_get_association(port); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_port = %p\n", __func__, isci_port); - - isci_port_link_down(isci_host, isci_phy, isci_port); -} - -/** - * isci_event_remote_device_start_complete() - This user callback method will - * inform the user that a start operation has completed. - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the completion callback. - * @completion_status: This parameter specifies the completion status for the - * operation. - * - */ -void isci_event_remote_device_start_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - enum sci_status completion_status) -{ - struct isci_host *isci_host; - struct isci_remote_device *isci_device; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - isci_device = - (struct isci_remote_device *)sci_object_get_association( - remote_device - ); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); - - isci_remote_device_start_complete( - isci_host, isci_device, completion_status); - -} - -/** - * isci_event_remote_device_stop_complete() - This user callback method will - * inform the user that a stop operation has completed. - * @scic: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the completion callback. - * @completion_status: This parameter specifies the completion status for the - * operation. - * - */ -void isci_event_remote_device_stop_complete(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - enum sci_status completion_status) -{ - struct isci_host *ihost; - struct isci_remote_device *idev; - - ihost = sci_object_get_association(scic); - idev = sci_object_get_association(sci_dev); - - dev_dbg(&ihost->pdev->dev, - "%s: idev = %p\n", __func__, idev); - - isci_remote_device_stop_complete(ihost, idev, completion_status); -} - -/** - * isci_event_remote_device_ready() - This user callback method will inform the - * user that a remote device is now capable of handling IO requests. - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the callback. - * - */ -void isci_event_remote_device_ready( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device) -{ - struct isci_remote_device *isci_device = - (struct isci_remote_device *) - sci_object_get_association(remote_device); - - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); - - isci_remote_device_ready(isci_device); -} - -/** - * isci_event_remote_device_not_ready() - This user callback method will inform - * the user that a remote device is no longer capable of handling IO - * requests (until a ready callback is invoked). - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the callback. - * @reason_code: This parameter specifies the reason for the remote device - * going to a not ready state. - * - */ -void isci_event_remote_device_not_ready( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - u32 reason_code) -{ - struct isci_remote_device *isci_device = - (struct isci_remote_device *) - sci_object_get_association(remote_device); - - struct isci_host *isci_host; - - isci_host = - (struct isci_host *)sci_object_get_association(controller); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p, reason_code = %x\n", - __func__, isci_device, reason_code); - - isci_remote_device_not_ready(isci_device, reason_code); -} - - diff --git a/drivers/scsi/isci/events.h b/drivers/scsi/isci/events.h deleted file mode 100644 index fa2f6aa1093c..000000000000 --- a/drivers/scsi/isci/events.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _ISCI_EVENT_H_ -#define _ISCI_EVENT_H_ - -/** - * isci_event_timer_create() - This callback method asks the user to create a - * timer and provide a handle for this timer for use in further timer - * interactions. - * @controller: This parameter specifies the controller with which this timer - * is to be associated. - * @timer_callback: This parameter specifies the callback method to be invoked - * whenever the timer expires. - * @cookie: This parameter specifies a piece of information that the user must - * retain. This cookie is to be supplied by the user anytime a timeout - * occurs for the created timer. - * - * The "timer_callback" method should be executed in a mutually exlusive manner - * from the controller completion handler handler. This method returns a handle - * to a timer object created by the user. The handle will be utilized for all - * further interactions relating to this timer. - */ -void *isci_event_timer_create( - struct scic_sds_controller *controller, - void (*timer_callback)(void *), - void *cookie); - -/** - * isci_event_timer_start() - This callback method asks the user to start the - * supplied timer. - * @controller: This parameter specifies the controller with which this timer - * is to associated. - * @timer: This parameter specifies the timer to be started. - * @milliseconds: This parameter specifies the number of milliseconds for which - * to stall. The operating system driver is allowed to round this value up - * where necessary. - * - * All timers in the system started by the SCI Core are one shot timers. - * Therefore, the SCI user should make sure that it removes the timer from it's - * list when a timer actually fires. Additionally, SCI Core user's should be - * able to handle calls from the SCI Core to stop a timer that may already be - * stopped. none - */ -void isci_event_timer_start( - struct scic_sds_controller *controller, - void *timer, - u32 milliseconds); - -/** - * isci_event_timer_stop() - This callback method asks the user to stop the - * supplied timer. - * @controller: This parameter specifies the controller with which this timer - * is to associated. - * @timer: This parameter specifies the timer to be stopped. - * - */ -void isci_event_timer_stop( - struct scic_sds_controller *controller, - void *timer); - - -void isci_event_timer_destroy(struct scic_sds_controller *scic, void *timer); - -/** - * isci_event_controller_start_complete() - This user callback will inform the - * user that the controller has finished the start process. - * @controller: This parameter specifies the controller that was started. - * @completion_status: This parameter specifies the results of the start - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void isci_event_controller_start_complete( - struct scic_sds_controller *controller, - enum sci_status completion_status); - -/** - * isci_event_controller_stop_complete() - This user callback will inform the - * user that the controller has finished the stop process. - * @controller: This parameter specifies the controller that was stopped. - * @completion_status: This parameter specifies the results of the stop - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void isci_event_controller_stop_complete( - struct scic_sds_controller *controller, - enum sci_status completion_status); - -/** - * isci_event_io_request_complete() - This user callback will inform the user - * that an IO request has completed. - * @controller: This parameter specifies the controller on which the IO is - * completing. - * @remote_device: This parameter specifies the remote device on which this IO - * request is completing. - * @io_request: This parameter specifies the IO request that has completed. - * @completion_status: This parameter specifies the results of the IO request - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void isci_event_io_request_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *scic_io_request, - enum sci_io_status completion_status); - -/** - * isci_event_task_request_complete() - This user callback will inform the user - * that a task management request completed. - * @controller: This parameter specifies the controller on which the task - * management request is completing. - * @remote_device: This parameter specifies the remote device on which this - * task management request is completing. - * @task_request: This parameter specifies the task management request that has - * completed. - * @completion_status: This parameter specifies the results of the IO request - * operation. SCI_SUCCESS indicates successful completion. - * - */ -void isci_event_task_request_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *scic_task_request, - enum sci_task_status completion_status); - -/** - * isci_event_port_stop_complete() - This method informs the user when a stop - * operation on the port has completed. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @completion_status: This parameter specifies the status for the operation - * being completed. - * - */ -void isci_event_port_stop_complete( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - enum sci_status completion_status); - -/** - * isci_event_port_hard_reset_complete() - This method informs the user when a - * hard reset on the port has completed. This hard reset could have been - * initiated by the user or by the remote port. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @completion_status: This parameter specifies the status for the operation - * being completed. - * - */ -void isci_event_port_hard_reset_complete( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - enum sci_status completion_status); - -/** - * isci_event_port_ready() - This method informs the user that the port is now - * in a ready state and can be utilized to issue IOs. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * - */ -void isci_event_port_ready( - struct scic_sds_controller *controller, - struct scic_sds_port *port); - -/** - * isci_event_port_not_ready() - This method informs the user that the port is - * now not in a ready (i.e. busy) state and can't be utilized to issue IOs. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @reason_code: This parameter specifies the reason for the port not ready - * callback. - * - */ -void isci_event_port_not_ready( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - u32 reason_code); - -/** - * isci_event_port_invalid_link_up() - This method informs the SCI Core user - * that a phy/link became ready, but the phy is not allowed in the port. In - * some situations the underlying hardware only allows for certain phy to port - * mappings. If these mappings are violated, then this API is invoked. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @phy: This parameter specifies the phy that came ready, but the phy can't be - * a valid member of the port. - * - */ -void isci_event_port_invalid_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy); - -/** - * isci_event_port_bc_change_primitive_received() - This callback method informs - * the user that a broadcast change primitive was received. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. For instances where the phy on which the primitive was - * received is not part of a port, this parameter will be - * NULL. - * @phy: This parameter specifies the phy on which the primitive was received. - * - */ -void isci_event_port_bc_change_primitive_received( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy); - -/** - * isci_event_port_link_up() - This callback method informs the user that a phy - * has become operational and is capable of communicating with the remote - * end point. - * @controller: This parameter represents the controller associated with the - * phy. - * @port: This parameter specifies the port object for which the user callback - * is being invoked. There may be conditions where this parameter can be - * NULL - * @phy: This parameter specifies the phy object for which the user callback is - * being invoked. - * - */ -void isci_event_port_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy); - -/** - * isci_event_port_link_down() - This callback method informs the user that a - * phy is no longer operational and is not capable of communicating with the - * remote end point. - * @controller: This parameter represents the controller associated with the - * phy. - * @port: This parameter specifies the port object for which the user callback - * is being invoked. There may be conditions where this parameter can be - * NULL - * @phy: This parameter specifies the phy object for which the user callback is - * being invoked. - * - */ -void isci_event_port_link_down( - struct scic_sds_controller *controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy); - -/** - * isci_event_remote_device_start_complete() - This user callback method will - * inform the user that a start operation has completed. - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the completion callback. - * @completion_status: This parameter specifies the completion status for the - * operation. - * - */ -void isci_event_remote_device_start_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - enum sci_status completion_status); - -/** - * isci_event_remote_device_stop_complete() - This user callback method will - * inform the user that a stop operation has completed. - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the completion callback. - * @completion_status: This parameter specifies the completion status for the - * operation. - * - */ -void isci_event_remote_device_stop_complete( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - enum sci_status completion_status); - -/** - * isci_event_remote_device_ready() - This user callback method will inform the - * user that a remote device is now capable of handling IO requests. - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the callback. - * - */ -void isci_event_remote_device_ready( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device); - -/** - * isci_event_remote_device_not_ready() - This user callback method will inform - * the user that a remote device is no longer capable of handling IO - * requests (until a ready callback is invoked). - * @controller: This parameter specifies the core controller associated with - * the completion callback. - * @remote_device: This parameter specifies the remote device associated with - * the callback. - * @reason_code: This paramete specifies the reason the remote device is not - * ready. - * - */ -void isci_event_remote_device_not_ready( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - u32 reason_code); - -#endif diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index a2df59c9e06d..87643857bade 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -71,7 +71,6 @@ #include "timers.h" #include "sci_status.h" #include "request.h" -#include "events.h" #include "task.h" #include "sata.h" diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index a5b2565ac5af..666076a2834e 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -279,10 +279,8 @@ void isci_port_link_up( * @port: This parameter specifies the isci port with the active link. * */ -void isci_port_link_down( - struct isci_host *isci_host, - struct isci_phy *isci_phy, - struct isci_port *isci_port) +void isci_port_link_down(struct isci_host *isci_host, struct isci_phy *isci_phy, + struct isci_port *isci_port) { struct isci_remote_device *isci_device; @@ -358,9 +356,7 @@ void isci_port_formed( * @port: This parameter specifies the sci port with the active link. * */ -void isci_port_ready( - struct isci_host *isci_host, - struct isci_port *isci_port) +void isci_port_ready(struct isci_host *isci_host, struct isci_port *isci_port) { dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", __func__, isci_port); @@ -378,9 +374,7 @@ void isci_port_ready( * @port: This parameter specifies the sci port with the active link. * */ -void isci_port_not_ready( - struct isci_host *isci_host, - struct isci_port *isci_port) +void isci_port_not_ready(struct isci_host *isci_host, struct isci_port *isci_port) { dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", __func__, isci_port); @@ -394,9 +388,8 @@ void isci_port_not_ready( * process. * */ -void isci_port_hard_reset_complete( - struct isci_port *isci_port, - enum sci_status completion_status) +void isci_port_hard_reset_complete(struct isci_port *isci_port, + enum sci_status completion_status) { dev_dbg(&isci_port->isci_host->pdev->dev, "%s: isci_port = %p, completion_status=%x\n", @@ -480,3 +473,35 @@ int isci_port_perform_hard_reset( return ret; } + +/** + * isci_port_invalid_link_up() - This function informs the SCI Core user that + * a phy/link became ready, but the phy is not allowed in the port. In some + * situations the underlying hardware only allows for certain phy to port + * mappings. If these mappings are violated, then this API is invoked. + * @controller: This parameter represents the controller which contains the + * port. + * @port: This parameter specifies the SCI port object for which the callback + * is being invoked. + * @phy: This parameter specifies the phy that came ready, but the phy can't be + * a valid member of the port. + * + */ +void isci_port_invalid_link_up(struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + struct scic_sds_phy *phy) +{ + struct isci_host *ihost = + (struct isci_host *)sci_object_get_association(scic); + + dev_warn(&ihost->pdev->dev, "Invalid link up!\n"); +} + +void isci_port_stop_complete(struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + enum sci_status completion_status) +{ + struct isci_host *ihost = sci_object_get_association(scic); + + dev_dbg(&ihost->pdev->dev, "Port stop complete\n"); +} diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index b7a7dd7dca69..dfdd12a0f68e 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -147,5 +147,15 @@ int isci_port_perform_hard_reset( struct isci_port *isci_port_ptr, struct isci_phy *isci_phy_ptr); +void isci_port_invalid_link_up( + struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + struct scic_sds_phy *phy); + +void isci_port_stop_complete( + struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + enum sci_status completion_status); + #endif /* !defined(_ISCI_PORT_H_) */ -- cgit v1.2.3 From f942f32ea05eff727c41e1a1112cab305b836377 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 26 Mar 2011 16:30:06 -0700 Subject: isci: reorder init to cleanup unneeded declarations Just move isci_pci_driver below the function definitions and delete the declarations. A couple other whitespace fixups, and unused symbol deletions. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/init.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 1b04b9c117a4..5e63ae6a75d1 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -84,23 +84,8 @@ static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { {} }; -struct isci_firmware *isci_firmware; - -static int __devinit isci_pci_probe( - struct pci_dev *pdev, - const struct pci_device_id *device_id_p); - -static void __devexit isci_pci_remove(struct pci_dev *pdev); - MODULE_DEVICE_TABLE(pci, isci_id_table); -static struct pci_driver isci_pci_driver = { - .name = DRV_NAME, - .id_table = isci_id_table, - .probe = isci_pci_probe, - .remove = __devexit_p(isci_pci_remove), -}; - /* linux isci specific settings */ #if defined(CONFIG_PBG_HBA_A0) @@ -339,7 +324,7 @@ static int num_controllers(struct pci_dev *pdev) */ resource_size_t scu_bar_size = pci_resource_len(pdev, SCI_SCU_BAR*2); resource_size_t smu_bar_size = pci_resource_len(pdev, SCI_SMU_BAR*2); - + if (scu_bar_size >= SCI_SCU_BAR_SIZE*SCI_MAX_CONTROLLERS && smu_bar_size >= SCI_SMU_BAR_SIZE*SCI_MAX_CONTROLLERS) return SCI_MAX_CONTROLLERS; @@ -484,7 +469,7 @@ static void check_si_rev(struct pci_dev *pdev) dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n", isci_si_rev == ISCI_SI_REVA0 ? "A0" : isci_si_rev == ISCI_SI_REVA2 ? "A2" : "B0", pdev->revision); - + } static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -573,6 +558,13 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev) } } +static struct pci_driver isci_pci_driver = { + .name = DRV_NAME, + .id_table = isci_id_table, + .probe = isci_pci_probe, + .remove = __devexit_p(isci_pci_remove), +}; + static __init int isci_init(void) { int err; -- cgit v1.2.3 From 068b2c03635bf50c9b408b21435e23e7a0b89b0f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 26 Mar 2011 16:30:35 -0700 Subject: isci: kill some long macros Delete some macros that are longer to type than the open coded operation that they perform. scic_sds_phy_get_base_state_machine scic_sds_phy_get_starting_substate_machine scic_sds_port_get_base_state_machine scic_sds_port_get_ready_substate_machine scic_sds_remote_device_get_base_state_machine scic_sds_remote_device_get_ready_substate_machine scic_sds_remote_node_context_set_remote_node_index scic_sds_controller_get_base_state_machine Also performs some collateral cleanups like killing casts that assume structure member ordering, and consolidating a lot of duplicated default handler code (the primary callers of the *_get_base_state_machine macros) via a helper. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 259 +++-------- drivers/scsi/isci/core/scic_sds_controller.h | 9 - drivers/scsi/isci/core/scic_sds_phy.c | 400 ++++++---------- drivers/scsi/isci/core/scic_sds_phy.h | 48 -- drivers/scsi/isci/core/scic_sds_port.c | 424 ++++------------- drivers/scsi/isci/core/scic_sds_port.h | 16 - drivers/scsi/isci/core/scic_sds_remote_device.c | 508 +++++---------------- drivers/scsi/isci/core/scic_sds_remote_device.h | 16 - .../scsi/isci/core/scic_sds_remote_node_context.h | 3 - 9 files changed, 389 insertions(+), 1294 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index eaaa4cc89a85..7d25a0aafb66 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -739,9 +739,8 @@ static void scic_sds_controller_transition_to_ready( * We move into the ready state, because some of the phys/ports * may be up and operational. */ - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_READY); + sci_base_state_machine_change_state(&scic->parent.state_machine, + SCI_BASE_CONTROLLER_STATE_READY); isci_host_start_complete(ihost, status); } @@ -751,18 +750,12 @@ void scic_sds_controller_timeout_handler(void *_scic) { struct scic_sds_controller *scic = _scic; struct isci_host *ihost = sci_object_get_association(scic); - enum sci_base_controller_states current_state; - - current_state = sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine(scic)); + struct sci_base_state_machine *sm = &scic->parent.state_machine; - if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING) { - scic_sds_controller_transition_to_ready( - scic, SCI_FAILURE_TIMEOUT); - } else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING) { - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); + if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) + scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT); + else if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STOPPING) { + sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_FAILED); isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); } else /* / @todo Now what do we want to do in this case? */ dev_err(scic_to_dev(scic), @@ -1619,16 +1612,15 @@ void scic_sds_controller_error_handler(struct scic_sds_controller *scic) dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, interrupt_status); - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); + sci_base_state_machine_change_state(&scic->parent.state_machine, + SCI_BASE_CONTROLLER_STATE_FAILED); return; } - /* - * If we dont process any completions I am not sure that we want to do this. - * We are in the middle of a hardware fault and should probably be reset. */ + /* If we dont process any completions I am not sure that we want to do this. + * We are in the middle of a hardware fault and should probably be reset. + */ SMU_IMR_WRITE(scic, 0x00000000); } @@ -1655,12 +1647,8 @@ void scic_sds_controller_link_up( else dev_dbg(scic_to_dev(scic), "%s: SCIC Controller linkup event from phy %d in " - "unexpected state %d\n", - __func__, - sci_phy->phy_index, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - scic))); + "unexpected state %d\n", __func__, sci_phy->phy_index, + state); } @@ -2125,11 +2113,7 @@ enum sci_status scic_controller_initialize( else dev_warn(scic_to_dev(scic), "%s: SCIC Controller initialize operation requested " - "in invalid state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - scic))); + "in invalid state %d\n", __func__, state); return status; } @@ -2180,11 +2164,7 @@ enum sci_status scic_controller_start( else dev_warn(scic_to_dev(scic), "%s: SCIC Controller start operation requested in " - "invalid state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - scic))); + "invalid state %d\n", __func__, state); return status; } @@ -2207,11 +2187,7 @@ enum sci_status scic_controller_stop( else dev_warn(scic_to_dev(scic), "%s: SCIC Controller stop operation requested in " - "invalid state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - scic))); + "invalid state %d\n", __func__, state); return status; } @@ -2233,11 +2209,7 @@ enum sci_status scic_controller_reset( else dev_warn(scic_to_dev(scic), "%s: SCIC Controller reset operation requested in " - "invalid state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - scic))); + "invalid state %d\n", __func__, state); return status; } @@ -2765,128 +2737,57 @@ struct scic_sds_controller *scic_controller_alloc(struct device *dev) return devm_kzalloc(dev, sizeof(struct scic_sds_controller), GFP_KERNEL); } -/* - * ***************************************************************************** - * * DEFAULT STATE HANDLERS - * ***************************************************************************** */ +static enum sci_status default_controller_handler(struct sci_base_controller *base_scic, + const char *func) +{ + struct scic_sds_controller *scic = container_of(base_scic, typeof(*scic), parent); + u32 state = base_scic->state_machine.current_state_id; + + dev_warn(scic_to_dev(scic), "%s: invalid state %d\n", func, state); + + return SCI_FAILURE_INVALID_STATE; +} -/** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which, if it was used, would - * be cast to a struct scic_sds_remote_device. - * @io_request: This is the struct sci_base_request which, if it was used, would be - * cast to a SCIC_SDS_IO_REQUEST. - * @io_tag: This is the IO tag to be assigned to the IO request or - * SCI_CONTROLLER_INVALID_IO_TAG. - * - * This method is called when the struct scic_sds_controller default start io/task - * handler is in place. - Issue a warning message enum sci_status - * SCI_FAILURE_INVALID_STATE - */ static enum sci_status scic_sds_controller_default_start_operation_handler( - struct sci_base_controller *controller, + struct sci_base_controller *base_scic, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request, u16 io_tag) { - struct scic_sds_controller *this_controller; - - this_controller = (struct scic_sds_controller *)controller; - - dev_warn(scic_to_dev(this_controller), - "%s: SCIC Controller requested to start an io/task from " - "invalid state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - this_controller))); - - return SCI_FAILURE_INVALID_STATE; + return default_controller_handler(base_scic, __func__); } -/** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which, if it was used, would - * be cast to a struct scic_sds_remote_device. - * @io_request: This is the struct sci_base_request which, if it was used, would be - * cast to a SCIC_SDS_IO_REQUEST. - * - * This method is called when the struct scic_sds_controller default request handler - * is in place. - Issue a warning message enum sci_status SCI_FAILURE_INVALID_STATE - */ static enum sci_status scic_sds_controller_default_request_handler( - struct sci_base_controller *controller, + struct sci_base_controller *base_scic, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request) { - struct scic_sds_controller *this_controller; - - this_controller = (struct scic_sds_controller *)controller; - - dev_warn(scic_to_dev(this_controller), - "%s: SCIC Controller request operation from invalid state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_controller_get_base_state_machine( - this_controller))); - - return SCI_FAILURE_INVALID_STATE; + return default_controller_handler(base_scic, __func__); } -/* - * ***************************************************************************** - * * GENERAL (COMMON) STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @controller: The struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * - * This method is called when the struct scic_sds_controller is in the ready state - * reset handler is in place. - Transition to - * SCI_BASE_CONTROLLER_STATE_RESETTING enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_controller_general_reset_handler( - struct sci_base_controller *controller) +static enum sci_status scic_sds_controller_general_reset_handler(struct sci_base_controller *base_scic) { - struct scic_sds_controller *this_controller; - - this_controller = (struct scic_sds_controller *)controller; - - /* - * The reset operation is not a graceful cleanup just perform the state - * transition. */ - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(this_controller), - SCI_BASE_CONTROLLER_STATE_RESETTING - ); + /* The reset operation is not a graceful cleanup just perform the state + * transition. + */ + sci_base_state_machine_change_state(&base_scic->state_machine, + SCI_BASE_CONTROLLER_STATE_RESETTING); return SCI_SUCCESS; } -/* - * ***************************************************************************** - * * RESET STATE HANDLERS - * ***************************************************************************** */ - static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct sci_base_controller *base_scic) { + struct sci_base_state_machine *sm = &base_scic->state_machine; enum sci_status result = SCI_SUCCESS; struct scic_sds_controller *scic; struct isci_host *ihost; - u32 index; + u32 index, state; scic = container_of(base_scic, typeof(*scic), parent); ihost = sci_object_get_association(scic); - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_INITIALIZING); + sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); scic->timeout_timer = isci_timer_create(ihost, scic, @@ -3028,13 +2929,10 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct /* Advance the controller state machine */ if (result == SCI_SUCCESS) - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_INITIALIZED); + state = SCI_BASE_CONTROLLER_STATE_INITIALIZED; else - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); + state = SCI_BASE_CONTROLLER_STATE_FAILED; + sci_base_state_machine_change_state(sm, state); return result; } @@ -3065,14 +2963,14 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct * descriptor fields is invalid. */ static enum sci_status scic_sds_controller_initialized_state_start_handler( - struct sci_base_controller *controller, + struct sci_base_controller *base_scic, u32 timeout) { u16 index; enum sci_status result; struct scic_sds_controller *scic; - scic = (struct scic_sds_controller *)controller; + scic = container_of(base_scic, typeof(*scic), parent); /* * Make sure that the SCI User filled in the memory descriptor @@ -3135,9 +3033,8 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( isci_timer_start(scic->timeout_timer, timeout); - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_STARTING); + sci_base_state_machine_change_state(&base_scic->state_machine, + SCI_BASE_CONTROLLER_STATE_STARTING); } return result; @@ -3197,33 +3094,15 @@ static void scic_sds_controller_starting_state_link_down_handler( /* scic_sds_port_link_down(port, phy); */ } -/* - * ***************************************************************************** - * * READY STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @controller: The struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @timeout: The timeout for when the stop operation should report a failure. - * - * This method is called when the struct scic_sds_controller is in the ready state - * stop handler is called. - Start the timeout timer - Transition to - * SCI_BASE_CONTROLLER_STATE_STOPPING. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_controller_ready_state_stop_handler( - struct sci_base_controller *controller, - u32 timeout) +static enum sci_status scic_sds_controller_ready_state_stop_handler(struct sci_base_controller *base_scic, + u32 timeout) { - struct scic_sds_controller *scic = - (struct scic_sds_controller *)controller; + struct scic_sds_controller *scic; + scic = container_of(base_scic, typeof(*scic), parent); isci_timer_start(scic->timeout_timer, timeout); - - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_STOPPING); + sci_base_state_machine_change_state(&base_scic->state_machine, + SCI_BASE_CONTROLLER_STATE_STOPPING); return SCI_SUCCESS; } @@ -3749,33 +3628,16 @@ static inline void scic_sds_controller_stopping_state_exit( isci_timer_stop(scic->timeout_timer); } -/** - * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller - * object. - * - * This method implements the actions taken by the struct scic_sds_controller on entry - * to the SCI_BASE_CONTROLLER_STATE_RESETTING. - Set the state handlers to the - * controllers resetting state. - Write to the SCU hardware reset register to - * force a reset - Transition to the SCI_BASE_CONTROLLER_STATE_RESET none - */ -static void scic_sds_controller_resetting_state_enter( - struct sci_base_object *object) +static void scic_sds_controller_resetting_state_enter(struct sci_base_object *object) { - struct scic_sds_controller *this_controller; - - this_controller = (struct scic_sds_controller *)object; - - scic_sds_controller_reset_hardware(this_controller); + struct scic_sds_controller *scic; - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(this_controller), - SCI_BASE_CONTROLLER_STATE_RESET - ); + scic = container_of(object, typeof(*scic), parent.parent); + scic_sds_controller_reset_hardware(scic); + sci_base_state_machine_change_state(&scic->parent.state_machine, + SCI_BASE_CONTROLLER_STATE_RESET); } -/* --------------------------------------------------------------------------- */ - const struct sci_base_state scic_sds_controller_state_table[] = { [SCI_BASE_CONTROLLER_STATE_INITIAL] = { .enter_state = scic_sds_controller_initial_state_enter, @@ -3800,4 +3662,3 @@ const struct sci_base_state scic_sds_controller_state_table[] = { [SCI_BASE_CONTROLLER_STATE_STOPPED] = {}, [SCI_BASE_CONTROLLER_STATE_FAILED] = {} }; - diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index f426324bf3a9..aa2698bb7ca1 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -420,15 +420,6 @@ extern const struct sci_base_state scic_sds_controller_state_table[]; } \ } -/** - * scic_sds_controller_get_base_state_machine() - - * - * This is a helper macro that gets the base state machine for the controller - * object - */ -#define scic_sds_controller_get_base_state_machine(this_controller) \ - (&(this_controller)->parent.state_machine) - /** * scic_sds_controller_get_port_configuration_agent() - * diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 225e67a9e7b1..e546e20f1ffd 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -246,7 +246,7 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, 0x1F4); /* We can exit the initial state to the stopped state */ - sci_base_state_machine_change_state(scic_sds_phy_get_base_state_machine(sci_phy), + sci_base_state_machine_change_state(&sci_phy->parent.state_machine, SCI_BASE_PHY_STATE_STOPPED); return SCI_SUCCESS; @@ -267,13 +267,10 @@ void scic_sds_phy_sata_timeout(void *phy) __func__, sci_phy); - sci_base_state_machine_stop( - scic_sds_phy_get_starting_substate_machine(sci_phy)); + sci_base_state_machine_stop(&sci_phy->starting_substate_machine); - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(sci_phy), - SCI_BASE_PHY_STATE_STARTING - ); + sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + SCI_BASE_PHY_STATE_STARTING); } /** @@ -390,9 +387,8 @@ enum sci_status scic_sds_phy_initialize( /* * There is nothing that needs to be done in this state just * transition to the stopped state. */ - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(sci_phy), - SCI_BASE_PHY_STATE_STOPPED); + sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + SCI_BASE_PHY_STATE_STOPPED); return SCI_SUCCESS; } @@ -716,9 +712,9 @@ static void scic_sds_phy_start_sata_link_training( } /** - * This method performs processing common to all protocols upon completion of - * link training. - * @this_phy: This parameter specifies the phy object for which link training + * scic_sds_phy_complete_link_training - perform processing common to + * all protocols upon completion of link training. + * @sci_phy: This parameter specifies the phy object for which link training * has completed. * @max_link_rate: This parameter specifies the maximum link rate to be * associated with this phy. @@ -727,37 +723,25 @@ static void scic_sds_phy_start_sata_link_training( * */ static void scic_sds_phy_complete_link_training( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, enum sci_sas_link_rate max_link_rate, u32 next_state) { - this_phy->max_negotiated_speed = max_link_rate; + sci_phy->max_negotiated_speed = max_link_rate; - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), next_state - ); + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + next_state); } -/** - * - * @this_phy: The struct scic_sds_phy object to restart. - * - * This method restarts the struct scic_sds_phy objects base state machine in the - * starting state from any starting substate. none - */ static void scic_sds_phy_restart_starting_state( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { /* Stop the current substate machine */ - sci_base_state_machine_stop( - scic_sds_phy_get_starting_substate_machine(this_phy) - ); + sci_base_state_machine_stop(&sci_phy->starting_substate_machine); /* Re-enter the base state machine starting state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), - SCI_BASE_PHY_STATE_STARTING - ); + sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + SCI_BASE_PHY_STATE_STARTING); } /* **************************************************************************** @@ -1041,7 +1025,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_han } /** - * + * scic_sds_phy_starting_substate_await_sata_phy_event_handler - * @phy: This struct scic_sds_phy object which has received an event. * @event_code: This is the event code which the phy object is to decode. * @@ -1054,42 +1038,39 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_han * failure event SCI_FAILURE on any unexpected event notifation */ static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handler( - struct scic_sds_phy *this_phy, - u32 event_code) + struct scic_sds_phy *sci_phy, u32 event_code) { u32 result = SCI_SUCCESS; switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(this_phy); + scic_sds_phy_restart_starting_state(sci_phy); break; case SCU_EVENT_SATA_SPINUP_HOLD: - /* - * These events might be received since we dont know how many may be in - * the completion queue while waiting for power */ + /* These events might be received since we dont know how many may be in + * the completion queue while waiting for power + */ break; case SCU_EVENT_SATA_PHY_DETECTED: - this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; /* We have received the SATA PHY notification change state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN - ); + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); break; case SCU_EVENT_SAS_PHY_DETECTED: - /* - * There has been a change in the phy type before OOB/SN for the - * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(this_phy); + /* There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. + */ + scic_sds_phy_start_sas_link_training(sci_phy); break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -1182,7 +1163,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_han } /** - * + * scic_sds_phy_starting_substate_await_sig_fis_event_handler - * @phy: This struct scic_sds_phy object which has received an event. * @event_code: This is the event code which the phy object is to decode. * @@ -1196,27 +1177,24 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_han * unexpected event notifation */ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handler( - struct scic_sds_phy *this_phy, - u32 event_code) + struct scic_sds_phy *sci_phy, u32 event_code) { u32 result = SCI_SUCCESS; switch (scu_get_event_code(event_code)) { case SCU_EVENT_SATA_PHY_DETECTED: /* Backup the state machine */ - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN - ); + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(this_phy); + scic_sds_phy_restart_starting_state(sci_phy); break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -1249,15 +1227,14 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handle * unsolicted frame - release frame buffer enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler( - struct scic_sds_phy *this_phy, - u32 frame_index) + struct scic_sds_phy *sci_phy, u32 frame_index) { enum sci_status result; u32 *frame_words; struct sci_sas_identify_address_frame *identify_frame; result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(this_phy)->uf_control), + &(scic_sds_phy_get_controller(sci_phy)->uf_control), frame_index, (void **)&frame_words); @@ -1269,49 +1246,43 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler identify_frame = (struct sci_sas_identify_address_frame *)frame_words; if (identify_frame->address_frame_type == 0) { - /* - * Byte swap the rest of the frame so we can make - * a copy of the buffer */ + u32 state; + + /* Byte swap the rest of the frame so we can make + * a copy of the buffer + */ frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]); frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]); frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]); frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]); frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]); - memcpy( - &this_phy->phy_type.sas.identify_address_frame_buffer, + memcpy(&sci_phy->phy_type.sas.identify_address_frame_buffer, identify_frame, - sizeof(struct sci_sas_identify_address_frame) - ); + sizeof(struct sci_sas_identify_address_frame)); if (identify_frame->protocols.u.bits.smp_target) { - /* - * We got the IAF for an expander PHY go to the final state since - * there are no power requirements for expander phys. */ - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL - ); + /* We got the IAF for an expander PHY go to the final state since + * there are no power requirements for expander phys. + */ + state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; } else { /* We got the IAF we can now go to the await spinup semaphore state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER - ); + state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; } - + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + state); result = SCI_SUCCESS; } else - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected frame id %x\n", __func__, frame_index); /* Regardless of the result release this frame since we are done with it */ - scic_sds_controller_release_frame( - scic_sds_phy_get_controller(this_phy), frame_index - ); + scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), + frame_index); return result; } @@ -1331,7 +1302,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler * data */ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 frame_index) { enum sci_status result; @@ -1340,7 +1311,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle u32 *fis_frame_data; result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(this_phy)->uf_control), + &(scic_sds_phy_get_controller(sci_phy)->uf_control), frame_index, (void **)&frame_words); @@ -1350,40 +1321,33 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle fis_frame_header = (struct sata_fis_header *)frame_words; - if ( - (fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H) - && !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT) - ) { + if ((fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H) && + !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT)) { scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_phy_get_controller(this_phy)->uf_control), + &(scic_sds_phy_get_controller(sci_phy)->uf_control), frame_index, - (void **)&fis_frame_data - ); + (void **)&fis_frame_data); scic_sds_controller_copy_sata_response( - &this_phy->phy_type.sata.signature_fis_buffer, + &sci_phy->phy_type.sata.signature_fis_buffer, frame_words, - fis_frame_data - ); + fis_frame_data); /* We got the IAF we can now go to the await spinup semaphore state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL - ); + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); result = SCI_SUCCESS; } else - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected frame id %x\n", __func__, frame_index); /* Regardless of the result release this frame since we are done with it */ - scic_sds_controller_release_frame( - scic_sds_phy_get_controller(this_phy), frame_index - ); + scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), + frame_index); return result; } @@ -1394,7 +1358,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle * ***************************************************************************** */ /** - * + * scic_sds_phy_starting_substate_await_sas_power_consume_power_handler - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy * object. * @@ -1404,19 +1368,17 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle * SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_power_handler( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { u32 enable_spinup; - enable_spinup = SCU_SAS_ENSPINUP_READ(this_phy); + enable_spinup = SCU_SAS_ENSPINUP_READ(sci_phy); enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); - SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup); + SCU_SAS_ENSPINUP_WRITE(sci_phy, enable_spinup); /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL - ); + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); return SCI_SUCCESS; } @@ -1431,27 +1393,25 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_po * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_power_handler( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { u32 scu_sas_pcfg_value; /* Release the spinup hold state and reset the OOB state machine */ - scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + scu_sas_pcfg_value = SCU_SAS_PCFG_READ(sci_phy); scu_sas_pcfg_value &= ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + SCU_SAS_PCFG_WRITE(sci_phy, scu_sas_pcfg_value); /* Now restart the OOB operation */ scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); - SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + SCU_SAS_PCFG_WRITE(sci_phy, scu_sas_pcfg_value); /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN - ); + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); return SCI_SUCCESS; } @@ -1566,7 +1526,7 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t * **************************************************************************** */ /** - * + * scic_sds_phy_starting_initial_substate_enter - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on @@ -1574,21 +1534,18 @@ const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_t * handlers are put in place for the struct scic_sds_phy object. - The state is * changed to the wait phy type event notification. none */ -static void scic_sds_phy_starting_initial_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); /* This is just an temporary state go off to the starting state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_starting_substate_machine(this_phy), - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN - ); + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN); } /** @@ -1892,23 +1849,20 @@ static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( * object state handlers for this state. - Change base state machine to the * ready state. none */ -static void scic_sds_phy_starting_final_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_final_substate_enter(struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = container_of(object, typeof(*sci_phy), parent.parent); - scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL - ); + scic_sds_phy_set_starting_substate_handlers(sci_phy, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); - /* - * State machine has run to completion so exit out and change - * the base state machine to the ready state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), - SCI_BASE_PHY_STATE_READY); + /* State machine has run to completion so exit out and change + * the base state machine to the ready state + */ + sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + SCI_BASE_PHY_STATE_READY); } /* --------------------------------------------------------------------------- */ @@ -2150,153 +2104,85 @@ enum sci_status scic_sds_phy_default_consume_power_handler( * attempts to start it. - The phy state machine is transitioned to the * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS */ -static enum sci_status scic_sds_phy_stopped_state_start_handler( - struct sci_base_phy *phy) +static enum sci_status scic_sds_phy_stopped_state_start_handler(struct sci_base_phy *base_phy) { - struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)phy; - struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost; + struct scic_sds_phy *sci_phy; + struct scic_sds_controller *scic; + + sci_phy = container_of(base_phy, typeof(*sci_phy), parent); + scic = scic_sds_phy_get_controller(sci_phy), + ihost = sci_object_get_association(scic); /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = - isci_timer_create( - ihost, - sci_phy, - scic_sds_phy_sata_timeout); + sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, + scic_sds_phy_sata_timeout); - if (sci_phy->sata_timeout_timer != NULL) { - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(sci_phy), - SCI_BASE_PHY_STATE_STARTING); - } + if (sci_phy->sata_timeout_timer) + sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + SCI_BASE_PHY_STATE_STARTING); return SCI_SUCCESS; } -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * - * This method takes the struct scic_sds_phy from a stopped state and destroys it. - - * This function takes no action. Shouldnt this function transition the - * struct sci_base_phy::state_machine to the SCI_BASE_PHY_STATE_FINAL? enum sci_status - * SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_stopped_state_destroy_handler( - struct sci_base_phy *phy) +static enum sci_status scic_sds_phy_stopped_state_destroy_handler(struct sci_base_phy *base_phy) { - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)phy; - - /* @todo what do we actually need to do here? */ return SCI_SUCCESS; } -/* - * ****************************************************************************** - * * PHY STARTING STATE HANDLERS - * ****************************************************************************** */ - -/* All of these state handlers are mapped to the starting sub-state machine */ - -/* - * ****************************************************************************** - * * PHY READY STATE HANDLERS - * ****************************************************************************** */ - -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * - * This method takes the struct scic_sds_phy from a ready state and attempts to stop - * it. - The phy state machine is transitioned to the - * SCI_BASE_PHY_STATE_STOPPED. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_ready_state_stop_handler( - struct sci_base_phy *phy) +static enum sci_status scic_sds_phy_ready_state_stop_handler(struct sci_base_phy *base_phy) { - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)phy; - - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), - SCI_BASE_PHY_STATE_STOPPED - ); + sci_base_state_machine_change_state(&base_phy->state_machine, + SCI_BASE_PHY_STATE_STOPPED); return SCI_SUCCESS; } -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * - * This method takes the struct scic_sds_phy from a ready state and attempts to reset - * it. - The phy state machine is transitioned to the - * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_ready_state_reset_handler( - struct sci_base_phy *phy) +static enum sci_status scic_sds_phy_ready_state_reset_handler(struct sci_base_phy *base_phy) { - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)phy; - - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), - SCI_BASE_PHY_STATE_RESETTING - ); + sci_base_state_machine_change_state(&base_phy->state_machine, + SCI_BASE_PHY_STATE_RESETTING); return SCI_SUCCESS; } /** - * + * scic_sds_phy_ready_state_event_handler - * @phy: This is the struct scic_sds_phy object which has received the event. * * This method request the struct scic_sds_phy handle the received event. The only * event that we are interested in while in the ready state is the link failure * event. - decoded event is a link failure - transition the struct scic_sds_phy back - * to the SCI_BASE_PHY_STATE_STARTING state. - any other event recived will + * to the SCI_BASE_PHY_STATE_STARTING state. - any other event received will * report a warning message enum sci_status SCI_SUCCESS if the event received is a * link failure SCI_FAILURE_INVALID_STATE for any other event received. */ -static enum sci_status scic_sds_phy_ready_state_event_handler( - struct scic_sds_phy *this_phy, - u32 event_code) +static enum sci_status scic_sds_phy_ready_state_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) { enum sci_status result = SCI_FAILURE; switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), - SCI_BASE_PHY_STATE_STARTING - ); - + sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + SCI_BASE_PHY_STATE_STARTING); result = SCI_SUCCESS; break; case SCU_EVENT_BROADCAST_CHANGE: /* Broadcast change received. Notify the port. */ - if (scic_sds_phy_get_port(this_phy) != NULL) - scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); + if (scic_sds_phy_get_port(sci_phy) != NULL) + scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); else - this_phy->bcn_received_while_port_unassigned = true; + sci_phy->bcn_received_while_port_unassigned = true; break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%sP SCIC PHY 0x%p ready state machine received " "unexpected event_code %x\n", - __func__, - this_phy, - event_code); + __func__, sci_phy, event_code); result = SCI_FAILURE_INVALID_STATE; break; @@ -2305,40 +2191,24 @@ static enum sci_status scic_sds_phy_ready_state_event_handler( return result; } -/* --------------------------------------------------------------------------- */ - -/** - * - * @this_phy: This is the struct scic_sds_phy object which is receiving the event. - * @event_code: This is the event code to be processed. - * - * This is the resetting state event handler. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_phy_resetting_state_event_handler( - struct scic_sds_phy *this_phy, - u32 event_code) +static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) { enum sci_status result = SCI_FAILURE; switch (scu_get_event_code(event_code)) { case SCU_EVENT_HARD_RESET_TRANSMITTED: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state( - scic_sds_phy_get_base_state_machine(this_phy), - SCI_BASE_PHY_STATE_STARTING - ); - + sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + SCI_BASE_PHY_STATE_STARTING); result = SCI_SUCCESS; break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: SCIC PHY 0x%p resetting state machine received " "unexpected event_code %x\n", - __func__, - this_phy, - event_code); + __func__, sci_phy, event_code); result = SCI_FAILURE_INVALID_STATE; break; diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index b611e33180b2..af9e24c30945 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -316,24 +316,6 @@ extern const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_ha #define scic_sds_phy_get_controller(phy) \ (scic_sds_port_get_controller((phy)->owning_port)) -/** - * scic_sds_phy_get_base_state_machine() - This macro returns the state machine - * for the base phy - * - * - */ -#define scic_sds_phy_get_base_state_machine(phy) \ - (&(phy)->parent.state_machine) - -/** - * scic_sds_phy_get_starting_substate_machine() - This macro returns the - * starting substate machine for this phy - * - * - */ -#define scic_sds_phy_get_starting_substate_machine(phy) \ - (&(phy)->starting_substate_machine) - /** * scic_sds_phy_set_state_handlers() - This macro sets the state handlers for * this phy object @@ -354,27 +336,6 @@ extern const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_ha &scic_sds_phy_state_handler_table[(state_id)] \ ) -/** - * scic_sds_phy_is_ready() - - * - * This macro returns true if the current base state for this phy is - * SCI_BASE_PHY_STATE_READY - */ -#define scic_sds_phy_is_ready(phy) \ - (\ - SCI_BASE_PHY_STATE_READY \ - == sci_base_state_machine_get_state(\ - scic_sds_phy_get_base_state_machine(phy) \ - ) \ - ) - -/* --------------------------------------------------------------------------- */ - - - - -/* --------------------------------------------------------------------------- */ - void scic_sds_phy_construct( struct scic_sds_phy *this_phy, struct scic_sds_port *owning_port, @@ -404,8 +365,6 @@ enum sci_status scic_sds_phy_reset( void scic_sds_phy_sata_timeout( void *cookie); -/* --------------------------------------------------------------------------- */ - void scic_sds_phy_suspend( struct scic_sds_phy *this_phy); @@ -416,8 +375,6 @@ void scic_sds_phy_setup_transport( struct scic_sds_phy *this_phy, u32 device_id); -/* --------------------------------------------------------------------------- */ - enum sci_status scic_sds_phy_event_handler( struct scic_sds_phy *this_phy, u32 event_code); @@ -445,11 +402,6 @@ void scic_sds_phy_get_attached_phy_protocols( struct scic_sds_phy *this_phy, struct sci_sas_identify_address_frame_protocols *protocols); -/* - * ****************************************************************************- - * * SCIC SDS PHY Handler Methods - * ****************************************************************************- */ - enum sci_status scic_sds_phy_default_start_handler( struct sci_base_phy *phy); diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 3ae0f0d80f1f..72b815ef98ca 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -576,12 +576,10 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, sci_base_port_construct(&sci_port->parent, scic_sds_port_state_table); - sci_base_state_machine_construct( - scic_sds_port_get_ready_substate_machine(sci_port), - &sci_port->parent.parent, - scic_sds_port_ready_substate_table, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING - ); + sci_base_state_machine_construct(&sci_port->ready_substate_machine, + &sci_port->parent.parent, + scic_sds_port_ready_substate_table, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; sci_port->physical_port_index = port_index; @@ -1339,9 +1337,9 @@ static void scic_sds_port_ready_operational_substate_link_up_handler( /** * scic_sds_port_ready_operational_substate_link_down_handler() - - * @this_port: This is the struct scic_sds_port object that which has a phy that has + * @sci_port: This is the struct scic_sds_port object that which has a phy that has * gone link down. - * @the_phy: This is the struct scic_sds_phy object that has gone link down. + * @sci_phy: This is the struct scic_sds_phy object that has gone link down. * * This method is the ready operational substate link down handler for the * struct scic_sds_port object. This function notifies the SCI User that the phy has @@ -1349,21 +1347,18 @@ static void scic_sds_port_ready_operational_substate_link_up_handler( * state to the ready waiting substate. none */ static void scic_sds_port_ready_operational_substate_link_down_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - scic_sds_port_deactivate_phy(this_port, the_phy, true); + scic_sds_port_deactivate_phy(sci_port, sci_phy, true); /* * If there are no active phys left in the port, then transition * the port to the WAITING state until such time as a phy goes * link up. */ - if (this_port->active_phy_mask == 0) { - sci_base_state_machine_change_state( - scic_sds_port_get_ready_substate_machine(this_port), - SCIC_SDS_PORT_READY_SUBSTATE_WAITING - ); - } + if (sci_port->active_phy_mask == 0) + sci_base_state_machine_change_state(&sci_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); } /** @@ -1820,169 +1815,52 @@ const struct sci_base_state scic_sds_port_ready_substate_table[] = { }, }; -/* - * *************************************************************************** - * * DEFAULT HANDLERS - * *************************************************************************** */ - -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for port a start request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_port_default_start_handler( - struct sci_base_port *port) +static enum sci_status default_port_handler(struct sci_base_port *base_port, const char *func) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)port; + struct scic_sds_port *sci_port; + sci_port = container_of(base_port, typeof(*sci_port), parent); dev_warn(sciport_to_dev(sci_port), - "%s: SCIC Port 0x%p requested to start while in invalid " - "state %d\n", - __func__, - port, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine( - (struct scic_sds_port *)port))); - + "%s: in wrong state: %d\n", func, + sci_base_state_machine_get_state(&base_port->state_machine)); return SCI_FAILURE_INVALID_STATE; } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port stop request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_default_stop_handler( - struct sci_base_port *port) +enum sci_status scic_sds_port_default_start_handler(struct sci_base_port *base_port) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)port; - - dev_warn(sciport_to_dev(sci_port), - "%s: SCIC Port 0x%p requested to stop while in invalid " - "state %d\n", - __func__, - port, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine( - (struct scic_sds_port *)port))); - - return SCI_FAILURE_INVALID_STATE; + return default_port_handler(base_port, __func__); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port destruct request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_port_default_destruct_handler( - struct sci_base_port *port) +static enum sci_status scic_sds_port_default_stop_handler(struct sci_base_port *base_port) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)port; - - dev_warn(sciport_to_dev(sci_port), - "%s: SCIC Port 0x%p requested to destruct while in invalid " - "state %d\n", - __func__, - port, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine( - (struct scic_sds_port *)port))); - - return SCI_FAILURE_INVALID_STATE; + return default_port_handler(base_port, __func__); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * @timeout: This is the timeout for the reset request to complete. - * - * This is the default method for a port reset request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_port_default_reset_handler( - struct sci_base_port *port, - u32 timeout) +enum sci_status scic_sds_port_default_destruct_handler(struct sci_base_port *base_port) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)port; - - dev_warn(sciport_to_dev(sci_port), - "%s: SCIC Port 0x%p requested to reset while in invalid " - "state %d\n", - __func__, - port, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine( - (struct scic_sds_port *)port))); - - return SCI_FAILURE_INVALID_STATE; + return default_port_handler(base_port, __func__); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port add phy request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_default_add_phy_handler( - struct sci_base_port *port, - struct sci_base_phy *phy) +enum sci_status scic_sds_port_default_reset_handler(struct sci_base_port *base_port, + u32 timeout) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)port; - - dev_warn(sciport_to_dev(sci_port), - "%s: SCIC Port 0x%p requested to add phy 0x%p while in " - "invalid state %d\n", - __func__, - port, - phy, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine( - (struct scic_sds_port *)port))); - - return SCI_FAILURE_INVALID_STATE; + return default_port_handler(base_port, __func__); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port remove phy request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_port_default_remove_phy_handler( - struct sci_base_port *port, - struct sci_base_phy *phy) +static enum sci_status scic_sds_port_default_add_phy_handler(struct sci_base_port *base_port, + struct sci_base_phy *base_phy) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)port; - - dev_warn(sciport_to_dev(sci_port), - "%s: SCIC Port 0x%p requested to remove phy 0x%p while in " - "invalid state %d\n", - __func__, - port, - phy, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine( - (struct scic_sds_port *)port))); + return default_port_handler(base_port, __func__); +} - return SCI_FAILURE_INVALID_STATE; +enum sci_status scic_sds_port_default_remove_phy_handler(struct sci_base_port *base_port, + struct sci_base_phy *base_phy) +{ + return default_port_handler(base_port, __func__); } /** - * + * scic_sds_port_default_frame_handler * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port * object. * @@ -1991,149 +1869,48 @@ enum sci_status scic_sds_port_default_remove_phy_handler( * possible to receive an unsolicited frame directed to a port object? It * seems possible if we implementing virtual functions but until then? */ -enum sci_status scic_sds_port_default_frame_handler( - struct scic_sds_port *port, - u32 frame_index) -{ - dev_warn(sciport_to_dev(port), - "%s: SCIC Port 0x%p requested to process frame %d while in " - "invalid state %d\n", - __func__, - port, - frame_index, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine(port))); - - scic_sds_controller_release_frame( - scic_sds_port_get_controller(port), frame_index - ); - - return SCI_FAILURE_INVALID_STATE; -} +enum sci_status scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port, + u32 frame_index) +{ + struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port event request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_port_default_event_handler( - struct scic_sds_port *port, - u32 event_code) -{ - dev_warn(sciport_to_dev(port), - "%s: SCIC Port 0x%p requested to process event 0x%x while " - "in invalid state %d\n", - __func__, - port, - event_code, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine( - (struct scic_sds_port *)port))); + default_port_handler(&sci_port->parent, __func__); + scic_sds_controller_release_frame(scic, frame_index); return SCI_FAILURE_INVALID_STATE; } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port link up notification. It will report - * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -void scic_sds_port_default_link_up_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy) +enum sci_status scic_sds_port_default_event_handler(struct scic_sds_port *sci_port, + u32 event_code) { - dev_warn(sciport_to_dev(this_port), - "%s: SCIC Port 0x%p received link_up notification from phy " - "0x%p while in invalid state %d\n", - __func__, - this_port, - phy, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine(this_port))); + return default_port_handler(&sci_port->parent, __func__); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port link down notification. It will - * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -void scic_sds_port_default_link_down_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy) +void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - dev_warn(sciport_to_dev(this_port), - "%s: SCIC Port 0x%p received link down notification from " - "phy 0x%p while in invalid state %d\n", - __func__, - this_port, - phy, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine(this_port))); + default_port_handler(&sci_port->parent, __func__); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port start io request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_port_default_start_io_handler( - struct scic_sds_port *this_port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) +void scic_sds_port_default_link_down_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - dev_warn(sciport_to_dev(this_port), - "%s: SCIC Port 0x%p requested to start io request 0x%p " - "while in invalid state %d\n", - __func__, - this_port, - io_request, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine(this_port))); - - return SCI_FAILURE_INVALID_STATE; + default_port_handler(&sci_port->parent, __func__); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port complete io request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_default_complete_io_handler( - struct scic_sds_port *this_port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) +enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) { - dev_warn(sciport_to_dev(this_port), - "%s: SCIC Port 0x%p requested to complete io request 0x%p " - "while in invalid state %d\n", - __func__, - this_port, - io_request, - sci_base_state_machine_get_state( - scic_sds_port_get_base_state_machine(this_port))); - - return SCI_FAILURE_INVALID_STATE; + return default_port_handler(&sci_port->parent, __func__); } -/* - * **************************************************************************** - * * GENERAL STATE HANDLERS - * **************************************************************************** */ +static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + return default_port_handler(&sci_port->parent, __func__); +} /** * @@ -2160,11 +1937,6 @@ static enum sci_status scic_sds_port_general_complete_io_handler( return SCI_SUCCESS; } -/* - * **************************************************************************** - * * STOPPED STATE HANDLERS - * **************************************************************************** */ - /** * scic_sds_port_stopped_state_start_handler() - stop a port from "started" * @@ -2242,9 +2014,8 @@ scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port) * silicon. */ if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { - sci_base_state_machine_change_state( - scic_sds_port_get_base_state_machine(sci_port), - SCI_BASE_PORT_STATE_READY); + sci_base_state_machine_change_state(&base_port->state_machine, + SCI_BASE_PORT_STATE_READY); return SCI_SUCCESS; } else @@ -2390,19 +2161,15 @@ static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( * object will transition to the stopped state. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( - struct scic_sds_port *port, + struct scic_sds_port *sci_port, struct scic_sds_remote_device *device, struct scic_sds_request *io_request) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; - - scic_sds_port_decrement_request_count(this_port); + scic_sds_port_decrement_request_count(sci_port); - if (this_port->started_request_count == 0) { - sci_base_state_machine_change_state( - scic_sds_port_get_base_state_machine(this_port), - SCI_BASE_PORT_STATE_STOPPED - ); + if (sci_port->started_request_count == 0) { + sci_base_state_machine_change_state(&sci_port->parent.state_machine, + SCI_BASE_PORT_STATE_STOPPED); } return SCI_SUCCESS; @@ -2727,9 +2494,8 @@ static void scic_sds_port_stopped_state_exit( } /** - * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_port object. + * scic_sds_port_ready_state_enter - + * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state @@ -2738,50 +2504,40 @@ static void scic_sds_port_stopped_state_exit( */ static void scic_sds_port_ready_state_enter(struct sci_base_object *object) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; - struct isci_port *iport = sci_object_get_association(sci_port); - struct scic_sds_controller *scic = - scic_sds_port_get_controller(sci_port); - struct isci_host *ihost = sci_object_get_association(scic); + struct scic_sds_controller *scic; + struct scic_sds_port *sci_port; + struct isci_port *iport; + struct isci_host *ihost; + u32 prev_state; - /* - * Put the ready state handlers in place though they will not be - * there long - */ - scic_sds_port_set_base_state_handlers(sci_port, - SCI_BASE_PORT_STATE_READY); + sci_port = container_of(object, typeof(*sci_port), parent.parent); + scic = scic_sds_port_get_controller(sci_port); + ihost = sci_object_get_association(scic); + iport = sci_object_get_association(sci_port); - if (sci_port->parent.state_machine.previous_state_id == - SCI_BASE_PORT_STATE_RESETTING) + /* Put the ready state handlers in place though they will not be there long */ + scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_READY); + + prev_state = sci_port->parent.state_machine.previous_state_id; + if (prev_state == SCI_BASE_PORT_STATE_RESETTING) isci_port_hard_reset_complete(iport, SCI_SUCCESS); - else /* Notify the caller that the port is not yet ready */ + else isci_port_not_ready(ihost, iport); /* Post and suspend the dummy remote node context for this port. */ scic_sds_port_post_dummy_remote_node(sci_port); /* Start the ready substate machine */ - sci_base_state_machine_start( - scic_sds_port_get_ready_substate_machine(sci_port)); + sci_base_state_machine_start(&sci_port->ready_substate_machine); } -/** - * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * exiting the SCI_BASE_STATE_READY. This function does nothing. none - */ -static void scic_sds_port_ready_state_exit( - struct sci_base_object *object) +static void scic_sds_port_ready_state_exit(struct sci_base_object *object) { - struct scic_sds_port *this_port; - - this_port = (struct scic_sds_port *)object; - - sci_base_state_machine_stop(&this_port->ready_substate_machine); + struct scic_sds_port *sci_port; - scic_sds_port_invalidate_dummy_remote_node(this_port); + sci_port = container_of(object, typeof(*sci_port), parent.parent); + sci_base_state_machine_stop(&sci_port->ready_substate_machine); + scic_sds_port_invalidate_dummy_remote_node(sci_port); } /** diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index c98caefa7cf2..ac81a92c348a 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -250,14 +250,6 @@ extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_t #define scic_sds_port_get_controller(this_port) \ ((this_port)->owning_controller) -/** - * scic_sds_port_get_base_state_machine() - - * - * Helper macro to get the base state machine for this port - */ -#define scic_sds_port_get_base_state_machine(this_port) \ - (&(this_port)->parent.state_machine) - /** * scic_sds_port_set_base_state_handlers() - * @@ -267,14 +259,6 @@ extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_t scic_sds_port_set_state_handlers(\ (this_port), &scic_sds_port_state_handler_table[(state_id)]) -/** - * scic_sds_port_get_ready_substate_machine() - - * - * Helper macro to get the ready substate machine for this port - */ -#define scic_sds_port_get_ready_substate_machine(this_port) \ - (&(this_port)->ready_substate_machine) - /** * scic_sds_port_set_state_handlers() - * diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index f722678eed8e..05599d178caa 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -135,8 +135,7 @@ enum sci_status scic_remote_device_da_construct( &remote_node_index); if (status == SCI_SUCCESS) { - scic_sds_remote_node_context_set_remote_node_index( - sci_dev->rnc, remote_node_index); + sci_dev->rnc->remote_node_index = remote_node_index; scic_sds_port_get_attached_sas_address( sci_dev->owning_port, &sci_dev->device_address); @@ -510,16 +509,14 @@ bool scic_sds_remote_device_is_atapi( static void scic_sds_cb_remote_device_rnc_destruct_complete( void *user_parameter) { - struct scic_sds_remote_device *this_device; + struct scic_sds_remote_device *sci_dev; - this_device = (struct scic_sds_remote_device *)user_parameter; + sci_dev = (struct scic_sds_remote_device *)user_parameter; - BUG_ON(this_device->started_request_count != 0); + BUG_ON(sci_dev->started_request_count != 0); - sci_base_state_machine_change_state( - scic_sds_remote_device_get_base_state_machine(this_device), - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED - ); + sci_base_state_machine_change_state(&sci_dev->parent.state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); } /** @@ -649,206 +646,64 @@ static enum sci_status scic_sds_remote_device_terminate_requests( return status; } -/* - * ***************************************************************************** - * * DEFAULT STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * - * This method is the default start handler. It logs a warning and returns a - * failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_remote_device_default_start_handler( - struct sci_base_remote_device *device) +static enum sci_status default_device_handler(struct sci_base_remote_device *base_dev, + const char *func) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to start while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - sds_device))); + struct scic_sds_remote_device *sci_dev; + sci_dev = container_of(base_dev, typeof(*sci_dev), parent); + dev_warn(scirdev_to_dev(sci_dev), + "%s: in wrong state: %d\n", func, + sci_base_state_machine_get_state(&base_dev->state_machine)); return SCI_FAILURE_INVALID_STATE; } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * - * This method is the default stop handler. It logs a warning and returns a - * failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_remote_device_default_stop_handler( - struct sci_base_remote_device *device) +enum sci_status scic_sds_remote_device_default_start_handler( + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to stop while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - sds_device))); + return default_device_handler(base_dev, __func__); +} - return SCI_FAILURE_INVALID_STATE; +static enum sci_status scic_sds_remote_device_default_stop_handler( + struct sci_base_remote_device *base_dev) +{ + return default_device_handler(base_dev, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * - * This method is the default fail handler. It logs a warning and returns a - * failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_fail_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to fail while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - sds_device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(base_dev, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * - * This method is the default destruct handler. It logs a warning and returns - * a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_destruct_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to destroy while in " - "wrong state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - sds_device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(base_dev, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * - * This method is the default reset handler. It logs a warning and returns a - * failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_reset_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to reset while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - sds_device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(base_dev, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * - * This method is the default reset complete handler. It logs a warning and - * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_reset_complete_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to complete reset while " - "in wrong state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - sds_device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(base_dev, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * - * This method is the default suspend handler. It logs a warning and returns a - * failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_suspend_handler( - struct scic_sds_remote_device *this_device, - u32 suspend_type) + struct scic_sds_remote_device *sci_dev, u32 suspend_type) { - dev_warn(scirdev_to_dev(this_device), - "%s: SCIC Remote Device 0x%p requested to suspend %d while " - "in wrong state %d\n", - __func__, - this_device, - suspend_type, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - this_device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(&sci_dev->parent, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * - * This method is the default resume handler. It logs a warning and returns a - * failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_resume_handler( - struct scic_sds_remote_device *this_device) + struct scic_sds_remote_device *sci_dev) { - dev_warn(scirdev_to_dev(this_device), - "%s: SCIC Remote Device requested to resume while in " - "wrong state %d\n", - __func__, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - this_device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(&sci_dev->parent, __func__); } /** @@ -960,109 +815,27 @@ enum sci_status scic_sds_remote_device_default_frame_handler( return SCI_FAILURE_INVALID_STATE; } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST - * to start. - * - * This method is the default start io handler. It logs a warning and returns - * a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_start_request_handler( - struct sci_base_remote_device *device, + struct sci_base_remote_device *base_dev, struct sci_base_request *request) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to start io request %p " - "while in wrong state %d\n", - __func__, - request, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - (struct scic_sds_remote_device *)device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(base_dev, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST - * to complete. - * - * This method is the default complete io handler. It logs a warning and - * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_complete_request_handler( - struct sci_base_remote_device *device, + struct sci_base_remote_device *base_dev, struct sci_base_request *request) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to complete io_request %p " - "while in wrong state %d\n", - __func__, - request, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - sds_device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(base_dev, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST - * to continue. - * - * This method is the default continue io handler. It logs a warning and - * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ enum sci_status scic_sds_remote_device_default_continue_request_handler( - struct sci_base_remote_device *device, + struct sci_base_remote_device *base_dev, struct sci_base_request *request) { - struct scic_sds_remote_device *sds_device = - (struct scic_sds_remote_device *)device; - - dev_warn(scirdev_to_dev(sds_device), - "%s: SCIC Remote Device requested to continue io request %p " - "while in wrong state %d\n", - __func__, - request, - sci_base_state_machine_get_state( - scic_sds_remote_device_get_base_state_machine( - sds_device))); - - return SCI_FAILURE_INVALID_STATE; + return default_device_handler(base_dev, __func__); } -/** - * - * @device: The struct sci_base_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST - * to complete. - * - * This method is the default complete task handler. It logs a warning and - * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ - -/* - * ***************************************************************************** - * * NORMAL STATE HANDLERS - * ***************************************************************************** */ - /** * * @device: The struct sci_base_remote_device which is then cast into a @@ -1146,45 +919,32 @@ enum sci_status scic_sds_remote_device_general_event_handler( * which to construct the remote device. */ static enum sci_status scic_sds_remote_device_stopped_state_start_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { enum sci_status status; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_remote_device *sci_dev; - status = scic_sds_remote_node_context_resume( - this_device->rnc, - scic_sds_remote_device_resume_complete_handler, - this_device - ); + sci_dev = container_of(base_dev, typeof(*sci_dev), parent); - if (status == SCI_SUCCESS) { - sci_base_state_machine_change_state( - scic_sds_remote_device_get_base_state_machine(this_device), - SCI_BASE_REMOTE_DEVICE_STATE_STARTING - ); - } + status = scic_sds_remote_node_context_resume(sci_dev->rnc, + scic_sds_remote_device_resume_complete_handler, sci_dev); + + if (status == SCI_SUCCESS) + sci_base_state_machine_change_state(&base_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STARTING); return status; } -/** - * - * @this_device: The struct sci_base_remote_device which is cast into a - * struct scic_sds_remote_device. - * - * This method will stop a struct scic_sds_remote_device that is already in a stopped - * state. This is not considered an error since the device is already stopped. - * enum sci_status SCI_SUCCESS - */ static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( - struct sci_base_remote_device *this_device) + struct sci_base_remote_device *base_dev) { return SCI_SUCCESS; } /** * - * @this_device: The struct sci_base_remote_device which is cast into a + * @sci_dev: The struct sci_base_remote_device which is cast into a * struct scic_sds_remote_device. * * This method will destruct a struct scic_sds_remote_device that is in a stopped @@ -1194,25 +954,19 @@ static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( * enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - - scic_sds_controller_free_remote_node_context( - scic_sds_remote_device_get_controller(this_device), - this_device, - this_device->rnc->remote_node_index - ); + struct scic_sds_remote_device *sci_dev; + struct scic_sds_controller *scic; - scic_sds_remote_node_context_set_remote_node_index( - this_device->rnc, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX - ); + sci_dev = container_of(base_dev, typeof(*sci_dev), parent); + scic = scic_sds_remote_device_get_controller(sci_dev); + scic_sds_controller_free_remote_node_context(scic, sci_dev, + sci_dev->rnc->remote_node_index); + sci_dev->rnc->remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - sci_base_state_machine_change_state( - scic_sds_remote_device_get_base_state_machine(this_device), - SCI_BASE_REMOTE_DEVICE_STATE_FINAL - ); + sci_base_state_machine_change_state(&base_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_FINAL); return SCI_SUCCESS; } @@ -1223,86 +977,49 @@ static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( * ***************************************************************************** */ static enum sci_status scic_sds_remote_device_starting_state_stop_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_remote_device *sci_dev; + sci_dev = container_of(base_dev, typeof(*sci_dev), parent); /* * This device has not yet started so there had better be no IO requests */ - BUG_ON(this_device->started_request_count != 0); + BUG_ON(sci_dev->started_request_count != 0); /* * Destroy the remote node context */ - scic_sds_remote_node_context_destruct( - this_device->rnc, - scic_sds_cb_remote_device_rnc_destruct_complete, - this_device - ); + scic_sds_remote_node_context_destruct(sci_dev->rnc, + scic_sds_cb_remote_device_rnc_destruct_complete, sci_dev); /* * Transition to the stopping state and wait for the remote node to * complete being posted and invalidated. */ - sci_base_state_machine_change_state( - scic_sds_remote_device_get_base_state_machine(this_device), - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING - ); + sci_base_state_machine_change_state(&base_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); return SCI_SUCCESS; } -/* - * ***************************************************************************** - * * INITIALIZING STATE HANDLERS - * ***************************************************************************** */ - -/* There is nothing to do here for SSP devices */ - -/* - * ***************************************************************************** - * * READY STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @this_device: The struct scic_sds_remote_device object to be suspended. - * - * This method is the resume handler for the struct scic_sds_remote_device object. It - * will post an RNC resume to the SCU hardware. enum sci_status SCI_SUCCESS - */ - -/** - * - * @device: The struct sci_base_remote_device object which is cast to a - * struct scic_sds_remote_device object. - * - * This method is the default stop handler for the struct scic_sds_remote_device ready - * substate machine. It will stop the current substate machine and transition - * the base state machine to SCI_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status - * SCI_SUCCESS - */ enum sci_status scic_sds_remote_device_ready_state_stop_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - enum sci_status status = SCI_SUCCESS; + struct scic_sds_remote_device *sci_dev; + enum sci_status status = SCI_SUCCESS; + sci_dev = container_of(base_dev, typeof(*sci_dev), parent); /* Request the parent state machine to transition to the stopping state */ - sci_base_state_machine_change_state( - scic_sds_remote_device_get_base_state_machine(this_device), - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING - ); + sci_base_state_machine_change_state(&base_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); - if (this_device->started_request_count == 0) { - scic_sds_remote_node_context_destruct( - this_device->rnc, + if (sci_dev->started_request_count == 0) { + scic_sds_remote_node_context_destruct(sci_dev->rnc, scic_sds_cb_remote_device_rnc_destruct_complete, - this_device - ); + sci_dev); } else - status = scic_sds_remote_device_terminate_requests(this_device); + status = scic_sds_remote_device_terminate_requests(sci_dev); return status; } @@ -1315,30 +1032,18 @@ enum sci_status scic_sds_remote_device_ready_state_stop_handler( * This is the ready state device reset handler enum sci_status */ enum sci_status scic_sds_remote_device_ready_state_reset_handler( - struct sci_base_remote_device *device) + struct sci_base_remote_device *base_dev) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; + struct scic_sds_remote_device *sci_dev; + sci_dev = container_of(base_dev, typeof(*sci_dev), parent); /* Request the parent state machine to transition to the stopping state */ - sci_base_state_machine_change_state( - scic_sds_remote_device_get_base_state_machine(this_device), - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING - ); + sci_base_state_machine_change_state(&base_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING); return SCI_SUCCESS; } -/** - * - * @device: The struct sci_base_remote_device object which is cast to a - * struct scic_sds_remote_device object. - * - * This is the default fail handler for the struct scic_sds_remote_device ready - * substate machine. It will stop the current ready substate and transition - * the remote device object to the SCI_BASE_REMOTE_DEVICE_STATE_FAILED. - * enum sci_status SCI_SUCCESS - */ - /** * * @device: The struct sci_base_remote_device which is cast to a @@ -1775,19 +1480,15 @@ const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_h static void scic_sds_remote_device_initial_state_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - SET_STATE_HANDLER( - this_device, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL - ); + sci_dev = container_of(object, typeof(*sci_dev), parent.parent); + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); /* Initial state is a transitional state to the stopped state */ - sci_base_state_machine_change_state( - scic_sds_remote_device_get_base_state_machine(this_device), - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED - ); + sci_base_state_machine_change_state(&sci_dev->parent.state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); } /** @@ -1803,29 +1504,28 @@ static void scic_sds_remote_device_initial_state_enter( static void scic_sds_remote_device_stopped_state_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)object; - struct scic_sds_controller *scic = - scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = - sci_object_get_association(sci_dev); + struct scic_sds_remote_device *sci_dev; + struct scic_sds_controller *scic; + struct isci_remote_device *idev; + struct isci_host *ihost; + u32 prev_state; - SET_STATE_HANDLER(sci_dev, - scic_sds_remote_device_state_handler_table, + sci_dev = container_of(object, typeof(*sci_dev), parent.parent); + scic = scic_sds_remote_device_get_controller(sci_dev); + ihost = sci_object_get_association(scic); + idev = sci_object_get_association(sci_dev); + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); - /* - * If we are entering from the stopping state let the SCI User know that + /* If we are entering from the stopping state let the SCI User know that * the stop operation has completed. */ - if (sci_dev->parent.state_machine.previous_state_id == - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) + prev_state = sci_dev->parent.state_machine.previous_state_id; + if (prev_state == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) isci_remote_device_stop_complete(ihost, idev, SCI_SUCCESS); - scic_sds_controller_remote_device_stopped( - scic_sds_remote_device_get_controller(sci_dev), - sci_dev); + scic_sds_controller_remote_device_stopped(scic, sci_dev); } /** diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index 4841e4579643..aa466249f229 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -376,22 +376,6 @@ extern const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_dev #define scic_sds_remote_device_set_state_handlers(this_device, handlers) \ ((this_device)->state_handlers = (handlers)) -/** - * scic_sds_remote_device_get_base_state_machine() - - * - * This macro returns the base sate machine object for the remote device. - */ -#define scic_sds_remote_device_get_base_state_machine(this_device) \ - (&(this_device)->parent.state_machine) - -/** - * scic_sds_remote_device_get_ready_substate_machine() - - * - * This macro returns the remote device ready substate machine - */ -#define scic_sds_remote_device_get_ready_substate_machine(this_device) \ - (&(this_device)->ready_substate_machine) - /** * scic_sds_remote_device_get_port() - * diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h index 86c6d75a1110..c7c75ae6f092 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.h +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h @@ -296,9 +296,6 @@ void scic_sds_remote_node_context_construct_buffer( bool scic_sds_remote_node_context_is_ready( struct scic_sds_remote_node_context *this_rnc); -#define scic_sds_remote_node_context_set_remote_node_index(rnc, rni) \ - ((rnc)->remote_node_index = (rni)) - #define scic_sds_remote_node_context_get_remote_node_index(rcn) \ ((rnc)->remote_node_index) -- cgit v1.2.3 From 35173d579a08c0d145b3020039d3ba33fbf2c184 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 26 Mar 2011 16:43:01 -0700 Subject: isci: namespacecheck cleanups * mark needlessly global routines static * delete unused functions * move kernel-doc blocks from header files to source * reorder some functions to delete declarations * more default handler cleanups phy Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_port.h | 12 - drivers/scsi/isci/core/scic_config_parameters.h | 13 - drivers/scsi/isci/core/scic_controller.h | 348 ----------- drivers/scsi/isci/core/scic_io_request.h | 2 +- drivers/scsi/isci/core/scic_port.h | 98 --- drivers/scsi/isci/core/scic_sds_controller.c | 675 +++++++++++++-------- drivers/scsi/isci/core/scic_sds_controller.h | 60 -- drivers/scsi/isci/core/scic_sds_phy.c | 324 +++------- drivers/scsi/isci/core/scic_sds_phy.h | 35 -- drivers/scsi/isci/core/scic_sds_port.c | 444 +++++++------- drivers/scsi/isci/core/scic_sds_port.h | 53 -- drivers/scsi/isci/core/scic_sds_remote_device.c | 48 +- drivers/scsi/isci/core/scic_sds_remote_device.h | 5 - .../scsi/isci/core/scic_sds_remote_node_context.c | 46 +- .../scsi/isci/core/scic_sds_remote_node_context.h | 8 - drivers/scsi/isci/core/scic_sds_request.c | 309 ++++------ drivers/scsi/isci/core/scic_sds_request.h | 7 - .../scsi/isci/core/scic_sds_smp_remote_device.c | 2 +- drivers/scsi/isci/core/scic_sds_smp_request.c | 137 +++-- drivers/scsi/isci/core/scic_sds_ssp_request.c | 2 +- drivers/scsi/isci/core/scic_sds_stp_pio_request.h | 11 - .../scsi/isci/core/scic_sds_stp_remote_device.c | 2 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 251 ++++---- drivers/scsi/isci/core/scic_sds_stp_request.h | 23 +- drivers/scsi/isci/firmware/README | 2 +- drivers/scsi/isci/port.c | 2 +- drivers/scsi/isci/request.c | 73 --- drivers/scsi/isci/request.h | 6 - drivers/scsi/isci/task.c | 11 +- drivers/scsi/isci/task.h | 10 - 30 files changed, 1056 insertions(+), 1963 deletions(-) diff --git a/drivers/scsi/isci/core/sci_base_port.h b/drivers/scsi/isci/core/sci_base_port.h index 4e2031d195f0..b931c3c2cdf9 100644 --- a/drivers/scsi/isci/core/sci_base_port.h +++ b/drivers/scsi/isci/core/sci_base_port.h @@ -188,16 +188,4 @@ struct sci_base_port_state_handler { SCI_BASE_PORT_PHY_HANDLER_T remove_phy_handler; }; - -/** - * sci_base_port_construct() - Construct the base port object - * @this_port: This parameter specifies the base port to be constructed. - * @state_table: This parameter specifies the table of state definitions to be - * utilized for the domain state machine. - * - */ -void sci_base_port_construct( - struct sci_base_port *this_port, - const struct sci_base_state *state_table); - #endif /* _SCI_BASE_PORT_H_ */ diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index f64f24fad5a3..cb6abcc7e7cd 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -260,19 +260,6 @@ enum sci_status scic_user_parameters_set( struct scic_sds_controller *controller, union scic_user_parameters *user_parameters); -/** - * scic_user_parameters_get() - This method allows the user to retrieve the - * user parameters utilized by the controller. - * @controller: This parameter specifies the controller on which to set the - * user parameters. - * @user_parameters: This parameter specifies the USER_PARAMETERS object into - * which the framework shall save it's parameters. - * - */ -void scic_user_parameters_get( - struct scic_sds_controller *controller, - union scic_user_parameters *user_parameters); - /** * scic_oem_parameters_set() - This method allows the user to attempt to change * the OEM parameters utilized by the controller. diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 481e0de5148b..236c583162ec 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -56,14 +56,6 @@ #ifndef _SCIC_CONTROLLER_H_ #define _SCIC_CONTROLLER_H_ -/** - * This file contains all of the interface methods that can be called by an - * SCIC user on a controller object. - * - * - */ - - #include "sci_status.h" #include "sci_controller.h" #include "scic_config_parameters.h" @@ -79,417 +71,77 @@ enum sci_controller_mode { SCI_MODE_SIZE /* Optimized for memory use */ }; - -/** - * scic_controller_construct() - This method will attempt to construct a - * controller object utilizing the supplied parameter information. - * @c: This parameter specifies the controller to be constructed. - * @scu_base: mapped base address of the scu registers - * @smu_base: mapped base address of the smu registers - * - * Indicate if the controller was successfully constructed or if it failed in - * some way. SCI_SUCCESS This value is returned if the controller was - * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned - * if the interrupt coalescence timer may cause SAS compliance issues for SMP - * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE - * This value is returned if the controller does not support the supplied type. - * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the - * controller does not support the supplied initialization data version. - */ enum sci_status scic_controller_construct(struct scic_sds_controller *c, void __iomem *scu_base, void __iomem *smu_base); -/** - * scic_controller_enable_interrupts() - This method will enable all controller - * interrupts. - * @controller: This parameter specifies the controller for which to enable - * interrupts. - * - */ void scic_controller_enable_interrupts( struct scic_sds_controller *controller); -/** - * scic_controller_disable_interrupts() - This method will disable all - * controller interrupts. - * @controller: This parameter specifies the controller for which to disable - * interrupts. - * - */ void scic_controller_disable_interrupts( struct scic_sds_controller *controller); - -/** - * scic_controller_initialize() - This method will initialize the controller - * hardware managed by the supplied core controller object. This method - * will bring the physical controller hardware out of reset and enable the - * core to determine the capabilities of the hardware being managed. Thus, - * the core controller can determine it's exact physical (DMA capable) - * memory requirements. - * @controller: This parameter specifies the controller to be initialized. - * - * The SCI Core user must have called scic_controller_construct() on the - * supplied controller object previously. Indicate if the controller was - * successfully initialized or if it failed in some way. SCI_SUCCESS This value - * is returned if the controller hardware was successfully initialized. - */ enum sci_status scic_controller_initialize( struct scic_sds_controller *controller); -/** - * scic_controller_get_suggested_start_timeout() - This method returns the - * suggested scic_controller_start() timeout amount. The user is free to - * use any timeout value, but this method provides the suggested minimum - * start timeout value. The returned value is based upon empirical - * information determined as a result of interoperability testing. - * @controller: the handle to the controller object for which to return the - * suggested start timeout. - * - * This method returns the number of milliseconds for the suggested start - * operation timeout. - */ u32 scic_controller_get_suggested_start_timeout( struct scic_sds_controller *controller); -/** - * scic_controller_start() - This method will start the supplied core - * controller. This method will start the staggered spin up operation. The - * SCI User completion callback is called when the following conditions are - * met: -# the return status of this method is SCI_SUCCESS. -# after all of - * the phys have successfully started or been given the opportunity to start. - * @controller: the handle to the controller object to start. - * @timeout: This parameter specifies the number of milliseconds in which the - * start operation should complete. - * - * The SCI Core user must have filled in the physical memory descriptor - * structure via the sci_controller_get_memory_descriptor_list() method. The - * SCI Core user must have invoked the scic_controller_initialize() method - * prior to invoking this method. The controller must be in the INITIALIZED or - * STARTED state. Indicate if the controller start method succeeded or failed - * in some way. SCI_SUCCESS if the start operation succeeded. - * SCI_WARNING_ALREADY_IN_STATE if the controller is already in the STARTED - * state. SCI_FAILURE_INVALID_STATE if the controller is not either in the - * INITIALIZED or STARTED states. SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if - * there are inconsistent or invalid values in the supplied - * struct sci_physical_memory_descriptor array. - */ enum sci_status scic_controller_start( struct scic_sds_controller *controller, u32 timeout); -/** - * scic_controller_stop() - This method will stop an individual controller - * object.This method will invoke the associated user callback upon - * completion. The completion callback is called when the following - * conditions are met: -# the method return status is SCI_SUCCESS. -# the - * controller has been quiesced. This method will ensure that all IO - * requests are quiesced, phys are stopped, and all additional operation by - * the hardware is halted. - * @controller: the handle to the controller object to stop. - * @timeout: This parameter specifies the number of milliseconds in which the - * stop operation should complete. - * - * The controller must be in the STARTED or STOPPED state. Indicate if the - * controller stop method succeeded or failed in some way. SCI_SUCCESS if the - * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the - * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the - * controller is not either in the STARTED or STOPPED states. - */ enum sci_status scic_controller_stop( struct scic_sds_controller *controller, u32 timeout); -/** - * scic_controller_reset() - This method will reset the supplied core - * controller regardless of the state of said controller. This operation is - * considered destructive. In other words, all current operations are wiped - * out. No IO completions for outstanding devices occur. Outstanding IO - * requests are not aborted or completed at the actual remote device. - * @controller: the handle to the controller object to reset. - * - * Indicate if the controller reset method succeeded or failed in some way. - * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if - * the controller reset operation is unable to complete. - */ enum sci_status scic_controller_reset( struct scic_sds_controller *controller); -/** - * scic_controller_start_io() - This method is called by the SCI user to - * send/start an IO request. If the method invocation is successful, then - * the IO request has been queued to the hardware for processing. - * @controller: the handle to the controller object for which to start an IO - * request. - * @remote_device: the handle to the remote device object for which to start an - * IO request. - * @io_request: the handle to the io request object to start. - * @io_tag: This parameter specifies a previously allocated IO tag that the - * user desires to be utilized for this request. This parameter is optional. - * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value - * for this parameter. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a - * result, it is expected the user will have set the NCQ tag field in the host - * to device register FIS prior to calling this method. There is also a - * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking - * the scic_controller_start_io() method. scic_controller_allocate_tag() for - * more information on allocating a tag. Indicate if the controller - * successfully started the IO request. SCI_IO_SUCCESS if the IO request was - * successfully started. Determine the failure situations and return values. - */ enum sci_io_status scic_controller_start_io( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, struct scic_sds_request *io_request, u16 io_tag); - -/** - * scic_controller_start_task() - This method is called by the SCIC user to - * send/start a framework task management request. - * @controller: the handle to the controller object for which to start the task - * management request. - * @remote_device: the handle to the remote device object for which to start - * the task management request. - * @task_request: the handle to the task request object to start. - * @io_tag: This parameter specifies a previously allocated IO tag that the - * user desires to be utilized for this request. Note this not the io_tag - * of the request being managed. It is to be utilized for the task request - * itself. This parameter is optional. The user is allowed to supply - * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - The user must synchronize this task with completion - * queue processing. If they are not synchronized then it is possible for the - * io requests that are being managed by the task request can complete before - * starting the task request. scic_controller_allocate_tag() for more - * information on allocating a tag. Indicate if the controller successfully - * started the IO request. SCI_TASK_SUCCESS if the task request was - * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is - * returned if there is/are task(s) outstanding that require termination or - * completion before this request can succeed. - */ enum sci_task_status scic_controller_start_task( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, struct scic_sds_request *task_request, u16 io_tag); -/** - * scic_controller_complete_task() - This method will perform core specific - * completion operations for task management request. After this method is - * invoked, the user should consider the task request as invalid until it is - * properly reused (i.e. re-constructed). - * @controller: The handle to the controller object for which to complete the - * task management request. - * @remote_device: The handle to the remote device object for which to complete - * the task management request. - * @task_request: the handle to the task management request object to complete. - * - * Indicate if the controller successfully completed the task management - * request. SCI_SUCCESS if the completion process was successful. - */ enum sci_status scic_controller_complete_task( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, struct scic_sds_request *task_request); - -/** - * scic_controller_terminate_request() - This method is called by the SCI Core - * user to terminate an ongoing (i.e. started) core IO request. This does - * not abort the IO request at the target, but rather removes the IO request - * from the host controller. - * @controller: the handle to the controller object for which to terminate a - * request. - * @remote_device: the handle to the remote device object for which to - * terminate a request. - * @request: the handle to the io or task management request object to - * terminate. - * - * Indicate if the controller successfully began the terminate process for the - * IO request. SCI_SUCCESS if the terminate process was successfully started - * for the request. Determine the failure situations and return values. - */ enum sci_status scic_controller_terminate_request( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, struct scic_sds_request *request); -/** - * scic_controller_complete_io() - This method will perform core specific - * completion operations for an IO request. After this method is invoked, - * the user should consider the IO request as invalid until it is properly - * reused (i.e. re-constructed). - * @controller: The handle to the controller object for which to complete the - * IO request. - * @remote_device: The handle to the remote device object for which to complete - * the IO request. - * @io_request: the handle to the io request object to complete. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI - * Core user, using the scic_controller_allocate_io_tag() method, then it is - * the responsibility of the caller to invoke the scic_controller_free_io_tag() - * method to free the tag (i.e. this method will not free the IO tag). Indicate - * if the controller successfully completed the IO request. SCI_SUCCESS if the - * completion process was successful. - */ enum sci_status scic_controller_complete_io( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, struct scic_sds_request *io_request); - -/** - * scic_controller_get_port_handle() - This method simply provides the user - * with a unique handle for a given SAS/SATA core port index. - * @controller: This parameter represents the handle to the controller object - * from which to retrieve a port (SAS or SATA) handle. - * @port_index: This parameter specifies the port index in the controller for - * which to retrieve the port handle. 0 <= port_index < maximum number of - * phys. - * @port_handle: This parameter specifies the retrieved port handle to be - * provided to the caller. - * - * Indicate if the retrieval of the port handle was successful. SCI_SUCCESS - * This value is returned if the retrieval was successful. - * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port id is - * not in the supported range. - */ enum sci_status scic_controller_get_port_handle( struct scic_sds_controller *controller, u8 port_index, struct scic_sds_port **port_handle); -/** - * scic_controller_get_phy_handle() - This method simply provides the user with - * a unique handle for a given SAS/SATA phy index/identifier. - * @controller: This parameter represents the handle to the controller object - * from which to retrieve a phy (SAS or SATA) handle. - * @phy_index: This parameter specifies the phy index in the controller for - * which to retrieve the phy handle. 0 <= phy_index < maximum number of phys. - * @phy_handle: This parameter specifies the retrieved phy handle to be - * provided to the caller. - * - * Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This - * value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY - * This value is returned if the supplied phy id is not in the supported range. - */ enum sci_status scic_controller_get_phy_handle( struct scic_sds_controller *controller, u8 phy_index, struct scic_sds_phy **phy_handle); -/** - * scic_controller_allocate_io_tag() - This method will allocate a tag from the - * pool of free IO tags. Direct allocation of IO tags by the SCI Core user - * is optional. The scic_controller_start_io() method will allocate an IO - * tag if this method is not utilized and the tag is not supplied to the IO - * construct routine. Direct allocation of IO tags may provide additional - * performance improvements in environments capable of supporting this usage - * model. Additionally, direct allocation of IO tags also provides - * additional flexibility to the SCI Core user. Specifically, the user may - * retain IO tags across the lives of multiple IO requests. - * @controller: the handle to the controller object for which to allocate the - * tag. - * - * IO tags are a protected resource. It is incumbent upon the SCI Core user to - * ensure that each of the methods that may allocate or free available IO tags - * are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). An unsigned integer representing an available IO tag. - * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no - * currently available tags to be allocated. All return other values indicate a - * legitimate tag. - */ u16 scic_controller_allocate_io_tag( struct scic_sds_controller *controller); -/** - * scic_controller_free_io_tag() - This method will free an IO tag to the pool - * of free IO tags. This method provides the SCI Core user more flexibility - * with regards to IO tags. The user may desire to keep an IO tag after an - * IO request has completed, because they plan on re-using the tag for a - * subsequent IO request. This method is only legal if the tag was - * allocated via scic_controller_allocate_io_tag(). - * @controller: This parameter specifies the handle to the controller object - * for which to free/return the tag. - * @io_tag: This parameter represents the tag to be freed to the pool of - * available tags. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI - * Core user, using the scic_controller_allocate_io_tag() method, then it is - * the responsibility of the caller to invoke this method to free the tag. This - * method returns an indication of whether the tag was successfully put back - * (freed) to the pool of available tags. SCI_SUCCESS This return value - * indicates the tag was successfully placed into the pool of available IO - * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag - * is not a valid IO tag value. - */ enum sci_status scic_controller_free_io_tag( struct scic_sds_controller *controller, u16 io_tag); - - - -/** - * scic_controller_set_mode() - This method allows the user to configure the - * SCI core into either a performance mode or a memory savings mode. - * @controller: This parameter represents the handle to the controller object - * for which to update the operating mode. - * @mode: This parameter specifies the new mode for the controller. - * - * Indicate if the user successfully change the operating mode of the - * controller. SCI_SUCCESS The user successfully updated the mode. - */ -enum sci_status scic_controller_set_mode( - struct scic_sds_controller *controller, - enum sci_controller_mode mode); - - -/** - * scic_controller_set_interrupt_coalescence() - This method allows the user to - * configure the interrupt coalescence. - * @controller: This parameter represents the handle to the controller object - * for which its interrupt coalesce register is overridden. - * @coalesce_number: Used to control the number of entries in the Completion - * Queue before an interrupt is generated. If the number of entries exceed - * this number, an interrupt will be generated. The valid range of the input - * is [0, 256]. A setting of 0 results in coalescing being disabled. - * @coalesce_timeout: Timeout value in microseconds. The valid range of the - * input is [0, 2700000] . A setting of 0 is allowed and results in no - * interrupt coalescing timeout. - * - * Indicate if the user successfully set the interrupt coalesce parameters. - * SCI_SUCCESS The user successfully updated the interrutp coalescence. - * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range. - */ -enum sci_status scic_controller_set_interrupt_coalescence( - struct scic_sds_controller *controller, - u32 coalesce_number, - u32 coalesce_timeout); - struct device; struct scic_sds_controller *scic_controller_alloc(struct device *dev); - - #endif /* _SCIC_CONTROLLER_H_ */ - diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h index a52f33d94abd..fea894a0d28e 100644 --- a/drivers/scsi/isci/core/scic_io_request.h +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -325,7 +325,7 @@ enum sci_status scic_io_request_construct( struct scic_sds_remote_device *scic_remote_device, u16 io_tag, void *user_io_request_object, - void *scic_io_request_memory, + struct scic_sds_request *scic_io_request_memory, struct scic_sds_request **new_scic_io_request_handle); /** diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h index 8222443c9fd7..582953343237 100644 --- a/drivers/scsi/isci/core/scic_port.h +++ b/drivers/scsi/isci/core/scic_port.h @@ -56,14 +56,6 @@ #ifndef _SCIC_PORT_H_ #define _SCIC_PORT_H_ -/** - * This file contains all of the interface methods that can be called by an SCI - * Core user on a SAS or SATA port. - * - * - */ - - #include "sci_status.h" #include "intel_sas.h" @@ -78,118 +70,28 @@ enum SCIC_PORT_NOT_READY_REASON_CODE { SCIC_PORT_NOT_READY_REASON_CODE_MAX }; -/** - * struct scic_port_end_point_properties - This structure defines the - * properties that can be retrieved for each end-point local or remote - * (attached) port in the controller. - * - * - */ struct scic_port_end_point_properties { - /** - * This field indicates the SAS address for the associated end - * point in the port. - */ struct sci_sas_address sas_address; - - /** - * This field indicates the protocols supported by the associated - * end-point in the port. - */ struct sci_sas_identify_address_frame_protocols protocols; }; -/** - * struct scic_port_properties - This structure defines the properties that can - * be retrieved for each port in the controller. - * - * - */ struct scic_port_properties { - /** - * This field specifies the logical index of the port (0 relative). - */ u32 index; - - /** - * This field indicates the local end-point properties for port. - */ struct scic_port_end_point_properties local; - - /** - * This field indicates the remote (attached) end-point properties - * for the port. - */ struct scic_port_end_point_properties remote; - - /** - * This field specifies the phys contained inside the port. - */ u32 phy_mask; - }; -/** - * scic_port_get_properties() - This method simply returns the properties - * regarding the port, such as: physical index, protocols, sas address, etc. - * @port: this parameter specifies the port for which to retrieve the physical - * index. - * @properties: This parameter specifies the properties structure into which to - * copy the requested information. - * - * Indicate if the user specified a valid port. SCI_SUCCESS This value is - * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This - * value is returned if the specified port is not valid. When this value is - * returned, no data is copied to the properties output parameter. - */ enum sci_status scic_port_get_properties( struct scic_sds_port *port, struct scic_port_properties *properties); -/** - * scic_port_stop() - This method will make the port no longer ready for - * operation. After invoking this method IO operation is not possible. - * @port: This parameter specifies the port to be stopped. - * - * Indicate if the port was successfully stopped. SCI_SUCCESS This value is - * returned if the port was successfully stopped. SCI_WARNING_ALREADY_IN_STATE - * This value is returned if the port is already stopped or in the process of - * stopping. SCI_FAILURE_INVALID_PORT This value is returned if the supplied - * port is not valid. SCI_FAILURE_INVALID_STATE This value is returned if a - * stop operation can't be completed due to the state of port. - */ -enum sci_status scic_port_stop( - struct scic_sds_port *port); - -/** - * scic_port_hard_reset() - This method will request the SCI implementation to - * perform a HARD RESET on the SAS Port. If/When the HARD RESET completes - * the SCI user will be notified via an SCI OS callback indicating a direct - * attached device was found. - * @port: a handle corresponding to the SAS port to be hard reset. - * @reset_timeout: This parameter specifies the number of milliseconds in which - * the port reset operation should complete. - * - * The SCI User callback in SCIC_USER_CALLBACKS_T will only be called once for - * each phy in the SAS Port at completion of the hard reset sequence. Return a - * status indicating whether the hard reset started successfully. SCI_SUCCESS - * This value is returned if the hard reset operation started successfully. - */ enum sci_status scic_port_hard_reset( struct scic_sds_port *port, u32 reset_timeout); -/** - * scic_port_enable_broadcast_change_notification() - This API method enables - * the broadcast change notification from underneath hardware. - * @port: The port upon which broadcast change notifications (BCN) are to be - * enabled. - * - */ void scic_port_enable_broadcast_change_notification( struct scic_sds_port *port); - #endif /* _SCIC_PORT_H_ */ - diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 7d25a0aafb66..5cc6f2fa0939 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -219,98 +219,33 @@ sci_controller_get_memory_descriptor_list_handle(struct scic_sds_controller *sci return &scic->parent.mdl; } -/* - * ****************************************************************************- - * * SCIC SDS Controller Initialization Methods - * ****************************************************************************- */ - -/** - * This timer is used to start another phy after we have given up on the - * previous phy to transition to the ready state. - * - * - */ -static void scic_sds_controller_phy_startup_timeout_handler( - void *controller) -{ - enum sci_status status; - struct scic_sds_controller *this_controller; - - this_controller = (struct scic_sds_controller *)controller; - - this_controller->phy_startup_timer_pending = false; - - status = SCI_FAILURE; - - while (status != SCI_SUCCESS) { - status = scic_sds_controller_start_next_phy(this_controller); - } -} - -/** - * - * - * This method initializes the phy startup operations for controller start. - */ -enum sci_status scic_sds_controller_initialize_phy_startup( - struct scic_sds_controller *scic) +static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) { struct isci_host *ihost = sci_object_get_association(scic); + scic->power_control.timer = isci_timer_create(ihost, + scic, + scic_sds_controller_power_control_timer_handler); - scic->phy_startup_timer = isci_timer_create(ihost, - scic, - scic_sds_controller_phy_startup_timeout_handler); - - if (scic->phy_startup_timer == NULL) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - else { - scic->next_phy_to_start = 0; - scic->phy_startup_timer_pending = false; - } - - return SCI_SUCCESS; -} - -/** - * - * - * This method initializes the power control operations for the controller - * object. - */ -void scic_sds_controller_initialize_power_control( - struct scic_sds_controller *scic) -{ - struct isci_host *ihost = sci_object_get_association(scic); - scic->power_control.timer = isci_timer_create( - ihost, - scic, - scic_sds_controller_power_control_timer_handler); - - memset(scic->power_control.requesters, - 0, + memset(scic->power_control.requesters, 0, sizeof(scic->power_control.requesters)); scic->power_control.phys_waiting = 0; scic->power_control.phys_granted_power = 0; } -/* --------------------------------------------------------------------------- */ - #define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT (32) #define SCU_TASK_CONTEXT_ALIGNMENT (256) #define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64) #define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT (1024) #define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT (64) -/* --------------------------------------------------------------------------- */ - /** * This method builds the memory descriptor table for this controller. * @this_controller: This parameter specifies the controller object for which * to build the memory table. * */ -void scic_sds_controller_build_memory_descriptor_table( +static void scic_sds_controller_build_memory_descriptor_table( struct scic_sds_controller *this_controller) { sci_base_mde_construct( @@ -356,7 +291,7 @@ void scic_sds_controller_build_memory_descriptor_table( * * enum sci_status */ -enum sci_status scic_sds_controller_validate_memory_descriptor_table( +static enum sci_status scic_sds_controller_validate_memory_descriptor_table( struct scic_sds_controller *this_controller) { bool mde_list_valid; @@ -410,7 +345,7 @@ enum sci_status scic_sds_controller_validate_memory_descriptor_table( * @this_controller: * */ -void scic_sds_controller_ram_initialization( +static void scic_sds_controller_ram_initialization( struct scic_sds_controller *this_controller) { struct sci_physical_memory_descriptor *mde; @@ -457,7 +392,7 @@ void scic_sds_controller_ram_initialization( * @this_controller: * */ -void scic_sds_controller_assign_task_entries( +static void scic_sds_controller_assign_task_entries( struct scic_sds_controller *this_controller) { u32 task_assignment; @@ -483,7 +418,7 @@ void scic_sds_controller_assign_task_entries( * * */ -void scic_sds_controller_initialize_completion_queue( +static void scic_sds_controller_initialize_completion_queue( struct scic_sds_controller *this_controller) { u32 index; @@ -533,7 +468,7 @@ void scic_sds_controller_initialize_completion_queue( * * */ -void scic_sds_controller_initialize_unsolicited_frame_queue( +static void scic_sds_controller_initialize_unsolicited_frame_queue( struct scic_sds_controller *this_controller) { u32 frame_queue_control_value; @@ -565,7 +500,7 @@ void scic_sds_controller_initialize_unsolicited_frame_queue( * * */ -void scic_sds_controller_enable_port_task_scheduler( +static void scic_sds_controller_enable_port_task_scheduler( struct scic_sds_controller *this_controller) { u32 port_task_scheduler_value; @@ -578,8 +513,6 @@ void scic_sds_controller_enable_port_task_scheduler( SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value); } -/* --------------------------------------------------------------------------- */ - /** * * @@ -591,7 +524,7 @@ void scic_sds_controller_enable_port_task_scheduler( /* Initialize the AFE for this phy index. We need to read the AFE setup from * the OEM parameters none */ -void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) +static void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) { const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; u32 afe_status; @@ -746,7 +679,7 @@ static void scic_sds_controller_transition_to_ready( } } -void scic_sds_controller_timeout_handler(void *_scic) +static void scic_sds_controller_timeout_handler(void *_scic) { struct scic_sds_controller *scic = _scic; struct isci_host *ihost = sci_object_get_association(scic); @@ -764,7 +697,7 @@ void scic_sds_controller_timeout_handler(void *_scic) __func__); } -enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) +static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) { u32 index; enum sci_status port_status; @@ -802,8 +735,7 @@ static inline void scic_sds_controller_phy_timer_start( scic->phy_startup_timer_pending = true; } -inline void scic_sds_controller_phy_timer_stop( - struct scic_sds_controller *scic) +static void scic_sds_controller_phy_timer_stop(struct scic_sds_controller *scic) { isci_timer_stop(scic->phy_startup_timer); @@ -811,16 +743,14 @@ inline void scic_sds_controller_phy_timer_stop( } /** - * This method is called internally by the controller object to start the next - * phy on the controller. If all the phys have been started, then this - * method will attempt to transition the controller to the READY state and - * inform the user (scic_cb_controller_start_complete()). - * @this_controller: This parameter specifies the controller object for which - * to start the next phy. + * scic_sds_controller_start_next_phy - start phy + * @scic: controller * - * enum sci_status + * If all the phys have been started, then attempt to transition the + * controller to the READY state and inform the user + * (scic_cb_controller_start_complete()). */ -enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic) +static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic) { struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; struct scic_sds_phy *sci_phy; @@ -907,14 +837,36 @@ enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *s return status; } -/** - * - * @this_controller: - * - * enum sci_status - */ -enum sci_status scic_sds_controller_stop_phys( - struct scic_sds_controller *this_controller) +static void scic_sds_controller_phy_startup_timeout_handler(void *_scic) +{ + struct scic_sds_controller *scic = _scic; + enum sci_status status; + + scic->phy_startup_timer_pending = false; + status = SCI_FAILURE; + while (status != SCI_SUCCESS) + status = scic_sds_controller_start_next_phy(scic); +} + +static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic) +{ + struct isci_host *ihost = sci_object_get_association(scic); + + scic->phy_startup_timer = isci_timer_create(ihost, + scic, + scic_sds_controller_phy_startup_timeout_handler); + + if (scic->phy_startup_timer == NULL) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + else { + scic->next_phy_to_start = 0; + scic->phy_startup_timer_pending = false; + } + + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller *scic) { u32 index; enum sci_status status; @@ -923,7 +875,7 @@ enum sci_status scic_sds_controller_stop_phys( status = SCI_SUCCESS; for (index = 0; index < SCI_MAX_PHYS; index++) { - phy_status = scic_sds_phy_stop(&this_controller->phy_table[index]); + phy_status = scic_sds_phy_stop(&scic->phy_table[index]); if ( (phy_status != SCI_SUCCESS) @@ -931,25 +883,18 @@ enum sci_status scic_sds_controller_stop_phys( ) { status = SCI_FAILURE; - dev_warn(scic_to_dev(this_controller), + dev_warn(scic_to_dev(scic), "%s: Controller stop operation failed to stop " "phy %d because of status %d.\n", __func__, - this_controller->phy_table[index].phy_index, phy_status); + scic->phy_table[index].phy_index, phy_status); } } return status; } -/** - * - * @this_controller: - * - * enum sci_status - */ -enum sci_status scic_sds_controller_stop_devices( - struct scic_sds_controller *this_controller) +static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controller *scic) { u32 index; enum sci_status status; @@ -957,19 +902,19 @@ enum sci_status scic_sds_controller_stop_devices( status = SCI_SUCCESS; - for (index = 0; index < this_controller->remote_node_entries; index++) { - if (this_controller->device_table[index] != NULL) { + for (index = 0; index < scic->remote_node_entries; index++) { + if (scic->device_table[index] != NULL) { /* / @todo What timeout value do we want to provide to this request? */ - device_status = scic_remote_device_stop(this_controller->device_table[index], 0); + device_status = scic_remote_device_stop(scic->device_table[index], 0); if ((device_status != SCI_SUCCESS) && (device_status != SCI_FAILURE_INVALID_STATE)) { - dev_warn(scic_to_dev(this_controller), + dev_warn(scic_to_dev(scic), "%s: Controller stop operation failed " "to stop device 0x%p because of " "status %d.\n", __func__, - this_controller->device_table[index], device_status); + scic->device_table[index], device_status); } } } @@ -977,18 +922,7 @@ enum sci_status scic_sds_controller_stop_devices( return status; } -/* - * ****************************************************************************- - * * SCIC SDS Controller Power Control (Staggered Spinup) - * ****************************************************************************- */ - -/** - * This function starts the power control timer for this controller object. - * - * @param scic - */ -static inline void scic_sds_controller_power_control_timer_start( - struct scic_sds_controller *scic) +static void scic_sds_controller_power_control_timer_start(struct scic_sds_controller *scic) { isci_timer_start(scic->power_control.timer, SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); @@ -996,13 +930,7 @@ static inline void scic_sds_controller_power_control_timer_start( scic->power_control.timer_started = true; } -/** - * This method stops the power control timer for this controller object. - * - * @param scic - */ -static inline void scic_sds_controller_power_control_timer_stop( - struct scic_sds_controller *scic) +static void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic) { if (scic->power_control.timer_started) { isci_timer_stop(scic->power_control.timer); @@ -1010,24 +938,12 @@ static inline void scic_sds_controller_power_control_timer_stop( } } -/** - * This method stops and starts the power control timer for this controller - * object. - * - * @param scic - */ -static inline void scic_sds_controller_power_control_timer_restart( - struct scic_sds_controller *scic) +static void scic_sds_controller_power_control_timer_restart(struct scic_sds_controller *scic) { scic_sds_controller_power_control_timer_stop(scic); scic_sds_controller_power_control_timer_start(scic); } -/** - * - * - * - */ static void scic_sds_controller_power_control_timer_handler( void *controller) { @@ -1146,8 +1062,6 @@ static bool scic_sds_controller_completion_queue_has_entries( return false; } -/* --------------------------------------------------------------------------- */ - /** * This method processes a task completion notification. This is called from * within the controller completion handler. @@ -1625,10 +1539,6 @@ void scic_sds_controller_error_handler(struct scic_sds_controller *scic) } -u32 scic_sds_controller_get_object_size(void) -{ - return sizeof(struct scic_sds_controller); -} void scic_sds_controller_link_up( @@ -1703,7 +1613,7 @@ void scic_sds_controller_remote_device_started(struct scic_sds_controller *scic, * controller are still in the stopping state. * */ -bool scic_sds_controller_has_remote_devices_stopping( +static bool scic_sds_controller_has_remote_devices_stopping( struct scic_sds_controller *this_controller) { u32 index; @@ -2042,62 +1952,20 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co scic->user_parameters.sds1.no_outbound_task_timeout = 20; } - -enum sci_status scic_controller_construct(struct scic_sds_controller *controller, - void __iomem *scu_base, - void __iomem *smu_base) -{ - u8 index; - - sci_base_controller_construct( - &controller->parent, - scic_sds_controller_state_table, - controller->memory_descriptors, - ARRAY_SIZE(controller->memory_descriptors), - NULL - ); - - controller->scu_registers = scu_base; - controller->smu_registers = smu_base; - - scic_sds_port_configuration_agent_construct(&controller->port_agent); - - /* Construct the ports for this controller */ - for (index = 0; index < SCI_MAX_PORTS; index++) - scic_sds_port_construct(&controller->port_table[index], - index, controller); - scic_sds_port_construct(&controller->port_table[index], - SCIC_SDS_DUMMY_PORT, controller); - - /* Construct the phys for this controller */ - for (index = 0; index < SCI_MAX_PHYS; index++) { - /* Add all the PHYs to the dummy port */ - scic_sds_phy_construct( - &controller->phy_table[index], - &controller->port_table[SCI_MAX_PORTS], - index - ); - } - - controller->invalid_phy_mask = 0; - - /* Set the default maximum values */ - controller->completion_event_entries = SCU_EVENT_COUNT; - controller->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; - controller->remote_node_entries = SCI_MAX_REMOTE_DEVICES; - controller->logical_port_entries = SCI_MAX_PORTS; - controller->task_context_entries = SCU_IO_REQUEST_COUNT; - controller->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT; - controller->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT; - - /* Initialize the User and OEM parameters to default values. */ - scic_sds_controller_set_default_config_parameters(controller); - - return scic_controller_reset(controller); -} - -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_initialize() - This method will initialize the controller + * hardware managed by the supplied core controller object. This method + * will bring the physical controller hardware out of reset and enable the + * core to determine the capabilities of the hardware being managed. Thus, + * the core controller can determine it's exact physical (DMA capable) + * memory requirements. + * @controller: This parameter specifies the controller to be initialized. + * + * The SCI Core user must have called scic_controller_construct() on the + * supplied controller object previously. Indicate if the controller was + * successfully initialized or if it failed in some way. SCI_SUCCESS This value + * is returned if the controller hardware was successfully initialized. + */ enum sci_status scic_controller_initialize( struct scic_sds_controller *scic) { @@ -2118,8 +1986,18 @@ enum sci_status scic_controller_initialize( return status; } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_get_suggested_start_timeout() - This method returns the + * suggested scic_controller_start() timeout amount. The user is free to + * use any timeout value, but this method provides the suggested minimum + * start timeout value. The returned value is based upon empirical + * information determined as a result of interoperability testing. + * @controller: the handle to the controller object for which to return the + * suggested start timeout. + * + * This method returns the number of milliseconds for the suggested start + * operation timeout. + */ u32 scic_controller_get_suggested_start_timeout( struct scic_sds_controller *sc) { @@ -2146,8 +2024,28 @@ u32 scic_controller_get_suggested_start_timeout( + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_start() - This method will start the supplied core + * controller. This method will start the staggered spin up operation. The + * SCI User completion callback is called when the following conditions are + * met: -# the return status of this method is SCI_SUCCESS. -# after all of + * the phys have successfully started or been given the opportunity to start. + * @controller: the handle to the controller object to start. + * @timeout: This parameter specifies the number of milliseconds in which the + * start operation should complete. + * + * The SCI Core user must have filled in the physical memory descriptor + * structure via the sci_controller_get_memory_descriptor_list() method. The + * SCI Core user must have invoked the scic_controller_initialize() method + * prior to invoking this method. The controller must be in the INITIALIZED or + * STARTED state. Indicate if the controller start method succeeded or failed + * in some way. SCI_SUCCESS if the start operation succeeded. + * SCI_WARNING_ALREADY_IN_STATE if the controller is already in the STARTED + * state. SCI_FAILURE_INVALID_STATE if the controller is not either in the + * INITIALIZED or STARTED states. SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if + * there are inconsistent or invalid values in the supplied + * struct sci_physical_memory_descriptor array. + */ enum sci_status scic_controller_start( struct scic_sds_controller *scic, u32 timeout) @@ -2169,8 +2067,24 @@ enum sci_status scic_controller_start( return status; } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_stop() - This method will stop an individual controller + * object.This method will invoke the associated user callback upon + * completion. The completion callback is called when the following + * conditions are met: -# the method return status is SCI_SUCCESS. -# the + * controller has been quiesced. This method will ensure that all IO + * requests are quiesced, phys are stopped, and all additional operation by + * the hardware is halted. + * @controller: the handle to the controller object to stop. + * @timeout: This parameter specifies the number of milliseconds in which the + * stop operation should complete. + * + * The controller must be in the STARTED or STOPPED state. Indicate if the + * controller stop method succeeded or failed in some way. SCI_SUCCESS if the + * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the + * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the + * controller is not either in the STARTED or STOPPED states. + */ enum sci_status scic_controller_stop( struct scic_sds_controller *scic, u32 timeout) @@ -2192,8 +2106,18 @@ enum sci_status scic_controller_stop( return status; } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_reset() - This method will reset the supplied core + * controller regardless of the state of said controller. This operation is + * considered destructive. In other words, all current operations are wiped + * out. No IO completions for outstanding devices occur. Outstanding IO + * requests are not aborted or completed at the actual remote device. + * @controller: the handle to the controller object to reset. + * + * Indicate if the controller reset method succeeded or failed in some way. + * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if + * the controller reset operation is unable to complete. + */ enum sci_status scic_controller_reset( struct scic_sds_controller *scic) { @@ -2214,6 +2138,33 @@ enum sci_status scic_controller_reset( return status; } +/** + * scic_controller_start_io() - This method is called by the SCI user to + * send/start an IO request. If the method invocation is successful, then + * the IO request has been queued to the hardware for processing. + * @controller: the handle to the controller object for which to start an IO + * request. + * @remote_device: the handle to the remote device object for which to start an + * IO request. + * @io_request: the handle to the io request object to start. + * @io_tag: This parameter specifies a previously allocated IO tag that the + * user desires to be utilized for this request. This parameter is optional. + * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value + * for this parameter. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a + * result, it is expected the user will have set the NCQ tag field in the host + * to device register FIS prior to calling this method. There is also a + * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking + * the scic_controller_start_io() method. scic_controller_allocate_tag() for + * more information on allocating a tag. Indicate if the controller + * successfully started the IO request. SCI_IO_SUCCESS if the IO request was + * successfully started. Determine the failure situations and return values. + */ enum sci_io_status scic_controller_start_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, @@ -2231,8 +2182,22 @@ enum sci_io_status scic_controller_start_io( (struct sci_base_request *)io_request, io_tag); } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_terminate_request() - This method is called by the SCI Core + * user to terminate an ongoing (i.e. started) core IO request. This does + * not abort the IO request at the target, but rather removes the IO request + * from the host controller. + * @controller: the handle to the controller object for which to terminate a + * request. + * @remote_device: the handle to the remote device object for which to + * terminate a request. + * @request: the handle to the io or task management request object to + * terminate. + * + * Indicate if the controller successfully began the terminate process for the + * IO request. SCI_SUCCESS if the terminate process was successfully started + * for the request. Determine the failure situations and return values. + */ enum sci_status scic_controller_terminate_request( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, @@ -2249,8 +2214,28 @@ enum sci_status scic_controller_terminate_request( (struct sci_base_request *)request); } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_complete_io() - This method will perform core specific + * completion operations for an IO request. After this method is invoked, + * the user should consider the IO request as invalid until it is properly + * reused (i.e. re-constructed). + * @controller: The handle to the controller object for which to complete the + * IO request. + * @remote_device: The handle to the remote device object for which to complete + * the IO request. + * @io_request: the handle to the io request object to complete. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI + * Core user, using the scic_controller_allocate_io_tag() method, then it is + * the responsibility of the caller to invoke the scic_controller_free_io_tag() + * method to free the tag (i.e. this method will not free the IO tag). Indicate + * if the controller successfully completed the IO request. SCI_SUCCESS if the + * completion process was successful. + */ enum sci_status scic_controller_complete_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, @@ -2267,9 +2252,34 @@ enum sci_status scic_controller_complete_io( (struct sci_base_request *)io_request); } -/* --------------------------------------------------------------------------- */ - - +/** + * scic_controller_start_task() - This method is called by the SCIC user to + * send/start a framework task management request. + * @controller: the handle to the controller object for which to start the task + * management request. + * @remote_device: the handle to the remote device object for which to start + * the task management request. + * @task_request: the handle to the task request object to start. + * @io_tag: This parameter specifies a previously allocated IO tag that the + * user desires to be utilized for this request. Note this not the io_tag + * of the request being managed. It is to be utilized for the task request + * itself. This parameter is optional. The user is allowed to supply + * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - The user must synchronize this task with completion + * queue processing. If they are not synchronized then it is possible for the + * io requests that are being managed by the task request can complete before + * starting the task request. scic_controller_allocate_tag() for more + * information on allocating a tag. Indicate if the controller successfully + * started the IO request. SCI_TASK_SUCCESS if the task request was + * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is + * returned if there is/are task(s) outstanding that require termination or + * completion before this request can succeed. + */ enum sci_task_status scic_controller_start_task( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, @@ -2297,8 +2307,20 @@ enum sci_task_status scic_controller_start_task( return status; } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_complete_task() - This method will perform core specific + * completion operations for task management request. After this method is + * invoked, the user should consider the task request as invalid until it is + * properly reused (i.e. re-constructed). + * @controller: The handle to the controller object for which to complete the + * task management request. + * @remote_device: The handle to the remote device object for which to complete + * the task management request. + * @task_request: the handle to the task management request object to complete. + * + * Indicate if the controller successfully completed the task management + * request. SCI_SUCCESS if the completion process was successful. + */ enum sci_status scic_controller_complete_task( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, @@ -2325,8 +2347,22 @@ enum sci_status scic_controller_complete_task( } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_get_port_handle() - This method simply provides the user + * with a unique handle for a given SAS/SATA core port index. + * @controller: This parameter represents the handle to the controller object + * from which to retrieve a port (SAS or SATA) handle. + * @port_index: This parameter specifies the port index in the controller for + * which to retrieve the port handle. 0 <= port_index < maximum number of + * phys. + * @port_handle: This parameter specifies the retrieved port handle to be + * provided to the caller. + * + * Indicate if the retrieval of the port handle was successful. SCI_SUCCESS + * This value is returned if the retrieval was successful. + * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port id is + * not in the supported range. + */ enum sci_status scic_controller_get_port_handle( struct scic_sds_controller *scic, u8 port_index, @@ -2341,8 +2377,20 @@ enum sci_status scic_controller_get_port_handle( return SCI_FAILURE_INVALID_PORT; } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_get_phy_handle() - This method simply provides the user with + * a unique handle for a given SAS/SATA phy index/identifier. + * @controller: This parameter represents the handle to the controller object + * from which to retrieve a phy (SAS or SATA) handle. + * @phy_index: This parameter specifies the phy index in the controller for + * which to retrieve the phy handle. 0 <= phy_index < maximum number of phys. + * @phy_handle: This parameter specifies the retrieved phy handle to be + * provided to the caller. + * + * Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This + * value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY + * This value is returned if the supplied phy id is not in the supported range. + */ enum sci_status scic_controller_get_phy_handle( struct scic_sds_controller *scic, u8 phy_index, @@ -2361,8 +2409,28 @@ enum sci_status scic_controller_get_phy_handle( return SCI_FAILURE_INVALID_PHY; } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_allocate_io_tag() - This method will allocate a tag from the + * pool of free IO tags. Direct allocation of IO tags by the SCI Core user + * is optional. The scic_controller_start_io() method will allocate an IO + * tag if this method is not utilized and the tag is not supplied to the IO + * construct routine. Direct allocation of IO tags may provide additional + * performance improvements in environments capable of supporting this usage + * model. Additionally, direct allocation of IO tags also provides + * additional flexibility to the SCI Core user. Specifically, the user may + * retain IO tags across the lives of multiple IO requests. + * @controller: the handle to the controller object for which to allocate the + * tag. + * + * IO tags are a protected resource. It is incumbent upon the SCI Core user to + * ensure that each of the methods that may allocate or free available IO tags + * are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). An unsigned integer representing an available IO tag. + * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no + * currently available tags to be allocated. All return other values indicate a + * legitimate tag. + */ u16 scic_controller_allocate_io_tag( struct scic_sds_controller *scic) { @@ -2380,8 +2448,31 @@ u16 scic_controller_allocate_io_tag( return SCI_CONTROLLER_INVALID_IO_TAG; } -/* --------------------------------------------------------------------------- */ - +/** + * scic_controller_free_io_tag() - This method will free an IO tag to the pool + * of free IO tags. This method provides the SCI Core user more flexibility + * with regards to IO tags. The user may desire to keep an IO tag after an + * IO request has completed, because they plan on re-using the tag for a + * subsequent IO request. This method is only legal if the tag was + * allocated via scic_controller_allocate_io_tag(). + * @controller: This parameter specifies the handle to the controller object + * for which to free/return the tag. + * @io_tag: This parameter represents the tag to be freed to the pool of + * available tags. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI + * Core user, using the scic_controller_allocate_io_tag() method, then it is + * the responsibility of the caller to invoke this method to free the tag. This + * method returns an indication of whether the tag was successfully put back + * (freed) to the pool of available tags. SCI_SUCCESS This return value + * indicates the tag was successfully placed into the pool of available IO + * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag + * is not a valid IO tag value. + */ enum sci_status scic_controller_free_io_tag( struct scic_sds_controller *scic, u16 io_tag) @@ -2408,8 +2499,6 @@ enum sci_status scic_controller_free_io_tag( return SCI_FAILURE_INVALID_IO_TAG; } -/* --------------------------------------------------------------------------- */ - void scic_controller_enable_interrupts( struct scic_sds_controller *scic) { @@ -2417,8 +2506,6 @@ void scic_controller_enable_interrupts( SMU_IMR_WRITE(scic, 0x00000000); } -/* --------------------------------------------------------------------------- */ - void scic_controller_disable_interrupts( struct scic_sds_controller *scic) { @@ -2426,9 +2513,7 @@ void scic_controller_disable_interrupts( SMU_IMR_WRITE(scic, 0xffffffff); } -/* --------------------------------------------------------------------------- */ - -enum sci_status scic_controller_set_mode( +static enum sci_status scic_controller_set_mode( struct scic_sds_controller *scic, enum sci_controller_mode operating_mode) { @@ -2476,7 +2561,7 @@ enum sci_status scic_controller_set_mode( * * This method will reset the controller hardware. */ -void scic_sds_controller_reset_hardware( +static void scic_sds_controller_reset_hardware( struct scic_sds_controller *scic) { /* Disable interrupts so we dont take any spurious interrupts */ @@ -2495,8 +2580,6 @@ void scic_sds_controller_reset_hardware( SCU_UFQGP_WRITE(scic, 0x00000000); } -/* --------------------------------------------------------------------------- */ - enum sci_status scic_user_parameters_set( struct scic_sds_controller *scic, union scic_user_parameters *scic_parms) @@ -2551,17 +2634,6 @@ enum sci_status scic_user_parameters_set( return SCI_FAILURE_INVALID_STATE; } -/* --------------------------------------------------------------------------- */ - -void scic_user_parameters_get( - struct scic_sds_controller *scic, - union scic_user_parameters *scic_parms) -{ - memcpy(scic_parms, (&scic->user_parameters), sizeof(*scic_parms)); -} - -/* --------------------------------------------------------------------------- */ - enum sci_status scic_oem_parameters_set( struct scic_sds_controller *scic, union scic_oem_parameters *scic_parms) @@ -2616,8 +2688,6 @@ enum sci_status scic_oem_parameters_set( return SCI_FAILURE_INVALID_STATE; } -/* --------------------------------------------------------------------------- */ - void scic_oem_parameters_get( struct scic_sds_controller *scic, union scic_oem_parameters *scic_parms) @@ -2625,9 +2695,6 @@ void scic_oem_parameters_get( memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms)); } -/* --------------------------------------------------------------------------- */ - - #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853 #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280 #define INTERRUPT_COALESCE_TIMEOUT_MAX_US 2700000 @@ -2635,7 +2702,24 @@ void scic_oem_parameters_get( #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 7 #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28 -enum sci_status scic_controller_set_interrupt_coalescence( +/** + * scic_controller_set_interrupt_coalescence() - This method allows the user to + * configure the interrupt coalescence. + * @controller: This parameter represents the handle to the controller object + * for which its interrupt coalesce register is overridden. + * @coalesce_number: Used to control the number of entries in the Completion + * Queue before an interrupt is generated. If the number of entries exceed + * this number, an interrupt will be generated. The valid range of the input + * is [0, 256]. A setting of 0 results in coalescing being disabled. + * @coalesce_timeout: Timeout value in microseconds. The valid range of the + * input is [0, 2700000] . A setting of 0 is allowed and results in no + * interrupt coalescing timeout. + * + * Indicate if the user successfully set the interrupt coalesce parameters. + * SCI_SUCCESS The user successfully updated the interrutp coalescence. + * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range. + */ +static enum sci_status scic_controller_set_interrupt_coalescence( struct scic_sds_controller *scic_controller, u32 coalesce_number, u32 coalesce_timeout) @@ -3419,7 +3503,7 @@ static enum sci_status scic_sds_controller_stopping_state_complete_io_handler( * This method is called when the struct scic_sds_controller is in a stopping state * and the remote device has stopped. **/ -void scic_sds_controller_stopping_state_device_stopped_handler( +static void scic_sds_controller_stopping_state_device_stopped_handler( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device ) @@ -3638,7 +3722,7 @@ static void scic_sds_controller_resetting_state_enter(struct sci_base_object *ob SCI_BASE_CONTROLLER_STATE_RESET); } -const struct sci_base_state scic_sds_controller_state_table[] = { +static const struct sci_base_state scic_sds_controller_state_table[] = { [SCI_BASE_CONTROLLER_STATE_INITIAL] = { .enter_state = scic_sds_controller_initial_state_enter, }, @@ -3662,3 +3746,64 @@ const struct sci_base_state scic_sds_controller_state_table[] = { [SCI_BASE_CONTROLLER_STATE_STOPPED] = {}, [SCI_BASE_CONTROLLER_STATE_FAILED] = {} }; + +/** + * scic_controller_construct() - This method will attempt to construct a + * controller object utilizing the supplied parameter information. + * @c: This parameter specifies the controller to be constructed. + * @scu_base: mapped base address of the scu registers + * @smu_base: mapped base address of the smu registers + * + * Indicate if the controller was successfully constructed or if it failed in + * some way. SCI_SUCCESS This value is returned if the controller was + * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned + * if the interrupt coalescence timer may cause SAS compliance issues for SMP + * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE + * This value is returned if the controller does not support the supplied type. + * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the + * controller does not support the supplied initialization data version. + */ +enum sci_status scic_controller_construct(struct scic_sds_controller *scic, + void __iomem *scu_base, + void __iomem *smu_base) +{ + u8 i; + + sci_base_controller_construct(&scic->parent, + scic_sds_controller_state_table, + scic->memory_descriptors, + ARRAY_SIZE(scic->memory_descriptors), NULL); + + scic->scu_registers = scu_base; + scic->smu_registers = smu_base; + + scic_sds_port_configuration_agent_construct(&scic->port_agent); + + /* Construct the ports for this controller */ + for (i = 0; i < SCI_MAX_PORTS; i++) + scic_sds_port_construct(&scic->port_table[i], i, scic); + scic_sds_port_construct(&scic->port_table[i], SCIC_SDS_DUMMY_PORT, scic); + + /* Construct the phys for this controller */ + for (i = 0; i < SCI_MAX_PHYS; i++) { + /* Add all the PHYs to the dummy port */ + scic_sds_phy_construct(&scic->phy_table[i], + &scic->port_table[SCI_MAX_PORTS], i); + } + + scic->invalid_phy_mask = 0; + + /* Set the default maximum values */ + scic->completion_event_entries = SCU_EVENT_COUNT; + scic->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; + scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; + scic->logical_port_entries = SCI_MAX_PORTS; + scic->task_context_entries = SCU_IO_REQUEST_COUNT; + scic->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT; + scic->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT; + + /* Initialize the User and OEM parameters to default values. */ + scic_sds_controller_set_default_config_parameters(scic); + + return scic_controller_reset(scic); +} diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index aa2698bb7ca1..fedf5032d898 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -402,7 +402,6 @@ struct scic_sds_controller_state_handler { extern const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[]; -extern const struct sci_base_state scic_sds_controller_state_table[]; /** * INCREMENT_QUEUE_GET() - @@ -535,7 +534,6 @@ extern const struct sci_base_state scic_sds_controller_state_table[]; /* --------------------------------------------------------------------------- */ -u32 scic_sds_controller_get_object_size(void); /* --------------------------------------------------------------------------- */ @@ -615,8 +613,6 @@ void scic_sds_controller_link_down( * * CORE CONTROLLER REMOTE DEVICE MESSAGE PROCESSING * ***************************************************************************** */ -bool scic_sds_controller_has_remote_devices_stopping( - struct scic_sds_controller *this_controller); void scic_sds_controller_remote_device_started( struct scic_sds_controller *this_controller, @@ -626,67 +622,11 @@ void scic_sds_controller_remote_device_stopped( struct scic_sds_controller *this_controller, struct scic_sds_remote_device *the_device); - -/* - * ***************************************************************************** - * * CORE CONTROLLER PRIVATE METHODS - * ***************************************************************************** */ - -enum sci_status scic_sds_controller_validate_memory_descriptor_table( - struct scic_sds_controller *this_controller); - -void scic_sds_controller_ram_initialization( - struct scic_sds_controller *this_controller); - -void scic_sds_controller_assign_task_entries( - struct scic_sds_controller *this_controller); - -void scic_sds_controller_afe_initialization( - struct scic_sds_controller *this_controller); - -void scic_sds_controller_enable_port_task_scheduler( - struct scic_sds_controller *this_controller); - -void scic_sds_controller_initialize_completion_queue( - struct scic_sds_controller *this_controller); - -void scic_sds_controller_initialize_unsolicited_frame_queue( - struct scic_sds_controller *this_controller); - -void scic_sds_controller_phy_timer_stop( - struct scic_sds_controller *this_controller); - -enum sci_status scic_sds_controller_start_next_phy( - struct scic_sds_controller *this_controller); - -enum sci_status scic_sds_controller_stop_phys( - struct scic_sds_controller *this_controller); - -enum sci_status scic_sds_controller_stop_ports( - struct scic_sds_controller *this_controller); - -enum sci_status scic_sds_controller_stop_devices( - struct scic_sds_controller *this_controller); - void scic_sds_controller_copy_task_context( struct scic_sds_controller *this_controller, struct scic_sds_request *this_request); -void scic_sds_controller_timeout_handler(void *controller); - -void scic_sds_controller_initialize_power_control( - struct scic_sds_controller *this_controller); - void scic_sds_controller_register_setup( struct scic_sds_controller *this_controller); -void scic_sds_controller_reset_hardware( - struct scic_sds_controller *this_controller); - -enum sci_status scic_sds_controller_initialize_phy_startup( - struct scic_sds_controller *this_controller); - -void scic_sds_controller_build_memory_descriptor_table( - struct scic_sds_controller *this_controller); - #endif /* _SCIC_SDS_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index e546e20f1ffd..532338eb302b 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -257,7 +257,7 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, * restart the starting substate machine since we dont know what has actually * happening. */ -void scic_sds_phy_sata_timeout(void *phy) +static void scic_sds_phy_sata_timeout(void *phy) { struct scic_sds_phy *sci_phy = phy; @@ -273,47 +273,6 @@ void scic_sds_phy_sata_timeout(void *phy) SCI_BASE_PHY_STATE_STARTING); } -/** - * This method will construct the struct scic_sds_phy object - * @this_phy: - * @owning_port: - * @phy_index: - * - */ -void scic_sds_phy_construct( - struct scic_sds_phy *this_phy, - struct scic_sds_port *owning_port, - u8 phy_index) -{ - /* - * Call the base constructor first - */ - sci_base_phy_construct( - &this_phy->parent, - scic_sds_phy_state_table - ); - - /* Copy the rest of the input data to our locals */ - this_phy->owning_port = owning_port; - this_phy->phy_index = phy_index; - this_phy->bcn_received_while_port_unassigned = false; - this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; - this_phy->link_layer_registers = NULL; - this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; - this_phy->sata_timeout_timer = NULL; - - /* Clear out the identification buffer data */ - memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type)); - - /* Initialize the the substate machines */ - sci_base_state_machine_construct( - &this_phy->starting_substate_machine, - &this_phy->parent.parent, - scic_sds_phy_starting_substates, - SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL - ); -} - /** * This method returns the port currently containing this phy. If the phy is * currently contained by the dummy port, then the phy is considered to not @@ -426,7 +385,7 @@ void scic_sds_phy_setup_transport( * This function will perform the register reads/writes to suspend the SCU * hardware protocol engine. none */ -void scic_sds_phy_suspend( +static void scic_sds_phy_suspend( struct scic_sds_phy *this_phy) { u32 scu_sas_pcfg_value; @@ -1416,7 +1375,62 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_p return SCI_SUCCESS; } -const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = { +static enum sci_status default_phy_handler(struct sci_base_phy *base_phy, const char *func) +{ + struct scic_sds_phy *sci_phy; + + sci_phy = container_of(base_phy, typeof(*sci_phy), parent); + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", func, + sci_base_state_machine_get_state(&base_phy->state_machine)); + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_phy_default_start_handler(struct sci_base_phy *base_phy) +{ + return default_phy_handler(base_phy, __func__); +} + +static enum sci_status scic_sds_phy_default_stop_handler(struct sci_base_phy *base_phy) +{ + return default_phy_handler(base_phy, __func__); +} + +static enum sci_status scic_sds_phy_default_reset_handler(struct sci_base_phy *base_phy) +{ + return default_phy_handler(base_phy, __func__); +} + +static enum sci_status scic_sds_phy_default_destroy_handler(struct sci_base_phy *base_phy) +{ + return default_phy_handler(base_phy, __func__); +} + +static enum sci_status scic_sds_phy_default_frame_handler(struct scic_sds_phy *sci_phy, + u32 frame_index) +{ + struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); + + default_phy_handler(&sci_phy->parent, __func__); + scic_sds_controller_release_frame(scic, frame_index); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_phy_default_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) +{ + return default_phy_handler(&sci_phy->parent, __func__); +} + +static enum sci_status scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) +{ + return default_phy_handler(&sci_phy->parent, __func__); +} + + + +static const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = { [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { .parent.start_handler = scic_sds_phy_default_start_handler, .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, @@ -1867,7 +1881,7 @@ static void scic_sds_phy_starting_final_substate_enter(struct sci_base_object *o /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_phy_starting_substates[] = { +static const struct sci_base_state scic_sds_phy_starting_substates[] = { [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { .enter_state = scic_sds_phy_starting_initial_substate_enter, }, @@ -1905,196 +1919,6 @@ const struct sci_base_state scic_sds_phy_starting_substates[] = { } }; -/* - * *************************************************************************** - * * DEFAULT HANDLERS - * *************************************************************************** */ - -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * - * This is the default method for phy a start request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_phy_default_start_handler( - struct sci_base_phy *phy) -{ - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)phy; - - dev_warn(sciphy_to_dev(this_phy), - "%s: SCIC Phy 0x%p requested to start from invalid " - "state %d\n", - __func__, - this_phy, - sci_base_state_machine_get_state( - &this_phy->parent.state_machine)); - - return SCI_FAILURE_INVALID_STATE; - -} - -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a - * struct scic_sds_phy object. - * - * This is the default method for phy a stop request. It will report a warning - * and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_phy_default_stop_handler(struct sci_base_phy *base_phy) -{ - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)base_phy; - - dev_dbg(sciphy_to_dev(sci_phy), - "%s: SCIC Phy 0x%p requested to stop from invalid state %d\n", - __func__, - sci_phy, - sci_base_state_machine_get_state( - &sci_phy->parent.state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * - * This is the default method for phy a reset request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_phy_default_reset_handler( - struct sci_base_phy *phy) -{ - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)phy; - - dev_warn(sciphy_to_dev(this_phy), - "%s: SCIC Phy 0x%p requested to reset from invalid state " - "%d\n", - __func__, - this_phy, - sci_base_state_machine_get_state( - &this_phy->parent.state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * - * This is the default method for phy a destruct request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_phy_default_destroy_handler( - struct sci_base_phy *phy) -{ - struct scic_sds_phy *this_phy; - - this_phy = (struct scic_sds_phy *)phy; - - /* / @todo Implement something for the default */ - dev_warn(sciphy_to_dev(this_phy), - "%s: SCIC Phy 0x%p requested to destroy from invalid " - "state %d\n", - __func__, - this_phy, - sci_base_state_machine_get_state( - &this_phy->parent.state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * @frame_index: This is the frame index that was received from the SCU - * hardware. - * - * This is the default method for a phy frame handling request. It will report - * a warning, release the frame and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_phy_default_frame_handler( - struct scic_sds_phy *this_phy, - u32 frame_index) -{ - dev_warn(sciphy_to_dev(this_phy), - "%s: SCIC Phy 0x%p received unexpected frame data %d " - "while in state %d\n", - __func__, - this_phy, - frame_index, - sci_base_state_machine_get_state( - &this_phy->parent.state_machine)); - - scic_sds_controller_release_frame( - scic_sds_phy_get_controller(this_phy), frame_index); - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * @event_code: This is the event code that was received from the SCU hardware. - * - * This is the default method for a phy event handler. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_phy_default_event_handler( - struct scic_sds_phy *this_phy, - u32 event_code) -{ - dev_dbg(sciphy_to_dev(this_phy), - "%s: SCIC Phy 0x%p received unexpected event status %x " - "while in state %d\n", - __func__, - this_phy, - event_code, - sci_base_state_machine_get_state( - &this_phy->parent.state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * - * This is the default method for a phy consume power handler. It will report - * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_phy_default_consume_power_handler( - struct scic_sds_phy *this_phy) -{ - dev_warn(sciphy_to_dev(this_phy), - "%s: SCIC Phy 0x%p given unexpected permission to consume " - "power while in state %d\n", - __func__, - this_phy, - sci_base_state_machine_get_state( - &this_phy->parent.state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/* - * ****************************************************************************** - * * PHY STOPPED STATE HANDLERS - * ****************************************************************************** */ - /** * * @phy: This is the struct sci_base_phy object which is cast into a @@ -2219,7 +2043,7 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sd /* --------------------------------------------------------------------------- */ -const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { +static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { .parent.start_handler = scic_sds_phy_default_start_handler, .parent.stop_handler = scic_sds_phy_default_stop_handler, @@ -2563,7 +2387,7 @@ static void scic_sds_phy_final_state_enter( /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_phy_state_table[] = { +static const struct sci_base_state scic_sds_phy_state_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { .enter_state = scic_sds_phy_initial_state_enter, }, @@ -2585,3 +2409,29 @@ const struct sci_base_state scic_sds_phy_state_table[] = { }, }; +void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, + struct scic_sds_port *owning_port, u8 phy_index) +{ + /* + * Call the base constructor first + */ + sci_base_phy_construct(&sci_phy->parent, scic_sds_phy_state_table); + + /* Copy the rest of the input data to our locals */ + sci_phy->owning_port = owning_port; + sci_phy->phy_index = phy_index; + sci_phy->bcn_received_while_port_unassigned = false; + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; + sci_phy->link_layer_registers = NULL; + sci_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; + sci_phy->sata_timeout_timer = NULL; + + /* Clear out the identification buffer data */ + memset(&sci_phy->phy_type, 0, sizeof(sci_phy->phy_type)); + + /* Initialize the the substate machines */ + sci_base_state_machine_construct(&sci_phy->starting_substate_machine, + &sci_phy->parent.parent, + scic_sds_phy_starting_substates, + SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); +} diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index af9e24c30945..4745a791f15b 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -293,12 +293,6 @@ struct scic_sds_phy_state_handler { }; -extern const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[]; -extern const struct sci_base_state scic_sds_phy_state_table[]; -extern const struct sci_base_state scic_sds_phy_starting_substates[]; -extern const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[]; - - /** * scic_sds_phy_get_index() - * @@ -362,12 +356,6 @@ enum sci_status scic_sds_phy_stop( enum sci_status scic_sds_phy_reset( struct scic_sds_phy *this_phy); -void scic_sds_phy_sata_timeout( - void *cookie); - -void scic_sds_phy_suspend( - struct scic_sds_phy *this_phy); - void scic_sds_phy_resume( struct scic_sds_phy *this_phy); @@ -402,27 +390,4 @@ void scic_sds_phy_get_attached_phy_protocols( struct scic_sds_phy *this_phy, struct sci_sas_identify_address_frame_protocols *protocols); -enum sci_status scic_sds_phy_default_start_handler( - struct sci_base_phy *phy); - -enum sci_status scic_sds_phy_default_stop_handler( - struct sci_base_phy *phy); - -enum sci_status scic_sds_phy_default_reset_handler( - struct sci_base_phy *phy); - -enum sci_status scic_sds_phy_default_destroy_handler( - struct sci_base_phy *phy); - -enum sci_status scic_sds_phy_default_frame_handler( - struct scic_sds_phy *phy, - u32 frame_index); - -enum sci_status scic_sds_phy_default_event_handler( - struct scic_sds_phy *phy, - u32 evnet_code); - -enum sci_status scic_sds_phy_default_consume_power_handler( - struct scic_sds_phy *phy); - #endif /* _SCIC_SDS_PHY_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 72b815ef98ca..0a95f649c04f 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -69,19 +69,13 @@ #include "sci_environment.h" #include "scic_sds_controller_registers.h" - -static void scic_sds_port_invalid_link_up( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy); -static void scic_sds_port_timeout_handler( - void *port); #define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) #define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) #define SCU_DUMMY_INDEX (0xFFFF) -void sci_base_port_construct( +static void sci_base_port_construct( struct sci_base_port *base_port, const struct sci_base_state *state_table) { @@ -168,7 +162,7 @@ bool scic_sds_port_is_valid_phy_assignment( * Return a bit mask indicating which phys are a part of this port. Each bit * corresponds to a phy identifier (e.g. bit 0 = phy id 0). */ -u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) +static u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) { u32 index; u32 mask; @@ -196,7 +190,7 @@ u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) * phy mask can be supported. true if this is a valid phy assignment for the * port false if this is not a valid phy assignment for the port */ -bool scic_sds_port_is_phy_mask_valid( +static bool scic_sds_port_is_phy_mask_valid( struct scic_sds_port *this_port, u32 phy_mask) { @@ -269,7 +263,7 @@ static struct scic_sds_phy *scic_sds_port_get_a_connected_phy( * is a functional test that only fails if the phy is currently assigned to a * different port. */ -enum sci_status scic_sds_port_set_phy( +static enum sci_status scic_sds_port_set_phy( struct scic_sds_port *port, struct scic_sds_phy *phy) { @@ -304,7 +298,7 @@ enum sci_status scic_sds_port_set_phy( * this phy is not currently assinged to this port. bool true if the phy is * removed from the port. false if this phy is not assined to this port. */ -enum sci_status scic_sds_port_clear_phy( +static enum sci_status scic_sds_port_clear_phy( struct scic_sds_port *port, struct scic_sds_phy *phy) { @@ -485,7 +479,7 @@ void scic_sds_port_get_attached_protocols( * This structure will be posted to the hardware to work around a scheduler * error in the hardware. */ -void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni) +static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni) { union scu_remote_node_context *rnc; @@ -520,7 +514,7 @@ void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni) * in the hardware. * */ -void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci) +static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci) { struct scu_task_context *task_context; @@ -554,7 +548,7 @@ void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci) task_context->task_phase = 0x01; } -void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port) +static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; @@ -569,38 +563,6 @@ void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port) sci_port->reserved_tci = SCU_DUMMY_INDEX; } -void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, - struct scic_sds_controller *scic) -{ - u32 index; - - sci_base_port_construct(&sci_port->parent, scic_sds_port_state_table); - - sci_base_state_machine_construct(&sci_port->ready_substate_machine, - &sci_port->parent.parent, - scic_sds_port_ready_substate_table, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); - - sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; - sci_port->physical_port_index = port_index; - sci_port->active_phy_mask = 0; - - sci_port->owning_controller = scic; - - sci_port->started_request_count = 0; - sci_port->assigned_device_count = 0; - - sci_port->reserved_rni = SCU_DUMMY_INDEX; - sci_port->reserved_tci = SCU_DUMMY_INDEX; - - sci_port->timer_handle = NULL; - - sci_port->port_task_scheduler_registers = NULL; - - for (index = 0; index < SCI_MAX_PHYS; index++) - sci_port->phy_table[index] = NULL; -} - /** * This method performs initialization of the supplied port. Initialization * includes: - state machine initialization - member variable initialization @@ -627,61 +589,18 @@ enum sci_status scic_sds_port_initialize( } /** + * scic_port_get_properties() - This method simply returns the properties + * regarding the port, such as: physical index, protocols, sas address, etc. + * @port: this parameter specifies the port for which to retrieve the physical + * index. + * @properties: This parameter specifies the properties structure into which to + * copy the requested information. * - * @this_port: This is the struct scic_sds_port object for which has a phy that has - * gone link up. - * @the_phy: This is the struct scic_sds_phy object that has gone link up. - * @do_notify_user: This parameter specifies whether to inform the user (via - * scic_cb_port_link_up()) as to the fact that a new phy as become ready. - * - * This method is the a general link up handler for the struct scic_sds_port object. - * This function will determine if this struct scic_sds_phy can be assigned to this - * struct scic_sds_port object. If the struct scic_sds_phy object can is not a valid PHY for - * this port then the function will notify the SCIC_USER. A PHY can only be - * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in - * the same port. none + * Indicate if the user specified a valid port. SCI_SUCCESS This value is + * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This + * value is returned if the specified port is not valid. When this value is + * returned, no data is copied to the properties output parameter. */ -void scic_sds_port_general_link_up_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy, - bool do_notify_user) -{ - struct sci_sas_address port_sas_address; - struct sci_sas_address phy_sas_address; - - scic_sds_port_get_attached_sas_address(this_port, &port_sas_address); - scic_sds_phy_get_attached_sas_address(the_phy, &phy_sas_address); - - /* - * If the SAS address of the new phy matches the SAS address of - * other phys in the port OR this is the first phy in the port, - * then activate the phy and allow it to be used for operations - * in this port. */ - if ( - ( - (phy_sas_address.high == port_sas_address.high) - && (phy_sas_address.low == port_sas_address.low) - ) - || (this_port->active_phy_mask == 0) - ) { - scic_sds_port_activate_phy(this_port, the_phy, do_notify_user); - - if (this_port->parent.state_machine.current_state_id - == SCI_BASE_PORT_STATE_RESETTING) { - sci_base_state_machine_change_state( - &this_port->parent.state_machine, SCI_BASE_PORT_STATE_READY - ); - } - } else { - scic_sds_port_invalid_link_up(this_port, the_phy); - } -} - -enum sci_status scic_port_stop(struct scic_sds_port *port) -{ - return port->state_handlers->parent.stop_handler(&port->parent); -} - enum sci_status scic_port_get_properties( struct scic_sds_port *port, struct scic_port_properties *prop) @@ -700,7 +619,20 @@ enum sci_status scic_port_get_properties( return SCI_SUCCESS; } - +/** + * scic_port_hard_reset() - This method will request the SCI implementation to + * perform a HARD RESET on the SAS Port. If/When the HARD RESET completes + * the SCI user will be notified via an SCI OS callback indicating a direct + * attached device was found. + * @port: a handle corresponding to the SAS port to be hard reset. + * @reset_timeout: This parameter specifies the number of milliseconds in which + * the port reset operation should complete. + * + * The SCI User callback in SCIC_USER_CALLBACKS_T will only be called once for + * each phy in the SAS Port at completion of the hard reset sequence. Return a + * status indicating whether the hard reset started successfully. SCI_SUCCESS + * This value is returned if the hard reset operation started successfully. + */ enum sci_status scic_port_hard_reset( struct scic_sds_port *port, u32 reset_timeout) @@ -741,12 +673,11 @@ void scic_sds_port_setup_transports( * the phy to the port - enabling the Protocol Engine in the silicon. - * notifying the user that the link is up. none */ -void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, - bool do_notify_user) +static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user) { - struct scic_sds_controller *scic = - scic_sds_port_get_controller(sci_port); + struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct sci_sas_identify_address_frame_protocols protocols; struct isci_host *ihost = sci_object_get_association(scic); @@ -764,22 +695,11 @@ void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, isci_port_link_up(ihost, sci_port, sci_phy); } -/** - * - * @this_port: This is the port on which the phy should be deactivated. - * @the_phy: This is the specific phy that is no longer active in the port. - * @do_notify_user: This parameter specifies whether to inform the user (via - * isci_port_link_down()) as to the fact that a new phy as become - * ready. - * - * This function will deactivate the supplied phy in the port. none - */ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy, bool do_notify_user) { - struct scic_sds_controller *scic = - scic_sds_port_get_controller(sci_port); + struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_port *iport = sci_object_get_association(sci_port); struct isci_host *ihost = sci_object_get_association(scic); struct isci_phy *iphy = sci_object_get_association(sci_phy); @@ -821,6 +741,48 @@ static void scic_sds_port_invalid_link_up( } } +/** + * scic_sds_port_general_link_up_handler - phy can be assigned to port? + * @sci_port: scic_sds_port object for which has a phy that has gone link up. + * @sci_phy: This is the struct scic_sds_phy object that has gone link up. + * @do_notify_user: This parameter specifies whether to inform the user (via + * scic_cb_port_link_up()) as to the fact that a new phy as become ready. + * + * Determine if this phy can be assigned to this + * port . If the phy is not a valid PHY for + * this port then the function will notify the user. A PHY can only be + * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in + * the same port. none + */ +static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user) +{ + struct sci_sas_address port_sas_address; + struct sci_sas_address phy_sas_address; + + scic_sds_port_get_attached_sas_address(sci_port, &port_sas_address); + scic_sds_phy_get_attached_sas_address(sci_phy, &phy_sas_address); + + /* If the SAS address of the new phy matches the SAS address of + * other phys in the port OR this is the first phy in the port, + * then activate the phy and allow it to be used for operations + * in this port. + */ + if ((phy_sas_address.high == port_sas_address.high && + phy_sas_address.low == port_sas_address.low) || + sci_port->active_phy_mask == 0) { + struct sci_base_state_machine *sm = &sci_port->parent.state_machine; + + scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); + if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING) + sci_base_state_machine_change_state(sm, SCI_BASE_PORT_STATE_READY); + } else + scic_sds_port_invalid_link_up(sci_port, sci_phy); +} + + + /** * This method returns false if the port only has a single phy object assigned. * If there are no phys or more than one phy then the method will return @@ -1004,7 +966,7 @@ static void scic_sds_port_timeout_handler(void *port) * * */ -void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port) +static void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port) { struct sci_sas_address sas_address; @@ -1483,9 +1445,106 @@ static enum sci_status scic_sds_port_ready_configuring_substate_complete_io_hand return SCI_SUCCESS; } -/* --------------------------------------------------------------------------- */ +static enum sci_status default_port_handler(struct sci_base_port *base_port, const char *func) +{ + struct scic_sds_port *sci_port; + + sci_port = container_of(base_port, typeof(*sci_port), parent); + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", func, + sci_base_state_machine_get_state(&base_port->state_machine)); + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_port_default_start_handler(struct sci_base_port *base_port) +{ + return default_port_handler(base_port, __func__); +} + +static enum sci_status scic_sds_port_default_stop_handler(struct sci_base_port *base_port) +{ + return default_port_handler(base_port, __func__); +} + +static enum sci_status scic_sds_port_default_destruct_handler(struct sci_base_port *base_port) +{ + return default_port_handler(base_port, __func__); +} + +static enum sci_status scic_sds_port_default_reset_handler(struct sci_base_port *base_port, + u32 timeout) +{ + return default_port_handler(base_port, __func__); +} + +static enum sci_status scic_sds_port_default_add_phy_handler(struct sci_base_port *base_port, + struct sci_base_phy *base_phy) +{ + return default_port_handler(base_port, __func__); +} + +static enum sci_status scic_sds_port_default_remove_phy_handler(struct sci_base_port *base_port, + struct sci_base_phy *base_phy) +{ + return default_port_handler(base_port, __func__); +} + +/** + * scic_sds_port_default_frame_handler + * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port + * object. + * + * This is the default method for a port unsolicited frame request. It will + * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even + * possible to receive an unsolicited frame directed to a port object? It + * seems possible if we implementing virtual functions but until then? + */ +static enum sci_status scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port, + u32 frame_index) +{ + struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); + + default_port_handler(&sci_port->parent, __func__); + scic_sds_controller_release_frame(scic, frame_index); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_port_default_event_handler(struct scic_sds_port *sci_port, + u32 event_code) +{ + return default_port_handler(&sci_port->parent, __func__); +} + +static void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + default_port_handler(&sci_port->parent, __func__); +} + +static void scic_sds_port_default_link_down_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + default_port_handler(&sci_port->parent, __func__); +} -struct scic_sds_port_state_handler +static enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + return default_port_handler(&sci_port->parent, __func__); +} + +static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + return default_port_handler(&sci_port->parent, __func__); +} + + + +static struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = { /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */ @@ -1541,7 +1600,6 @@ scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = } }; - /** * scic_sds_port_set_ready_state_handlers() - * @@ -1584,7 +1642,7 @@ static void scic_sds_port_suspend_port_task_scheduler( * ongoing requests. * */ -void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) +static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) { u32 command; struct scu_task_context *task_context; @@ -1609,7 +1667,7 @@ void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) * @sci_port: The port on which the task must be aborted. * */ -void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) +static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; u16 tci = sci_port->reserved_tci; @@ -1801,7 +1859,7 @@ static void scic_sds_port_ready_substate_configuring_exit( /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_port_ready_substate_table[] = { +static const struct sci_base_state scic_sds_port_ready_substate_table[] = { [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { .enter_state = scic_sds_port_ready_substate_waiting_enter, }, @@ -1815,103 +1873,6 @@ const struct sci_base_state scic_sds_port_ready_substate_table[] = { }, }; -static enum sci_status default_port_handler(struct sci_base_port *base_port, const char *func) -{ - struct scic_sds_port *sci_port; - - sci_port = container_of(base_port, typeof(*sci_port), parent); - dev_warn(sciport_to_dev(sci_port), - "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&base_port->state_machine)); - return SCI_FAILURE_INVALID_STATE; -} - -enum sci_status scic_sds_port_default_start_handler(struct sci_base_port *base_port) -{ - return default_port_handler(base_port, __func__); -} - -static enum sci_status scic_sds_port_default_stop_handler(struct sci_base_port *base_port) -{ - return default_port_handler(base_port, __func__); -} - -enum sci_status scic_sds_port_default_destruct_handler(struct sci_base_port *base_port) -{ - return default_port_handler(base_port, __func__); -} - -enum sci_status scic_sds_port_default_reset_handler(struct sci_base_port *base_port, - u32 timeout) -{ - return default_port_handler(base_port, __func__); -} - -static enum sci_status scic_sds_port_default_add_phy_handler(struct sci_base_port *base_port, - struct sci_base_phy *base_phy) -{ - return default_port_handler(base_port, __func__); -} - -enum sci_status scic_sds_port_default_remove_phy_handler(struct sci_base_port *base_port, - struct sci_base_phy *base_phy) -{ - return default_port_handler(base_port, __func__); -} - -/** - * scic_sds_port_default_frame_handler - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * - * This is the default method for a port unsolicited frame request. It will - * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even - * possible to receive an unsolicited frame directed to a port object? It - * seems possible if we implementing virtual functions but until then? - */ -enum sci_status scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port, - u32 frame_index) -{ - struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - - default_port_handler(&sci_port->parent, __func__); - scic_sds_controller_release_frame(scic, frame_index); - - return SCI_FAILURE_INVALID_STATE; -} - -enum sci_status scic_sds_port_default_event_handler(struct scic_sds_port *sci_port, - u32 event_code) -{ - return default_port_handler(&sci_port->parent, __func__); -} - -void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - default_port_handler(&sci_port->parent, __func__); -} - -void scic_sds_port_default_link_down_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - default_port_handler(&sci_port->parent, __func__); -} - -enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return default_port_handler(&sci_port->parent, __func__); -} - -static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return default_port_handler(&sci_port->parent, __func__); -} - /** * * @port: This is the struct scic_sds_port object on which the io request count will @@ -2248,9 +2209,7 @@ static void scic_sds_port_reset_state_link_down_handler( scic_sds_port_deactivate_phy(this_port, phy, false); } -/* --------------------------------------------------------------------------- */ - -struct scic_sds_port_state_handler +static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = { /* SCI_BASE_PORT_STATE_STOPPED */ @@ -2384,7 +2343,7 @@ static void scic_sds_port_disable_port_task_scheduler( scu_port_task_scheduler_write(this_port, control, pts_control_value); } -void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) +static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; u8 phys_index = sci_port->physical_port_index; @@ -2412,7 +2371,7 @@ void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) scic_sds_controller_post_request(scic, command); } -void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) +static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; u8 phys_index = sci_port->physical_port_index; @@ -2639,7 +2598,7 @@ static void scic_sds_port_failed_state_enter(struct sci_base_object *object) /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_port_state_table[] = { +static const struct sci_base_state scic_sds_port_state_table[] = { [SCI_BASE_PORT_STATE_STOPPED] = { .enter_state = scic_sds_port_stopped_state_enter, .exit_state = scic_sds_port_stopped_state_exit @@ -2661,3 +2620,34 @@ const struct sci_base_state scic_sds_port_state_table[] = { } }; +void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, + struct scic_sds_controller *scic) +{ + u32 index; + + sci_base_port_construct(&sci_port->parent, scic_sds_port_state_table); + + sci_base_state_machine_construct(&sci_port->ready_substate_machine, + &sci_port->parent.parent, + scic_sds_port_ready_substate_table, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + + sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; + sci_port->physical_port_index = port_index; + sci_port->active_phy_mask = 0; + + sci_port->owning_controller = scic; + + sci_port->started_request_count = 0; + sci_port->assigned_device_count = 0; + + sci_port->reserved_rni = SCU_DUMMY_INDEX; + sci_port->reserved_tci = SCU_DUMMY_INDEX; + + sci_port->timer_handle = NULL; + + sci_port->port_task_scheduler_registers = NULL; + + for (index = 0; index < SCI_MAX_PHYS; index++) + sci_port->phy_table[index] = NULL; +} diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index ac81a92c348a..8167f5e3be3d 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -236,12 +236,6 @@ struct scic_sds_port_state_handler { }; -extern const struct sci_base_state scic_sds_port_state_table[]; -extern const struct sci_base_state scic_sds_port_ready_substate_table[]; - -extern struct scic_sds_port_state_handler scic_sds_port_state_handler_table[]; -extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[]; - /** * scic_sds_port_get_controller() - * @@ -351,10 +345,6 @@ void scic_sds_port_setup_transports( struct scic_sds_port *this_port, u32 device_id); -void scic_sds_port_activate_phy( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy, - bool do_notify_user); void scic_sds_port_deactivate_phy( struct scic_sds_port *this_port, @@ -363,10 +353,6 @@ void scic_sds_port_deactivate_phy( -void scic_sds_port_general_link_up_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy, - bool do_notify_user); bool scic_sds_port_link_detected( struct scic_sds_port *this_port, @@ -397,47 +383,19 @@ enum sci_status scic_sds_port_complete_io( /* --------------------------------------------------------------------------- */ -void scic_sds_port_update_viit_entry( - struct scic_sds_port *this_port); /* --------------------------------------------------------------------------- */ -enum sci_status scic_sds_port_default_start_handler( - struct sci_base_port *port); -enum sci_status scic_sds_port_default_destruct_handler( - struct sci_base_port *port); -enum sci_status scic_sds_port_default_reset_handler( - struct sci_base_port *port, - u32 timeout); -enum sci_status scic_sds_port_default_remove_phy_handler( - struct sci_base_port *port, - struct sci_base_phy *phy); -enum sci_status scic_sds_port_default_frame_handler( - struct scic_sds_port *port, - u32 frame_index); -enum sci_status scic_sds_port_default_event_handler( - struct scic_sds_port *port, - u32 event_code); -void scic_sds_port_default_link_up_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy); -void scic_sds_port_default_link_down_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy); -enum sci_status scic_sds_port_default_start_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request); enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( @@ -451,12 +409,7 @@ bool scic_sds_port_is_valid_phy_assignment( struct scic_sds_port *this_port, u32 phy_index); -bool scic_sds_port_is_phy_mask_valid( - struct scic_sds_port *this_port, - u32 phy_mask); -u32 scic_sds_port_get_phys( - struct scic_sds_port *this_port); void scic_sds_port_get_sas_address( struct scic_sds_port *this_port, @@ -470,13 +423,7 @@ void scic_sds_port_get_attached_protocols( struct scic_sds_port *this_port, struct sci_sas_identify_address_frame_protocols *protocols); -enum sci_status scic_sds_port_set_phy( - struct scic_sds_port *port, - struct scic_sds_phy *phy); -enum sci_status scic_sds_port_clear_phy( - struct scic_sds_port *port, - struct scic_sds_phy *phy); diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 05599d178caa..5ab8b0321de5 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -87,30 +87,6 @@ u32 scic_remote_device_get_object_size(void) + sizeof(struct scic_sds_remote_node_context); } -/* --------------------------------------------------------------------------- */ - -void scic_remote_device_construct(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev) -{ - sci_dev->owning_port = sci_port; - sci_dev->started_request_count = 0; - sci_dev->rnc = (struct scic_sds_remote_node_context *) &sci_dev[1]; - - sci_base_remote_device_construct( - &sci_dev->parent, - scic_sds_remote_device_state_table - ); - - scic_sds_remote_node_context_construct( - sci_dev, - sci_dev->rnc, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX - ); - - sci_object_set_association(sci_dev->rnc, sci_dev); -} - - enum sci_status scic_remote_device_da_construct( struct scic_sds_remote_device *sci_dev) { @@ -1330,7 +1306,7 @@ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_h /* --------------------------------------------------------------------------- */ -const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { +static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { .parent.start_handler = scic_sds_remote_device_default_start_handler, .parent.stop_handler = scic_sds_remote_device_default_stop_handler, @@ -1741,7 +1717,7 @@ static void scic_sds_remote_device_final_state_enter( /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_remote_device_state_table[] = { +static const struct sci_base_state scic_sds_remote_device_state_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { .enter_state = scic_sds_remote_device_initial_state_enter, }, @@ -1771,3 +1747,23 @@ const struct sci_base_state scic_sds_remote_device_state_table[] = { }, }; +void scic_remote_device_construct(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev) +{ + sci_dev->owning_port = sci_port; + sci_dev->started_request_count = 0; + sci_dev->rnc = (struct scic_sds_remote_node_context *) &sci_dev[1]; + + sci_base_remote_device_construct( + &sci_dev->parent, + scic_sds_remote_device_state_table + ); + + scic_sds_remote_node_context_construct( + sci_dev, + sci_dev->rnc, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX + ); + + sci_object_set_association(sci_dev->rnc, sci_dev); +} diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index aa466249f229..725c0588f2ab 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -316,15 +316,10 @@ struct scic_sds_remote_device_state_handler { scic_sds_remote_device_frame_handler_t frame_handler; }; -extern const struct sci_base_state scic_sds_remote_device_state_table[]; extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[]; extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[]; extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[]; -extern const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[]; -extern const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[]; -extern const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[]; - /** * scic_sds_remote_device_increment_request_count() - * diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c index 253b2d8aa23b..81e4ab34dd30 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.c +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c @@ -64,26 +64,6 @@ #include "scu_event_codes.h" #include "scu_task_context.h" -void scic_sds_remote_node_context_construct( - struct scic_sds_remote_device *device, - struct scic_sds_remote_node_context *rnc, - u16 remote_node_index) -{ - memset(rnc, 0, sizeof(struct scic_sds_remote_node_context)); - - rnc->remote_node_index = remote_node_index; - rnc->device = device; - rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - - sci_base_state_machine_construct( - &rnc->state_machine, - &rnc->parent, - scic_sds_remote_node_context_state_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE - ); - - sci_base_state_machine_start(&rnc->state_machine); -} /** * @@ -124,7 +104,7 @@ bool scic_sds_remote_node_context_is_ready( * * This method will construct the RNC buffer for this remote device object. none */ -void scic_sds_remote_node_context_construct_buffer( +static void scic_sds_remote_node_context_construct_buffer( struct scic_sds_remote_node_context *this_rnc) { union scu_remote_node_context *rnc; @@ -830,7 +810,7 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_event /* --------------------------------------------------------------------------- */ -struct scic_sds_remote_node_context_handlers +static struct scic_sds_remote_node_context_handlers scic_sds_remote_node_context_state_handler_table[ SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] = { @@ -1218,7 +1198,7 @@ static void scic_sds_remote_node_context_await_suspension_state_enter( /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_remote_node_context_state_table[] = { +static const struct sci_base_state scic_sds_remote_node_context_state_table[] = { [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { .enter_state = scic_sds_remote_node_context_initial_state_enter, }, @@ -1245,3 +1225,23 @@ const struct sci_base_state scic_sds_remote_node_context_state_table[] = { }, }; +void scic_sds_remote_node_context_construct( + struct scic_sds_remote_device *device, + struct scic_sds_remote_node_context *rnc, + u16 remote_node_index) +{ + memset(rnc, 0, sizeof(struct scic_sds_remote_node_context)); + + rnc->remote_node_index = remote_node_index; + rnc->device = device; + rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; + + sci_base_state_machine_construct( + &rnc->state_machine, + &rnc->parent, + scic_sds_remote_node_context_state_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE + ); + + sci_base_state_machine_start(&rnc->state_machine); +} diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h index c7c75ae6f092..eccad55ea571 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.h +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h @@ -279,19 +279,11 @@ struct scic_sds_remote_node_context { struct scic_sds_remote_node_context_handlers *state_handlers; }; -extern const struct sci_base_state scic_sds_remote_node_context_state_table[]; - -extern struct scic_sds_remote_node_context_handlers - scic_sds_remote_node_context_state_handler_table[ - SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES]; - void scic_sds_remote_node_context_construct( struct scic_sds_remote_device *device, struct scic_sds_remote_node_context *rnc, u16 remote_node_index); -void scic_sds_remote_node_context_construct_buffer( - struct scic_sds_remote_node_context *rnc); bool scic_sds_remote_node_context_is_ready( struct scic_sds_remote_node_context *this_rnc); diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 4542f4e75f7f..45b8571726f7 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -325,59 +325,6 @@ void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) } } -/** - * This method initializes common portions of the io request object. This - * includes construction of the struct sci_base_request parent. - * @the_controller: This parameter specifies the controller for which the - * request is being constructed. - * @the_target: This parameter specifies the remote device for which the - * request is being constructed. - * @io_tag: This parameter specifies the IO tag to be utilized for this - * request. This parameter can be set to SCI_CONTROLLER_INVALID_IO_TAG. - * @user_io_request_object: This parameter specifies the user request object - * for which the request is being constructed. - * @this_request: This parameter specifies the request being constructed. - * - */ -static void scic_sds_general_request_construct( - struct scic_sds_controller *the_controller, - struct scic_sds_remote_device *the_target, - u16 io_tag, - void *user_io_request_object, - struct scic_sds_request *this_request) -{ - sci_base_request_construct( - &this_request->parent, - scic_sds_request_state_table - ); - - this_request->io_tag = io_tag; - this_request->user_request = user_io_request_object; - this_request->owning_controller = the_controller; - this_request->target_device = the_target; - this_request->has_started_substate_machine = false; - this_request->protocol = SCIC_NO_PROTOCOL; - this_request->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; - this_request->device_sequence = scic_sds_remote_device_get_sequence(the_target); - - this_request->sci_status = SCI_SUCCESS; - this_request->scu_status = 0; - this_request->post_context = 0xFFFFFFFF; - - this_request->is_task_management_request = false; - - if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { - this_request->was_tag_assigned_by_user = false; - this_request->task_context_buffer = NULL; - } else { - this_request->was_tag_assigned_by_user = true; - - this_request->task_context_buffer = - scic_sds_controller_get_task_context_buffer( - this_request->owning_controller, io_tag); - } -} - /** * This method build the remainder of the IO request object. * @this_request: This parameter specifies the request object being constructed. @@ -754,16 +701,6 @@ static enum sci_status scic_io_request_construct_sata(struct scic_sds_request *s return status; } -/* - * **************************************************************************** - * * SCIC Interface Implementation - * **************************************************************************** */ - - - - -/* --------------------------------------------------------------------------- */ - u32 scic_io_request_get_object_size(void) { u32 ssp_request_size; @@ -777,128 +714,6 @@ u32 scic_io_request_get_object_size(void) return max(ssp_request_size, max(stp_request_size, smp_request_size)); } -/* --------------------------------------------------------------------------- */ - - -/* --------------------------------------------------------------------------- */ - - -/* --------------------------------------------------------------------------- */ - - -/* --------------------------------------------------------------------------- */ - -enum sci_status scic_io_request_construct( - struct scic_sds_controller *scic_controller, - struct scic_sds_remote_device *scic_remote_device, - u16 io_tag, - void *user_io_request_object, - void *scic_io_request_memory, - struct scic_sds_request **new_scic_io_request_handle) -{ - enum sci_status status = SCI_SUCCESS; - struct scic_sds_request *this_request; - struct smp_discover_response_protocols device_protocol; - - this_request = (struct scic_sds_request *)scic_io_request_memory; - - /* Build the common part of the request */ - scic_sds_general_request_construct( - (struct scic_sds_controller *)scic_controller, - (struct scic_sds_remote_device *)scic_remote_device, - io_tag, - user_io_request_object, - this_request - ); - - if ( - scic_sds_remote_device_get_index((struct scic_sds_remote_device *)scic_remote_device) - == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX - ) { - return SCI_FAILURE_INVALID_REMOTE_DEVICE; - } - - scic_remote_device_get_protocols(scic_remote_device, &device_protocol); - - if (device_protocol.u.bits.attached_ssp_target) { - scic_sds_ssp_io_request_assign_buffers(this_request); - } else if (device_protocol.u.bits.attached_stp_target) { - scic_sds_stp_request_assign_buffers(this_request); - memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); - } else if (device_protocol.u.bits.attached_smp_target) { - scic_sds_smp_request_assign_buffers(this_request); - memset(this_request->command_buffer, 0, sizeof(struct smp_request)); - } else { - status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - } - - if (status == SCI_SUCCESS) { - memset( - this_request->task_context_buffer, - 0, - SCI_FIELD_OFFSET(struct scu_task_context, sgl_pair_ab) - ); - *new_scic_io_request_handle = scic_io_request_memory; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - - -enum sci_status scic_task_request_construct( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - u16 io_tag, - void *user_io_request_object, - void *scic_task_request_memory, - struct scic_sds_request **new_scic_task_request_handle) -{ - enum sci_status status = SCI_SUCCESS; - struct scic_sds_request *this_request = (struct scic_sds_request *) - scic_task_request_memory; - struct smp_discover_response_protocols device_protocol; - - /* Build the common part of the request */ - scic_sds_general_request_construct( - (struct scic_sds_controller *)controller, - (struct scic_sds_remote_device *)remote_device, - io_tag, - user_io_request_object, - this_request - ); - - scic_remote_device_get_protocols(remote_device, &device_protocol); - - if (device_protocol.u.bits.attached_ssp_target) { - scic_sds_ssp_task_request_assign_buffers(this_request); - - this_request->has_started_substate_machine = true; - - /* Construct the started sub-state machine. */ - sci_base_state_machine_construct( - &this_request->started_substate_machine, - &this_request->parent.parent, - scic_sds_io_request_started_task_mgmt_substate_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION - ); - } else if (device_protocol.u.bits.attached_stp_target) { - scic_sds_stp_request_assign_buffers(this_request); - } else { - status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - } - - if (status == SCI_SUCCESS) { - this_request->is_task_management_request = true; - memset(this_request->task_context_buffer, 0x00, sizeof(struct scu_task_context)); - *new_scic_task_request_handle = scic_task_request_memory; - } - - return status; -} - - enum sci_status scic_io_request_construct_basic_ssp( struct scic_sds_request *sci_req) { @@ -1915,9 +1730,7 @@ static enum sci_status scic_sds_request_aborting_state_frame_handler( return SCI_SUCCESS; } -/* --------------------------------------------------------------------------- */ - -const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { +static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_default_abort_handler, @@ -2142,9 +1955,7 @@ static void scic_sds_request_final_state_enter( ); } -/* --------------------------------------------------------------------------- */ - -const struct sci_base_state scic_sds_request_state_table[] = { +static const struct sci_base_state scic_sds_request_state_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { .enter_state = scic_sds_request_initial_state_enter, }, @@ -2166,3 +1977,119 @@ const struct sci_base_state scic_sds_request_state_table[] = { }, }; +static void scic_sds_general_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, + void *user_io_request_object, + struct scic_sds_request *sci_req) +{ + sci_base_request_construct(&sci_req->parent, scic_sds_request_state_table); + sci_req->io_tag = io_tag; + sci_req->user_request = user_io_request_object; + sci_req->owning_controller = scic; + sci_req->target_device = sci_dev; + sci_req->has_started_substate_machine = false; + sci_req->protocol = SCIC_NO_PROTOCOL; + sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; + sci_req->device_sequence = scic_sds_remote_device_get_sequence(sci_dev); + + sci_req->sci_status = SCI_SUCCESS; + sci_req->scu_status = 0; + sci_req->post_context = 0xFFFFFFFF; + + sci_req->is_task_management_request = false; + + if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { + sci_req->was_tag_assigned_by_user = false; + sci_req->task_context_buffer = NULL; + } else { + sci_req->was_tag_assigned_by_user = true; + + sci_req->task_context_buffer = + scic_sds_controller_get_task_context_buffer(scic, io_tag); + } +} + +enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, + void *user_io_request_object, + struct scic_sds_request *sci_req, + struct scic_sds_request **new_scic_io_request_handle) +{ + enum sci_status status = SCI_SUCCESS; + struct smp_discover_response_protocols device_protocol; + + /* Build the common part of the request */ + scic_sds_general_request_construct(scic, sci_dev, io_tag, + user_io_request_object, sci_req); + + if (sci_dev->rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) + return SCI_FAILURE_INVALID_REMOTE_DEVICE; + + scic_remote_device_get_protocols(sci_dev, &device_protocol); + + if (device_protocol.u.bits.attached_ssp_target) { + scic_sds_ssp_io_request_assign_buffers(sci_req); + } else if (device_protocol.u.bits.attached_stp_target) { + scic_sds_stp_request_assign_buffers(sci_req); + memset(sci_req->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); + } else if (device_protocol.u.bits.attached_smp_target) { + scic_sds_smp_request_assign_buffers(sci_req); + memset(sci_req->command_buffer, 0, sizeof(struct smp_request)); + } else { + status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + } + + if (status == SCI_SUCCESS) { + memset(sci_req->task_context_buffer, 0, + SCI_FIELD_OFFSET(struct scu_task_context, sgl_pair_ab)); + *new_scic_io_request_handle = sci_req; + } + + return status; +} + +enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, + void *user_io_request_object, + struct scic_sds_request *sci_req, + struct scic_sds_request **new_sci_req) +{ + enum sci_status status = SCI_SUCCESS; + struct smp_discover_response_protocols device_protocol; + + /* Build the common part of the request */ + scic_sds_general_request_construct(scic, sci_dev, io_tag, + user_io_request_object, + sci_req); + + scic_remote_device_get_protocols(sci_dev, &device_protocol); + + if (device_protocol.u.bits.attached_ssp_target) { + scic_sds_ssp_task_request_assign_buffers(sci_req); + + sci_req->has_started_substate_machine = true; + + /* Construct the started sub-state machine. */ + sci_base_state_machine_construct( + &sci_req->started_substate_machine, + &sci_req->parent.parent, + scic_sds_io_request_started_task_mgmt_substate_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION + ); + } else if (device_protocol.u.bits.attached_stp_target) { + scic_sds_stp_request_assign_buffers(sci_req); + } else { + status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + } + + if (status == SCI_SUCCESS) { + sci_req->is_task_management_request = true; + memset(sci_req->task_context_buffer, 0, sizeof(struct scu_task_context)); + *new_sci_req = sci_req; + } + + return status; +} diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 06b53c3b0aa0..c54d8ef79ed8 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -256,14 +256,7 @@ struct scic_sds_io_request_state_handler { }; -extern const struct sci_base_state scic_sds_request_state_table[]; -extern const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[]; - extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[]; -extern const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[]; - -extern const struct sci_base_state scic_sds_smp_request_started_substate_table[]; -extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[]; /** * diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index fb832ef544e5..55202481e091 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -207,7 +207,7 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl /* --------------------------------------------------------------------------- */ -const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = { +static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = { [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { .parent.start_handler = scic_sds_remote_device_default_start_handler, .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 962bd3994f10..84b0fdd7ed91 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -142,73 +142,6 @@ void scic_sds_smp_request_assign_buffers( } } -/** - * This method is called by the SCI user to build an SMP IO request. - * - * - The user must have previously called scic_io_request_construct() on the - * supplied IO request. Indicate if the controller successfully built the IO - * request. SCI_SUCCESS This value is returned if the IO request was - * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned - * if the remote_device does not support the SMP protocol. - * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not - * properly set the association between the SCIC IO request and the user's IO - * request. Please refer to the sci_object_set_association() routine for more - * information. - */ -enum sci_status scic_io_request_construct_smp( - struct scic_sds_request *sci_req) -{ - struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); - - if (!smp_req) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - - sci_req->protocol = SCIC_SMP_PROTOCOL; - sci_req->has_started_substate_machine = true; - - /* Construct the started sub-state machine. */ - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - &sci_req->parent.parent, - scic_sds_smp_request_started_substate_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE - ); - - /* Construct the SMP SCU Task Context */ - memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req)); - - /* - * Look at the SMP requests' header fields; for certain SAS 1.x SMP - * functions under SAS 2.0, a zero request length really indicates - * a non-zero default length. */ - if (smp_req->header.request_length == 0) { - switch (smp_req->header.function) { - case SMP_FUNCTION_DISCOVER: - case SMP_FUNCTION_REPORT_PHY_ERROR_LOG: - case SMP_FUNCTION_REPORT_PHY_SATA: - case SMP_FUNCTION_REPORT_ROUTE_INFORMATION: - smp_req->header.request_length = 2; - break; - case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION: - case SMP_FUNCTION_PHY_CONTROL: - case SMP_FUNCTION_PHY_TEST: - smp_req->header.request_length = 9; - break; - /* Default - zero is a valid default for 2.0. */ - } - } - - scu_smp_request_construct_task_context(sci_req, smp_req); - - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED - ); - - kfree(smp_req); - - return SCI_SUCCESS; -} /** * This method is called by the SCI user to build an SMP pass-through IO @@ -595,7 +528,7 @@ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_ha } -const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { +static const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, @@ -658,7 +591,7 @@ static void scic_sds_smp_request_started_await_tc_completion_substate_enter( ); } -const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { +static const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { .enter_state = scic_sds_smp_request_started_await_response_substate_enter, }, @@ -667,3 +600,69 @@ const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { }, }; +/** + * This method is called by the SCI user to build an SMP IO request. + * + * - The user must have previously called scic_io_request_construct() on the + * supplied IO request. Indicate if the controller successfully built the IO + * request. SCI_SUCCESS This value is returned if the IO request was + * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned + * if the remote_device does not support the SMP protocol. + * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not + * properly set the association between the SCIC IO request and the user's IO + * request. Please refer to the sci_object_set_association() routine for more + * information. + */ +enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) +{ + struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); + + if (!smp_req) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + + sci_req->protocol = SCIC_SMP_PROTOCOL; + sci_req->has_started_substate_machine = true; + + /* Construct the started sub-state machine. */ + sci_base_state_machine_construct( + &sci_req->started_substate_machine, + &sci_req->parent.parent, + scic_sds_smp_request_started_substate_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE + ); + + /* Construct the SMP SCU Task Context */ + memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req)); + + /* + * Look at the SMP requests' header fields; for certain SAS 1.x SMP + * functions under SAS 2.0, a zero request length really indicates + * a non-zero default length. */ + if (smp_req->header.request_length == 0) { + switch (smp_req->header.function) { + case SMP_FUNCTION_DISCOVER: + case SMP_FUNCTION_REPORT_PHY_ERROR_LOG: + case SMP_FUNCTION_REPORT_PHY_SATA: + case SMP_FUNCTION_REPORT_ROUTE_INFORMATION: + smp_req->header.request_length = 2; + break; + case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION: + case SMP_FUNCTION_PHY_CONTROL: + case SMP_FUNCTION_PHY_TEST: + smp_req->header.request_length = 9; + break; + /* Default - zero is a valid default for 2.0. */ + } + } + + scu_smp_request_construct_task_context(sci_req, smp_req); + + sci_base_state_machine_change_state( + &sci_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED + ); + + kfree(smp_req); + + return SCI_SUCCESS; +} diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index a826e4bf2928..c9aa35f5cd15 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -193,7 +193,7 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler return SCI_SUCCESS; } -const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { +static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, diff --git a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h index 64bf40a6e1d2..d4dc118f2deb 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h @@ -99,18 +99,7 @@ enum _SCIC_SDS_STP_REQUEST_STARTED_PIO_SUBSTATES { SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, }; - -/* --------------------------------------------------------------------------- */ - -extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[]; - -extern const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[]; - -/* --------------------------------------------------------------------------- */ - struct scic_sds_stp_request; -struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl( - struct scic_sds_stp_request *this_request); #endif /* _SCIC_SDS_SATA_PIO_REQUEST_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index cb396d127773..193a95fa90e1 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -565,7 +565,7 @@ enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_hand /* --------------------------------------------------------------------------- */ -const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { +static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { .parent.start_handler = scic_sds_remote_device_default_start_handler, .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 8da309f81ac2..0e961e9cd6eb 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -267,7 +267,7 @@ static void scu_sata_reqeust_construct_task_context( * This method will perform any general sata request construction. What part of * SATA IO request construction is general? none */ -void scic_sds_stp_non_ncq_request_construct( +static void scic_sds_stp_non_ncq_request_construct( struct scic_sds_request *this_request) { this_request->has_started_substate_machine = true; @@ -318,33 +318,6 @@ static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sc } } -/** - * - * @sci_req: This parameter specifies the request to be constructed. - * - * This method will construct the STP UDMA request and its associated TC data. - * This method returns an indication as to whether the construction was - * successful. SCI_SUCCESS Currently this method always returns this value. - */ -enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, - u32 len, - enum dma_data_direction dir) -{ - scic_sds_stp_non_ncq_request_construct(sci_req); - - scic_sds_stp_optimized_request_construct(sci_req, SCU_TASK_TYPE_DMA_IN, - len, dir); - - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - &sci_req->parent.parent, - scic_sds_stp_request_started_udma_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE - ); - - return SCI_SUCCESS; -} - /** * * @sci_req: This parameter specifies the request to be constructed. @@ -364,7 +337,7 @@ enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_ } /** - * + * scu_stp_raw_request_construct_task_context - * @this_request: This parameter specifies the STP request object for which to * construct a RAW command frame task context. * @task_context: This parameter specifies the SCU specific task context buffer @@ -373,7 +346,7 @@ enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_ * This method performs the operations common to all SATA/STP requests * utilizing the raw frame method. none */ -void scu_stp_raw_request_construct_task_context( +static void scu_stp_raw_request_construct_task_context( struct scic_sds_stp_request *this_request, struct scu_task_context *task_context) { @@ -386,59 +359,6 @@ void scu_stp_raw_request_construct_task_context( task_context->transfer_length_bytes = sizeof(struct sata_fis_reg_h2d) - sizeof(u32); } -/** - * - * @this_request: This parameter specifies the core request object to - * construction into an STP/SATA non-data request. - * - * This method will construct the STP Non-data request and its associated TC - * data. A non-data request essentially behaves like a 0 length read request - * in the SCU. This method currently always returns SCI_SUCCESS - */ -enum sci_status scic_sds_stp_non_data_request_construct( - struct scic_sds_request *this_request) -{ - scic_sds_stp_non_ncq_request_construct(this_request); - - /* Build the STP task context structure */ - scu_stp_raw_request_construct_task_context( - (struct scic_sds_stp_request *)this_request, - this_request->task_context_buffer - ); - - sci_base_state_machine_construct( - &this_request->started_substate_machine, - &this_request->parent.parent, - scic_sds_stp_request_started_non_data_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE - ); - - return SCI_SUCCESS; -} - - -enum sci_status scic_sds_stp_soft_reset_request_construct( - struct scic_sds_request *this_request) -{ - scic_sds_stp_non_ncq_request_construct(this_request); - - /* Build the STP task context structure */ - scu_stp_raw_request_construct_task_context( - (struct scic_sds_stp_request *)this_request, - this_request->task_context_buffer - ); - - sci_base_state_machine_construct( - &this_request->started_substate_machine, - &this_request->parent.parent, - scic_sds_stp_request_started_soft_reset_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE - ); - - return SCI_SUCCESS; -} - - void scic_stp_io_request_set_ncq_tag( struct scic_sds_request *req, u16 ncq_tag) @@ -474,7 +394,7 @@ void *scic_stp_io_request_get_d2h_reg_address( * - if there are more SGL element pairs - advance to the next pair and return * element A struct scu_sgl_element* */ -struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) +static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) { struct scu_sgl_element *current_sgl; struct scic_sds_request *sci_req = &stp_req->parent; @@ -508,60 +428,6 @@ struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_st return current_sgl; } -/** - * - * @scic_io_request: The core request object which is cast to a SATA PIO - * request object. - * - * This method will construct the SATA PIO request. This method returns an - * indication as to whether the construction was successful. SCI_SUCCESS - * Currently this method always returns this value. - */ -enum sci_status scic_sds_stp_pio_request_construct( - struct scic_sds_request *scic_io_request, - u8 sat_protocol, - bool copy_rx_frame) -{ - struct scic_sds_stp_request *this_request; - - this_request = (struct scic_sds_stp_request *)scic_io_request; - - scic_sds_stp_non_ncq_request_construct(&this_request->parent); - - scu_stp_raw_request_construct_task_context( - this_request, this_request->parent.task_context_buffer - ); - - this_request->type.pio.current_transfer_bytes = 0; - this_request->type.pio.ending_error = 0; - this_request->type.pio.ending_status = 0; - - this_request->type.pio.request_current.sgl_offset = 0; - this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; - this_request->type.pio.sat_protocol = sat_protocol; - - if (copy_rx_frame) { - scic_sds_request_build_sgl(&this_request->parent); - /* - * Since the IO request copy of the TC contains the same data as - * the actual TC this pointer is vaild for either. */ - this_request->type.pio.request_current.sgl_pair = - &this_request->parent.task_context_buffer->sgl_pair_ab; - } else { - /* The user does not want the data copied to the SGL buffer location */ - this_request->type.pio.request_current.sgl_pair = NULL; - } - - sci_base_state_machine_construct( - &this_request->parent.started_substate_machine, - &this_request->parent.parent.parent, - scic_sds_stp_request_started_pio_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE - ); - - return SCI_SUCCESS; -} - /** * * @this_request: @@ -689,7 +555,7 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( /* --------------------------------------------------------------------------- */ -const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { +static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, @@ -740,7 +606,7 @@ static void scic_sds_stp_request_started_non_data_await_d2h_enter( /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = { +static const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, }, @@ -749,6 +615,23 @@ const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table }, }; +enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req) +{ + struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + + scic_sds_stp_non_ncq_request_construct(sci_req); + + /* Build the STP task context structure */ + scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); + + sci_base_state_machine_construct(&sci_req->started_substate_machine, + &sci_req->parent.parent, + scic_sds_stp_request_started_non_data_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE); + + return SCI_SUCCESS; +} + #define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ /** @@ -1330,7 +1213,7 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler /* --------------------------------------------------------------------------- */ -const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { +static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, @@ -1422,7 +1305,7 @@ static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = { +static const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, }, @@ -1437,6 +1320,45 @@ const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = } }; +enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, + u8 sat_protocol, + bool copy_rx_frame) +{ + struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; + + scic_sds_stp_non_ncq_request_construct(sci_req); + + scu_stp_raw_request_construct_task_context(stp_req, + sci_req->task_context_buffer); + + pio->current_transfer_bytes = 0; + pio->ending_error = 0; + pio->ending_status = 0; + + pio->request_current.sgl_offset = 0; + pio->request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; + pio->sat_protocol = sat_protocol; + + if (copy_rx_frame) { + scic_sds_request_build_sgl(sci_req); + /* Since the IO request copy of the TC contains the same data as + * the actual TC this pointer is vaild for either. + */ + pio->request_current.sgl_pair = &sci_req->task_context_buffer->sgl_pair_ab; + } else { + /* The user does not want the data copied to the SGL buffer location */ + pio->request_current.sgl_pair = NULL; + } + + sci_base_state_machine_construct(&sci_req->started_substate_machine, + &sci_req->parent.parent, + scic_sds_stp_request_started_pio_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE); + + return SCI_SUCCESS; +} + static void scic_sds_stp_request_udma_complete_request( struct scic_sds_request *this_request, u32 scu_status, @@ -1594,7 +1516,7 @@ static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler /* --------------------------------------------------------------------------- */ -const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { +static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, @@ -1648,7 +1570,7 @@ static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( /* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = { +static const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter, }, @@ -1657,6 +1579,25 @@ const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = }, }; +enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, + u32 len, + enum dma_data_direction dir) +{ + scic_sds_stp_non_ncq_request_construct(sci_req); + + scic_sds_stp_optimized_request_construct(sci_req, SCU_TASK_TYPE_DMA_IN, + len, dir); + + sci_base_state_machine_construct( + &sci_req->started_substate_machine, + &sci_req->parent.parent, + scic_sds_stp_request_started_udma_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE + ); + + return SCI_SUCCESS; +} + /** * * @this_request: @@ -1831,7 +1772,7 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( /* --------------------------------------------------------------------------- */ -const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { +static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, @@ -1925,9 +1866,7 @@ static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( ); } -/* --------------------------------------------------------------------------- */ - -const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = { +static const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, }, @@ -1939,3 +1878,19 @@ const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_tab }, }; +enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req) +{ + struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + + scic_sds_stp_non_ncq_request_construct(sci_req); + + /* Build the STP task context structure */ + scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); + + sci_base_state_machine_construct(&sci_req->started_substate_machine, + &sci_req->parent.parent, + scic_sds_stp_request_started_soft_reset_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE); + + return SCI_SUCCESS; +} diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index c950bb33ee04..107487978f06 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -76,7 +76,7 @@ struct scic_sds_stp_request { u32 udma; - struct { + struct scic_sds_stp_pio_request { /** * Total transfer for the entire PIO request recorded at request constuction * time. @@ -169,26 +169,8 @@ enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES { SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, }; -extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[]; - -extern const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[]; - -extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[]; - -extern const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[]; - -extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[]; - -extern const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[]; - -/* --------------------------------------------------------------------------- */ - u32 scic_sds_stp_request_get_object_size(void); - -void scic_sds_stp_non_ncq_request_construct( - struct scic_sds_request *this_request); - enum sci_status scic_sds_stp_pio_request_construct( struct scic_sds_request *scic_io_request, u8 sat_protocol, @@ -214,8 +196,5 @@ enum sci_status scic_sds_stp_ncq_request_construct( u32 transfer_length, enum dma_data_direction dir); -void scu_stp_raw_request_construct_task_context( - struct scic_sds_stp_request *this_request, - struct scu_task_context *task_context); #endif /* _SCIC_SDS_STP_REQUEST_T_ */ diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README index cf7e4286e896..8056d2bd233b 100644 --- a/drivers/scsi/isci/firmware/README +++ b/drivers/scsi/isci/firmware/README @@ -32,5 +32,5 @@ Header Type - u8: 0xf ============================================================================== Place isci_firmware.bin in /lib/firmware -Be sure to recreate the initramfs image to include the firmware. +Be sure to recreate the initramfs image to include the firmware. diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 666076a2834e..74dc96dc6b17 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -201,7 +201,7 @@ void isci_port_link_up( call_status = scic_sata_phy_get_properties(phy, &sata_phy_properties); - /* + /* * XXX I am concerned about this "assert". shouldn't we * handle the return appropriately? */ diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index eba8e0b3c873..c6ce9d0c50c2 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1263,47 +1263,6 @@ enum dma_data_direction isci_request_io_request_get_data_direction( * * physical address in the specified sge. */ -dma_addr_t isci_request_sge_get_address_field( - struct isci_request *request, - void *sge_address) -{ - struct sas_task *task = isci_request_access_task(request); - dma_addr_t ret; - struct isci_host *isci_host = isci_host_from_sas_ha( - task->dev->port->ha); - - dev_dbg(&isci_host->pdev->dev, - "%s: request = %p, sge_address = %p\n", - __func__, - request, - sge_address); - - if (task->data_dir == PCI_DMA_NONE) - return 0; - - /* the case where num_scatter == 0 is special, in that - * task->scatter is the actual buffer address, not an sgl. - * so a map single is required here. - */ - if ((task->num_scatter == 0) && - !sas_protocol_ata(task->task_proto)) { - ret = dma_map_single( - &isci_host->pdev->dev, - task->scatter, - task->total_xfer_len, - task->data_dir - ); - request->zero_scatter_daddr = ret; - } else - ret = sg_dma_address(((struct scatterlist *)sge_address)); - - dev_dbg(&isci_host->pdev->dev, - "%s: bus address = %lx\n", - __func__, - (unsigned long)ret); - - return ret; -} /** @@ -1314,38 +1273,6 @@ dma_addr_t isci_request_sge_get_address_field( * * length field value in the specified sge. */ -u32 isci_request_sge_get_length_field( - struct isci_request *request, - void *sge_address) -{ - struct sas_task *task = isci_request_access_task(request); - int ret; - - dev_dbg(&request->isci_host->pdev->dev, - "%s: request = %p, sge_address = %p\n", - __func__, - request, - sge_address); - - if (task->data_dir == PCI_DMA_NONE) - return 0; - - /* the case where num_scatter == 0 is special, in that - * task->scatter is the actual buffer address, not an sgl. - * so we return total_xfer_len here. - */ - if (task->num_scatter == 0) - ret = task->total_xfer_len; - else - ret = sg_dma_len((struct scatterlist *)sge_address); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: len = %d\n", - __func__, - ret); - - return ret; -} /** diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index b45c0f1f057f..4a63bb6de44e 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -391,13 +391,7 @@ static inline void *isci_request_io_request_get_next_sge( return ret; } -dma_addr_t isci_request_sge_get_address_field( - struct isci_request *request, - void *sge_address); -u32 isci_request_sge_get_length_field( - struct isci_request *request, - void *sge_address); void *isci_request_ssp_io_request_get_cdb_address( struct isci_request *request); diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index d48368002504..7e9668402559 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -588,7 +588,7 @@ void isci_task_build_tmf( tmf->cb_data = cb_data; } -void isci_task_build_abort_task_tmf( +static void isci_task_build_abort_task_tmf( struct isci_tmf *tmf, struct isci_remote_device *isci_device, enum isci_tmf_function_codes code, @@ -1528,15 +1528,6 @@ void isci_task_request_complete( * * lun for specified task request. */ -u32 isci_task_ssp_request_get_lun(struct isci_request *request) -{ - struct isci_tmf *isci_tmf = isci_request_access_tmf(request); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: lun = %d\n", __func__, isci_tmf->lun[0]); -/* @todo: build lun from array of bytes to 32 bit */ - return isci_tmf->lun[0]; -} /** * isci_task_ssp_request_get_function() - This function is called by the sci diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index 9754b43f5b0b..d7cb6fe268c4 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -202,8 +202,6 @@ u16 isci_task_ssp_request_get_io_tag_to_manage( u8 isci_task_ssp_request_get_function( struct isci_request *request); -u32 isci_task_ssp_request_get_lun( - struct isci_request *request); void *isci_task_ssp_request_get_response_data_address( struct isci_request *request); @@ -226,14 +224,6 @@ void isci_task_build_tmf( void *), void *cb_data); -void isci_task_build_abort_task_tmf( - struct isci_tmf *tmf, - struct isci_remote_device *isci_device, - enum isci_tmf_function_codes code, - void (*tmf_sent_cb)( - enum isci_tmf_cb_state, - struct isci_tmf *, void *), - struct isci_request *old_request); int isci_task_execute_tmf( struct isci_host *isci_host, -- cgit v1.2.3 From 2828dc0b55da8937439121eaa82e9ee80c520f53 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 26 Mar 2011 16:56:55 -0700 Subject: isci: remove unused "remote_device_started" These routines are just stubs, re-add them when / if they are needed. Also cleanup remote_device_stopped. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 29 ++------------------ drivers/scsi/isci/core/scic_sds_controller.h | 35 +------------------------ drivers/scsi/isci/core/scic_sds_remote_device.c | 23 +++------------- 3 files changed, 7 insertions(+), 80 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 5cc6f2fa0939..f20d0eb9bda6 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1583,31 +1583,6 @@ void scic_sds_controller_link_down( sci_phy->phy_index, state); } -/** - * This method is called by the remote device to inform the controller - * that this remote device has started. - * - */ - -void scic_sds_controller_remote_device_started(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev) -{ - u32 state; - scic_sds_controller_device_handler_t started; - - state = scic->parent.state_machine.current_state_id; - started = scic_sds_controller_state_handler_table[state].remote_device_started_handler; - - if (started) - started(scic, sci_dev); - else { - dev_dbg(scic_to_dev(scic), - "%s: SCIC Controller 0x%p remote device started event " - "from device 0x%p in unexpected state %d\n", - __func__, scic, sci_dev, state); - } -} - /** * This is a helper method to determine if any remote devices on this * controller are still in the stopping state. @@ -1642,7 +1617,7 @@ void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, scic_sds_controller_device_handler_t stopped; state = scic->parent.state_machine.current_state_id; - stopped = scic_sds_controller_state_handler_table[state].remote_device_stopped_handler; + stopped = scic_sds_controller_state_handler_table[state].device_stopped; if (stopped) stopped(scic, sci_dev); @@ -3575,7 +3550,7 @@ const struct scic_sds_controller_state_handler scic_sds_controller_state_handler .base.complete_io = scic_sds_controller_stopping_state_complete_io_handler, .base.continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, - .remote_device_stopped_handler = scic_sds_controller_stopping_state_device_stopped_handler, + .device_stopped = scic_sds_controller_stopping_state_device_stopped_handler, }, [SCI_BASE_CONTROLLER_STATE_STOPPED] = { .base.reset = scic_sds_controller_general_reset_handler, diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index fedf5032d898..22b5f2c24a02 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -396,8 +396,7 @@ struct scic_sds_controller_state_handler { sci_base_controller_request_handler_t terminate_request; scic_sds_controller_phy_handler_t link_up; scic_sds_controller_phy_handler_t link_down; - scic_sds_controller_device_handler_t remote_device_started_handler; - scic_sds_controller_device_handler_t remote_device_stopped_handler; + scic_sds_controller_device_handler_t device_stopped; }; extern const struct scic_sds_controller_state_handler @@ -532,17 +531,10 @@ extern const struct scic_sds_controller_state_handler #define scic_sds_controller_clear_invalid_phy(controller, phy) \ ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) -/* --------------------------------------------------------------------------- */ - - -/* --------------------------------------------------------------------------- */ - void scic_sds_controller_post_request( struct scic_sds_controller *this_controller, u32 request); -/* --------------------------------------------------------------------------- */ - void scic_sds_controller_release_frame( struct scic_sds_controller *this_controller, u32 frame_index); @@ -552,8 +544,6 @@ void scic_sds_controller_copy_sata_response( void *frame_header, void *frame_buffer); -/* --------------------------------------------------------------------------- */ - enum sci_status scic_sds_controller_allocate_remote_node_context( struct scic_sds_controller *this_controller, struct scic_sds_remote_device *the_device, @@ -568,8 +558,6 @@ union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffe struct scic_sds_controller *this_controller, u16 node_id); -/* --------------------------------------------------------------------------- */ - struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( struct scic_sds_controller *this_controller, u16 io_tag); @@ -579,12 +567,6 @@ struct scu_task_context *scic_sds_controller_get_task_context_buffer( struct scic_sds_controller *this_controller, u16 io_tag); -/* - * ***************************************************************************** - * * CORE CONTROLLER POWER CONTROL METHODS - * ***************************************************************************** */ - - void scic_sds_controller_power_control_queue_insert( struct scic_sds_controller *this_controller, struct scic_sds_phy *the_phy); @@ -593,11 +575,6 @@ void scic_sds_controller_power_control_queue_remove( struct scic_sds_controller *this_controller, struct scic_sds_phy *the_phy); -/* - * ***************************************************************************** - * * CORE CONTROLLER PHY MESSAGE PROCESSING - * ***************************************************************************** */ - void scic_sds_controller_link_up( struct scic_sds_controller *this_controller, struct scic_sds_port *the_port, @@ -608,16 +585,6 @@ void scic_sds_controller_link_down( struct scic_sds_port *the_port, struct scic_sds_phy *the_phy); -/* - * ***************************************************************************** - * * CORE CONTROLLER REMOTE DEVICE MESSAGE PROCESSING - * ***************************************************************************** */ - - -void scic_sds_controller_remote_device_started( - struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *the_device); - void scic_sds_controller_remote_device_stopped( struct scic_sds_controller *this_controller, struct scic_sds_remote_device *the_device); diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 5ab8b0321de5..e100fdeee031 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1533,34 +1533,19 @@ static void scic_sds_remote_device_starting_state_enter( SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); } -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the exit function for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it - * reports that the device start is complete. none - */ -static void scic_sds_remote_device_starting_state_exit( - struct sci_base_object *object) +static void scic_sds_remote_device_starting_state_exit(struct sci_base_object *object) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)object; - struct scic_sds_controller *scic = - scic_sds_remote_device_get_controller(sci_dev); + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); - /* * @todo Check the device object for the proper return code for this * callback */ isci_remote_device_start_complete(ihost, idev, SCI_SUCCESS); - - scic_sds_controller_remote_device_started( - scic_sds_remote_device_get_controller(sci_dev), - sci_dev); } /** -- cgit v1.2.3 From de728b7d72089330603819a74255a0469780fd0e Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Sat, 26 Mar 2011 17:14:07 -0700 Subject: isci: Remove "screaming" data types Converting the all CAPS data types to lower case. Reported-by: Christoph Hellwig Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sati_translator_sequence.h | 16 ++--- drivers/scsi/isci/core/sci_base_port.h | 44 ++++++------- drivers/scsi/isci/core/sci_base_request.h | 10 +-- drivers/scsi/isci/core/sci_base_state.h | 8 +-- drivers/scsi/isci/core/sci_base_state_machine.c | 4 +- drivers/scsi/isci/core/sci_status.h | 6 +- drivers/scsi/isci/core/scic_port.h | 2 +- drivers/scsi/isci/core/scic_sds_controller.c | 2 +- drivers/scsi/isci/core/scic_sds_controller.h | 4 +- drivers/scsi/isci/core/scic_sds_phy.h | 8 +-- drivers/scsi/isci/core/scic_sds_port.c | 7 +-- drivers/scsi/isci/core/scic_sds_port.h | 72 ++++++++++++---------- .../isci/core/scic_sds_port_configuration_agent.c | 2 +- .../isci/core/scic_sds_port_configuration_agent.h | 6 +- .../scsi/isci/core/scic_sds_remote_node_context.h | 4 +- drivers/scsi/isci/core/scic_sds_request.h | 8 +-- .../scsi/isci/core/scic_sds_stp_packet_request.c | 4 +- .../scsi/isci/core/scic_sds_stp_packet_request.h | 2 +- drivers/scsi/isci/core/scic_sds_stp_pio_request.h | 2 +- drivers/scsi/isci/core/scic_sds_stp_request.h | 12 ++-- .../isci/core/scic_sds_unsolicited_frame_control.h | 6 +- drivers/scsi/isci/core/scu_registers.h | 62 +++++++++---------- drivers/scsi/isci/core/scu_task_context.h | 48 +++++++-------- drivers/scsi/isci/probe_roms.h | 2 +- 24 files changed, 167 insertions(+), 174 deletions(-) diff --git a/drivers/scsi/isci/core/sati_translator_sequence.h b/drivers/scsi/isci/core/sati_translator_sequence.h index 592570d50ebd..915724c380d9 100644 --- a/drivers/scsi/isci/core/sati_translator_sequence.h +++ b/drivers/scsi/isci/core/sati_translator_sequence.h @@ -67,7 +67,7 @@ #include "sati_device.h" /** - * enum _SATI_TRANSLATOR_SEQUENCE_TYPE - This enumeration defines the possible + * enum _sati_translator_sequence_type - This enumeration defines the possible * sequence types for the translator. * * @@ -172,7 +172,7 @@ enum sati_translator_sequence_type { * * */ -typedef struct SATI_MODE_SELECT_PROCESSING_STATE { +struct sati_mode_select_processing_state { u8 *mode_pages; u32 mode_page_offset; u32 mode_pages_size; @@ -180,11 +180,10 @@ typedef struct SATI_MODE_SELECT_PROCESSING_STATE { u32 total_ata_command_sent; u32 ata_command_sent_for_cmp; /* cmp: current mode page */ bool current_mode_page_processed; - -} SATI_MODE_SELECT_PROCESSING_STATE_T; +}; -enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS { +enum sati_reassign_blocks_ata_command_status { SATI_REASSIGN_BLOCKS_READY_TO_SEND, SATI_REASSIGN_BLOCKS_COMMAND_FAIL, SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS, @@ -204,7 +203,7 @@ struct sati_reassign_blocks_processing_state { u32 size_of_data_processed; u32 ata_command_sent_for_current_lba; bool current_lba_processed; - enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS ata_command_status; + enum sati_reassign_blocks_ata_command_status ata_command_status; }; @@ -291,8 +290,9 @@ struct sati_translator_sequence { u32 translated_command; u32 move_sector_count; u32 scratch; - struct sati_reassign_blocks_processing_state reassign_blocks_process_state; - SATI_MODE_SELECT_PROCESSING_STATE_T process_state; + struct sati_reassign_blocks_processing_state + reassign_blocks_process_state; + struct sati_mode_select_processing_state process_state; struct sati_atapi_data sati_atapi_data; } command_specific_data; diff --git a/drivers/scsi/isci/core/sci_base_port.h b/drivers/scsi/isci/core/sci_base_port.h index b931c3c2cdf9..252d48c1ab65 100644 --- a/drivers/scsi/isci/core/sci_base_port.h +++ b/drivers/scsi/isci/core/sci_base_port.h @@ -128,19 +128,16 @@ struct sci_base_port { struct sci_base_phy; -typedef enum sci_status (*SCI_BASE_PORT_HANDLER_T)( - struct sci_base_port * - ); +typedef enum sci_status (*sci_base_port_handler_t) ( + struct sci_base_port *); -typedef enum sci_status (*SCI_BASE_PORT_PHY_HANDLER_T)( +typedef enum sci_status (*sci_base_port_phy_handler_t) ( struct sci_base_port *, - struct sci_base_phy * - ); + struct sci_base_phy *); -typedef enum sci_status (*SCI_BASE_PORT_RESET_HANDLER_T)( +typedef enum sci_status (*sci_base_port_reset_handler_t) ( struct sci_base_port *, - u32 timeout - ); + u32 timeout); /** * struct sci_base_port_state_handler - This structure contains all of the @@ -152,40 +149,39 @@ typedef enum sci_status (*SCI_BASE_PORT_RESET_HANDLER_T)( */ struct sci_base_port_state_handler { /** - * The start_handler specifies the method invoked when a user attempts to - * start a port. + * The start_handler specifies the method invoked when a user + * attempts to start a port. */ - SCI_BASE_PORT_HANDLER_T start_handler; + sci_base_port_handler_t start_handler; /** - * The stop_handler specifies the method invoked when a user attempts to - * stop a port. + * The stop_handler specifies the method invoked when a user + * attempts to stop a port. */ - SCI_BASE_PORT_HANDLER_T stop_handler; + sci_base_port_handler_t stop_handler; /** * The destruct_handler specifies the method invoked when attempting to * destruct a port. */ - SCI_BASE_PORT_HANDLER_T destruct_handler; + sci_base_port_handler_t destruct_handler; /** - * The reset_handler specifies the method invoked when a user attempts to - * hard reset a port. + * The reset_handler specifies the method invoked when a user + * attempts to hard reset a port. */ - SCI_BASE_PORT_RESET_HANDLER_T reset_handler; + sci_base_port_reset_handler_t reset_handler; /** - * The add_phy_handler specifies the method invoked when a user attempts to - * add another phy into the port. + * The add_phy_handler specifies the method invoked when a user + * attempts to add another phy into the port. */ - SCI_BASE_PORT_PHY_HANDLER_T add_phy_handler; + sci_base_port_phy_handler_t add_phy_handler; /** * The remove_phy_handler specifies the method invoked when a user * attempts to remove a phy from the port. */ - SCI_BASE_PORT_PHY_HANDLER_T remove_phy_handler; - + sci_base_port_phy_handler_t remove_phy_handler; }; #endif /* _SCI_BASE_PORT_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_request.h b/drivers/scsi/isci/core/sci_base_request.h index d1b2195b228a..223aa4c5f757 100644 --- a/drivers/scsi/isci/core/sci_base_request.h +++ b/drivers/scsi/isci/core/sci_base_request.h @@ -129,7 +129,7 @@ struct sci_base_request { struct sci_base_state_machine state_machine; }; -typedef enum sci_status (*SCI_BASE_REQUEST_HANDLER_T)( +typedef enum sci_status (*sci_base_request_handler_t)( struct sci_base_request *this_request ); @@ -146,25 +146,25 @@ struct sci_base_request_state_handler { * The start_handler specifies the method invoked when a user attempts to * start a request. */ - SCI_BASE_REQUEST_HANDLER_T start_handler; + sci_base_request_handler_t start_handler; /** * The abort_handler specifies the method invoked when a user attempts to * abort a request. */ - SCI_BASE_REQUEST_HANDLER_T abort_handler; + sci_base_request_handler_t abort_handler; /** * The complete_handler specifies the method invoked when a user attempts to * complete a request. */ - SCI_BASE_REQUEST_HANDLER_T complete_handler; + sci_base_request_handler_t complete_handler; /** * The destruct_handler specifies the method invoked when a user attempts to * destruct a request. */ - SCI_BASE_REQUEST_HANDLER_T destruct_handler; + sci_base_request_handler_t destruct_handler; }; diff --git a/drivers/scsi/isci/core/sci_base_state.h b/drivers/scsi/isci/core/sci_base_state.h index d6b9c1a951b1..4272a6f116de 100644 --- a/drivers/scsi/isci/core/sci_base_state.h +++ b/drivers/scsi/isci/core/sci_base_state.h @@ -58,11 +58,11 @@ #include "sci_object.h" -typedef void (*SCI_BASE_STATE_HANDLER_T)( +typedef void (*sci_base_state_handler_t)( void ); -typedef void (*SCI_STATE_TRANSITION_T)( +typedef void (*sci_state_transition_t)( struct sci_base_object *base_object ); @@ -77,13 +77,13 @@ struct sci_base_state { * This field is a function pointer that defines the method to be * invoked when the state is entered. */ - SCI_STATE_TRANSITION_T enter_state; + sci_state_transition_t enter_state; /** * This field is a function pointer that defines the method to be * invoked when the state is exited. */ - SCI_STATE_TRANSITION_T exit_state; + sci_state_transition_t exit_state; }; diff --git a/drivers/scsi/isci/core/sci_base_state_machine.c b/drivers/scsi/isci/core/sci_base_state_machine.c index 5b1e8da55fe6..bc416d504d7e 100644 --- a/drivers/scsi/isci/core/sci_base_state_machine.c +++ b/drivers/scsi/isci/core/sci_base_state_machine.c @@ -65,7 +65,7 @@ static void sci_state_machine_exit_state(struct sci_base_state_machine *sm) { u32 state = sm->current_state_id; - SCI_STATE_TRANSITION_T exit = sm->state_table[state].exit_state; + sci_state_transition_t exit = sm->state_table[state].exit_state; if (exit) exit(sm->state_machine_owner); @@ -74,7 +74,7 @@ static void sci_state_machine_exit_state(struct sci_base_state_machine *sm) static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) { u32 state = sm->current_state_id; - SCI_STATE_TRANSITION_T enter = sm->state_table[state].enter_state; + sci_state_transition_t enter = sm->state_table[state].enter_state; if (enter) enter(sm->state_machine_owner); diff --git a/drivers/scsi/isci/core/sci_status.h b/drivers/scsi/isci/core/sci_status.h index 72b61081c28d..8b66619022cf 100644 --- a/drivers/scsi/isci/core/sci_status.h +++ b/drivers/scsi/isci/core/sci_status.h @@ -65,7 +65,7 @@ /** - * enum _SCI_STATUS - This is the general return status enumeration for non-IO, + * enum sci_status - This is the general return status enumeration for non-IO, * non-task management related SCI interface methods. * * @@ -347,7 +347,7 @@ enum sci_status { }; /** - * enum _SCI_IO_STATUS - This enumeration depicts all of the possible IO + * enum sci_io_status - This enumeration depicts all of the possible IO * completion status values. Each value in this enumeration maps directly * to a value in the enum sci_status enumeration. Please refer to that * enumeration for detailed comments concerning what the status represents. @@ -380,7 +380,7 @@ enum sci_io_status { }; /** - * enum _SCI_TASK_STATUS - This enumeration depicts all of the possible task + * enum sci_task_status - This enumeration depicts all of the possible task * completion status values. Each value in this enumeration maps directly * to a value in the enum sci_status enumeration. Please refer to that * enumeration for detailed comments concerning what the status represents. diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h index 582953343237..56d05073f9c5 100644 --- a/drivers/scsi/isci/core/scic_port.h +++ b/drivers/scsi/isci/core/scic_port.h @@ -61,7 +61,7 @@ struct scic_sds_port; -enum SCIC_PORT_NOT_READY_REASON_CODE { +enum scic_port_not_ready_reason_code { SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index f20d0eb9bda6..9266fbee79e7 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -705,7 +705,7 @@ static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller for (index = 0; index < scic->logical_port_entries; index++) { struct scic_sds_port *sci_port = &scic->port_table[index]; - SCI_BASE_PORT_HANDLER_T stop; + sci_base_port_handler_t stop; stop = sci_port->state_handlers->parent.stop_handler; port_status = stop(&sci_port->parent); diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 22b5f2c24a02..fd78148d93d9 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -90,12 +90,12 @@ struct scic_sds_controller; #define SCU_COMPLETION_RAM_ALIGNMENT (64) /** - * enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS - + * enum scic_sds_controller_memory_descriptors - * * This enumeration depects the types of MDEs that are going to be created for * the controller object. */ -enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS { +enum scic_sds_controller_memory_descriptors { /** * Completion queue MDE entry */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 4745a791f15b..7f7a04542031 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -92,11 +92,11 @@ struct scic_sds_port; #define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250 /** - * enum SCIC_SDS_PHY_STARTING_SUBSTATES - + * enum scic_sds_phy_starting_substates - * * */ -enum SCIC_SDS_PHY_STARTING_SUBSTATES { +enum scic_sds_phy_starting_substates { /** * Initial state */ @@ -156,7 +156,7 @@ struct scic_sds_controller; * * */ -enum SCIC_SDS_PHY_PROTOCOL { +enum scic_sds_phy_protocol { /** * This is an unknown phy type since there is either nothing on the other * end or we have not detected the phy type as yet. @@ -202,7 +202,7 @@ struct scic_sds_phy { * field contains a legitamite value once the PHY has link trained with * a remote phy. */ - enum SCIC_SDS_PHY_PROTOCOL protocol; + enum scic_sds_phy_protocol protocol; /** * This field specifies the index with which this phy is associated (0-3). diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 0a95f649c04f..88b892de5de4 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -620,15 +620,12 @@ enum sci_status scic_port_get_properties( } /** - * scic_port_hard_reset() - This method will request the SCI implementation to - * perform a HARD RESET on the SAS Port. If/When the HARD RESET completes - * the SCI user will be notified via an SCI OS callback indicating a direct - * attached device was found. + * scic_port_hard_reset() - perform port hard reset * @port: a handle corresponding to the SAS port to be hard reset. * @reset_timeout: This parameter specifies the number of milliseconds in which * the port reset operation should complete. * - * The SCI User callback in SCIC_USER_CALLBACKS_T will only be called once for + * The SCI User callback in scic_user_callbacks_t will only be called once for * each phy in the SAS Port at completion of the hard reset sequence. Return a * status indicating whether the hard reset started successfully. SCI_SUCCESS * This value is returned if the hard reset operation started successfully. diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 8167f5e3be3d..a5aa9e102242 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -84,21 +84,23 @@ * This enumeration depicts all of the states for the core port ready substate * machine. */ -enum SCIC_SDS_PORT_READY_SUBSTATES { +enum scic_sds_port_ready_substates { /** - * The substate where the port is started and ready but has no active phys. + * The substate where the port is started and ready but has no + * active phys. */ SCIC_SDS_PORT_READY_SUBSTATE_WAITING, /** - * The substate where the port is started and ready and there is at least one - * phy operational. + * The substate where the port is started and ready and there is + * at least one phy operational. */ SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, /** - * The substate where the port is started and there was an add/remove phy - * event. This state is only used in Automatic Port Configuration Mode (APC) + * The substate where the port is started and there was an + * add/remove phy event. This state is only used in Automatic + * Port Configuration Mode (APC) */ SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, @@ -122,9 +124,9 @@ struct scic_sds_port { struct sci_base_port parent; /** - * This field is the port index that is reported to the SCI USER. This allows - * the actual hardware physical port to change without the SCI USER getting a - * different answer for the get port index. + * This field is the port index that is reported to the SCI USER. + * This allows the actual hardware physical port to change without + * the SCI USER getting a different answer for the get port index. */ u8 logical_port_index; @@ -134,9 +136,9 @@ struct scic_sds_port { u8 physical_port_index; /** - * This field contains the active phy mask for the port. This mask is used in - * conjunction with the phy state to determine which phy to select for some - * port operations. + * This field contains the active phy mask for the port. + * This mask is used in conjunction with the phy state to determine + * which phy to select for some port operations. */ u8 active_phy_mask; @@ -150,8 +152,8 @@ struct scic_sds_port { u32 started_request_count; /** - * This field contains the number of devices assigned to this port. It is - * used to control port start requests. + * This field contains the number of devices assigned to this port. + * It is used to control port start requests. */ u32 assigned_device_count; @@ -167,7 +169,8 @@ struct scic_sds_port { struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; /** - * This field is a pointer back to the controller that owns this port object. + * This field is a pointer back to the controller that owns this + * port object. */ struct scic_sds_controller *owning_controller; @@ -178,8 +181,8 @@ struct scic_sds_port { /** * This field points to the current set of state handlers for this port - * object. These state handlers are assigned at each enter state of the state - * machine. + * object. These state handlers are assigned at each enter state of + * the state machine. */ struct scic_sds_port_state_handler *state_handlers; @@ -191,17 +194,18 @@ struct scic_sds_port { /* / Memory mapped hardware register space */ /** - * This field is the pointer to the port task scheduler registers for the SCU - * hardware. + * This field is the pointer to the port task scheduler registers + * for the SCU hardware. */ - struct scu_port_task_scheduler_registers __iomem *port_task_scheduler_registers; + struct scu_port_task_scheduler_registers __iomem + *port_task_scheduler_registers; /** - * This field is identical for all port objects and points to the port task - * scheduler group PE configuration registers. It is used to assign PEs to a - * port. + * This field is identical for all port objects and points to the port + * task scheduler group PE configuration registers. + * It is used to assign PEs to a port. */ - SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register; + u32 *port_pe_configuration_register; /** * This field is the VIIT register space for ths port object. @@ -211,13 +215,13 @@ struct scic_sds_port { }; -typedef enum sci_status (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct scic_sds_port *, u32); +typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32); -typedef enum sci_status (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct scic_sds_port *, u32); +typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, u32); -typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct scic_sds_port *, struct scic_sds_phy *); +typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *); -typedef enum sci_status (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)( +typedef enum sci_status (*scic_sds_port_io_request_handler_t)( struct scic_sds_port *, struct scic_sds_remote_device *, struct scic_sds_request *); @@ -225,14 +229,14 @@ typedef enum sci_status (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)( struct scic_sds_port_state_handler { struct sci_base_port_state_handler parent; - SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler; - SCIC_SDS_PORT_EVENT_HANDLER_T event_handler; + scic_sds_port_frame_handler_t frame_handler; + scic_sds_port_event_handler_t event_handler; - SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler; - SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler; + scic_sds_port_link_handler_t link_up_handler; + scic_sds_port_link_handler_t link_down_handler; - SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler; - SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler; + scic_sds_port_io_request_handler_t start_io_handler; + scic_sds_port_io_request_handler_t complete_io_handler; }; diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index d2d3f5293b2c..22703b372c64 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -820,7 +820,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize( struct scic_sds_port_configuration_agent *port_agent) { enum sci_status status = SCI_SUCCESS; - enum SCIC_PORT_CONFIGURATION_MODE mode; + enum scic_port_configuration_mode mode; struct isci_host *ihost = sci_object_get_association(scic); mode = scic->oem_parameters.sds1.controller.mode_type; diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h index 4146735ffc32..56a40a712589 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h @@ -71,7 +71,7 @@ struct scic_sds_port_configuration_agent; struct scic_sds_port; struct scic_sds_phy; -typedef void (*SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T)( +typedef void (*scic_sds_port_configuration_agent_phy_handler_t)( struct scic_sds_controller *, struct scic_sds_port_configuration_agent *, struct scic_sds_port *, @@ -91,8 +91,8 @@ struct scic_sds_port_configuration_agent { bool timer_pending; - SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_up_handler; - SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_down_handler; + scic_sds_port_configuration_agent_phy_handler_t link_up_handler; + scic_sds_port_configuration_agent_phy_handler_t link_down_handler; void *timer; diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h index eccad55ea571..e21abe2c6523 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.h +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h @@ -213,7 +213,7 @@ enum scis_sds_remote_node_context_states { * This enumeration is used to define the end destination state for the remote * node context. */ -enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE { +enum scic_sds_remote_node_context_destination_state { SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED, SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY, SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL @@ -257,7 +257,7 @@ struct scic_sds_remote_node_context { * state. This can cause an automatic resume on receiving a suspension * notification. */ - enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE destination_state; + enum scic_sds_remote_node_context_destination_state destination_state; /** * This field contains the callback function that the user requested to be diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index c54d8ef79ed8..286b74943d68 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -74,7 +74,7 @@ struct scic_sds_remote_device; struct scic_sds_io_request_state_handler; /** - * enum _SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATES - This enumeration + * enum _scic_sds_io_request_started_task_mgmt_substates - This enumeration * depicts all of the substates for a task management request to be * performed in the STARTED super-state. * @@ -98,7 +98,7 @@ enum scic_sds_raw_request_started_task_mgmt_substates { /** - * enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES - This enumeration depicts all + * enum _scic_sds_smp_request_started_substates - This enumeration depicts all * of the substates for a SMP request to be performed in the STARTED * super-state. * @@ -120,7 +120,7 @@ enum scic_sds_smp_request_started_substates { }; /** - * struct SCIC_SDS_IO_REQUEST - This structure contains or references all of + * struct scic_sds_request - This structure contains or references all of * the data necessary to process a task management or normal IO request. * * @@ -328,7 +328,7 @@ extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substat * scic_sds_io_request_tc_completion() - * * This macro invokes the core state task completion handler for the - * SCIC_SDS_IO_REQUEST_T object. + * struct scic_sds_io_request object. */ #define scic_sds_io_request_tc_completion(this_request, completion_code) \ { \ diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c index 97dc9bfa7b9c..9635b37fad16 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c @@ -146,7 +146,7 @@ void scu_stp_packet_request_command_phase_construct_task_context( } /* sata header */ - memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT)); + memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context)); task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; /* @@ -213,7 +213,7 @@ void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); - memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT)); + memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context)); task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; /* diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h index 2a7aec922dee..eebfff32216b 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h @@ -70,7 +70,7 @@ * * This is the enumeration of the SATA PIO DATA IN started substate machine. */ -enum _SCIC_SDS_STP_PACKET_REQUEST_STARTED_SUBSTATES { +enum _scic_sds_stp_packet_request_started_substates { /** * While in this state the IO request object is waiting for the TC completion * notification for the H2D Register FIS diff --git a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h index d4dc118f2deb..d0ae5909aee2 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h @@ -72,7 +72,7 @@ * * This is the enumeration of the SATA PIO DATA IN started substate machine. */ -enum _SCIC_SDS_STP_REQUEST_STARTED_PIO_SUBSTATES { +enum _scic_sds_stp_request_started_pio_substates { /** * While in this state the IO request object is waiting for the TC completion * notification for the H2D Register FIS diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index 107487978f06..cb4d2d626639 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -134,36 +134,36 @@ struct scic_sds_stp_request { }; /** - * enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES - This enumeration depicts + * enum scic_sds_stp_request_started_udma_substates - This enumeration depicts * the various sub-states associated with a SATA/STP UDMA protocol operation. * * */ -enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES { +enum scic_sds_stp_request_started_udma_substates { SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, }; /** - * enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES - This enumeration + * enum scic_sds_stp_request_started_non_data_substates - This enumeration * depicts the various sub-states associated with a SATA/STP non-data * protocol operation. * * */ -enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES { +enum scic_sds_stp_request_started_non_data_substates { SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, }; /** - * enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES - THis enumeration + * enum scic_sds_stp_request_started_soft_reset_substates - THis enumeration * depicts the various sub-states associated with a SATA/STP soft reset * operation. * * */ -enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES { +enum scic_sds_stp_request_started_soft_reset_substates { SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h index 49db83faac37..a0204aa7128a 100644 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h @@ -69,13 +69,13 @@ #include "sci_status.h" /** - * enum UNSOLICITED_FRAME_STATE - + * enum unsolicited_frame_state - * * This enumeration represents the current unsolicited frame state. The * controller object can not updtate the hardware unsolicited frame put pointer * unless it has already processed the priror unsolicited frames. */ -enum UNSOLICITED_FRAME_STATE { +enum unsolicited_frame_state { /** * This state is when the frame is empty and not in use. It is * different from the released state in that the hardware could DMA @@ -110,7 +110,7 @@ struct scic_sds_unsolicited_frame { /** * This field contains the current frame state */ - enum UNSOLICITED_FRAME_STATE state; + enum unsolicited_frame_state state; /** * This field points to the frame header data. diff --git a/drivers/scsi/isci/core/scu_registers.h b/drivers/scsi/isci/core/scu_registers.h index 05a141181844..12f2bacc9c09 100644 --- a/drivers/scsi/isci/core/scu_registers.h +++ b/drivers/scsi/isci/core/scu_registers.h @@ -1423,7 +1423,7 @@ struct scu_sgpio_registers { * ***************************************************************************** */ #define SCU_VIIT_BASE 0x1c00 -struct SCU_VIIT_REGISTERS { +struct scu_viit_registers { u32 registers[256]; }; @@ -1463,8 +1463,6 @@ struct scu_port_task_scheduler_registers { u32 status; }; -typedef u32 SCU_PORT_PE_CONFIGURATION_REGISTER_T; - /** * struct scu_port_task_scheduler_group_registers - These are the PORT Task * Scheduler registers @@ -1495,7 +1493,7 @@ struct scu_port_task_scheduler_group_registers { * 0x0034 PCSPE1CR * 0x0038 PCSPE2CR * 0x003C PCSPE3CR */ - SCU_PORT_PE_CONFIGURATION_REGISTER_T protocol_engine[4]; + u32 protocol_engine[4]; /* 0x0040 ETMTSCCR */ u32 tc_scanning_interval_control; /* 0x0044 ETMRNSCCR */ @@ -1684,12 +1682,12 @@ struct scu_afe_registers { u32 reserved_0c00_0ffc[0x0100]; }; -struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS { +struct scu_protocol_engine_group_registers { u32 table[0xE0]; }; -struct SCU_VIIT_IIT { +struct scu_viit_iit { u32 table[256]; }; @@ -1699,7 +1697,7 @@ struct SCU_VIIT_IIT { * * */ -struct SCU_ZONE_PARTITION_TABLE { +struct scu_zone_partition_table { u32 table[2048]; }; @@ -1709,7 +1707,7 @@ struct SCU_ZONE_PARTITION_TABLE { * * */ -struct SCU_COMPLETION_RAM { +struct scu_completion_ram { u32 ram[128]; }; @@ -1719,19 +1717,19 @@ struct SCU_COMPLETION_RAM { * * */ -struct SCU_FRAME_BUFFER_RAM { +struct scu_frame_buffer_ram { u32 ram[128]; }; -#define SCU_SCRATCH_RAM_SIZE_IN_DWORDS 256 +#define scu_scratch_ram_SIZE_IN_DWORDS 256 /** * Placeholder for the scratch RAM registers. * * */ -struct SCU_SCRATCH_RAM { - u32 ram[SCU_SCRATCH_RAM_SIZE_IN_DWORDS]; +struct scu_scratch_ram { + u32 ram[scu_scratch_ram_SIZE_IN_DWORDS]; }; /** @@ -1739,7 +1737,7 @@ struct SCU_SCRATCH_RAM { * * */ -struct NOA_PROTOCOL_ENGINE_PARTITION { +struct noa_protocol_engine_partition { u32 reserved[64]; }; @@ -1748,7 +1746,7 @@ struct NOA_PROTOCOL_ENGINE_PARTITION { * * */ -struct NOA_HUB_PARTITION { +struct noa_hub_partition { u32 reserved[64]; }; @@ -1757,38 +1755,38 @@ struct NOA_HUB_PARTITION { * * */ -struct NOA_HOST_INTERFACE_PARTITION { +struct noa_host_interface_partition { u32 reserved[64]; }; /** - * struct TRANSPORT_LINK_LAYER_PAIR - The SCU Hardware pairs up the TL + * struct transport_link_layer_pair - The SCU Hardware pairs up the TL * registers with the LL registers so we must place them adjcent to make the * array of registers in the PEG. * * */ -struct TRANSPORT_LINK_LAYER_PAIR { +struct transport_link_layer_pair { struct scu_transport_layer_registers tl; struct scu_link_layer_registers ll; }; /** - * struct SCU_PEG_REGISTERS - SCU Protocol Engine Memory mapped register space. + * struct scu_peg_registers - SCU Protocol Engine Memory mapped register space. * These registers are unique to each protocol engine group. There can be * at most two PEG for a single SCU part. * * */ -struct SCU_PEG_REGISTERS { - struct TRANSPORT_LINK_LAYER_PAIR pe[4]; +struct scu_peg_registers { + struct transport_link_layer_pair pe[4]; struct scu_port_task_scheduler_group_registers ptsg; - struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS peg; + struct scu_protocol_engine_group_registers peg; struct scu_sgpio_registers sgpio; u32 reserved_01500_1BFF[0x1C0]; struct scu_viit_entry viit[64]; - struct SCU_ZONE_PARTITION_TABLE zpt0; - struct SCU_ZONE_PARTITION_TABLE zpt1; + struct scu_zone_partition_table zpt0; + struct scu_zone_partition_table zpt1; }; /** @@ -1800,20 +1798,20 @@ struct SCU_PEG_REGISTERS { */ struct scu_registers { /* 0x0000 - PEG 0 */ - struct SCU_PEG_REGISTERS peg0; + struct scu_peg_registers peg0; /* 0x6000 - SDMA and Miscellaneous */ struct scu_sdma_registers sdma; - struct SCU_COMPLETION_RAM cram; - struct SCU_FRAME_BUFFER_RAM fbram; + struct scu_completion_ram cram; + struct scu_frame_buffer_ram fbram; u32 reserved_6800_69FF[0x80]; - struct NOA_PROTOCOL_ENGINE_PARTITION noa_pe; - struct NOA_HUB_PARTITION noa_hub; - struct NOA_HOST_INTERFACE_PARTITION noa_if; + struct noa_protocol_engine_partition noa_pe; + struct noa_hub_partition noa_hub; + struct noa_host_interface_partition noa_if; u32 reserved_6d00_7fff[0x4c0]; /* 0x8000 - PEG 1 */ - struct SCU_PEG_REGISTERS peg1; + struct scu_peg_registers peg1; /* 0xE000 - AFE Registers */ struct scu_afe_registers afe; @@ -1822,9 +1820,7 @@ struct scu_registers { u32 reserved_f000_211fff[0x80c00]; /* 0x212000 - scratch RAM */ - struct SCU_SCRATCH_RAM scratch_ram; - + struct scu_scratch_ram scratch_ram; }; - #endif /* _SCU_REGISTERS_HEADER_ */ diff --git a/drivers/scsi/isci/core/scu_task_context.h b/drivers/scsi/isci/core/scu_task_context.h index 818a575298d3..7df87d923285 100644 --- a/drivers/scsi/isci/core/scu_task_context.h +++ b/drivers/scsi/isci/core/scu_task_context.h @@ -65,7 +65,7 @@ /** - * enum SCU_SSP_TASK_TYPE - This enumberation defines the various SSP task + * enum scu_ssp_task_type - This enumberation defines the various SSP task * types the SCU hardware will accept. The definition for the various task * types the SCU hardware will accept can be found in the DS specification. * @@ -78,10 +78,10 @@ typedef enum { SCU_TASK_TYPE_RESPONSE, /* /< Driver generated response frame (targt mode) */ SCU_TASK_TYPE_RAW_FRAME, /* /< Raw frame request type */ SCU_TASK_TYPE_PRIMITIVE /* /< Request for a primitive to be transmitted */ -} SCU_SSP_TASK_TYPE; +} scu_ssp_task_type; /** - * enum SCU_SATA_TASK_TYPE - This enumeration defines the various SATA task + * enum scu_sata_task_type - This enumeration defines the various SATA task * types the SCU hardware will accept. The definition for the various task * types the SCU hardware will accept can be found in the DS specification. * @@ -99,7 +99,7 @@ typedef enum { SCU_TASK_TYPE_DMA_OUT, /* /< Write request */ SCU_TASK_TYPE_FPDMAQ_WRITE, /* /< NCQ write Request */ SCU_TASK_TYPE_PACKET_DMA_OUT /* /< Packet write request */ -} SCU_SATA_TASK_TYPE; +} scu_sata_task_type; /** @@ -290,12 +290,12 @@ typedef enum { #define SCU_TASK_CONTEXT_PROTOCOL_NONE 0x07 /** - * struct SSP_TASK_CONTEXT - This is the SCU hardware definition for an SSP + * struct ssp_task_context - This is the SCU hardware definition for an SSP * request. * * */ -struct SSP_TASK_CONTEXT { +struct ssp_task_context { /* OFFSET 0x18 */ u32 reserved00:24; u32 frame_type:8; @@ -324,12 +324,12 @@ struct SSP_TASK_CONTEXT { }; /** - * struct STP_TASK_CONTEXT - This is the SCU hardware definition for an STP + * struct stp_task_context - This is the SCU hardware definition for an STP * request. * * */ -struct STP_TASK_CONTEXT { +struct stp_task_context { /* OFFSET 0x18 */ u32 fis_type:8; u32 pm_port:4; @@ -356,12 +356,12 @@ struct STP_TASK_CONTEXT { }; /** - * struct SMP_TASK_CONTEXT - This is the SCU hardware definition for an SMP + * struct smp_task_context - This is the SCU hardware definition for an SMP * request. * * */ -struct SMP_TASK_CONTEXT { +struct smp_task_context { /* OFFSET 0x18 */ u32 response_length:8; u32 function_result:8; @@ -386,12 +386,12 @@ struct SMP_TASK_CONTEXT { }; /** - * struct PRIMITIVE_TASK_CONTEXT - This is the SCU hardware definition used + * struct primitive_task_context - This is the SCU hardware definition used * when the driver wants to send a primitive on the link. * * */ -struct PRIMITIVE_TASK_CONTEXT { +struct primitive_task_context { /* OFFSET 0x18 */ /** * This field is the control word and it must be 0. @@ -421,13 +421,13 @@ struct PRIMITIVE_TASK_CONTEXT { * The union of the protocols that can be selected in the SCU task context * field. * - * PROTOCOL_CONTEXT + * protocol_context */ -union PROTOCOL_CONTEXT { - struct SSP_TASK_CONTEXT ssp; - struct STP_TASK_CONTEXT stp; - struct SMP_TASK_CONTEXT smp; - struct PRIMITIVE_TASK_CONTEXT primitive; +union protocol_context { + struct ssp_task_context ssp; + struct stp_task_context stp; + struct smp_task_context smp; + struct primitive_task_context primitive; u32 words[6]; }; @@ -502,13 +502,13 @@ struct scu_sgl_element_pair { }; /** - * struct TRANSPORT_SNAPSHOT - This structure is the SCU hardware scratch area + * struct transport_snapshot - This structure is the SCU hardware scratch area * for the task context. This is set to 0 by the driver but can be read by * issuing a dump TC request to the SCU. * * */ -struct TRANSPORT_SNAPSHOT { +struct transport_snapshot { /* OFFSET 0x48 */ u32 xfer_rdy_write_data_length; @@ -639,7 +639,7 @@ struct scu_task_context { /** * This field is programmed with one of the following command type codes * - * For SAS requests use the SCU_SSP_TASK_TYPE + * For SAS requests use the scu_ssp_task_type * - SCU_TASK_TYPE_IOREAD * - SCU_TASK_TYPE_IOWRITE * - SCU_TASK_TYPE_SMP_REQUEST @@ -647,7 +647,7 @@ struct scu_task_context { * - SCU_TASK_TYPE_RAW_FRAME * - SCU_TASK_TYPE_PRIMITIVE * - * For SATA requests use the SCU_SATA_TASK_TYPE + * For SATA requests use the scu_sata_task_type * - SCU_TASK_TYPE_DMA_IN * - SCU_TASK_TYPE_FPDMAQ_READ * - SCU_TASK_TYPE_PACKET_DMA_IN @@ -787,7 +787,7 @@ struct scu_task_context { /** * This union provides for the protocol specif part of the SCU Task Context. */ - union PROTOCOL_CONTEXT type; + union protocol_context type; /* OFFSET 0x30-0x34 */ /** @@ -863,7 +863,7 @@ struct scu_task_context { u32 write_data_length; /* read only set to 0 */ /* OFFSET 0x48-0x58 */ - struct TRANSPORT_SNAPSHOT snapshot; /* read only set to 0 */ + struct transport_snapshot snapshot; /* read only set to 0 */ /* OFFSET 0x5C */ u32 block_protection_enable:1; diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index c2162cf12056..f07935844bbd 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -111,7 +111,7 @@ struct isci_oem_hdr { * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs * being assigned is sufficient to declare manual PORT configuration. */ -enum SCIC_PORT_CONFIGURATION_MODE { +enum scic_port_configuration_mode { SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0, SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1 }; -- cgit v1.2.3 From f219f010a355487638bf2fff4724a420e7158fd2 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 31 Mar 2011 13:10:34 -0700 Subject: isci: Properly handle requests in the "aborting" state. When a TMF times-out, the request is set back to "aborting". Requests in the "aborting" state must be terminated when LUN and device resets occur. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.h | 2 +- drivers/scsi/isci/task.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 4a63bb6de44e..0c08da6bcd8a 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -199,7 +199,7 @@ static inline enum isci_request_status isci_request_change_started_to_newstate( old_state = isci_request->status; - if (old_state == started) { + if (old_state == started || old_state == aborting) { BUG_ON(isci_request->io_request_completion != NULL); isci_request->io_request_completion = completion_ptr; diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 7e9668402559..338f08ec4d8e 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -903,7 +903,9 @@ static void isci_terminate_request( new_request_state ); - if ((old_state == started) || (old_state == completed)) { + if ((old_state == started) || + (old_state == completed) || + (old_state == aborting)) { /* If the old_state is started: * This request was not already being aborted. If it had been, @@ -920,6 +922,10 @@ static void isci_terminate_request( * This request completed from the SCU hardware perspective * and now just needs cleaning up in terms of freeing the * request and potentially calling up to libsas. + * + * If old_state == aborting: + * This request has already gone through a TMF timeout, but may + * not have been terminated; needs cleaning up at least. */ isci_terminate_request_core(isci_host, isci_device, isci_request); @@ -1297,14 +1303,16 @@ int isci_task_abort_task(struct sas_task *task) spin_lock_irqsave(&isci_host->scic_lock, flags); - /* Check the request status and change to "aborting" if currently + /* Check the request status and change to "aborted" if currently * "starting"; if true then set the I/O kernel completion * struct that will be triggered when the request completes. */ old_state = isci_task_validate_request_to_abort( old_request, isci_host, isci_device, &aborted_io_completion); - if ((old_state != started) && (old_state != completed)) { + if ((old_state != started) && + (old_state != completed) && + (old_state != aborting)) { spin_unlock_irqrestore(&isci_host->scic_lock, flags); -- cgit v1.2.3 From ce4f75def3999fbe454da9aa733ed322bc671b06 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 31 Mar 2011 13:10:36 -0700 Subject: isci: Free host lock for SATA/STP abort escalation at submission time. In the case of I/O requests that fail at submit time because of a pending reset condition, the host lock for SATA/STP devices must be managed for any SCSI-initiated I/O before sas_task_abort is called. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 60 ++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c6ce9d0c50c2..946caaeb66c6 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "isci.h" #include "scic_remote_device.h" #include "scic_io_request.h" @@ -355,33 +356,6 @@ int isci_request_alloc_tmf( return retval; } -/** - * isci_request_signal_device_reset() - This function will set the "device - * needs target reset" flag in the given sas_tasks' task_state_flags, and - * then cause the task to be added into the SCSI error handler queue which - * will eventually be escalated to a target reset. - * - * - */ -static void isci_request_signal_device_reset( - struct isci_request *isci_request) -{ - unsigned long flags; - struct sas_task *task = isci_request_access_task(isci_request); - - dev_dbg(&isci_request->isci_host->pdev->dev, - "%s: request=%p, task=%p\n", __func__, isci_request, task); - - spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; - spin_unlock_irqrestore(&task->task_state_lock, flags); - - /* Cause this task to be scheduled in the SCSI error handler - * thread. - */ - sas_task_abort(task); -} - /** * isci_request_execute() - This function allocates the isci_request object, * all fills in some common fields. @@ -453,11 +427,18 @@ int isci_request_execute( /* Save the tag for possible task mgmt later. */ request->io_tag = scic_io_request_get_io_tag( request->sci_request_handle); + } else { + /* The request did not really start in the + * hardware, so clear the request handle + * here so no terminations will be done. + */ + request->sci_request_handle = NULL; } + } else dev_warn(&isci_host->pdev->dev, - "%s: failed request start\n", - __func__); + "%s: failed request start (0x%x)\n", + __func__, status); spin_unlock_irqrestore(&isci_host->scic_lock, flags); @@ -467,7 +448,26 @@ int isci_request_execute( * handler thread to work on this I/O and that * we want a device reset. */ - isci_request_signal_device_reset(request); + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + /* Cause this task to be scheduled in the SCSI error handler + * thread. + */ + if (dev_is_sata(task->dev)) { + /* Since we are still in the submit path, and since + * libsas takes the host lock on behalf of SATA + * devices before I/O starts, we need to unlock + * before we can put the task in the error path. + */ + raw_local_irq_save(flags); + spin_unlock(isci_host->shost->host_lock); + sas_task_abort(task); + spin_lock(isci_host->shost->host_lock); + raw_local_irq_restore(flags); + } else + sas_task_abort(task); /* Change the status, since we are holding * the I/O until it is managed by the SCSI -- cgit v1.2.3 From 26e953bc6ec11c9e81ad8e9a59b14cf260776007 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 31 Mar 2011 13:10:38 -0700 Subject: isci: Fix use of SATA soft reset state machine. The driver SATA LUN reset function incorrectly sent an SRST deassert FIS, which is unnecessary because the core initiates the entire SATA soft reset state machine from the assert request. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/sata.c | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 7a1b58600ca0..794ab7ca9f1a 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -301,8 +301,8 @@ int isci_task_send_lu_reset_sata( int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; - /* Send the initial SRST to the target */ - #define ISCI_SRST_TIMEOUT_MS 20 /* 20 ms timeout. */ + /* Send the soft reset to the target */ + #define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */ isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_high, NULL, NULL ); @@ -319,38 +319,6 @@ int isci_task_send_lu_reset_sata( /* Return the failure so that the LUN reset is escalated * to a target reset. */ - goto out; } - - /* Leave SRST high for a bit. */ - #define ISCI_SRST_ASSERT_DELAY 100 /* usecs */ - udelay(ISCI_SRST_ASSERT_DELAY); - - /* Deassert SRST. */ - isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_low, - NULL, NULL - ); - ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS); - - if (ret == TMF_RESP_FUNC_COMPLETE) - dev_dbg(&isci_host->pdev->dev, - "%s: SATA LUN reset passed (%p)\n", - __func__, - isci_device); - else - dev_warn(&isci_host->pdev->dev, - "%s: Deassert SRST failed (%p)=%x\n", - __func__, - isci_device, - ret); - - out: - spin_lock_irqsave(&isci_host->scic_lock, flags); - - /* Resume the device. */ - scic_sds_remote_device_resume(to_sci_dev(isci_device)); - - spin_unlock_irqrestore(&isci_host->scic_lock, flags); - return ret; } -- cgit v1.2.3 From ed8a72d108bd951909b28fa4a89aad6489f414e1 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 31 Mar 2011 13:10:40 -0700 Subject: isci: Qualify when the host lock is managed for STP/SATA callbacks. In the case of internal discovery related STP/SATA I/O started through sas_execute_task the host lock is not taken by libsas before calling lldd_execute_task, so the lock should not be managed before calling back to libsas through task->task_done or sas_task_abort. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 20 ++++---------------- drivers/scsi/isci/sata.c | 1 - drivers/scsi/isci/task.c | 29 +++++++++-------------------- drivers/scsi/isci/task.h | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 946caaeb66c6..b519373597a5 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -53,7 +53,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include "isci.h" #include "scic_remote_device.h" #include "scic_io_request.h" @@ -452,22 +451,11 @@ int isci_request_execute( task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; spin_unlock_irqrestore(&task->task_state_lock, flags); - /* Cause this task to be scheduled in the SCSI error handler - * thread. + /* Cause this task to be scheduled in the SCSI error + * handler thread. */ - if (dev_is_sata(task->dev)) { - /* Since we are still in the submit path, and since - * libsas takes the host lock on behalf of SATA - * devices before I/O starts, we need to unlock - * before we can put the task in the error path. - */ - raw_local_irq_save(flags); - spin_unlock(isci_host->shost->host_lock); - sas_task_abort(task); - spin_lock(isci_host->shost->host_lock); - raw_local_irq_restore(flags); - } else - sas_task_abort(task); + isci_execpath_callback(isci_host, task, + sas_task_abort); /* Change the status, since we are holding * the I/O until it is managed by the SCSI diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 794ab7ca9f1a..c941d9090b8d 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -299,7 +299,6 @@ int isci_task_send_lu_reset_sata( { struct isci_tmf tmf; int ret = TMF_RESP_FUNC_FAILED; - unsigned long flags; /* Send the soft reset to the target */ #define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */ diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 338f08ec4d8e..5bcea60fd8c4 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -55,7 +55,6 @@ #include #include -#include #include "scic_task_request.h" #include "scic_remote_device.h" #include "scic_io_request.h" @@ -93,26 +92,13 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, case isci_perform_normal_io_completion: /* Normal notification (task_done) */ dev_dbg(&ihost->pdev->dev, - "%s: Normal - task = %p, response=%d, status=%d\n", + "%s: Normal - task = %p, response=%d, " + "status=%d\n", __func__, task, response, status); task->lldd_task = NULL; - if (dev_is_sata(task->dev)) { - /* Since we are still in the submit path, and since - * libsas takes the host lock on behalf of SATA - * devices before I/O starts, we need to unlock - * before we can call back and report the I/O - * submission error. - */ - unsigned long flags; - raw_local_irq_save(flags); - spin_unlock(ihost->shost->host_lock); - task->task_done(task); - spin_lock(ihost->shost->host_lock); - raw_local_irq_restore(flags); - } else - task->task_done(task); + isci_execpath_callback(ihost, task, task->task_done); break; case isci_perform_aborted_io_completion: @@ -120,16 +106,19 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, * abort path. */ dev_warn(&ihost->pdev->dev, - "%s: Aborted - task = %p, response=%d, status=%d\n", + "%s: Aborted - task = %p, response=%d, " + "status=%d\n", __func__, task, response, status); break; case isci_perform_error_io_completion: /* Use sas_task_abort */ dev_warn(&ihost->pdev->dev, - "%s: Error - task = %p, response=%d, status=%d\n", + "%s: Error - task = %p, response=%d, " + "status=%d\n", __func__, task, response, status); - sas_task_abort(task); + + isci_execpath_callback(ihost, task, sas_task_abort); break; default: diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index d7cb6fe268c4..c5afd1cfbde7 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -56,6 +56,8 @@ #if !defined(_ISCI_TASK_H_) #define _ISCI_TASK_H_ +#include + struct isci_request; struct isci_host; @@ -332,5 +334,40 @@ isci_task_set_completion_status( return task_notification_selection; } +/** +* isci_execpath_callback() - This function is called from the task +* execute path when the task needs to callback libsas about the submit-time +* task failure. The callback occurs either through the task's done function +* or through sas_task_abort. In the case of regular non-discovery SATA/STP I/O +* requests, libsas takes the host lock before calling execute task. Therefore +* in this situation the host lock must be managed before calling the func. +* +* @ihost: This parameter is the controller to which the I/O request was sent. +* @task: This parameter is the I/O request. +* @func: This parameter is the function to call in the correct context. +* @status: This parameter is the status code for the completed task. +* +*/ +static inline void isci_execpath_callback( + struct isci_host *ihost, + struct sas_task *task, + void (*func)(struct sas_task *)) +{ + unsigned long flags; + + if (dev_is_sata(task->dev) && task->uldd_task) { + /* Since we are still in the submit path, and since + * libsas takes the host lock on behalf of SATA + * devices before I/O starts (in the non-discovery case), + * we need to unlock before we can call the callback function. + */ + raw_local_irq_save(flags); + spin_unlock(ihost->shost->host_lock); + func(task); + spin_lock(ihost->shost->host_lock); + raw_local_irq_restore(flags); + } else + func(task); +} #endif /* !defined(_SCI_TASK_H_) */ -- cgit v1.2.3 From 037afc7812e2b202fbc18218e6c0eff34dad36ed Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 31 Mar 2011 13:10:42 -0700 Subject: isci: cleanup isci_remote_device[_not]_ready interface Require a valid isci_host in support of the general cleanup to not re-lookup the host via potentially fragile methods when more robust methods are available. Also cleans up some more casting that should be using container_of() to up-cast a base structure in a more type-safe manner. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_remote_device.c | 54 +++++------ .../scsi/isci/core/scic_sds_smp_remote_device.c | 46 +++++----- .../scsi/isci/core/scic_sds_stp_remote_device.c | 101 +++++++-------------- drivers/scsi/isci/remote_device.c | 22 ++--- drivers/scsi/isci/remote_device.h | 9 +- 5 files changed, 92 insertions(+), 140 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index e100fdeee031..a6bcaa15fbf4 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1513,24 +1513,19 @@ static void scic_sds_remote_device_stopped_state_enter( * sets the starting state handlers, sets the device not ready, and posts the * remote node context to the hardware. none */ -static void scic_sds_remote_device_starting_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_device_starting_state_enter(struct sci_base_object *object) { - struct scic_sds_controller *scic; - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); - scic = scic_sds_remote_device_get_controller(sci_dev); - - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STARTING); + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STARTING); - isci_remote_device_not_ready( - idev, - SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); + isci_remote_device_not_ready(ihost, idev, + SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); } static void scic_sds_remote_device_starting_state_exit(struct sci_base_object *object) @@ -1556,14 +1551,13 @@ static void scic_sds_remote_device_starting_state_exit(struct sci_base_object *o * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets * the ready state handlers, and starts the ready substate machine. none */ -static void scic_sds_remote_device_ready_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_device_ready_state_enter(struct sci_base_object *object) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); - struct scic_sds_controller *scic - = scic_sds_remote_device_get_controller(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, @@ -1574,7 +1568,7 @@ static void scic_sds_remote_device_ready_state_enter( if (sci_dev->has_ready_substate_machine) sci_base_state_machine_start(&sci_dev->ready_substate_machine); else - isci_remote_device_ready(idev); + isci_remote_device_ready(ihost, idev); } /** @@ -1588,16 +1582,18 @@ static void scic_sds_remote_device_ready_state_enter( static void scic_sds_remote_device_ready_state_exit( struct sci_base_object *object) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)object; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); if (sci_dev->has_ready_substate_machine) sci_base_state_machine_stop(&sci_dev->ready_substate_machine); - else - isci_remote_device_not_ready( - idev, - SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); + else { + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + isci_remote_device_not_ready(ihost, idev, + SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); + } } /** diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index 55202481e091..06cb93221b4c 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -253,20 +253,19 @@ static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_dev * This function sets the ready cmd substate handlers and reports the device as * ready. none */ -static inline void scic_sds_smp_remote_device_ready_idle_substate_enter( - struct sci_base_object *object) +static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_object *object) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); + SET_STATE_HANDLER(sci_dev, + scic_sds_smp_remote_device_ready_substate_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - SET_STATE_HANDLER( - sci_dev, - scic_sds_smp_remote_device_ready_substate_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - - isci_remote_device_ready(idev); + isci_remote_device_ready(ihost, idev); } /** @@ -281,20 +280,20 @@ static inline void scic_sds_smp_remote_device_ready_idle_substate_enter( static void scic_sds_smp_remote_device_ready_cmd_substate_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); BUG_ON(sci_dev->working_request == NULL); - SET_STATE_HANDLER( - sci_dev, - scic_sds_smp_remote_device_ready_substate_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + SET_STATE_HANDLER(sci_dev, + scic_sds_smp_remote_device_ready_substate_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - isci_remote_device_not_ready( - idev, - SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); + isci_remote_device_not_ready(ihost, idev, + SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); } /** @@ -304,12 +303,11 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter( * * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none */ -static void scic_sds_smp_remote_device_ready_cmd_substate_exit( - struct sci_base_object *object) +static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; - - this_device->working_request = NULL; + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + sci_dev->working_request = NULL; } /* --------------------------------------------------------------------------- */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index 193a95fa90e1..0a00a40bdbbe 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -677,13 +677,13 @@ static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_dev * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS * ***************************************************************************** */ -static inline void -scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( - void *user_cookie) +static void +scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *user_cookie) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)user_cookie; + struct scic_sds_remote_device *sci_dev = user_cookie; struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); /* * For NCQ operation we do not issue a @@ -692,7 +692,7 @@ scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( */ if (sci_dev->ready_substate_machine.previous_state_id != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) - isci_remote_device_ready(idev); + isci_remote_device_ready(ihost, idev); } /* @@ -737,87 +737,48 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter( } } -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY CMD SUBSTATE - * ***************************************************************************** */ - -/** - * - * @device: This is the SCI base object which is cast into a - * struct scic_sds_remote_device object. - * - */ -static inline void scic_sds_stp_remote_device_ready_cmd_substate_enter( - struct sci_base_object *device) +static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_object *object) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)device; + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); BUG_ON(sci_dev->working_request == NULL); - SET_STATE_HANDLER( - sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + SET_STATE_HANDLER(sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - isci_remote_device_not_ready( - idev, - SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); + isci_remote_device_not_ready(ihost, idev, + SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY NCQ SUBSTATE - * ***************************************************************************** */ - -/** - * - * @device: This is the SCI base object which is cast into a - * struct scic_sds_remote_device object. - * - */ -static void scic_sds_stp_remote_device_ready_ncq_substate_enter( - struct sci_base_object *device) +static void scic_sds_stp_remote_device_ready_ncq_substate_enter(struct sci_base_object *object) { - struct scic_sds_remote_device *this_device; - - this_device = (struct scic_sds_remote_device *)device; - - SET_STATE_HANDLER( - this_device, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ - ); + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + SET_STATE_HANDLER(sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); } -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE - * ***************************************************************************** */ - -/** - * - * @device: This is the SCI base object which is cast into a - * struct scic_sds_remote_device object. - * - */ -static inline void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( - struct sci_base_object *device) +static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_object *object) { - struct scic_sds_remote_device *sci_dev = - (struct scic_sds_remote_device *)device; + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent.parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); - SET_STATE_HANDLER( - sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + SET_STATE_HANDLER(sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); if (sci_dev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) - isci_remote_device_not_ready(idev, sci_dev->not_ready_reason); + isci_remote_device_not_ready(ihost, idev, sci_dev->not_ready_reason); } /* diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 6fe6815e4b74..0fdaa6d62c1b 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -281,13 +281,12 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) * isci_remote_device_ready() - This function is called by the scic when the * remote device is ready. We mark the isci device as ready and signal the * waiting proccess. - * @idev: This parameter specifies the remote device + * @ihost: our valid isci_host + * @idev: remote device * */ -void isci_remote_device_ready(struct isci_remote_device *idev) +void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev) { - struct isci_host *ihost = idev->isci_port->isci_host; - dev_dbg(&ihost->pdev->dev, "%s: idev = %p\n", __func__, idev); @@ -304,18 +303,17 @@ void isci_remote_device_ready(struct isci_remote_device *idev) * @isci_device: This parameter specifies the remote device * */ -void isci_remote_device_not_ready( - struct isci_remote_device *isci_device, - u32 reason_code) +void isci_remote_device_not_ready(struct isci_host *ihost, + struct isci_remote_device *idev, u32 reason) { - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); + dev_dbg(&ihost->pdev->dev, + "%s: isci_device = %p\n", __func__, idev); - if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) - isci_remote_device_change_state(isci_device, isci_stopping); + if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) + isci_remote_device_change_state(idev, isci_stopping); else /* device ready is actually a "not ready for io" state. */ - isci_remote_device_change_state(isci_device, isci_ready); + isci_remote_device_change_state(idev, isci_ready); } /** diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index f45a5f064fce..cf5302abb8b2 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -109,12 +109,11 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, void isci_remote_device_nuke_requests( struct isci_remote_device *isci_device); -void isci_remote_device_ready( - struct isci_remote_device *); +void isci_remote_device_ready(struct isci_host *ihost, + struct isci_remote_device *idev); -void isci_remote_device_not_ready( - struct isci_remote_device *, - u32); +void isci_remote_device_not_ready(struct isci_host *ihost, + struct isci_remote_device *idev, u32 reason); void isci_remote_device_gone( struct domain_device *domain_dev); -- cgit v1.2.3 From 4393aa4e6b9517a666f0ef6b774fd421a9dc4c68 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 31 Mar 2011 13:10:44 -0700 Subject: isci: fix fragile/conditional isci_host lookups A domain_device can always reference back to ->lldd_ha unlike local lldd structures. Fix up cases where the driver uses local objects to look up the isci_host. This also changes the calling conventions of some routines to expect a valid isci_host parameter rather than re-lookup the pointer on entry. Incidentally cleans up some macros that are longer to type than the open-coded equivalent: isci_host_from_sas_ha isci_dev_from_domain_dev Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 4 +- drivers/scsi/isci/host.h | 13 ++---- drivers/scsi/isci/phy.c | 2 +- drivers/scsi/isci/port.c | 68 +++++++++++------------------- drivers/scsi/isci/port.h | 5 +-- drivers/scsi/isci/remote_device.c | 70 ++++++++----------------------- drivers/scsi/isci/remote_device.h | 62 +++++++--------------------- drivers/scsi/isci/request.c | 2 +- drivers/scsi/isci/task.c | 87 ++++++++++++--------------------------- 9 files changed, 94 insertions(+), 219 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 79515be5f7c1..66449593aa8c 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -129,7 +129,7 @@ void isci_host_start_complete(struct isci_host *ihost, enum sci_status completio int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) { - struct isci_host *ihost = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); + struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha; if (test_bit(IHOST_START_PENDING, &ihost->flags)) return 0; @@ -149,7 +149,7 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) void isci_host_scan_start(struct Scsi_Host *shost) { - struct isci_host *ihost = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); + struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha; struct scic_sds_controller *scic = ihost->core_controller; unsigned long tmo = scic_controller_get_suggested_start_timeout(scic); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index d012b69d8d61..8372094ef5ad 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -233,15 +233,10 @@ static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_rem wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags)); } -/** - * isci_host_from_sas_ha() - This accessor retrieves the isci_host object - * reference from the Linux sas_ha_struct reference. - * @ha_struct,: This parameter points to the Linux sas_ha_struct object - * - * A reference to the associated isci_host structure. - */ -#define isci_host_from_sas_ha(ha_struct) \ - ((struct isci_host *)(ha_struct)->lldd_ha) +static inline struct isci_host *dev_to_ihost(struct domain_device *dev) +{ + return dev->port->ha->lldd_ha; +} /** * isci_host_scan_finished() - diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index decc0c05a3dd..9e081a4c8a3c 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -163,7 +163,7 @@ int isci_phy_control(struct asd_sas_phy *sas_phy, return -ENODEV; /* Perform the port reset. */ - ret = isci_port_perform_hard_reset(iport, iphy); + ret = isci_port_perform_hard_reset(ihost, iport, iphy); break; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 74dc96dc6b17..b675a94f4a73 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -400,55 +400,43 @@ void isci_port_hard_reset_complete(struct isci_port *isci_port, complete_all(&isci_port->hard_reset_complete); } -/** - * isci_port_perform_hard_reset() - This function is one of the SAS Domain - * Template functions. This is a phy management function. - * @isci_port: - * @isci_phy: - * - * status, TMF_RESP_FUNC_COMPLETE indicates success. - */ -int isci_port_perform_hard_reset( - struct isci_port *isci_port, - struct isci_phy *isci_phy) + +int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, + struct isci_phy *iphy) { + unsigned long flags; enum sci_status status; int ret = TMF_RESP_FUNC_COMPLETE; - unsigned long flags; + dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n", + __func__, iport); - dev_dbg(&isci_port->isci_host->pdev->dev, - "%s: isci_port = %p\n", - __func__, isci_port); - - BUG_ON(isci_port == NULL); - - init_completion(&isci_port->hard_reset_complete); + init_completion(&iport->hard_reset_complete); - spin_lock_irqsave(&isci_port->isci_host->scic_lock, flags); + spin_lock_irqsave(&ihost->scic_lock, flags); #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT - status = scic_port_hard_reset(isci_port->sci_port_handle, + status = scic_port_hard_reset(iport->sci_port_handle, ISCI_PORT_RESET_TIMEOUT); - spin_unlock_irqrestore(&isci_port->isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); if (status == SCI_SUCCESS) { - wait_for_completion(&isci_port->hard_reset_complete); + wait_for_completion(&iport->hard_reset_complete); - dev_dbg(&isci_port->isci_host->pdev->dev, - "%s: isci_port = %p; hard reset completion\n", - __func__, isci_port); + dev_dbg(&ihost->pdev->dev, + "%s: iport = %p; hard reset completion\n", + __func__, iport); - if (isci_port->hard_reset_status != SCI_SUCCESS) + if (iport->hard_reset_status != SCI_SUCCESS) ret = TMF_RESP_FUNC_FAILED; } else { ret = TMF_RESP_FUNC_FAILED; - dev_err(&isci_port->isci_host->pdev->dev, - "%s: isci_port = %p; scic_port_hard_reset call" + dev_err(&ihost->pdev->dev, + "%s: iport = %p; scic_port_hard_reset call" " failed 0x%x\n", - __func__, isci_port, status); + __func__, iport, status); } @@ -456,19 +444,12 @@ int isci_port_perform_hard_reset( * the same as link failures on all phys in the port. */ if (ret != TMF_RESP_FUNC_COMPLETE) { - BUG_ON(isci_port->isci_host == NULL); - - dev_err(&isci_port->isci_host->pdev->dev, - "%s: isci_port = %p; hard reset failed " + dev_err(&ihost->pdev->dev, + "%s: iport = %p; hard reset failed " "(0x%x) - sending link down to libsas for phy %p\n", - __func__, - isci_port, - isci_port->hard_reset_status, - isci_phy); - - isci_port_link_down(isci_port->isci_host, - isci_phy, - isci_port); + __func__, iport, iport->hard_reset_status, iphy); + + isci_port_link_down(ihost, iphy, iport); } return ret; @@ -491,8 +472,7 @@ void isci_port_invalid_link_up(struct scic_sds_controller *scic, struct scic_sds_port *sci_port, struct scic_sds_phy *phy) { - struct isci_host *ihost = - (struct isci_host *)sci_object_get_association(scic); + struct isci_host *ihost = sci_object_get_association(scic); dev_warn(&ihost->pdev->dev, "Invalid link up!\n"); } diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index dfdd12a0f68e..76546fd5b7d0 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -143,9 +143,8 @@ void isci_port_hard_reset_complete( struct isci_port *isci_port, enum sci_status completion_status); -int isci_port_perform_hard_reset( - struct isci_port *isci_port_ptr, - struct isci_phy *isci_phy_ptr); +int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, + struct isci_phy *iphy); void isci_port_invalid_link_up( struct scic_sds_controller *scic, diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 0fdaa6d62c1b..ab638ec5881c 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -218,33 +218,20 @@ static enum sci_status isci_remote_device_construct( return status; } - -/** - * isci_remote_device_nuke_requests() - This function terminates all requests - * for a given remote device. - * @isci_device: This parameter specifies the remote device - * - */ -void isci_remote_device_nuke_requests( - struct isci_remote_device *isci_device) +void isci_remote_device_nuke_requests(struct isci_host *ihost, struct isci_remote_device *idev) { DECLARE_COMPLETION_ONSTACK(aborted_task_completion); - struct isci_host *isci_host; - isci_host = isci_device->isci_port->isci_host; - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); + dev_dbg(&ihost->pdev->dev, + "%s: idev = %p\n", __func__, idev); /* Cleanup all requests pending for this device. */ - isci_terminate_pending_requests(isci_host, isci_device, terminating); + isci_terminate_pending_requests(ihost, idev, terminating); - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p, done\n", __func__, isci_device); + dev_dbg(&ihost->pdev->dev, + "%s: idev = %p, done\n", __func__, idev); } - - /** * This function builds the isci_remote_device when a libsas dev_found message * is received. @@ -380,7 +367,7 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem isci_remote_device_change_state(idev, isci_stopping); /* Kill all outstanding requests. */ - isci_remote_device_nuke_requests(idev); + isci_remote_device_nuke_requests(ihost, idev); set_bit(IDEV_STOP_PENDING, &idev->flags); @@ -409,7 +396,7 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem */ void isci_remote_device_gone(struct domain_device *dev) { - struct isci_host *ihost = dev->port->ha->lldd_ha; + struct isci_host *ihost = dev_to_ihost(dev); struct isci_remote_device *idev = dev->lldd_dev; dev_dbg(&ihost->pdev->dev, @@ -431,7 +418,7 @@ void isci_remote_device_gone(struct domain_device *dev) */ int isci_remote_device_found(struct domain_device *domain_dev) { - struct isci_host *isci_host; + struct isci_host *isci_host = dev_to_ihost(domain_dev); struct isci_port *isci_port; struct isci_phy *isci_phy; struct asd_sas_port *sas_port; @@ -439,8 +426,6 @@ int isci_remote_device_found(struct domain_device *domain_dev) struct isci_remote_device *isci_device; enum sci_status status; - isci_host = isci_host_from_sas_ha(domain_dev->port->ha); - dev_dbg(&isci_host->pdev->dev, "%s: domain_device = %p\n", __func__, domain_dev); @@ -556,41 +541,22 @@ bool isci_device_is_reset_pending( * * true if there is a reset pending for the device. */ -void isci_device_clear_reset_pending(struct isci_remote_device *isci_device) +void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev) { struct isci_request *isci_request; struct isci_request *tmp_req; - struct isci_host *isci_host = NULL; unsigned long flags = 0; - /* FIXME more port gone confusion, and this time it makes the - * locking "fun" - */ - if (isci_device->isci_port != NULL) - isci_host = isci_device->isci_port->isci_host; - - /* - * FIXME when the isci_host gets sorted out - * use dev_dbg() - */ - pr_debug("%s: isci_device=%p, isci_host=%p\n", - __func__, isci_device, isci_host); + dev_dbg(&ihost->pdev->dev, "%s: idev=%p, ihost=%p\n", + __func__, idev, ihost); - if (isci_host != NULL) - spin_lock_irqsave(&isci_host->scic_lock, flags); - else - pr_err("%s: isci_device %p; isci_host == NULL!\n", - __func__, isci_device); + spin_lock_irqsave(&ihost->scic_lock, flags); /* Clear reset pending on all pending requests. */ list_for_each_entry_safe(isci_request, tmp_req, - &isci_device->reqs_in_process, dev_node) { - /* - * FIXME when the conditional spinlock is gone - * change to dev_dbg() - */ - pr_debug("%s: isci_device = %p request = %p\n", - __func__, isci_device, isci_request); + &idev->reqs_in_process, dev_node) { + dev_dbg(&ihost->pdev->dev, "%s: idev = %p request = %p\n", + __func__, idev, isci_request); if (isci_request->ttype == io_task) { @@ -603,9 +569,7 @@ void isci_device_clear_reset_pending(struct isci_remote_device *isci_device) spin_unlock_irqrestore(&task->task_state_lock, flags2); } } - - if (isci_host != NULL) - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); } /** diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index cf5302abb8b2..9925316ac55a 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -78,59 +78,29 @@ static inline struct scic_sds_remote_device *to_sci_dev(struct isci_remote_devic return (struct scic_sds_remote_device *) &idev[1]; } -#define to_isci_remote_device(p) \ - container_of(p, struct isci_remote_device, sci_remote_device); - #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 - -/** - * isci_dev_from_domain_dev() - This accessor retrieves the remote_device - * object reference from the Linux domain_device reference. - * @domdev,: This parameter points to the Linux domain_device object . - * - * A reference to the associated isci remote device. - */ -#define isci_dev_from_domain_dev(domdev) \ - ((struct isci_remote_device *)(domdev)->lldd_dev) - -void isci_remote_device_start_complete( - struct isci_host *, - struct isci_remote_device *, - enum sci_status); - -void isci_remote_device_stop_complete( - struct isci_host *, - struct isci_remote_device *, - enum sci_status); - +void isci_remote_device_start_complete(struct isci_host *ihost, + struct isci_remote_device *idev, + enum sci_status); +void isci_remote_device_stop_complete(struct isci_host *ihost, + struct isci_remote_device *idev, + enum sci_status); enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev); -void isci_remote_device_nuke_requests( - struct isci_remote_device *isci_device); - +void isci_remote_device_nuke_requests(struct isci_host *ihost, + struct isci_remote_device *idev); void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev); - void isci_remote_device_not_ready(struct isci_host *ihost, struct isci_remote_device *idev, u32 reason); - -void isci_remote_device_gone( - struct domain_device *domain_dev); - -int isci_remote_device_found( - struct domain_device *domain_dev); - -bool isci_device_is_reset_pending( - struct isci_host *isci_host, - struct isci_remote_device *isci_device); - -void isci_device_clear_reset_pending( - struct isci_remote_device *isci_device); - -void isci_remote_device_change_state( - struct isci_remote_device *isci_device, - enum isci_status status); +void isci_remote_device_gone(struct domain_device *domain_dev); +int isci_remote_device_found(struct domain_device *domain_dev); +bool isci_device_is_reset_pending(struct isci_host *ihost, + struct isci_remote_device *idev); +void isci_device_clear_reset_pending(struct isci_host *ihost, + struct isci_remote_device *idev); +void isci_remote_device_change_state(struct isci_remote_device *idev, + enum isci_status status); #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ - diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index b519373597a5..37ffedc94ac0 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -379,7 +379,7 @@ int isci_request_execute( struct isci_request *request; unsigned long flags; - isci_device = isci_dev_from_domain_dev(task->dev); + isci_device = task->dev->lldd_dev; sci_device = to_sci_dev(isci_device); /* do common allocation and init of request object. */ diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 5bcea60fd8c4..c6c97ad58c9f 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -146,7 +146,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, */ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) { - struct isci_host *ihost = task->dev->port->ha->lldd_ha; + struct isci_host *ihost = dev_to_ihost(task->dev); struct isci_request *request = NULL; struct isci_remote_device *device; unsigned long flags; @@ -169,7 +169,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) "task = %p, num = %d; dev = %p; cmd = %p\n", task, num, task->dev, task->uldd_task); - device = isci_dev_from_domain_dev(task->dev); + device = task->dev->lldd_dev; if (device) device_status = device->status; @@ -593,7 +593,6 @@ static void isci_task_build_abort_task_tmf( static struct isci_request *isci_task_get_request_from_task( struct sas_task *task, - struct isci_host **isci_host, struct isci_remote_device **isci_device) { @@ -609,9 +608,6 @@ static struct isci_request *isci_task_get_request_from_task( (task->task_state_flags & SAS_TASK_AT_INITIATOR) && (request != NULL)) { - if (isci_host != NULL) - *isci_host = request->isci_host; - if (isci_device != NULL) *isci_device = request->isci_device; } @@ -1027,26 +1023,17 @@ static int isci_task_send_lu_reset_sas( * * status, zero indicates success. */ -int isci_task_lu_reset( - struct domain_device *domain_device, - u8 *lun) +int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) { - struct isci_host *isci_host = NULL; + struct isci_host *isci_host = dev_to_ihost(domain_device); struct isci_remote_device *isci_device = NULL; int ret; bool device_stopping = false; - if (domain_device == NULL) { - pr_warn("%s: domain_device == NULL\n", __func__); - return TMF_RESP_FUNC_FAILED; - } - - isci_device = isci_dev_from_domain_dev(domain_device); - - if (domain_device->port != NULL) - isci_host = isci_host_from_sas_ha(domain_device->port->ha); + isci_device = domain_device->lldd_dev; - pr_debug("%s: domain_device=%p, isci_host=%p; isci_device=%p\n", + dev_dbg(&isci_host->pdev->dev, + "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", __func__, domain_device, isci_host, isci_device); if (isci_device != NULL) @@ -1057,24 +1044,18 @@ int isci_task_lu_reset( * device's list, fail this LUN reset request in order to * escalate to the device reset. */ - if ((isci_device == NULL) || - (isci_host == NULL) || - ((isci_host != NULL) && - (isci_device != NULL) && - (device_stopping || - (isci_device_is_reset_pending(isci_host, isci_device))))) { + if (!isci_device || device_stopping || + isci_device_is_reset_pending(isci_host, isci_device)) { dev_warn(&isci_host->pdev->dev, - "%s: No dev (%p), no host (%p), or " + "%s: No dev (%p), or " "RESET PENDING: domain_device=%p\n", - __func__, isci_device, isci_host, domain_device); + __func__, isci_device, domain_device); return TMF_RESP_FUNC_FAILED; } /* Send the task management part of the reset. */ if (sas_protocol_ata(domain_device->tproto)) { - ret = isci_task_send_lu_reset_sata( - isci_host, isci_device, lun - ); + ret = isci_task_send_lu_reset_sata(isci_host, isci_device, lun); } else ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun); @@ -1173,11 +1154,11 @@ static void isci_abort_task_process_cb( */ int isci_task_abort_task(struct sas_task *task) { + struct isci_host *isci_host = dev_to_ihost(task->dev); DECLARE_COMPLETION_ONSTACK(aborted_io_completion); struct isci_request *old_request = NULL; enum isci_request_status old_state; struct isci_remote_device *isci_device = NULL; - struct isci_host *isci_host = NULL; struct isci_tmf tmf; int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; @@ -1189,8 +1170,7 @@ int isci_task_abort_task(struct sas_task *task) * in the device, because tasks driving resets may land here * after completion in the core. */ - old_request = isci_task_get_request_from_task(task, &isci_host, - &isci_device); + old_request = isci_task_get_request_from_task(task, &isci_device); dev_dbg(&isci_host->pdev->dev, "%s: task = %p\n", __func__, task); @@ -1610,37 +1590,29 @@ u32 isci_task_ssp_request_get_response_data_length( */ int isci_bus_reset_handler(struct scsi_cmnd *cmd) { + struct domain_device *dev = cmd_to_domain_dev(cmd); + struct isci_host *isci_host = dev_to_ihost(dev); unsigned long flags = 0; - struct isci_host *isci_host = NULL; enum sci_status status; int base_status; - struct isci_remote_device *isci_dev - = isci_dev_from_domain_dev( - sdev_to_domain_dev(cmd->device)); + struct isci_remote_device *isci_dev = dev->lldd_dev; - dev_dbg(&cmd->device->sdev_gendev, + dev_dbg(&isci_host->pdev->dev, "%s: cmd %p, isci_dev %p\n", __func__, cmd, isci_dev); if (!isci_dev) { - dev_warn(&cmd->device->sdev_gendev, + dev_warn(&isci_host->pdev->dev, "%s: isci_dev is GONE!\n", __func__); return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */ } - if (isci_dev->isci_port != NULL) - isci_host = isci_dev->isci_port->isci_host; - - if (isci_host != NULL) - spin_lock_irqsave(&isci_host->scic_lock, flags); - + spin_lock_irqsave(&isci_host->scic_lock, flags); status = scic_remote_device_reset(to_sci_dev(isci_dev)); if (status != SCI_SUCCESS) { - - if (isci_host != NULL) - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); scmd_printk(KERN_WARNING, cmd, "%s: scic_remote_device_reset(%p) returned %d!\n", @@ -1648,14 +1620,13 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) return TMF_RESP_FUNC_FAILED; } - if (isci_host != NULL) - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); /* Make sure all pending requests are able to be fully terminated. */ - isci_device_clear_reset_pending(isci_dev); + isci_device_clear_reset_pending(isci_host, isci_dev); /* Terminate in-progress I/O now. */ - isci_remote_device_nuke_requests(isci_dev); + isci_remote_device_nuke_requests(isci_host, isci_dev); /* Call into the libsas default handler (which calls sas_phy_reset). */ base_status = sas_eh_bus_reset_handler(cmd); @@ -1672,13 +1643,9 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) } /* WHAT TO DO HERE IF sas_phy_reset FAILS? */ - - if (isci_host != NULL) - spin_lock_irqsave(&isci_host->scic_lock, flags); + spin_lock_irqsave(&isci_host->scic_lock, flags); status = scic_remote_device_reset_complete(to_sci_dev(isci_dev)); - - if (isci_host != NULL) - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); if (status != SCI_SUCCESS) { scmd_printk(KERN_WARNING, cmd, @@ -1688,7 +1655,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) } /* WHAT TO DO HERE IF scic_remote_device_reset_complete FAILS? */ - dev_dbg(&cmd->device->sdev_gendev, + dev_dbg(&isci_host->pdev->dev, "%s: cmd %p, isci_dev %p complete.\n", __func__, cmd, isci_dev); -- cgit v1.2.3 From bc99aa47108e9fd759071d4741c7abdf7b903579 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Mar 2011 20:07:54 -0400 Subject: isci: remove mmio wrappers Remove a couple of layers around read/writel to make the driver readable. Signed-off-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 225 +++++----- drivers/scsi/isci/core/scic_sds_controller.h | 34 +- .../scsi/isci/core/scic_sds_controller_registers.h | 463 --------------------- drivers/scsi/isci/core/scic_sds_pci.h | 94 ----- drivers/scsi/isci/core/scic_sds_phy.c | 146 ++++--- drivers/scsi/isci/core/scic_sds_phy_registers.h | 248 ----------- drivers/scsi/isci/core/scic_sds_port.c | 95 ++--- drivers/scsi/isci/core/scic_sds_port.h | 23 - drivers/scsi/isci/core/scic_sds_port_registers.h | 81 ---- drivers/scsi/isci/core/scic_sds_request.c | 11 +- .../isci/core/scic_sds_unsolicited_frame_control.c | 5 +- 11 files changed, 258 insertions(+), 1167 deletions(-) delete mode 100644 drivers/scsi/isci/core/scic_sds_controller_registers.h delete mode 100644 drivers/scsi/isci/core/scic_sds_pci.h delete mode 100644 drivers/scsi/isci/core/scic_sds_phy_registers.h diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 9266fbee79e7..774c4b3b0dfb 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -59,8 +59,7 @@ #include "scic_port.h" #include "scic_remote_device.h" #include "scic_sds_controller.h" -#include "scic_sds_controller_registers.h" -#include "scic_sds_pci.h" +#include "scu_registers.h" #include "scic_sds_phy.h" #include "scic_sds_port_configuration_agent.h" #include "scic_sds_port.h" @@ -355,7 +354,10 @@ static void scic_sds_controller_ram_initialization( * Therefore it no longer comes out of memory in the MDL. */ mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE]; this_controller->completion_queue = (u32 *)mde->virtual_address; - SMU_CQBAR_WRITE(this_controller, mde->physical_address); + writel(lower_32_bits(mde->physical_address), \ + &this_controller->smu_registers->completion_queue_lower); + writel(upper_32_bits(mde->physical_address), + &this_controller->smu_registers->completion_queue_upper); /* * Program the location of the Remote Node Context table @@ -363,13 +365,19 @@ static void scic_sds_controller_ram_initialization( mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT]; this_controller->remote_node_context_table = (union scu_remote_node_context *) mde->virtual_address; - SMU_RNCBAR_WRITE(this_controller, mde->physical_address); + writel(lower_32_bits(mde->physical_address), + &this_controller->smu_registers->remote_node_context_lower); + writel(upper_32_bits(mde->physical_address), + &this_controller->smu_registers->remote_node_context_upper); /* Program the location of the Task Context table into the SCU. */ mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT]; this_controller->task_context_table = (struct scu_task_context *) mde->virtual_address; - SMU_HTTBAR_WRITE(this_controller, mde->physical_address); + writel(lower_32_bits(mde->physical_address), + &this_controller->smu_registers->host_task_table_lower); + writel(upper_32_bits(mde->physical_address), + &this_controller->smu_registers->host_task_table_upper); mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER]; scic_sds_unsolicited_frame_control_construct( @@ -378,13 +386,17 @@ static void scic_sds_controller_ram_initialization( /* * Inform the silicon as to the location of the UF headers and - * address table. */ - SCU_UFHBAR_WRITE( - this_controller, - this_controller->uf_control.headers.physical_address); - SCU_PUFATHAR_WRITE( - this_controller, - this_controller->uf_control.address_table.physical_address); + * address table. + */ + writel(lower_32_bits(this_controller->uf_control.headers.physical_address), + &this_controller->scu_registers->sdma.uf_header_base_address_lower); + writel(upper_32_bits(this_controller->uf_control.headers.physical_address), + &this_controller->scu_registers->sdma.uf_header_base_address_upper); + + writel(lower_32_bits(this_controller->uf_control.address_table.physical_address), + &this_controller->scu_registers->sdma.uf_address_table_lower); + writel(upper_32_bits(this_controller->uf_control.address_table.physical_address), + &this_controller->scu_registers->sdma.uf_address_table_upper); } /** @@ -392,25 +404,26 @@ static void scic_sds_controller_ram_initialization( * @this_controller: * */ -static void scic_sds_controller_assign_task_entries( - struct scic_sds_controller *this_controller) +static void +scic_sds_controller_assign_task_entries(struct scic_sds_controller *controller) { u32 task_assignment; /* * Assign all the TCs to function 0 - * TODO: Do we actually need to read this register to write it back? */ - task_assignment = SMU_TCA_READ(this_controller, 0); + * TODO: Do we actually need to read this register to write it back? + */ task_assignment = - ( - task_assignment - | (SMU_TCA_GEN_VAL(STARTING, 0)) - | (SMU_TCA_GEN_VAL(ENDING, this_controller->task_context_entries - 1)) - | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE)) - ); + readl(&controller->smu_registers->task_context_assignment[0]); + + task_assignment |= (SMU_TCA_GEN_VAL(STARTING, 0)) | + (SMU_TCA_GEN_VAL(ENDING, controller->task_context_entries - 1)) | + (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE)); + + writel(task_assignment, + &controller->smu_registers->task_context_assignment[0]); - SMU_TCA_WRITE(this_controller, 0, task_assignment); } /** @@ -433,7 +446,9 @@ static void scic_sds_controller_initialize_completion_queue( | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1) ); - SMU_CQC_WRITE(this_controller, completion_queue_control_value); + writel(completion_queue_control_value, + &this_controller->smu_registers->completion_queue_control); + /* Set the completion queue get pointer and enable the queue */ completion_queue_get_value = ( @@ -443,7 +458,8 @@ static void scic_sds_controller_initialize_completion_queue( | (SMU_CQGR_GEN_BIT(EVENT_ENABLE)) ); - SMU_CQGR_WRITE(this_controller, completion_queue_get_value); + writel(completion_queue_get_value, + &this_controller->smu_registers->completion_queue_get); /* Set the completion queue put pointer */ completion_queue_put_value = ( @@ -451,7 +467,9 @@ static void scic_sds_controller_initialize_completion_queue( | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0)) ); - SMU_CQPR_WRITE(this_controller, completion_queue_put_value); + writel(completion_queue_put_value, + &this_controller->smu_registers->completion_queue_put); + /* Initialize the cycle bit of the completion queue entries */ for (index = 0; index < this_controller->completion_queue_entries; index++) { @@ -479,7 +497,8 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue( frame_queue_control_value = SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count); - SCU_UFQC_WRITE(this_controller, frame_queue_control_value); + writel(frame_queue_control_value, + &this_controller->scu_registers->sdma.unsolicited_frame_queue_control); /* Setup the get pointer for the unsolicited frame queue */ frame_queue_get_value = ( @@ -487,12 +506,12 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue( | SCU_UFQGP_GEN_BIT(ENABLE_BIT) ); - SCU_UFQGP_WRITE(this_controller, frame_queue_get_value); - + writel(frame_queue_get_value, + &this_controller->scu_registers->sdma.unsolicited_frame_get_pointer); /* Setup the put pointer for the unsolicited frame queue */ frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0); - - SCU_UFQPP_WRITE(this_controller, frame_queue_put_value); + writel(frame_queue_put_value, + &this_controller->scu_registers->sdma.unsolicited_frame_put_pointer); } /** @@ -505,12 +524,12 @@ static void scic_sds_controller_enable_port_task_scheduler( { u32 port_task_scheduler_value; - port_task_scheduler_value = SCU_PTSGCR_READ(this_controller); - + port_task_scheduler_value = + readl(&this_controller->scu_registers->peg0.ptsg.control); port_task_scheduler_value |= (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE)); - - SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value); + writel(port_task_scheduler_value, + &this_controller->scu_registers->peg0.ptsg.control); } /** @@ -531,35 +550,34 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s u32 phy_id; /* Clear DFX Status registers */ - scu_afe_register_write(scic, afe_dfx_master_control0, 0x0081000f); + writel(0x0081000f, &scic->scu_registers->afe.afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Configure bias currents to normal */ if (is_a0()) - scu_afe_register_write(scic, afe_bias_control, 0x00005500); + writel(0x00005500, &scic->scu_registers->afe.afe_bias_control); else - scu_afe_register_write(scic, afe_bias_control, 0x00005A00); + writel(0x00005A00, &scic->scu_registers->afe.afe_bias_control); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable PLL */ if (is_b0()) - scu_afe_register_write(scic, afe_pll_control0, 0x80040A08); + writel(0x80040A08, &scic->scu_registers->afe.afe_pll_control0); else - scu_afe_register_write(scic, afe_pll_control0, 0x80040908); + writel(0x80040908, &scic->scu_registers->afe.afe_pll_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Wait for the PLL to lock */ do { - afe_status = scu_afe_register_read( - scic, afe_common_block_status); + afe_status = readl(&scic->scu_registers->afe.afe_common_block_status); udelay(AFE_REGISTER_WRITE_DELAY); } while ((afe_status & 0x00001000) == 0); if (is_b0()) { /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ - scu_afe_register_write(scic, afe_pmsn_master_control0, 0x7bcc96ad); + writel(0x7bcc96ad, &scic->scu_registers->afe.afe_pmsn_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); } @@ -568,16 +586,16 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s if (is_b0()) { /* Configure transmitter SSC parameters */ - scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000); + writel(0x00030000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); } else { /* * All defaults, except the Receive Word Alignament/Comma Detect * Enable....(0xe800) */ - scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004512); + writel(0x00004512, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_xcvr_control1, 0x0050100F); + writel(0x0050100F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1); udelay(AFE_REGISTER_WRITE_DELAY); } @@ -585,61 +603,65 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) * & increase TX int & ext bias 20%....(0xe85c) */ if (is_a0()) - scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003D4); + writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); else if (is_a2()) - scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003F0); + writel(0x000003F0, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); else { /* Power down TX and RX (PWRDNTX and PWRDNRX) */ - scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d7); + writel(0x000003d7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); /* * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) * & increase TX int & ext bias 20%....(0xe85c) */ - scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d4); + writel(0x000003d4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); } udelay(AFE_REGISTER_WRITE_DELAY); if (is_a0() || is_a2()) { /* Enable TX equalization (0xe824) */ - scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000); + writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); udelay(AFE_REGISTER_WRITE_DELAY); } /* * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On), * RDD=0x0(RX Detect Enabled) ....(0xe800) */ - scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004100); + writel(0x00004100, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Leave DFE/FFE on */ if (is_a0()) - scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F09983F); + writel(0x3F09983F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); else if (is_a2()) - scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F); + writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); else { - scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F); + writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable TX equalization (0xe824) */ - scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000); + writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); } udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control0); + writel(oem_phy->afe_tx_amp_control0, + &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0); udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control1); + writel(oem_phy->afe_tx_amp_control1, + &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1); udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control2); + writel(oem_phy->afe_tx_amp_control2, + &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2); udelay(AFE_REGISTER_WRITE_DELAY); - scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, oem_phy->afe_tx_amp_control3); + writel(oem_phy->afe_tx_amp_control3, + &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3); udelay(AFE_REGISTER_WRITE_DELAY); } /* Transfer control to the PEs */ - scu_afe_register_write(scic, afe_dfx_master_control0, 0x00010f00); + writel(0x00010f00, &scic->scu_registers->afe.afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); } @@ -1437,8 +1459,9 @@ static void scic_sds_controller_process_completions( | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); - SMU_CQGR_WRITE(this_controller, - this_controller->completion_queue_get); + writel(this_controller->completion_queue_get, + &this_controller->smu_registers->completion_queue_get); + } dev_dbg(scic_to_dev(this_controller), @@ -1456,15 +1479,15 @@ bool scic_sds_controller_isr(struct scic_sds_controller *scic) /* * we have a spurious interrupt it could be that we have already * emptied the completion queue from a previous interrupt */ - SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); + writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); /* * There is a race in the hardware that could cause us not to be notified * of an interrupt completion if we do not take this step. We will mask * then unmask the interrupts so if there is another interrupt pending * the clearing of the interrupt source we get the next interrupt message. */ - SMU_IMR_WRITE(scic, 0xFF000000); - SMU_IMR_WRITE(scic, 0x00000000); + writel(0xFF000000, &scic->smu_registers->interrupt_mask); + writel(0, &scic->smu_registers->interrupt_mask); } return false; @@ -1477,18 +1500,18 @@ void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) scic_sds_controller_process_completions(scic); /* Clear the interrupt and enable all interrupts again */ - SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); + writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); /* Could we write the value of SMU_ISR_COMPLETION? */ - SMU_IMR_WRITE(scic, 0xFF000000); - SMU_IMR_WRITE(scic, 0x00000000); + writel(0xFF000000, &scic->smu_registers->interrupt_mask); + writel(0, &scic->smu_registers->interrupt_mask); } bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) { u32 interrupt_status; - interrupt_status = SMU_ISR_READ(scic); - + interrupt_status = + readl(&scic->smu_registers->interrupt_status); interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); if (interrupt_status != 0) { @@ -1504,8 +1527,8 @@ bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) * then unmask the error interrupts so if there was another interrupt * pending we will be notified. * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */ - SMU_IMR_WRITE(scic, 0x000000FF); - SMU_IMR_WRITE(scic, 0x00000000); + writel(0xff, &scic->smu_registers->interrupt_mask); + writel(0, &scic->smu_registers->interrupt_mask); return false; } @@ -1514,14 +1537,14 @@ void scic_sds_controller_error_handler(struct scic_sds_controller *scic) { u32 interrupt_status; - interrupt_status = SMU_ISR_READ(scic); + interrupt_status = + readl(&scic->smu_registers->interrupt_status); if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && scic_sds_controller_completion_queue_has_entries(scic)) { scic_sds_controller_process_completions(scic); - SMU_ISR_WRITE(scic, SMU_ISR_QUEUE_SUSPEND); - + writel(SMU_ISR_QUEUE_SUSPEND, &scic->smu_registers->interrupt_status); } else { dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, interrupt_status); @@ -1535,7 +1558,7 @@ void scic_sds_controller_error_handler(struct scic_sds_controller *scic) /* If we dont process any completions I am not sure that we want to do this. * We are in the middle of a hardware fault and should probably be reset. */ - SMU_IMR_WRITE(scic, 0x00000000); + writel(0, &scic->smu_registers->interrupt_mask); } @@ -1648,7 +1671,7 @@ void scic_sds_controller_post_request( this_controller, request); - SMU_PCP_WRITE(this_controller, request); + writel(request, &this_controller->smu_registers->post_context_port); } /** @@ -1871,7 +1894,8 @@ void scic_sds_controller_release_frame( { if (scic_sds_unsolicited_frame_control_release_frame( &this_controller->uf_control, frame_index) == true) - SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get); + writel(this_controller->uf_control.get, + &this_controller->scu_registers->sdma.unsolicited_frame_get_pointer); } /** @@ -2478,14 +2502,14 @@ void scic_controller_enable_interrupts( struct scic_sds_controller *scic) { BUG_ON(scic->smu_registers == NULL); - SMU_IMR_WRITE(scic, 0x00000000); + writel(0, &scic->smu_registers->interrupt_mask); } void scic_controller_disable_interrupts( struct scic_sds_controller *scic) { BUG_ON(scic->smu_registers == NULL); - SMU_IMR_WRITE(scic, 0xffffffff); + writel(0xffffffff, &scic->smu_registers->interrupt_mask); } static enum sci_status scic_controller_set_mode( @@ -2543,16 +2567,16 @@ static void scic_sds_controller_reset_hardware( scic_controller_disable_interrupts(scic); /* Reset the SCU */ - SMU_SMUSRCR_WRITE(scic, 0xFFFFFFFF); + writel(0xFFFFFFFF, &scic->smu_registers->soft_reset_control); /* Delay for 1ms to before clearing the CQP and UFQPR. */ udelay(1000); /* The write to the CQGR clears the CQP */ - SMU_CQGR_WRITE(scic, 0x00000000); + writel(0x00000000, &scic->smu_registers->completion_queue_get); /* The write to the UFQGP clears the UFQPR */ - SCU_UFQGP_WRITE(scic, 0x00000000); + writel(0, &scic->scu_registers->sdma.unsolicited_frame_get_pointer); } enum sci_status scic_user_parameters_set( @@ -2778,11 +2802,10 @@ static enum sci_status scic_controller_set_interrupt_coalescence( return SCI_FAILURE_INVALID_PARAMETER_VALUE; } - SMU_ICC_WRITE( - scic_controller, - (SMU_ICC_GEN_VAL(NUMBER, coalesce_number) | - SMU_ICC_GEN_VAL(TIMER, timeout_encode)) - ); + writel(SMU_ICC_GEN_VAL(NUMBER, coalesce_number) | + SMU_ICC_GEN_VAL(TIMER, timeout_encode), + &scic_controller->smu_registers->interrupt_coalesce_control); + scic_controller->interrupt_coalesce_number = (u16)coalesce_number; scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100; @@ -2868,7 +2891,7 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct u32 terminate_loop; /* Take the hardware out of reset */ - SMU_SMUSRCR_WRITE(scic, 0x00000000); + writel(0, &scic->smu_registers->soft_reset_control); /* * / @todo Provide meaningfull error code for hardware failure @@ -2879,7 +2902,7 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct while (terminate_loop-- && (result != SCI_SUCCESS)) { /* Loop until the hardware reports success */ udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME); - status = SMU_SMUCSR_READ(scic); + status = readl(&scic->smu_registers->control_status); if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) @@ -2896,7 +2919,9 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct /* * Determine what are the actaul device capacities that the * hardware will support */ - device_context_capacity = SMU_DCC_READ(scic); + device_context_capacity = + readl(&scic->smu_registers->device_context_capacity); + max_supported_ports = smu_dcc_get_max_ports(device_context_capacity); max_supported_devices = smu_dcc_get_max_remote_node_context(device_context_capacity); @@ -2910,9 +2935,7 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct struct scu_port_task_scheduler_group_registers *ptsg = &scic->scu_registers->peg0.ptsg; - scu_register_write(scic, - ptsg->protocol_engine[index], - index); + writel(index, &ptsg->protocol_engine[index]); } /* Record the smaller of the two capacity values */ @@ -2939,16 +2962,20 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct u32 dma_configuration; /* Configure the payload DMA */ - dma_configuration = SCU_PDMACR_READ(scic); + dma_configuration = + readl(&scic->scu_registers->sdma.pdma_configuration); dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - SCU_PDMACR_WRITE(scic, dma_configuration); + writel(dma_configuration, + &scic->scu_registers->sdma.pdma_configuration); /* Configure the control DMA */ - dma_configuration = SCU_CDMACR_READ(scic); + dma_configuration = + readl(&scic->scu_registers->sdma.cdma_configuration); dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - SCU_CDMACR_WRITE(scic, dma_configuration); + writel(dma_configuration, + &scic->scu_registers->sdma.cdma_configuration); } /* diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index fd78148d93d9..baf0b9ededec 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -57,6 +57,7 @@ #define _SCIC_SDS_CONTROLLER_H_ #include +#include /** * This file contains the structures, constants and prototypes used for the @@ -80,7 +81,6 @@ #include "scu_unsolicited_frame.h" #include "scic_sds_unsolicited_frame_control.h" #include "scic_sds_port_configuration_agent.h" -#include "scic_sds_pci.h" struct scic_sds_remote_device; struct scic_sds_request; @@ -427,38 +427,6 @@ extern const struct scic_sds_controller_state_handler #define scic_sds_controller_get_port_configuration_agent(controller) \ (&(controller)->port_agent) -/** - * smu_register_write() - - * - * This macro writes to the smu_register for this controller - */ -#define smu_register_write(controller, reg, value) \ - scic_sds_pci_write_smu_dword((controller), &(reg), (value)) - -/** - * smu_register_read() - - * - * This macro reads the smu_register for this controller - */ -#define smu_register_read(controller, reg) \ - scic_sds_pci_read_smu_dword((controller), &(reg)) - -/** - * scu_register_write() - - * - * This mcaro writes the scu_register for this controller - */ -#define scu_register_write(controller, reg, value) \ - scic_sds_pci_write_scu_dword((controller), &(reg), (value)) - -/** - * scu_register_read() - - * - * This macro reads the scu_register for this controller - */ -#define scu_register_read(controller, reg) \ - scic_sds_pci_read_scu_dword((controller), &(reg)) - /** * scic_sds_controller_get_protocol_engine_group() - * diff --git a/drivers/scsi/isci/core/scic_sds_controller_registers.h b/drivers/scsi/isci/core/scic_sds_controller_registers.h deleted file mode 100644 index b7bec92ee59c..000000000000 --- a/drivers/scsi/isci/core/scic_sds_controller_registers.h +++ /dev/null @@ -1,463 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_CONTROLLER_REGISTERS_H_ -#define _SCIC_SDS_CONTROLLER_REGISTERS_H_ - -/** - * This file contains macros used to perform the register reads/writes to the - * SCU hardware. - * - * - */ - -#include "scu_registers.h" -#include "scic_sds_controller.h" - -/** - * scic_sds_controller_smu_register_read() - - * - * SMU_REGISTER_ACCESS_MACROS - */ -#define scic_sds_controller_smu_register_read(controller, reg) \ - smu_register_read(\ - (controller), \ - (controller)->smu_registers->reg \ - ) - -#define scic_sds_controller_smu_register_write(controller, reg, value) \ - smu_register_write(\ - (controller), \ - (controller)->smu_registers->reg, \ - (value) \ - ) - -/** - * scu_afe_register_write() - - * - * AFE_REGISTER_ACCESS_MACROS - */ -#define scu_afe_register_write(controller, reg, value) \ - scu_register_write(\ - (controller), \ - (controller)->scu_registers->afe.reg, \ - (value) \ - ) - -#define scu_afe_txreg_write(controller, phy, reg, value) \ - scu_register_write(\ - (controller), \ - (controller)->scu_registers->afe.scu_afe_xcvr[phy].reg,\ - (value) \ - ) - -#define scu_afe_register_read(controller, reg) \ - scu_register_read(\ - (controller), \ - (controller)->scu_registers->afe.reg \ - ) - -/** - * scu_controller_viit_register_write() - - * - * VIIT_REGISTER_ACCESS_MACROS - */ -#define scu_controller_viit_register_write(controller, index, reg, value) \ - scu_register_write(\ - (controller), \ - (controller)->scu_registers->peg0.viit[index].reg, \ - value \ - ) - -/* - * ***************************************************************************** - * * SMU REGISTERS - * ***************************************************************************** */ - -/** - * SMU_PCP_WRITE() - - * - * struct smu_registers - */ -#define SMU_PCP_WRITE(controller, value) \ - scic_sds_controller_smu_register_write(\ - controller, post_context_port, value \ - ) - -#define SMU_TCR_READ(controller, value) \ - scic_sds_controller_smu_register_read(\ - controller, task_context_range \ - ) - -#define SMU_TCR_WRITE(controller, value) \ - scic_sds_controller_smu_register_write(\ - controller, task_context_range, value \ - ) - -#define SMU_HTTBAR_WRITE(controller, address) \ - { \ - scic_sds_controller_smu_register_write(\ - controller, \ - host_task_table_lower, \ - lower_32_bits(address) \ - ); \ - scic_sds_controller_smu_register_write(\ - controller, \ - host_task_table_upper, \ - upper_32_bits(address) \ - ); \ - } - -#define SMU_CQBAR_WRITE(controller, address) \ - { \ - scic_sds_controller_smu_register_write(\ - controller, \ - completion_queue_lower, \ - lower_32_bits(address) \ - ); \ - scic_sds_controller_smu_register_write(\ - controller, \ - completion_queue_upper, \ - upper_32_bits(address) \ - ); \ - } - -#define SMU_CQGR_WRITE(controller, value) \ - scic_sds_controller_smu_register_write(\ - controller, completion_queue_get, value \ - ) - -#define SMU_CQGR_READ(controller, value) \ - scic_sds_controller_smu_register_read(\ - controller, completion_queue_get \ - ) - -#define SMU_CQPR_WRITE(controller, value) \ - scic_sds_controller_smu_register_write(\ - controller, completion_queue_put, value \ - ) - -#define SMU_RNCBAR_WRITE(controller, address) \ - { \ - scic_sds_controller_smu_register_write(\ - controller, \ - remote_node_context_lower, \ - lower_32_bits(address) \ - ); \ - scic_sds_controller_smu_register_write(\ - controller, \ - remote_node_context_upper, \ - upper_32_bits(address) \ - ); \ - } - -#define SMU_AMR_READ(controller) \ - scic_sds_controller_smu_register_read(\ - controller, address_modifier \ - ) - -#define SMU_IMR_READ(controller) \ - scic_sds_controller_smu_register_read(\ - controller, interrupt_mask \ - ) - -#define SMU_IMR_WRITE(controller, mask) \ - scic_sds_controller_smu_register_write(\ - controller, interrupt_mask, mask \ - ) - -#define SMU_ISR_READ(controller) \ - scic_sds_controller_smu_register_read(\ - controller, interrupt_status \ - ) - -#define SMU_ISR_WRITE(controller, status) \ - scic_sds_controller_smu_register_write(\ - controller, interrupt_status, status \ - ) - -#define SMU_ICC_READ(controller) \ - scic_sds_controller_smu_register_read(\ - controller, interrupt_coalesce_control \ - ) - -#define SMU_ICC_WRITE(controller, value) \ - scic_sds_controller_smu_register_write(\ - controller, interrupt_coalesce_control, value \ - ) - -#define SMU_CQC_WRITE(controller, value) \ - scic_sds_controller_smu_register_write(\ - controller, completion_queue_control, value \ - ) - -#define SMU_SMUSRCR_WRITE(controller, value) \ - scic_sds_controller_smu_register_write(\ - controller, soft_reset_control, value \ - ) - -#define SMU_TCA_WRITE(controller, index, value) \ - scic_sds_controller_smu_register_write(\ - controller, task_context_assignment[index], value \ - ) - -#define SMU_TCA_READ(controller, index) \ - scic_sds_controller_smu_register_read(\ - controller, task_context_assignment[index] \ - ) - -#define SMU_DCC_READ(controller) \ - scic_sds_controller_smu_register_read(\ - controller, device_context_capacity \ - ) - -#define SMU_DFC_READ(controller) \ - scic_sds_controller_smu_register_read(\ - controller, device_function_capacity \ - ) - -#define SMU_SMUCSR_READ(controller) \ - scic_sds_controller_smu_register_read(\ - controller, control_status \ - ) - -#define SMU_CQPR_READ(controller) \ - scic_sds_controller_smu_register_read(\ - controller, completion_queue_put \ - ) - - -/** - * scic_sds_controller_scu_register_read() - - * - * SCU_REGISTER_ACCESS_MACROS - */ -#define scic_sds_controller_scu_register_read(controller, reg) \ - scu_register_read(\ - (controller), \ - (controller)->scu_registers->reg \ - ) - -#define scic_sds_controller_scu_register_write(controller, reg, value) \ - scu_register_write(\ - (controller), \ - (controller)->scu_registers->reg, \ - (value) \ - ) - - -/* - * **************************************************************************** - * * SCU SDMA REGISTERS - * **************************************************************************** */ - -/** - * scu_sdma_register_read() - - * - * SCU_SDMA_REGISTER_ACCESS_MACROS - */ -#define scu_sdma_register_read(controller, reg) \ - scu_register_read(\ - (controller), \ - (controller)->scu_registers->sdma.reg \ - ) - -#define scu_sdma_register_write(controller, reg, value) \ - scu_register_write(\ - (controller), \ - (controller)->scu_registers->sdma.reg, \ - (value) \ - ) - -/** - * SCU_PUFATHAR_WRITE() - - * - * struct scu_sdma_registers - */ -#define SCU_PUFATHAR_WRITE(controller, address) \ - { \ - scu_sdma_register_write(\ - controller, \ - uf_address_table_lower, \ - lower_32_bits(address) \ - ); \ - scu_sdma_register_write(\ - controller, \ - uf_address_table_upper, \ - upper_32_bits(address) \ - ); \ - } - -#define SCU_UFHBAR_WRITE(controller, address) \ - { \ - scu_sdma_register_write(\ - controller, \ - uf_header_base_address_lower, \ - lower_32_bits(address) \ - ); \ - scu_sdma_register_write(\ - controller, \ - uf_header_base_address_upper, \ - upper_32_bits(address) \ - ); \ - } - -#define SCU_UFQC_READ(controller) \ - scu_sdma_register_read(\ - controller, \ - unsolicited_frame_queue_control \ - ) - -#define SCU_UFQC_WRITE(controller, value) \ - scu_sdma_register_write(\ - controller, \ - unsolicited_frame_queue_control, \ - value \ - ) - -#define SCU_UFQPP_READ(controller) \ - scu_sdma_register_read(\ - controller, \ - unsolicited_frame_put_pointer \ - ) - -#define SCU_UFQPP_WRITE(controller, value) \ - scu_sdma_register_write(\ - controller, \ - unsolicited_frame_put_pointer, \ - value \ - ) - -#define SCU_UFQGP_WRITE(controller, value) \ - scu_sdma_register_write(\ - controller, \ - unsolicited_frame_get_pointer, \ - value \ - ) - -#define SCU_PDMACR_READ(controller) \ - scu_sdma_register_read(\ - controller, \ - pdma_configuration \ - ) - -#define SCU_PDMACR_WRITE(controller, value) \ - scu_sdma_register_write(\ - controller, \ - pdma_configuration, \ - value \ - ) - -#define SCU_CDMACR_READ(controller) \ - scu_sdma_register_read(\ - controller, \ - cdma_configuration \ - ) - -#define SCU_CDMACR_WRITE(controller, value) \ - scu_sdma_register_write(\ - controller, \ - cdma_configuration, \ - value \ - ) - -/* - * ***************************************************************************** - * * SCU Port Task Scheduler Group Registers - * ***************************************************************************** */ - -/** - * scu_ptsg_register_read() - - * - * SCU_PTSG_REGISTER_ACCESS_MACROS - */ -#define scu_ptsg_register_read(controller, reg) \ - scu_register_read(\ - (controller), \ - (controller)->scu_registers->peg0.ptsg.reg \ - ) - -#define scu_ptsg_register_write(controller, reg, value) \ - scu_register_write(\ - (controller), \ - (controller)->scu_registers->peg0.ptsg.reg, \ - (value) \ - ) - -/** - * SCU_PTSGCR_READ() - - * - * SCU_PTSG_REGISTERS - */ -#define SCU_PTSGCR_READ(controller) \ - scu_ptsg_register_read(\ - (controller), \ - control \ - ) - -#define SCU_PTSGCR_WRITE(controller, value) \ - scu_ptsg_register_write(\ - (controller), \ - control, \ - value \ - ) - -#define SCU_PTSGRTC_READ(controller) \ - scu_ptsg_register_read(\ - contoller, \ - real_time_clock \ - ) - -#endif /* _SCIC_SDS_CONTROLLER_REGISTERS_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_pci.h b/drivers/scsi/isci/core/scic_sds_pci.h deleted file mode 100644 index bf0cbcaac526..000000000000 --- a/drivers/scsi/isci/core/scic_sds_pci.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_PCI_H_ -#define _SCIC_SDS_PCI_H_ - -/** - * This file contains the prototypes/macros utilized in writing out PCI data - * for the SCI core. - * - * - */ - -#include - -struct scic_sds_controller; - -void scic_sds_pci_bar_initialization(struct scic_sds_controller *scic); - -/* for debug we separate scu and smu accesses and require a controller */ -static inline u32 scic_sds_pci_read_smu_dword(struct scic_sds_controller *scic, void __iomem *addr) -{ - return readl(addr); -} - -static inline void scic_sds_pci_write_smu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value) -{ - writel(value, addr); -} - -static inline u32 scic_sds_pci_read_scu_dword(struct scic_sds_controller *scic, void __iomem *addr) -{ - return readl(addr); -} - -static inline void scic_sds_pci_write_scu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value) -{ - writel(value, addr); -} - - -#endif /* _SCIC_SDS_PCI_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 532338eb302b..c26e5df18142 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -60,7 +60,6 @@ #include "scic_phy.h" #include "scic_sds_controller.h" #include "scic_sds_phy.h" -#include "scic_sds_phy_registers.h" #include "scic_sds_port.h" #include "scic_sds_remote_node_context.h" #include "sci_environment.h" @@ -98,12 +97,13 @@ static enum sci_status scic_sds_phy_transport_layer_initialization( this_phy->transport_layer_registers = transport_layer_registers; - SCU_STPTLDARNI_WRITE(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); + writel(SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX, + &this_phy->transport_layer_registers->stp_rni); /* Hardware team recommends that we enable the STP prefetch for all transports */ - tl_control = SCU_TLCR_READ(this_phy); + tl_control = readl(&this_phy->transport_layer_registers->control); tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); - SCU_TLCR_WRITE(this_phy, tl_control); + writel(tl_control, &this_phy->transport_layer_registers->control); return SCI_SUCCESS; } @@ -135,30 +135,36 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, /* Set our IDENTIFY frame data */ #define SCI_END_DEVICE 0x01 - SCU_SAS_TIID_WRITE(sci_phy, (SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) | - SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) | - SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) | - SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) | - SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE))); + writel(SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) | + SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE), + &sci_phy->link_layer_registers->transmit_identification); /* Write the device SAS Address */ - SCU_SAS_TIDNH_WRITE(sci_phy, 0xFEDCBA98); - SCU_SAS_TIDNL_WRITE(sci_phy, phy_idx); + writel(0xFEDCBA98, &sci_phy->link_layer_registers->sas_device_name_high); + writel(phy_idx, &sci_phy->link_layer_registers->sas_device_name_low); /* Write the source SAS Address */ - SCU_SAS_TISSAH_WRITE(sci_phy, phy_oem->sas_address.high); - SCU_SAS_TISSAL_WRITE(sci_phy, phy_oem->sas_address.low); + writel(phy_oem->sas_address.high, + &sci_phy->link_layer_registers->source_sas_address_high); + writel(phy_oem->sas_address.low, + &sci_phy->link_layer_registers->source_sas_address_low); /* Clear and Set the PHY Identifier */ - SCU_SAS_TIPID_WRITE(sci_phy, 0x00000000); - SCU_SAS_TIPID_WRITE(sci_phy, SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx)); + writel(0, &sci_phy->link_layer_registers->identify_frame_phy_id); + writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), + &sci_phy->link_layer_registers->identify_frame_phy_id); /* Change the initial state of the phy configuration register */ - phy_configuration = SCU_SAS_PCFG_READ(sci_phy); + phy_configuration = + readl(&sci_phy->link_layer_registers->phy_configuration); /* Hold OOB state machine in reset */ phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - SCU_SAS_PCFG_WRITE(sci_phy, phy_configuration); + writel(phy_configuration, + &sci_phy->link_layer_registers->phy_configuration); /* Configure the SNW capabilities */ phy_capabilities.u.all = 0; @@ -188,13 +194,15 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, if ((parity_count % 2) != 0) phy_capabilities.u.bits.parity = 1; - SCU_SAS_PHYCAP_WRITE(sci_phy, phy_capabilities.u.all); + writel(phy_capabilities.u.all, + &sci_phy->link_layer_registers->phy_capabilities); /* Set the enable spinup period but disable the ability to send * notify enable spinup */ - SCU_SAS_ENSPINUP_WRITE(sci_phy, SCU_ENSPINUP_GEN_VAL(COUNT, - phy_user->notify_enable_spin_up_insertion_frequency)); + writel(SCU_ENSPINUP_GEN_VAL(COUNT, + phy_user->notify_enable_spin_up_insertion_frequency), + &sci_phy->link_layer_registers->notify_enable_spinup_control); /* Write the ALIGN Insertion Ferequency for connected phy and * inpendent of connected state @@ -205,10 +213,11 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL, phy_user->align_insertion_frequency); - SCU_SAS_CLKSM_WRITE(sci_phy, clksm_value); + writel(clksm_value, &sci_phy->link_layer_registers->clock_skew_management); /* @todo Provide a way to write this register correctly */ - scu_link_layer_register_write(sci_phy, afe_lookup_table_control, 0x02108421); + writel(0x02108421, + &sci_phy->link_layer_registers->afe_lookup_table_control); llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, (u8)scic->user_parameters.sds1.no_outbound_task_timeout); @@ -225,8 +234,7 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, break; } llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate); - - scu_link_layer_register_write(sci_phy, link_layer_control, llctl); + writel(llctl, &sci_phy->link_layer_registers->link_layer_control); if (is_a0() || is_a2()) { /* Program the max ARB time for the PHY to 700us so we inter-operate with @@ -234,16 +242,15 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, * many breaks. This time value will guarantee that the initiator PHY will * generate the break. */ - scu_link_layer_register_write(sci_phy, - maximum_arbitration_wait_timer_timeout, - SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME); + writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME, + &sci_phy->link_layer_registers->maximum_arbitration_wait_timer_timeout); } /* * Set the link layer hang detection to 500ms (0x1F4) from its default - * value of 128ms. Max value is 511 ms. */ - scu_link_layer_register_write(sci_phy, link_layer_hang_detection_timeout, - 0x1F4); + * value of 128ms. Max value is 511 ms. + */ + writel(0x1F4, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout); /* We can exit the initial state to the stopped state */ sci_base_state_machine_change_state(&sci_phy->parent.state_machine, @@ -367,15 +374,15 @@ void scic_sds_phy_setup_transport( { u32 tl_control; - SCU_STPTLDARNI_WRITE(this_phy, device_id); + writel(device_id, &this_phy->transport_layer_registers->stp_rni); /* * The read should guarantee that the first write gets posted * before the next write */ - tl_control = SCU_TLCR_READ(this_phy); + tl_control = readl(&this_phy->transport_layer_registers->control); tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); - SCU_TLCR_WRITE(this_phy, tl_control); + writel(tl_control, &this_phy->transport_layer_registers->control); } /** @@ -390,9 +397,12 @@ static void scic_sds_phy_suspend( { u32 scu_sas_pcfg_value; - scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + scu_sas_pcfg_value = + readl(&this_phy->link_layer_registers->phy_configuration); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); - SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + writel(scu_sas_pcfg_value, + &this_phy->link_layer_registers->phy_configuration); + scic_sds_phy_setup_transport(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); } @@ -408,11 +418,11 @@ void scic_sds_phy_resume( { u32 scu_sas_pcfg_value; - scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); - + scu_sas_pcfg_value = + readl(&this_phy->link_layer_registers->phy_configuration); scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); - - SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + writel(scu_sas_pcfg_value, + &this_phy->link_layer_registers->phy_configuration); } /** @@ -427,8 +437,8 @@ void scic_sds_phy_get_sas_address( struct scic_sds_phy *this_phy, struct sci_sas_address *sas_address) { - sas_address->high = SCU_SAS_TISSAH_READ(this_phy); - sas_address->low = SCU_SAS_TISSAL_READ(this_phy); + sas_address->high = readl(&this_phy->link_layer_registers->source_sas_address_high); + sas_address->low = readl(&this_phy->link_layer_registers->source_sas_address_low); } /** @@ -460,7 +470,10 @@ void scic_sds_phy_get_protocols( struct scic_sds_phy *this_phy, struct sci_sas_identify_address_frame_protocols *protocols) { - protocols->u.all = (u16)(SCU_SAS_TIID_READ(this_phy) & 0x0000FFFF); + protocols->u.all = + (u16)(readl(&this_phy-> + link_layer_registers->transmit_identification) & + 0x0000FFFF); } /** @@ -589,8 +602,8 @@ enum sci_status scic_sas_phy_get_properties( sizeof(struct sci_sas_identify_address_frame) ); - properties->received_capabilities.u.all - = SCU_SAS_RECPHYCAP_READ(sci_phy); + properties->received_capabilities.u.all = + readl(&sci_phy->link_layer_registers->receive_phycap); return SCI_SUCCESS; } @@ -639,9 +652,11 @@ static void scic_sds_phy_start_sas_link_training( { u32 phy_control; - phy_control = SCU_SAS_PCFG_READ(this_phy); + phy_control = + readl(&this_phy->link_layer_registers->phy_configuration); phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); - SCU_SAS_PCFG_WRITE(this_phy, phy_control); + writel(phy_control, + &this_phy->link_layer_registers->phy_configuration); sci_base_state_machine_change_state( &this_phy->starting_substate_machine, @@ -1331,9 +1346,9 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_po { u32 enable_spinup; - enable_spinup = SCU_SAS_ENSPINUP_READ(sci_phy); + enable_spinup = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); - SCU_SAS_ENSPINUP_WRITE(sci_phy, enable_spinup); + writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control); /* Change state to the final state this substate machine has run to completion */ sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, @@ -1357,16 +1372,19 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_p u32 scu_sas_pcfg_value; /* Release the spinup hold state and reset the OOB state machine */ - scu_sas_pcfg_value = SCU_SAS_PCFG_READ(sci_phy); + scu_sas_pcfg_value = + readl(&sci_phy->link_layer_registers->phy_configuration); scu_sas_pcfg_value &= ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - SCU_SAS_PCFG_WRITE(sci_phy, scu_sas_pcfg_value); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); /* Now restart the OOB operation */ scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); - SCU_SAS_PCFG_WRITE(sci_phy, scu_sas_pcfg_value); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); /* Change state to the final state this substate machine has run to completion */ sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, @@ -2120,18 +2138,20 @@ static void scu_link_layer_stop_protocol_engine( u32 enable_spinup_value; /* Suspend the protocol engine and place it in a sata spinup hold state */ - scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + scu_sas_pcfg_value = + readl(&this_phy->link_layer_registers->phy_configuration); scu_sas_pcfg_value |= ( SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) ); - SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + writel(scu_sas_pcfg_value, + &this_phy->link_layer_registers->phy_configuration); /* Disable the notify enable spinup primitives */ - enable_spinup_value = SCU_SAS_ENSPINUP_READ(this_phy); + enable_spinup_value = readl(&this_phy->link_layer_registers->notify_enable_spinup_control); enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE); - SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup_value); + writel(enable_spinup_value, &this_phy->link_layer_registers->notify_enable_spinup_control); } /** @@ -2144,12 +2164,13 @@ static void scu_link_layer_start_oob( { u32 scu_sas_pcfg_value; - scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); + scu_sas_pcfg_value = + readl(&this_phy->link_layer_registers->phy_configuration); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); scu_sas_pcfg_value &= ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); - - SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); + writel(scu_sas_pcfg_value, + &this_phy->link_layer_registers->phy_configuration); } /** @@ -2168,15 +2189,18 @@ static void scu_link_layer_tx_hard_reset( /* * SAS Phys must wait for the HARD_RESET_TX event notification to transition * to the starting state. */ - phy_configuration_value = SCU_SAS_PCFG_READ(this_phy); + phy_configuration_value = + readl(&this_phy->link_layer_registers->phy_configuration); phy_configuration_value |= (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); - SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value); + writel(phy_configuration_value, + &this_phy->link_layer_registers->phy_configuration); /* Now take the OOB state machine out of reset */ phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value); + writel(phy_configuration_value, + &this_phy->link_layer_registers->phy_configuration); } /* diff --git a/drivers/scsi/isci/core/scic_sds_phy_registers.h b/drivers/scsi/isci/core/scic_sds_phy_registers.h deleted file mode 100644 index ddbb2361510d..000000000000 --- a/drivers/scsi/isci/core/scic_sds_phy_registers.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_PHY_REGISTERS_H_ -#define _SCIC_SDS_PHY_REGISTERS_H_ - -/** - * This file contains the macros used by the phy object to read/write to the - * SCU link layer registers. - * - * - */ - -#include "scic_sds_controller.h" - -/* ************************************************************************** - * * SCU TRANSPORT LAYER REGISTER OPERATIONS - * ************************************************************************** */ - -/** - * Macro to read the transport layer register associated with this phy - * object. - */ -#define scu_transport_layer_read(phy, reg) \ - scu_register_read( \ - scic_sds_phy_get_controller(phy), \ - (phy)->transport_layer_registers->reg \ - ) - -/** - * Macro to write the transport layer register associated with this phy - * object. - */ -#define scu_transport_layer_write(phy, reg, value) \ - scu_register_write( \ - scic_sds_phy_get_controller(phy), \ - (phy)->transport_layer_registers->reg, \ - (value) \ - ) - -/* ************************************************************************** - * * Transport Layer registers controlled by the phy object - * ************************************************************************** */ - -/* This macro reads the Transport layer control register */ -#define SCU_TLCR_READ(phy) \ - scu_transport_layer_read(phy, control) - -/* This macro writes the Transport layer control register */ -#define SCU_TLCR_WRITE(phy, value) \ - scu_transport_layer_write(phy, control, value) - -/* This macro reads the Transport layer address translation register */ -#define SCU_TLADTR_READ(phy) \ - scu_transport_layer_read(phy, address_translation) - -/* This macro writes the Transport layer address translation register */ -#define SCU_TLADTR_WRITE(phy) \ - scu_transport_layer_write(phy, address_translation, value) - -/* This macro writes the STP Transport Layer Direct Attached RNi register */ -#define SCU_STPTLDARNI_WRITE(phy, index) \ - scu_transport_layer_write(phy, stp_rni, index) - -/* This macro reads the STP Transport Layer Direct Attached RNi register */ -#define SCU_STPTLDARNI_READ(phy) \ - scu_transport_layer_read(phy, stp_rni) - -/* - * ***************************************************************************** - * * SCU LINK LAYER REGISTER OPERATIONS - * ***************************************************************************** */ - -/** - * scu_link_layer_register_read() - - * - * THis macro requests the SCU register write for the specified link layer - * register. - */ -#define scu_link_layer_register_read(phy, reg) \ - scu_register_read(\ - scic_sds_phy_get_controller(phy), \ - (phy)->link_layer_registers->reg \ - ) - -/** - * scu_link_layer_register_write() - - * - * This macro requests the SCU register read for the specified link layer - * register. - */ -#define scu_link_layer_register_write(phy, reg, value) \ - scu_register_write(\ - scic_sds_phy_get_controller(phy), \ - (phy)->link_layer_registers->reg, \ - (value) \ - ) - -/* - * ***************************************************************************** - * * SCU LINK LAYER REGISTERS - * ***************************************************************************** */ - -/* / This macro reads from the SAS Identify Frame PHY Identifier register */ -#define SCU_SAS_TIPID_READ(phy) \ - scu_link_layer_register_read(phy, identify_frame_phy_id) - -/* / This macro writes to the SAS Identify Frame PHY Identifier register */ -#define SCU_SAS_TIPID_WRITE(phy, value) \ - scu_link_layer_register_write(phy, identify_frame_phy_id, value) - -/* / This macro reads from the SAS Identification register */ -#define SCU_SAS_TIID_READ(phy) \ - scu_link_layer_register_read(phy, transmit_identification) - -/* / This macro writes to the SAS Identification register */ -#define SCU_SAS_TIID_WRITE(phy, value) \ - scu_link_layer_register_write(phy, transmit_identification, value) - -/* / This macro reads the SAS Device Name High register */ -#define SCU_SAS_TIDNH_READ(phy) \ - scu_link_layer_register_read(phy, sas_device_name_high) - -/* / This macro writes the SAS Device Name High register */ -#define SCU_SAS_TIDNH_WRITE(phy, value) \ - scu_link_layer_register_write(phy, sas_device_name_high, value) - -/* / This macro reads the SAS Device Name Low register */ -#define SCU_SAS_TIDNL_READ(phy) \ - scu_link_layer_register_read(phy, sas_device_name_low) - -/* / This macro writes the SAS Device Name Low register */ -#define SCU_SAS_TIDNL_WRITE(phy, value) \ - scu_link_layer_register_write(phy, sas_device_name_low, value) - -/* / This macro reads the Source SAS Address High register */ -#define SCU_SAS_TISSAH_READ(phy) \ - scu_link_layer_register_read(phy, source_sas_address_high) - -/* / This macro writes the Source SAS Address High register */ -#define SCU_SAS_TISSAH_WRITE(phy, value) \ - scu_link_layer_register_write(phy, source_sas_address_high, value) - -/* / This macro reads the Source SAS Address Low register */ -#define SCU_SAS_TISSAL_READ(phy) \ - scu_link_layer_register_read(phy, source_sas_address_low) - -/* / This macro writes the Source SAS Address Low register */ -#define SCU_SAS_TISSAL_WRITE(phy, value) \ - scu_link_layer_register_write(phy, source_sas_address_low, value) - -/* / This macro reads the PHY Configuration register */ -#define SCU_SAS_PCFG_READ(phy) \ - scu_link_layer_register_read(phy, phy_configuration); - -/* / This macro writes the PHY Configuration register */ -#define SCU_SAS_PCFG_WRITE(phy, value) \ - scu_link_layer_register_write(phy, phy_configuration, value) - -/* / This macro reads the PHY Enable Spinup register */ -#define SCU_SAS_ENSPINUP_READ(phy) \ - scu_link_layer_register_read(phy, notify_enable_spinup_control) - -/* / This macro writes the PHY Enable Spinup register */ -#define SCU_SAS_ENSPINUP_WRITE(phy, value) \ - scu_link_layer_register_write(phy, notify_enable_spinup_control, value) - -/* This macro reads the CLKSM register */ -#define SCU_SAS_CLKSM_READ(phy) \ - scu_link_layer_register_read(phy, clock_skew_management) - -/* This macro writes the CLKSM register */ -#define SCU_SAS_CLKSM_WRITE(phy, value) \ - scu_link_layer_register_write(phy, clock_skew_management, value) - -/* / This macro reads the PHY Capacity register */ -#define SCU_SAS_PHYCAP_READ(phy) \ - scu_link_layer_register_read(phy, phy_capabilities) - -/* / This macro writes the PHY Capacity register */ -#define SCU_SAS_PHYCAP_WRITE(phy, value) \ - scu_link_layer_register_write(phy, phy_capabilities, value) - -/* / This macro reads the Recieved PHY Capacity register */ -#define SCU_SAS_RECPHYCAP_READ(phy) \ - scu_link_layer_register_read(phy, receive_phycap) - -/* / This macro reads the link layer control register */ -#define SCU_SAS_LLCTL_READ(phy) \ - scu_link_layer_register_read(phy, link_layer_control); - -/* / This macro writes the link layer control register */ -#define SCU_SAS_LLCTL_WRITE(phy, value) \ - scu_link_layer_register_write(phy, link_layer_control, value); - -#endif /* _SCIC_SDS_PHY_REGISTERS_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 88b892de5de4..8e3983ebc4dc 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -60,14 +60,12 @@ #include "scic_port.h" #include "scic_sds_controller.h" #include "scic_sds_phy.h" -#include "scic_sds_phy_registers.h" #include "scic_sds_port.h" -#include "scic_sds_port_registers.h" #include "scic_sds_remote_device.h" #include "scic_sds_remote_node_context.h" #include "scic_sds_request.h" #include "sci_environment.h" -#include "scic_sds_controller_registers.h" +#include "scu_registers.h" #define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) #define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) @@ -706,7 +704,8 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, sci_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; /* Re-assign the phy back to the LP as if it were a narrow port */ - SCU_PCSPExCR_WRITE(sci_port, sci_phy->phy_index, sci_phy->phy_index); + writel(sci_phy->phy_index, + &sci_port->port_pe_configuration_register[sci_phy->phy_index]); if (do_notify_user == true) isci_port_link_down(ihost, iphy, iport); @@ -969,25 +968,20 @@ static void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port) scic_sds_port_get_sas_address(this_port, &sas_address); - scu_port_viit_register_write( - this_port, initiator_sas_address_hi, sas_address.high); - - scu_port_viit_register_write( - this_port, initiator_sas_address_lo, sas_address.low); + writel(sas_address.high, + &this_port->viit_registers->initiator_sas_address_hi); + writel(sas_address.low, + &this_port->viit_registers->initiator_sas_address_lo); /* This value get cleared just in case its not already cleared */ - scu_port_viit_register_write( - this_port, reserved, 0); + writel(0, &this_port->viit_registers->reserved); /* We are required to update the status register last */ - scu_port_viit_register_write( - this_port, status, ( - SCU_VIIT_ENTRY_ID_VIIT - | SCU_VIIT_IPPT_INITIATOR - | ((1 << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) - | SCU_VIIT_STATUS_ALL_VALID - ) - ); + writel(SCU_VIIT_ENTRY_ID_VIIT | + SCU_VIIT_IPPT_INITIATOR | + ((1 << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) | + SCU_VIIT_STATUS_ALL_VALID, + &this_port->viit_registers->status); } /** @@ -1059,10 +1053,12 @@ void scic_port_enable_broadcast_change_notification( for (index = 0; index < SCI_MAX_PHYS; index++) { phy = port->phy_table[index]; if (phy != NULL) { - register_value = SCU_SAS_LLCTL_READ(phy); + register_value = + readl(&phy->link_layer_registers->link_layer_control); /* clear the bit by writing 1. */ - SCU_SAS_LLCTL_WRITE(phy, register_value); + writel(register_value, + &phy->link_layer_registers->link_layer_control); } } } @@ -1618,16 +1614,14 @@ scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = * * This method will susped the port task scheduler for this port object. none */ -static void scic_sds_port_suspend_port_task_scheduler( - struct scic_sds_port *this_port) +static void +scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port) { u32 pts_control_value; - pts_control_value = scu_port_task_scheduler_read(this_port, control); - + pts_control_value = readl(&port->port_task_scheduler_registers->control); pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND); - - scu_port_task_scheduler_write(this_port, control, pts_control_value); + writel(pts_control_value, &port->port_task_scheduler_registers->control); } /** @@ -1688,16 +1682,14 @@ static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) * * This method will resume the port task scheduler for this port object. none */ -static void scic_sds_port_resume_port_task_scheduler( - struct scic_sds_port *this_port) +static void +scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) { u32 pts_control_value; - pts_control_value = scu_port_task_scheduler_read(this_port, control); - + pts_control_value = readl(&port->port_task_scheduler_registers->control); pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND); - - scu_port_task_scheduler_write(this_port, control, pts_control_value); + writel(pts_control_value, &port->port_task_scheduler_registers->control); } /* @@ -1763,10 +1755,11 @@ static void scic_sds_port_ready_substate_operational_enter( isci_port_ready(ihost, iport); for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) - scic_sds_port_write_phy_assignment( - sci_port, - sci_port->phy_table[index]); + if (sci_port->phy_table[index]) { + writel(sci_port->physical_port_index, + &sci_port->port_pe_configuration_register[ + sci_port->phy_table[index]->phy_index]); + } } scic_sds_port_update_viit_entry(sci_port); @@ -2308,16 +2301,14 @@ scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = * This method will enable the SCU Port Task Scheduler for this port object but * will leave the port task scheduler in a suspended state. none */ -static void scic_sds_port_enable_port_task_scheduler( - struct scic_sds_port *this_port) +static void +scic_sds_port_enable_port_task_scheduler(struct scic_sds_port *port) { u32 pts_control_value; - pts_control_value = scu_port_task_scheduler_read(this_port, control); - + pts_control_value = readl(&port->port_task_scheduler_registers->control); pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND); - - scu_port_task_scheduler_write(this_port, control, pts_control_value); + writel(pts_control_value, &port->port_task_scheduler_registers->control); } /** @@ -2327,17 +2318,15 @@ static void scic_sds_port_enable_port_task_scheduler( * This method will disable the SCU port task scheduler for this port object. * none */ -static void scic_sds_port_disable_port_task_scheduler( - struct scic_sds_port *this_port) +static void +scic_sds_port_disable_port_task_scheduler(struct scic_sds_port *port) { u32 pts_control_value; - pts_control_value = scu_port_task_scheduler_read(this_port, control); - - pts_control_value &= ~(SCU_PTSxCR_GEN_BIT(ENABLE) - | SCU_PTSxCR_GEN_BIT(SUSPEND)); - - scu_port_task_scheduler_write(this_port, control, pts_control_value); + pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value &= + ~(SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND)); + writel(pts_control_value, &port->port_task_scheduler_registers->control); } static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) @@ -2359,7 +2348,7 @@ static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) /* ensure hardware has seen the post rnc command and give it * ample time to act before sending the suspend */ - SMU_ISR_READ(scic); /* flush */ + readl(&scic->smu_registers->interrupt_status); /* flush */ udelay(10); command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX | @@ -2384,7 +2373,7 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci * controller and give it ample time to act before posting the rnc * invalidate */ - SMU_ISR_READ(scic); /* flush */ + readl(&scic->smu_registers->interrupt_status); /* flush */ udelay(10); command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index a5aa9e102242..4cd6bbb0b570 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -289,29 +289,6 @@ static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *s sci_port->started_request_count--; } -/** - * scic_sds_port_write_phy_assignment() - - * - * Helper macro to write the phys port assignment - */ -#define scic_sds_port_write_phy_assignment(port, phy) \ - SCU_PCSPExCR_WRITE(\ - (port), \ - (phy)->phy_index, \ - (port)->physical_port_index \ - ) - -/** - * scic_sds_port_read_phy_assignment() - - * - * Helper macro to read the phys port assignment - */ -#define scic_sds_port_read_phy_assignment(port, phy) \ - SCU_PCSPExCR_READ(\ - (port), \ - (phy)->phy_index \ - ) - #define scic_sds_port_active_phy(port, phy) \ (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) diff --git a/drivers/scsi/isci/core/scic_sds_port_registers.h b/drivers/scsi/isci/core/scic_sds_port_registers.h index dbe82d864eac..01e24e52990c 100644 --- a/drivers/scsi/isci/core/scic_sds_port_registers.h +++ b/drivers/scsi/isci/core/scic_sds_port_registers.h @@ -63,85 +63,4 @@ * */ -/** - * scu_port_task_scheduler_read() - - * - * Macro to read the port task scheduler register associated with this port - * object - */ -#define scu_port_task_scheduler_read(port, reg) \ - scu_register_read(\ - scic_sds_port_get_controller(port), \ - (port)->port_task_scheduler_registers->reg \ - ) - -/** - * scu_port_task_scheduler_write() - - * - * Macro to write the port task scheduler register associated with this port - * object - */ -#define scu_port_task_scheduler_write(port, reg, value) \ - scu_register_write(\ - scic_sds_port_get_controller(port), \ - (port)->port_task_scheduler_registers->reg, \ - (value) \ - ) - -#define scu_port_viit_register_write(port, reg, value) \ - scu_register_write(\ - scic_sds_port_get_controller(port), \ - (port)->viit_registers->reg, \ - (value) \ - ) - -/* - * **************************************************************************** - * * Port Task Scheduler registers controlled by the port object - * **************************************************************************** */ - -/** - * SCU_PTSxCR_READ() - - * - * Macro to read the port task scheduler control register - */ -#define SCU_PTSxCR_READ(port) \ - scu_port_task_scheduler_read(port, control) - -/** - * SCU_PTSxCR_WRITE() - - * - * Macro to write the port task scheduler control regsister - */ -#define SCU_PTSxCR_WRITE(port, value) \ - scu_port_task_scheduler_write(port, control, value) - -/* - * **************************************************************************** - * * Port PE Configuration registers - * **************************************************************************** */ - -/** - * SCU_PCSPExCR_WRITE() - - * - * Macro to write the PE Port Configuration Register - */ -#define SCU_PCSPExCR_WRITE(port, phy_id, value) \ - scu_register_write(\ - scic_sds_port_get_controller(port), \ - (port)->port_pe_configuration_register[phy_id], \ - (value) \ - ) - -/** - * SCU_PCSPExCR_READ() - - * - * Macro to read the PE Port Configuration Regsiter - */ -#define SCU_PCSPExCR_READ(port, phy_id) \ - scu_register_read(\ - scic_sds_port_get_controller(port), \ - (port)->port_pe_configuration_register[phy_id] \ - ) - #endif /* _SCIC_SDS_PORT_REGISTERS_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 45b8571726f7..d0cbb97b63a7 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -62,8 +62,7 @@ #include "scic_io_request.h" #include "scic_remote_device.h" #include "scic_sds_controller.h" -#include "scic_sds_controller_registers.h" -#include "scic_sds_pci.h" +#include "scu_registers.h" #include "scic_sds_port.h" #include "scic_sds_remote_device.h" #include "scic_sds_request.h" @@ -862,20 +861,16 @@ u32 scic_io_request_get_number_of_bytes_transferred( { u32 ret_val = 0; - if (SMU_AMR_READ(scic_sds_request->owning_controller) == 0) { + if (readl(&scic_sds_request->owning_controller->smu_registers->address_modifier) == 0) { /* * get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where * BAR1 is the scu_registers * 0x20002C = 0x200000 + 0x2c * = start of task context SRAM + offset of (type.ssp.data_offset) * TCi is the io_tag of struct scic_sds_request */ - ret_val = scic_sds_pci_read_scu_dword( - scic_sds_request->owning_controller, - ( - (u8 *)scic_sds_request->owning_controller->scu_registers + + ret_val = readl((u8 *)scic_sds_request->owning_controller->scu_registers + (SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(struct scu_task_context, type.ssp.data_offset)) + ((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(scic_sds_request->io_tag)) - ) ); } diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c index 66be58b002d9..31a3516ddebe 100644 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c @@ -315,10 +315,7 @@ enum sci_status scic_sds_unsolicited_frame_control_get_buffer( * @frame_index: This parameter specifies the frame index to attempt to release. * * This method returns an indication to the caller as to whether the - * unsolicited frame get pointer should be updated. true This value indicates - * the unsolicited frame get pointer should be updated (i.e. write - * SCU_UFQGP_WRITE). false This value indicates the get pointer should not be - * updated. + * unsolicited frame get pointer should be updated. */ bool scic_sds_unsolicited_frame_control_release_frame( struct scic_sds_unsolicited_frame_control *uf_control, -- cgit v1.2.3 From ca841f0e862bccd61f537b76c94579c1bd391448 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 28 Mar 2011 09:21:04 -0400 Subject: isci: remove base_controller abstraction Merge struct sci_base_controller into scic_sds_controller, and also factor the two types of state machine handlers into one function. While we're at it also remove lots of duplicate incorrect kerneldoc comments for the state machine handlers. Signed-off-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_controller.h | 304 ---------------- drivers/scsi/isci/core/sci_controller.h | 29 -- drivers/scsi/isci/core/scic_sds_controller.c | 438 +++++++++--------------- drivers/scsi/isci/core/scic_sds_controller.h | 198 ++++++++++- drivers/scsi/isci/core/scic_sds_remote_device.c | 9 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 16 +- drivers/scsi/isci/host.c | 6 +- drivers/scsi/isci/isci.h | 2 +- 8 files changed, 364 insertions(+), 638 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_base_controller.h diff --git a/drivers/scsi/isci/core/sci_base_controller.h b/drivers/scsi/isci/core/sci_base_controller.h deleted file mode 100644 index 8e0c46f8b221..000000000000 --- a/drivers/scsi/isci/core/sci_base_controller.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_CONTROLLER_H_ -#define _SCI_BASE_CONTROLLER_H_ - -#include "intel_sas.h" -#include "sci_controller_constants.h" -#include "sci_base_state.h" -#include "sci_base_memory_descriptor_list.h" -#include "sci_base_state_machine.h" -#include "sci_object.h" - -struct sci_base_memory_descriptor_list; - -/** - * enum sci_base_controller_states - This enumeration depicts all the states - * for the common controller state machine. - * - * - */ -enum sci_base_controller_states { - /** - * Simply the initial state for the base controller state machine. - */ - SCI_BASE_CONTROLLER_STATE_INITIAL = 0, - - /** - * This state indicates that the controller is reset. The memory for - * the controller is in it's initial state, but the controller requires - * initialization. - * This state is entered from the INITIAL state. - * This state is entered from the RESETTING state. - */ - SCI_BASE_CONTROLLER_STATE_RESET, - - /** - * This state is typically an action state that indicates the controller - * is in the process of initialization. In this state no new IO operations - * are permitted. - * This state is entered from the RESET state. - */ - SCI_BASE_CONTROLLER_STATE_INITIALIZING, - - /** - * This state indicates that the controller has been successfully - * initialized. In this state no new IO operations are permitted. - * This state is entered from the INITIALIZING state. - */ - SCI_BASE_CONTROLLER_STATE_INITIALIZED, - - /** - * This state indicates the the controller is in the process of becoming - * ready (i.e. starting). In this state no new IO operations are permitted. - * This state is entered from the INITIALIZED state. - */ - SCI_BASE_CONTROLLER_STATE_STARTING, - - /** - * This state indicates the controller is now ready. Thus, the user - * is able to perform IO operations on the controller. - * This state is entered from the STARTING state. - */ - SCI_BASE_CONTROLLER_STATE_READY, - - /** - * This state is typically an action state that indicates the controller - * is in the process of resetting. Thus, the user is unable to perform - * IO operations on the controller. A reset is considered destructive in - * most cases. - * This state is entered from the READY state. - * This state is entered from the FAILED state. - * This state is entered from the STOPPED state. - */ - SCI_BASE_CONTROLLER_STATE_RESETTING, - - /** - * This state indicates that the controller is in the process of stopping. - * In this state no new IO operations are permitted, but existing IO - * operations are allowed to complete. - * This state is entered from the READY state. - */ - SCI_BASE_CONTROLLER_STATE_STOPPING, - - /** - * This state indicates that the controller has successfully been stopped. - * In this state no new IO operations are permitted. - * This state is entered from the STOPPING state. - */ - SCI_BASE_CONTROLLER_STATE_STOPPED, - - /** - * This state indicates that the controller could not successfully be - * initialized. In this state no new IO operations are permitted. - * This state is entered from the INITIALIZING state. - * This state is entered from the STARTING state. - * This state is entered from the STOPPING state. - * This state is entered from the RESETTING state. - */ - SCI_BASE_CONTROLLER_STATE_FAILED, - - SCI_BASE_CONTROLLER_MAX_STATES - -}; - -/** - * struct sci_base_controller - The base controller object abstracts the fields - * common to all SCI controller objects. - * - * - */ -struct sci_base_controller { - /** - * The field specifies that the parent object for the base controller - * is the base object itself. - */ - struct sci_base_object parent; - - /** - * This field points to the memory descriptor list associated with this - * controller. The MDL indicates the memory requirements necessary for - * this controller object. - */ - struct sci_base_memory_descriptor_list mdl; - - /** - * This field contains the information for the base controller state - * machine. - */ - struct sci_base_state_machine state_machine; -}; - -/* Forward declarations */ -struct sci_base_remote_device; -struct sci_base_request; - -typedef enum sci_status -(*sci_base_controller_handler_t)(struct sci_base_controller *); - -typedef enum sci_status -(*sci_base_controller_timed_handler_t)(struct sci_base_controller *, u32); - -typedef enum sci_status -(*sci_base_controller_request_handler_t)(struct sci_base_controller *, - struct sci_base_remote_device *, - struct sci_base_request *); - -typedef enum sci_status -(*sci_base_controller_start_request_handler_t)(struct sci_base_controller *, - struct sci_base_remote_device *, - struct sci_base_request *, u16); - -/** - * struct sci_base_controller_state_handler - This structure contains all of - * the state handler methods common to base controller state machines. - * Handler methods provide the ability to change the behavior for user - * requests or transitions depending on the state the machine is in. - * - * - */ -struct sci_base_controller_state_handler { - /** - * The start_handler specifies the method invoked when a user attempts to - * start a controller. - */ - sci_base_controller_timed_handler_t start; - - /** - * The stop_handler specifies the method invoked when a user attempts to - * stop a controller. - */ - sci_base_controller_timed_handler_t stop; - - /** - * The reset_handler specifies the method invoked when a user attempts to - * reset a controller. - */ - sci_base_controller_handler_t reset; - - /** - * The initialize_handler specifies the method invoked when a user - * attempts to initialize a controller. - */ - sci_base_controller_handler_t initialize; - - /** - * The start_io_handler specifies the method invoked when a user - * attempts to start an IO request for a controller. - */ - sci_base_controller_start_request_handler_t start_io; - - /** - * The complete_io_handler specifies the method invoked when a user - * attempts to complete an IO request for a controller. - */ - sci_base_controller_request_handler_t complete_io; - - /** - * The continue_io_handler specifies the method invoked when a user - * attempts to continue an IO request for a controller. - */ - sci_base_controller_request_handler_t continue_io; - - /** - * The start_task_handler specifies the method invoked when a user - * attempts to start a task management request for a controller. - */ - sci_base_controller_start_request_handler_t start_task; - - /** - * The complete_task_handler specifies the method invoked when a user - * attempts to complete a task management request for a controller. - */ - sci_base_controller_request_handler_t complete_task; - -}; - -/** - * sci_base_controller_construct() - Construct the base controller - * @this_controller: This parameter specifies the base controller to be - * constructed. - * @state_table: This parameter specifies the table of state definitions to be - * utilized for the controller state machine. - * @mde_array: This parameter specifies the array of memory descriptor entries - * to be managed by this list. - * @mde_array_length: This parameter specifies the size of the array of entries. - * @next_mdl: This parameter specifies a subsequent MDL object to be managed by - * this MDL object. - * @oem_parameters: This parameter specifies the original equipment - * manufacturer parameters to be utilized by this controller object. - * - */ -static inline void sci_base_controller_construct( - struct sci_base_controller *scic_base, - const struct sci_base_state *state_table, - struct sci_physical_memory_descriptor *mdes, - u32 mde_count, - struct sci_base_memory_descriptor_list *next_mdl) -{ - sci_base_state_machine_construct( - &scic_base->state_machine, - &scic_base->parent, - state_table, - SCI_BASE_CONTROLLER_STATE_INITIAL - ); - - sci_base_mdl_construct(&scic_base->mdl, mdes, mde_count, next_mdl); - - sci_base_state_machine_start(&scic_base->state_machine); -} - -#endif /* _SCI_BASE_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/sci_controller.h b/drivers/scsi/isci/core/sci_controller.h index 5c7774e75ddf..01316b1a8f27 100644 --- a/drivers/scsi/isci/core/sci_controller.h +++ b/drivers/scsi/isci/core/sci_controller.h @@ -63,36 +63,7 @@ * */ - -struct sci_base_memory_descriptor_list; -struct scic_sds_controller; - #define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF -/** - * sci_controller_get_memory_descriptor_list_handle() - This method simply - * returns a handle for the memory descriptor list associated with the - * supplied controller. The descriptor list provides DMA safe/capable - * memory requirements for this controller. - * @controller: This parameter specifies the controller for which to retrieve - * the DMA safe memory descriptor list. - * - * The user must adhere to the alignment requirements specified in memory - * descriptor. In situations where the operating environment does not offer - * memory allocation utilities supporting alignment, then it is the - * responsibility of the user to manually align the memory buffer for SCI. - * Thus, the user may have to allocate a larger buffer to meet the alignment. - * Additionally, the user will need to remember the actual memory allocation - * addresses in order to ensure the memory can be properly freed when necessary - * to do so. This method will return a valid handle, but the MDL may not be - * accurate until after the user has invoked the associated - * sci_controller_initialize() routine. A pointer to a physical memory - * descriptor array. - */ -struct sci_base_memory_descriptor_list * - sci_controller_get_memory_descriptor_list_handle( - struct scic_sds_controller *controller); - - #endif /* _SCI_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 774c4b3b0dfb..e7790bb7dfdd 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -212,12 +212,6 @@ static void scic_sds_controller_power_control_timer_handler( SMU_CQGR_EVENT_CYCLE_BIT \ ) -struct sci_base_memory_descriptor_list * -sci_controller_get_memory_descriptor_list_handle(struct scic_sds_controller *scic) -{ - return &scic->parent.mdl; -} - static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) { struct isci_host *ihost = sci_object_get_association(scic); @@ -688,13 +682,13 @@ static void scic_sds_controller_transition_to_ready( { struct isci_host *ihost = sci_object_get_association(scic); - if (scic->parent.state_machine.current_state_id == - SCI_BASE_CONTROLLER_STATE_STARTING) { + if (scic->state_machine.current_state_id == + SCI_BASE_CONTROLLER_STATE_STARTING) { /* * We move into the ready state, because some of the phys/ports * may be up and operational. */ - sci_base_state_machine_change_state(&scic->parent.state_machine, + sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_READY); isci_host_start_complete(ihost, status); @@ -705,7 +699,7 @@ static void scic_sds_controller_timeout_handler(void *_scic) { struct scic_sds_controller *scic = _scic; struct isci_host *ihost = sci_object_get_association(scic); - struct sci_base_state_machine *sm = &scic->parent.state_machine; + struct sci_base_state_machine *sm = &scic->state_machine; if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT); @@ -1549,7 +1543,7 @@ void scic_sds_controller_error_handler(struct scic_sds_controller *scic) dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, interrupt_status); - sci_base_state_machine_change_state(&scic->parent.state_machine, + sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_FAILED); return; @@ -1572,7 +1566,7 @@ void scic_sds_controller_link_up( scic_sds_controller_phy_handler_t link_up; u32 state; - state = scic->parent.state_machine.current_state_id; + state = scic->state_machine.current_state_id; link_up = scic_sds_controller_state_handler_table[state].link_up; if (link_up) @@ -1593,7 +1587,7 @@ void scic_sds_controller_link_down( u32 state; scic_sds_controller_phy_handler_t link_down; - state = scic->parent.state_machine.current_state_id; + state = scic->state_machine.current_state_id; link_down = scic_sds_controller_state_handler_table[state].link_down; if (link_down) @@ -1639,7 +1633,7 @@ void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, u32 state; scic_sds_controller_device_handler_t stopped; - state = scic->parent.state_machine.current_state_id; + state = scic->state_machine.current_state_id; stopped = scic_sds_controller_state_handler_table[state].device_stopped; if (stopped) @@ -1969,14 +1963,14 @@ enum sci_status scic_controller_initialize( struct scic_sds_controller *scic) { enum sci_status status = SCI_FAILURE_INVALID_STATE; - sci_base_controller_handler_t initialize; + scic_sds_controller_handler_t initialize; u32 state; - state = scic->parent.state_machine.current_state_id; - initialize = scic_sds_controller_state_handler_table[state].base.initialize; + state = scic->state_machine.current_state_id; + initialize = scic_sds_controller_state_handler_table[state].initialize; if (initialize) - status = initialize(&scic->parent); + status = initialize(scic); else dev_warn(scic_to_dev(scic), "%s: SCIC Controller initialize operation requested " @@ -2050,14 +2044,14 @@ enum sci_status scic_controller_start( u32 timeout) { enum sci_status status = SCI_FAILURE_INVALID_STATE; - sci_base_controller_timed_handler_t start; + scic_sds_controller_timed_handler_t start; u32 state; - state = scic->parent.state_machine.current_state_id; - start = scic_sds_controller_state_handler_table[state].base.start; + state = scic->state_machine.current_state_id; + start = scic_sds_controller_state_handler_table[state].start; if (start) - status = start(&scic->parent, timeout); + status = start(scic, timeout); else dev_warn(scic_to_dev(scic), "%s: SCIC Controller start operation requested in " @@ -2089,14 +2083,14 @@ enum sci_status scic_controller_stop( u32 timeout) { enum sci_status status = SCI_FAILURE_INVALID_STATE; - sci_base_controller_timed_handler_t stop; + scic_sds_controller_timed_handler_t stop; u32 state; - state = scic->parent.state_machine.current_state_id; - stop = scic_sds_controller_state_handler_table[state].base.stop; + state = scic->state_machine.current_state_id; + stop = scic_sds_controller_state_handler_table[state].stop; if (stop) - status = stop(&scic->parent, timeout); + status = stop(scic, timeout); else dev_warn(scic_to_dev(scic), "%s: SCIC Controller stop operation requested in " @@ -2121,14 +2115,14 @@ enum sci_status scic_controller_reset( struct scic_sds_controller *scic) { enum sci_status status = SCI_FAILURE_INVALID_STATE; - sci_base_controller_handler_t reset; + scic_sds_controller_handler_t reset; u32 state; - state = scic->parent.state_machine.current_state_id; - reset = scic_sds_controller_state_handler_table[state].base.reset; + state = scic->state_machine.current_state_id; + reset = scic_sds_controller_state_handler_table[state].reset; if (reset) - status = reset(&scic->parent); + status = reset(scic); else dev_warn(scic_to_dev(scic), "%s: SCIC Controller reset operation requested in " @@ -2171,12 +2165,12 @@ enum sci_io_status scic_controller_start_io( u16 io_tag) { u32 state; - sci_base_controller_start_request_handler_t start_io; + scic_sds_controller_start_request_handler_t start_io; - state = scic->parent.state_machine.current_state_id; - start_io = scic_sds_controller_state_handler_table[state].base.start_io; + state = scic->state_machine.current_state_id; + start_io = scic_sds_controller_state_handler_table[state].start_io; - return start_io(&scic->parent, + return start_io(scic, (struct sci_base_remote_device *) remote_device, (struct sci_base_request *)io_request, io_tag); } @@ -2202,13 +2196,13 @@ enum sci_status scic_controller_terminate_request( struct scic_sds_remote_device *remote_device, struct scic_sds_request *request) { - sci_base_controller_request_handler_t terminate_request; + scic_sds_controller_request_handler_t terminate_request; u32 state; - state = scic->parent.state_machine.current_state_id; + state = scic->state_machine.current_state_id; terminate_request = scic_sds_controller_state_handler_table[state].terminate_request; - return terminate_request(&scic->parent, + return terminate_request(scic, (struct sci_base_remote_device *)remote_device, (struct sci_base_request *)request); } @@ -2241,12 +2235,12 @@ enum sci_status scic_controller_complete_io( struct scic_sds_request *io_request) { u32 state; - sci_base_controller_request_handler_t complete_io; + scic_sds_controller_request_handler_t complete_io; - state = scic->parent.state_machine.current_state_id; - complete_io = scic_sds_controller_state_handler_table[state].base.complete_io; + state = scic->state_machine.current_state_id; + complete_io = scic_sds_controller_state_handler_table[state].complete_io; - return complete_io(&scic->parent, + return complete_io(scic, (struct sci_base_remote_device *)remote_device, (struct sci_base_request *)io_request); } @@ -2286,14 +2280,14 @@ enum sci_task_status scic_controller_start_task( u16 task_tag) { u32 state; - sci_base_controller_start_request_handler_t start_task; + scic_sds_controller_start_request_handler_t start_task; enum sci_task_status status = SCI_TASK_FAILURE_INVALID_STATE; - state = scic->parent.state_machine.current_state_id; - start_task = scic_sds_controller_state_handler_table[state].base.start_task; + state = scic->state_machine.current_state_id; + start_task = scic_sds_controller_state_handler_table[state].start_task; if (start_task) - status = start_task(&scic->parent, + status = start_task(scic, (struct sci_base_remote_device *)remote_device, (struct sci_base_request *)task_request, task_tag); @@ -2326,14 +2320,14 @@ enum sci_status scic_controller_complete_task( struct scic_sds_request *task_request) { u32 state; - sci_base_controller_request_handler_t complete_task; + scic_sds_controller_request_handler_t complete_task; enum sci_status status = SCI_FAILURE_INVALID_STATE; - state = scic->parent.state_machine.current_state_id; - complete_task = scic_sds_controller_state_handler_table[state].base.complete_task; + state = scic->state_machine.current_state_id; + complete_task = scic_sds_controller_state_handler_table[state].complete_task; if (complete_task) - status = complete_task(&scic->parent, + status = complete_task(scic, (struct sci_base_remote_device *)remote_device, (struct sci_base_request *)task_request); else @@ -2518,9 +2512,9 @@ static enum sci_status scic_controller_set_mode( { enum sci_status status = SCI_SUCCESS; - if ((scic->parent.state_machine.current_state_id == + if ((scic->state_machine.current_state_id == SCI_BASE_CONTROLLER_STATE_INITIALIZING) || - (scic->parent.state_machine.current_state_id == + (scic->state_machine.current_state_id == SCI_BASE_CONTROLLER_STATE_INITIALIZED)) { switch (operating_mode) { case SCI_MODE_SPEED: @@ -2583,7 +2577,7 @@ enum sci_status scic_user_parameters_set( struct scic_sds_controller *scic, union scic_user_parameters *scic_parms) { - u32 state = scic->parent.state_machine.current_state_id; + u32 state = scic->state_machine.current_state_id; if (state == SCI_BASE_CONTROLLER_STATE_RESET || state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || @@ -2637,7 +2631,7 @@ enum sci_status scic_oem_parameters_set( struct scic_sds_controller *scic, union scic_oem_parameters *scic_parms) { - u32 state = scic->parent.state_machine.current_state_id; + u32 state = scic->state_machine.current_state_id; if (state == SCI_BASE_CONTROLLER_STATE_RESET || state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || @@ -2819,54 +2813,52 @@ struct scic_sds_controller *scic_controller_alloc(struct device *dev) return devm_kzalloc(dev, sizeof(struct scic_sds_controller), GFP_KERNEL); } -static enum sci_status default_controller_handler(struct sci_base_controller *base_scic, - const char *func) +static enum sci_status +default_controller_handler(struct scic_sds_controller *scic, const char *func) { - struct scic_sds_controller *scic = container_of(base_scic, typeof(*scic), parent); - u32 state = base_scic->state_machine.current_state_id; - - dev_warn(scic_to_dev(scic), "%s: invalid state %d\n", func, state); + dev_warn(scic_to_dev(scic), "%s: invalid state %d\n", func, + scic->state_machine.current_state_id); return SCI_FAILURE_INVALID_STATE; } static enum sci_status scic_sds_controller_default_start_operation_handler( - struct sci_base_controller *base_scic, + struct scic_sds_controller *scic, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request, u16 io_tag) { - return default_controller_handler(base_scic, __func__); + return default_controller_handler(scic, __func__); } static enum sci_status scic_sds_controller_default_request_handler( - struct sci_base_controller *base_scic, + struct scic_sds_controller *scic, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request) { - return default_controller_handler(base_scic, __func__); + return default_controller_handler(scic, __func__); } -static enum sci_status scic_sds_controller_general_reset_handler(struct sci_base_controller *base_scic) +static enum sci_status +scic_sds_controller_general_reset_handler(struct scic_sds_controller *scic) { /* The reset operation is not a graceful cleanup just perform the state * transition. */ - sci_base_state_machine_change_state(&base_scic->state_machine, + sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_RESETTING); return SCI_SUCCESS; } -static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct sci_base_controller *base_scic) +static enum sci_status +scic_sds_controller_reset_state_initialize_handler(struct scic_sds_controller *scic) { - struct sci_base_state_machine *sm = &base_scic->state_machine; + struct sci_base_state_machine *sm = &scic->state_machine; enum sci_status result = SCI_SUCCESS; - struct scic_sds_controller *scic; struct isci_host *ihost; u32 index, state; - scic = container_of(base_scic, typeof(*scic), parent); ihost = sci_object_get_association(scic); sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); @@ -3028,13 +3020,7 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct * * INITIALIZED STATE HANDLERS * ***************************************************************************** */ -/** - * - * @controller: This is the struct sci_base_controller object which is cast - * into a struct scic_sds_controller object. - * @timeout: This is the allowed time for the controller object to reach the - * started state. - * +/* * This function is the struct scic_sds_controller start handler for the * initialized state. * - Validate we have a good memory descriptor table - Initialze the @@ -3049,14 +3035,10 @@ static enum sci_status scic_sds_controller_reset_state_initialize_handler(struct * descriptor fields is invalid. */ static enum sci_status scic_sds_controller_initialized_state_start_handler( - struct sci_base_controller *base_scic, - u32 timeout) + struct scic_sds_controller *scic, u32 timeout) { u16 index; enum sci_status result; - struct scic_sds_controller *scic; - - scic = container_of(base_scic, typeof(*scic), parent); /* * Make sure that the SCI User filled in the memory descriptor @@ -3119,7 +3101,7 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( isci_timer_start(scic->timeout_timer, timeout); - sci_base_state_machine_change_state(&base_scic->state_machine, + sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_STARTING); } @@ -3180,79 +3162,54 @@ static void scic_sds_controller_starting_state_link_down_handler( /* scic_sds_port_link_down(port, phy); */ } -static enum sci_status scic_sds_controller_ready_state_stop_handler(struct sci_base_controller *base_scic, - u32 timeout) +static enum sci_status scic_sds_controller_ready_state_stop_handler( + struct scic_sds_controller *scic, + u32 timeout) { - struct scic_sds_controller *scic; - - scic = container_of(base_scic, typeof(*scic), parent); isci_timer_start(scic->timeout_timer, timeout); - sci_base_state_machine_change_state(&base_scic->state_machine, + sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_STOPPING); - return SCI_SUCCESS; } -/** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device object. - * @io_request: This is the struct sci_base_request which is cast to a - * SCIC_SDS_IO_REQUEST object. - * @io_tag: This is the IO tag to be assigned to the IO request or - * SCI_CONTROLLER_INVALID_IO_TAG. - * +/* * This method is called when the struct scic_sds_controller is in the ready state and * the start io handler is called. - Start the io request on the remote device * - if successful - assign the io_request to the io_request_table - post the * request to the hardware enum sci_status SCI_SUCCESS if the start io operation * succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be * allocated for the io request. SCI_FAILURE_INVALID_STATE if one or more - * objects are not in a valid state to accept io requests. How does the io_tag - * parameter get assigned to the io request? + * objects are not in a valid state to accept io requests. + * + * XXX: How does the io_tag parameter get assigned to the io request? */ static enum sci_status scic_sds_controller_ready_state_start_io_handler( - struct sci_base_controller *controller, + struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request, u16 io_tag) { enum sci_status status; - struct scic_sds_controller *this_controller; struct scic_sds_request *the_request; struct scic_sds_remote_device *the_device; - this_controller = (struct scic_sds_controller *)controller; the_request = (struct scic_sds_request *)io_request; the_device = (struct scic_sds_remote_device *)remote_device; - status = scic_sds_remote_device_start_io(this_controller, the_device, the_request); - - if (status == SCI_SUCCESS) { - this_controller->io_request_table[ - scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + status = scic_sds_remote_device_start_io(controller, the_device, the_request); - scic_sds_controller_post_request( - this_controller, - scic_sds_request_get_post_context(the_request) - ); - } + if (status != SCI_SUCCESS) + return status; - return status; + controller->io_request_table[ + scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + scic_sds_controller_post_request(controller, + scic_sds_request_get_post_context(the_request)); + return SCI_SUCCESS; } -/** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device object. - * @io_request: This is the struct sci_base_request which is cast to a - * SCIC_SDS_IO_REQUEST object. - * +/* * This method is called when the struct scic_sds_controller is in the ready state and * the complete io handler is called. - Complete the io request on the remote * device - if successful - remove the io_request to the io_request_table @@ -3261,76 +3218,49 @@ static enum sci_status scic_sds_controller_ready_state_start_io_handler( * accept io requests. */ static enum sci_status scic_sds_controller_ready_state_complete_io_handler( - struct sci_base_controller *controller, + struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request) { u16 index; enum sci_status status; - struct scic_sds_controller *this_controller; struct scic_sds_request *the_request; struct scic_sds_remote_device *the_device; - this_controller = (struct scic_sds_controller *)controller; the_request = (struct scic_sds_request *)io_request; the_device = (struct scic_sds_remote_device *)remote_device; - status = scic_sds_remote_device_complete_io( - this_controller, the_device, the_request); - - if (status == SCI_SUCCESS) { - index = scic_sds_io_tag_get_index(the_request->io_tag); - this_controller->io_request_table[index] = NULL; - } + status = scic_sds_remote_device_complete_io(controller, the_device, + the_request); + if (status != SCI_SUCCESS) + return status; - return status; + index = scic_sds_io_tag_get_index(the_request->io_tag); + controller->io_request_table[index] = NULL; + return SCI_SUCCESS; } -/** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device object. - * @io_request: This is the struct sci_base_request which is cast to a - * SCIC_SDS_IO_REQUEST object. - * +/* * This method is called when the struct scic_sds_controller is in the ready state and * the continue io handler is called. enum sci_status */ static enum sci_status scic_sds_controller_ready_state_continue_io_handler( - struct sci_base_controller *controller, + struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request) { - struct scic_sds_controller *this_controller; struct scic_sds_request *the_request; the_request = (struct scic_sds_request *)io_request; - this_controller = (struct scic_sds_controller *)controller; - this_controller->io_request_table[ + controller->io_request_table[ scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; - - scic_sds_controller_post_request( - this_controller, - scic_sds_request_get_post_context(the_request) - ); - + scic_sds_controller_post_request(controller, + scic_sds_request_get_post_context(the_request)); return SCI_SUCCESS; } -/** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device object. - * @io_request: This is the struct sci_base_request which is cast to a - * SCIC_SDS_IO_REQUEST object. - * @task_tag: This is the task tag to be assigned to the task request or - * SCI_CONTROLLER_INVALID_IO_TAG. - * +/* * This method is called when the struct scic_sds_controller is in the ready state and * the start task handler is called. - The remote device is requested to start * the task request - if successful - assign the task to the io_request_table - @@ -3341,33 +3271,28 @@ static enum sci_status scic_sds_controller_ready_state_continue_io_handler( * tag get assigned in this code path? */ static enum sci_status scic_sds_controller_ready_state_start_task_handler( - struct sci_base_controller *controller, + struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request, u16 task_tag) { - struct scic_sds_controller *this_controller = (struct scic_sds_controller *) - controller; struct scic_sds_request *the_request = (struct scic_sds_request *) io_request; struct scic_sds_remote_device *the_device = (struct scic_sds_remote_device *) remote_device; enum sci_status status; - status = scic_sds_remote_device_start_task( - this_controller, the_device, the_request - ); + status = scic_sds_remote_device_start_task(controller, the_device, + the_request); if (status == SCI_SUCCESS) { - this_controller->io_request_table[ + controller->io_request_table[ scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; - scic_sds_controller_post_request( - this_controller, - scic_sds_request_get_post_context(the_request) - ); + scic_sds_controller_post_request(controller, + scic_sds_request_get_post_context(the_request)); } else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS) { - this_controller->io_request_table[ + controller->io_request_table[ scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; /* @@ -3379,15 +3304,7 @@ static enum sci_status scic_sds_controller_ready_state_start_task_handler( return status; } -/** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device object. - * @io_request: This is the struct sci_base_request which is cast to a - * SCIC_SDS_IO_REQUEST object. - * +/* * This method is called when the struct scic_sds_controller is in the ready state and * the terminate request handler is called. - call the io request terminate * function - if successful - post the terminate request to the SCU hardware @@ -3396,29 +3313,26 @@ static enum sci_status scic_sds_controller_ready_state_start_task_handler( * accept io requests. */ static enum sci_status scic_sds_controller_ready_state_terminate_request_handler( - struct sci_base_controller *controller, + struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request) { - struct scic_sds_controller *this_controller = (struct scic_sds_controller *) - controller; struct scic_sds_request *the_request = (struct scic_sds_request *) io_request; enum sci_status status; status = scic_sds_io_request_terminate(the_request); - if (status == SCI_SUCCESS) { - /* - * Utilize the original post context command and or in the POST_TC_ABORT - * request sub-type. */ - scic_sds_controller_post_request( - this_controller, - scic_sds_request_get_post_context(the_request) - | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT - ); - } + if (status != SCI_SUCCESS) + return status; - return status; + /* + * Utilize the original post context command and or in the POST_TC_ABORT + * request sub-type. + */ + scic_sds_controller_post_request(controller, + scic_sds_request_get_post_context(the_request) | + SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); + return SCI_SUCCESS; } /** @@ -3470,38 +3384,20 @@ static void scic_sds_controller_ready_state_link_down_handler( * ***************************************************************************** */ /** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device object. - * @io_request: This is the struct sci_base_request which is cast to a - * SCIC_SDS_IO_REQUEST object. - * * This method is called when the struct scic_sds_controller is in a stopping state * and the complete io handler is called. - This function is not yet * implemented enum sci_status SCI_FAILURE */ static enum sci_status scic_sds_controller_stopping_state_complete_io_handler( - struct sci_base_controller *controller, + struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, struct sci_base_request *io_request) { - struct scic_sds_controller *this_controller; - - this_controller = (struct scic_sds_controller *)controller; - - /* / @todo Implement this function */ + /* XXX: Implement this function */ return SCI_FAILURE; } /** - * - * @controller: This is struct sci_base_controller object which is cast into a - * struct scic_sds_controller object. - * @remote_device: This is struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device object. - * * This method is called when the struct scic_sds_controller is in a stopping state * and the remote device has stopped. **/ @@ -3511,8 +3407,7 @@ static void scic_sds_controller_stopping_state_device_stopped_handler( ) { if (!scic_sds_controller_has_remote_devices_stopping(controller)) { - sci_base_state_machine_change_state( - &controller->parent.state_machine, + sci_base_state_machine_change_state(&controller->state_machine, SCI_BASE_CONTROLLER_STATE_STOPPED ); } @@ -3520,77 +3415,77 @@ static void scic_sds_controller_stopping_state_device_stopped_handler( const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[] = { [SCI_BASE_CONTROLLER_STATE_INITIAL] = { - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_default_request_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_default_request_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, }, [SCI_BASE_CONTROLLER_STATE_RESET] = { - .base.reset = scic_sds_controller_general_reset_handler, - .base.initialize = scic_sds_controller_reset_state_initialize_handler, - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_default_request_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .reset = scic_sds_controller_general_reset_handler, + .initialize = scic_sds_controller_reset_state_initialize_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_default_request_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, }, [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = { - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_default_request_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_default_request_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, }, [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = { - .base.start = scic_sds_controller_initialized_state_start_handler, - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_default_request_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .start = scic_sds_controller_initialized_state_start_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_default_request_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, }, [SCI_BASE_CONTROLLER_STATE_STARTING] = { - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_default_request_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_default_request_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, .link_up = scic_sds_controller_starting_state_link_up_handler, .link_down = scic_sds_controller_starting_state_link_down_handler }, [SCI_BASE_CONTROLLER_STATE_READY] = { - .base.stop = scic_sds_controller_ready_state_stop_handler, - .base.reset = scic_sds_controller_general_reset_handler, - .base.start_io = scic_sds_controller_ready_state_start_io_handler, - .base.complete_io = scic_sds_controller_ready_state_complete_io_handler, - .base.continue_io = scic_sds_controller_ready_state_continue_io_handler, - .base.start_task = scic_sds_controller_ready_state_start_task_handler, - .base.complete_task = scic_sds_controller_ready_state_complete_io_handler, + .stop = scic_sds_controller_ready_state_stop_handler, + .reset = scic_sds_controller_general_reset_handler, + .start_io = scic_sds_controller_ready_state_start_io_handler, + .complete_io = scic_sds_controller_ready_state_complete_io_handler, + .continue_io = scic_sds_controller_ready_state_continue_io_handler, + .start_task = scic_sds_controller_ready_state_start_task_handler, + .complete_task = scic_sds_controller_ready_state_complete_io_handler, .terminate_request = scic_sds_controller_ready_state_terminate_request_handler, .link_up = scic_sds_controller_ready_state_link_up_handler, .link_down = scic_sds_controller_ready_state_link_down_handler }, [SCI_BASE_CONTROLLER_STATE_RESETTING] = { - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_default_request_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_default_request_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, }, [SCI_BASE_CONTROLLER_STATE_STOPPING] = { - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_stopping_state_complete_io_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_stopping_state_complete_io_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, .device_stopped = scic_sds_controller_stopping_state_device_stopped_handler, }, [SCI_BASE_CONTROLLER_STATE_STOPPED] = { - .base.reset = scic_sds_controller_general_reset_handler, - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_default_request_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .reset = scic_sds_controller_general_reset_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_default_request_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, }, [SCI_BASE_CONTROLLER_STATE_FAILED] = { - .base.reset = scic_sds_controller_general_reset_handler, - .base.start_io = scic_sds_controller_default_start_operation_handler, - .base.complete_io = scic_sds_controller_default_request_handler, - .base.continue_io = scic_sds_controller_default_request_handler, + .reset = scic_sds_controller_general_reset_handler, + .start_io = scic_sds_controller_default_start_operation_handler, + .complete_io = scic_sds_controller_default_request_handler, + .continue_io = scic_sds_controller_default_request_handler, .terminate_request = scic_sds_controller_default_request_handler, }, }; @@ -3612,8 +3507,8 @@ static void scic_sds_controller_initial_state_enter( this_controller = (struct scic_sds_controller *)object; - sci_base_state_machine_change_state( - &this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET); + sci_base_state_machine_change_state(&this_controller->state_machine, + SCI_BASE_CONTROLLER_STATE_RESET); } /** @@ -3718,9 +3613,9 @@ static void scic_sds_controller_resetting_state_enter(struct sci_base_object *ob { struct scic_sds_controller *scic; - scic = container_of(object, typeof(*scic), parent.parent); + scic = container_of(object, typeof(*scic), parent); scic_sds_controller_reset_hardware(scic); - sci_base_state_machine_change_state(&scic->parent.state_machine, + sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_RESET); } @@ -3771,10 +3666,13 @@ enum sci_status scic_controller_construct(struct scic_sds_controller *scic, { u8 i; - sci_base_controller_construct(&scic->parent, - scic_sds_controller_state_table, - scic->memory_descriptors, - ARRAY_SIZE(scic->memory_descriptors), NULL); + sci_base_state_machine_construct(&scic->state_machine, + &scic->parent, scic_sds_controller_state_table, + SCI_BASE_CONTROLLER_STATE_INITIAL); + + sci_base_mdl_construct(&scic->mdl, scic->memory_descriptors, + ARRAY_SIZE(scic->memory_descriptors), NULL); + sci_base_state_machine_start(&scic->state_machine); scic->scu_registers = scu_base; scic->smu_registers = smu_base; diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index baf0b9ededec..f2d7e9c05b17 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -69,7 +69,9 @@ #include "sci_pool.h" #include "sci_controller_constants.h" #include "sci_memory_descriptor_list.h" -#include "sci_base_controller.h" +#include "sci_base_state.h" +#include "sci_base_state_machine.h" +#include "sci_base_memory_descriptor_list.h" #include "scic_config_parameters.h" #include "scic_sds_port.h" #include "scic_sds_phy.h" @@ -82,11 +84,12 @@ #include "scic_sds_unsolicited_frame_control.h" #include "scic_sds_port_configuration_agent.h" +struct sci_base_remote_device; struct scic_sds_remote_device; +struct sci_base_request; struct scic_sds_request; struct scic_sds_controller; - #define SCU_COMPLETION_RAM_ALIGNMENT (64) /** @@ -166,10 +169,23 @@ struct scic_power_control { */ struct scic_sds_controller { /** - * The struct sci_base_controller is the parent object for the struct scic_sds_controller - * object. + * The field specifies that the parent object for the base controller + * is the base object itself. + */ + struct sci_base_object parent; + + /** + * This field points to the memory descriptor list associated with this + * controller. The MDL indicates the memory requirements necessary for + * this controller object. + */ + struct sci_base_memory_descriptor_list mdl; + + /** + * This field contains the information for the base controller state + * machine. */ - struct sci_base_controller parent; + struct sci_base_state_machine state_machine; /** * This field is the driver timer object handler used to time the controller @@ -376,24 +392,170 @@ struct scic_sds_controller { }; -typedef void (*scic_sds_controller_phy_handler_t)(struct scic_sds_controller *, - struct scic_sds_port *, - struct scic_sds_phy *); +/** + * enum scic_sds_controller_states - This enumeration depicts all the states + * for the common controller state machine. + */ +enum scic_sds_controller_states { + /** + * Simply the initial state for the base controller state machine. + */ + SCI_BASE_CONTROLLER_STATE_INITIAL = 0, -typedef void (*scic_sds_controller_device_handler_t)(struct scic_sds_controller *, - struct scic_sds_remote_device *); + /** + * This state indicates that the controller is reset. The memory for + * the controller is in it's initial state, but the controller requires + * initialization. + * This state is entered from the INITIAL state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_CONTROLLER_STATE_RESET, + /** + * This state is typically an action state that indicates the controller + * is in the process of initialization. In this state no new IO operations + * are permitted. + * This state is entered from the RESET state. + */ + SCI_BASE_CONTROLLER_STATE_INITIALIZING, + + /** + * This state indicates that the controller has been successfully + * initialized. In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + */ + SCI_BASE_CONTROLLER_STATE_INITIALIZED, + + /** + * This state indicates the the controller is in the process of becoming + * ready (i.e. starting). In this state no new IO operations are permitted. + * This state is entered from the INITIALIZED state. + */ + SCI_BASE_CONTROLLER_STATE_STARTING, + + /** + * This state indicates the controller is now ready. Thus, the user + * is able to perform IO operations on the controller. + * This state is entered from the STARTING state. + */ + SCI_BASE_CONTROLLER_STATE_READY, + + /** + * This state is typically an action state that indicates the controller + * is in the process of resetting. Thus, the user is unable to perform + * IO operations on the controller. A reset is considered destructive in + * most cases. + * This state is entered from the READY state. + * This state is entered from the FAILED state. + * This state is entered from the STOPPED state. + */ + SCI_BASE_CONTROLLER_STATE_RESETTING, + + /** + * This state indicates that the controller is in the process of stopping. + * In this state no new IO operations are permitted, but existing IO + * operations are allowed to complete. + * This state is entered from the READY state. + */ + SCI_BASE_CONTROLLER_STATE_STOPPING, + + /** + * This state indicates that the controller has successfully been stopped. + * In this state no new IO operations are permitted. + * This state is entered from the STOPPING state. + */ + SCI_BASE_CONTROLLER_STATE_STOPPED, + + /** + * This state indicates that the controller could not successfully be + * initialized. In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + * This state is entered from the STARTING state. + * This state is entered from the STOPPING state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_CONTROLLER_STATE_FAILED, + + SCI_BASE_CONTROLLER_MAX_STATES + +}; + +typedef enum sci_status (*scic_sds_controller_handler_t) + (struct scic_sds_controller *); +typedef enum sci_status (*scic_sds_controller_timed_handler_t) + (struct scic_sds_controller *, u32); +typedef enum sci_status (*scic_sds_controller_request_handler_t) + (struct scic_sds_controller *, + struct sci_base_remote_device *, + struct sci_base_request *); +typedef enum sci_status (*scic_sds_controller_start_request_handler_t) + (struct scic_sds_controller *, + struct sci_base_remote_device *, + struct sci_base_request *, u16); +typedef void (*scic_sds_controller_phy_handler_t) + (struct scic_sds_controller *, + struct scic_sds_port *, + struct scic_sds_phy *); +typedef void (*scic_sds_controller_device_handler_t) + (struct scic_sds_controller *, + struct scic_sds_remote_device *); -/** - * struct scic_sds_controller_state_handler - - * - * This structure contains the SDS core specific definition for the state - * handlers. - */ struct scic_sds_controller_state_handler { - struct sci_base_controller_state_handler base; + /** + * The start_handler specifies the method invoked when a user attempts to + * start a controller. + */ + scic_sds_controller_timed_handler_t start; + + /** + * The stop_handler specifies the method invoked when a user attempts to + * stop a controller. + */ + scic_sds_controller_timed_handler_t stop; + + /** + * The reset_handler specifies the method invoked when a user attempts to + * reset a controller. + */ + scic_sds_controller_handler_t reset; + + /** + * The initialize_handler specifies the method invoked when a user + * attempts to initialize a controller. + */ + scic_sds_controller_handler_t initialize; + + /** + * The start_io_handler specifies the method invoked when a user + * attempts to start an IO request for a controller. + */ + scic_sds_controller_start_request_handler_t start_io; + + /** + * The complete_io_handler specifies the method invoked when a user + * attempts to complete an IO request for a controller. + */ + scic_sds_controller_request_handler_t complete_io; + + /** + * The continue_io_handler specifies the method invoked when a user + * attempts to continue an IO request for a controller. + */ + scic_sds_controller_request_handler_t continue_io; + + /** + * The start_task_handler specifies the method invoked when a user + * attempts to start a task management request for a controller. + */ + scic_sds_controller_start_request_handler_t start_task; + + /** + * The complete_task_handler specifies the method invoked when a user + * attempts to complete a task management request for a controller. + */ + scic_sds_controller_request_handler_t complete_task; - sci_base_controller_request_handler_t terminate_request; + scic_sds_controller_request_handler_t terminate_request; scic_sds_controller_phy_handler_t link_up; scic_sds_controller_phy_handler_t link_down; scic_sds_controller_device_handler_t device_stopped; diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index a6bcaa15fbf4..b4b6be7cdfb9 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -563,12 +563,11 @@ void scic_sds_remote_device_continue_request(void *dev) /* we need to check if this request is still valid to continue. */ if (sci_req) { struct scic_sds_controller *scic = sci_req->owning_controller; - u32 state = scic->parent.state_machine.current_state_id; - sci_base_controller_request_handler_t continue_io; + u32 state = scic->state_machine.current_state_id; + scic_sds_controller_request_handler_t continue_io; - continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; - continue_io(&scic->parent, &sci_req->target_device->parent, - &sci_req->parent); + continue_io = scic_sds_controller_state_handler_table[state].continue_io; + continue_io(scic, &sci_req->target_device->parent, &sci_req->parent); } } diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 0e961e9cd6eb..5dd4896576d4 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -649,7 +649,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( u32 length) { struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_request; - sci_base_controller_request_handler_t continue_io; + scic_sds_controller_request_handler_t continue_io; struct scu_sgl_element *current_sgl; struct scic_sds_controller *scic; u32 state; @@ -675,9 +675,9 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( /* send the new TC out. */ scic = this_request->owning_controller; - state = scic->parent.state_machine.current_state_id; - continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; - return continue_io(&scic->parent, &this_request->target_device->parent, + state = scic->state_machine.current_state_id; + continue_io = scic_sds_controller_state_handler_table[state].continue_io; + return continue_io(scic, &this_request->target_device->parent, &this_request->parent); } @@ -1822,7 +1822,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet struct sci_base_object *object) { struct scic_sds_request *this_request = (struct scic_sds_request *)object; - sci_base_controller_request_handler_t continue_io; + scic_sds_controller_request_handler_t continue_io; struct scu_task_context *task_context; struct sata_fis_reg_h2d *h2d_fis; struct scic_sds_controller *scic; @@ -1839,10 +1839,10 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet task_context->control_frame = 0; scic = this_request->owning_controller; - state = scic->parent.state_machine.current_state_id; - continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; + state = scic->state_machine.current_state_id; + continue_io = scic_sds_controller_state_handler_table[state].continue_io; - status = continue_io(&scic->parent, &this_request->target_device->parent, + status = continue_io(scic, &this_request->target_device->parent, &this_request->parent); if (status == SCI_SUCCESS) { diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 66449593aa8c..adfc2452d216 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -62,6 +62,7 @@ #include "request.h" #include "host.h" #include "probe_roms.h" +#include "core/scic_sds_controller.h" irqreturn_t isci_msix_isr(int vec, void *data) { @@ -231,9 +232,8 @@ static int isci_host_mdl_allocate_coherent( struct coherent_memory_info *mdl_struct; u32 size = 0; - struct sci_base_memory_descriptor_list *mdl_handle - = sci_controller_get_memory_descriptor_list_handle( - isci_host->core_controller); + struct sci_base_memory_descriptor_list *mdl_handle = + &isci_host->core_controller->mdl; sci_mdl_first_entry(mdl_handle); diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 87643857bade..ac292d2a75de 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -65,7 +65,7 @@ #include #include -#include "sci_base_controller.h" +#include "core/sci_object.h" #include "scic_controller.h" #include "host.h" #include "timers.h" -- cgit v1.2.3 From 38aa74eb704c5886a5ded4085acd5f2895ab3511 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 28 Mar 2011 09:21:14 -0400 Subject: isci: remove base_request abstraction Merge struct sci_base_request into scic_sds_request, and also factor the two types of state machine handlers into one function. While we're at it also remove lots of duplicate incorrect kerneldoc comments for the state machine handlers. Signed-off-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_remote_device.h | 6 +- drivers/scsi/isci/core/sci_base_request.h | 195 ---------- drivers/scsi/isci/core/scic_sds_controller.c | 68 ++-- drivers/scsi/isci/core/scic_sds_controller.h | 5 +- drivers/scsi/isci/core/scic_sds_port.c | 30 +- drivers/scsi/isci/core/scic_sds_remote_device.c | 99 ++--- drivers/scsi/isci/core/scic_sds_remote_device.h | 7 +- drivers/scsi/isci/core/scic_sds_request.c | 402 +++++++-------------- drivers/scsi/isci/core/scic_sds_request.h | 122 +++++-- .../scsi/isci/core/scic_sds_smp_remote_device.c | 23 +- drivers/scsi/isci/core/scic_sds_smp_request.c | 63 ++-- drivers/scsi/isci/core/scic_sds_ssp_request.c | 69 ++-- .../scsi/isci/core/scic_sds_stp_packet_request.c | 12 +- .../scsi/isci/core/scic_sds_stp_remote_device.c | 173 ++++----- drivers/scsi/isci/core/scic_sds_stp_request.c | 218 ++++++----- 15 files changed, 551 insertions(+), 941 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_base_request.h diff --git a/drivers/scsi/isci/core/sci_base_remote_device.h b/drivers/scsi/isci/core/sci_base_remote_device.h index 45414ce6a2c6..5db5f31336fc 100644 --- a/drivers/scsi/isci/core/sci_base_remote_device.h +++ b/drivers/scsi/isci/core/sci_base_remote_device.h @@ -65,7 +65,7 @@ #include "sci_base_state_machine.h" -struct sci_base_request; +struct scic_sds_request; /** * enum sci_base_remote_device_states - This enumeration depicts all the states @@ -159,12 +159,12 @@ typedef enum sci_status (*sci_base_remote_device_handler_t)( typedef enum sci_status (*sci_base_remote_device_request_handler_t)( struct sci_base_remote_device *, - struct sci_base_request * + struct scic_sds_request * ); typedef enum sci_status (*sci_base_remote_device_high_priority_request_complete_handler_t)( struct sci_base_remote_device *, - struct sci_base_request *, + struct scic_sds_request *, void *, enum sci_io_status ); diff --git a/drivers/scsi/isci/core/sci_base_request.h b/drivers/scsi/isci/core/sci_base_request.h deleted file mode 100644 index 223aa4c5f757..000000000000 --- a/drivers/scsi/isci/core/sci_base_request.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_REQUST_H_ -#define _SCI_BASE_REQUST_H_ - -/** - * This file contains all of the constants, types, and method declarations for - * the SCI base IO and task request objects. - * - * - */ - -#include "sci_base_state_machine.h" - -/** - * enum sci_base_request_states - This enumeration depicts all the states for - * the common request state machine. - * - * - */ -enum sci_base_request_states { - /** - * Simply the initial state for the base request state machine. - */ - SCI_BASE_REQUEST_STATE_INITIAL, - - /** - * This state indicates that the request has been constructed. This state - * is entered from the INITIAL state. - */ - SCI_BASE_REQUEST_STATE_CONSTRUCTED, - - /** - * This state indicates that the request has been started. This state is - * entered from the CONSTRUCTED state. - */ - SCI_BASE_REQUEST_STATE_STARTED, - - /** - * This state indicates that the request has completed. - * This state is entered from the STARTED state. This state is entered from - * the ABORTING state. - */ - SCI_BASE_REQUEST_STATE_COMPLETED, - - /** - * This state indicates that the request is in the process of being - * terminated/aborted. - * This state is entered from the CONSTRUCTED state. - * This state is entered from the STARTED state. - */ - SCI_BASE_REQUEST_STATE_ABORTING, - - /** - * Simply the final state for the base request state machine. - */ - SCI_BASE_REQUEST_STATE_FINAL, -}; - -/** - * struct sci_base_request - The base request object abstracts the fields - * common to all SCI IO and task request objects. - * - * - */ -struct sci_base_request { - /** - * The field specifies that the parent object for the base request is the - * base object itself. - */ - struct sci_base_object parent; - - /** - * This field contains the information for the base request state machine. - */ - struct sci_base_state_machine state_machine; -}; - -typedef enum sci_status (*sci_base_request_handler_t)( - struct sci_base_request *this_request - ); - -/** - * struct sci_base_request_state_handler - This structure contains all of the - * state handler methods common to base IO and task request state machines. - * Handler methods provide the ability to change the behavior for user - * requests or transitions depending on the state the machine is in. - * - * - */ -struct sci_base_request_state_handler { - /** - * The start_handler specifies the method invoked when a user attempts to - * start a request. - */ - sci_base_request_handler_t start_handler; - - /** - * The abort_handler specifies the method invoked when a user attempts to - * abort a request. - */ - sci_base_request_handler_t abort_handler; - - /** - * The complete_handler specifies the method invoked when a user attempts to - * complete a request. - */ - sci_base_request_handler_t complete_handler; - - /** - * The destruct_handler specifies the method invoked when a user attempts to - * destruct a request. - */ - sci_base_request_handler_t destruct_handler; - -}; - -/** - * sci_base_request_construct() - Construct the base request. - * @this_request: This parameter specifies the base request to be constructed. - * @state_table: This parameter specifies the table of state definitions to be - * utilized for the request state machine. - * - */ -static inline void sci_base_request_construct( - struct sci_base_request *base_req, - const struct sci_base_state *my_state_table) -{ - base_req->parent.private = NULL; - sci_base_state_machine_construct( - &base_req->state_machine, - &base_req->parent, - my_state_table, - SCI_BASE_REQUEST_STATE_INITIAL - ); - - sci_base_state_machine_start( - &base_req->state_machine - ); -} - -#endif /* _SCI_BASE_REQUST_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index e7790bb7dfdd..7ead6f381550 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -2161,7 +2161,7 @@ enum sci_status scic_controller_reset( enum sci_io_status scic_controller_start_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, - struct scic_sds_request *io_request, + struct scic_sds_request *request, u16 io_tag) { u32 state; @@ -2172,7 +2172,7 @@ enum sci_io_status scic_controller_start_io( return start_io(scic, (struct sci_base_remote_device *) remote_device, - (struct sci_base_request *)io_request, io_tag); + request, io_tag); } /** @@ -2204,7 +2204,7 @@ enum sci_status scic_controller_terminate_request( return terminate_request(scic, (struct sci_base_remote_device *)remote_device, - (struct sci_base_request *)request); + request); } /** @@ -2232,7 +2232,7 @@ enum sci_status scic_controller_terminate_request( enum sci_status scic_controller_complete_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, - struct scic_sds_request *io_request) + struct scic_sds_request *request) { u32 state; scic_sds_controller_request_handler_t complete_io; @@ -2242,7 +2242,7 @@ enum sci_status scic_controller_complete_io( return complete_io(scic, (struct sci_base_remote_device *)remote_device, - (struct sci_base_request *)io_request); + request); } /** @@ -2289,7 +2289,7 @@ enum sci_task_status scic_controller_start_task( if (start_task) status = start_task(scic, (struct sci_base_remote_device *)remote_device, - (struct sci_base_request *)task_request, + task_request, task_tag); else dev_warn(scic_to_dev(scic), @@ -2329,7 +2329,7 @@ enum sci_status scic_controller_complete_task( if (complete_task) status = complete_task(scic, (struct sci_base_remote_device *)remote_device, - (struct sci_base_request *)task_request); + task_request); else dev_warn(scic_to_dev(scic), "%s: SCIC Controller completing task from invalid " @@ -2825,7 +2825,7 @@ default_controller_handler(struct scic_sds_controller *scic, const char *func) static enum sci_status scic_sds_controller_default_start_operation_handler( struct scic_sds_controller *scic, struct sci_base_remote_device *remote_device, - struct sci_base_request *io_request, + struct scic_sds_request *request, u16 io_tag) { return default_controller_handler(scic, __func__); @@ -2834,7 +2834,7 @@ static enum sci_status scic_sds_controller_default_start_operation_handler( static enum sci_status scic_sds_controller_default_request_handler( struct scic_sds_controller *scic, struct sci_base_remote_device *remote_device, - struct sci_base_request *io_request) + struct scic_sds_request *request) { return default_controller_handler(scic, __func__); } @@ -3186,26 +3186,24 @@ static enum sci_status scic_sds_controller_ready_state_stop_handler( static enum sci_status scic_sds_controller_ready_state_start_io_handler( struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, - struct sci_base_request *io_request, + struct scic_sds_request *request, u16 io_tag) { enum sci_status status; - struct scic_sds_request *the_request; struct scic_sds_remote_device *the_device; - the_request = (struct scic_sds_request *)io_request; the_device = (struct scic_sds_remote_device *)remote_device; - status = scic_sds_remote_device_start_io(controller, the_device, the_request); + status = scic_sds_remote_device_start_io(controller, the_device, request); if (status != SCI_SUCCESS) return status; controller->io_request_table[ - scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + scic_sds_io_tag_get_index(request->io_tag)] = request; scic_sds_controller_post_request(controller, - scic_sds_request_get_post_context(the_request)); + scic_sds_request_get_post_context(request)); return SCI_SUCCESS; } @@ -3220,22 +3218,20 @@ static enum sci_status scic_sds_controller_ready_state_start_io_handler( static enum sci_status scic_sds_controller_ready_state_complete_io_handler( struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, - struct sci_base_request *io_request) + struct scic_sds_request *request) { u16 index; enum sci_status status; - struct scic_sds_request *the_request; struct scic_sds_remote_device *the_device; - the_request = (struct scic_sds_request *)io_request; the_device = (struct scic_sds_remote_device *)remote_device; status = scic_sds_remote_device_complete_io(controller, the_device, - the_request); + request); if (status != SCI_SUCCESS) return status; - index = scic_sds_io_tag_get_index(the_request->io_tag); + index = scic_sds_io_tag_get_index(request->io_tag); controller->io_request_table[index] = NULL; return SCI_SUCCESS; } @@ -3247,16 +3243,12 @@ static enum sci_status scic_sds_controller_ready_state_complete_io_handler( static enum sci_status scic_sds_controller_ready_state_continue_io_handler( struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, - struct sci_base_request *io_request) + struct scic_sds_request *request) { - struct scic_sds_request *the_request; - - the_request = (struct scic_sds_request *)io_request; - controller->io_request_table[ - scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + scic_sds_io_tag_get_index(request->io_tag)] = request; scic_sds_controller_post_request(controller, - scic_sds_request_get_post_context(the_request)); + scic_sds_request_get_post_context(request)); return SCI_SUCCESS; } @@ -3273,27 +3265,25 @@ static enum sci_status scic_sds_controller_ready_state_continue_io_handler( static enum sci_status scic_sds_controller_ready_state_start_task_handler( struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, - struct sci_base_request *io_request, + struct scic_sds_request *request, u16 task_tag) { - struct scic_sds_request *the_request = (struct scic_sds_request *) - io_request; struct scic_sds_remote_device *the_device = (struct scic_sds_remote_device *) remote_device; enum sci_status status; status = scic_sds_remote_device_start_task(controller, the_device, - the_request); + request); if (status == SCI_SUCCESS) { controller->io_request_table[ - scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + scic_sds_io_tag_get_index(request->io_tag)] = request; scic_sds_controller_post_request(controller, - scic_sds_request_get_post_context(the_request)); + scic_sds_request_get_post_context(request)); } else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS) { controller->io_request_table[ - scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; + scic_sds_io_tag_get_index(request->io_tag)] = request; /* * We will let framework know this task request started successfully, @@ -3315,13 +3305,11 @@ static enum sci_status scic_sds_controller_ready_state_start_task_handler( static enum sci_status scic_sds_controller_ready_state_terminate_request_handler( struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, - struct sci_base_request *io_request) + struct scic_sds_request *request) { - struct scic_sds_request *the_request = (struct scic_sds_request *) - io_request; enum sci_status status; - status = scic_sds_io_request_terminate(the_request); + status = scic_sds_io_request_terminate(request); if (status != SCI_SUCCESS) return status; @@ -3330,7 +3318,7 @@ static enum sci_status scic_sds_controller_ready_state_terminate_request_handler * request sub-type. */ scic_sds_controller_post_request(controller, - scic_sds_request_get_post_context(the_request) | + scic_sds_request_get_post_context(request) | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); return SCI_SUCCESS; } @@ -3391,7 +3379,7 @@ static void scic_sds_controller_ready_state_link_down_handler( static enum sci_status scic_sds_controller_stopping_state_complete_io_handler( struct scic_sds_controller *controller, struct sci_base_remote_device *remote_device, - struct sci_base_request *io_request) + struct scic_sds_request *request) { /* XXX: Implement this function */ return SCI_FAILURE; diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index f2d7e9c05b17..5cff8066a0ef 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -86,7 +86,6 @@ struct sci_base_remote_device; struct scic_sds_remote_device; -struct sci_base_request; struct scic_sds_request; struct scic_sds_controller; @@ -487,11 +486,11 @@ typedef enum sci_status (*scic_sds_controller_timed_handler_t) typedef enum sci_status (*scic_sds_controller_request_handler_t) (struct scic_sds_controller *, struct sci_base_remote_device *, - struct sci_base_request *); + struct scic_sds_request *); typedef enum sci_status (*scic_sds_controller_start_request_handler_t) (struct scic_sds_controller *, struct sci_base_remote_device *, - struct sci_base_request *, u16); + struct scic_sds_request *, u16); typedef void (*scic_sds_controller_phy_handler_t) (struct scic_sds_controller *, struct scic_sds_port *, diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 8e3983ebc4dc..ef9cb9eb66f4 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -1090,15 +1090,7 @@ static enum sci_status scic_sds_port_ready_substate_stop_handler( return SCI_SUCCESS; } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * @device: This is the struct sci_base_remote_device object which is not used in this - * function. - * @io_request: This is the struct sci_base_request object which is not used in this - * function. - * +/* * This method is the general ready substate complete io handler for the * struct scic_sds_port object. This function decrments the outstanding request count * for this port object. enum sci_status SCI_SUCCESS @@ -1194,15 +1186,7 @@ static void scic_sds_port_ready_waiting_substate_link_up_handler( ); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * @device: This is the struct sci_base_remote_device object which is not used in this - * request. - * @io_request: This is the struct sci_base_request object which is not used in this - * function. - * +/* * This method is the ready waiting substate start io handler for the * struct scic_sds_port object. The port object can not accept new requests so the * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE @@ -1316,15 +1300,7 @@ static void scic_sds_port_ready_operational_substate_link_down_handler( SCIC_SDS_PORT_READY_SUBSTATE_WAITING); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * @device: This is the struct sci_base_remote_device object which is not used in this - * function. - * @io_request: This is the struct sci_base_request object which is not used in this - * function. - * +/* * This method is the ready operational substate start io handler for the * struct scic_sds_port object. This function incremetns the outstanding request * count for this port object. enum sci_status SCI_SUCCESS diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index b4b6be7cdfb9..cb49a33285d9 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -363,7 +363,7 @@ enum sci_status scic_sds_remote_device_start_io( struct scic_sds_request *io_request) { return this_device->state_handlers->parent.start_io_handler( - &this_device->parent, &io_request->parent); + &this_device->parent, io_request); } /** @@ -381,7 +381,7 @@ enum sci_status scic_sds_remote_device_complete_io( struct scic_sds_request *io_request) { return this_device->state_handlers->parent.complete_io_handler( - &this_device->parent, &io_request->parent); + &this_device->parent, io_request); } /** @@ -399,7 +399,7 @@ enum sci_status scic_sds_remote_device_start_task( struct scic_sds_request *io_request) { return this_device->state_handlers->parent.start_task_handler( - &this_device->parent, &io_request->parent); + &this_device->parent, io_request); } /** @@ -567,7 +567,7 @@ void scic_sds_remote_device_continue_request(void *dev) scic_sds_controller_request_handler_t continue_io; continue_io = scic_sds_controller_state_handler_table[state].continue_io; - continue_io(scic, &sci_req->target_device->parent, &sci_req->parent); + continue_io(scic, &sci_req->target_device->parent, sci_req); } } @@ -792,21 +792,21 @@ enum sci_status scic_sds_remote_device_default_frame_handler( enum sci_status scic_sds_remote_device_default_start_request_handler( struct sci_base_remote_device *base_dev, - struct sci_base_request *request) + struct scic_sds_request *request) { return default_device_handler(base_dev, __func__); } enum sci_status scic_sds_remote_device_default_complete_request_handler( struct sci_base_remote_device *base_dev, - struct sci_base_request *request) + struct scic_sds_request *request) { return default_device_handler(base_dev, __func__); } enum sci_status scic_sds_remote_device_default_continue_request_handler( struct sci_base_remote_device *base_dev, - struct sci_base_request *request) + struct scic_sds_request *request) { return default_device_handler(base_dev, __func__); } @@ -1019,13 +1019,7 @@ enum sci_status scic_sds_remote_device_ready_state_reset_handler( return SCI_SUCCESS; } -/** - * - * @device: The struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device for which the request is to be started. - * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that - * is to be started. - * +/* * This method will attempt to start a task request for this device object. The * remote device object will issue the start request for the task and if * successful it will start the request for the port object then increment its @@ -1035,38 +1029,28 @@ enum sci_status scic_sds_remote_device_ready_state_reset_handler( */ static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { enum sci_status result; struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - struct scic_sds_request *task_request = (struct scic_sds_request *)request; /* See if the port is in a state where we can start the IO request */ result = scic_sds_port_start_io( - scic_sds_remote_device_get_port(this_device), this_device, task_request); + scic_sds_remote_device_get_port(this_device), this_device, request); if (result == SCI_SUCCESS) { result = scic_sds_remote_node_context_start_task( - this_device->rnc, task_request - ); - - if (result == SCI_SUCCESS) { - result = scic_sds_request_start(task_request); - } + this_device->rnc, request); + if (result == SCI_SUCCESS) + result = scic_sds_request_start(request); - scic_sds_remote_device_start_request(this_device, task_request, result); + scic_sds_remote_device_start_request(this_device, request, result); } return result; } -/** - * - * @device: The struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device for which the request is to be started. - * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that - * is to be started. - * +/* * This method will attempt to start an io request for this device object. The * remote device object will issue the start request for the io and if * successful it will start the request for the port object then increment its @@ -1076,38 +1060,28 @@ static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( */ static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { enum sci_status result; struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - struct scic_sds_request *io_request = (struct scic_sds_request *)request; /* See if the port is in a state where we can start the IO request */ result = scic_sds_port_start_io( - scic_sds_remote_device_get_port(this_device), this_device, io_request); + scic_sds_remote_device_get_port(this_device), this_device, request); if (result == SCI_SUCCESS) { result = scic_sds_remote_node_context_start_io( - this_device->rnc, io_request - ); + this_device->rnc, request); + if (result == SCI_SUCCESS) + result = scic_sds_request_start(request); - if (result == SCI_SUCCESS) { - result = scic_sds_request_start(io_request); - } - - scic_sds_remote_device_start_request(this_device, io_request, result); + scic_sds_remote_device_start_request(this_device, request, result); } return result; } -/** - * - * @device: The struct sci_base_remote_device which is cast to a - * struct scic_sds_remote_device for which the request is to be completed. - * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that - * is to be completed. - * +/* * This method will complete the request for the remote device object. The * method will call the completion handler for the request object and if * successful it will complete the request on the port object then decrement @@ -1115,18 +1089,17 @@ static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( */ static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { enum sci_status result; struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - struct scic_sds_request *the_request = (struct scic_sds_request *)request; - result = scic_sds_request_complete(the_request); + result = scic_sds_request_complete(request); if (result == SCI_SUCCESS) { /* See if the port is in a state where we can start the IO request */ result = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(this_device), this_device, the_request); + scic_sds_remote_device_get_port(this_device), this_device, request); if (result == SCI_SUCCESS) { scic_sds_remote_device_decrement_request_count(this_device); @@ -1178,19 +1151,16 @@ static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( */ static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { enum sci_status status = SCI_SUCCESS; - struct scic_sds_request *this_request = (struct scic_sds_request *)request; struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - status = scic_sds_request_complete(this_request); + status = scic_sds_request_complete(request); if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( scic_sds_remote_device_get_port(this_device), - this_device, - this_request - ); + this_device, request); if (status == SCI_SUCCESS) { scic_sds_remote_device_decrement_request_count(this_device); @@ -1255,11 +1225,7 @@ static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( return SCI_SUCCESS; } -/** - * - * @device: The device object for which the request is completing. - * @request: The task request that is being completed. - * +/* * This method completes requests for this struct scic_sds_remote_device while it is * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the * complete method for the request object and if that is successful the port @@ -1268,17 +1234,16 @@ static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( */ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { enum sci_status status = SCI_SUCCESS; - struct scic_sds_request *this_request = (struct scic_sds_request *)request; struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - status = scic_sds_request_complete(this_request); + status = scic_sds_request_complete(request); if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(this_device), this_device, this_request); + scic_sds_remote_device_get_port(this_device), this_device, request); if (status == SCI_SUCCESS) { scic_sds_remote_device_decrement_request_count(this_device); diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index 725c0588f2ab..90b231833872 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -65,7 +65,6 @@ #include "intel_sas.h" #include "sci_base_remote_device.h" -#include "sci_base_request.h" #include "scu_remote_node_context.h" #include "scic_sds_remote_node_context.h" @@ -507,15 +506,15 @@ enum sci_status scic_sds_remote_device_default_reset_complete_handler( enum sci_status scic_sds_remote_device_default_start_request_handler( struct sci_base_remote_device *device, - struct sci_base_request *request); + struct scic_sds_request *request); enum sci_status scic_sds_remote_device_default_complete_request_handler( struct sci_base_remote_device *device, - struct sci_base_request *request); + struct scic_sds_request *request); enum sci_status scic_sds_remote_device_default_continue_request_handler( struct sci_base_remote_device *device, - struct sci_base_request *request); + struct scic_sds_request *request); enum sci_status scic_sds_remote_device_default_suspend_handler( struct scic_sds_remote_device *this_device, diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index d0cbb97b63a7..7c21de0cc3a6 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -57,7 +57,6 @@ #include "intel_sas.h" #include "intel_sata.h" #include "intel_sat.h" -#include "sci_base_request.h" #include "scic_controller.h" #include "scic_io_request.h" #include "scic_remote_device.h" @@ -728,10 +727,8 @@ enum sci_status scic_io_request_construct_basic_ssp( scic_sds_io_request_build_ssp_command_iu(sci_req); - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return SCI_SUCCESS; } @@ -746,10 +743,8 @@ enum sci_status scic_task_request_construct_ssp( /* Fill in the SSP Task IU */ scic_sds_task_request_build_ssp_task_iu(sci_req); - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return SCI_SUCCESS; } @@ -780,10 +775,8 @@ enum sci_status scic_io_request_construct_basic_sata( status = scic_io_request_construct_sata(sci_req, proto, len, dir, copy); if (status == SCI_SUCCESS) - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return status; } @@ -818,10 +811,8 @@ enum sci_status scic_task_request_construct_sata( } if (status == SCI_SUCCESS) - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return status; } @@ -891,18 +882,12 @@ u32 scic_io_request_get_number_of_bytes_transferred( * This method invokes the base state start request handler for the * SCIC_SDS_IO_REQUEST_T object. enum sci_status */ -enum sci_status scic_sds_request_start( - struct scic_sds_request *this_request) +enum sci_status +scic_sds_request_start(struct scic_sds_request *request) { - if ( - this_request->device_sequence - == scic_sds_remote_device_get_sequence(this_request->target_device) - ) { - return this_request->state_handlers->parent.start_handler( - &this_request->parent - ); - } - + if (request->device_sequence == + scic_sds_remote_device_get_sequence(request->target_device)) + return request->state_handlers->start_handler(request); return SCI_FAILURE; } @@ -914,11 +899,10 @@ enum sci_status scic_sds_request_start( * This method invokes the base state terminate request handber for the * SCIC_SDS_IO_REQUEST_T object. enum sci_status */ -enum sci_status scic_sds_io_request_terminate( - struct scic_sds_request *this_request) +enum sci_status +scic_sds_io_request_terminate(struct scic_sds_request *request) { - return this_request->state_handlers->parent.abort_handler( - &this_request->parent); + return request->state_handlers->abort_handler(request); } /** @@ -929,11 +913,10 @@ enum sci_status scic_sds_io_request_terminate( * This method invokes the base state request completion handler for the * SCIC_SDS_IO_REQUEST_T object. enum sci_status */ -enum sci_status scic_sds_io_request_complete( - struct scic_sds_request *this_request) +enum sci_status +scic_sds_io_request_complete(struct scic_sds_request *request) { - return this_request->state_handlers->parent.complete_handler( - &this_request->parent); + return request->state_handlers->complete_handler(request); } /** @@ -1023,175 +1006,132 @@ void scic_sds_io_request_copy_response(struct scic_sds_request *sds_request) * * DEFAULT STATE HANDLERS * ***************************************************************************** */ -/** - * scic_sds_request_default_start_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_start() request. The default action is * to log a warning and return a failure status. enum sci_status * SCI_FAILURE_INVALID_STATE */ enum sci_status scic_sds_request_default_start_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *scic_request = - (struct scic_sds_request *)request; - - dev_warn(scic_to_dev(scic_request->owning_controller), + dev_warn(scic_to_dev(request->owning_controller), "%s: SCIC IO Request requested to start while in wrong " "state %d\n", __func__, - sci_base_state_machine_get_state( - &((struct scic_sds_request *)request)->parent.state_machine)); + sci_base_state_machine_get_state(&request->state_machine)); return SCI_FAILURE_INVALID_STATE; } static enum sci_status scic_sds_request_default_abort_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *scic_request = - (struct scic_sds_request *)request; - - dev_warn(scic_to_dev(scic_request->owning_controller), + dev_warn(scic_to_dev(request->owning_controller), "%s: SCIC IO Request requested to abort while in wrong " "state %d\n", __func__, - sci_base_state_machine_get_state( - &((struct scic_sds_request *)request)->parent.state_machine)); + sci_base_state_machine_get_state(&request->state_machine)); return SCI_FAILURE_INVALID_STATE; } -/** - * scic_sds_request_default_complete_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_complete() request. The default action * is to log a warning and return a failure status. enum sci_status * SCI_FAILURE_INVALID_STATE */ enum sci_status scic_sds_request_default_complete_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *scic_request = - (struct scic_sds_request *)request; - - dev_warn(scic_to_dev(scic_request->owning_controller), + dev_warn(scic_to_dev(request->owning_controller), "%s: SCIC IO Request requested to complete while in wrong " "state %d\n", __func__, - sci_base_state_machine_get_state( - &((struct scic_sds_request *)request)->parent.state_machine)); + sci_base_state_machine_get_state(&request->state_machine)); return SCI_FAILURE_INVALID_STATE; } -/** - * scic_sds_request_default_destruct_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_complete() request. The default action * is to log a warning and return a failure status. enum sci_status * SCI_FAILURE_INVALID_STATE */ enum sci_status scic_sds_request_default_destruct_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *scic_request = - (struct scic_sds_request *)request; - - dev_warn(scic_to_dev(scic_request->owning_controller), + dev_warn(scic_to_dev(request->owning_controller), "%s: SCIC IO Request requested to destroy while in wrong " "state %d\n", __func__, - sci_base_state_machine_get_state( - &((struct scic_sds_request *)request)->parent.state_machine)); + sci_base_state_machine_get_state(&request->state_machine)); return SCI_FAILURE_INVALID_STATE; } /** - * scic_sds_request_default_tc_completion_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_task_request_complete() request. The default * action is to log a warning and return a failure status. enum sci_status * SCI_FAILURE_INVALID_STATE */ enum sci_status scic_sds_request_default_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *request, u32 completion_code) { - dev_warn(scic_to_dev(this_request->owning_controller), + dev_warn(scic_to_dev(request->owning_controller), "%s: SCIC IO Request given task completion notification %x " "while in wrong state %d\n", __func__, completion_code, - sci_base_state_machine_get_state( - &this_request->parent.state_machine)); + sci_base_state_machine_get_state(&request->state_machine)); return SCI_FAILURE_INVALID_STATE; } -/** - * scic_sds_request_default_event_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_event_handler() request. The default * action is to log a warning and return a failure status. enum sci_status * SCI_FAILURE_INVALID_STATE */ enum sci_status scic_sds_request_default_event_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *request, u32 event_code) { - dev_warn(scic_to_dev(this_request->owning_controller), + dev_warn(scic_to_dev(request->owning_controller), "%s: SCIC IO Request given event code notification %x while " "in wrong state %d\n", __func__, event_code, - sci_base_state_machine_get_state( - &this_request->parent.state_machine)); + sci_base_state_machine_get_state(&request->state_machine)); return SCI_FAILURE_INVALID_STATE; } -/** - * scic_sds_request_default_frame_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_event_handler() request. The default * action is to log a warning and return a failure status. enum sci_status * SCI_FAILURE_INVALID_STATE */ enum sci_status scic_sds_request_default_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *request, u32 frame_index) { - dev_warn(scic_to_dev(this_request->owning_controller), + dev_warn(scic_to_dev(request->owning_controller), "%s: SCIC IO Request given unexpected frame %x while in " "state %d\n", __func__, frame_index, - sci_base_state_machine_get_state( - &this_request->parent.state_machine)); + sci_base_state_machine_get_state(&request->state_machine)); scic_sds_controller_release_frame( - this_request->owning_controller, frame_index); + request->owning_controller, frame_index); return SCI_FAILURE_INVALID_STATE; } @@ -1201,11 +1141,7 @@ enum sci_status scic_sds_request_default_frame_handler( * * CONSTRUCTED STATE HANDLERS * ***************************************************************************** */ -/** - * scic_sds_request_constructed_state_start_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method implements the action taken when a constructed * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request. * This method will, if necessary, allocate a TCi for the io request object and @@ -1215,34 +1151,33 @@ enum sci_status scic_sds_request_default_frame_handler( * SCI_SUCCESS SCI_FAILURE_INSUFFICIENT_RESOURCES */ static enum sci_status scic_sds_request_constructed_state_start_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { struct scu_task_context *task_context; - struct scic_sds_request *this_request = (struct scic_sds_request *)request; - if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { - this_request->io_tag = - scic_controller_allocate_io_tag(this_request->owning_controller); + if (request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { + request->io_tag = + scic_controller_allocate_io_tag(request->owning_controller); } /* Record the IO Tag in the request */ - if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { - task_context = this_request->task_context_buffer; + if (request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { + task_context = request->task_context_buffer; - task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag); + task_context->task_index = scic_sds_io_tag_get_index(request->io_tag); switch (task_context->protocol_type) { case SCU_TASK_CONTEXT_PROTOCOL_SMP: case SCU_TASK_CONTEXT_PROTOCOL_SSP: /* SSP/SMP Frame */ - task_context->type.ssp.tag = this_request->io_tag; + task_context->type.ssp.tag = request->io_tag; task_context->type.ssp.target_port_transfer_tag = 0xFFFF; break; case SCU_TASK_CONTEXT_PROTOCOL_STP: /* * STP/SATA Frame - * task_context->type.stp.ncq_tag = this_request->ncq_tag; */ + * task_context->type.stp.ncq_tag = request->ncq_tag; */ break; case SCU_TASK_CONTEXT_PROTOCOL_NONE: @@ -1257,20 +1192,17 @@ static enum sci_status scic_sds_request_constructed_state_start_handler( /* * Check to see if we need to copy the task context buffer * or have been building into the task context buffer */ - if (this_request->was_tag_assigned_by_user == false) { + if (request->was_tag_assigned_by_user == false) { scic_sds_controller_copy_task_context( - this_request->owning_controller, this_request - ); + request->owning_controller, request); } /* Add to the post_context the io tag value */ - this_request->post_context |= scic_sds_io_tag_get_index(this_request->io_tag); + request->post_context |= scic_sds_io_tag_get_index(request->io_tag); /* Everything is good go ahead and change state */ - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_STARTED - ); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_STARTED); return SCI_SUCCESS; } @@ -1278,35 +1210,24 @@ static enum sci_status scic_sds_request_constructed_state_start_handler( return SCI_FAILURE_INSUFFICIENT_RESOURCES; } -/** - * scic_sds_request_constructed_state_abort_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_terminate() request. Since the request * has not yet been posted to the hardware the request transitions to the * completed state. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_request_constructed_state_abort_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *this_request = (struct scic_sds_request *)request; - /* * This request has been terminated by the user make sure that the correct * status code is returned */ - scic_sds_request_set_status( - this_request, + scic_sds_request_set_status(request, SCU_TASK_DONE_TASK_ABORT, - SCI_FAILURE_IO_TERMINATED - ); - - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + SCI_FAILURE_IO_TERMINATED); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } @@ -1315,30 +1236,20 @@ static enum sci_status scic_sds_request_constructed_state_abort_handler( * * STARTED STATE HANDLERS * ***************************************************************************** */ -/** - * scic_sds_request_started_state_abort_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_terminate() request. Since the request * has been posted to the hardware the io request state is changed to the * aborting state. enum sci_status SCI_SUCCESS */ enum sci_status scic_sds_request_started_state_abort_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *this_request = (struct scic_sds_request *)request; - - if (this_request->has_started_substate_machine) { - sci_base_state_machine_stop(&this_request->started_substate_machine); - } - - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_ABORTING - ); + if (request->has_started_substate_machine) + sci_base_state_machine_stop(&request->started_substate_machine); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_ABORTING); return SCI_SUCCESS; } @@ -1512,20 +1423,12 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( */ /* In all cases we will treat this as the completion of the IO request. */ - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - + sci_base_state_machine_change_state(&this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } -/** - * scic_sds_request_started_state_frame_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * @frame_index: This is the index of the unsolicited frame to be processed. - * +/* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_frame_handler() request. This method * first determines the frame type received. If this is a response frame then @@ -1601,11 +1504,7 @@ static enum sci_status scic_sds_request_started_state_frame_handler( * ***************************************************************************** */ -/** - * scic_sds_request_completed_state_complete_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_complete() request. This method frees up * any io request resources that have been allocated and transitions the @@ -1613,26 +1512,20 @@ static enum sci_status scic_sds_request_started_state_frame_handler( * transitioning to the final state? enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_request_completed_state_complete_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *this_request = (struct scic_sds_request *)request; - - if (this_request->was_tag_assigned_by_user != true) { + if (request->was_tag_assigned_by_user != true) { scic_controller_free_io_tag( - this_request->owning_controller, this_request->io_tag - ); + request->owning_controller, request->io_tag); } - if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) { + if (request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) { scic_sds_controller_release_frame( - this_request->owning_controller, this_request->saved_rx_frame_index); + request->owning_controller, request->saved_rx_frame_index); } - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_FINAL - ); - + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_FINAL); return SCI_SUCCESS; } @@ -1641,11 +1534,7 @@ static enum sci_status scic_sds_request_completed_state_complete_handler( * * ABORTING STATE HANDLERS * ***************************************************************************** */ -/** - * scic_sds_request_aborting_state_abort_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_terminate() request. This method is the * io request aborting state abort handlers. On receipt of a multiple @@ -1653,23 +1542,14 @@ static enum sci_status scic_sds_request_completed_state_complete_handler( * This should not happen in normal operation. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_request_aborting_state_abort_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *this_request = (struct scic_sds_request *)request; - - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } -/** - * scic_sds_request_aborting_state_tc_completion_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_task_completion() request. This method * decodes the completion type waiting for the abort task complete @@ -1687,10 +1567,8 @@ static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED ); - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + sci_base_state_machine_change_state(&this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; default: @@ -1703,11 +1581,7 @@ static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( return SCI_SUCCESS; } -/** - * scic_sds_request_aborting_state_frame_handler() - - * @request: This is the struct sci_base_request object that is cast to the - * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. - * +/* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_frame_handler() request. This method * discards the unsolicited frame since we are waiting for the abort task @@ -1727,58 +1601,58 @@ static enum sci_status scic_sds_request_aborting_state_frame_handler( static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_default_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_default_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, }, [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { - .parent.start_handler = scic_sds_request_constructed_state_start_handler, - .parent.abort_handler = scic_sds_request_constructed_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_constructed_state_start_handler, + .abort_handler = scic_sds_request_constructed_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, }, [SCI_BASE_REQUEST_STATE_STARTED] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_started_state_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_started_state_frame_handler, }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_default_abort_handler, - .parent.complete_handler = scic_sds_request_completed_state_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_default_abort_handler, + .complete_handler = scic_sds_request_completed_state_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, }, [SCI_BASE_REQUEST_STATE_ABORTING] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_aborting_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_aborting_state_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_aborting_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_aborting_state_frame_handler, }, [SCI_BASE_REQUEST_STATE_FINAL] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_default_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_default_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, }, }; @@ -1978,7 +1852,11 @@ static void scic_sds_general_request_construct(struct scic_sds_controller *scic, void *user_io_request_object, struct scic_sds_request *sci_req) { - sci_base_request_construct(&sci_req->parent, scic_sds_request_state_table); + sci_req->parent.private = NULL; + sci_base_state_machine_construct(&sci_req->state_machine, &sci_req->parent, + scic_sds_request_state_table, SCI_BASE_REQUEST_STATE_INITIAL); + sci_base_state_machine_start(&sci_req->state_machine); + sci_req->io_tag = io_tag; sci_req->user_request = user_io_request_object; sci_req->owning_controller = scic; @@ -2070,7 +1948,7 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, /* Construct the started sub-state machine. */ sci_base_state_machine_construct( &sci_req->started_substate_machine, - &sci_req->parent.parent, + &sci_req->parent, scic_sds_io_request_started_task_mgmt_substate_table, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION ); diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 286b74943d68..5b0f88596370 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -64,8 +64,7 @@ */ #include "scic_io_request.h" - -#include "sci_base_request.h" +#include "sci_base_state_machine.h" #include "scu_task_context.h" #include "intel_sas.h" @@ -127,9 +126,15 @@ enum scic_sds_smp_request_started_substates { */ struct scic_sds_request { /** - * This field indictes the parent object of the request. + * The field specifies that the parent object for the base request is the + * base object itself. */ - struct sci_base_request parent; + struct sci_base_object parent; + + /** + * This field contains the information for the base request state machine. + */ + struct sci_base_state_machine state_machine; void *user_request; @@ -231,15 +236,59 @@ struct scic_sds_request { }; +/** + * enum sci_base_request_states - This enumeration depicts all the states for + * the common request state machine. + * + * + */ +enum sci_base_request_states { + /** + * Simply the initial state for the base request state machine. + */ + SCI_BASE_REQUEST_STATE_INITIAL, + + /** + * This state indicates that the request has been constructed. This state + * is entered from the INITIAL state. + */ + SCI_BASE_REQUEST_STATE_CONSTRUCTED, + + /** + * This state indicates that the request has been started. This state is + * entered from the CONSTRUCTED state. + */ + SCI_BASE_REQUEST_STATE_STARTED, + + /** + * This state indicates that the request has completed. + * This state is entered from the STARTED state. This state is entered from + * the ABORTING state. + */ + SCI_BASE_REQUEST_STATE_COMPLETED, -typedef enum sci_status -(*scic_sds_io_request_frame_handler_t)(struct scic_sds_request *req, u32 frame); + /** + * This state indicates that the request is in the process of being + * terminated/aborted. + * This state is entered from the CONSTRUCTED state. + * This state is entered from the STARTED state. + */ + SCI_BASE_REQUEST_STATE_ABORTING, -typedef enum sci_status -(*scic_sds_io_request_event_handler_t)(struct scic_sds_request *req, u32 event); + /** + * Simply the final state for the base request state machine. + */ + SCI_BASE_REQUEST_STATE_FINAL, +}; -typedef enum sci_status -(*scic_sds_io_request_task_completion_handler_t)(struct scic_sds_request *req, u32 completion_code); +typedef enum sci_status (*scic_sds_io_request_handler_t) + (struct scic_sds_request *request); +typedef enum sci_status (*scic_sds_io_request_frame_handler_t) + (struct scic_sds_request *req, u32 frame); +typedef enum sci_status (*scic_sds_io_request_event_handler_t) + (struct scic_sds_request *req, u32 event); +typedef enum sci_status (*scic_sds_io_request_task_completion_handler_t) + (struct scic_sds_request *req, u32 completion_code); /** * struct scic_sds_io_request_state_handler - This is the SDS core definition @@ -248,7 +297,30 @@ typedef enum sci_status * */ struct scic_sds_io_request_state_handler { - struct sci_base_request_state_handler parent; + /** + * The start_handler specifies the method invoked when a user attempts to + * start a request. + */ + scic_sds_io_request_handler_t start_handler; + + /** + * The abort_handler specifies the method invoked when a user attempts to + * abort a request. + */ + scic_sds_io_request_handler_t abort_handler; + + /** + * The complete_handler specifies the method invoked when a user attempts to + * complete a request. + */ + scic_sds_io_request_handler_t complete_handler; + + /** + * The destruct_handler specifies the method invoked when a user attempts to + * destruct a request. + */ + scic_sds_io_request_handler_t destruct_handler; + scic_sds_io_request_task_completion_handler_t tc_completion_handler; scic_sds_io_request_event_handler_t event_handler; @@ -319,7 +391,7 @@ extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substat } #define scic_sds_request_complete(a_request) \ - ((a_request)->state_handlers->parent.complete_handler(&(a_request)->parent)) + ((a_request)->state_handlers->complete_handler(a_request)) @@ -331,15 +403,15 @@ extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substat * struct scic_sds_io_request object. */ #define scic_sds_io_request_tc_completion(this_request, completion_code) \ - { \ - if (this_request->parent.state_machine.current_state_id \ - == SCI_BASE_REQUEST_STATE_STARTED \ - && this_request->has_started_substate_machine \ - == false) \ - scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \ - else \ - this_request->state_handlers->tc_completion_handler(this_request, completion_code); \ - } +{ \ + if (this_request->state_machine.current_state_id \ + == SCI_BASE_REQUEST_STATE_STARTED \ + && this_request->has_started_substate_machine \ + == false) \ + scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \ + else \ + this_request->state_handlers->tc_completion_handler(this_request, completion_code); \ +} /** * SCU_SGL_ZERO() - @@ -426,14 +498,14 @@ enum sci_status scic_sds_task_request_terminate( * ***************************************************************************** */ enum sci_status scic_sds_request_default_start_handler( - struct sci_base_request *this_request); + struct scic_sds_request *request); enum sci_status scic_sds_request_default_complete_handler( - struct sci_base_request *this_request); + struct scic_sds_request *request); enum sci_status scic_sds_request_default_destruct_handler( - struct sci_base_request *this_request); + struct scic_sds_request *request); enum sci_status scic_sds_request_default_tc_completion_handler( struct scic_sds_request *this_request, @@ -453,7 +525,7 @@ enum sci_status scic_sds_request_default_frame_handler( * ***************************************************************************** */ enum sci_status scic_sds_request_started_state_abort_handler( - struct sci_base_request *this_request); + struct scic_sds_request *request); enum sci_status scic_sds_request_started_state_tc_completion_handler( struct scic_sds_request *this_request, diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index 06cb93221b4c..040a3d8c08b9 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -78,29 +78,24 @@ */ static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { enum sci_status status; struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - struct scic_sds_request *io_request = (struct scic_sds_request *)request; /* Will the port allow the io request to start? */ status = this_device->owning_port->state_handlers->start_io_handler( - this_device->owning_port, - this_device, - io_request - ); + this_device->owning_port, this_device, request); if (status == SCI_SUCCESS) { status = - scic_sds_remote_node_context_start_io(this_device->rnc, io_request); + scic_sds_remote_node_context_start_io(this_device->rnc, request); - if (status == SCI_SUCCESS) { - status = scic_sds_request_start(io_request); - } + if (status == SCI_SUCCESS) + status = scic_sds_request_start(request); if (status == SCI_SUCCESS) { - this_device->working_request = io_request; + this_device->working_request = request; sci_base_state_machine_change_state( &this_device->ready_substate_machine, @@ -108,7 +103,7 @@ static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_h ); } - scic_sds_remote_device_start_request(this_device, io_request, status); + scic_sds_remote_device_start_request(this_device, request, status); } return status; @@ -129,7 +124,7 @@ static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_h */ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { return SCI_FAILURE_INVALID_STATE; } @@ -144,7 +139,7 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_ha */ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { enum sci_status status; struct scic_sds_remote_device *this_device; diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 84b0fdd7ed91..9293c2d5fc91 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -394,7 +394,7 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &this_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); } @@ -433,9 +433,8 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): @@ -452,9 +451,8 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; default: @@ -468,9 +466,8 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -502,9 +499,8 @@ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_ha ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; default: @@ -518,9 +514,8 @@ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_ha ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -530,22 +525,22 @@ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_ha static const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_smp_request_await_response_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_smp_request_await_response_frame_handler, }, [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, } }; @@ -626,7 +621,7 @@ enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) /* Construct the started sub-state machine. */ sci_base_state_machine_construct( &sci_req->started_substate_machine, - &sci_req->parent.parent, + &sci_req->parent, scic_sds_smp_request_started_substate_table, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE ); @@ -657,10 +652,8 @@ enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) scu_smp_request_construct_task_context(sci_req, smp_req); - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); kfree(smp_req); diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index c9aa35f5cd15..1eecb19c3ad6 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -120,10 +120,8 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + sci_base_state_machine_change_state(&this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -143,20 +141,12 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi * pattern for this particular device). */ static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *this_request = (struct scic_sds_request *)request; - - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_ABORTING - ); - - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_ABORTING); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } @@ -176,41 +166,36 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler * probably update to check frame type and make sure it is a response frame. */ static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *request, u32 frame_index) { - scic_sds_io_request_copy_response(this_request); - - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - - scic_sds_controller_release_frame( - this_request->owning_controller, frame_index - ); + scic_sds_io_request_copy_response(request); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + scic_sds_controller_release_frame(request->owning_controller, + frame_index); return SCI_SUCCESS; } static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, }, [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, } }; diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c index 9635b37fad16..2d551ad3a46c 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c @@ -659,16 +659,12 @@ enum sci_status scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_ha } enum sci_status scic_sds_stp_packet_request_started_completion_delay_complete_handler( - struct sci_base_request *request) + struct scic_sds_request *request) { - struct scic_sds_request *this_request = (struct scic_sds_request *)request; + sci_base_state_machine_change_state(&request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - - return this_request->sci_status; + return request->sci_status; } /* --------------------------------------------------------------------------- */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index 0a00a40bdbbe..bb582497039b 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -78,22 +78,20 @@ */ static enum sci_status scic_sds_stp_remote_device_complete_request( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - struct scic_sds_request *the_request = (struct scic_sds_request *)request; enum sci_status status; - status = scic_sds_io_request_complete(the_request); + status = scic_sds_io_request_complete(request); if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( - this_device->owning_port, this_device, the_request - ); + this_device->owning_port, this_device, request); if (status == SCI_SUCCESS) { scic_sds_remote_device_decrement_request_count(this_device); - if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + if (request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { /* * This request causes hardware error, device needs to be Lun Reset. * So here we force the state machine to IDLE state so the rest IOs @@ -119,7 +117,7 @@ static enum sci_status scic_sds_stp_remote_device_complete_request( __func__, this_device->owning_port, this_device, - the_request, + request, status); return status; @@ -143,64 +141,54 @@ static enum sci_status scic_sds_stp_remote_device_complete_request( */ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { enum sci_status status; struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - struct scic_sds_request *this_request = (struct scic_sds_request *)request; /* Will the port allow the io request to start? */ status = this_device->owning_port->state_handlers->start_io_handler( - this_device->owning_port, - this_device, - this_request - ); - - if (SCI_SUCCESS == status) { - status = - scic_sds_remote_node_context_start_task(this_device->rnc, this_request); - - if (SCI_SUCCESS == status) { - status = this_request->state_handlers->parent.start_handler(request); - } - - if (status == SCI_SUCCESS) { - /* - * / @note If the remote device state is not IDLE this will replace - * / the request that probably resulted in the task management - * / request. */ - this_device->working_request = this_request; - - sci_base_state_machine_change_state( - &this_device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD - ); + this_device->owning_port, this_device, request); + if (status != SCI_SUCCESS) + return status; - /* - * The remote node context must cleanup the TCi to NCQ mapping table. - * The only way to do this correctly is to either write to the TLCR - * register or to invalidate and repost the RNC. In either case the - * remote node context state machine will take the correct action when - * the remote node context is suspended and later resumed. */ - scic_sds_remote_node_context_suspend( - this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); - - scic_sds_remote_node_context_resume( - this_device->rnc, - scic_sds_remote_device_continue_request, - this_device); - } + status = scic_sds_remote_node_context_start_task(this_device->rnc, request); + if (status != SCI_SUCCESS) + goto out; - scic_sds_remote_device_start_request(this_device, this_request, status); + status = request->state_handlers->start_handler(request); + if (status != SCI_SUCCESS) + goto out; - /* - * We need to let the controller start request handler know that it can't - * post TC yet. We will provide a callback function to post TC when RNC gets - * resumed. */ - return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; - } + /* + * Note: If the remote device state is not IDLE this will replace + * the request that probably resulted in the task management request. + */ + this_device->working_request = request; + sci_base_state_machine_change_state(&this_device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - return status; + /* + * The remote node context must cleanup the TCi to NCQ mapping table. + * The only way to do this correctly is to either write to the TLCR + * register or to invalidate and repost the RNC. In either case the + * remote node context state machine will take the correct action when + * the remote node context is suspended and later resumed. + */ + scic_sds_remote_node_context_suspend(this_device->rnc, + SCI_SOFTWARE_SUSPENSION, NULL, NULL); + scic_sds_remote_node_context_resume(this_device->rnc, + scic_sds_remote_device_continue_request, + this_device); + +out: + scic_sds_remote_device_start_request(this_device, request, status); + /* + * We need to let the controller start request handler know that it can't + * post TC yet. We will provide a callback function to post TC when RNC gets + * resumed. + */ + return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; } /* @@ -221,53 +209,39 @@ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_h */ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( struct sci_base_remote_device *base_device, - struct sci_base_request *base_request) + struct scic_sds_request *request) { enum sci_status status; struct scic_sds_remote_device *device = (struct scic_sds_remote_device *)&base_device->parent; - struct scic_sds_request *sds_request = - (struct scic_sds_request *)&base_request->parent; struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sds_request); + (struct isci_request *)sci_object_get_association(request); /* Will the port allow the io request to start? */ status = device->owning_port->state_handlers->start_io_handler( - device->owning_port, - device, - sds_request); - - if (status == SCI_SUCCESS) { - status = - scic_sds_remote_node_context_start_io(device->rnc, - sds_request); - - if (status == SCI_SUCCESS) - status = - sds_request->state_handlers-> - parent.start_handler(base_request); + device->owning_port, device, request); + if (status != SCI_SUCCESS) + return status; - if (status == SCI_SUCCESS) { - if (isci_sata_get_sat_protocol(isci_request) == - SAT_PROTOCOL_FPDMA) - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); - else { - device->working_request = sds_request; + status = scic_sds_remote_node_context_start_io(device->rnc, request); + if (status != SCI_SUCCESS) + goto out; - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - } - } + status = request->state_handlers->start_handler(request); + if (status != SCI_SUCCESS) + goto out; - scic_sds_remote_device_start_request(device, - sds_request, - status); + if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { + sci_base_state_machine_change_state(&device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); + } else { + device->working_request = request; + sci_base_state_machine_change_state(&device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); } - +out: + scic_sds_remote_device_start_request(device, request, status); return status; } @@ -308,33 +282,30 @@ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_hand static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( struct sci_base_remote_device *base_device, - struct sci_base_request *base_request) + struct scic_sds_request *request) { enum sci_status status; struct scic_sds_remote_device *device = (struct scic_sds_remote_device *)&base_device->parent; - struct scic_sds_request *sds_request = - (struct scic_sds_request *)&base_request->parent; struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sds_request); + (struct isci_request *)sci_object_get_association(request); if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { status = device->owning_port->state_handlers->start_io_handler( device->owning_port, device, - sds_request); + request); if (status == SCI_SUCCESS) { status = scic_sds_remote_node_context_start_io( device->rnc, - sds_request); + request); if (status == SCI_SUCCESS) - status = sds_request->state_handlers-> - parent.start_handler(base_request); + status = request->state_handlers->start_handler(request); scic_sds_remote_device_start_request(device, - sds_request, + request, status); } } else @@ -422,7 +393,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl */ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { return SCI_FAILURE_INVALID_STATE; } @@ -475,7 +446,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handl * ***************************************************************************** */ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; } @@ -494,7 +465,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_sta */ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( struct sci_base_remote_device *device, - struct sci_base_request *request) + struct scic_sds_request *request) { struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; struct scic_sds_request *the_request = (struct scic_sds_request *)request; diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 5dd4896576d4..6d0a17866aac 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -465,8 +465,7 @@ static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_han ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED - ); + &this_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -495,7 +494,7 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; status = scic_sds_unsolicited_frame_control_get_header( - &(this_request->parent.owning_controller->uf_control), + &this_request->parent.owning_controller->uf_control, frame_index, (void **)&frame_header ); @@ -504,7 +503,7 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( switch (frame_header->fis_type) { case SATA_FIS_TYPE_REGD2H: scic_sds_unsolicited_frame_control_get_buffer( - &(this_request->parent.owning_controller->uf_control), + &this_request->parent.owning_controller->uf_control, frame_index, (void **)&frame_buffer ); @@ -536,14 +535,13 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( } sci_base_state_machine_change_state( - &this_request->parent.parent.state_machine, + &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame( - this_request->parent.owning_controller, frame_index - ); + this_request->parent.owning_controller, frame_index); } else dev_err(scic_to_dev(request->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " @@ -557,22 +555,22 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, } }; @@ -625,7 +623,7 @@ enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); sci_base_state_machine_construct(&sci_req->started_substate_machine, - &sci_req->parent.parent, + &sci_req->parent, scic_sds_stp_request_started_non_data_substate_table, SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE); @@ -677,8 +675,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( scic = this_request->owning_controller; state = scic->state_machine.current_state_id; continue_io = scic_sds_controller_state_handler_table[state].continue_io; - return continue_io(scic, &this_request->target_device->parent, - &this_request->parent); + return continue_io(scic, &this_request->target_device->parent, this_request); } /** @@ -859,7 +856,7 @@ static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completi ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &this_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; @@ -961,7 +958,7 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( ); sci_base_state_machine_change_state( - &this_request->parent.parent.state_machine, + &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); } else { @@ -1056,12 +1053,12 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler ); sci_base_state_machine_change_state( - &this_request->parent.parent.state_machine, + &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); } else { sci_base_state_machine_change_state( - &this_request->parent.started_substate_machine, + &request->started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE ); } @@ -1083,7 +1080,7 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler ); sci_base_state_machine_change_state( - &this_request->parent.parent.state_machine, + &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); @@ -1160,7 +1157,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_com ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &this_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; @@ -1215,40 +1212,40 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, - .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, + .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, } }; @@ -1352,7 +1349,7 @@ enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_ } sci_base_state_machine_construct(&sci_req->started_substate_machine, - &sci_req->parent.parent, + &sci_req->parent, scic_sds_stp_request_started_pio_substate_table, SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE); @@ -1360,18 +1357,13 @@ enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_ } static void scic_sds_stp_request_udma_complete_request( - struct scic_sds_request *this_request, + struct scic_sds_request *request, u32 scu_status, enum sci_status sci_status) { - scic_sds_request_set_status( - this_request, scu_status, sci_status - ); - - sci_base_state_machine_change_state( - &this_request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + scic_sds_request_set_status(request, scu_status, sci_status); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); } /** @@ -1518,22 +1510,22 @@ static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_stp_request_udma_general_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_udma_general_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, }, }; @@ -1590,7 +1582,7 @@ enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci sci_base_state_machine_construct( &sci_req->started_substate_machine, - &sci_req->parent.parent, + &sci_req->parent, scic_sds_stp_request_started_udma_substate_table, SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE ); @@ -1635,8 +1627,7 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_com ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED - ); + &this_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -1679,9 +1670,8 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_c SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); - sci_base_state_machine_change_state( - &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED - ); + sci_base_state_machine_change_state(&this_request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -1753,9 +1743,8 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( } sci_base_state_machine_change_state( - &this_request->parent.parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &this_request->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame( @@ -1774,31 +1763,31 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_request_default_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, + .start_handler = scic_sds_request_default_start_handler, + .abort_handler = scic_sds_request_started_state_abort_handler, + .complete_handler = scic_sds_request_default_complete_handler, + .destruct_handler = scic_sds_request_default_destruct_handler, + .tc_completion_handler = scic_sds_request_default_tc_completion_handler, + .event_handler = scic_sds_request_default_event_handler, + .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, }, }; @@ -1842,8 +1831,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet state = scic->state_machine.current_state_id; continue_io = scic_sds_controller_state_handler_table[state].continue_io; - status = continue_io(scic, &this_request->target_device->parent, - &this_request->parent); + status = continue_io(scic, &this_request->target_device->parent, this_request); if (status == SCI_SUCCESS) { SET_STATE_HANDLER( @@ -1888,7 +1876,7 @@ enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_reques scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); sci_base_state_machine_construct(&sci_req->started_substate_machine, - &sci_req->parent.parent, + &sci_req->parent, scic_sds_stp_request_started_soft_reset_substate_table, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE); -- cgit v1.2.3 From 78141676784ed190ce2546f97a7d6368f21e450b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 31 Mar 2011 11:01:39 -0400 Subject: isci: kill dead data structurs in scic_io_request.h Signed-off-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_io_request.h | 180 -------------------------- drivers/scsi/isci/core/scic_sds_stp_request.h | 4 - 2 files changed, 184 deletions(-) diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h index fea894a0d28e..1ac530d2d3bd 100644 --- a/drivers/scsi/isci/core/scic_io_request.h +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -71,186 +71,6 @@ struct scic_sds_request; struct scic_sds_remote_device; struct scic_sds_controller; -/** - * struct scic_io_parameters - This structure contains additional optional - * parameters for SSP IO requests. These parameters are utilized with the - * scic_io_request_construct_advanced_ssp() method. - * - * Add Block-guard/DIF, TLR - */ -struct scic_io_parameters { - /** - * This sub-structure contains SCSI specific features (for use with SSP - * IO requests). - */ - struct { - /** - * Data Integrity Format (DIF) is also known as protection information - * or block-guard. This sub-structure contains DIF specific feature - * information for SSP IO requests. - */ - struct { - void *placeholder; - } dif; - - /** - * Transport Layer Retries (TLR) is an SSP protocol specific feature. - * This sub-structure contains Transport Layer Retries (TLR) specific - * feature information for SSP IO requests. - */ - struct { - void *placeholder; - } tlr; - - } scsi; - -}; - -/** - * struct scic_passthru_request_callbacks - This structure contains the pointer - * to the callback functions for constructing the passthrough request common - * to SSP, SMP and STP. This structure must be set by the win sci layer - * before the passthrough build is called - * - * - */ -struct scic_passthru_request_callbacks { - /** - * Function pointer to get the phy identifier for passthrough request. - */ - u32 (*scic_cb_passthru_get_phy_identifier)(void *, u8 *); - /** - * Function pointer to get the port identifier for passthrough request. - */ - u32 (*scic_cb_passthru_get_port_identifier)(void *, u8 *); - /** - * Function pointer to get the connection rate for passthrough request. - */ - u32 (*scic_cb_passthru_get_connection_rate)(void *, void *); - /** - * Function pointer to get the destination sas address for passthrough request. - */ - void (*scic_cb_passthru_get_destination_sas_address)(void *, u8 **); - /** - * Function pointer to get the transfer length for passthrough request. - */ - u32 (*scic_cb_passthru_get_transfer_length)(void *); - /** - * Function pointer to get the data direction for passthrough request. - */ - u32 (*scic_cb_passthru_get_data_direction)(void *); - -}; - -/** - * struct scic_ssp_passthru_request_callbacks - This structure contains the - * pointer to the callback functions for constructing the passthrough - * request specific to SSP. This structure must be set by the win sci layer - * before the passthrough build is called - * - * - */ -struct scic_ssp_passthru_request_callbacks { - /** - * Common callbacks for all Passthru requests - */ - struct scic_passthru_request_callbacks common_callbacks; - /** - * Function pointer to get the lun for passthrough request. - */ - void (*scic_cb_ssp_passthru_get_lun)(void *, u8 **); - /** - * Function pointer to get the cdb - */ - void (*scic_cb_ssp_passthru_get_cdb)(void *, u32 *, u8 **, u32 *, u8 **); - /** - * Function pointer to get the task attribute for passthrough request. - */ - u32 (*scic_cb_ssp_passthru_get_task_attribute)(void *); -}; - -/** - * struct scic_stp_passthru_request_callbacks - This structure contains the - * pointer to the callback functions for constructing the passthrough - * request specific to STP. This structure must be set by the win sci layer - * before the passthrough build is called - * - * - */ -struct scic_stp_passthru_request_callbacks { - /** - * Common callbacks for all Passthru requests - */ - struct scic_passthru_request_callbacks common_callbacks; - /** - * Function pointer to get the protocol for passthrough request. - */ - u8 (*scic_cb_stp_passthru_get_protocol)(void *); - /** - * Function pointer to get the resgister fis - */ - void (*scic_cb_stp_passthru_get_register_fis)(void *, u8 **); - /** - * Function pointer to get the MULTIPLE_COUNT (bits 5,6,7 in Byte 1 in the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) - */ - u8 (*scic_cb_stp_passthru_get_multiplecount)(void *); - /** - * Function pointer to get the EXTEND (bit 0 in Byte 1 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) - */ - u8 (*scic_cb_stp_passthru_get_extend)(void *); - /** - * Function pointer to get the CK_COND (bit 5 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) - */ - u8 (*scic_cb_stp_passthru_get_ckcond)(void *); - /** - * Function pointer to get the T_DIR (bit 3 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) - */ - u8 (*scic_cb_stp_passthru_get_tdir)(void *); - /** - * Function pointer to get the BYTE_BLOCK (bit 2 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) - */ - u8 (*scic_cb_stp_passthru_get_byteblock)(void *); - /** - * Function pointer to get the T_LENGTH (bits 0,1 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) - */ - u8 (*scic_cb_stp_passthru_get_tlength)(void *); - -}; - -/** - * struct scic_smp_passthru_request_callbacks - This structure contains the - * pointer to the callback functions for constructing the passthrough - * request specific to SMP. This structure must be set by the win sci layer - * before the passthrough build is called - * - * - */ -struct scic_smp_passthru_request_callbacks { - /** - * Common callbacks for all Passthru requests - */ - struct scic_passthru_request_callbacks common_callbacks; - - /** - * Function pointer to get the length of the smp request and its length - */ - u32 (*scic_cb_smp_passthru_get_request)(void *, u8 **); - /** - * Function pointer to get the frame type of the smp request - */ - u8 (*scic_cb_smp_passthru_get_frame_type)(void *); - /** - * Function pointer to get the function in the the smp request - */ - u8 (*scic_cb_smp_passthru_get_function)(void *); - - /** - * Function pointer to get the "allocated response length" in the the smp request - */ - u8 (*scic_cb_smp_passthru_get_allocated_response_length)(void *); - -}; - /** * This enumeration specifies the transport protocol utilized for the request. * diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index cb4d2d626639..a6c02d3cba50 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -176,10 +176,6 @@ enum sci_status scic_sds_stp_pio_request_construct( u8 sat_protocol, bool copy_rx_frame); -enum sci_status scic_sds_stp_pio_request_construct_pass_through( - struct scic_sds_request *scic_io_request, - struct scic_stp_passthru_request_callbacks *passthru_cb); - enum sci_status scic_sds_stp_udma_request_construct( struct scic_sds_request *this_request, u32 transfer_length, -- cgit v1.2.3 From 524b5f723be8a1d966c1285d69810bc461f181c2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 31 Mar 2011 11:06:16 -0400 Subject: isci: simplify request state handlers Instead of filling up tables with default handlers call the default handler in the only caller. IMHO the whole state handlers concept is not very suitable for the isci request. For example there is a single real instance of the start handler, and we'd be much better off just having a check for the right state in the only caller, than all this mess. It's quite similar for the abort handler as well. Even the actual state machine has a lot of states that are rather pointless. The initial and constructed states are not needed at all as the request is not reachable for calls before it's fully set up and started. And the abort state should be replaced with an abort actions and a state transition to the completed state. Signed-off-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_request.c | 287 ++++++--------------- drivers/scsi/isci/core/scic_sds_request.h | 54 +--- drivers/scsi/isci/core/scic_sds_smp_request.c | 9 - drivers/scsi/isci/core/scic_sds_ssp_request.c | 10 - .../scsi/isci/core/scic_sds_stp_packet_request.c | 24 -- drivers/scsi/isci/core/scic_sds_stp_request.c | 53 ---- 6 files changed, 80 insertions(+), 357 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 7c21de0cc3a6..191b5d0f1a53 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -874,67 +874,93 @@ u32 scic_io_request_get_number_of_bytes_transferred( * * SCIC SDS Interface Implementation * **************************************************************************** */ -/** - * - * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start - * operation is to be executed. - * - * This method invokes the base state start request handler for the - * SCIC_SDS_IO_REQUEST_T object. enum sci_status - */ enum sci_status scic_sds_request_start(struct scic_sds_request *request) { - if (request->device_sequence == + if (request->device_sequence != scic_sds_remote_device_get_sequence(request->target_device)) + return SCI_FAILURE; + + if (request->state_handlers->start_handler) return request->state_handlers->start_handler(request); - return SCI_FAILURE; + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request requested to start while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state(&request->state_machine)); + + return SCI_FAILURE_INVALID_STATE; } -/** - * - * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start - * operation is to be executed. - * - * This method invokes the base state terminate request handber for the - * SCIC_SDS_IO_REQUEST_T object. enum sci_status - */ enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *request) { - return request->state_handlers->abort_handler(request); + if (request->state_handlers->abort_handler) + return request->state_handlers->abort_handler(request); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request requested to abort while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state(&request->state_machine)); + + return SCI_FAILURE_INVALID_STATE; } -/** - * - * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start - * operation is to be executed. - * - * This method invokes the base state request completion handler for the - * SCIC_SDS_IO_REQUEST_T object. enum sci_status - */ enum sci_status scic_sds_io_request_complete(struct scic_sds_request *request) { - return request->state_handlers->complete_handler(request); + if (request->state_handlers->complete_handler) + return request->state_handlers->complete_handler(request); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request requested to complete while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state(&request->state_machine)); + + return SCI_FAILURE_INVALID_STATE; } -/** - * - * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start - * operation is to be executed. - * @event_code: The event code returned by the hardware for the task reqeust. - * - * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T - * object. enum sci_status - */ enum sci_status scic_sds_io_request_event_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *request, u32 event_code) { - return this_request->state_handlers->event_handler(this_request, event_code); + if (request->state_handlers->event_handler) + return request->state_handlers->event_handler(request, event_code); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request given event code notification %x while " + "in wrong state %d\n", + __func__, + event_code, + sci_base_state_machine_get_state(&request->state_machine)); + + return SCI_FAILURE_INVALID_STATE; } +enum sci_status +scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code) +{ + if (request->state_machine.current_state_id == SCI_BASE_REQUEST_STATE_STARTED && + request->has_started_substate_machine == false) + return scic_sds_request_started_state_tc_completion_handler(request, completion_code); + else if (request->state_handlers->tc_completion_handler) + return request->state_handlers->tc_completion_handler(request, completion_code); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request given task completion notification %x " + "while in wrong state %d\n", + __func__, + completion_code, + sci_base_state_machine_get_state(&request->state_machine)); + + return SCI_FAILURE_INVALID_STATE; + +} + + /** * * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start @@ -946,10 +972,21 @@ enum sci_status scic_sds_io_request_event_handler( * SCIC_SDS_IO_REQUEST_T object. enum sci_status */ enum sci_status scic_sds_io_request_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *request, u32 frame_index) { - return this_request->state_handlers->frame_handler(this_request, frame_index); + if (request->state_handlers->frame_handler) + return request->state_handlers->frame_handler(request, frame_index); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request given unexpected frame %x while in " + "state %d\n", + __func__, + frame_index, + sci_base_state_machine_get_state(&request->state_machine)); + + scic_sds_controller_release_frame(request->owning_controller, frame_index); + return SCI_FAILURE_INVALID_STATE; } /** @@ -1001,141 +1038,6 @@ void scic_sds_io_request_copy_response(struct scic_sds_request *sds_request) memcpy(response_buffer, ssp_response->data, user_response_length); } -/* - * ***************************************************************************** - * * DEFAULT STATE HANDLERS - * ***************************************************************************** */ - -/* - * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_start() request. The default action is - * to log a warning and return a failure status. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_request_default_start_handler( - struct scic_sds_request *request) -{ - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to start while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_request_default_abort_handler( - struct scic_sds_request *request) -{ - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to abort while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/* - * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_complete() request. The default action - * is to log a warning and return a failure status. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_request_default_complete_handler( - struct scic_sds_request *request) -{ - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to complete while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/* - * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_complete() request. The default action - * is to log a warning and return a failure status. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_request_default_destruct_handler( - struct scic_sds_request *request) -{ - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to destroy while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_task_request_complete() request. The default - * action is to log a warning and return a failure status. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_request_default_tc_completion_handler( - struct scic_sds_request *request, - u32 completion_code) -{ - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given task completion notification %x " - "while in wrong state %d\n", - __func__, - completion_code, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; - -} - -/* - * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_event_handler() request. The default - * action is to log a warning and return a failure status. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_request_default_event_handler( - struct scic_sds_request *request, - u32 event_code) -{ - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given event code notification %x while " - "in wrong state %d\n", - __func__, - event_code, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/* - * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_event_handler() request. The default - * action is to log a warning and return a failure status. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_request_default_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given unexpected frame %x while in " - "state %d\n", - __func__, - frame_index, - sci_base_state_machine_get_state(&request->state_machine)); - - scic_sds_controller_release_frame( - request->owning_controller, frame_index); - - return SCI_FAILURE_INVALID_STATE; -} - /* * ***************************************************************************** * * CONSTRUCTED STATE HANDLERS @@ -1601,58 +1503,25 @@ static enum sci_status scic_sds_request_aborting_state_frame_handler( static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { - .start_handler = scic_sds_request_default_start_handler, - .abort_handler = scic_sds_request_default_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, }, [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { .start_handler = scic_sds_request_constructed_state_start_handler, .abort_handler = scic_sds_request_constructed_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, }, [SCI_BASE_REQUEST_STATE_STARTED] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_request_started_state_frame_handler, }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { - .start_handler = scic_sds_request_default_start_handler, - .abort_handler = scic_sds_request_default_abort_handler, .complete_handler = scic_sds_request_completed_state_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, }, [SCI_BASE_REQUEST_STATE_ABORTING] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_aborting_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_request_aborting_state_frame_handler, }, [SCI_BASE_REQUEST_STATE_FINAL] = { - .start_handler = scic_sds_request_default_start_handler, - .abort_handler = scic_sds_request_default_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, }, }; diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 5b0f88596370..423567a62901 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -315,13 +315,6 @@ struct scic_sds_io_request_state_handler { */ scic_sds_io_request_handler_t complete_handler; - /** - * The destruct_handler specifies the method invoked when a user attempts to - * destruct a request. - */ - scic_sds_io_request_handler_t destruct_handler; - - scic_sds_io_request_task_completion_handler_t tc_completion_handler; scic_sds_io_request_event_handler_t event_handler; scic_sds_io_request_frame_handler_t frame_handler; @@ -394,24 +387,8 @@ extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substat ((a_request)->state_handlers->complete_handler(a_request)) - - -/** - * scic_sds_io_request_tc_completion() - - * - * This macro invokes the core state task completion handler for the - * struct scic_sds_io_request object. - */ -#define scic_sds_io_request_tc_completion(this_request, completion_code) \ -{ \ - if (this_request->state_machine.current_state_id \ - == SCI_BASE_REQUEST_STATE_STARTED \ - && this_request->has_started_substate_machine \ - == false) \ - scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \ - else \ - this_request->state_handlers->tc_completion_handler(this_request, completion_code); \ -} +extern enum sci_status +scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code); /** * SCU_SGL_ZERO() - @@ -492,33 +469,6 @@ enum sci_status scic_sds_io_request_frame_handler( enum sci_status scic_sds_task_request_terminate( struct scic_sds_request *this_request); -/* - * ***************************************************************************** - * * DEFAULT STATE HANDLERS - * ***************************************************************************** */ - -enum sci_status scic_sds_request_default_start_handler( - struct scic_sds_request *request); - - -enum sci_status scic_sds_request_default_complete_handler( - struct scic_sds_request *request); - -enum sci_status scic_sds_request_default_destruct_handler( - struct scic_sds_request *request); - -enum sci_status scic_sds_request_default_tc_completion_handler( - struct scic_sds_request *this_request, - u32 completion_code); - -enum sci_status scic_sds_request_default_event_handler( - struct scic_sds_request *this_request, - u32 event_code); - -enum sci_status scic_sds_request_default_frame_handler( - struct scic_sds_request *this_request, - u32 frame_index); - /* * ***************************************************************************** * * STARTED STATE HANDLERS diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 9293c2d5fc91..70bc8d2cf048 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -525,22 +525,13 @@ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_ha static const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_smp_request_await_response_frame_handler, }, [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, } }; diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index 1eecb19c3ad6..4d3a21b6ac03 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -180,21 +180,11 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, }, [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, } }; diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c index 2d551ad3a46c..25c68cef298e 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c @@ -671,49 +671,25 @@ enum sci_status scic_sds_stp_packet_request_started_completion_delay_complete_ha const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[] = { [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler .tc_completion_handler = scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler }, [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler }, [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler .tc_completion_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler }, [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_request_default_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler }, [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = { - .parent.start_handler = scic_sds_request_default_start_handler, .parent.abort_handler = scic_sds_request_started_state_abort_handler, .parent.complete_handler = scic_sds_stp_packet_request_started_completion_delay_complete_handler, - .parent.destruct_handler = scic_sds_request_default_destruct_handler - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler }, }; diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 6d0a17866aac..0b3bc65b8a2b 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -555,21 +555,11 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, } }; @@ -1212,40 +1202,21 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, } }; @@ -1510,21 +1481,12 @@ static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_stp_request_udma_general_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, }, }; @@ -1763,30 +1725,15 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, - .frame_handler = scic_sds_request_default_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .start_handler = scic_sds_request_default_start_handler, .abort_handler = scic_sds_request_started_state_abort_handler, - .complete_handler = scic_sds_request_default_complete_handler, - .destruct_handler = scic_sds_request_default_destruct_handler, - .tc_completion_handler = scic_sds_request_default_tc_completion_handler, - .event_handler = scic_sds_request_default_event_handler, .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, }, }; -- cgit v1.2.3 From bc5c96748a5f2067193faa8131b2aa5f9775d309 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 2 Apr 2011 08:15:04 -0400 Subject: isci: simplify dma coherent allocation Remove the insane infrastructure for preallocating coheren DMA regions, and just allocate the memory where needed. This also gets rid of the aligment adjustments given that Documentation/DMA-API-HOWTO.txt sais: "The cpu return address and the DMA bus master address are both guaranteed to be aligned to the smallest PAGE_SIZE order which is greater than or equal to the requested size. This invariant exists (for example) to guarantee that if you allocate a chunk which is smaller than or equal to 64 kilobytes, the extent of the buffer you receive will not cross a 64K boundary." Signed-off-by: Christoph Hellwig [djbw: moved allocation from start to init, re-add memset] Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 1 - .../isci/core/sci_base_memory_descriptor_list.c | 159 ----------- .../isci/core/sci_base_memory_descriptor_list.h | 153 ----------- .../scsi/isci/core/sci_memory_descriptor_list.h | 168 ------------ drivers/scsi/isci/core/scic_controller.h | 1 + drivers/scsi/isci/core/scic_sds_controller.c | 291 ++++++--------------- drivers/scsi/isci/core/scic_sds_controller.h | 49 ---- .../isci/core/scic_sds_unsolicited_frame_control.c | 66 ++--- .../isci/core/scic_sds_unsolicited_frame_control.h | 22 +- drivers/scsi/isci/host.c | 95 +------ drivers/scsi/isci/host.h | 9 - 11 files changed, 111 insertions(+), 903 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_base_memory_descriptor_list.c delete mode 100644 drivers/scsi/isci/core/sci_base_memory_descriptor_list.h delete mode 100644 drivers/scsi/isci/core/sci_memory_descriptor_list.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index a65c0ae9d2c4..522e7a7c062e 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -25,6 +25,5 @@ isci-objs := init.o phy.o request.o sata.o \ core/scic_sds_smp_remote_device.o \ core/scic_sds_remote_node_table.o \ core/scic_sds_unsolicited_frame_control.o \ - core/sci_base_memory_descriptor_list.o \ core/sci_base_state_machine.o \ core/sci_util.o diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c deleted file mode 100644 index 2d785b518a06..000000000000 --- a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains the base implementation for the memory descriptor list. - * This is currently comprised of MDL iterator methods. - * - * - */ - -#include "sci_environment.h" -#include "sci_base_memory_descriptor_list.h" - -/* - * ****************************************************************************** - * * P U B L I C M E T H O D S - * ****************************************************************************** */ - -void sci_mdl_first_entry( - struct sci_base_memory_descriptor_list *base_mdl) -{ - base_mdl->next_index = 0; - - /* - * If this MDL is managing another MDL, then recursively rewind that MDL - * object as well. */ - if (base_mdl->next_mdl != NULL) - sci_mdl_first_entry(base_mdl->next_mdl); -} - - -void sci_mdl_next_entry( - struct sci_base_memory_descriptor_list *base_mdl) -{ - /* - * If there is at least one more entry left in the array, then change - * the next pointer to it. */ - if (base_mdl->next_index < base_mdl->length) - base_mdl->next_index++; - else if (base_mdl->next_index == base_mdl->length) { - /* - * This MDL has exhausted it's set of entries. If this MDL is managing - * another MDL, then start iterating through that MDL. */ - if (base_mdl->next_mdl != NULL) - sci_mdl_next_entry(base_mdl->next_mdl); - } -} - - -struct sci_physical_memory_descriptor *sci_mdl_get_current_entry( - struct sci_base_memory_descriptor_list *base_mdl) -{ - if (base_mdl->next_index < base_mdl->length) - return &base_mdl->mde_array[base_mdl->next_index]; - else if (base_mdl->next_index == base_mdl->length) { - /* - * This MDL has exhausted it's set of entries. If this MDL is managing - * another MDL, then return it's current entry. */ - if (base_mdl->next_mdl != NULL) - return sci_mdl_get_current_entry(base_mdl->next_mdl); - } - - return NULL; -} - -/* - * ****************************************************************************** - * * P R O T E C T E D M E T H O D S - * ****************************************************************************** */ - -void sci_base_mdl_construct( - struct sci_base_memory_descriptor_list *mdl, - struct sci_physical_memory_descriptor *mde_array, - u32 mde_array_length, - struct sci_base_memory_descriptor_list *next_mdl) -{ - mdl->length = mde_array_length; - mdl->mde_array = mde_array; - mdl->next_index = 0; - mdl->next_mdl = next_mdl; -} - -/* --------------------------------------------------------------------------- */ - -bool sci_base_mde_is_valid( - struct sci_physical_memory_descriptor *mde, - u32 alignment, - u32 size, - u16 attributes) -{ - /* Only need the lower 32 bits to ensure alignment is met. */ - u32 physical_address = lower_32_bits(mde->physical_address); - - if ( - ((((unsigned long)mde->virtual_address) & (alignment - 1)) != 0) - || ((physical_address & (alignment - 1)) != 0) - || (mde->constant_memory_alignment != alignment) - || (mde->constant_memory_size != size) - || (mde->virtual_address == NULL) - || (mde->constant_memory_attributes != attributes) - ) { - return false; - } - - return true; -} - diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h deleted file mode 100644 index b58d4e86e7b9..000000000000 --- a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ -#define _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ - -/** - * This file contains the protected interface structures, constants and - * interface methods for the struct sci_base_memory_descriptor_list object. - * - * - */ - - -#include "sci_memory_descriptor_list.h" - - -/** - * struct sci_base_memory_descriptor_list - This structure contains all of the - * fields necessary to implement a simple stack for managing the list of - * available controller indices. - * - * - */ -struct sci_base_memory_descriptor_list { - /** - * This field indicates the length of the memory descriptor entry array. - */ - u32 length; - - /** - * This field is utilized to provide iterator pattern functionality. - * It indicates the index of the next memory descriptor in the iteration. - */ - u32 next_index; - - /** - * This field will point to the list of memory descriptors. - */ - struct sci_physical_memory_descriptor *mde_array; - - /** - * This field simply allows a user to chain memory descriptor lists - * together if desired. This field will be initialized to NULL. - */ - struct sci_base_memory_descriptor_list *next_mdl; - -}; - -/** - * sci_base_mdl_construct() - This method is invoked to construct an memory - * descriptor list. It initializes the fields of the MDL. - * @mdl: This parameter specifies the memory descriptor list to be constructed. - * @mde_array: This parameter specifies the array of memory descriptor entries - * to be managed by this list. - * @mde_array_length: This parameter specifies the size of the array of entries. - * @next_mdl: This parameter specifies a subsequent MDL object to be managed by - * this MDL object. - * - * none. - */ -void sci_base_mdl_construct( - struct sci_base_memory_descriptor_list *mdl, - struct sci_physical_memory_descriptor *mde_array, - u32 mde_array_length, - struct sci_base_memory_descriptor_list *next_mdl); - -/** - * sci_base_mde_construct() - - * - * This macro constructs an memory descriptor entry with the given alignment - * and size - */ -#define sci_base_mde_construct(mde, alignment, size, attributes) \ - { \ - (mde)->constant_memory_alignment = (alignment); \ - (mde)->constant_memory_size = (size); \ - (mde)->constant_memory_attributes = (attributes); \ - } - -/** - * sci_base_mde_is_valid() - This method validates that the memory descriptor - * is correctly filled out by the SCI User - * @mde: This parameter is the mde entry to validate - * @alignment: This parameter specifies the expected alignment of the memory - * for the mde. - * @size: This parameter specifies the memory size expected for the mde its - * value should not have been changed by the SCI User. - * @attributes: This parameter specifies the attributes for the memory - * descriptor provided. - * - * bool This method returns an indication as to whether the supplied MDE is - * valid or not. true The MDE is valid. false The MDE is not valid. - */ -bool sci_base_mde_is_valid( - struct sci_physical_memory_descriptor *mde, - u32 alignment, - u32 size, - u16 attributes); - -#endif /* _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ */ diff --git a/drivers/scsi/isci/core/sci_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_memory_descriptor_list.h deleted file mode 100644 index a039998d01c6..000000000000 --- a/drivers/scsi/isci/core/sci_memory_descriptor_list.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_MEMORY_DESCRIPTOR_LIST_H_ -#define _SCI_MEMORY_DESCRIPTOR_LIST_H_ - -/** - * This file contains all of the basic data types utilized by an SCI user or - * implementor. - * - * - */ - - - -struct sci_base_memory_descriptor_list; - -/** - * - * - * SCI_MDE_ATTRIBUTES These constants depict memory attributes for the Memory - * Descriptor Entries (MDEs) contained in the MDL. - */ -#define SCI_MDE_ATTRIBUTE_CACHEABLE 0x0001 -#define SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS 0x0002 - -/** - * struct sci_physical_memory_descriptor - This structure defines a description - * of a memory location for the SCI implementation. - * - * - */ -struct sci_physical_memory_descriptor { - /** - * This field contains the virtual address associated with this descriptor - * element. This field shall be zero when the descriptor is retrieved from - * the SCI implementation. The user shall set this field prior - * sci_controller_start() - */ - void *virtual_address; - - /** - * This field contains the physical address associated with this desciptor - * element. This field shall be zero when the descriptor is retrieved from - * the SCI implementation. The user shall set this field prior - * sci_controller_start() - */ - dma_addr_t physical_address; - - /** - * This field contains the size requirement for this memory descriptor. - * A value of zero for this field indicates the end of the descriptor - * list. The value should be treated as read only for an SCI user. - */ - u32 constant_memory_size; - - /** - * This field contains the alignment requirement for this memory - * descriptor. A value of zero for this field indicates the end of the - * descriptor list. All other values indicate the number of bytes to - * achieve the necessary alignment. The value should be treated as - * read only for an SCI user. - */ - u32 constant_memory_alignment; - - /** - * This field contains an indication regarding the desired memory - * attributes for this memory descriptor entry. - * Notes: - * - If the cacheable attribute is set, the user can allocate - * memory that is backed by cache for better performance. It - * is not required that the memory be backed by cache. - * - If the physically contiguous attribute is set, then the - * entire memory must be physically contiguous across all - * page boundaries. - */ - u16 constant_memory_attributes; - -}; - -/** - * sci_mdl_first_entry() - This method simply rewinds the MDL iterator back to - * the first memory descriptor entry in the list. - * @mdl: This parameter specifies the memory descriptor list that is to be - * rewound. - * - */ -void sci_mdl_first_entry( - struct sci_base_memory_descriptor_list *mdl); - -/** - * sci_mdl_next_entry() - This method simply updates the "current" pointer to - * the next sequential memory descriptor. - * @mdl: This parameter specifies the memory descriptor list for which to - * return the next memory descriptor entry in the list. - * - * none. - */ -void sci_mdl_next_entry( - struct sci_base_memory_descriptor_list *mdl); - -/** - * sci_mdl_get_current_entry() - This method simply returns the current memory - * descriptor entry. - * @mdl: This parameter specifies the memory descriptor list for which to - * return the current memory descriptor entry. - * - * This method returns a pointer to the current physical memory descriptor in - * the MDL. NULL This value is returned if there are no descriptors in the list. - */ -struct sci_physical_memory_descriptor *sci_mdl_get_current_entry( - struct sci_base_memory_descriptor_list *mdl); - - -#endif /* _SCI_MEMORY_DESCRIPTOR_LIST_H_ */ - diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 236c583162ec..649b61ac5d6d 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -144,4 +144,5 @@ enum sci_status scic_controller_free_io_tag( struct device; struct scic_sds_controller *scic_controller_alloc(struct device *dev); +int scic_controller_mem_init(struct scic_sds_controller *scic); #endif /* _SCIC_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 7ead6f381550..4aae7b6361a7 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -226,171 +226,66 @@ static void scic_sds_controller_initialize_power_control(struct scic_sds_control scic->power_control.phys_granted_power = 0; } -#define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT (32) -#define SCU_TASK_CONTEXT_ALIGNMENT (256) -#define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64) -#define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT (1024) -#define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT (64) - -/** - * This method builds the memory descriptor table for this controller. - * @this_controller: This parameter specifies the controller object for which - * to build the memory table. - * - */ -static void scic_sds_controller_build_memory_descriptor_table( - struct scic_sds_controller *this_controller) +int scic_controller_mem_init(struct scic_sds_controller *scic) { - sci_base_mde_construct( - &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE], - SCU_COMPLETION_RAM_ALIGNMENT, - (sizeof(u32) * this_controller->completion_queue_entries), - (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS) - ); - - sci_base_mde_construct( - &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT], - SCU_REMOTE_NODE_CONTEXT_ALIGNMENT, - this_controller->remote_node_entries * sizeof(union scu_remote_node_context), - SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS - ); - - sci_base_mde_construct( - &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT], - SCU_TASK_CONTEXT_ALIGNMENT, - this_controller->task_context_entries * sizeof(struct scu_task_context), - SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS - ); - - /* - * The UF buffer address table size must be programmed to a power - * of 2. Find the first power of 2 that is equal to or greater then - * the number of unsolicited frame buffers to be utilized. */ - scic_sds_unsolicited_frame_control_set_address_table_count( - &this_controller->uf_control - ); - - sci_base_mde_construct( - &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER], - SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT, - scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control), - SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS - ); -} - -/** - * This method validates the driver supplied memory descriptor table. - * @this_controller: - * - * enum sci_status - */ -static enum sci_status scic_sds_controller_validate_memory_descriptor_table( - struct scic_sds_controller *this_controller) -{ - bool mde_list_valid; - - mde_list_valid = sci_base_mde_is_valid( - &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE], - SCU_COMPLETION_RAM_ALIGNMENT, - (sizeof(u32) * this_controller->completion_queue_entries), - (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS) - ); - - if (mde_list_valid == false) - return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; - - mde_list_valid = sci_base_mde_is_valid( - &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT], - SCU_REMOTE_NODE_CONTEXT_ALIGNMENT, - this_controller->remote_node_entries * sizeof(union scu_remote_node_context), - SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS - ); - - if (mde_list_valid == false) - return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; - - mde_list_valid = sci_base_mde_is_valid( - &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT], - SCU_TASK_CONTEXT_ALIGNMENT, - this_controller->task_context_entries * sizeof(struct scu_task_context), - SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS - ); - - if (mde_list_valid == false) - return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; - - mde_list_valid = sci_base_mde_is_valid( - &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER], - SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT, - scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control), - SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS - ); - - if (mde_list_valid == false) - return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; - - return SCI_SUCCESS; -} - -/** - * This method initializes the controller with the physical memory addresses - * that are used to communicate with the driver. - * @this_controller: - * - */ -static void scic_sds_controller_ram_initialization( - struct scic_sds_controller *this_controller) -{ - struct sci_physical_memory_descriptor *mde; + struct device *dev = scic_to_dev(scic); + dma_addr_t dma_handle; + enum sci_status result; - /* - * The completion queue is actually placed in cacheable memory - * Therefore it no longer comes out of memory in the MDL. */ - mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE]; - this_controller->completion_queue = (u32 *)mde->virtual_address; - writel(lower_32_bits(mde->physical_address), \ - &this_controller->smu_registers->completion_queue_lower); - writel(upper_32_bits(mde->physical_address), - &this_controller->smu_registers->completion_queue_upper); - - /* - * Program the location of the Remote Node Context table - * into the SCU. */ - mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT]; - this_controller->remote_node_context_table = (union scu_remote_node_context *) - mde->virtual_address; - writel(lower_32_bits(mde->physical_address), - &this_controller->smu_registers->remote_node_context_lower); - writel(upper_32_bits(mde->physical_address), - &this_controller->smu_registers->remote_node_context_upper); - - /* Program the location of the Task Context table into the SCU. */ - mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT]; - this_controller->task_context_table = (struct scu_task_context *) - mde->virtual_address; - writel(lower_32_bits(mde->physical_address), - &this_controller->smu_registers->host_task_table_lower); - writel(upper_32_bits(mde->physical_address), - &this_controller->smu_registers->host_task_table_upper); - - mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER]; - scic_sds_unsolicited_frame_control_construct( - &this_controller->uf_control, mde, this_controller - ); + scic->completion_queue = dmam_alloc_coherent(dev, + scic->completion_queue_entries * sizeof(u32), + &dma_handle, GFP_KERNEL); + if (!scic->completion_queue) + return -ENOMEM; + + writel(lower_32_bits(dma_handle), + &scic->smu_registers->completion_queue_lower); + writel(upper_32_bits(dma_handle), + &scic->smu_registers->completion_queue_upper); + + scic->remote_node_context_table = dmam_alloc_coherent(dev, + scic->remote_node_entries * + sizeof(union scu_remote_node_context), + &dma_handle, GFP_KERNEL); + if (!scic->remote_node_context_table) + return -ENOMEM; + + writel(lower_32_bits(dma_handle), + &scic->smu_registers->remote_node_context_lower); + writel(upper_32_bits(dma_handle), + &scic->smu_registers->remote_node_context_upper); + + scic->task_context_table = dmam_alloc_coherent(dev, + scic->task_context_entries * + sizeof(struct scu_task_context), + &dma_handle, GFP_KERNEL); + if (!scic->task_context_table) + return -ENOMEM; + + writel(lower_32_bits(dma_handle), + &scic->smu_registers->host_task_table_lower); + writel(upper_32_bits(dma_handle), + &scic->smu_registers->host_task_table_upper); + + result = scic_sds_unsolicited_frame_control_construct(scic); + if (result) + return result; /* * Inform the silicon as to the location of the UF headers and * address table. */ - writel(lower_32_bits(this_controller->uf_control.headers.physical_address), - &this_controller->scu_registers->sdma.uf_header_base_address_lower); - writel(upper_32_bits(this_controller->uf_control.headers.physical_address), - &this_controller->scu_registers->sdma.uf_header_base_address_upper); + writel(lower_32_bits(scic->uf_control.headers.physical_address), + &scic->scu_registers->sdma.uf_header_base_address_lower); + writel(upper_32_bits(scic->uf_control.headers.physical_address), + &scic->scu_registers->sdma.uf_header_base_address_upper); + + writel(lower_32_bits(scic->uf_control.address_table.physical_address), + &scic->scu_registers->sdma.uf_address_table_lower); + writel(upper_32_bits(scic->uf_control.address_table.physical_address), + &scic->scu_registers->sdma.uf_address_table_upper); - writel(lower_32_bits(this_controller->uf_control.address_table.physical_address), - &this_controller->scu_registers->sdma.uf_address_table_lower); - writel(upper_32_bits(this_controller->uf_control.address_table.physical_address), - &this_controller->scu_registers->sdma.uf_address_table_upper); + return 0; } /** @@ -2525,7 +2420,6 @@ static enum sci_status scic_controller_set_mode( scic->completion_event_entries = SCU_EVENT_COUNT; scic->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; - scic_sds_controller_build_memory_descriptor_table(scic); break; case SCI_MODE_SIZE: @@ -2536,7 +2430,6 @@ static enum sci_status scic_controller_set_mode( scic->completion_event_entries = SCU_MIN_EVENTS; scic->completion_queue_entries = SCU_MIN_COMPLETION_QUEUE_ENTRIES; - scic_sds_controller_build_memory_descriptor_table(scic); break; default: @@ -3040,72 +2933,52 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( u16 index; enum sci_status result; - /* - * Make sure that the SCI User filled in the memory descriptor - * table correctly - */ - result = scic_sds_controller_validate_memory_descriptor_table(scic); - - if (result == SCI_SUCCESS) { - /* - * The memory descriptor list looks good so program the - * hardware - */ - scic_sds_controller_ram_initialization(scic); - } - - if (result == SCI_SUCCESS) { - /* Build the TCi free pool */ - sci_pool_initialize(scic->tci_pool); - for (index = 0; index < scic->task_context_entries; index++) - sci_pool_put(scic->tci_pool, index); + /* Build the TCi free pool */ + sci_pool_initialize(scic->tci_pool); + for (index = 0; index < scic->task_context_entries; index++) + sci_pool_put(scic->tci_pool, index); - /* Build the RNi free pool */ - scic_sds_remote_node_table_initialize( - &scic->available_remote_nodes, - scic->remote_node_entries); - } + /* Build the RNi free pool */ + scic_sds_remote_node_table_initialize( + &scic->available_remote_nodes, + scic->remote_node_entries); - if (result == SCI_SUCCESS) { - /* - * Before anything else lets make sure we will not be - * interrupted by the hardware. - */ - scic_controller_disable_interrupts(scic); + /* + * Before anything else lets make sure we will not be + * interrupted by the hardware. + */ + scic_controller_disable_interrupts(scic); - /* Enable the port task scheduler */ - scic_sds_controller_enable_port_task_scheduler(scic); + /* Enable the port task scheduler */ + scic_sds_controller_enable_port_task_scheduler(scic); - /* Assign all the task entries to scic physical function */ - scic_sds_controller_assign_task_entries(scic); + /* Assign all the task entries to scic physical function */ + scic_sds_controller_assign_task_entries(scic); - /* Now initialze the completion queue */ - scic_sds_controller_initialize_completion_queue(scic); + /* Now initialze the completion queue */ + scic_sds_controller_initialize_completion_queue(scic); - /* Initialize the unsolicited frame queue for use */ - scic_sds_controller_initialize_unsolicited_frame_queue(scic); - } + /* Initialize the unsolicited frame queue for use */ + scic_sds_controller_initialize_unsolicited_frame_queue(scic); /* Start all of the ports on this controller */ - for (index = 0; - (index < scic->logical_port_entries) && (result == SCI_SUCCESS); - index++) { + for (index = 0; index < scic->logical_port_entries; index++) { struct scic_sds_port *sci_port = &scic->port_table[index]; result = sci_port->state_handlers->parent.start_handler( &sci_port->parent); + if (result) + return result; } - if (result == SCI_SUCCESS) { - scic_sds_controller_start_next_phy(scic); + scic_sds_controller_start_next_phy(scic); - isci_timer_start(scic->timeout_timer, timeout); + isci_timer_start(scic->timeout_timer, timeout); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_STARTING); - } + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_STARTING); - return result; + return SCI_SUCCESS; } /* @@ -3658,8 +3531,6 @@ enum sci_status scic_controller_construct(struct scic_sds_controller *scic, &scic->parent, scic_sds_controller_state_table, SCI_BASE_CONTROLLER_STATE_INITIAL); - sci_base_mdl_construct(&scic->mdl, scic->memory_descriptors, - ARRAY_SIZE(scic->memory_descriptors), NULL); sci_base_state_machine_start(&scic->state_machine); scic->scu_registers = scu_base; diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 5cff8066a0ef..163a9e11576a 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -68,10 +68,8 @@ #include "sci_pool.h" #include "sci_controller_constants.h" -#include "sci_memory_descriptor_list.h" #include "sci_base_state.h" #include "sci_base_state_machine.h" -#include "sci_base_memory_descriptor_list.h" #include "scic_config_parameters.h" #include "scic_sds_port.h" #include "scic_sds_phy.h" @@ -89,40 +87,6 @@ struct scic_sds_remote_device; struct scic_sds_request; struct scic_sds_controller; -#define SCU_COMPLETION_RAM_ALIGNMENT (64) - -/** - * enum scic_sds_controller_memory_descriptors - - * - * This enumeration depects the types of MDEs that are going to be created for - * the controller object. - */ -enum scic_sds_controller_memory_descriptors { - /** - * Completion queue MDE entry - */ - SCU_MDE_COMPLETION_QUEUE, - - /** - * Remote node context MDE entry - */ - SCU_MDE_REMOTE_NODE_CONTEXT, - - /** - * Task context MDE entry - */ - SCU_MDE_TASK_CONTEXT, - - /** - * Unsolicited frame buffer MDE entrys this is the start of the unsolicited - * frame buffer entries. - */ - SCU_MDE_UF_BUFFER, - - SCU_MAX_MDES -}; - - /** * struct scic_power_control - * @@ -173,13 +137,6 @@ struct scic_sds_controller { */ struct sci_base_object parent; - /** - * This field points to the memory descriptor list associated with this - * controller. The MDL indicates the memory requirements necessary for - * this controller object. - */ - struct sci_base_memory_descriptor_list mdl; - /** * This field contains the information for the base controller state * machine. @@ -284,12 +241,6 @@ struct scic_sds_controller { */ union scu_remote_node_context *remote_node_context_table; - /** - * This field is the array of physical memory requiremets for this controller - * object. - */ - struct sci_physical_memory_descriptor memory_descriptors[SCU_MAX_MDES]; - /** * This field is a pointer to the completion queue. This memory is * written to by the hardware and read by the software. diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c index 31a3516ddebe..9e393e5df8ec 100644 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c @@ -67,26 +67,6 @@ #include "sci_util.h" #include "sci_environment.h" -/** - * The UF buffer address table size must be programmed to a power of 2. Find - * the first power of 2 that is equal to or greater then the number of - * unsolicited frame buffers to be utilized. - * @uf_control: This parameter specifies the UF control object for which to - * update the address table count. - * - */ -void scic_sds_unsolicited_frame_control_set_address_table_count( - struct scic_sds_unsolicited_frame_control *uf_control) -{ - uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES; - while ( - (uf_control->address_table.count < uf_control->buffers.count) - && (uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES) - ) { - uf_control->address_table.count <<= 1; - } -} - /** * This method will program the unsolicited frames (UFs) into the UF address * table and construct the UF frame structure being modeled in the core. It @@ -155,23 +135,9 @@ static void scic_sds_unsolicited_frame_control_construct_frames( } } -/** - * This method constructs the various members of the unsolicted frame control - * object (buffers, headers, address, table, etc). - * @uf_control: This parameter specifies the unsolicited frame control object - * to construct. - * @mde: This parameter specifies the memory descriptor from which to derive - * all of the address information needed to get the unsolicited frame - * functionality working. - * @controller: This parameter specifies the controller object associated with - * the uf_control being constructed. - * - */ -void scic_sds_unsolicited_frame_control_construct( - struct scic_sds_unsolicited_frame_control *uf_control, - struct sci_physical_memory_descriptor *mde, - struct scic_sds_controller *controller) +int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic) { + struct scic_sds_unsolicited_frame_control *uf_control = &scic->uf_control; u32 unused_uf_header_entries; u32 used_uf_header_entries; u32 used_uf_buffer_bytes; @@ -179,10 +145,22 @@ void scic_sds_unsolicited_frame_control_construct( u32 used_uf_header_bytes; dma_addr_t uf_buffer_phys_address; void *uf_buffer_virt_address; + size_t size; + + /* + * The UF buffer address table size must be programmed to a power + * of 2. Find the first power of 2 that is equal to or greater then + * the number of unsolicited frame buffers to be utilized. + */ + uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES; + while (uf_control->address_table.count < uf_control->buffers.count && + uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES) + uf_control->address_table.count <<= 1; /* * Prepare all of the memory sizes for the UF headers, UF address - * table, and UF buffers themselves. */ + * table, and UF buffers themselves. + */ used_uf_buffer_bytes = uf_control->buffers.count * SCU_UNSOLICITED_FRAME_BUFFER_SIZE; unused_uf_header_entries = uf_control->address_table.count @@ -193,13 +171,19 @@ void scic_sds_unsolicited_frame_control_construct( used_uf_header_bytes = used_uf_header_entries * sizeof(struct scu_unsolicited_frame_header); + size = used_uf_buffer_bytes + used_uf_header_bytes + + uf_control->address_table.count * sizeof(dma_addr_t); + + /* * The Unsolicited Frame buffers are set at the start of the UF * memory descriptor entry. The headers and address table will be * placed after the buffers. */ - uf_buffer_phys_address = mde->physical_address; - uf_buffer_virt_address = mde->virtual_address; + uf_buffer_virt_address = dmam_alloc_coherent(scic_to_dev(scic), size, + &uf_buffer_phys_address, GFP_KERNEL); + if (!uf_buffer_virt_address) + return -ENOMEM; /* * Program the location of the UF header table into the SCU. @@ -254,10 +238,12 @@ void scic_sds_unsolicited_frame_control_construct( scic_sds_unsolicited_frame_control_construct_frames( uf_control, uf_buffer_phys_address, - mde->virtual_address, + uf_buffer_virt_address, unused_uf_header_entries, used_uf_header_entries ); + + return 0; } /** diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h index a0204aa7128a..4eb244c06cfc 100644 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h @@ -64,7 +64,6 @@ #define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ #include "scu_unsolicited_frame.h" -#include "sci_memory_descriptor_list.h" #include "scu_constants.h" #include "sci_status.h" @@ -248,14 +247,9 @@ struct scic_sds_unsolicited_frame_control { }; -void scic_sds_unsolicited_frame_control_set_address_table_count( - struct scic_sds_unsolicited_frame_control *uf_control); - struct scic_sds_controller; -void scic_sds_unsolicited_frame_control_construct( - struct scic_sds_unsolicited_frame_control *uf_control, - struct sci_physical_memory_descriptor *mde, - struct scic_sds_controller *this_controller); + +int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic); enum sci_status scic_sds_unsolicited_frame_control_get_header( struct scic_sds_unsolicited_frame_control *uf_control, @@ -271,16 +265,4 @@ bool scic_sds_unsolicited_frame_control_release_frame( struct scic_sds_unsolicited_frame_control *uf_control, u32 frame_index); -/** - * scic_sds_unsolicited_frame_control_get_mde_size() - - * - * This macro simply calculates the size of the memory descriptor entry that - * relates to unsolicited frames and the surrounding silicon memory required to - * utilize it. - */ -#define scic_sds_unsolicited_frame_control_get_mde_size(uf_control) \ - (((uf_control).buffers.count * SCU_UNSOLICITED_FRAME_BUFFER_SIZE) \ - + ((uf_control).address_table.count * sizeof(dma_addr_t)) \ - + ((uf_control).buffers.count * sizeof(struct scu_unsolicited_frame_header))) - #endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */ diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index adfc2452d216..927f08892ad6 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -170,96 +170,6 @@ void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion wake_up(&ihost->eventq); } -static struct coherent_memory_info *isci_host_alloc_mdl_struct( - struct isci_host *isci_host, - u32 size) -{ - struct coherent_memory_info *mdl_struct; - void *uncached_address = NULL; - - - mdl_struct = devm_kzalloc(&isci_host->pdev->dev, - sizeof(*mdl_struct), - GFP_KERNEL); - if (!mdl_struct) - return NULL; - - INIT_LIST_HEAD(&mdl_struct->node); - - uncached_address = dmam_alloc_coherent(&isci_host->pdev->dev, - size, - &mdl_struct->dma_handle, - GFP_KERNEL); - if (!uncached_address) - return NULL; - - /* memset the whole memory area. */ - memset((char *)uncached_address, 0, size); - mdl_struct->vaddr = uncached_address; - mdl_struct->size = (size_t)size; - - return mdl_struct; -} - -static void isci_host_build_mde( - struct sci_physical_memory_descriptor *mde_struct, - struct coherent_memory_info *mdl_struct) -{ - unsigned long address = 0; - dma_addr_t dma_addr = 0; - - address = (unsigned long)mdl_struct->vaddr; - dma_addr = mdl_struct->dma_handle; - - /* to satisfy the alignment. */ - if ((address % mde_struct->constant_memory_alignment) != 0) { - int align_offset - = (mde_struct->constant_memory_alignment - - (address % mde_struct->constant_memory_alignment)); - address += align_offset; - dma_addr += align_offset; - } - - mde_struct->virtual_address = (void *)address; - mde_struct->physical_address = dma_addr; - mdl_struct->mde = mde_struct; -} - -static int isci_host_mdl_allocate_coherent( - struct isci_host *isci_host) -{ - struct sci_physical_memory_descriptor *current_mde; - struct coherent_memory_info *mdl_struct; - u32 size = 0; - - struct sci_base_memory_descriptor_list *mdl_handle = - &isci_host->core_controller->mdl; - - sci_mdl_first_entry(mdl_handle); - - current_mde = sci_mdl_get_current_entry(mdl_handle); - - while (current_mde != NULL) { - - size = (current_mde->constant_memory_size - + current_mde->constant_memory_alignment); - - mdl_struct = isci_host_alloc_mdl_struct(isci_host, size); - if (!mdl_struct) - return -ENOMEM; - - list_add_tail(&mdl_struct->node, &isci_host->mdl_struct_list); - - isci_host_build_mde(current_mde, mdl_struct); - - sci_mdl_next_entry(mdl_handle); - current_mde = sci_mdl_get_current_entry(mdl_handle); - } - - return 0; -} - - /** * isci_host_completion_routine() - This function is the delayed service * routine that calls the sci core library's completion handler. It's @@ -523,8 +433,6 @@ int isci_host_init(struct isci_host *isci_host) tasklet_init(&isci_host->completion_tasklet, isci_host_completion_routine, (unsigned long)isci_host); - INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); - INIT_LIST_HEAD(&isci_host->requests_to_complete); INIT_LIST_HEAD(&isci_host->requests_to_errorback); @@ -539,8 +447,7 @@ int isci_host_init(struct isci_host *isci_host) return -ENODEV; } - /* populate mdl with dma memory. scu_mdl_allocate_coherent() */ - err = isci_host_mdl_allocate_coherent(isci_host); + err = scic_controller_mem_init(isci_host->core_controller); if (err) return err; diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 8372094ef5ad..6e660744d8d4 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -75,14 +75,6 @@ #define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */ #define SCIC_CONTROLLER_STOP_TIMEOUT 5000 -struct coherent_memory_info { - struct list_head node; - dma_addr_t dma_handle; - void *vaddr; - size_t size; - struct sci_physical_memory_descriptor *mde; -}; - struct isci_host { struct scic_sds_controller *core_controller; union scic_oem_parameters oem_parameters; @@ -114,7 +106,6 @@ struct isci_host { wait_queue_head_t eventq; struct Scsi_Host *shost; struct tasklet_struct completion_tasklet; - struct list_head mdl_struct_list; struct list_head requests_to_complete; struct list_head requests_to_errorback; spinlock_t scic_lock; -- cgit v1.2.3 From c629582d0dea42d8b3617f8c46ea2770b95e23aa Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 2 Apr 2011 08:15:20 -0400 Subject: isci: remove scic_controller state handlers Remove the state handler indirections for the scic_controller, and replace them with procedural calls that check for the correct state first. Signed-off-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_controller.h | 5 - drivers/scsi/isci/core/scic_sds_controller.c | 847 ++++++------------------ drivers/scsi/isci/core/scic_sds_controller.h | 86 +-- drivers/scsi/isci/core/scic_sds_remote_device.c | 11 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 18 +- drivers/scsi/isci/task.c | 2 +- 6 files changed, 193 insertions(+), 776 deletions(-) diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 649b61ac5d6d..23a2c785fecd 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -110,11 +110,6 @@ enum sci_task_status scic_controller_start_task( struct scic_sds_request *task_request, u16 io_tag); -enum sci_status scic_controller_complete_task( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *task_request); - enum sci_status scic_controller_terminate_request( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 4aae7b6361a7..f16a23a2f9e4 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1453,46 +1453,45 @@ void scic_sds_controller_error_handler(struct scic_sds_controller *scic) -void scic_sds_controller_link_up( - struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - scic_sds_controller_phy_handler_t link_up; - u32 state; - - state = scic->state_machine.current_state_id; - link_up = scic_sds_controller_state_handler_table[state].link_up; - - if (link_up) - link_up(scic, sci_port, sci_phy); - else +void scic_sds_controller_link_up(struct scic_sds_controller *scic, + struct scic_sds_port *port, struct scic_sds_phy *phy) +{ + switch (scic->state_machine.current_state_id) { + case SCI_BASE_CONTROLLER_STATE_STARTING: + scic_sds_controller_phy_timer_stop(scic); + scic->port_agent.link_up_handler(scic, &scic->port_agent, + port, phy); + scic_sds_controller_start_next_phy(scic); + break; + case SCI_BASE_CONTROLLER_STATE_READY: + scic->port_agent.link_up_handler(scic, &scic->port_agent, + port, phy); + break; + default: dev_dbg(scic_to_dev(scic), "%s: SCIC Controller linkup event from phy %d in " - "unexpected state %d\n", __func__, sci_phy->phy_index, - state); + "unexpected state %d\n", __func__, phy->phy_index, + scic->state_machine.current_state_id); + } } - -void scic_sds_controller_link_down( - struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) +void scic_sds_controller_link_down(struct scic_sds_controller *scic, + struct scic_sds_port *port, struct scic_sds_phy *phy) { - u32 state; - scic_sds_controller_phy_handler_t link_down; - - state = scic->state_machine.current_state_id; - link_down = scic_sds_controller_state_handler_table[state].link_down; - - if (link_down) - link_down(scic, sci_port, sci_phy); - else + switch (scic->state_machine.current_state_id) { + case SCI_BASE_CONTROLLER_STATE_STARTING: + case SCI_BASE_CONTROLLER_STATE_READY: + scic->port_agent.link_down_handler(scic, &scic->port_agent, + port, phy); + break; + default: dev_dbg(scic_to_dev(scic), "%s: SCIC Controller linkdown event from phy %d in " "unexpected state %d\n", __func__, - sci_phy->phy_index, state); + phy->phy_index, + scic->state_machine.current_state_id); + } } /** @@ -1518,30 +1517,25 @@ static bool scic_sds_controller_has_remote_devices_stopping( /** * This method is called by the remote device to inform the controller * object that the remote device has stopped. - * */ - void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev) { - - u32 state; - scic_sds_controller_device_handler_t stopped; - - state = scic->state_machine.current_state_id; - stopped = scic_sds_controller_state_handler_table[state].device_stopped; - - if (stopped) - stopped(scic, sci_dev); - else { + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_STOPPING) { dev_dbg(scic_to_dev(scic), - "%s: SCIC Controller 0x%p remote device stopped event " - "from device 0x%p in unexpected state %d\n", - __func__, scic, sci_dev, state); + "SCIC Controller 0x%p remote device stopped event " + "from device 0x%p in unexpected state %d\n", + scic, sci_dev, + scic->state_machine.current_state_id); + return; } -} - + if (!scic_sds_controller_has_remote_devices_stopping(scic)) { + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_STOPPED); + } +} /** * This method will write to the SCU PCP register the request value. The method @@ -1840,40 +1834,6 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co scic->user_parameters.sds1.no_outbound_task_timeout = 20; } -/** - * scic_controller_initialize() - This method will initialize the controller - * hardware managed by the supplied core controller object. This method - * will bring the physical controller hardware out of reset and enable the - * core to determine the capabilities of the hardware being managed. Thus, - * the core controller can determine it's exact physical (DMA capable) - * memory requirements. - * @controller: This parameter specifies the controller to be initialized. - * - * The SCI Core user must have called scic_controller_construct() on the - * supplied controller object previously. Indicate if the controller was - * successfully initialized or if it failed in some way. SCI_SUCCESS This value - * is returned if the controller hardware was successfully initialized. - */ -enum sci_status scic_controller_initialize( - struct scic_sds_controller *scic) -{ - enum sci_status status = SCI_FAILURE_INVALID_STATE; - scic_sds_controller_handler_t initialize; - u32 state; - - state = scic->state_machine.current_state_id; - initialize = scic_sds_controller_state_handler_table[state].initialize; - - if (initialize) - status = initialize(scic); - else - dev_warn(scic_to_dev(scic), - "%s: SCIC Controller initialize operation requested " - "in invalid state %d\n", __func__, state); - - return status; -} - /** * scic_controller_get_suggested_start_timeout() - This method returns the * suggested scic_controller_start() timeout amount. The user is free to @@ -1912,49 +1872,6 @@ u32 scic_controller_get_suggested_start_timeout( + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); } -/** - * scic_controller_start() - This method will start the supplied core - * controller. This method will start the staggered spin up operation. The - * SCI User completion callback is called when the following conditions are - * met: -# the return status of this method is SCI_SUCCESS. -# after all of - * the phys have successfully started or been given the opportunity to start. - * @controller: the handle to the controller object to start. - * @timeout: This parameter specifies the number of milliseconds in which the - * start operation should complete. - * - * The SCI Core user must have filled in the physical memory descriptor - * structure via the sci_controller_get_memory_descriptor_list() method. The - * SCI Core user must have invoked the scic_controller_initialize() method - * prior to invoking this method. The controller must be in the INITIALIZED or - * STARTED state. Indicate if the controller start method succeeded or failed - * in some way. SCI_SUCCESS if the start operation succeeded. - * SCI_WARNING_ALREADY_IN_STATE if the controller is already in the STARTED - * state. SCI_FAILURE_INVALID_STATE if the controller is not either in the - * INITIALIZED or STARTED states. SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if - * there are inconsistent or invalid values in the supplied - * struct sci_physical_memory_descriptor array. - */ -enum sci_status scic_controller_start( - struct scic_sds_controller *scic, - u32 timeout) -{ - enum sci_status status = SCI_FAILURE_INVALID_STATE; - scic_sds_controller_timed_handler_t start; - u32 state; - - state = scic->state_machine.current_state_id; - start = scic_sds_controller_state_handler_table[state].start; - - if (start) - status = start(scic, timeout); - else - dev_warn(scic_to_dev(scic), - "%s: SCIC Controller start operation requested in " - "invalid state %d\n", __func__, state); - - return status; -} - /** * scic_controller_stop() - This method will stop an individual controller * object.This method will invoke the associated user callback upon @@ -1977,21 +1894,18 @@ enum sci_status scic_controller_stop( struct scic_sds_controller *scic, u32 timeout) { - enum sci_status status = SCI_FAILURE_INVALID_STATE; - scic_sds_controller_timed_handler_t stop; - u32 state; - - state = scic->state_machine.current_state_id; - stop = scic_sds_controller_state_handler_table[state].stop; - - if (stop) - status = stop(scic, timeout); - else + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { dev_warn(scic_to_dev(scic), - "%s: SCIC Controller stop operation requested in " - "invalid state %d\n", __func__, state); + "SCIC Controller stop operation requested in " + "invalid state\n"); + return SCI_FAILURE_INVALID_STATE; + } - return status; + isci_timer_start(scic->timeout_timer, timeout); + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_STOPPING); + return SCI_SUCCESS; } /** @@ -2009,21 +1923,24 @@ enum sci_status scic_controller_stop( enum sci_status scic_controller_reset( struct scic_sds_controller *scic) { - enum sci_status status = SCI_FAILURE_INVALID_STATE; - scic_sds_controller_handler_t reset; - u32 state; - - state = scic->state_machine.current_state_id; - reset = scic_sds_controller_state_handler_table[state].reset; - - if (reset) - status = reset(scic); - else + switch (scic->state_machine.current_state_id) { + case SCI_BASE_CONTROLLER_STATE_RESET: + case SCI_BASE_CONTROLLER_STATE_READY: + case SCI_BASE_CONTROLLER_STATE_STOPPED: + case SCI_BASE_CONTROLLER_STATE_FAILED: + /* + * The reset operation is not a graceful cleanup, just + * perform the state transition. + */ + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_RESETTING); + return SCI_SUCCESS; + default: dev_warn(scic_to_dev(scic), - "%s: SCIC Controller reset operation requested in " - "invalid state %d\n", __func__, state); - - return status; + "SCIC Controller reset operation requested in " + "invalid state\n"); + return SCI_FAILURE_INVALID_STATE; + } } /** @@ -2055,19 +1972,25 @@ enum sci_status scic_controller_reset( */ enum sci_io_status scic_controller_start_io( struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *request, + struct scic_sds_remote_device *rdev, + struct scic_sds_request *req, u16 io_tag) { - u32 state; - scic_sds_controller_start_request_handler_t start_io; + enum sci_status status; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { + dev_warn(scic_to_dev(scic), "invalid state to start I/O"); + return SCI_FAILURE_INVALID_STATE; + } - state = scic->state_machine.current_state_id; - start_io = scic_sds_controller_state_handler_table[state].start_io; + status = scic_sds_remote_device_start_io(scic, rdev, req); + if (status != SCI_SUCCESS) + return status; - return start_io(scic, - (struct sci_base_remote_device *) remote_device, - request, io_tag); + scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; + scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); + return SCI_SUCCESS; } /** @@ -2088,18 +2011,30 @@ enum sci_io_status scic_controller_start_io( */ enum sci_status scic_controller_terminate_request( struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *request) + struct scic_sds_remote_device *rdev, + struct scic_sds_request *req) { - scic_sds_controller_request_handler_t terminate_request; - u32 state; + enum sci_status status; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { + dev_warn(scic_to_dev(scic), + "invalid state to terminate request\n"); + return SCI_FAILURE_INVALID_STATE; + } - state = scic->state_machine.current_state_id; - terminate_request = scic_sds_controller_state_handler_table[state].terminate_request; + status = scic_sds_io_request_terminate(req); + if (status != SCI_SUCCESS) + return status; - return terminate_request(scic, - (struct sci_base_remote_device *)remote_device, - request); + /* + * Utilize the original post context command and or in the POST_TC_ABORT + * request sub-type. + */ + scic_sds_controller_post_request(scic, + scic_sds_request_get_post_context(req) | + SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); + return SCI_SUCCESS; } /** @@ -2126,18 +2061,44 @@ enum sci_status scic_controller_terminate_request( */ enum sci_status scic_controller_complete_io( struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, + struct scic_sds_remote_device *rdev, struct scic_sds_request *request) { - u32 state; - scic_sds_controller_request_handler_t complete_io; + enum sci_status status; + u16 index; + + switch (scic->state_machine.current_state_id) { + case SCI_BASE_CONTROLLER_STATE_STOPPING: + /* XXX: Implement this function */ + return SCI_FAILURE; + case SCI_BASE_CONTROLLER_STATE_READY: + status = scic_sds_remote_device_complete_io(scic, rdev, request); + if (status != SCI_SUCCESS) + return status; + + index = scic_sds_io_tag_get_index(request->io_tag); + scic->io_request_table[index] = NULL; + return SCI_SUCCESS; + default: + dev_warn(scic_to_dev(scic), "invalid state to complete I/O"); + return SCI_FAILURE_INVALID_STATE; + } + +} + +enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; - state = scic->state_machine.current_state_id; - complete_io = scic_sds_controller_state_handler_table[state].complete_io; + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { + dev_warn(scic_to_dev(scic), "invalid state to continue I/O"); + return SCI_FAILURE_INVALID_STATE; + } - return complete_io(scic, - (struct sci_base_remote_device *)remote_device, - request); + scic->io_request_table[scic_sds_io_tag_get_index(sci_req->io_tag)] = sci_req; + scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req)); + return SCI_SUCCESS; } /** @@ -2170,71 +2131,45 @@ enum sci_status scic_controller_complete_io( */ enum sci_task_status scic_controller_start_task( struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *task_request, + struct scic_sds_remote_device *rdev, + struct scic_sds_request *req, u16 task_tag) { - u32 state; - scic_sds_controller_start_request_handler_t start_task; - enum sci_task_status status = SCI_TASK_FAILURE_INVALID_STATE; - - state = scic->state_machine.current_state_id; - start_task = scic_sds_controller_state_handler_table[state].start_task; + enum sci_status status; - if (start_task) - status = start_task(scic, - (struct sci_base_remote_device *)remote_device, - task_request, - task_tag); - else + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { dev_warn(scic_to_dev(scic), "%s: SCIC Controller starting task from invalid " "state\n", __func__); + return SCI_TASK_FAILURE_INVALID_STATE; + } - return status; -} - -/** - * scic_controller_complete_task() - This method will perform core specific - * completion operations for task management request. After this method is - * invoked, the user should consider the task request as invalid until it is - * properly reused (i.e. re-constructed). - * @controller: The handle to the controller object for which to complete the - * task management request. - * @remote_device: The handle to the remote device object for which to complete - * the task management request. - * @task_request: the handle to the task management request object to complete. - * - * Indicate if the controller successfully completed the task management - * request. SCI_SUCCESS if the completion process was successful. - */ -enum sci_status scic_controller_complete_task( - struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *task_request) -{ - u32 state; - scic_sds_controller_request_handler_t complete_task; - enum sci_status status = SCI_FAILURE_INVALID_STATE; + status = scic_sds_remote_device_start_task(scic, rdev, req); + switch (status) { + case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: + scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; - state = scic->state_machine.current_state_id; - complete_task = scic_sds_controller_state_handler_table[state].complete_task; + /* + * We will let framework know this task request started successfully, + * although core is still woring on starting the request (to post tc when + * RNC is resumed.) + */ + return SCI_SUCCESS; + case SCI_SUCCESS: + scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; - if (complete_task) - status = complete_task(scic, - (struct sci_base_remote_device *)remote_device, - task_request); - else - dev_warn(scic_to_dev(scic), - "%s: SCIC Controller completing task from invalid " - "state\n", - __func__); + scic_sds_controller_post_request(scic, + scic_sds_request_get_post_context(req)); + break; + default: + break; + } return status; } - /** * scic_controller_get_port_handle() - This method simply provides the user * with a unique handle for a given SAS/SATA core port index. @@ -2706,52 +2641,23 @@ struct scic_sds_controller *scic_controller_alloc(struct device *dev) return devm_kzalloc(dev, sizeof(struct scic_sds_controller), GFP_KERNEL); } -static enum sci_status -default_controller_handler(struct scic_sds_controller *scic, const char *func) -{ - dev_warn(scic_to_dev(scic), "%s: invalid state %d\n", func, - scic->state_machine.current_state_id); - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_controller_default_start_operation_handler( - struct scic_sds_controller *scic, - struct sci_base_remote_device *remote_device, - struct scic_sds_request *request, - u16 io_tag) -{ - return default_controller_handler(scic, __func__); -} - -static enum sci_status scic_sds_controller_default_request_handler( - struct scic_sds_controller *scic, - struct sci_base_remote_device *remote_device, - struct scic_sds_request *request) -{ - return default_controller_handler(scic, __func__); -} - -static enum sci_status -scic_sds_controller_general_reset_handler(struct scic_sds_controller *scic) -{ - /* The reset operation is not a graceful cleanup just perform the state - * transition. - */ - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_RESETTING); - - return SCI_SUCCESS; -} - -static enum sci_status -scic_sds_controller_reset_state_initialize_handler(struct scic_sds_controller *scic) +enum sci_status scic_controller_initialize( + struct scic_sds_controller *scic) { struct sci_base_state_machine *sm = &scic->state_machine; enum sci_status result = SCI_SUCCESS; struct isci_host *ihost; u32 index, state; + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_RESET) { + dev_warn(scic_to_dev(scic), + "SCIC Controller initialize operation requested " + "in invalid state\n"); + return SCI_FAILURE_INVALID_STATE; + } + + ihost = sci_object_get_association(scic); sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); @@ -2908,30 +2814,19 @@ scic_sds_controller_reset_state_initialize_handler(struct scic_sds_controller *s return result; } -/* - * ***************************************************************************** - * * INITIALIZED STATE HANDLERS - * ***************************************************************************** */ - -/* - * This function is the struct scic_sds_controller start handler for the - * initialized state. - * - Validate we have a good memory descriptor table - Initialze the - * physical memory before programming the hardware - Program the SCU hardware - * with the physical memory addresses passed in the memory descriptor table. - - * Initialzie the TCi pool - Initialize the RNi pool - Initialize the - * completion queue - Initialize the unsolicited frame data - Take the SCU port - * task scheduler out of reset - Start the first phy object. - Transition to - * SCI_BASE_CONTROLLER_STATE_STARTING. enum sci_status SCI_SUCCESS if all of the - * controller start operations complete - * SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the memory - * descriptor fields is invalid. - */ -static enum sci_status scic_sds_controller_initialized_state_start_handler( - struct scic_sds_controller *scic, u32 timeout) +enum sci_status scic_controller_start(struct scic_sds_controller *scic, + u32 timeout) { - u16 index; enum sci_status result; + u16 index; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_INITIALIZED) { + dev_warn(scic_to_dev(scic), + "SCIC Controller start operation requested in " + "invalid state\n"); + return SCI_FAILURE_INVALID_STATE; + } /* Build the TCi free pool */ sci_pool_initialize(scic->tci_pool); @@ -2981,376 +2876,6 @@ static enum sci_status scic_sds_controller_initialized_state_start_handler( return SCI_SUCCESS; } -/* - * ***************************************************************************** - * * INITIALIZED STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @controller: This is struct scic_sds_controller which receives the link up - * notification. - * @port: This is struct scic_sds_port with which the phy is associated. - * @phy: This is the struct scic_sds_phy which has gone link up. - * - * This method is called when the struct scic_sds_controller is in the starting state - * link up handler is called. This method will perform the following: - Stop - * the phy timer - Start the next phy - Report the link up condition to the - * port object none - */ -static void scic_sds_controller_starting_state_link_up_handler( - struct scic_sds_controller *this_controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - scic_sds_controller_phy_timer_stop(this_controller); - - this_controller->port_agent.link_up_handler( - this_controller, &this_controller->port_agent, port, phy - ); - /* scic_sds_port_link_up(port, phy); */ - - scic_sds_controller_start_next_phy(this_controller); -} - -/** - * - * @controller: This is struct scic_sds_controller which receives the link down - * notification. - * @port: This is struct scic_sds_port with which the phy is associated. - * @phy: This is the struct scic_sds_phy which has gone link down. - * - * This method is called when the struct scic_sds_controller is in the starting state - * link down handler is called. - Report the link down condition to the port - * object none - */ -static void scic_sds_controller_starting_state_link_down_handler( - struct scic_sds_controller *this_controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - this_controller->port_agent.link_down_handler( - this_controller, &this_controller->port_agent, port, phy - ); - /* scic_sds_port_link_down(port, phy); */ -} - -static enum sci_status scic_sds_controller_ready_state_stop_handler( - struct scic_sds_controller *scic, - u32 timeout) -{ - isci_timer_start(scic->timeout_timer, timeout); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_STOPPING); - return SCI_SUCCESS; -} - -/* - * This method is called when the struct scic_sds_controller is in the ready state and - * the start io handler is called. - Start the io request on the remote device - * - if successful - assign the io_request to the io_request_table - post the - * request to the hardware enum sci_status SCI_SUCCESS if the start io operation - * succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be - * allocated for the io request. SCI_FAILURE_INVALID_STATE if one or more - * objects are not in a valid state to accept io requests. - * - * XXX: How does the io_tag parameter get assigned to the io request? - */ -static enum sci_status scic_sds_controller_ready_state_start_io_handler( - struct scic_sds_controller *controller, - struct sci_base_remote_device *remote_device, - struct scic_sds_request *request, - u16 io_tag) -{ - enum sci_status status; - - struct scic_sds_remote_device *the_device; - - the_device = (struct scic_sds_remote_device *)remote_device; - - status = scic_sds_remote_device_start_io(controller, the_device, request); - - if (status != SCI_SUCCESS) - return status; - - controller->io_request_table[ - scic_sds_io_tag_get_index(request->io_tag)] = request; - scic_sds_controller_post_request(controller, - scic_sds_request_get_post_context(request)); - return SCI_SUCCESS; -} - -/* - * This method is called when the struct scic_sds_controller is in the ready state and - * the complete io handler is called. - Complete the io request on the remote - * device - if successful - remove the io_request to the io_request_table - * enum sci_status SCI_SUCCESS if the start io operation succeeds - * SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid state to - * accept io requests. - */ -static enum sci_status scic_sds_controller_ready_state_complete_io_handler( - struct scic_sds_controller *controller, - struct sci_base_remote_device *remote_device, - struct scic_sds_request *request) -{ - u16 index; - enum sci_status status; - struct scic_sds_remote_device *the_device; - - the_device = (struct scic_sds_remote_device *)remote_device; - - status = scic_sds_remote_device_complete_io(controller, the_device, - request); - if (status != SCI_SUCCESS) - return status; - - index = scic_sds_io_tag_get_index(request->io_tag); - controller->io_request_table[index] = NULL; - return SCI_SUCCESS; -} - -/* - * This method is called when the struct scic_sds_controller is in the ready state and - * the continue io handler is called. enum sci_status - */ -static enum sci_status scic_sds_controller_ready_state_continue_io_handler( - struct scic_sds_controller *controller, - struct sci_base_remote_device *remote_device, - struct scic_sds_request *request) -{ - controller->io_request_table[ - scic_sds_io_tag_get_index(request->io_tag)] = request; - scic_sds_controller_post_request(controller, - scic_sds_request_get_post_context(request)); - return SCI_SUCCESS; -} - -/* - * This method is called when the struct scic_sds_controller is in the ready state and - * the start task handler is called. - The remote device is requested to start - * the task request - if successful - assign the task to the io_request_table - - * post the request to the SCU hardware enum sci_status SCI_SUCCESS if the start io - * operation succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could - * not be allocated for the io request. SCI_FAILURE_INVALID_STATE if one or - * more objects are not in a valid state to accept io requests. How does the io - * tag get assigned in this code path? - */ -static enum sci_status scic_sds_controller_ready_state_start_task_handler( - struct scic_sds_controller *controller, - struct sci_base_remote_device *remote_device, - struct scic_sds_request *request, - u16 task_tag) -{ - struct scic_sds_remote_device *the_device = (struct scic_sds_remote_device *) - remote_device; - enum sci_status status; - - status = scic_sds_remote_device_start_task(controller, the_device, - request); - - if (status == SCI_SUCCESS) { - controller->io_request_table[ - scic_sds_io_tag_get_index(request->io_tag)] = request; - - scic_sds_controller_post_request(controller, - scic_sds_request_get_post_context(request)); - } else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS) { - controller->io_request_table[ - scic_sds_io_tag_get_index(request->io_tag)] = request; - - /* - * We will let framework know this task request started successfully, - * although core is still woring on starting the request (to post tc when - * RNC is resumed.) */ - status = SCI_SUCCESS; - } - return status; -} - -/* - * This method is called when the struct scic_sds_controller is in the ready state and - * the terminate request handler is called. - call the io request terminate - * function - if successful - post the terminate request to the SCU hardware - * enum sci_status SCI_SUCCESS if the start io operation succeeds - * SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid state to - * accept io requests. - */ -static enum sci_status scic_sds_controller_ready_state_terminate_request_handler( - struct scic_sds_controller *controller, - struct sci_base_remote_device *remote_device, - struct scic_sds_request *request) -{ - enum sci_status status; - - status = scic_sds_io_request_terminate(request); - if (status != SCI_SUCCESS) - return status; - - /* - * Utilize the original post context command and or in the POST_TC_ABORT - * request sub-type. - */ - scic_sds_controller_post_request(controller, - scic_sds_request_get_post_context(request) | - SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); - return SCI_SUCCESS; -} - -/** - * - * @controller: This is struct scic_sds_controller which receives the link up - * notification. - * @port: This is struct scic_sds_port with which the phy is associated. - * @phy: This is the struct scic_sds_phy which has gone link up. - * - * This method is called when the struct scic_sds_controller is in the starting state - * link up handler is called. This method will perform the following: - Stop - * the phy timer - Start the next phy - Report the link up condition to the - * port object none - */ -static void scic_sds_controller_ready_state_link_up_handler( - struct scic_sds_controller *this_controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - this_controller->port_agent.link_up_handler( - this_controller, &this_controller->port_agent, port, phy - ); -} - -/** - * - * @controller: This is struct scic_sds_controller which receives the link down - * notification. - * @port: This is struct scic_sds_port with which the phy is associated. - * @phy: This is the struct scic_sds_phy which has gone link down. - * - * This method is called when the struct scic_sds_controller is in the starting state - * link down handler is called. - Report the link down condition to the port - * object none - */ -static void scic_sds_controller_ready_state_link_down_handler( - struct scic_sds_controller *this_controller, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - this_controller->port_agent.link_down_handler( - this_controller, &this_controller->port_agent, port, phy - ); -} - -/* - * ***************************************************************************** - * * STOPPING STATE HANDLERS - * ***************************************************************************** */ - -/** - * This method is called when the struct scic_sds_controller is in a stopping state - * and the complete io handler is called. - This function is not yet - * implemented enum sci_status SCI_FAILURE - */ -static enum sci_status scic_sds_controller_stopping_state_complete_io_handler( - struct scic_sds_controller *controller, - struct sci_base_remote_device *remote_device, - struct scic_sds_request *request) -{ - /* XXX: Implement this function */ - return SCI_FAILURE; -} - -/** - * This method is called when the struct scic_sds_controller is in a stopping state - * and the remote device has stopped. - **/ -static void scic_sds_controller_stopping_state_device_stopped_handler( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device -) -{ - if (!scic_sds_controller_has_remote_devices_stopping(controller)) { - sci_base_state_machine_change_state(&controller->state_machine, - SCI_BASE_CONTROLLER_STATE_STOPPED - ); - } -} - -const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[] = { - [SCI_BASE_CONTROLLER_STATE_INITIAL] = { - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_default_request_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - }, - [SCI_BASE_CONTROLLER_STATE_RESET] = { - .reset = scic_sds_controller_general_reset_handler, - .initialize = scic_sds_controller_reset_state_initialize_handler, - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_default_request_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - }, - [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = { - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_default_request_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - }, - [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = { - .start = scic_sds_controller_initialized_state_start_handler, - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_default_request_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - }, - [SCI_BASE_CONTROLLER_STATE_STARTING] = { - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_default_request_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - .link_up = scic_sds_controller_starting_state_link_up_handler, - .link_down = scic_sds_controller_starting_state_link_down_handler - }, - [SCI_BASE_CONTROLLER_STATE_READY] = { - .stop = scic_sds_controller_ready_state_stop_handler, - .reset = scic_sds_controller_general_reset_handler, - .start_io = scic_sds_controller_ready_state_start_io_handler, - .complete_io = scic_sds_controller_ready_state_complete_io_handler, - .continue_io = scic_sds_controller_ready_state_continue_io_handler, - .start_task = scic_sds_controller_ready_state_start_task_handler, - .complete_task = scic_sds_controller_ready_state_complete_io_handler, - .terminate_request = scic_sds_controller_ready_state_terminate_request_handler, - .link_up = scic_sds_controller_ready_state_link_up_handler, - .link_down = scic_sds_controller_ready_state_link_down_handler - }, - [SCI_BASE_CONTROLLER_STATE_RESETTING] = { - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_default_request_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - }, - [SCI_BASE_CONTROLLER_STATE_STOPPING] = { - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_stopping_state_complete_io_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - .device_stopped = scic_sds_controller_stopping_state_device_stopped_handler, - }, - [SCI_BASE_CONTROLLER_STATE_STOPPED] = { - .reset = scic_sds_controller_general_reset_handler, - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_default_request_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - }, - [SCI_BASE_CONTROLLER_STATE_FAILED] = { - .reset = scic_sds_controller_general_reset_handler, - .start_io = scic_sds_controller_default_start_operation_handler, - .complete_io = scic_sds_controller_default_request_handler, - .continue_io = scic_sds_controller_default_request_handler, - .terminate_request = scic_sds_controller_default_request_handler, - }, -}; - /** * * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 163a9e11576a..9a646e5c7f45 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -430,90 +430,6 @@ enum scic_sds_controller_states { }; -typedef enum sci_status (*scic_sds_controller_handler_t) - (struct scic_sds_controller *); -typedef enum sci_status (*scic_sds_controller_timed_handler_t) - (struct scic_sds_controller *, u32); -typedef enum sci_status (*scic_sds_controller_request_handler_t) - (struct scic_sds_controller *, - struct sci_base_remote_device *, - struct scic_sds_request *); -typedef enum sci_status (*scic_sds_controller_start_request_handler_t) - (struct scic_sds_controller *, - struct sci_base_remote_device *, - struct scic_sds_request *, u16); -typedef void (*scic_sds_controller_phy_handler_t) - (struct scic_sds_controller *, - struct scic_sds_port *, - struct scic_sds_phy *); -typedef void (*scic_sds_controller_device_handler_t) - (struct scic_sds_controller *, - struct scic_sds_remote_device *); - -struct scic_sds_controller_state_handler { - /** - * The start_handler specifies the method invoked when a user attempts to - * start a controller. - */ - scic_sds_controller_timed_handler_t start; - - /** - * The stop_handler specifies the method invoked when a user attempts to - * stop a controller. - */ - scic_sds_controller_timed_handler_t stop; - - /** - * The reset_handler specifies the method invoked when a user attempts to - * reset a controller. - */ - scic_sds_controller_handler_t reset; - - /** - * The initialize_handler specifies the method invoked when a user - * attempts to initialize a controller. - */ - scic_sds_controller_handler_t initialize; - - /** - * The start_io_handler specifies the method invoked when a user - * attempts to start an IO request for a controller. - */ - scic_sds_controller_start_request_handler_t start_io; - - /** - * The complete_io_handler specifies the method invoked when a user - * attempts to complete an IO request for a controller. - */ - scic_sds_controller_request_handler_t complete_io; - - /** - * The continue_io_handler specifies the method invoked when a user - * attempts to continue an IO request for a controller. - */ - scic_sds_controller_request_handler_t continue_io; - - /** - * The start_task_handler specifies the method invoked when a user - * attempts to start a task management request for a controller. - */ - scic_sds_controller_start_request_handler_t start_task; - - /** - * The complete_task_handler specifies the method invoked when a user - * attempts to complete a task management request for a controller. - */ - scic_sds_controller_request_handler_t complete_task; - - scic_sds_controller_request_handler_t terminate_request; - scic_sds_controller_phy_handler_t link_up; - scic_sds_controller_phy_handler_t link_down; - scic_sds_controller_device_handler_t device_stopped; -}; - -extern const struct scic_sds_controller_state_handler - scic_sds_controller_state_handler_table[]; - /** * INCREMENT_QUEUE_GET() - * @@ -676,4 +592,6 @@ void scic_sds_controller_copy_task_context( void scic_sds_controller_register_setup( struct scic_sds_controller *this_controller); +enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req); + #endif /* _SCIC_SDS_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index cb49a33285d9..f0d1c098f9b6 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -558,17 +558,10 @@ void scic_sds_remote_device_start_request( void scic_sds_remote_device_continue_request(void *dev) { struct scic_sds_remote_device *sci_dev = dev; - struct scic_sds_request *sci_req = sci_dev->working_request; /* we need to check if this request is still valid to continue. */ - if (sci_req) { - struct scic_sds_controller *scic = sci_req->owning_controller; - u32 state = scic->state_machine.current_state_id; - scic_sds_controller_request_handler_t continue_io; - - continue_io = scic_sds_controller_state_handler_table[state].continue_io; - continue_io(scic, &sci_req->target_device->parent, sci_req); - } + if (sci_dev->working_request) + scic_controller_continue_io(sci_dev->working_request); } /** diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 0b3bc65b8a2b..e4ca4e40ae87 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -637,10 +637,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( u32 length) { struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_request; - scic_sds_controller_request_handler_t continue_io; struct scu_sgl_element *current_sgl; - struct scic_sds_controller *scic; - u32 state; /* * Recycle the TC and reconstruct it for sending out DATA FIS containing @@ -662,10 +659,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; /* send the new TC out. */ - scic = this_request->owning_controller; - state = scic->state_machine.current_state_id; - continue_io = scic_sds_controller_state_handler_table[state].continue_io; - return continue_io(scic, &this_request->target_device->parent, this_request); + return scic_controller_continue_io(this_request); } /** @@ -1758,12 +1752,9 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet struct sci_base_object *object) { struct scic_sds_request *this_request = (struct scic_sds_request *)object; - scic_sds_controller_request_handler_t continue_io; struct scu_task_context *task_context; struct sata_fis_reg_h2d *h2d_fis; - struct scic_sds_controller *scic; enum sci_status status; - u32 state; /* Clear the SRST bit */ h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request); @@ -1774,12 +1765,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet this_request->owning_controller, this_request->io_tag); task_context->control_frame = 0; - scic = this_request->owning_controller; - state = scic->state_machine.current_state_id; - continue_io = scic_sds_controller_state_handler_table[state].continue_io; - - status = continue_io(scic, &this_request->target_device->parent, this_request); - + status = scic_controller_continue_io(this_request); if (status == SCI_SUCCESS) { SET_STATE_HANDLER( this_request, diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c6c97ad58c9f..aa6b43067e25 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1480,7 +1480,7 @@ void isci_task_request_complete( /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; - scic_controller_complete_task( + scic_controller_complete_io( isci_host->core_controller, to_sci_dev(isci_device), request->sci_request_handle -- cgit v1.2.3 From 0ea99d52cbcdb4bf5f5dd3097088a2919a115981 Mon Sep 17 00:00:00 2001 From: Maciej Trela Date: Tue, 12 Apr 2011 17:28:35 -0700 Subject: isci: remove base_remote_device abstraction Merge struct sci_base_remote_device into scic_sds_remote_device. As for now sci_base_remote_device was accessed indirectly using scic_sds_remote_device->parent field. Both machine state handlers are also merged together. Reported-by: Christoph Hellwig Signed-off-by: Maciej Trela Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_remote_device.h | 274 ----------- drivers/scsi/isci/core/scic_sds_controller.c | 8 +- drivers/scsi/isci/core/scic_sds_remote_device.c | 512 ++++++++++----------- drivers/scsi/isci/core/scic_sds_remote_device.h | 188 ++++++-- .../scsi/isci/core/scic_sds_smp_remote_device.c | 104 ++--- .../scsi/isci/core/scic_sds_stp_remote_device.c | 227 +++++---- 6 files changed, 572 insertions(+), 741 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_base_remote_device.h diff --git a/drivers/scsi/isci/core/sci_base_remote_device.h b/drivers/scsi/isci/core/sci_base_remote_device.h deleted file mode 100644 index 5db5f31336fc..000000000000 --- a/drivers/scsi/isci/core/sci_base_remote_device.h +++ /dev/null @@ -1,274 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_REMOTE_DEVICE_H_ -#define _SCI_BASE_REMOTE_DEVICE_H_ - -/** - * This file contains all of the structures, constants, and methods common to - * all remote device object definitions. - * - * - */ - -#include "sci_base_state_machine.h" - -struct scic_sds_request; - -/** - * enum sci_base_remote_device_states - This enumeration depicts all the states - * for the common remote device state machine. - * - * - */ -enum sci_base_remote_device_states { - /** - * Simply the initial state for the base remote device state machine. - */ - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL, - - /** - * This state indicates that the remote device has successfully been - * stopped. In this state no new IO operations are permitted. - * This state is entered from the INITIAL state. - * This state is entered from the STOPPING state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED, - - /** - * This state indicates the the remote device is in the process of - * becoming ready (i.e. starting). In this state no new IO operations - * are permitted. - * This state is entered from the STOPPED state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_STARTING, - - /** - * This state indicates the remote device is now ready. Thus, the user - * is able to perform IO operations on the remote device. - * This state is entered from the STARTING state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_READY, - - /** - * This state indicates that the remote device is in the process of - * stopping. In this state no new IO operations are permitted, but - * existing IO operations are allowed to complete. - * This state is entered from the READY state. - * This state is entered from the FAILED state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, - - /** - * This state indicates that the remote device has failed. - * In this state no new IO operations are permitted. - * This state is entered from the INITIALIZING state. - * This state is entered from the READY state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_FAILED, - - /** - * This state indicates the device is being reset. - * In this state no new IO operations are permitted. - * This state is entered from the READY state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, - - /** - * Simply the final state for the base remote device state machine. - */ - SCI_BASE_REMOTE_DEVICE_STATE_FINAL, -}; - -/** - * struct sci_base_remote_device - The base remote device object abstracts the - * fields common to all SCI remote device objects. - * - * - */ -struct sci_base_remote_device { - /** - * The field specifies that the parent object for the base remote - * device is the base object itself. - */ - struct sci_base_object parent; - - /** - * This field contains the information for the base remote device state - * machine. - */ - struct sci_base_state_machine state_machine; -}; - - -typedef enum sci_status (*sci_base_remote_device_handler_t)( - struct sci_base_remote_device * - ); - -typedef enum sci_status (*sci_base_remote_device_request_handler_t)( - struct sci_base_remote_device *, - struct scic_sds_request * - ); - -typedef enum sci_status (*sci_base_remote_device_high_priority_request_complete_handler_t)( - struct sci_base_remote_device *, - struct scic_sds_request *, - void *, - enum sci_io_status - ); - -/** - * struct sci_base_remote_device_state_handler - This structure contains all of - * the state handler methods common to base remote device state machines. - * Handler methods provide the ability to change the behavior for user - * requests or transitions depending on the state the machine is in. - * - * - */ -struct sci_base_remote_device_state_handler { - /** - * The start_handler specifies the method invoked when a user attempts to - * start a remote device. - */ - sci_base_remote_device_handler_t start_handler; - - /** - * The stop_handler specifies the method invoked when a user attempts to - * stop a remote device. - */ - sci_base_remote_device_handler_t stop_handler; - - /** - * The fail_handler specifies the method invoked when a remote device - * failure has occurred. A failure may be due to an inability to - * initialize/configure the device. - */ - sci_base_remote_device_handler_t fail_handler; - - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a remote device. - */ - sci_base_remote_device_handler_t destruct_handler; - - /** - * The reset handler specifies the method invloked when requesting to reset a - * remote device. - */ - sci_base_remote_device_handler_t reset_handler; - - /** - * The reset complete handler specifies the method invloked when reporting - * that a reset has completed to the remote device. - */ - sci_base_remote_device_handler_t reset_complete_handler; - - /** - * The start_io_handler specifies the method invoked when a user - * attempts to start an IO request for a remote device. - */ - sci_base_remote_device_request_handler_t start_io_handler; - - /** - * The complete_io_handler specifies the method invoked when a user - * attempts to complete an IO request for a remote device. - */ - sci_base_remote_device_request_handler_t complete_io_handler; - - /** - * The continue_io_handler specifies the method invoked when a user - * attempts to continue an IO request for a remote device. - */ - sci_base_remote_device_request_handler_t continue_io_handler; - - /** - * The start_task_handler specifies the method invoked when a user - * attempts to start a task management request for a remote device. - */ - sci_base_remote_device_request_handler_t start_task_handler; - - /** - * The complete_task_handler specifies the method invoked when a user - * attempts to complete a task management request for a remote device. - */ - sci_base_remote_device_request_handler_t complete_task_handler; - -}; - -/** - * sci_base_remote_device_construct() - Construct the base remote device - * @this_remote_device: This parameter specifies the base remote device to be - * constructed. - * @state_table: This parameter specifies the table of state definitions to be - * utilized for the remote device state machine. - * - */ -static inline void sci_base_remote_device_construct( - struct sci_base_remote_device *base_dev, - const struct sci_base_state *state_table) -{ - base_dev->parent.private = NULL; - sci_base_state_machine_construct( - &base_dev->state_machine, - &base_dev->parent, - state_table, - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL - ); - - sci_base_state_machine_start( - &base_dev->state_machine - ); -} -#endif /* _SCI_BASE_REMOTE_DEVICE_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index f16a23a2f9e4..7a0c5905cfbe 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1500,13 +1500,13 @@ void scic_sds_controller_link_down(struct scic_sds_controller *scic, * */ static bool scic_sds_controller_has_remote_devices_stopping( - struct scic_sds_controller *this_controller) + struct scic_sds_controller *controller) { u32 index; - for (index = 0; index < this_controller->remote_node_entries; index++) { - if ((this_controller->device_table[index] != NULL) && - (this_controller->device_table[index]->parent.state_machine.current_state_id + for (index = 0; index < controller->remote_node_entries; index++) { + if ((controller->device_table[index] != NULL) && + (controller->device_table[index]->state_machine.current_state_id == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING)) return true; } diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index f0d1c098f9b6..d756216872b5 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -123,7 +123,7 @@ enum sci_status scic_remote_device_da_construct( sci_base_state_machine_construct( &sci_dev->ready_substate_machine, - &sci_dev->parent.parent, + &sci_dev->parent, scic_sds_stp_remote_device_ready_substate_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { @@ -132,7 +132,7 @@ enum sci_status scic_remote_device_da_construct( /* add the SMP ready substate machine construction here */ sci_base_state_machine_construct( &sci_dev->ready_substate_machine, - &sci_dev->parent.parent, + &sci_dev->parent, scic_sds_smp_remote_device_ready_substate_table, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } @@ -187,7 +187,7 @@ enum sci_status scic_remote_device_ea_construct( /* add the SMP ready substate machine construction here */ sci_base_state_machine_construct( &sci_dev->ready_substate_machine, - &sci_dev->parent.parent, + &sci_dev->parent, scic_sds_smp_remote_device_ready_substate_table, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { @@ -195,7 +195,7 @@ enum sci_status scic_remote_device_ea_construct( sci_base_state_machine_construct( &sci_dev->ready_substate_machine, - &sci_dev->parent.parent, + &sci_dev->parent, scic_sds_stp_remote_device_ready_substate_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } @@ -222,7 +222,7 @@ enum sci_status scic_remote_device_ea_construct( enum sci_status scic_remote_device_destruct( struct scic_sds_remote_device *sci_dev) { - return sci_dev->state_handlers->parent.destruct_handler(&sci_dev->parent); + return sci_dev->state_handlers->destruct_handler(sci_dev); } @@ -230,7 +230,7 @@ enum sci_status scic_remote_device_start( struct scic_sds_remote_device *sci_dev, u32 timeout) { - return sci_dev->state_handlers->parent.start_handler(&sci_dev->parent); + return sci_dev->state_handlers->start_handler(sci_dev); } @@ -238,21 +238,21 @@ enum sci_status scic_remote_device_stop( struct scic_sds_remote_device *sci_dev, u32 timeout) { - return sci_dev->state_handlers->parent.stop_handler(&sci_dev->parent); + return sci_dev->state_handlers->stop_handler(sci_dev); } enum sci_status scic_remote_device_reset( struct scic_sds_remote_device *sci_dev) { - return sci_dev->state_handlers->parent.reset_handler(&sci_dev->parent); + return sci_dev->state_handlers->reset_handler(sci_dev); } enum sci_status scic_remote_device_reset_complete( struct scic_sds_remote_device *sci_dev) { - return sci_dev->state_handlers->parent.reset_complete_handler(&sci_dev->parent); + return sci_dev->state_handlers->reset_complete_handler(sci_dev); } @@ -362,8 +362,8 @@ enum sci_status scic_sds_remote_device_start_io( struct scic_sds_remote_device *this_device, struct scic_sds_request *io_request) { - return this_device->state_handlers->parent.start_io_handler( - &this_device->parent, io_request); + return this_device->state_handlers->start_io_handler( + this_device, io_request); } /** @@ -380,8 +380,8 @@ enum sci_status scic_sds_remote_device_complete_io( struct scic_sds_remote_device *this_device, struct scic_sds_request *io_request) { - return this_device->state_handlers->parent.complete_io_handler( - &this_device->parent, io_request); + return this_device->state_handlers->complete_io_handler( + this_device, io_request); } /** @@ -398,8 +398,8 @@ enum sci_status scic_sds_remote_device_start_task( struct scic_sds_remote_device *this_device, struct scic_sds_request *io_request) { - return this_device->state_handlers->parent.start_task_handler( - &this_device->parent, io_request); + return this_device->state_handlers->start_task_handler( + this_device, io_request); } /** @@ -491,7 +491,7 @@ static void scic_sds_cb_remote_device_rnc_destruct_complete( BUG_ON(sci_dev->started_request_count != 0); - sci_base_state_machine_change_state(&sci_dev->parent.state_machine, + sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); } @@ -511,11 +511,11 @@ static void scic_sds_remote_device_resume_complete_handler( this_device = (struct scic_sds_remote_device *)user_parameter; if ( - sci_base_state_machine_get_state(&this_device->parent.state_machine) + sci_base_state_machine_get_state(&this_device->state_machine) != SCI_BASE_REMOTE_DEVICE_STATE_READY ) { sci_base_state_machine_change_state( - &this_device->parent.state_machine, + &this_device->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_READY ); } @@ -614,69 +614,67 @@ static enum sci_status scic_sds_remote_device_terminate_requests( return status; } -static enum sci_status default_device_handler(struct sci_base_remote_device *base_dev, - const char *func) +static enum sci_status +default_device_handler(struct scic_sds_remote_device *sci_dev, + const char *func) { - struct scic_sds_remote_device *sci_dev; - - sci_dev = container_of(base_dev, typeof(*sci_dev), parent); dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&base_dev->state_machine)); + sci_base_state_machine_get_state(&sci_dev->state_machine)); return SCI_FAILURE_INVALID_STATE; } enum sci_status scic_sds_remote_device_default_start_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } static enum sci_status scic_sds_remote_device_default_stop_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } enum sci_status scic_sds_remote_device_default_fail_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } enum sci_status scic_sds_remote_device_default_destruct_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } enum sci_status scic_sds_remote_device_default_reset_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } enum sci_status scic_sds_remote_device_default_reset_complete_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } enum sci_status scic_sds_remote_device_default_suspend_handler( struct scic_sds_remote_device *sci_dev, u32 suspend_type) { - return default_device_handler(&sci_dev->parent, __func__); + return default_device_handler(sci_dev, __func__); } enum sci_status scic_sds_remote_device_default_resume_handler( struct scic_sds_remote_device *sci_dev) { - return default_device_handler(&sci_dev->parent, __func__); + return default_device_handler(sci_dev, __func__); } /** * - * @device: The struct sci_base_remote_device which is then cast into a + * @device: The struct scic_sds_remote_device which is then cast into a * struct scic_sds_remote_device. * @event_code: The event code that the struct scic_sds_controller wants the device * object to process. @@ -734,7 +732,7 @@ static enum sci_status scic_sds_remote_device_core_event_handler( } /** * - * @device: The struct sci_base_remote_device which is then cast into a + * @device: The struct scic_sds_remote_device which is then cast into a * struct scic_sds_remote_device. * @event_code: The event code that the struct scic_sds_controller wants the device * object to process. @@ -754,7 +752,7 @@ static enum sci_status scic_sds_remote_device_default_event_handler( /** * - * @device: The struct sci_base_remote_device which is then cast into a + * @device: The struct scic_sds_remote_device which is then cast into a * struct scic_sds_remote_device. * @frame_index: The frame index for which the struct scic_sds_controller wants this * device object to process. @@ -773,7 +771,7 @@ enum sci_status scic_sds_remote_device_default_frame_handler( __func__, frame_index, sci_base_state_machine_get_state( - &this_device->parent.state_machine)); + &this_device->state_machine)); /* Return the frame back to the controller */ scic_sds_controller_release_frame( @@ -784,29 +782,29 @@ enum sci_status scic_sds_remote_device_default_frame_handler( } enum sci_status scic_sds_remote_device_default_start_request_handler( - struct sci_base_remote_device *base_dev, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } enum sci_status scic_sds_remote_device_default_complete_request_handler( - struct sci_base_remote_device *base_dev, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } enum sci_status scic_sds_remote_device_default_continue_request_handler( - struct sci_base_remote_device *base_dev, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { - return default_device_handler(base_dev, __func__); + return default_device_handler(sci_dev, __func__); } /** * - * @device: The struct sci_base_remote_device which is then cast into a + * @device: The struct scic_sds_remote_device which is then cast into a * struct scic_sds_remote_device. * @frame_index: The frame index for which the struct scic_sds_controller wants this * device object to process. @@ -887,32 +885,29 @@ enum sci_status scic_sds_remote_device_general_event_handler( * which to construct the remote device. */ static enum sci_status scic_sds_remote_device_stopped_state_start_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { enum sci_status status; - struct scic_sds_remote_device *sci_dev; - - sci_dev = container_of(base_dev, typeof(*sci_dev), parent); status = scic_sds_remote_node_context_resume(sci_dev->rnc, scic_sds_remote_device_resume_complete_handler, sci_dev); if (status == SCI_SUCCESS) - sci_base_state_machine_change_state(&base_dev->state_machine, + sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STARTING); return status; } static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { return SCI_SUCCESS; } /** * - * @sci_dev: The struct sci_base_remote_device which is cast into a + * @sci_dev: The struct scic_sds_remote_device which is cast into a * struct scic_sds_remote_device. * * This method will destruct a struct scic_sds_remote_device that is in a stopped @@ -922,18 +917,16 @@ static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( * enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - struct scic_sds_remote_device *sci_dev; struct scic_sds_controller *scic; - sci_dev = container_of(base_dev, typeof(*sci_dev), parent); scic = scic_sds_remote_device_get_controller(sci_dev); scic_sds_controller_free_remote_node_context(scic, sci_dev, sci_dev->rnc->remote_node_index); sci_dev->rnc->remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - sci_base_state_machine_change_state(&base_dev->state_machine, + sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FINAL); return SCI_SUCCESS; @@ -945,11 +938,8 @@ static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( * ***************************************************************************** */ static enum sci_status scic_sds_remote_device_starting_state_stop_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - struct scic_sds_remote_device *sci_dev; - - sci_dev = container_of(base_dev, typeof(*sci_dev), parent); /* * This device has not yet started so there had better be no IO requests */ @@ -965,21 +955,19 @@ static enum sci_status scic_sds_remote_device_starting_state_stop_handler( * Transition to the stopping state and wait for the remote node to * complete being posted and invalidated. */ - sci_base_state_machine_change_state(&base_dev->state_machine, + sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); return SCI_SUCCESS; } enum sci_status scic_sds_remote_device_ready_state_stop_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - struct scic_sds_remote_device *sci_dev; enum sci_status status = SCI_SUCCESS; - sci_dev = container_of(base_dev, typeof(*sci_dev), parent); /* Request the parent state machine to transition to the stopping state */ - sci_base_state_machine_change_state(&base_dev->state_machine, + sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); if (sci_dev->started_request_count == 0) { @@ -994,19 +982,16 @@ enum sci_status scic_sds_remote_device_ready_state_stop_handler( /** * - * @device: The struct sci_base_remote_device object which is cast to a + * @device: The struct scic_sds_remote_device object which is cast to a * struct scic_sds_remote_device object. * * This is the ready state device reset handler enum sci_status */ enum sci_status scic_sds_remote_device_ready_state_reset_handler( - struct sci_base_remote_device *base_dev) + struct scic_sds_remote_device *sci_dev) { - struct scic_sds_remote_device *sci_dev; - - sci_dev = container_of(base_dev, typeof(*sci_dev), parent); /* Request the parent state machine to transition to the stopping state */ - sci_base_state_machine_change_state(&base_dev->state_machine, + sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_RESETTING); return SCI_SUCCESS; @@ -1021,23 +1006,22 @@ enum sci_status scic_sds_remote_device_ready_state_reset_handler( * object could not get the resources to start. */ static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { enum sci_status result; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; /* See if the port is in a state where we can start the IO request */ result = scic_sds_port_start_io( - scic_sds_remote_device_get_port(this_device), this_device, request); + scic_sds_remote_device_get_port(sci_dev), sci_dev, request); if (result == SCI_SUCCESS) { result = scic_sds_remote_node_context_start_task( - this_device->rnc, request); + sci_dev->rnc, request); if (result == SCI_SUCCESS) result = scic_sds_request_start(request); - scic_sds_remote_device_start_request(this_device, request, result); + scic_sds_remote_device_start_request(sci_dev, request, result); } return result; @@ -1052,23 +1036,22 @@ static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( * object could not get the resources to start. */ static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { enum sci_status result; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; /* See if the port is in a state where we can start the IO request */ result = scic_sds_port_start_io( - scic_sds_remote_device_get_port(this_device), this_device, request); + scic_sds_remote_device_get_port(sci_dev), sci_dev, request); if (result == SCI_SUCCESS) { result = scic_sds_remote_node_context_start_io( - this_device->rnc, request); + sci_dev->rnc, request); if (result == SCI_SUCCESS) result = scic_sds_request_start(request); - scic_sds_remote_device_start_request(this_device, request, result); + scic_sds_remote_device_start_request(sci_dev, request, result); } return result; @@ -1081,23 +1064,24 @@ static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( * its own started_request_count. enum sci_status */ static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { enum sci_status result; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; result = scic_sds_request_complete(request); - if (result == SCI_SUCCESS) { - /* See if the port is in a state where we can start the IO request */ - result = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(this_device), this_device, request); + if (result != SCI_SUCCESS) + return result; - if (result == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(this_device); - } - } + /* See if the port is in a state + * where we can start the IO request */ + result = scic_sds_port_complete_io( + scic_sds_remote_device_get_port(sci_dev), + sci_dev, request); + + if (result == SCI_SUCCESS) + scic_sds_remote_device_decrement_request_count(sci_dev); return result; } @@ -1109,7 +1093,7 @@ static enum sci_status scic_sds_remote_device_ready_state_complete_request_handl /** * - * @this_device: The struct sci_base_remote_device which is cast into a + * @this_device: The struct scic_sds_remote_device which is cast into a * struct scic_sds_remote_device. * * This method will stop a struct scic_sds_remote_device that is already in the @@ -1118,14 +1102,13 @@ static enum sci_status scic_sds_remote_device_ready_state_complete_request_handl * stopped. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( - struct sci_base_remote_device *device) + struct scic_sds_remote_device *device) { /* * All requests should have been terminated, but if there is an * attempt to stop a device already in the stopping state, then * try again to terminate. */ - return scic_sds_remote_device_terminate_requests( - (struct scic_sds_remote_device *)device); + return scic_sds_remote_device_terminate_requests(device); } @@ -1143,54 +1126,44 @@ static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( * transition to the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. enum sci_status */ static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { enum sci_status status = SCI_SUCCESS; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; status = scic_sds_request_complete(request); - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(this_device), - this_device, request); - if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(this_device); - - if (scic_sds_remote_device_get_request_count(this_device) == 0) { - scic_sds_remote_node_context_destruct( - this_device->rnc, - scic_sds_cb_remote_device_rnc_destruct_complete, - this_device - ); - } - } - } + if (status != SCI_SUCCESS) + return status; - return status; -} + status = scic_sds_port_complete_io(scic_sds_remote_device_get_port(sci_dev), + sci_dev, request); + if (status != SCI_SUCCESS) + return status; -/* - * ***************************************************************************** - * * RESETTING STATE HANDLERS - * ***************************************************************************** */ + scic_sds_remote_device_decrement_request_count(sci_dev); + + if (scic_sds_remote_device_get_request_count(sci_dev) == 0) + scic_sds_remote_node_context_destruct(sci_dev->rnc, + scic_sds_cb_remote_device_rnc_destruct_complete, + sci_dev); + return SCI_SUCCESS; +} /** * - * @device: The struct sci_base_remote_device which is to be cast into a + * @device: The struct scic_sds_remote_device which is to be cast into a * struct scic_sds_remote_device object. * * This method will complete the reset operation when the device is in the * resetting state. enum sci_status */ static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( - struct sci_base_remote_device *device) + struct scic_sds_remote_device *sci_dev) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; sci_base_state_machine_change_state( - &this_device->parent.state_machine, + &sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_READY ); @@ -1199,19 +1172,17 @@ static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_han /** * - * @device: The struct sci_base_remote_device which is to be cast into a + * @device: The struct scic_sds_remote_device which is to be cast into a * struct scic_sds_remote_device object. * * This method will stop the remote device while in the resetting state. * enum sci_status */ static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( - struct sci_base_remote_device *device) + struct scic_sds_remote_device *sci_dev) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; - sci_base_state_machine_change_state( - &this_device->parent.state_machine, + &sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING ); @@ -1226,20 +1197,20 @@ static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( * completes the task request. enum sci_status */ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { enum sci_status status = SCI_SUCCESS; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; status = scic_sds_request_complete(request); if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(this_device), this_device, request); + scic_sds_remote_device_get_port(sci_dev), + sci_dev, request); if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(this_device); + scic_sds_remote_device_decrement_request_count(sci_dev); } } @@ -1253,7 +1224,7 @@ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_h /** * - * @device: The struct sci_base_remote_device which is to be cast into a + * @device: The struct scic_sds_remote_device which is to be cast into a * struct scic_sds_remote_device object. * * This method handles the remove request for a failed struct scic_sds_remote_device @@ -1265,140 +1236,140 @@ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_h static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_default_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .parent.start_handler = scic_sds_remote_device_stopped_state_start_handler, - .parent.stop_handler = scic_sds_remote_device_stopped_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler + .start_handler = scic_sds_remote_device_stopped_state_start_handler, + .stop_handler = scic_sds_remote_device_stopped_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_starting_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_starting_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, - .parent.complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, - .parent.complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler, + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, + .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, + .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_stopping_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_stopping_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_default_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_resetting_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_resetting_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_default_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler } }; @@ -1415,12 +1386,12 @@ static void scic_sds_remote_device_initial_state_enter( { struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - sci_dev = container_of(object, typeof(*sci_dev), parent.parent); + sci_dev = container_of(object, typeof(*sci_dev), parent); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); /* Initial state is a transitional state to the stopped state */ - sci_base_state_machine_change_state(&sci_dev->parent.state_machine, + sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); } @@ -1443,7 +1414,7 @@ static void scic_sds_remote_device_stopped_state_enter( struct isci_host *ihost; u32 prev_state; - sci_dev = container_of(object, typeof(*sci_dev), parent.parent); + sci_dev = container_of(object, typeof(*sci_dev), parent); scic = scic_sds_remote_device_get_controller(sci_dev); ihost = sci_object_get_association(scic); idev = sci_object_get_association(sci_dev); @@ -1454,7 +1425,7 @@ static void scic_sds_remote_device_stopped_state_enter( /* If we are entering from the stopping state let the SCI User know that * the stop operation has completed. */ - prev_state = sci_dev->parent.state_machine.previous_state_id; + prev_state = sci_dev->state_machine.previous_state_id; if (prev_state == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) isci_remote_device_stop_complete(ihost, idev, SCI_SUCCESS); @@ -1473,7 +1444,7 @@ static void scic_sds_remote_device_stopped_state_enter( static void scic_sds_remote_device_starting_state_enter(struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); @@ -1488,7 +1459,7 @@ static void scic_sds_remote_device_starting_state_enter(struct sci_base_object * static void scic_sds_remote_device_starting_state_exit(struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); @@ -1511,7 +1482,7 @@ static void scic_sds_remote_device_starting_state_exit(struct sci_base_object *o static void scic_sds_remote_device_ready_state_enter(struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); @@ -1540,7 +1511,7 @@ static void scic_sds_remote_device_ready_state_exit( struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); if (sci_dev->has_ready_substate_machine) sci_base_state_machine_stop(&sci_dev->ready_substate_machine); else { @@ -1691,10 +1662,17 @@ void scic_remote_device_construct(struct scic_sds_port *sci_port, sci_dev->owning_port = sci_port; sci_dev->started_request_count = 0; sci_dev->rnc = (struct scic_sds_remote_node_context *) &sci_dev[1]; + sci_dev->parent.private = NULL; - sci_base_remote_device_construct( + sci_base_state_machine_construct( + &sci_dev->state_machine, &sci_dev->parent, - scic_sds_remote_device_state_table + scic_sds_remote_device_state_table, + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL + ); + + sci_base_state_machine_start( + &sci_dev->state_machine ); scic_sds_remote_node_context_construct( diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index 90b231833872..0e8bb0f98b1e 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -56,22 +56,74 @@ #ifndef _SCIC_SDS_REMOTE_DEVICE_H_ #define _SCIC_SDS_REMOTE_DEVICE_H_ +#include "intel_sas.h" +#include "scu_remote_node_context.h" +#include "scic_sds_remote_node_context.h" + /** - * This file contains the structures, constants, and prototypes for the - * struct scic_sds_remote_device object. + * enum scic_sds_remote_device_states - This enumeration depicts all the states + * for the common remote device state machine. * * */ +enum scic_sds_remote_device_states { + /** + * Simply the initial state for the base remote device state machine. + */ + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL, -#include "intel_sas.h" -#include "sci_base_remote_device.h" -#include "scu_remote_node_context.h" -#include "scic_sds_remote_node_context.h" + /** + * This state indicates that the remote device has successfully been + * stopped. In this state no new IO operations are permitted. + * This state is entered from the INITIAL state. + * This state is entered from the STOPPING state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED, + + /** + * This state indicates the the remote device is in the process of + * becoming ready (i.e. starting). In this state no new IO operations + * are permitted. + * This state is entered from the STOPPED state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STARTING, + + /** + * This state indicates the remote device is now ready. Thus, the user + * is able to perform IO operations on the remote device. + * This state is entered from the STARTING state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_READY, + + /** + * This state indicates that the remote device is in the process of + * stopping. In this state no new IO operations are permitted, but + * existing IO operations are allowed to complete. + * This state is entered from the READY state. + * This state is entered from the FAILED state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, + + /** + * This state indicates that the remote device has failed. + * In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + * This state is entered from the READY state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_FAILED, -struct scic_sds_controller; -struct scic_sds_port; -struct scic_sds_request; -struct scic_sds_remote_device_state_handler; + /** + * This state indicates the device is being reset. + * In this state no new IO operations are permitted. + * This state is entered from the READY state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, + + /** + * Simply the final state for the base remote device state machine. + */ + SCI_BASE_REMOTE_DEVICE_STATE_FINAL, +}; /** * enum scic_sds_ssp_remote_device_ready_substates - @@ -186,14 +238,21 @@ enum scic_sds_smp_remote_device_ready_substates { */ struct scic_sds_remote_device { /** - * This field is the common base for all remote device objects. + * The field specifies that the parent object for the base remote + * device is the base object itself. + */ + struct sci_base_object parent; + + /** + * This field contains the information for the base remote device state + * machine. */ - struct sci_base_remote_device parent; + struct sci_base_state_machine state_machine; /** - * This field is the programmed device port width. This value is written to - * the RCN data structure to tell the SCU how many open connections this - * device can have. + * This field is the programmed device port width. This value is + * written to the RCN data structure to tell the SCU how many open + * connections this device can have. */ u32 device_port_width; @@ -279,6 +338,16 @@ struct scic_sds_remote_device { const struct scic_sds_remote_device_state_handler *state_handlers; }; +typedef enum sci_status (*scic_sds_remote_device_request_handler_t)( + struct scic_sds_remote_device *device, + struct scic_sds_request *request); + +typedef enum sci_status (*scic_sds_remote_device_high_priority_request_complete_handler_t)( + struct scic_sds_remote_device *device, + struct scic_sds_request *request, + void *, + enum sci_io_status); + typedef enum sci_status (*scic_sds_remote_device_handler_t)( struct scic_sds_remote_device *this_device); @@ -308,7 +377,74 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - struct sci_base_remote_device_state_handler parent; + /** + * The start_handler specifies the method invoked when a user + * attempts to start a remote device. + */ + scic_sds_remote_device_handler_t start_handler; + + /** + * The stop_handler specifies the method invoked when a user attempts to + * stop a remote device. + */ + scic_sds_remote_device_handler_t stop_handler; + + /** + * The fail_handler specifies the method invoked when a remote device + * failure has occurred. A failure may be due to an inability to + * initialize/configure the device. + */ + scic_sds_remote_device_handler_t fail_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a remote device. + */ + scic_sds_remote_device_handler_t destruct_handler; + + /** + * The reset handler specifies the method invloked when requesting to + * reset a remote device. + */ + scic_sds_remote_device_handler_t reset_handler; + + /** + * The reset complete handler specifies the method invloked when + * reporting that a reset has completed to the remote device. + */ + scic_sds_remote_device_handler_t reset_complete_handler; + + /** + * The start_io_handler specifies the method invoked when a user + * attempts to start an IO request for a remote device. + */ + scic_sds_remote_device_request_handler_t start_io_handler; + + /** + * The complete_io_handler specifies the method invoked when a user + * attempts to complete an IO request for a remote device. + */ + scic_sds_remote_device_request_handler_t complete_io_handler; + + /** + * The continue_io_handler specifies the method invoked when a user + * attempts to continue an IO request for a remote device. + */ + scic_sds_remote_device_request_handler_t continue_io_handler; + + /** + * The start_task_handler specifies the method invoked when a user + * attempts to start a task management request for a remote device. + */ + scic_sds_remote_device_request_handler_t start_task_handler; + + /** + * The complete_task_handler specifies the method invoked when a user + * attempts to complete a task management request for a remote device. + */ + scic_sds_remote_device_request_handler_t complete_task_handler; + + scic_sds_remote_device_suspend_handler_t suspend_handler; scic_sds_remote_device_resume_handler_t resume_handler; scic_sds_remote_device_event_handler_t event_handler; @@ -490,30 +626,30 @@ void scic_sds_remote_device_start_request( void scic_sds_remote_device_continue_request(void *sci_dev); enum sci_status scic_sds_remote_device_default_start_handler( - struct sci_base_remote_device *this_device); + struct scic_sds_remote_device *this_device); enum sci_status scic_sds_remote_device_default_fail_handler( - struct sci_base_remote_device *this_device); + struct scic_sds_remote_device *this_device); enum sci_status scic_sds_remote_device_default_destruct_handler( - struct sci_base_remote_device *this_device); + struct scic_sds_remote_device *this_device); enum sci_status scic_sds_remote_device_default_reset_handler( - struct sci_base_remote_device *device); + struct scic_sds_remote_device *device); enum sci_status scic_sds_remote_device_default_reset_complete_handler( - struct sci_base_remote_device *device); + struct scic_sds_remote_device *device); enum sci_status scic_sds_remote_device_default_start_request_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request); enum sci_status scic_sds_remote_device_default_complete_request_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request); enum sci_status scic_sds_remote_device_default_continue_request_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request); enum sci_status scic_sds_remote_device_default_suspend_handler( @@ -529,10 +665,10 @@ enum sci_status scic_sds_remote_device_default_frame_handler( u32 frame_index); enum sci_status scic_sds_remote_device_ready_state_stop_handler( - struct sci_base_remote_device *device); + struct scic_sds_remote_device *device); enum sci_status scic_sds_remote_device_ready_state_reset_handler( - struct sci_base_remote_device *device); + struct scic_sds_remote_device *device); enum sci_status scic_sds_remote_device_general_frame_handler( struct scic_sds_remote_device *this_device, diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index 040a3d8c08b9..88c359548c1b 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -77,33 +77,32 @@ * the idle state. enum sci_status */ static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request) { enum sci_status status; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; /* Will the port allow the io request to start? */ - status = this_device->owning_port->state_handlers->start_io_handler( - this_device->owning_port, this_device, request); + status = device->owning_port->state_handlers->start_io_handler( + device->owning_port, device, request); if (status == SCI_SUCCESS) { - status = - scic_sds_remote_node_context_start_io(this_device->rnc, request); + status = scic_sds_remote_node_context_start_io( + device->rnc, request); if (status == SCI_SUCCESS) status = scic_sds_request_start(request); if (status == SCI_SUCCESS) { - this_device->working_request = request; + device->working_request = request; sci_base_state_machine_change_state( - &this_device->ready_substate_machine, + &device->ready_substate_machine, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD ); } - scic_sds_remote_device_start_request(this_device, request, status); + scic_sds_remote_device_start_request(device, request, status); } return status; @@ -123,7 +122,7 @@ static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_h * until this one is complete. enum sci_status */ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request) { return SCI_FAILURE_INVALID_STATE; @@ -137,38 +136,37 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_ha * * enum sci_status */ -static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( - struct sci_base_remote_device *device, +static enum sci_status +scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( + struct scic_sds_remote_device *device, struct scic_sds_request *request) { enum sci_status status; - struct scic_sds_remote_device *this_device; struct scic_sds_request *the_request; - this_device = (struct scic_sds_remote_device *)device; the_request = (struct scic_sds_request *)request; status = scic_sds_io_request_complete(the_request); if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( - this_device->owning_port, this_device, the_request); + device->owning_port, device, the_request); if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(this_device); + scic_sds_remote_device_decrement_request_count(device); sci_base_state_machine_change_state( - &this_device->ready_substate_machine, + &device->ready_substate_machine, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE ); } else - dev_err(scirdev_to_dev(this_device), + dev_err(scirdev_to_dev(device), "%s: SCIC SDS Remote Device 0x%p io request " "0x%p could not be completd on the port 0x%p " "failed with status %d.\n", __func__, - this_device, + device, the_request, - this_device->owning_port, + device->owning_port, status); } @@ -204,38 +202,38 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = { [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, - .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_default_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, - .parent.complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, + .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler } }; @@ -251,7 +249,7 @@ static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_dev static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); @@ -276,7 +274,7 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter( struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); @@ -301,7 +299,7 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter( static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); sci_dev->working_request = NULL; } diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index bb582497039b..a5b1fe3229ce 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -77,20 +77,19 @@ * completed successfully. */ static enum sci_status scic_sds_stp_remote_device_complete_request( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; enum sci_status status; status = scic_sds_io_request_complete(request); if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( - this_device->owning_port, this_device, request); + device->owning_port, device, request); if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(this_device); + scic_sds_remote_device_decrement_request_count(device); if (request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { /* * This request causes hardware error, device needs to be Lun Reset. @@ -98,12 +97,12 @@ static enum sci_status scic_sds_stp_remote_device_complete_request( * can reach RNC state handler, these IOs will be completed by RNC with * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ sci_base_state_machine_change_state( - &this_device->ready_substate_machine, + &device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET ); - } else if (scic_sds_remote_device_get_request_count(this_device) == 0) { + } else if (scic_sds_remote_device_get_request_count(device) == 0) { sci_base_state_machine_change_state( - &this_device->ready_substate_machine, + &device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE ); } @@ -111,12 +110,12 @@ static enum sci_status scic_sds_stp_remote_device_complete_request( } if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(this_device), + dev_err(scirdev_to_dev(device), "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " "could not complete\n", __func__, - this_device->owning_port, - this_device, + device->owning_port, + device, request, status); @@ -140,19 +139,18 @@ static enum sci_status scic_sds_stp_remote_device_complete_request( * callback will be called. */ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request) { enum sci_status status; - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; /* Will the port allow the io request to start? */ - status = this_device->owning_port->state_handlers->start_io_handler( - this_device->owning_port, this_device, request); + status = device->owning_port->state_handlers->start_io_handler( + device->owning_port, device, request); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_task(this_device->rnc, request); + status = scic_sds_remote_node_context_start_task(device->rnc, request); if (status != SCI_SUCCESS) goto out; @@ -164,8 +162,8 @@ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_h * Note: If the remote device state is not IDLE this will replace * the request that probably resulted in the task management request. */ - this_device->working_request = request; - sci_base_state_machine_change_state(&this_device->ready_substate_machine, + device->working_request = request; + sci_base_state_machine_change_state(&device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); /* @@ -175,14 +173,14 @@ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_h * remote node context state machine will take the correct action when * the remote node context is suspended and later resumed. */ - scic_sds_remote_node_context_suspend(this_device->rnc, + scic_sds_remote_node_context_suspend(device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); - scic_sds_remote_node_context_resume(this_device->rnc, + scic_sds_remote_node_context_resume(device->rnc, scic_sds_remote_device_continue_request, - this_device); + device); out: - scic_sds_remote_device_start_request(this_device, request, status); + scic_sds_remote_device_start_request(device, request, status); /* * We need to let the controller start request handler know that it can't * post TC yet. We will provide a callback function to post TC when RNC gets @@ -208,23 +206,21 @@ out: * enum sci_status */ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( - struct sci_base_remote_device *base_device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { enum sci_status status; - struct scic_sds_remote_device *device = - (struct scic_sds_remote_device *)&base_device->parent; struct isci_request *isci_request = (struct isci_request *)sci_object_get_association(request); /* Will the port allow the io request to start? */ - status = device->owning_port->state_handlers->start_io_handler( - device->owning_port, device, request); + status = sci_dev->owning_port->state_handlers->start_io_handler( + sci_dev->owning_port, sci_dev, request); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(device->rnc, request); + status = scic_sds_remote_node_context_start_io(sci_dev->rnc, request); if (status != SCI_SUCCESS) goto out; @@ -233,15 +229,15 @@ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_h goto out; if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { - sci_base_state_machine_change_state(&device->ready_substate_machine, + sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); } else { - device->working_request = request; - sci_base_state_machine_change_state(&device->ready_substate_machine, + sci_dev->working_request = request; + sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); } out: - scic_sds_remote_device_start_request(device, request, status); + scic_sds_remote_device_start_request(sci_dev, request, status); return status; } @@ -281,30 +277,28 @@ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_hand * ***************************************************************************** */ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( - struct sci_base_remote_device *base_device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { enum sci_status status; - struct scic_sds_remote_device *device = - (struct scic_sds_remote_device *)&base_device->parent; struct isci_request *isci_request = (struct isci_request *)sci_object_get_association(request); if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { - status = device->owning_port->state_handlers->start_io_handler( - device->owning_port, - device, + status = sci_dev->owning_port->state_handlers->start_io_handler( + sci_dev->owning_port, + sci_dev, request); if (status == SCI_SUCCESS) { status = scic_sds_remote_node_context_start_io( - device->rnc, + sci_dev->rnc, request); if (status == SCI_SUCCESS) status = request->state_handlers->start_handler(request); - scic_sds_remote_device_start_request(device, + scic_sds_remote_device_start_request(sci_dev, request, status); } @@ -392,7 +386,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl * enum sci_status */ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request) { return SCI_FAILURE_INVALID_STATE; @@ -445,7 +439,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handl * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS * ***************************************************************************** */ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request) { return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; @@ -464,10 +458,9 @@ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_sta * completed successfully. */ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( - struct sci_base_remote_device *device, + struct scic_sds_remote_device *device, struct scic_sds_request *request) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; struct scic_sds_request *the_request = (struct scic_sds_request *)request; enum sci_status status; @@ -475,20 +468,20 @@ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_com if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( - this_device->owning_port, this_device, the_request + device->owning_port, device, the_request ); if (status == SCI_SUCCESS) - scic_sds_remote_device_decrement_request_count(this_device); + scic_sds_remote_device_decrement_request_count(device); } if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(this_device), + dev_err(scirdev_to_dev(device), "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " "could not complete\n", __func__, - this_device->owning_port, - this_device, + device->owning_port, + device, the_request, status); @@ -538,68 +531,68 @@ enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_hand static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, - .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, - .parent.complete_io_handler = scic_sds_stp_remote_device_complete_request, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, - .parent.complete_io_handler = scic_sds_stp_remote_device_complete_request, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_stp_remote_device_complete_request, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, @@ -607,17 +600,17 @@ static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_dev }, #if !defined(DISABLE_ATAPI) [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, - .parent.complete_io_handler = scic_sds_stp_remote_device_complete_request, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, @@ -625,17 +618,17 @@ static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_dev }, #endif [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .parent.start_handler = scic_sds_remote_device_default_start_handler, - .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .parent.fail_handler = scic_sds_remote_device_default_fail_handler, - .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, - .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .parent.start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, - .parent.complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, - .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .parent.start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .parent.complete_task_handler = scic_sds_stp_remote_device_complete_request, + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, @@ -711,7 +704,7 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter( static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); @@ -729,7 +722,7 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_ static void scic_sds_stp_remote_device_ready_ncq_substate_enter(struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); SET_STATE_HANDLER(sci_dev, scic_sds_stp_remote_device_ready_substate_handler_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); @@ -738,7 +731,7 @@ static void scic_sds_stp_remote_device_ready_ncq_substate_enter(struct sci_base_ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_object *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent.parent); + parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = sci_object_get_association(scic); struct isci_remote_device *idev = sci_object_get_association(sci_dev); -- cgit v1.2.3 From 41e2b90584695cf5ae3a29eaa115e31913fbefe0 Mon Sep 17 00:00:00 2001 From: Maciej Trela Date: Tue, 12 Apr 2011 17:28:37 -0700 Subject: isci: remove base_port abstraction Merge struct sci_base_port into scic_sds_port. Until now sci_base_port was referenced indirectly with scic_sds_port->parent field. 'sci_base_port' state machine handlers were also incorporated into scic_sds_port handlers. Reported-by: Christoph Hellwig Signed-off-by: Maciej Trela Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_port.h | 187 --------- drivers/scsi/isci/core/scic_sds_controller.c | 10 +- drivers/scsi/isci/core/scic_sds_port.c | 442 ++++++++------------- drivers/scsi/isci/core/scic_sds_port.h | 168 +++++--- .../isci/core/scic_sds_port_configuration_agent.c | 2 +- 5 files changed, 285 insertions(+), 524 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_base_port.h diff --git a/drivers/scsi/isci/core/sci_base_port.h b/drivers/scsi/isci/core/sci_base_port.h deleted file mode 100644 index 252d48c1ab65..000000000000 --- a/drivers/scsi/isci/core/sci_base_port.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_PORT_H_ -#define _SCI_BASE_PORT_H_ - -#include "sci_base_state_machine.h" -#include "sci_object.h" - -/** - * enum sci_base_port_states - This enumeration depicts all the states for the - * common port state machine. - * - * - */ -enum sci_base_port_states { - /** - * This state indicates that the port has successfully been stopped. - * In this state no new IO operations are permitted. - * This state is entered from the STOPPING state. - */ - SCI_BASE_PORT_STATE_STOPPED, - - /** - * This state indicates that the port is in the process of stopping. - * In this state no new IO operations are permitted, but existing IO - * operations are allowed to complete. - * This state is entered from the READY state. - */ - SCI_BASE_PORT_STATE_STOPPING, - - /** - * This state indicates the port is now ready. Thus, the user is - * able to perform IO operations on this port. - * This state is entered from the STARTING state. - */ - SCI_BASE_PORT_STATE_READY, - - /** - * This state indicates the port is in the process of performing a hard - * reset. Thus, the user is unable to perform IO operations on this - * port. - * This state is entered from the READY state. - */ - SCI_BASE_PORT_STATE_RESETTING, - - /** - * This state indicates the port has failed a reset request. This state - * is entered when a port reset request times out. - * This state is entered from the RESETTING state. - */ - SCI_BASE_PORT_STATE_FAILED, - - SCI_BASE_PORT_MAX_STATES - -}; - -/** - * struct sci_base_port - The base port object abstracts the fields common to - * all SCI port objects. - * - * - */ -struct sci_base_port { - /** - * The field specifies that the parent object for the base controller - * is the base object itself. - */ - struct sci_base_object parent; - - /** - * This field contains the information for the base port state machine. - */ - struct sci_base_state_machine state_machine; -}; - -struct sci_base_phy; - -typedef enum sci_status (*sci_base_port_handler_t) ( - struct sci_base_port *); - -typedef enum sci_status (*sci_base_port_phy_handler_t) ( - struct sci_base_port *, - struct sci_base_phy *); - -typedef enum sci_status (*sci_base_port_reset_handler_t) ( - struct sci_base_port *, - u32 timeout); - -/** - * struct sci_base_port_state_handler - This structure contains all of the - * state handler methods common to base port state machines. Handler - * methods provide the ability to change the behavior for user requests or - * transitions depending on the state the machine is in. - * - * - */ -struct sci_base_port_state_handler { - /** - * The start_handler specifies the method invoked when a user - * attempts to start a port. - */ - sci_base_port_handler_t start_handler; - - /** - * The stop_handler specifies the method invoked when a user - * attempts to stop a port. - */ - sci_base_port_handler_t stop_handler; - - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a port. - */ - sci_base_port_handler_t destruct_handler; - - /** - * The reset_handler specifies the method invoked when a user - * attempts to hard reset a port. - */ - sci_base_port_reset_handler_t reset_handler; - - /** - * The add_phy_handler specifies the method invoked when a user - * attempts to add another phy into the port. - */ - sci_base_port_phy_handler_t add_phy_handler; - - /** - * The remove_phy_handler specifies the method invoked when a user - * attempts to remove a phy from the port. - */ - sci_base_port_phy_handler_t remove_phy_handler; -}; -#endif /* _SCI_BASE_PORT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 7a0c5905cfbe..577d1df2cfd2 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -616,10 +616,10 @@ static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller for (index = 0; index < scic->logical_port_entries; index++) { struct scic_sds_port *sci_port = &scic->port_table[index]; - sci_base_port_handler_t stop; + scic_sds_port_handler_t stop; - stop = sci_port->state_handlers->parent.stop_handler; - port_status = stop(&sci_port->parent); + stop = sci_port->state_handlers->stop_handler; + port_status = stop(sci_port); if ((port_status != SCI_SUCCESS) && (port_status != SCI_FAILURE_INVALID_STATE)) { @@ -2860,8 +2860,8 @@ enum sci_status scic_controller_start(struct scic_sds_controller *scic, for (index = 0; index < scic->logical_port_entries; index++) { struct scic_sds_port *sci_port = &scic->port_table[index]; - result = sci_port->state_handlers->parent.start_handler( - &sci_port->parent); + result = sci_port->state_handlers->start_handler( + sci_port); if (result) return result; } diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index ef9cb9eb66f4..ff9ac73927a4 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -54,7 +54,6 @@ */ #include "intel_sas.h" -#include "sci_base_port.h" #include "scic_controller.h" #include "scic_phy.h" #include "scic_port.h" @@ -73,22 +72,6 @@ #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) #define SCU_DUMMY_INDEX (0xFFFF) -static void sci_base_port_construct( - struct sci_base_port *base_port, - const struct sci_base_state *state_table) -{ - base_port->parent.private = NULL; - sci_base_state_machine_construct( - &base_port->state_machine, - &base_port->parent, - state_table, - SCI_BASE_PORT_STATE_STOPPED - ); - - sci_base_state_machine_start( - &base_port->state_machine - ); -} /** * @@ -332,8 +315,8 @@ enum sci_status scic_sds_port_add_phy( struct scic_sds_port *this_port, struct scic_sds_phy *the_phy) { - return this_port->state_handlers->parent.add_phy_handler( - &this_port->parent, &the_phy->parent); + return this_port->state_handlers->add_phy_handler( + this_port, &the_phy->parent); } @@ -350,8 +333,8 @@ enum sci_status scic_sds_port_remove_phy( struct scic_sds_port *this_port, struct scic_sds_phy *the_phy) { - return this_port->state_handlers->parent.remove_phy_handler( - &this_port->parent, &the_phy->parent); + return this_port->state_handlers->remove_phy_handler( + this_port, &the_phy->parent); } /** @@ -632,8 +615,8 @@ enum sci_status scic_port_hard_reset( struct scic_sds_port *port, u32 reset_timeout) { - return port->state_handlers->parent.reset_handler( - &port->parent, reset_timeout); + return port->state_handlers->reset_handler( + port, reset_timeout); } /** @@ -768,7 +751,7 @@ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port if ((phy_sas_address.high == port_sas_address.high && phy_sas_address.low == port_sas_address.low) || sci_port->active_phy_mask == 0) { - struct sci_base_state_machine *sm = &sci_port->parent.state_machine; + struct sci_base_state_machine *sm = &sci_port->state_machine; scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING) @@ -913,7 +896,7 @@ static void scic_sds_port_timeout_handler(void *port) u32 current_state; current_state = sci_base_state_machine_get_state( - &sci_port->parent.state_machine); + &sci_port->state_machine); if (current_state == SCI_BASE_PORT_STATE_RESETTING) { /* @@ -921,7 +904,7 @@ static void scic_sds_port_timeout_handler(void *port) * timeout fired before the reset completed. */ sci_base_state_machine_change_state( - &sci_port->parent.state_machine, + &sci_port->state_machine, SCI_BASE_PORT_STATE_FAILED); } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { /* @@ -1068,22 +1051,16 @@ void scic_port_enable_broadcast_change_notification( * * READY SUBSTATE HANDLERS * **************************************************************************** */ -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * +/* * This method is the general ready state stop handler for the struct scic_sds_port * object. This function will transition the ready substate machine to its * final state. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_port_ready_substate_stop_handler( - struct sci_base_port *port) + struct scic_sds_port *port) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; - sci_base_state_machine_change_state( - &this_port->parent.state_machine, + &port->state_machine, SCI_BASE_PORT_STATE_STOPPING ); @@ -1100,30 +1077,27 @@ static enum sci_status scic_sds_port_ready_substate_complete_io_handler( struct scic_sds_remote_device *device, struct scic_sds_request *io_request) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; - - scic_sds_port_decrement_request_count(this_port); + scic_sds_port_decrement_request_count(port); return SCI_SUCCESS; } static enum sci_status scic_sds_port_ready_substate_add_phy_handler( - struct sci_base_port *port, + struct scic_sds_port *port, struct sci_base_phy *phy) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; enum sci_status status; - status = scic_sds_port_set_phy(this_port, this_phy); + status = scic_sds_port_set_phy(port, this_phy); if (status == SCI_SUCCESS) { - scic_sds_port_general_link_up_handler(this_port, this_phy, true); + scic_sds_port_general_link_up_handler(port, this_phy, true); - this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; sci_base_state_machine_change_state( - &this_port->ready_substate_machine, + &port->ready_substate_machine, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING ); } @@ -1133,22 +1107,21 @@ static enum sci_status scic_sds_port_ready_substate_add_phy_handler( static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( - struct sci_base_port *port, + struct scic_sds_port *port, struct sci_base_phy *phy) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; enum sci_status status; - status = scic_sds_port_clear_phy(this_port, this_phy); + status = scic_sds_port_clear_phy(port, this_phy); if (status == SCI_SUCCESS) { - scic_sds_port_deactivate_phy(this_port, this_phy, true); + scic_sds_port_deactivate_phy(port, this_phy, true); - this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; sci_base_state_machine_change_state( - &this_port->ready_substate_machine, + &port->ready_substate_machine, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING ); } @@ -1204,22 +1177,16 @@ static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( * * READY SUBSTATE OPERATIONAL HANDLERS * **************************************************************************** */ -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * @timeout: This is the timeout for the reset request to complete. - * +/* * This method will casue the port to reset. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_port_ready_operational_substate_reset_handler( - struct sci_base_port *port, + struct scic_sds_port *port, u32 timeout) { enum sci_status status = SCI_FAILURE_INVALID_PHY; u32 phy_index; - struct scic_sds_port *sci_port = (struct scic_sds_port *)port; struct scic_sds_phy *selected_phy = NULL; @@ -1227,10 +1194,10 @@ sci_status scic_sds_port_ready_operational_substate_reset_handler( for (phy_index = 0; (phy_index < SCI_MAX_PHYS) && (selected_phy == NULL); phy_index++) { - selected_phy = sci_port->phy_table[phy_index]; + selected_phy = port->phy_table[phy_index]; if ((selected_phy != NULL) && - !scic_sds_port_active_phy(sci_port, selected_phy)) { + !scic_sds_port_active_phy(port, selected_phy)) { /* * We found a phy but it is not ready select * different phy @@ -1244,12 +1211,12 @@ sci_status scic_sds_port_ready_operational_substate_reset_handler( status = scic_sds_phy_reset(selected_phy); if (status == SCI_SUCCESS) { - isci_timer_start(sci_port->timer_handle, timeout); - sci_port->not_ready_reason = + isci_timer_start(port->timer_handle, timeout); + port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; sci_base_state_machine_change_state( - &sci_port->parent.state_machine, + &port->state_machine, SCI_BASE_PORT_STATE_RESETTING); } } @@ -1310,9 +1277,7 @@ static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler struct scic_sds_remote_device *device, struct scic_sds_request *io_request) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; - - scic_sds_port_increment_request_count(this_port); + scic_sds_port_increment_request_count(port); return SCI_SUCCESS; } @@ -1322,32 +1287,27 @@ static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler * * READY SUBSTATE OPERATIONAL HANDLERS * **************************************************************************** */ -/** - * scic_sds_port_ready_configuring_substate_add_phy_handler() - - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * +/* * This is the default method for a port add phy request. It will report a * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE */ static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( - struct sci_base_port *port, + struct scic_sds_port *port, struct sci_base_phy *phy) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; enum sci_status status; - status = scic_sds_port_set_phy(this_port, this_phy); + status = scic_sds_port_set_phy(port, this_phy); if (status == SCI_SUCCESS) { - scic_sds_port_general_link_up_handler(this_port, this_phy, true); + scic_sds_port_general_link_up_handler(port, this_phy, true); /* * Re-enter the configuring state since this may be the last phy in * the port. */ sci_base_state_machine_change_state( - &this_port->ready_substate_machine, + &port->ready_substate_machine, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING ); } @@ -1355,32 +1315,27 @@ static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( return status; } -/** - * scic_sds_port_ready_configuring_substate_remove_phy_handler() - - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * +/* * This is the default method for a port remove phy request. It will report a * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE */ static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler( - struct sci_base_port *port, + struct scic_sds_port *port, struct sci_base_phy *phy) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; enum sci_status status; - status = scic_sds_port_clear_phy(this_port, this_phy); + status = scic_sds_port_clear_phy(port, this_phy); if (status == SCI_SUCCESS) { - scic_sds_port_deactivate_phy(this_port, this_phy, true); + scic_sds_port_deactivate_phy(port, this_phy, true); /* * Re-enter the configuring state since this may be the last phy in * the port. */ sci_base_state_machine_change_state( - &this_port->ready_substate_machine, + &port->ready_substate_machine, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING ); } @@ -1397,7 +1352,8 @@ static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handl * the request count goes to 0 then the port can be reprogrammed with its new * phy data. */ -static enum sci_status scic_sds_port_ready_configuring_substate_complete_io_handler( +static enum sci_status +scic_sds_port_ready_configuring_substate_complete_io_handler( struct scic_sds_port *port, struct scic_sds_remote_device *device, struct scic_sds_request *io_request) @@ -1414,66 +1370,67 @@ static enum sci_status scic_sds_port_ready_configuring_substate_complete_io_hand return SCI_SUCCESS; } -static enum sci_status default_port_handler(struct sci_base_port *base_port, const char *func) +static enum sci_status default_port_handler(struct scic_sds_port *sci_port, + const char *func) { - struct scic_sds_port *sci_port; - - sci_port = container_of(base_port, typeof(*sci_port), parent); dev_warn(sciport_to_dev(sci_port), "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&base_port->state_machine)); + sci_base_state_machine_get_state(&sci_port->state_machine)); return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_port_default_start_handler(struct sci_base_port *base_port) +static enum sci_status +scic_sds_port_default_start_handler(struct scic_sds_port *sci_port) { - return default_port_handler(base_port, __func__); + return default_port_handler(sci_port, __func__); } -static enum sci_status scic_sds_port_default_stop_handler(struct sci_base_port *base_port) +static enum sci_status +scic_sds_port_default_stop_handler(struct scic_sds_port *sci_port) { - return default_port_handler(base_port, __func__); + return default_port_handler(sci_port, __func__); } -static enum sci_status scic_sds_port_default_destruct_handler(struct sci_base_port *base_port) +static enum sci_status +scic_sds_port_default_destruct_handler(struct scic_sds_port *sci_port) { - return default_port_handler(base_port, __func__); + return default_port_handler(sci_port, __func__); } -static enum sci_status scic_sds_port_default_reset_handler(struct sci_base_port *base_port, - u32 timeout) +static enum sci_status +scic_sds_port_default_reset_handler(struct scic_sds_port *sci_port, + u32 timeout) { - return default_port_handler(base_port, __func__); + return default_port_handler(sci_port, __func__); } -static enum sci_status scic_sds_port_default_add_phy_handler(struct sci_base_port *base_port, - struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_port_default_add_phy_handler(struct scic_sds_port *sci_port, + struct sci_base_phy *base_phy) { - return default_port_handler(base_port, __func__); + return default_port_handler(sci_port, __func__); } -static enum sci_status scic_sds_port_default_remove_phy_handler(struct sci_base_port *base_port, - struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_port_default_remove_phy_handler(struct scic_sds_port *sci_port, + struct sci_base_phy *base_phy) { - return default_port_handler(base_port, __func__); + return default_port_handler(sci_port, __func__); } -/** - * scic_sds_port_default_frame_handler - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * +/* * This is the default method for a port unsolicited frame request. It will * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even * possible to receive an unsolicited frame directed to a port object? It * seems possible if we implementing virtual functions but until then? */ -static enum sci_status scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port, - u32 frame_index) +static enum sci_status +scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port, + u32 frame_index) { struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - default_port_handler(&sci_port->parent, __func__); + default_port_handler(sci_port, __func__); scic_sds_controller_release_frame(scic, frame_index); return SCI_FAILURE_INVALID_STATE; @@ -1482,50 +1439,47 @@ static enum sci_status scic_sds_port_default_frame_handler(struct scic_sds_port static enum sci_status scic_sds_port_default_event_handler(struct scic_sds_port *sci_port, u32 event_code) { - return default_port_handler(&sci_port->parent, __func__); + return default_port_handler(sci_port, __func__); } static void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy) { - default_port_handler(&sci_port->parent, __func__); + default_port_handler(sci_port, __func__); } static void scic_sds_port_default_link_down_handler(struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy) { - default_port_handler(&sci_port->parent, __func__); + default_port_handler(sci_port, __func__); } static enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, struct scic_sds_request *sci_req) { - return default_port_handler(&sci_port->parent, __func__); + return default_port_handler(sci_port, __func__); } static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, struct scic_sds_request *sci_req) { - return default_port_handler(&sci_port->parent, __func__); + return default_port_handler(sci_port, __func__); } static struct scic_sds_port_state_handler -scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = -{ - /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */ +scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = { { - { - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_ready_substate_add_phy_handler, - scic_sds_port_default_remove_phy_handler - }, + /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */ + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_ready_substate_add_phy_handler, + scic_sds_port_default_remove_phy_handler, scic_sds_port_default_frame_handler, scic_sds_port_default_event_handler, scic_sds_port_ready_waiting_substate_link_up_handler, @@ -1533,33 +1487,31 @@ scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = scic_sds_port_ready_waiting_substate_start_io_handler, scic_sds_port_ready_substate_complete_io_handler, }, - /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */ + { - { - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_ready_operational_substate_reset_handler, - scic_sds_port_ready_substate_add_phy_handler, - scic_sds_port_ready_substate_remove_phy_handler - }, + /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */ + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_ready_operational_substate_reset_handler, + scic_sds_port_ready_substate_add_phy_handler, + scic_sds_port_ready_substate_remove_phy_handler, scic_sds_port_default_frame_handler, scic_sds_port_default_event_handler, scic_sds_port_ready_operational_substate_link_up_handler, scic_sds_port_ready_operational_substate_link_down_handler, scic_sds_port_ready_operational_substate_start_io_handler, - scic_sds_port_ready_substate_complete_io_handler + scic_sds_port_ready_substate_complete_io_handler, }, - /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */ + { - { - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_ready_configuring_substate_add_phy_handler, - scic_sds_port_ready_configuring_substate_remove_phy_handler - }, + /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */ + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_ready_configuring_substate_add_phy_handler, + scic_sds_port_ready_configuring_substate_remove_phy_handler, scic_sds_port_default_frame_handler, scic_sds_port_default_event_handler, scic_sds_port_default_link_up_handler, @@ -1857,9 +1809,7 @@ static enum sci_status scic_sds_port_general_complete_io_handler( struct scic_sds_remote_device *device, struct scic_sds_request *io_request) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; - - scic_sds_port_decrement_request_count(this_port); + scic_sds_port_decrement_request_count(port); return SCI_SUCCESS; } @@ -1867,7 +1817,7 @@ static enum sci_status scic_sds_port_general_complete_io_handler( /** * scic_sds_port_stopped_state_start_handler() - stop a port from "started" * - * @port: This is the struct sci_base_port object which is cast into a + * @port: This is the struct scic_sds_port object which is cast into a * struct scic_sds_port object. * * This function takes the struct scic_sds_port from a stopped state and @@ -1883,10 +1833,8 @@ static enum sci_status scic_sds_port_general_complete_io_handler( * has transitioned to the SCI_BASE_PORT_STATE_READY. */ static enum sci_status -scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port) +scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port) { - struct scic_sds_port *sci_port = - container_of(base_port, typeof(*sci_port), parent); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = sci_object_get_association(scic); enum sci_status status = SCI_SUCCESS; @@ -1941,8 +1889,9 @@ scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port) * silicon. */ if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { - sci_base_state_machine_change_state(&base_port->state_machine, - SCI_BASE_PORT_STATE_READY); + sci_base_state_machine_change_state( + &sci_port->state_machine, + SCI_BASE_PORT_STATE_READY); return SCI_SUCCESS; } else @@ -1955,49 +1904,33 @@ scic_sds_port_stopped_state_start_handler(struct sci_base_port *base_port) return status; } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * +/* * This method takes the struct scic_sds_port that is in a stopped state and handles a * stop request. This function takes no action. enum sci_status SCI_SUCCESS the * stop request is successful as the struct scic_sds_port object is already stopped. */ static enum sci_status scic_sds_port_stopped_state_stop_handler( - struct sci_base_port *port) + struct scic_sds_port *port) { /* We are already stopped so there is nothing to do here */ return SCI_SUCCESS; } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * +/* * This method takes the struct scic_sds_port that is in a stopped state and handles * the destruct request. The stopped state is the only state in which the * struct scic_sds_port can be destroyed. This function causes the port object to * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_port_stopped_state_destruct_handler( - struct sci_base_port *port) + struct scic_sds_port *port) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; - - sci_base_state_machine_stop(&this_port->parent.state_machine); + sci_base_state_machine_stop(&port->state_machine); return SCI_SUCCESS; } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * +/* * This method takes the struct scic_sds_port that is in a stopped state and handles * the add phy request. In MPC mode the only time a phy can be added to a port * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status @@ -2005,15 +1938,14 @@ static enum sci_status scic_sds_port_stopped_state_destruct_handler( * be added to the port. SCI_SUCCESS if the phy is added to the port. */ static enum sci_status scic_sds_port_stopped_state_add_phy_handler( - struct sci_base_port *port, + struct scic_sds_port *port, struct sci_base_phy *phy) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; struct sci_sas_address port_sas_address; /* Read the port assigned SAS Address if there is one */ - scic_sds_port_get_sas_address(this_port, &port_sas_address); + scic_sds_port_get_sas_address(port, &port_sas_address); if (port_sas_address.high != 0 && port_sas_address.low != 0) { struct sci_sas_address phy_sas_address; @@ -2031,17 +1963,11 @@ static enum sci_status scic_sds_port_stopped_state_add_phy_handler( } } - return scic_sds_port_set_phy(this_port, this_phy); + return scic_sds_port_set_phy(port, this_phy); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * +/* * This method takes the struct scic_sds_port that is in a stopped state and handles * the remove phy request. In MPC mode the only time a phy can be removed from * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status @@ -2049,13 +1975,12 @@ static enum sci_status scic_sds_port_stopped_state_add_phy_handler( * be added to the port. SCI_SUCCESS if the phy is added to the port. */ static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( - struct sci_base_port *port, + struct scic_sds_port *port, struct sci_base_phy *phy) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; - return scic_sds_port_clear_phy(this_port, this_phy); + return scic_sds_port_clear_phy(port, this_phy); } /* @@ -2073,16 +1998,7 @@ static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( * * STOPPING STATE HANDLERS * **************************************************************************** */ -/** - * - * @port: This is the struct scic_sds_port object on which the io request count will - * be decremented. - * @device: This is the struct scic_sds_remote_device object to which the io request - * is being directed. This parameter is not required to complete this - * operation. - * @io_request: This is the request that is being completed on this port - * object. This parameter is not required to complete this operation. - * +/* * This method takes the struct scic_sds_port that is in a stopping state and handles * the complete io request. Should the request count reach 0 then the port * object will transition to the stopped state. enum sci_status SCI_SUCCESS @@ -2095,7 +2011,7 @@ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( scic_sds_port_decrement_request_count(sci_port); if (sci_port->started_request_count == 0) { - sci_base_state_machine_change_state(&sci_port->parent.state_machine, + sci_base_state_machine_change_state(&sci_port->state_machine, SCI_BASE_PORT_STATE_STOPPED); } @@ -2115,29 +2031,23 @@ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( * stopping state. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_port_reset_state_stop_handler( - struct sci_base_port *port) + struct scic_sds_port *port) { - struct scic_sds_port *this_port = (struct scic_sds_port *)port; - sci_base_state_machine_change_state( - &this_port->parent.state_machine, + &port->state_machine, SCI_BASE_PORT_STATE_STOPPING ); return SCI_SUCCESS; } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * +/* * This method will transition a failed port to its ready state. The port * failed because a hard reset request timed out but at some time later one or * more phys in the port became ready. enum sci_status SCI_SUCCESS */ static void scic_sds_port_reset_state_link_up_handler( - struct scic_sds_port *this_port, + struct scic_sds_port *port, struct scic_sds_phy *phy) { /* @@ -2153,26 +2063,22 @@ static void scic_sds_port_reset_state_link_up_handler( /* * In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_general_link_up_handler(this_port, phy, false); + scic_sds_port_general_link_up_handler(port, phy, false); } -/** - * - * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port - * object. - * +/* * This method process link down notifications that occur during a port reset * operation. Link downs can occur during the reset operation. enum sci_status * SCI_SUCCESS */ static void scic_sds_port_reset_state_link_down_handler( - struct scic_sds_port *this_port, + struct scic_sds_port *port, struct scic_sds_phy *phy) { /* * In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_deactivate_phy(this_port, phy, false); + scic_sds_port_deactivate_phy(port, phy, false); } static struct scic_sds_port_state_handler @@ -2180,14 +2086,12 @@ scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = { /* SCI_BASE_PORT_STATE_STOPPED */ { - { - scic_sds_port_stopped_state_start_handler, - scic_sds_port_stopped_state_stop_handler, - scic_sds_port_stopped_state_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_stopped_state_add_phy_handler, - scic_sds_port_stopped_state_remove_phy_handler - }, + scic_sds_port_stopped_state_start_handler, + scic_sds_port_stopped_state_stop_handler, + scic_sds_port_stopped_state_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_stopped_state_add_phy_handler, + scic_sds_port_stopped_state_remove_phy_handler, scic_sds_port_default_frame_handler, scic_sds_port_default_event_handler, scic_sds_port_default_link_up_handler, @@ -2197,14 +2101,12 @@ scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = }, /* SCI_BASE_PORT_STATE_STOPPING */ { - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler - }, + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler, scic_sds_port_default_frame_handler, scic_sds_port_default_event_handler, scic_sds_port_default_link_up_handler, @@ -2214,14 +2116,12 @@ scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = }, /* SCI_BASE_PORT_STATE_READY */ { - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler - }, + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler, scic_sds_port_default_frame_handler, scic_sds_port_default_event_handler, scic_sds_port_default_link_up_handler, @@ -2231,14 +2131,12 @@ scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = }, /* SCI_BASE_PORT_STATE_RESETTING */ { - { - scic_sds_port_default_start_handler, - scic_sds_port_reset_state_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler - }, + scic_sds_port_default_start_handler, + scic_sds_port_reset_state_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler, scic_sds_port_default_frame_handler, scic_sds_port_default_event_handler, scic_sds_port_reset_state_link_up_handler, @@ -2248,14 +2146,12 @@ scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = }, /* SCI_BASE_PORT_STATE_FAILED */ { - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler - }, + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler, scic_sds_port_default_frame_handler, scic_sds_port_default_event_handler, scic_sds_port_default_link_up_handler, @@ -2385,7 +2281,7 @@ static void scic_sds_port_stopped_state_enter( if ( SCI_BASE_PORT_STATE_STOPPING - == this_port->parent.state_machine.previous_state_id + == this_port->state_machine.previous_state_id ) { /* * If we enter this state becasuse of a request to stop @@ -2431,7 +2327,7 @@ static void scic_sds_port_ready_state_enter(struct sci_base_object *object) struct isci_host *ihost; u32 prev_state; - sci_port = container_of(object, typeof(*sci_port), parent.parent); + sci_port = container_of(object, typeof(*sci_port), parent); scic = scic_sds_port_get_controller(sci_port); ihost = sci_object_get_association(scic); iport = sci_object_get_association(sci_port); @@ -2439,7 +2335,7 @@ static void scic_sds_port_ready_state_enter(struct sci_base_object *object) /* Put the ready state handlers in place though they will not be there long */ scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_READY); - prev_state = sci_port->parent.state_machine.previous_state_id; + prev_state = sci_port->state_machine.previous_state_id; if (prev_state == SCI_BASE_PORT_STATE_RESETTING) isci_port_hard_reset_complete(iport, SCI_SUCCESS); else @@ -2456,7 +2352,7 @@ static void scic_sds_port_ready_state_exit(struct sci_base_object *object) { struct scic_sds_port *sci_port; - sci_port = container_of(object, typeof(*sci_port), parent.parent); + sci_port = container_of(object, typeof(*sci_port), parent); sci_base_state_machine_stop(&sci_port->ready_substate_machine); scic_sds_port_invalidate_dummy_remote_node(sci_port); } @@ -2587,10 +2483,16 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, { u32 index; - sci_base_port_construct(&sci_port->parent, scic_sds_port_state_table); + sci_port->parent.private = NULL; + sci_base_state_machine_construct(&sci_port->state_machine, + &sci_port->parent, + scic_sds_port_state_table, + SCI_BASE_PORT_STATE_STOPPED); + + sci_base_state_machine_start(&sci_port->state_machine); sci_base_state_machine_construct(&sci_port->ready_substate_machine, - &sci_port->parent.parent, + &sci_port->parent, scic_sds_port_ready_substate_table, SCIC_SDS_PORT_READY_SUBSTATE_WAITING); diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 4cd6bbb0b570..528c84d569a0 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -56,22 +56,19 @@ #ifndef _SCIC_SDS_PORT_H_ #define _SCIC_SDS_PORT_H_ -/** - * This file contains the structures, constants and prototypes for the - * struct scic_sds_port object. - * - * - */ - #include #include "sci_controller_constants.h" #include "intel_sas.h" -#include "sci_base_port.h" #include "sci_base_phy.h" #include "scu_registers.h" #define SCIC_SDS_DUMMY_PORT 0xFF +struct scic_sds_controller; +struct scic_sds_phy; +struct scic_sds_remote_device; +struct scic_sds_request; + /** * This constant defines the value utilized by SCI Components to indicate * an invalid handle. @@ -107,10 +104,53 @@ enum scic_sds_port_ready_substates { SCIC_SDS_PORT_READY_MAX_SUBSTATES }; -struct scic_sds_controller; -struct scic_sds_phy; -struct scic_sds_remote_device; -struct scic_sds_request; +/** + * enum scic_sds_port_states - This enumeration depicts all the states for the + * common port state machine. + * + * + */ +enum scic_sds_port_states { + /** + * This state indicates that the port has successfully been stopped. + * In this state no new IO operations are permitted. + * This state is entered from the STOPPING state. + */ + SCI_BASE_PORT_STATE_STOPPED, + + /** + * This state indicates that the port is in the process of stopping. + * In this state no new IO operations are permitted, but existing IO + * operations are allowed to complete. + * This state is entered from the READY state. + */ + SCI_BASE_PORT_STATE_STOPPING, + + /** + * This state indicates the port is now ready. Thus, the user is + * able to perform IO operations on this port. + * This state is entered from the STARTING state. + */ + SCI_BASE_PORT_STATE_READY, + + /** + * This state indicates the port is in the process of performing a hard + * reset. Thus, the user is unable to perform IO operations on this + * port. + * This state is entered from the READY state. + */ + SCI_BASE_PORT_STATE_RESETTING, + + /** + * This state indicates the port has failed a reset request. This state + * is entered when a port reset request times out. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PORT_STATE_FAILED, + + SCI_BASE_PORT_MAX_STATES + +}; /** * struct scic_sds_port - @@ -119,9 +159,15 @@ struct scic_sds_request; */ struct scic_sds_port { /** - * This field is the oommon base port object. + * The field specifies that the parent object for the base controller + * is the base object itself. */ - struct sci_base_port parent; + struct sci_base_object parent; + + /** + * This field contains the information for the base port state machine. + */ + struct sci_base_state_machine state_machine; /** * This field is the port index that is reported to the SCI USER. @@ -214,6 +260,15 @@ struct scic_sds_port { }; +struct sci_base_phy; + +typedef enum sci_status (*scic_sds_port_handler_t)(struct scic_sds_port *); + +typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *, + struct sci_base_phy *); + +typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *, + u32 timeout); typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32); @@ -221,13 +276,46 @@ typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *); -typedef enum sci_status (*scic_sds_port_io_request_handler_t)( - struct scic_sds_port *, - struct scic_sds_remote_device *, - struct scic_sds_request *); +typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_port *, + struct scic_sds_remote_device *, + struct scic_sds_request *); struct scic_sds_port_state_handler { - struct sci_base_port_state_handler parent; + /** + * The start_handler specifies the method invoked when a user + * attempts to start a port. + */ + scic_sds_port_handler_t start_handler; + + /** + * The stop_handler specifies the method invoked when a user + * attempts to stop a port. + */ + scic_sds_port_handler_t stop_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a port. + */ + scic_sds_port_handler_t destruct_handler; + + /** + * The reset_handler specifies the method invoked when a user + * attempts to hard reset a port. + */ + scic_sds_port_reset_handler_t reset_handler; + + /** + * The add_phy_handler specifies the method invoked when a user + * attempts to add another phy into the port. + */ + scic_sds_port_phy_handler_t add_phy_handler; + + /** + * The remove_phy_handler specifies the method invoked when a user + * attempts to remove a phy from the port. + */ + scic_sds_port_phy_handler_t remove_phy_handler; scic_sds_port_frame_handler_t frame_handler; scic_sds_port_event_handler_t event_handler; @@ -292,15 +380,6 @@ static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *s #define scic_sds_port_active_phy(port, phy) \ (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) -/* --------------------------------------------------------------------------- */ - - - - -/* --------------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------------- */ - void scic_sds_port_construct( struct scic_sds_port *this_port, u8 port_index, @@ -312,8 +391,6 @@ enum sci_status scic_sds_port_initialize( void __iomem *port_configuration_regsiter, void __iomem *viit_registers); -/* --------------------------------------------------------------------------- */ - enum sci_status scic_sds_port_add_phy( struct scic_sds_port *this_port, struct scic_sds_phy *the_phy); @@ -332,9 +409,6 @@ void scic_sds_port_deactivate_phy( struct scic_sds_phy *phy, bool do_notify_user); - - - bool scic_sds_port_link_detected( struct scic_sds_port *this_port, struct scic_sds_phy *phy); @@ -347,11 +421,6 @@ void scic_sds_port_link_down( struct scic_sds_port *this_port, struct scic_sds_phy *phy); -/* --------------------------------------------------------------------------- */ - - -/* --------------------------------------------------------------------------- */ - enum sci_status scic_sds_port_start_io( struct scic_sds_port *this_port, struct scic_sds_remote_device *the_device, @@ -362,23 +431,6 @@ enum sci_status scic_sds_port_complete_io( struct scic_sds_remote_device *the_device, struct scic_sds_request *the_io_request); -/* --------------------------------------------------------------------------- */ - - -/* --------------------------------------------------------------------------- */ - - - - - - - - - - - - - enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( struct scic_sds_port *this_port); @@ -390,8 +442,6 @@ bool scic_sds_port_is_valid_phy_assignment( struct scic_sds_port *this_port, u32 phy_index); - - void scic_sds_port_get_sas_address( struct scic_sds_port *this_port, struct sci_sas_address *sas_address); @@ -404,8 +454,4 @@ void scic_sds_port_get_attached_protocols( struct scic_sds_port *this_port, struct sci_sas_identify_address_frame_protocols *protocols); - - - - #endif /* _SCIC_SDS_PORT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index 22703b372c64..a7e3833b1d56 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -700,7 +700,7 @@ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, scic_sds_apc_agent_configure_ports(scic, port_agent, sci_phy, true); } else { /* the phy is already the part of the port */ - u32 port_state = sci_port->parent.state_machine.current_state_id; + u32 port_state = sci_port->state_machine.current_state_id; /* if the PORT'S state is resetting then the link up is from * port hard reset in this case, we need to tell the port -- cgit v1.2.3 From d857d9a0adf49e332413d918322405192aafc766 Mon Sep 17 00:00:00 2001 From: Maciej Trela Date: Tue, 12 Apr 2011 17:28:39 -0700 Subject: isci: remove base_phy abstraction Merge struct sci_base_phy into scic_sds_phy. Until now sci_base_phy was referenced using scic_sds_phy->parent field. 'sci_base_phy' state machine handlers were also merged into scic_sds_phy state handlers. Reported-by: Christoph Hellwig Signed-off-by: Maciej Trela Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_phy.h | 200 ----------------- drivers/scsi/isci/core/scic_sds_controller.c | 2 +- drivers/scsi/isci/core/scic_sds_phy.c | 324 +++++++++++++-------------- drivers/scsi/isci/core/scic_sds_phy.h | 91 +++++++- drivers/scsi/isci/core/scic_sds_port.c | 50 ++--- drivers/scsi/isci/core/scic_sds_port.h | 5 +- 6 files changed, 260 insertions(+), 412 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_base_phy.h diff --git a/drivers/scsi/isci/core/sci_base_phy.h b/drivers/scsi/isci/core/sci_base_phy.h deleted file mode 100644 index 7e2c7e331437..000000000000 --- a/drivers/scsi/isci/core/sci_base_phy.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_PHY_H_ -#define _SCI_BASE_PHY_H_ - -/** - * This file contains all of the structures, constants, and methods common to - * all phy object definitions. - * - * - */ - -#include "sci_base_state_machine.h" - -/** - * enum sci_base_phy_states - This enumeration depicts the standard states - * common to all phy state machine implementations. - * - * - */ -enum sci_base_phy_states { - /** - * Simply the initial state for the base domain state machine. - */ - SCI_BASE_PHY_STATE_INITIAL, - - /** - * This state indicates that the phy has successfully been stopped. - * In this state no new IO operations are permitted on this phy. - * This state is entered from the INITIAL state. - * This state is entered from the STARTING state. - * This state is entered from the READY state. - * This state is entered from the RESETTING state. - */ - SCI_BASE_PHY_STATE_STOPPED, - - /** - * This state indicates that the phy is in the process of becomming - * ready. In this state no new IO operations are permitted on this phy. - * This state is entered from the STOPPED state. - * This state is entered from the READY state. - * This state is entered from the RESETTING state. - */ - SCI_BASE_PHY_STATE_STARTING, - - /** - * This state indicates the the phy is now ready. Thus, the user - * is able to perform IO operations utilizing this phy as long as it - * is currently part of a valid port. - * This state is entered from the STARTING state. - */ - SCI_BASE_PHY_STATE_READY, - - /** - * This state indicates that the phy is in the process of being reset. - * In this state no new IO operations are permitted on this phy. - * This state is entered from the READY state. - */ - SCI_BASE_PHY_STATE_RESETTING, - - /** - * Simply the final state for the base phy state machine. - */ - SCI_BASE_PHY_STATE_FINAL, -}; - -/** - * struct sci_base_phy - This structure defines all of the fields common to PHY - * objects. - * - * - */ -struct sci_base_phy { - /** - * This field depicts the parent object (struct sci_base_object) for the phy. - */ - struct sci_base_object parent; - - /** - * This field contains the information for the base phy state machine. - */ - struct sci_base_state_machine state_machine; -}; - -typedef enum sci_status (*sci_base_phy_handler_t)(struct sci_base_phy *); - -/** - * struct sci_base_phy_state_handler - This structure contains all of the state - * handler methods common to base phy state machines. Handler methods - * provide the ability to change the behavior for user requests or - * transitions depending on the state the machine is in. - * - * - */ -struct sci_base_phy_state_handler { - /** - * The start_handler specifies the method invoked when there is an - * attempt to start a phy. - */ - sci_base_phy_handler_t start_handler; - - /** - * The stop_handler specifies the method invoked when there is an - * attempt to stop a phy. - */ - sci_base_phy_handler_t stop_handler; - - /** - * The reset_handler specifies the method invoked when there is an - * attempt to reset a phy. - */ - sci_base_phy_handler_t reset_handler; - - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a phy. - */ - sci_base_phy_handler_t destruct_handler; - -}; - -/** - * sci_base_phy_construct() - Construct the base phy - * @this_phy: This parameter specifies the base phy to be constructed. - * @state_table: This parameter specifies the table of state definitions to be - * utilized for the phy state machine. - * - */ -static inline void sci_base_phy_construct( - struct sci_base_phy *base_phy, - const struct sci_base_state *state_table) -{ - base_phy->parent.private = NULL; - sci_base_state_machine_construct( - &base_phy->state_machine, - &base_phy->parent, - state_table, - SCI_BASE_PHY_STATE_INITIAL - ); - - sci_base_state_machine_start( - &base_phy->state_machine - ); -} - - -#endif /* _SCI_BASE_PHY_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 577d1df2cfd2..78b2e6f76d1a 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -679,7 +679,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro for (index = 0; index < SCI_MAX_PHYS; index++) { sci_phy = &scic->phy_table[index]; - state = sci_phy->parent.state_machine.current_state_id; + state = sci_phy->state_machine.current_state_id; if (!scic_sds_phy_get_port(sci_phy)) continue; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index c26e5df18142..d5bbc220ab84 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -253,7 +253,7 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, writel(0x1F4, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout); /* We can exit the initial state to the stopped state */ - sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STOPPED); return SCI_SUCCESS; @@ -276,7 +276,7 @@ static void scic_sds_phy_sata_timeout(void *phy) sci_base_state_machine_stop(&sci_phy->starting_substate_machine); - sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STARTING); } @@ -353,7 +353,7 @@ enum sci_status scic_sds_phy_initialize( /* * There is nothing that needs to be done in this state just * transition to the stopped state. */ - sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STOPPED); return SCI_SUCCESS; @@ -515,7 +515,7 @@ void scic_sds_phy_get_attached_phy_protocols( */ enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) { - return sci_phy->state_handlers->parent.start_handler(&sci_phy->parent); + return sci_phy->state_handlers->start_handler(sci_phy); } /** @@ -527,7 +527,7 @@ enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) */ enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) { - return sci_phy->state_handlers->parent.stop_handler(&sci_phy->parent); + return sci_phy->state_handlers->stop_handler(sci_phy); } /** @@ -540,9 +540,7 @@ enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) enum sci_status scic_sds_phy_reset( struct scic_sds_phy *this_phy) { - return this_phy->state_handlers->parent.reset_handler( - &this_phy->parent - ); + return this_phy->state_handlers->reset_handler(this_phy); } /** @@ -714,7 +712,7 @@ static void scic_sds_phy_restart_starting_state( sci_base_state_machine_stop(&sci_phy->starting_substate_machine); /* Re-enter the base state machine starting state */ - sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STARTING); } @@ -722,12 +720,9 @@ static void scic_sds_phy_restart_starting_state( * SCIC SDS PHY general handlers ************************************************************************** */ static enum sci_status scic_sds_phy_starting_substate_general_stop_handler( - struct sci_base_phy *phy) + struct scic_sds_phy *phy) { - struct scic_sds_phy *this_phy; - this_phy = (struct scic_sds_phy *)phy; - - sci_base_state_machine_stop(&this_phy->starting_substate_machine); + sci_base_state_machine_stop(&phy->starting_substate_machine); sci_base_state_machine_change_state(&phy->state_machine, SCI_BASE_PHY_STATE_STOPPED); @@ -1331,11 +1326,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle * * SCIC SDS PHY POWER_HANDLERS * ***************************************************************************** */ -/** - * scic_sds_phy_starting_substate_await_sas_power_consume_power_handler - - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * +/* * This method is called by the struct scic_sds_controller when the phy object is * granted power. - The notify enable spinups are turned on for this phy object * - The phy state machine is transitioned to the @@ -1357,11 +1348,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_po return SCI_SUCCESS; } -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy - * object. - * +/* * This method is called by the struct scic_sds_controller when the phy object is * granted power. - The phy state machine is transitioned to the * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. enum sci_status SCI_SUCCESS @@ -1393,148 +1380,153 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_p return SCI_SUCCESS; } -static enum sci_status default_phy_handler(struct sci_base_phy *base_phy, const char *func) +static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, + const char *func) { - struct scic_sds_phy *sci_phy; - - sci_phy = container_of(base_phy, typeof(*sci_phy), parent); dev_dbg(sciphy_to_dev(sci_phy), "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&base_phy->state_machine)); + sci_base_state_machine_get_state(&sci_phy->state_machine)); return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_phy_default_start_handler(struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_phy_default_start_handler(struct scic_sds_phy *sci_phy) { - return default_phy_handler(base_phy, __func__); + return default_phy_handler(sci_phy, __func__); } -static enum sci_status scic_sds_phy_default_stop_handler(struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_phy_default_stop_handler(struct scic_sds_phy *sci_phy) { - return default_phy_handler(base_phy, __func__); + return default_phy_handler(sci_phy, __func__); } -static enum sci_status scic_sds_phy_default_reset_handler(struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_phy_default_reset_handler(struct scic_sds_phy *sci_phy) { - return default_phy_handler(base_phy, __func__); + return default_phy_handler(sci_phy, __func__); } -static enum sci_status scic_sds_phy_default_destroy_handler(struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_phy_default_destroy_handler(struct scic_sds_phy *sci_phy) { - return default_phy_handler(base_phy, __func__); + return default_phy_handler(sci_phy, __func__); } -static enum sci_status scic_sds_phy_default_frame_handler(struct scic_sds_phy *sci_phy, - u32 frame_index) +static enum sci_status +scic_sds_phy_default_frame_handler(struct scic_sds_phy *sci_phy, + u32 frame_index) { struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - default_phy_handler(&sci_phy->parent, __func__); + default_phy_handler(sci_phy, __func__); scic_sds_controller_release_frame(scic, frame_index); return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_phy_default_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) +static enum sci_status +scic_sds_phy_default_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) { - return default_phy_handler(&sci_phy->parent, __func__); + return default_phy_handler(sci_phy, __func__); } -static enum sci_status scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) +static enum sci_status +scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) { - return default_phy_handler(&sci_phy->parent, __func__); + return default_phy_handler(sci_phy, __func__); } static const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = { [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, - .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, + .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, - .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, + .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler @@ -1885,7 +1877,7 @@ static void scic_sds_phy_starting_final_substate_enter(struct sci_base_object *o { struct scic_sds_phy *sci_phy; - sci_phy = container_of(object, typeof(*sci_phy), parent.parent); + sci_phy = container_of(object, typeof(*sci_phy), parent); scic_sds_phy_set_starting_substate_handlers(sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); @@ -1893,7 +1885,7 @@ static void scic_sds_phy_starting_final_substate_enter(struct sci_base_object *o /* State machine has run to completion so exit out and change * the base state machine to the ready state */ - sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_READY); } @@ -1937,22 +1929,17 @@ static const struct sci_base_state scic_sds_phy_starting_substates[] = { } }; -/** - * - * @phy: This is the struct sci_base_phy object which is cast into a - * struct scic_sds_phy object. - * +/* * This method takes the struct scic_sds_phy from a stopped state and * attempts to start it. - The phy state machine is transitioned to the * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS */ -static enum sci_status scic_sds_phy_stopped_state_start_handler(struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_phy_stopped_state_start_handler(struct scic_sds_phy *sci_phy) { struct isci_host *ihost; - struct scic_sds_phy *sci_phy; struct scic_sds_controller *scic; - sci_phy = container_of(base_phy, typeof(*sci_phy), parent); scic = scic_sds_phy_get_controller(sci_phy), ihost = sci_object_get_association(scic); @@ -1961,28 +1948,31 @@ static enum sci_status scic_sds_phy_stopped_state_start_handler(struct sci_base_ scic_sds_phy_sata_timeout); if (sci_phy->sata_timeout_timer) - sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STARTING); return SCI_SUCCESS; } -static enum sci_status scic_sds_phy_stopped_state_destroy_handler(struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) { return SCI_SUCCESS; } -static enum sci_status scic_sds_phy_ready_state_stop_handler(struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_phy_ready_state_stop_handler(struct scic_sds_phy *sci_phy) { - sci_base_state_machine_change_state(&base_phy->state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STOPPED); return SCI_SUCCESS; } -static enum sci_status scic_sds_phy_ready_state_reset_handler(struct sci_base_phy *base_phy) +static enum sci_status +scic_sds_phy_ready_state_reset_handler(struct scic_sds_phy *sci_phy) { - sci_base_state_machine_change_state(&base_phy->state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_RESETTING); return SCI_SUCCESS; @@ -2007,7 +1997,7 @@ static enum sci_status scic_sds_phy_ready_state_event_handler(struct scic_sds_ph switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STARTING); result = SCI_SUCCESS; break; @@ -2041,7 +2031,7 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sd switch (scu_get_event_code(event_code)) { case SCU_EVENT_HARD_RESET_TRANSMITTED: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->parent.state_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STARTING); result = SCI_SUCCESS; break; @@ -2063,55 +2053,55 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sd static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STOPPED] = { - .parent.start_handler = scic_sds_phy_stopped_state_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_stopped_state_destroy_handler, + .start_handler = scic_sds_phy_stopped_state_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STARTING] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_READY] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_ready_state_stop_handler, - .parent.reset_handler = scic_sds_phy_ready_state_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_ready_state_stop_handler, + .reset_handler = scic_sds_phy_ready_state_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_ready_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_RESETTING] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_resetting_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_FINAL] = { - .parent.start_handler = scic_sds_phy_default_start_handler, - .parent.stop_handler = scic_sds_phy_default_stop_handler, - .parent.reset_handler = scic_sds_phy_default_reset_handler, - .parent.destruct_handler = scic_sds_phy_default_destroy_handler, + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler @@ -2260,7 +2250,7 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) scu_link_layer_stop_protocol_engine(sci_phy); - if (sci_phy->parent.state_machine.previous_state_id != + if (sci_phy->state_machine.previous_state_id != SCI_BASE_PHY_STATE_INITIAL) scic_sds_controller_link_down( scic_sds_phy_get_controller(sci_phy), @@ -2299,7 +2289,7 @@ static void scic_sds_phy_starting_state_enter( /* Change over to the starting substate machine to continue */ sci_base_state_machine_start(&this_phy->starting_substate_machine); - if (this_phy->parent.state_machine.previous_state_id + if (this_phy->state_machine.previous_state_id == SCI_BASE_PHY_STATE_READY) { scic_sds_controller_link_down( scic_sds_phy_get_controller(this_phy), @@ -2380,12 +2370,10 @@ static void scic_sds_phy_resetting_state_enter( scu_link_layer_tx_hard_reset(this_phy); } else { /* - * The SCU does not need to have a descrete reset state so just go back to + * The SCU does not need to have a discrete reset state so just go back to * the starting state. */ - sci_base_state_machine_change_state( - &this_phy->parent.state_machine, - SCI_BASE_PHY_STATE_STARTING - ); + sci_base_state_machine_change_state(&this_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); } } @@ -2436,10 +2424,14 @@ static const struct sci_base_state scic_sds_phy_state_table[] = { void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, struct scic_sds_port *owning_port, u8 phy_index) { - /* - * Call the base constructor first - */ - sci_base_phy_construct(&sci_phy->parent, scic_sds_phy_state_table); + + sci_phy->parent.private = NULL; + sci_base_state_machine_construct(&sci_phy->state_machine, + &sci_phy->parent, + scic_sds_phy_state_table, + SCI_BASE_PHY_STATE_INITIAL); + + sci_base_state_machine_start(&sci_phy->state_machine); /* Copy the rest of the input data to our locals */ sci_phy->owning_port = owning_port; @@ -2455,7 +2447,7 @@ void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, /* Initialize the the substate machines */ sci_base_state_machine_construct(&sci_phy->starting_substate_machine, - &sci_phy->parent.parent, + &sci_phy->parent, scic_sds_phy_starting_substates, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); } diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 7f7a04542031..97c0476570ba 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -56,17 +56,10 @@ #ifndef _SCIC_SDS_PHY_H_ #define _SCIC_SDS_PHY_H_ -/** - * This file contains the structures, constants and prototypes for the - * struct scic_sds_phy object. - * - * - */ - #include "intel_sata.h" #include "intel_sas.h" -#include "sci_base_phy.h" #include "scu_registers.h" +#include "sci_base_state_machine.h" struct scic_sds_port; /** @@ -91,6 +84,53 @@ struct scic_sds_port; */ #define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250 +enum scic_sds_phy_states { + /** + * Simply the initial state for the base domain state machine. + */ + SCI_BASE_PHY_STATE_INITIAL, + + /** + * This state indicates that the phy has successfully been stopped. + * In this state no new IO operations are permitted on this phy. + * This state is entered from the INITIAL state. + * This state is entered from the STARTING state. + * This state is entered from the READY state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PHY_STATE_STOPPED, + + /** + * This state indicates that the phy is in the process of becomming + * ready. In this state no new IO operations are permitted on this phy. + * This state is entered from the STOPPED state. + * This state is entered from the READY state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PHY_STATE_STARTING, + + /** + * This state indicates the the phy is now ready. Thus, the user + * is able to perform IO operations utilizing this phy as long as it + * is currently part of a valid port. + * This state is entered from the STARTING state. + */ + SCI_BASE_PHY_STATE_READY, + + /** + * This state indicates that the phy is in the process of being reset. + * In this state no new IO operations are permitted on this phy. + * This state is entered from the READY state. + */ + SCI_BASE_PHY_STATE_RESETTING, + + /** + * Simply the final state for the base phy state machine. + */ + SCI_BASE_PHY_STATE_FINAL, +}; + + /** * enum scic_sds_phy_starting_substates - * @@ -184,7 +224,15 @@ enum scic_sds_phy_protocol { * */ struct scic_sds_phy { - struct sci_base_phy parent; + /** + * This field depicts the parent object (struct sci_base_object) for the phy. + */ + struct sci_base_object parent; + + /** + * This field contains the information for the base phy state machine. + */ + struct sci_base_state_machine state_machine; /** * This field specifies the port object that owns/contains this phy. @@ -260,7 +308,7 @@ struct scic_sds_phy { }; - +typedef enum sci_status (*scic_sds_phy_handler_t)(struct scic_sds_phy *); typedef enum sci_status (*scic_sds_phy_event_handler_t)(struct scic_sds_phy *, u32); typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u32); typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); @@ -272,9 +320,28 @@ typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); */ struct scic_sds_phy_state_handler { /** - * This is the struct sci_base_phy object state handlers. + * The start_handler specifies the method invoked when there is an + * attempt to start a phy. + */ + scic_sds_phy_handler_t start_handler; + + /** + * The stop_handler specifies the method invoked when there is an + * attempt to stop a phy. + */ + scic_sds_phy_handler_t stop_handler; + + /** + * The reset_handler specifies the method invoked when there is an + * attempt to reset a phy. + */ + scic_sds_phy_handler_t reset_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a phy. */ - struct sci_base_phy_state_handler parent; + scic_sds_phy_handler_t destruct_handler; /** * The state handler for unsolicited frames received from the SCU hardware. diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index ff9ac73927a4..ebbde7b3489f 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -316,7 +316,7 @@ enum sci_status scic_sds_port_add_phy( struct scic_sds_phy *the_phy) { return this_port->state_handlers->add_phy_handler( - this_port, &the_phy->parent); + this_port, the_phy); } @@ -334,7 +334,7 @@ enum sci_status scic_sds_port_remove_phy( struct scic_sds_phy *the_phy) { return this_port->state_handlers->remove_phy_handler( - this_port, &the_phy->parent); + this_port, the_phy); } /** @@ -1084,15 +1084,14 @@ static enum sci_status scic_sds_port_ready_substate_complete_io_handler( static enum sci_status scic_sds_port_ready_substate_add_phy_handler( struct scic_sds_port *port, - struct sci_base_phy *phy) + struct scic_sds_phy *phy) { - struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; enum sci_status status; - status = scic_sds_port_set_phy(port, this_phy); + status = scic_sds_port_set_phy(port, phy); if (status == SCI_SUCCESS) { - scic_sds_port_general_link_up_handler(port, this_phy, true); + scic_sds_port_general_link_up_handler(port, phy, true); port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; @@ -1108,15 +1107,14 @@ static enum sci_status scic_sds_port_ready_substate_add_phy_handler( static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( struct scic_sds_port *port, - struct sci_base_phy *phy) + struct scic_sds_phy *phy) { - struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; enum sci_status status; - status = scic_sds_port_clear_phy(port, this_phy); + status = scic_sds_port_clear_phy(port, phy); if (status == SCI_SUCCESS) { - scic_sds_port_deactivate_phy(port, this_phy, true); + scic_sds_port_deactivate_phy(port, phy, true); port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; @@ -1293,15 +1291,14 @@ static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler */ static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( struct scic_sds_port *port, - struct sci_base_phy *phy) + struct scic_sds_phy *phy) { - struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; enum sci_status status; - status = scic_sds_port_set_phy(port, this_phy); + status = scic_sds_port_set_phy(port, phy); if (status == SCI_SUCCESS) { - scic_sds_port_general_link_up_handler(port, this_phy, true); + scic_sds_port_general_link_up_handler(port, phy, true); /* * Re-enter the configuring state since this may be the last phy in @@ -1321,15 +1318,14 @@ static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( */ static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler( struct scic_sds_port *port, - struct sci_base_phy *phy) + struct scic_sds_phy *phy) { - struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; enum sci_status status; - status = scic_sds_port_clear_phy(port, this_phy); + status = scic_sds_port_clear_phy(port, phy); if (status == SCI_SUCCESS) { - scic_sds_port_deactivate_phy(port, this_phy, true); + scic_sds_port_deactivate_phy(port, phy, true); /* * Re-enter the configuring state since this may be the last phy in @@ -1406,14 +1402,14 @@ scic_sds_port_default_reset_handler(struct scic_sds_port *sci_port, static enum sci_status scic_sds_port_default_add_phy_handler(struct scic_sds_port *sci_port, - struct sci_base_phy *base_phy) + struct scic_sds_phy *base_phy) { return default_port_handler(sci_port, __func__); } static enum sci_status scic_sds_port_default_remove_phy_handler(struct scic_sds_port *sci_port, - struct sci_base_phy *base_phy) + struct scic_sds_phy *base_phy) { return default_port_handler(sci_port, __func__); } @@ -1939,9 +1935,8 @@ static enum sci_status scic_sds_port_stopped_state_destruct_handler( */ static enum sci_status scic_sds_port_stopped_state_add_phy_handler( struct scic_sds_port *port, - struct sci_base_phy *phy) + struct scic_sds_phy *phy) { - struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; struct sci_sas_address port_sas_address; /* Read the port assigned SAS Address if there is one */ @@ -1953,7 +1948,7 @@ static enum sci_status scic_sds_port_stopped_state_add_phy_handler( /* * Make sure that the PHY SAS Address matches the SAS Address * for this port. */ - scic_sds_phy_get_sas_address(this_phy, &phy_sas_address); + scic_sds_phy_get_sas_address(phy, &phy_sas_address); if ( (port_sas_address.high != phy_sas_address.high) @@ -1963,10 +1958,9 @@ static enum sci_status scic_sds_port_stopped_state_add_phy_handler( } } - return scic_sds_port_set_phy(port, this_phy); + return scic_sds_port_set_phy(port, phy); } - /* * This method takes the struct scic_sds_port that is in a stopped state and handles * the remove phy request. In MPC mode the only time a phy can be removed from @@ -1976,11 +1970,9 @@ static enum sci_status scic_sds_port_stopped_state_add_phy_handler( */ static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( struct scic_sds_port *port, - struct sci_base_phy *phy) + struct scic_sds_phy *phy) { - struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; - - return scic_sds_port_clear_phy(port, this_phy); + return scic_sds_port_clear_phy(port, phy); } /* diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 528c84d569a0..d79c5745e49a 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -59,7 +59,6 @@ #include #include "sci_controller_constants.h" #include "intel_sas.h" -#include "sci_base_phy.h" #include "scu_registers.h" #define SCIC_SDS_DUMMY_PORT 0xFF @@ -260,12 +259,10 @@ struct scic_sds_port { }; -struct sci_base_phy; - typedef enum sci_status (*scic_sds_port_handler_t)(struct scic_sds_port *); typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *, - struct sci_base_phy *); + struct scic_sds_phy *); typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *, u32 timeout); -- cgit v1.2.3 From 26bace349ecd08b1d744f7067d24fd1bedb91020 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 14 Apr 2011 18:27:49 -0700 Subject: isci: replace sci_sas_link_rate with sas_linkrate Drop duplicated enum definition. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 14 -------------- drivers/scsi/isci/core/scic_phy.h | 3 ++- drivers/scsi/isci/core/scic_remote_device.h | 2 +- drivers/scsi/isci/core/scic_sds_phy.c | 16 ++++++++-------- drivers/scsi/isci/core/scic_sds_phy.h | 3 ++- drivers/scsi/isci/core/scic_sds_port.c | 10 +++++----- drivers/scsi/isci/core/scic_sds_port.h | 2 +- drivers/scsi/isci/core/scic_sds_remote_device.c | 2 +- drivers/scsi/isci/core/scic_sds_remote_device.h | 3 ++- 9 files changed, 22 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index eb9686ea35f1..d9c9f33a7af5 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -179,20 +179,6 @@ struct sas_capabilities { }; -/** - * enum _SCI_SAS_LINK_RATE - This enumeration depicts the SAS specification - * defined link speeds. - * - * - */ -enum sci_sas_link_rate { - SCI_SAS_NO_LINK_RATE = 0, - SCI_SATA_SPINUP_HOLD = 0x3, - SCI_SAS_150_GB = 0x8, - SCI_SAS_300_GB = 0x9, - SCI_SAS_600_GB = 0xA -}; - /** * enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS * specification defined task attribute values for a command information diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index bf0d3be58eda..784c5b5c105b 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -68,6 +68,7 @@ #include "intel_sata.h" #include "intel_sas.h" +#include struct scic_sds_phy; struct scic_sds_port; @@ -93,7 +94,7 @@ struct scic_phy_properties { * This field specifies the link rate at which the phy is * currently operating. */ - enum sci_sas_link_rate negotiated_link_rate; + enum sas_linkrate negotiated_link_rate; /** * This field indicates the protocols supported by the phy. diff --git a/drivers/scsi/isci/core/scic_remote_device.h b/drivers/scsi/isci/core/scic_remote_device.h index 1401844349e6..62fa7fd572c1 100644 --- a/drivers/scsi/isci/core/scic_remote_device.h +++ b/drivers/scsi/isci/core/scic_remote_device.h @@ -254,7 +254,7 @@ enum sci_status scic_remote_device_reset_complete( * * Return the link rate at which we transfer for the supplied remote device. */ -enum sci_sas_link_rate scic_remote_device_get_connection_rate( +enum sas_linkrate scic_remote_device_get_connection_rate( struct scic_sds_remote_device *remote_device); /** diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index d5bbc220ab84..40176f0729c1 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -696,7 +696,7 @@ static void scic_sds_phy_start_sata_link_training( */ static void scic_sds_phy_complete_link_training( struct scic_sds_phy *sci_phy, - enum sci_sas_link_rate max_link_rate, + enum sas_linkrate max_link_rate, u32 next_state) { sci_phy->max_negotiated_speed = max_link_rate; @@ -808,21 +808,21 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_ case SCU_EVENT_SAS_15: case SCU_EVENT_SAS_15_SSC: scic_sds_phy_complete_link_training( - this_phy, SCI_SAS_150_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + this_phy, SAS_LINK_RATE_1_5_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF ); break; case SCU_EVENT_SAS_30: case SCU_EVENT_SAS_30_SSC: scic_sds_phy_complete_link_training( - this_phy, SCI_SAS_300_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + this_phy, SAS_LINK_RATE_3_0_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF ); break; case SCU_EVENT_SAS_60: case SCU_EVENT_SAS_60_SSC: scic_sds_phy_complete_link_training( - this_phy, SCI_SAS_600_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + this_phy, SAS_LINK_RATE_6_0_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF ); break; @@ -1082,7 +1082,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_han case SCU_EVENT_SATA_15_SSC: scic_sds_phy_complete_link_training( this_phy, - SCI_SAS_150_GB, + SAS_LINK_RATE_1_5_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF ); break; @@ -1091,7 +1091,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_han case SCU_EVENT_SATA_30_SSC: scic_sds_phy_complete_link_training( this_phy, - SCI_SAS_300_GB, + SAS_LINK_RATE_3_0_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF ); break; @@ -1100,7 +1100,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_han case SCU_EVENT_SATA_60_SSC: scic_sds_phy_complete_link_training( this_phy, - SCI_SAS_600_GB, + SAS_LINK_RATE_6_0_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF ); break; @@ -2439,7 +2439,7 @@ void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, sci_phy->bcn_received_while_port_unassigned = false; sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; sci_phy->link_layer_registers = NULL; - sci_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; + sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; sci_phy->sata_timeout_timer = NULL; /* Clear out the identification buffer data */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 97c0476570ba..fb99d472ce60 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -60,6 +60,7 @@ #include "intel_sas.h" #include "scu_registers.h" #include "sci_base_state_machine.h" +#include struct scic_sds_port; /** @@ -243,7 +244,7 @@ struct scic_sds_phy { * This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s, * or 6.0 Gb/s operation. */ - enum sci_sas_link_rate max_negotiated_speed; + enum sas_linkrate max_negotiated_speed; /** * This member specifies the protocol being utilized on this phy. This diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index ebbde7b3489f..40c1297849f3 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -684,7 +684,7 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); - sci_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; + sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; /* Re-assign the phy back to the LP as if it were a narrow port */ writel(sci_phy->phy_index, @@ -977,12 +977,12 @@ static void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port) * This method returns the maximum negotiated speed of the slowest phy in the * port. */ -enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( +enum sas_linkrate scic_sds_port_get_max_allowed_speed( struct scic_sds_port *this_port) { - u16 index = 0; - enum sci_sas_link_rate max_allowed_speed = SCI_SAS_600_GB; - struct scic_sds_phy *phy = NULL; + u16 index; + enum sas_linkrate max_allowed_speed = SAS_LINK_RATE_6_0_GBPS; + struct scic_sds_phy *phy = NULL; /* * Loop through all of the phys in this port and find the phy with the diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index d79c5745e49a..a17c64a7cbf2 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -428,7 +428,7 @@ enum sci_status scic_sds_port_complete_io( struct scic_sds_remote_device *the_device, struct scic_sds_request *the_io_request); -enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( +enum sas_linkrate scic_sds_port_get_max_allowed_speed( struct scic_sds_port *this_port); void scic_sds_port_broadcast_change_received( diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index d756216872b5..0976faeb4064 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -256,7 +256,7 @@ enum sci_status scic_remote_device_reset_complete( } -enum sci_sas_link_rate scic_remote_device_get_connection_rate( +enum sas_linkrate scic_remote_device_get_connection_rate( struct scic_sds_remote_device *sci_dev) { return sci_dev->connection_rate; diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index 0e8bb0f98b1e..ebb0ac8ef3a6 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -59,6 +59,7 @@ #include "intel_sas.h" #include "scu_remote_node_context.h" #include "scic_sds_remote_node_context.h" +#include /** * enum scic_sds_remote_device_states - This enumeration depicts all the states @@ -260,7 +261,7 @@ struct scic_sds_remote_device { * This field is the programmed connection rate for this remote device. It is * used to program the TC with the maximum allowed connection rate. */ - enum sci_sas_link_rate connection_rate; + enum sas_linkrate connection_rate; /** * This field contains the allowed target protocols for this remote device. -- cgit v1.2.3 From 467e855a0331f619f41fbf7391bc29ec0ca923a0 Mon Sep 17 00:00:00 2001 From: Bartosz Barcinski Date: Tue, 12 Apr 2011 17:28:41 -0700 Subject: isci: sparse warnings cleanup Clean warnings and errors reported by sparse tool. request.c:430:50: warning: mixing different enum types remote_device.c:534:39: warning: symbol 'flags' shadows an earlier one task.c:495:44: warning: mixing different enum types scic_sds_controller.c:2155:24: warning: mixing different enum types scic_sds_controller.c:2272:36: warning: mixing different enum types scic_sds_controller.c:2911:38: warning: incorrect type in initializer (different address spaces) scic_sds_controller.c:2913:25: warning: incorrect type in argument 2 (different address spaces) scic_sds_request.c:875:34: warning: cast removes address space of expression scic_sds_request.c:876:123: warning: incorrect type in argument 2 (different address spaces) scic_sds_port.c:585:51: warning: incorrect type in assignment (different address spaces) scic_sds_port.c:712:9: warning: incorrect type in argument 2 (different address spaces) scic_sds_port.c:1770:25: warning: incorrect type in argument 2 (different address spaces) Signed-off-by: Bartosz Barcinski Signed-off-by: Maciej Patelczyk [fixed up some false positives and misconversions] Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_controller.h | 2 +- drivers/scsi/isci/core/scic_sds_controller.c | 8 ++++---- drivers/scsi/isci/core/scic_sds_port.h | 2 +- drivers/scsi/isci/core/scic_sds_request.c | 11 ++++++----- drivers/scsi/isci/remote_device.c | 6 ++---- drivers/scsi/isci/task.c | 4 ++-- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 23a2c785fecd..23c7b5c004f4 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -98,7 +98,7 @@ enum sci_status scic_controller_stop( enum sci_status scic_controller_reset( struct scic_sds_controller *controller); -enum sci_io_status scic_controller_start_io( +enum sci_status scic_controller_start_io( struct scic_sds_controller *controller, struct scic_sds_remote_device *remote_device, struct scic_sds_request *io_request, diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 78b2e6f76d1a..8194618b76c6 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1967,10 +1967,10 @@ enum sci_status scic_controller_reset( * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking * the scic_controller_start_io() method. scic_controller_allocate_tag() for * more information on allocating a tag. Indicate if the controller - * successfully started the IO request. SCI_IO_SUCCESS if the IO request was + * successfully started the IO request. SCI_SUCCESS if the IO request was * successfully started. Determine the failure situations and return values. */ -enum sci_io_status scic_controller_start_io( +enum sci_status scic_controller_start_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *rdev, struct scic_sds_request *req, @@ -2723,8 +2723,8 @@ enum sci_status scic_controller_initialize( * logical ports */ for (index = 0; index < max_supported_ports; index++) { - struct scu_port_task_scheduler_group_registers *ptsg = - &scic->scu_registers->peg0.ptsg; + struct scu_port_task_scheduler_group_registers __iomem + *ptsg = &scic->scu_registers->peg0.ptsg; writel(index, &ptsg->protocol_engine[index]); } diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index a17c64a7cbf2..c7741e81336e 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -250,7 +250,7 @@ struct scic_sds_port { * task scheduler group PE configuration registers. * It is used to assign PEs to a port. */ - u32 *port_pe_configuration_register; + u32 __iomem *port_pe_configuration_register; /** * This field is the VIIT register space for ths port object. diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 191b5d0f1a53..64aa9c60836f 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -850,19 +850,20 @@ void *scic_io_request_get_response_iu_address( u32 scic_io_request_get_number_of_bytes_transferred( struct scic_sds_request *scic_sds_request) { + struct scic_sds_controller *scic = scic_sds_request->owning_controller; u32 ret_val = 0; - if (readl(&scic_sds_request->owning_controller->smu_registers->address_modifier) == 0) { + if (readl(&scic->smu_registers->address_modifier) == 0) { + void __iomem *scu_reg_base = scic->scu_registers; /* * get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where * BAR1 is the scu_registers * 0x20002C = 0x200000 + 0x2c * = start of task context SRAM + offset of (type.ssp.data_offset) * TCi is the io_tag of struct scic_sds_request */ - ret_val = readl((u8 *)scic_sds_request->owning_controller->scu_registers + - (SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(struct scu_task_context, type.ssp.data_offset)) + - ((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(scic_sds_request->io_tag)) - ); + ret_val = readl(scu_reg_base + + (SCU_TASK_CONTEXT_SRAM + offsetof(struct scu_task_context, type.ssp.data_offset)) + + ((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(scic_sds_request->io_tag))); } return ret_val; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index ab638ec5881c..320850cf46f2 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -513,15 +513,13 @@ bool isci_device_is_reset_pending( __func__, isci_device, isci_request); if (isci_request->ttype == io_task) { - - unsigned long flags; struct sas_task *task = isci_request_access_task( isci_request); - spin_lock_irqsave(&task->task_state_lock, flags); + spin_lock(&task->task_state_lock); if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) reset_is_pending = true; - spin_unlock_irqrestore(&task->task_state_lock, flags); + spin_unlock(&task->task_state_lock); } } diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index aa6b43067e25..b88101e195d1 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -429,7 +429,7 @@ int isci_task_execute_tmf( unsigned long timeout_ms) { DECLARE_COMPLETION_ONSTACK(completion); - enum sci_status status = SCI_FAILURE; + enum sci_task_status status = SCI_TASK_FAILURE; struct scic_sds_remote_device *sci_device; struct isci_remote_device *isci_device = tmf->device; struct isci_request *request; @@ -488,7 +488,7 @@ int isci_task_execute_tmf( SCI_CONTROLLER_INVALID_IO_TAG ); - if (status != SCI_SUCCESS) { + if (status != SCI_TASK_SUCCESS) { dev_warn(&isci_host->pdev->dev, "%s: start_io failed - status = 0x%x, request = %p\n", __func__, -- cgit v1.2.3 From 6cb4d6b382be6345c2d0c4b1b90dfdf9af32da7e Mon Sep 17 00:00:00 2001 From: Bartosz Barcinski Date: Tue, 12 Apr 2011 17:28:43 -0700 Subject: isci: audit usage of BUG_ON macro in isci driver Removes unnecessary usage of BUG_ON macro, excluding core directory. In some cases macro is unnecesary, check is done in caller function. In other cases macro is replaced by if construction with appropriate warning. Signed-off-by: Maciej Patelczyk [changed some survivable bug conditions to WARN_ONCE] Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_request.c | 1 - drivers/scsi/isci/init.c | 4 ---- drivers/scsi/isci/port.c | 1 + drivers/scsi/isci/remote_device.c | 10 ++++++---- drivers/scsi/isci/request.c | 1 - drivers/scsi/isci/request.h | 5 ++--- drivers/scsi/isci/task.c | 11 ++++++----- 7 files changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 64aa9c60836f..a6ee155c6825 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -1635,7 +1635,6 @@ static void scic_sds_request_completed_state_enter( struct isci_host *ihost = sci_object_get_association(scic); struct isci_request *ireq = sci_object_get_association(sci_req); - SET_STATE_HANDLER(sci_req, scic_sds_request_state_handler_table, SCI_BASE_REQUEST_STATE_COMPLETED); diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 5e63ae6a75d1..5da9a6925cd7 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -362,8 +362,6 @@ static int isci_setup_interrupts(struct pci_dev *pdev) else isr = isci_msix_isr; - BUG_ON(!isci_host); - err = devm_request_irq(&pdev->dev, msix->vector, isr, 0, DRV_NAME"-msix", isci_host); if (!err) @@ -379,13 +377,11 @@ static int isci_setup_interrupts(struct pci_dev *pdev) pci_disable_msix(pdev); goto intx; } - return 0; intx: err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr, IRQF_SHARED, DRV_NAME"-intx", pdev); - return err; } diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index b675a94f4a73..cf78cf0a6749 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -178,6 +178,7 @@ void isci_port_link_up( unsigned long success = true; BUG_ON(isci_phy->isci_port != NULL); + isci_phy->isci_port = isci_port; dev_dbg(&isci_host->pdev->dev, diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 320850cf46f2..9301e25dff31 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -202,8 +202,6 @@ static enum sci_status isci_remote_device_construct( sci_object_set_association(to_sci_dev(isci_device), isci_device); - BUG_ON(port->isci_host == NULL); - /* start the device. */ status = scic_remote_device_start(to_sci_dev(isci_device), ISCI_REMOTE_DEVICE_START_TIMEOUT); @@ -257,8 +255,12 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) return NULL; } - BUG_ON(!list_empty(&idev->reqs_in_process)); - BUG_ON(!list_empty(&idev->node)); + if (WARN_ONCE(!list_empty(&idev->reqs_in_process), "found requests in process\n")) + return NULL; + + if (WARN_ONCE(!list_empty(&idev->node), "found non-idle remote device\n")) + return NULL; + isci_remote_device_change_state(idev, isci_freed); return idev; diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 37ffedc94ac0..a90c299b723a 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -472,7 +472,6 @@ int isci_request_execute( out: if (status != SCI_SUCCESS) { - /* release dma memory on failure. */ isci_request_free(isci_host, request); request = NULL; diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 0c08da6bcd8a..642b21166fc6 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -193,8 +193,6 @@ static inline enum isci_request_status isci_request_change_started_to_newstate( enum isci_request_status old_state; unsigned long flags; - BUG_ON(isci_request == NULL); - spin_lock_irqsave(&isci_request->state_lock, flags); old_state = isci_request->status; @@ -243,7 +241,8 @@ static inline void isci_request_free( struct isci_host *isci_host, struct isci_request *isci_request) { - BUG_ON(isci_request == NULL); + if (!isci_request) + return; /* release the dma memory if we fail. */ dma_pool_free(isci_host->dma_pool, isci_request, diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index b88101e195d1..c79968db871c 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -272,7 +272,7 @@ static enum sci_status isci_task_request_build( { struct scic_sds_remote_device *sci_device; enum sci_status status = SCI_FAILURE; - struct isci_request *request; + struct isci_request *request = NULL; struct isci_remote_device *isci_device; /* struct sci_sas_identify_address_frame_protocols dev_protocols; */ struct smp_discover_response_protocols dev_protocols; @@ -372,8 +372,6 @@ static void isci_tmf_timeout_cb(void *tmf_request_arg) struct isci_tmf *tmf = isci_request_access_tmf(request); enum sci_status status; - BUG_ON(request->ttype != tmf_task); - /* This task management request has timed-out. Terminate the request * so that the request eventually completes to the requestor in the * request completion callback path. @@ -1121,8 +1119,11 @@ static void isci_abort_task_process_cb( * request state was already set to "aborted" by the abort * task function. */ - BUG_ON((old_request->status != aborted) - && (old_request->status != completed)); + if ((old_request->status != aborted) + && (old_request->status != completed)) + dev_err(&old_request->isci_host->pdev->dev, + "%s: Bad request status (%d): tmf=%p, old_request=%p\n", + __func__, old_request->status, tmf, old_request); break; case isci_tmf_timed_out: -- cgit v1.2.3 From f22be5d8386d9da67bfe02693806fbaff7b078da Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 19 Apr 2011 15:29:25 -0700 Subject: isci: fix oem parameter header definition The element_length is 2 bytes. Reported-by: Yinghai Lu Acked-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/probe_roms.h | 2 +- firmware/isci/isci_firmware.bin.ihex | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index f07935844bbd..55983363764b 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -123,7 +123,7 @@ struct sci_bios_oem_param_block_hdr { uint8_t version; uint8_t preboot_source; uint8_t num_elements; - uint8_t element_length; + uint16_t element_length; uint8_t reserved[8]; } __attribute__ ((packed)); diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex index 31b5ecf1bddb..13a9655dfc93 100644 --- a/firmware/isci/isci_firmware.bin.ihex +++ b/firmware/isci/isci_firmware.bin.ihex @@ -1,16 +1,16 @@ -:10000000495343554F454D42E70017100002000089 -:10001000000000000000000101000000000000FFDF -:10002000FFCF5F01000000037C0E00037C0E000385 -:100030007C0E00037C0E00FFFFCF5F010000000379 -:100040007C0E00037C0E00037C0E00037C0E00FF80 -:10005000FFCF5F01000000037C0E00037C0E000355 -:100060007C0E00037C0E00FFFFCF5F010000000349 -:100070007C0E00037C0E00037C0E00037C0E00014E -:1000800001000000000000FFFFCF5F02000000033E -:100090007C0E00037C0E00037C0E00037C0E00FF30 -:1000A000FFCF5F02000000037C0E00037C0E000304 -:1000B0007C0E00037C0E00FFFFCF5F0200000003F8 -:1000C0007C0E00037C0E00037C0E00037C0E00FF00 -:1000D000FFCF5F02000000037C0E00037C0E0003D4 -:0700E0007C0E00037C0E0002 +:10000000495343554F454D42E80018100002000087 +:1000100000000000000000000101000000000000DE +:10002000FFFFCF5F01000000037C0E00037C0E0089 +:10003000037C0E00037C0E00FFFFCF5F0100000079 +:10004000037C0E00037C0E00037C0E00037C0E007C +:10005000FFFFCF5F01000000037C0E00037C0E0059 +:10006000037C0E00037C0E00FFFFCF5F0100000049 +:10007000037C0E00037C0E00037C0E00037C0E004C +:100080000101000000000000FFFFCF5F0200000040 +:10009000037C0E00037C0E00037C0E00037C0E002C +:1000A000FFFFCF5F02000000037C0E00037C0E0008 +:1000B000037C0E00037C0E00FFFFCF5F02000000F8 +:1000C000037C0E00037C0E00037C0E00037C0E00FC +:1000D000FFFFCF5F02000000037C0E00037C0E00D8 +:0800E000037C0E00037C0E00FE :00000001FF -- cgit v1.2.3 From 2d70de5a0f03072289015917b059c155936c894d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 20 Apr 2011 12:57:08 -0700 Subject: isci: validate oem parameters early, and fallback If the platform specifies invalid parameters warn the user and fallback to internal defaults rather than fail the driver load altogether. Reported-by: Yinghai Lu Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_config_parameters.h | 2 + drivers/scsi/isci/core/scic_sds_controller.c | 75 ++++++++++++------------- drivers/scsi/isci/init.c | 10 ++++ 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index cb6abcc7e7cd..716abfcd0c23 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -279,6 +279,8 @@ enum sci_status scic_oem_parameters_set( struct scic_sds_controller *controller, union scic_oem_parameters *oem_parameters); +int scic_oem_parameters_validate(struct scic_sds_oem_params *oem); + /** * scic_oem_parameters_get() - This method allows the user to retreive the OEM * parameters utilized by the controller. diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 8194618b76c6..9bb78a2e6ff7 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -2455,52 +2455,51 @@ enum sci_status scic_user_parameters_set( return SCI_FAILURE_INVALID_STATE; } -enum sci_status scic_oem_parameters_set( - struct scic_sds_controller *scic, - union scic_oem_parameters *scic_parms) +int scic_oem_parameters_validate(struct scic_sds_oem_params *oem) { - u32 state = scic->state_machine.current_state_id; + int i; - if (state == SCI_BASE_CONTROLLER_STATE_RESET || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { - u16 index; - u8 combined_phy_mask = 0; + for (i = 0; i < SCI_MAX_PORTS; i++) + if (oem->ports[i].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) + return -EINVAL; + + for (i = 0; i < SCI_MAX_PHYS; i++) + if (oem->phys[i].sas_address.high == 0 && + oem->phys[i].sas_address.low == 0) + return -EINVAL; + + if (oem->controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) { + for (i = 0; i < SCI_MAX_PHYS; i++) + if (oem->ports[i].phy_mask != 0) + return -EINVAL; + } else if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { + u8 phy_mask = 0; + + for (i = 0; i < SCI_MAX_PHYS; i++) + phy_mask |= oem->ports[i].phy_mask; + + if (phy_mask == 0) + return -EINVAL; + } else + return -EINVAL; - /* - * Validate the oem parameters. If they are not legal, then - * return a failure. */ - for (index = 0; index < SCI_MAX_PORTS; index++) { - if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } + if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT) + return -EINVAL; - for (index = 0; index < SCI_MAX_PHYS; index++) { - if ((scic_parms->sds1.phys[index].sas_address.high == 0) && - (scic_parms->sds1.phys[index].sas_address.low == 0)) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } + return 0; +} - if (scic_parms->sds1.controller.mode_type == - SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) { - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (scic_parms->sds1.ports[index].phy_mask != 0) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } - } else if (scic_parms->sds1.controller.mode_type == - SCIC_PORT_MANUAL_CONFIGURATION_MODE) { - for (index = 0; index < SCI_MAX_PHYS; index++) - combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask; +enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic, + union scic_oem_parameters *scic_parms) +{ + u32 state = scic->state_machine.current_state_id; - if (combined_phy_mask == 0) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } else - return SCI_FAILURE_INVALID_PARAMETER_VALUE; + if (state == SCI_BASE_CONTROLLER_STATE_RESET || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { - if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > - MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT) + if (scic_oem_parameters_validate(&scic_parms->sds1)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - scic->oem_parameters.sds1 = scic_parms->sds1; return SCI_SUCCESS; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 5da9a6925cd7..015ce94453bb 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -489,6 +489,16 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic else orom = isci_request_oprom(pdev); + for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) { + if (scic_oem_parameters_validate(&orom->ctrl[i])) { + dev_warn(&pdev->dev, + "[%d]: invalid oem parameters detected, falling back to firmware\n", i); + devm_kfree(&pdev->dev, orom); + orom = NULL; + break; + } + } + if (!orom) { source = "(firmware)"; orom = isci_request_firmware(pdev, fw); -- cgit v1.2.3 From e2023b8735956bb78f167d0fdc575364e69b02c4 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Thu, 21 Apr 2011 05:34:49 +0000 Subject: isci: replace this_* and the_* variables with more meaningful names Removed any instances of the_* and this_* to variable names that are more meaningful and tell us what they actually are. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_pool.h | 60 ++-- drivers/scsi/isci/core/scic_sds_controller.c | 395 ++++++++++---------- drivers/scsi/isci/core/scic_sds_controller.h | 18 +- drivers/scsi/isci/core/scic_sds_phy.c | 396 +++++++++++---------- drivers/scsi/isci/core/scic_sds_port.c | 294 +++++++-------- drivers/scsi/isci/core/scic_sds_port.h | 58 +-- drivers/scsi/isci/core/scic_sds_remote_device.c | 186 +++++----- drivers/scsi/isci/core/scic_sds_remote_device.h | 102 +++--- .../scsi/isci/core/scic_sds_remote_node_context.c | 374 +++++++++---------- .../scsi/isci/core/scic_sds_remote_node_context.h | 16 +- drivers/scsi/isci/core/scic_sds_request.c | 196 +++++----- drivers/scsi/isci/core/scic_sds_request.h | 40 +-- .../scsi/isci/core/scic_sds_smp_remote_device.c | 16 +- drivers/scsi/isci/core/scic_sds_smp_request.c | 116 +++--- drivers/scsi/isci/core/scic_sds_smp_request.h | 3 +- drivers/scsi/isci/core/scic_sds_ssp_request.c | 30 +- .../scsi/isci/core/scic_sds_stp_packet_request.c | 194 +++++----- .../scsi/isci/core/scic_sds_stp_packet_request.h | 10 +- .../scsi/isci/core/scic_sds_stp_remote_device.c | 76 ++-- drivers/scsi/isci/core/scic_sds_stp_request.c | 370 +++++++++---------- drivers/scsi/isci/core/scic_sds_stp_request.h | 8 +- 21 files changed, 1481 insertions(+), 1477 deletions(-) diff --git a/drivers/scsi/isci/core/sci_pool.h b/drivers/scsi/isci/core/sci_pool.h index c0d2ea32529b..016ec832f74f 100644 --- a/drivers/scsi/isci/core/sci_pool.h +++ b/drivers/scsi/isci/core/sci_pool.h @@ -73,8 +73,8 @@ * * Private operation for the pool */ -#define SCI_POOL_INCREMENT(this_pool, index) \ - (((index) + 1) == (this_pool).size ? 0 : (index) + 1) +#define SCI_POOL_INCREMENT(pool, index) \ + (((index) + 1) == (pool).size ? 0 : (index) + 1) /** * SCI_POOL_CREATE() - @@ -98,8 +98,8 @@ * This macro evaluates the pool and returns true if the pool is empty. If the * pool is empty the user should not perform any get operation on the pool. */ -#define sci_pool_empty(this_pool) \ - ((this_pool).get == (this_pool).put) +#define sci_pool_empty(pool) \ + ((pool).get == (pool).put) /** * sci_pool_full() - @@ -107,8 +107,8 @@ * This macro evaluates the pool and returns true if the pool is full. If the * pool is full the user should not perform any put operation. */ -#define sci_pool_full(this_pool) \ - (SCI_POOL_INCREMENT(this_pool, (this_pool).put) == (this_pool).get) +#define sci_pool_full(pool) \ + (SCI_POOL_INCREMENT(pool, (pool).put) == (pool).get) /** * sci_pool_size() - @@ -118,25 +118,25 @@ * pointers can be written simultaneously by different users. As a result, * this macro subtracts 1 from the internal size */ -#define sci_pool_size(this_pool) \ - ((this_pool).size - 1) +#define sci_pool_size(pool) \ + ((pool).size - 1) /** * sci_pool_count() - * * This macro indicates the number of elements currently contained in the pool. */ -#define sci_pool_count(this_pool) \ +#define sci_pool_count(pool) \ (\ - sci_pool_empty((this_pool)) \ + sci_pool_empty((pool)) \ ? 0 \ : (\ - sci_pool_full((this_pool)) \ - ? sci_pool_size((this_pool)) \ + sci_pool_full((pool)) \ + ? sci_pool_size((pool)) \ : (\ - (this_pool).get > (this_pool).put \ - ? ((this_pool).size - (this_pool).get + (this_pool).put) \ - : ((this_pool).put - (this_pool).get) \ + (pool).get > (pool).put \ + ? ((pool).size - (pool).get + (pool).put) \ + : ((pool).put - (pool).get) \ ) \ ) \ ) @@ -146,11 +146,11 @@ * * This macro initializes the pool to an empty condition. */ -#define sci_pool_initialize(this_pool) \ +#define sci_pool_initialize(pool) \ { \ - (this_pool).size = (sizeof((this_pool).array) / sizeof((this_pool).array[0])); \ - (this_pool).get = 0; \ - (this_pool).put = 0; \ + (pool).size = (sizeof((pool).array) / sizeof((pool).array[0])); \ + (pool).get = 0; \ + (pool).put = 0; \ } /** @@ -159,10 +159,10 @@ * This macro will get the next free element from the pool. This should only be * called if the pool is not empty. */ -#define sci_pool_get(this_pool, my_value) \ +#define sci_pool_get(pool, my_value) \ { \ - (my_value) = (this_pool).array[(this_pool).get]; \ - (this_pool).get = SCI_POOL_INCREMENT((this_pool), (this_pool).get); \ + (my_value) = (pool).array[(pool).get]; \ + (pool).get = SCI_POOL_INCREMENT((pool), (pool).get); \ } /** @@ -171,10 +171,10 @@ * This macro will put the value into the pool. This should only be called if * the pool is not full. */ -#define sci_pool_put(this_pool, the_value) \ +#define sci_pool_put(pool, value) \ { \ - (this_pool).array[(this_pool).put] = (the_value); \ - (this_pool).put = SCI_POOL_INCREMENT((this_pool), (this_pool).put); \ + (pool).array[(pool).put] = (value); \ + (pool).put = SCI_POOL_INCREMENT((pool), (pool).put); \ } /** @@ -183,16 +183,16 @@ * This macro will search the pool and remove any elements in the pool matching * the supplied value. This method can only be utilized on pools */ -#define sci_pool_erase(this_pool, type, the_value) \ +#define sci_pool_erase(pool, type, value) \ { \ type tmp_value; \ u32 index; \ - u32 element_count = sci_pool_count((this_pool)); \ + u32 element_count = sci_pool_count((pool)); \ \ for (index = 0; index < element_count; index++) { \ - sci_pool_get((this_pool), tmp_value); \ - if (tmp_value != (the_value)) \ - sci_pool_put((this_pool), tmp_value); \ + sci_pool_get((pool), tmp_value); \ + if (tmp_value != (value)) \ + sci_pool_put((pool), tmp_value); \ } \ } diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 9bb78a2e6ff7..63f4cd130d1d 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -290,7 +290,7 @@ int scic_controller_mem_init(struct scic_sds_controller *scic) /** * This method initializes the task context data for the controller. - * @this_controller: + * @scic: * */ static void @@ -321,22 +321,22 @@ scic_sds_controller_assign_task_entries(struct scic_sds_controller *controller) * */ static void scic_sds_controller_initialize_completion_queue( - struct scic_sds_controller *this_controller) + struct scic_sds_controller *scic) { u32 index; u32 completion_queue_control_value; u32 completion_queue_get_value; u32 completion_queue_put_value; - this_controller->completion_queue_get = 0; + scic->completion_queue_get = 0; completion_queue_control_value = ( - SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1) - | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1) + SMU_CQC_QUEUE_LIMIT_SET(scic->completion_queue_entries - 1) + | SMU_CQC_EVENT_LIMIT_SET(scic->completion_event_entries - 1) ); writel(completion_queue_control_value, - &this_controller->smu_registers->completion_queue_control); + &scic->smu_registers->completion_queue_control); /* Set the completion queue get pointer and enable the queue */ @@ -348,7 +348,7 @@ static void scic_sds_controller_initialize_completion_queue( ); writel(completion_queue_get_value, - &this_controller->smu_registers->completion_queue_get); + &scic->smu_registers->completion_queue_get); /* Set the completion queue put pointer */ completion_queue_put_value = ( @@ -357,16 +357,15 @@ static void scic_sds_controller_initialize_completion_queue( ); writel(completion_queue_put_value, - &this_controller->smu_registers->completion_queue_put); - + &scic->smu_registers->completion_queue_put); /* Initialize the cycle bit of the completion queue entries */ - for (index = 0; index < this_controller->completion_queue_entries; index++) { + for (index = 0; index < scic->completion_queue_entries; index++) { /* * If get.cycle_bit != completion_queue.cycle_bit * its not a valid completion queue entry * so at system start all entries are invalid */ - this_controller->completion_queue[index] = 0x80000000; + scic->completion_queue[index] = 0x80000000; } } @@ -376,7 +375,7 @@ static void scic_sds_controller_initialize_completion_queue( * */ static void scic_sds_controller_initialize_unsolicited_frame_queue( - struct scic_sds_controller *this_controller) + struct scic_sds_controller *scic) { u32 frame_queue_control_value; u32 frame_queue_get_value; @@ -384,10 +383,11 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue( /* Write the queue size */ frame_queue_control_value = - SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count); + SCU_UFQC_GEN_VAL(QUEUE_SIZE, + scic->uf_control.address_table.count); writel(frame_queue_control_value, - &this_controller->scu_registers->sdma.unsolicited_frame_queue_control); + &scic->scu_registers->sdma.unsolicited_frame_queue_control); /* Setup the get pointer for the unsolicited frame queue */ frame_queue_get_value = ( @@ -396,11 +396,11 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue( ); writel(frame_queue_get_value, - &this_controller->scu_registers->sdma.unsolicited_frame_get_pointer); + &scic->scu_registers->sdma.unsolicited_frame_get_pointer); /* Setup the put pointer for the unsolicited frame queue */ frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0); writel(frame_queue_put_value, - &this_controller->scu_registers->sdma.unsolicited_frame_put_pointer); + &scic->scu_registers->sdma.unsolicited_frame_put_pointer); } /** @@ -409,16 +409,17 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue( * */ static void scic_sds_controller_enable_port_task_scheduler( - struct scic_sds_controller *this_controller) + struct scic_sds_controller *scic) { u32 port_task_scheduler_value; port_task_scheduler_value = - readl(&this_controller->scu_registers->peg0.ptsg.control); + readl(&scic->scu_registers->peg0.ptsg.control); port_task_scheduler_value |= - (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE)); + (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | + SCU_PTSGCR_GEN_BIT(PTSG_ENABLE)); writel(port_task_scheduler_value, - &this_controller->scu_registers->peg0.ptsg.control); + &scic->scu_registers->peg0.ptsg.control); } /** @@ -564,7 +565,7 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s * This method will attempt to transition into the ready state for the * controller and indicate that the controller start operation has completed * if all criteria are met. - * @this_controller: This parameter indicates the controller object for which + * @scic: This parameter indicates the controller object for which * to transition to ready. * @status: This parameter indicates the status value to be pass into the call * to scic_cb_controller_start_complete(). @@ -858,30 +859,30 @@ static void scic_sds_controller_power_control_timer_restart(struct scic_sds_cont static void scic_sds_controller_power_control_timer_handler( void *controller) { - struct scic_sds_controller *this_controller; + struct scic_sds_controller *scic; - this_controller = (struct scic_sds_controller *)controller; + scic = (struct scic_sds_controller *)controller; - this_controller->power_control.phys_granted_power = 0; + scic->power_control.phys_granted_power = 0; - if (this_controller->power_control.phys_waiting == 0) { - this_controller->power_control.timer_started = false; + if (scic->power_control.phys_waiting == 0) { + scic->power_control.timer_started = false; } else { - struct scic_sds_phy *the_phy = NULL; + struct scic_sds_phy *sci_phy = NULL; u8 i; for (i = 0; (i < SCI_MAX_PHYS) - && (this_controller->power_control.phys_waiting != 0); + && (scic->power_control.phys_waiting != 0); i++) { - if (this_controller->power_control.requesters[i] != NULL) { - if (this_controller->power_control.phys_granted_power < - this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { - the_phy = this_controller->power_control.requesters[i]; - this_controller->power_control.requesters[i] = NULL; - this_controller->power_control.phys_waiting--; - this_controller->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(the_phy); + if (scic->power_control.requesters[i] != NULL) { + if (scic->power_control.phys_granted_power < + scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { + sci_phy = scic->power_control.requesters[i]; + scic->power_control.requesters[i] = NULL; + scic->power_control.phys_waiting--; + scic->power_control.phys_granted_power++; + scic_sds_phy_consume_power_handler(sci_phy); } else { break; } @@ -892,56 +893,56 @@ static void scic_sds_controller_power_control_timer_handler( * It doesn't matter if the power list is empty, we need to start the * timer in case another phy becomes ready. */ - scic_sds_controller_power_control_timer_start(this_controller); + scic_sds_controller_power_control_timer_start(scic); } } /** * This method inserts the phy in the stagger spinup control queue. - * @this_controller: + * @scic: * * */ void scic_sds_controller_power_control_queue_insert( - struct scic_sds_controller *this_controller, - struct scic_sds_phy *the_phy) + struct scic_sds_controller *scic, + struct scic_sds_phy *sci_phy) { - BUG_ON(the_phy == NULL); + BUG_ON(sci_phy == NULL); - if (this_controller->power_control.phys_granted_power < - this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { - this_controller->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(the_phy); + if (scic->power_control.phys_granted_power < + scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { + scic->power_control.phys_granted_power++; + scic_sds_phy_consume_power_handler(sci_phy); /* * stop and start the power_control timer. When the timer fires, the * no_of_phys_granted_power will be set to 0 */ - scic_sds_controller_power_control_timer_restart(this_controller); + scic_sds_controller_power_control_timer_restart(scic); } else { /* Add the phy in the waiting list */ - this_controller->power_control.requesters[the_phy->phy_index] = the_phy; - this_controller->power_control.phys_waiting++; + scic->power_control.requesters[sci_phy->phy_index] = sci_phy; + scic->power_control.phys_waiting++; } } /** * This method removes the phy from the stagger spinup control queue. - * @this_controller: + * @scic: * * */ void scic_sds_controller_power_control_queue_remove( - struct scic_sds_controller *this_controller, - struct scic_sds_phy *the_phy) + struct scic_sds_controller *scic, + struct scic_sds_phy *sci_phy) { - BUG_ON(the_phy == NULL); + BUG_ON(sci_phy == NULL); - if (this_controller->power_control.requesters[the_phy->phy_index] != NULL) { - this_controller->power_control.phys_waiting--; + if (scic->power_control.requesters[sci_phy->phy_index] != NULL) { + scic->power_control.phys_waiting--; } - this_controller->power_control.requesters[the_phy->phy_index] = NULL; + scic->power_control.requesters[sci_phy->phy_index] = NULL; } /* @@ -952,23 +953,20 @@ void scic_sds_controller_power_control_queue_remove( /** * This method returns a true value if the completion queue has entries that * can be processed - * @this_controller: + * @scic: * * bool true if the completion queue has entries to process false if the * completion queue has no entries to process */ static bool scic_sds_controller_completion_queue_has_entries( - struct scic_sds_controller *this_controller) + struct scic_sds_controller *scic) { - u32 get_value = this_controller->completion_queue_get; + u32 get_value = scic->completion_queue_get; u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK; - if ( - NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) - == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index]) - ) { + if (NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) == + COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index])) return true; - } return false; } @@ -976,19 +974,19 @@ static bool scic_sds_controller_completion_queue_has_entries( /** * This method processes a task completion notification. This is called from * within the controller completion handler. - * @this_controller: + * @scic: * @completion_entry: * */ static void scic_sds_controller_task_completion( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u32 completion_entry) { u32 index; struct scic_sds_request *io_request; index = SCU_GET_COMPLETION_INDEX(completion_entry); - io_request = this_controller->io_request_table[index]; + io_request = scic->io_request_table[index]; /* Make sure that we really want to process this IO request */ if ( @@ -996,7 +994,7 @@ static void scic_sds_controller_task_completion( && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) && ( scic_sds_io_tag_get_sequence(io_request->io_tag) - == this_controller->io_request_sequence[index] + == scic->io_request_sequence[index] ) ) { /* Yep this is a valid io request pass it along to the io request handler */ @@ -1007,12 +1005,12 @@ static void scic_sds_controller_task_completion( /** * This method processes an SDMA completion event. This is called from within * the controller completion handler. - * @this_controller: + * @scic: * @completion_entry: * */ static void scic_sds_controller_sdma_completion( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u32 completion_entry) { u32 index; @@ -1024,8 +1022,8 @@ static void scic_sds_controller_sdma_completion( switch (scu_get_command_request_type(completion_entry)) { case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: - io_request = this_controller->io_request_table[index]; - dev_warn(scic_to_dev(this_controller), + io_request = scic->io_request_table[index]; + dev_warn(scic_to_dev(scic), "%s: SCIC SDS Completion type SDMA %x for io request " "%p\n", __func__, @@ -1039,8 +1037,8 @@ static void scic_sds_controller_sdma_completion( case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: - device = this_controller->device_table[index]; - dev_warn(scic_to_dev(this_controller), + device = scic->device_table[index]; + dev_warn(scic_to_dev(scic), "%s: SCIC SDS Completion type SDMA %x for remote " "device %p\n", __func__, @@ -1052,7 +1050,7 @@ static void scic_sds_controller_sdma_completion( break; default: - dev_warn(scic_to_dev(this_controller), + dev_warn(scic_to_dev(scic), "%s: SCIC SDS Completion unknown SDMA completion " "type %x\n", __func__, @@ -1064,14 +1062,14 @@ static void scic_sds_controller_sdma_completion( /** * - * @this_controller: + * @scic: * @completion_entry: * * This method processes an unsolicited frame message. This is called from * within the controller completion handler. none */ static void scic_sds_controller_unsolicited_frame( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u32 completion_entry) { u32 index; @@ -1086,8 +1084,8 @@ static void scic_sds_controller_unsolicited_frame( frame_index = SCU_GET_FRAME_INDEX(completion_entry); frame_header - = this_controller->uf_control.buffers.array[frame_index].header; - this_controller->uf_control.buffers.array[frame_index].state + = scic->uf_control.buffers.array[frame_index].header; + scic->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE; if (SCU_GET_FRAME_ERROR(completion_entry)) { @@ -1095,13 +1093,13 @@ static void scic_sds_controller_unsolicited_frame( * / @todo If the IAF frame or SIGNATURE FIS frame has an error will * / this cause a problem? We expect the phy initialization will * / fail if there is an error in the frame. */ - scic_sds_controller_release_frame(this_controller, frame_index); + scic_sds_controller_release_frame(scic, frame_index); return; } if (frame_header->is_address_frame) { index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &this_controller->phy_table[index]; + phy = &scic->phy_table[index]; if (phy != NULL) { result = scic_sds_phy_frame_handler(phy, frame_index); } @@ -1115,18 +1113,18 @@ static void scic_sds_controller_unsolicited_frame( * device that has not yet been created. In either case forwared * the frame to the PE and let it take care of the frame data. */ index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &this_controller->phy_table[index]; + phy = &scic->phy_table[index]; result = scic_sds_phy_frame_handler(phy, frame_index); } else { - if (index < this_controller->remote_node_entries) - device = this_controller->device_table[index]; + if (index < scic->remote_node_entries) + device = scic->device_table[index]; else device = NULL; if (device != NULL) result = scic_sds_remote_device_frame_handler(device, frame_index); else - scic_sds_controller_release_frame(this_controller, frame_index); + scic_sds_controller_release_frame(scic, frame_index); } } @@ -1140,12 +1138,12 @@ static void scic_sds_controller_unsolicited_frame( /** * This method processes an event completion entry. This is called from within * the controller completion handler. - * @this_controller: + * @scic: * @completion_entry: * */ static void scic_sds_controller_event_completion( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u32 completion_entry) { u32 index; @@ -1158,11 +1156,11 @@ static void scic_sds_controller_event_completion( switch (scu_get_event_type(completion_entry)) { case SCU_EVENT_TYPE_SMU_COMMAND_ERROR: /* / @todo The driver did something wrong and we need to fix the condtion. */ - dev_err(scic_to_dev(this_controller), + dev_err(scic_to_dev(scic), "%s: SCIC Controller 0x%p received SMU command error " "0x%x\n", __func__, - this_controller, + scic, completion_entry); break; @@ -1172,16 +1170,16 @@ static void scic_sds_controller_event_completion( /* * / @todo This is a hardware failure and its likely that we want to * / reset the controller. */ - dev_err(scic_to_dev(this_controller), + dev_err(scic_to_dev(scic), "%s: SCIC Controller 0x%p received fatal controller " "event 0x%x\n", __func__, - this_controller, + scic, completion_entry); break; case SCU_EVENT_TYPE_TRANSPORT_ERROR: - io_request = this_controller->io_request_table[index]; + io_request = scic->io_request_table[index]; scic_sds_io_request_event_handler(io_request, completion_entry); break; @@ -1189,31 +1187,31 @@ static void scic_sds_controller_event_completion( switch (scu_get_event_specifier(completion_entry)) { case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: - io_request = this_controller->io_request_table[index]; + io_request = scic->io_request_table[index]; if (io_request != NULL) scic_sds_io_request_event_handler(io_request, completion_entry); else - dev_warn(scic_to_dev(this_controller), + dev_warn(scic_to_dev(scic), "%s: SCIC Controller 0x%p received " "event 0x%x for io request object " "that doesnt exist.\n", __func__, - this_controller, + scic, completion_entry); break; case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: - device = this_controller->device_table[index]; + device = scic->device_table[index]; if (device != NULL) scic_sds_remote_device_event_handler(device, completion_entry); else - dev_warn(scic_to_dev(this_controller), + dev_warn(scic_to_dev(scic), "%s: SCIC Controller 0x%p received " "event 0x%x for remote device object " "that doesnt exist.\n", __func__, - this_controller, + scic, completion_entry); break; @@ -1230,32 +1228,32 @@ static void scic_sds_controller_event_completion( * we get the event notification. This is a type 4 event. */ case SCU_EVENT_TYPE_OSSP_EVENT: index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &this_controller->phy_table[index]; + phy = &scic->phy_table[index]; scic_sds_phy_event_handler(phy, completion_entry); break; case SCU_EVENT_TYPE_RNC_SUSPEND_TX: case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: case SCU_EVENT_TYPE_RNC_OPS_MISC: - if (index < this_controller->remote_node_entries) { - device = this_controller->device_table[index]; + if (index < scic->remote_node_entries) { + device = scic->device_table[index]; if (device != NULL) scic_sds_remote_device_event_handler(device, completion_entry); } else - dev_err(scic_to_dev(this_controller), + dev_err(scic_to_dev(scic), "%s: SCIC Controller 0x%p received event 0x%x " "for remote device object 0x%0x that doesnt " "exist.\n", __func__, - this_controller, + scic, completion_entry, index); break; default: - dev_warn(scic_to_dev(this_controller), + dev_warn(scic_to_dev(scic), "%s: SCIC Controller received unknown event code %x\n", __func__, completion_entry); @@ -1265,11 +1263,11 @@ static void scic_sds_controller_event_completion( /** * This method is a private routine for processing the completion queue entries. - * @this_controller: + * @scic: * */ static void scic_sds_controller_process_completions( - struct scic_sds_controller *this_controller) + struct scic_sds_controller *scic) { u32 completion_count = 0; u32 completion_entry; @@ -1278,60 +1276,60 @@ static void scic_sds_controller_process_completions( u32 event_index; u32 event_cycle; - dev_dbg(scic_to_dev(this_controller), + dev_dbg(scic_to_dev(scic), "%s: completion queue begining get:0x%08x\n", __func__, - this_controller->completion_queue_get); + scic->completion_queue_get); /* Get the component parts of the completion queue */ - get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get); - get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get; + get_index = NORMALIZE_GET_POINTER(scic->completion_queue_get); + get_cycle = SMU_CQGR_CYCLE_BIT & scic->completion_queue_get; - event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get); - event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get; + event_index = NORMALIZE_EVENT_POINTER(scic->completion_queue_get); + event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & scic->completion_queue_get; while ( NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) - == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index]) + == COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index]) ) { completion_count++; - completion_entry = this_controller->completion_queue[get_index]; - INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle); + completion_entry = scic->completion_queue[get_index]; + INCREMENT_COMPLETION_QUEUE_GET(scic, get_index, get_cycle); - dev_dbg(scic_to_dev(this_controller), + dev_dbg(scic_to_dev(scic), "%s: completion queue entry:0x%08x\n", __func__, completion_entry); switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { case SCU_COMPLETION_TYPE_TASK: - scic_sds_controller_task_completion(this_controller, completion_entry); + scic_sds_controller_task_completion(scic, completion_entry); break; case SCU_COMPLETION_TYPE_SDMA: - scic_sds_controller_sdma_completion(this_controller, completion_entry); + scic_sds_controller_sdma_completion(scic, completion_entry); break; case SCU_COMPLETION_TYPE_UFI: - scic_sds_controller_unsolicited_frame(this_controller, completion_entry); + scic_sds_controller_unsolicited_frame(scic, completion_entry); break; case SCU_COMPLETION_TYPE_EVENT: - INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); - scic_sds_controller_event_completion(this_controller, completion_entry); + INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle); + scic_sds_controller_event_completion(scic, completion_entry); break; case SCU_COMPLETION_TYPE_NOTIFY: /* * Presently we do the same thing with a notify event that we do with the * other event codes. */ - INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); - scic_sds_controller_event_completion(this_controller, completion_entry); + INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle); + scic_sds_controller_event_completion(scic, completion_entry); break; default: - dev_warn(scic_to_dev(this_controller), + dev_warn(scic_to_dev(scic), "%s: SCIC Controller received unknown " "completion type %x\n", __func__, @@ -1342,21 +1340,23 @@ static void scic_sds_controller_process_completions( /* Update the get register if we completed one or more entries */ if (completion_count > 0) { - this_controller->completion_queue_get = - SMU_CQGR_GEN_BIT(ENABLE) - | SMU_CQGR_GEN_BIT(EVENT_ENABLE) - | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) - | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); + scic->completion_queue_get = + SMU_CQGR_GEN_BIT(ENABLE) | + SMU_CQGR_GEN_BIT(EVENT_ENABLE) | + event_cycle | + SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) | + get_cycle | + SMU_CQGR_GEN_VAL(POINTER, get_index); - writel(this_controller->completion_queue_get, - &this_controller->smu_registers->completion_queue_get); + writel(scic->completion_queue_get, + &scic->smu_registers->completion_queue_get); } - dev_dbg(scic_to_dev(this_controller), + dev_dbg(scic_to_dev(scic), "%s: completion queue ending get:0x%08x\n", __func__, - this_controller->completion_queue_get); + scic->completion_queue_get); } @@ -1540,29 +1540,29 @@ void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, /** * This method will write to the SCU PCP register the request value. The method * is used to suspend/resume ports, devices, and phys. - * @this_controller: + * @scic: * * */ void scic_sds_controller_post_request( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u32 request) { - dev_dbg(scic_to_dev(this_controller), + dev_dbg(scic_to_dev(scic), "%s: SCIC Controller 0x%p post request 0x%08x\n", __func__, - this_controller, + scic, request); - writel(request, &this_controller->smu_registers->post_context_port); + writel(request, &scic->smu_registers->post_context_port); } /** * This method will copy the soft copy of the task context into the physical * memory accessible by the controller. - * @this_controller: This parameter specifies the controller for which to copy + * @scic: This parameter specifies the controller for which to copy * the task context. - * @this_request: This parameter specifies the request for which the task + * @sci_req: This parameter specifies the request for which the task * context is being copied. * * After this call is made the SCIC_SDS_IO_REQUEST object will always point to @@ -1571,43 +1571,40 @@ void scic_sds_controller_post_request( * memory). none */ void scic_sds_controller_copy_task_context( - struct scic_sds_controller *this_controller, - struct scic_sds_request *this_request) + struct scic_sds_controller *scic, + struct scic_sds_request *sci_req) { struct scu_task_context *task_context_buffer; task_context_buffer = scic_sds_controller_get_task_context_buffer( - this_controller, this_request->io_tag - ); + scic, sci_req->io_tag); - memcpy( - task_context_buffer, - this_request->task_context_buffer, - SCI_FIELD_OFFSET(struct scu_task_context, sgl_snapshot_ac) - ); + memcpy(task_context_buffer, + sci_req->task_context_buffer, + SCI_FIELD_OFFSET(struct scu_task_context, sgl_snapshot_ac)); /* * Now that the soft copy of the TC has been copied into the TC * table accessible by the silicon. Thus, any further changes to * the TC (e.g. TC termination) occur in the appropriate location. */ - this_request->task_context_buffer = task_context_buffer; + sci_req->task_context_buffer = task_context_buffer; } /** * This method returns the task context buffer for the given io tag. - * @this_controller: + * @scic: * @io_tag: * * struct scu_task_context* */ struct scu_task_context *scic_sds_controller_get_task_context_buffer( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u16 io_tag ) { u16 task_index = scic_sds_io_tag_get_index(io_tag); - if (task_index < this_controller->task_context_entries) { - return &this_controller->task_context_table[task_index]; + if (task_index < scic->task_context_entries) { + return &scic->task_context_table[task_index]; } return NULL; @@ -1615,7 +1612,7 @@ struct scu_task_context *scic_sds_controller_get_task_context_buffer( /** * This method returnst the sequence value from the io tag value - * @this_controller: + * @scic: * @io_tag: * * u16 @@ -1623,13 +1620,13 @@ struct scu_task_context *scic_sds_controller_get_task_context_buffer( /** * This method returns the IO request associated with the tag value - * @this_controller: + * @scic: * @io_tag: * * SCIC_SDS_IO_REQUEST_T* NULL if there is no valid IO request at the tag value */ struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u16 io_tag ) { u16 task_index; @@ -1637,12 +1634,12 @@ struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( task_index = scic_sds_io_tag_get_index(io_tag); - if (task_index < this_controller->task_context_entries) { - if (this_controller->io_request_table[task_index] != NULL) { + if (task_index < scic->task_context_entries) { + if (scic->io_request_table[task_index] != NULL) { task_sequence = scic_sds_io_tag_get_sequence(io_tag); - if (task_sequence == this_controller->io_request_sequence[task_index]) { - return this_controller->io_request_table[task_index]; + if (task_sequence == scic->io_request_sequence[task_index]) { + return scic->io_request_table[task_index]; } } } @@ -1654,9 +1651,9 @@ struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( * This method allocates remote node index and the reserves the remote node * context space for use. This method can fail if there are no more remote * node index available. - * @this_controller: This is the controller object which contains the set of + * @scic: This is the controller object which contains the set of * free remote node ids - * @the_devce: This is the device object which is requesting the a remote node + * @sci_dev: This is the device object which is requesting the a remote node * id * @node_id: This is the remote node id that is assinged to the device if one * is available @@ -1665,19 +1662,19 @@ struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( * node index available. */ enum sci_status scic_sds_controller_allocate_remote_node_context( - struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *the_device, + struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, u16 *node_id) { u16 node_index; - u32 remote_node_count = scic_sds_remote_device_node_count(the_device); + u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev); node_index = scic_sds_remote_node_table_allocate_remote_node( - &this_controller->available_remote_nodes, remote_node_count + &scic->available_remote_nodes, remote_node_count ); if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - this_controller->device_table[node_index] = the_device; + scic->device_table[node_index] = sci_dev; *node_id = node_index; @@ -1691,23 +1688,23 @@ enum sci_status scic_sds_controller_allocate_remote_node_context( * This method frees the remote node index back to the available pool. Once * this is done the remote node context buffer is no longer valid and can * not be used. - * @this_controller: - * @the_device: + * @scic: + * @sci_dev: * @node_id: * */ void scic_sds_controller_free_remote_node_context( - struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *the_device, + struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, u16 node_id) { - u32 remote_node_count = scic_sds_remote_device_node_count(the_device); + u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev); - if (this_controller->device_table[node_id] == the_device) { - this_controller->device_table[node_id] = NULL; + if (scic->device_table[node_id] == sci_dev) { + scic->device_table[node_id] = NULL; scic_sds_remote_node_table_release_remote_node_index( - &this_controller->available_remote_nodes, remote_node_count, node_id + &scic->available_remote_nodes, remote_node_count, node_id ); } } @@ -1715,20 +1712,20 @@ void scic_sds_controller_free_remote_node_context( /** * This method returns the union scu_remote_node_context for the specified remote * node id. - * @this_controller: + * @scic: * @node_id: * * union scu_remote_node_context* */ union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u16 node_id ) { if ( - (node_id < this_controller->remote_node_entries) - && (this_controller->device_table[node_id] != NULL) + (node_id < scic->remote_node_entries) + && (scic->device_table[node_id] != NULL) ) { - return &this_controller->remote_node_context_table[node_id]; + return &scic->remote_node_context_table[node_id]; } return NULL; @@ -1767,18 +1764,18 @@ void scic_sds_controller_copy_sata_response( * re-use by the hardware. The data contained in the frame header and frame * buffer is no longer valid. The UF queue get pointer is only updated if UF * control indicates this is appropriate. - * @this_controller: + * @scic: * @frame_index: * */ void scic_sds_controller_release_frame( - struct scic_sds_controller *this_controller, + struct scic_sds_controller *scic, u32 frame_index) { if (scic_sds_unsolicited_frame_control_release_frame( - &this_controller->uf_control, frame_index) == true) - writel(this_controller->uf_control.get, - &this_controller->scu_registers->sdma.unsolicited_frame_get_pointer); + &scic->uf_control, frame_index) == true) + writel(scic->uf_control.get, + &scic->scu_registers->sdma.unsolicited_frame_get_pointer); } /** @@ -2888,11 +2885,11 @@ enum sci_status scic_controller_start(struct scic_sds_controller *scic, static void scic_sds_controller_initial_state_enter( struct sci_base_object *object) { - struct scic_sds_controller *this_controller; + struct scic_sds_controller *scic; - this_controller = (struct scic_sds_controller *)object; + scic = (struct scic_sds_controller *)object; - sci_base_state_machine_change_state(&this_controller->state_machine, + sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_RESET); } @@ -2925,13 +2922,13 @@ static inline void scic_sds_controller_starting_state_exit( static void scic_sds_controller_ready_state_enter( struct sci_base_object *object) { - struct scic_sds_controller *this_controller; + struct scic_sds_controller *scic; - this_controller = (struct scic_sds_controller *)object; + scic = (struct scic_sds_controller *)object; /* set the default interrupt coalescence number and timeout value. */ scic_controller_set_interrupt_coalescence( - this_controller, 0x10, 250); + scic, 0x10, 250); } /** @@ -2945,12 +2942,12 @@ static void scic_sds_controller_ready_state_enter( static void scic_sds_controller_ready_state_exit( struct sci_base_object *object) { - struct scic_sds_controller *this_controller; + struct scic_sds_controller *scic; - this_controller = (struct scic_sds_controller *)object; + scic = (struct scic_sds_controller *)object; /* disable interrupt coalescence. */ - scic_controller_set_interrupt_coalescence(this_controller, 0, 0); + scic_controller_set_interrupt_coalescence(scic, 0, 0); } /** @@ -2966,14 +2963,14 @@ static void scic_sds_controller_ready_state_exit( static void scic_sds_controller_stopping_state_enter( struct sci_base_object *object) { - struct scic_sds_controller *this_controller; + struct scic_sds_controller *scic; - this_controller = (struct scic_sds_controller *)object; + scic = (struct scic_sds_controller *)object; /* Stop all of the components for this controller */ - scic_sds_controller_stop_phys(this_controller); - scic_sds_controller_stop_ports(this_controller); - scic_sds_controller_stop_devices(this_controller); + scic_sds_controller_stop_phys(scic); + scic_sds_controller_stop_ports(scic); + scic_sds_controller_stop_devices(scic); } /** diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 9a646e5c7f45..4bb9a43fbe4d 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -542,12 +542,12 @@ void scic_sds_controller_copy_sata_response( enum sci_status scic_sds_controller_allocate_remote_node_context( struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *the_device, + struct scic_sds_remote_device *sci_dev, u16 *node_id); void scic_sds_controller_free_remote_node_context( struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *the_device, + struct scic_sds_remote_device *sci_dev, u16 node_id); union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( @@ -565,25 +565,25 @@ struct scu_task_context *scic_sds_controller_get_task_context_buffer( void scic_sds_controller_power_control_queue_insert( struct scic_sds_controller *this_controller, - struct scic_sds_phy *the_phy); + struct scic_sds_phy *sci_phy); void scic_sds_controller_power_control_queue_remove( struct scic_sds_controller *this_controller, - struct scic_sds_phy *the_phy); + struct scic_sds_phy *sci_phy); void scic_sds_controller_link_up( struct scic_sds_controller *this_controller, - struct scic_sds_port *the_port, - struct scic_sds_phy *the_phy); + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); void scic_sds_controller_link_down( struct scic_sds_controller *this_controller, - struct scic_sds_port *the_port, - struct scic_sds_phy *the_phy); + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); void scic_sds_controller_remote_device_stopped( struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *the_device); + struct scic_sds_remote_device *sci_dev); void scic_sds_controller_copy_task_context( struct scic_sds_controller *this_controller, diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 40176f0729c1..34bd3b25ccf6 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -84,26 +84,29 @@ enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy) /** * This method will initialize the phy transport layer registers - * @this_phy: + * @sci_phy: * @transport_layer_registers * * enum sci_status */ static enum sci_status scic_sds_phy_transport_layer_initialization( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, struct scu_transport_layer_registers __iomem *transport_layer_registers) { u32 tl_control; - this_phy->transport_layer_registers = transport_layer_registers; + sci_phy->transport_layer_registers = transport_layer_registers; writel(SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX, - &this_phy->transport_layer_registers->stp_rni); + &sci_phy->transport_layer_registers->stp_rni); - /* Hardware team recommends that we enable the STP prefetch for all transports */ - tl_control = readl(&this_phy->transport_layer_registers->control); + /* + * Hardware team recommends that we enable the STP prefetch for all + * transports + */ + tl_control = readl(&sci_phy->transport_layer_registers->control); tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); - writel(tl_control, &this_phy->transport_layer_registers->control); + writel(tl_control, &sci_phy->transport_layer_registers->control); return SCI_SUCCESS; } @@ -284,7 +287,7 @@ static void scic_sds_phy_sata_timeout(void *phy) * This method returns the port currently containing this phy. If the phy is * currently contained by the dummy port, then the phy is considered to not * be part of a port. - * @this_phy: This parameter specifies the phy for which to retrieve the + * @sci_phy: This parameter specifies the phy for which to retrieve the * containing port. * * This method returns a handle to a port that contains the supplied phy. @@ -293,30 +296,30 @@ static void scic_sds_phy_sata_timeout(void *phy) * values indicate a handle/pointer to the port containing the phy. */ struct scic_sds_port *scic_sds_phy_get_port( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { - if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT) + if (scic_sds_port_get_index(sci_phy->owning_port) == SCIC_SDS_DUMMY_PORT) return NULL; - return this_phy->owning_port; + return sci_phy->owning_port; } /** * This method will assign a port to the phy object. - * @out]: this_phy This parameter specifies the phy for which to assign a port + * @out]: sci_phy This parameter specifies the phy for which to assign a port * object. * * */ void scic_sds_phy_set_port( - struct scic_sds_phy *this_phy, - struct scic_sds_port *the_port) + struct scic_sds_phy *sci_phy, + struct scic_sds_port *sci_port) { - this_phy->owning_port = the_port; + sci_phy->owning_port = sci_port; - if (this_phy->bcn_received_while_port_unassigned) { - this_phy->bcn_received_while_port_unassigned = false; - scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); + if (sci_phy->bcn_received_while_port_unassigned) { + sci_phy->bcn_received_while_port_unassigned = false; + scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); } } @@ -362,123 +365,125 @@ enum sci_status scic_sds_phy_initialize( /** * This method assigns the direct attached device ID for this phy. * - * @this_phy The phy for which the direct attached device id is to + * @sci_phy The phy for which the direct attached device id is to * be assigned. * @device_id The direct attached device ID to assign to the phy. * This will either be the RNi for the device or an invalid RNi if there * is no current device assigned to the phy. */ void scic_sds_phy_setup_transport( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 device_id) { u32 tl_control; - writel(device_id, &this_phy->transport_layer_registers->stp_rni); + writel(device_id, &sci_phy->transport_layer_registers->stp_rni); /* * The read should guarantee that the first write gets posted * before the next write */ - tl_control = readl(&this_phy->transport_layer_registers->control); + tl_control = readl(&sci_phy->transport_layer_registers->control); tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); - writel(tl_control, &this_phy->transport_layer_registers->control); + writel(tl_control, &sci_phy->transport_layer_registers->control); } /** * - * @this_phy: The phy object to be suspended. + * @sci_phy: The phy object to be suspended. * * This function will perform the register reads/writes to suspend the SCU * hardware protocol engine. none */ static void scic_sds_phy_suspend( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { u32 scu_sas_pcfg_value; scu_sas_pcfg_value = - readl(&this_phy->link_layer_registers->phy_configuration); + readl(&sci_phy->link_layer_registers->phy_configuration); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); writel(scu_sas_pcfg_value, - &this_phy->link_layer_registers->phy_configuration); + &sci_phy->link_layer_registers->phy_configuration); - scic_sds_phy_setup_transport(this_phy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); + scic_sds_phy_setup_transport( + sci_phy, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); } /** * - * @this_phy: The phy object to resume. + * @sci_phy: The phy object to resume. * * This function will perform the register reads/writes required to resume the * SCU hardware protocol engine. none */ void scic_sds_phy_resume( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { u32 scu_sas_pcfg_value; scu_sas_pcfg_value = - readl(&this_phy->link_layer_registers->phy_configuration); + readl(&sci_phy->link_layer_registers->phy_configuration); scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); writel(scu_sas_pcfg_value, - &this_phy->link_layer_registers->phy_configuration); + &sci_phy->link_layer_registers->phy_configuration); } /** * This method returns the local sas address assigned to this phy. - * @this_phy: This parameter specifies the phy for which to retrieve the local + * @sci_phy: This parameter specifies the phy for which to retrieve the local * SAS address. * @sas_address: This parameter specifies the location into which to copy the * local SAS address. * */ void scic_sds_phy_get_sas_address( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, struct sci_sas_address *sas_address) { - sas_address->high = readl(&this_phy->link_layer_registers->source_sas_address_high); - sas_address->low = readl(&this_phy->link_layer_registers->source_sas_address_low); + sas_address->high = readl(&sci_phy->link_layer_registers->source_sas_address_high); + sas_address->low = readl(&sci_phy->link_layer_registers->source_sas_address_low); } /** * This method returns the remote end-point (i.e. attached) sas address * assigned to this phy. - * @this_phy: This parameter specifies the phy for which to retrieve the remote + * @sci_phy: This parameter specifies the phy for which to retrieve the remote * end-point SAS address. * @sas_address: This parameter specifies the location into which to copy the * remote end-point SAS address. * */ void scic_sds_phy_get_attached_sas_address( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, struct sci_sas_address *sas_address) { sas_address->high - = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high; + = sci_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high; sas_address->low - = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low; + = sci_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low; } /** * This method returns the supported protocols assigned to this phy - * @this_phy: + * @sci_phy: * * */ void scic_sds_phy_get_protocols( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, struct sci_sas_identify_address_frame_protocols *protocols) { protocols->u.all = - (u16)(readl(&this_phy-> + (u16)(readl(&sci_phy-> link_layer_registers->transmit_identification) & 0x0000FFFF); } /** * - * @this_phy: The parameter is the phy object for which the attached phy + * @sci_phy: The parameter is the phy object for which the attached phy * protcols are to be returned. * * This method returns the supported protocols for the attached phy. If this @@ -488,15 +493,15 @@ void scic_sds_phy_get_protocols( * value. */ void scic_sds_phy_get_attached_phy_protocols( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, struct sci_sas_identify_address_frame_protocols *protocols) { protocols->u.all = 0; - if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { protocols->u.all = - this_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all; - } else if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { + sci_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all; + } else if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { protocols->u.bits.stp_target = 1; } } @@ -533,54 +538,54 @@ enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) /** * This method will attempt to reset the phy. This request is only valid when * the phy is in an ready state - * @this_phy: + * @sci_phy: * * enum sci_status */ enum sci_status scic_sds_phy_reset( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { - return this_phy->state_handlers->reset_handler(this_phy); + return sci_phy->state_handlers->reset_handler(sci_phy); } /** * This method will process the event code received. - * @this_phy: + * @sci_phy: * @event_code: * * enum sci_status */ enum sci_status scic_sds_phy_event_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 event_code) { - return this_phy->state_handlers->event_handler(this_phy, event_code); + return sci_phy->state_handlers->event_handler(sci_phy, event_code); } /** * This method will process the frame index received. - * @this_phy: + * @sci_phy: * @frame_index: * * enum sci_status */ enum sci_status scic_sds_phy_frame_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 frame_index) { - return this_phy->state_handlers->frame_handler(this_phy, frame_index); + return sci_phy->state_handlers->frame_handler(sci_phy, frame_index); } /** * This method will give the phy permission to consume power - * @this_phy: + * @sci_phy: * * enum sci_status */ enum sci_status scic_sds_phy_consume_power_handler( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { - return this_phy->state_handlers->consume_power_handler(this_phy); + return sci_phy->state_handlers->consume_power_handler(sci_phy); } /* @@ -638,7 +643,7 @@ enum sci_status scic_sata_phy_get_properties( /** * - * @this_phy: The phy object that received SAS PHY DETECTED. + * @sci_phy: The phy object that received SAS PHY DETECTED. * * This method continues the link training for the phy as if it were a SAS PHY * instead of a SATA PHY. This is done because the completion queue had a SAS @@ -646,41 +651,41 @@ enum sci_status scic_sata_phy_get_properties( * none */ static void scic_sds_phy_start_sas_link_training( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { u32 phy_control; phy_control = - readl(&this_phy->link_layer_registers->phy_configuration); + readl(&sci_phy->link_layer_registers->phy_configuration); phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); writel(phy_control, - &this_phy->link_layer_registers->phy_configuration); + &sci_phy->link_layer_registers->phy_configuration); sci_base_state_machine_change_state( - &this_phy->starting_substate_machine, + &sci_phy->starting_substate_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN ); - this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; } /** * - * @this_phy: The phy object that received a SATA SPINUP HOLD event + * @sci_phy: The phy object that received a SATA SPINUP HOLD event * * This method continues the link training for the phy as if it were a SATA PHY * instead of a SAS PHY. This is done because the completion queue had a SATA * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none */ static void scic_sds_phy_start_sata_link_training( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { sci_base_state_machine_change_state( - &this_phy->starting_substate_machine, + &sci_phy->starting_substate_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER ); - this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; } /** @@ -748,24 +753,24 @@ static enum sci_status scic_sds_phy_starting_substate_general_stop_handler( * SCI_FAILURE on any unexpected event notifation */ static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 event_code) { u32 result = SCI_SUCCESS; switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: - scic_sds_phy_start_sas_link_training(this_phy); - this_phy->is_in_link_training = true; + scic_sds_phy_start_sas_link_training(sci_phy); + sci_phy->is_in_link_training = true; break; case SCU_EVENT_SATA_SPINUP_HOLD: - scic_sds_phy_start_sata_link_training(this_phy); - this_phy->is_in_link_training = true; + scic_sds_phy_start_sata_link_training(sci_phy); + sci_phy->is_in_link_training = true; break; default: - dev_dbg(sciphy_to_dev(this_phy), + dev_dbg(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -793,7 +798,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler( * event notification SCI_FAILURE on any unexpected event notifation */ static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 event_code) { u32 result = SCI_SUCCESS; @@ -808,38 +813,41 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_ case SCU_EVENT_SAS_15: case SCU_EVENT_SAS_15_SSC: scic_sds_phy_complete_link_training( - this_phy, SAS_LINK_RATE_1_5_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF - ); + sci_phy, + SAS_LINK_RATE_1_5_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); break; case SCU_EVENT_SAS_30: case SCU_EVENT_SAS_30_SSC: scic_sds_phy_complete_link_training( - this_phy, SAS_LINK_RATE_3_0_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF - ); + sci_phy, + SAS_LINK_RATE_3_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); break; case SCU_EVENT_SAS_60: case SCU_EVENT_SAS_60_SSC: scic_sds_phy_complete_link_training( - this_phy, SAS_LINK_RATE_6_0_GBPS, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF - ); + sci_phy, + SAS_LINK_RATE_6_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* * We were doing SAS PHY link training and received a SATA PHY event * continue OOB/SN as if this were a SATA PHY */ - scic_sds_phy_start_sata_link_training(this_phy); + scic_sds_phy_start_sata_link_training(sci_phy); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(this_phy); + scic_sds_phy_restart_starting_state(sci_phy); break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -867,7 +875,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_ * unexpected event notifation */ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 event_code) { u32 result = SCI_SUCCESS; @@ -875,25 +883,25 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: /* Backup the state machine */ - scic_sds_phy_start_sas_link_training(this_phy); + scic_sds_phy_start_sas_link_training(sci_phy); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* * We were doing SAS PHY link training and received a SATA PHY event * continue OOB/SN as if this were a SATA PHY */ - scic_sds_phy_start_sata_link_training(this_phy); + scic_sds_phy_start_sata_link_training(sci_phy); break; case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: case SCU_EVENT_LINK_FAILURE: case SCU_EVENT_HARD_RESET_RECEIVED: /* Start the oob/sn state machine over again */ - scic_sds_phy_restart_starting_state(this_phy); + scic_sds_phy_restart_starting_state(sci_phy); break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -919,7 +927,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler * notifation */ static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 event_code) { u32 result = SCI_SUCCESS; @@ -927,11 +935,11 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_hand switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(this_phy); + scic_sds_phy_restart_starting_state(sci_phy); break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received unexpected " "event_code %x\n", __func__, @@ -957,7 +965,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_hand * on a link failure event SCI_FAILURE on any unexpected event notifation */ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 event_code) { u32 result = SCI_SUCCESS; @@ -965,7 +973,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_han switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(this_phy); + scic_sds_phy_restart_starting_state(sci_phy); break; case SCU_EVENT_SATA_SPINUP_HOLD: @@ -976,11 +984,11 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_han /* * There has been a change in the phy type before OOB/SN for the * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(this_phy); + scic_sds_phy_start_sas_link_training(sci_phy); break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -1066,7 +1074,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handl * valid event notification SCI_FAILURE on any unexpected event notifation */ static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_handler( - struct scic_sds_phy *this_phy, + struct scic_sds_phy *sci_phy, u32 event_code) { u32 result = SCI_SUCCESS; @@ -1081,44 +1089,41 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_han case SCU_EVENT_SATA_15: case SCU_EVENT_SATA_15_SSC: scic_sds_phy_complete_link_training( - this_phy, + sci_phy, SAS_LINK_RATE_1_5_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF - ); + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_SATA_30: case SCU_EVENT_SATA_30_SSC: scic_sds_phy_complete_link_training( - this_phy, + sci_phy, SAS_LINK_RATE_3_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF - ); + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_SATA_60: case SCU_EVENT_SATA_60_SSC: scic_sds_phy_complete_link_training( - this_phy, + sci_phy, SAS_LINK_RATE_6_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF - ); + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(this_phy); + scic_sds_phy_restart_starting_state(sci_phy); break; case SCU_EVENT_SAS_PHY_DETECTED: /* * There has been a change in the phy type before OOB/SN for the * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(this_phy); + scic_sds_phy_start_sas_link_training(sci_phy); break; default: - dev_warn(sciphy_to_dev(this_phy), + dev_warn(sciphy_to_dev(sci_phy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -1583,12 +1588,12 @@ static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_object static void scic_sds_phy_starting_await_ossp_en_substate_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN ); } @@ -1603,12 +1608,12 @@ static void scic_sds_phy_starting_await_ossp_en_substate_enter( static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN ); } @@ -1623,12 +1628,12 @@ static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( static void scic_sds_phy_starting_await_iaf_uf_substate_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF ); } @@ -1644,17 +1649,17 @@ static void scic_sds_phy_starting_await_iaf_uf_substate_enter( static void scic_sds_phy_starting_await_sas_power_substate_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER ); scic_sds_controller_power_control_queue_insert( - scic_sds_phy_get_controller(this_phy), - this_phy + scic_sds_phy_get_controller(sci_phy), + sci_phy ); } @@ -1669,12 +1674,12 @@ static void scic_sds_phy_starting_await_sas_power_substate_enter( static void scic_sds_phy_starting_await_sas_power_substate_exit( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; scic_sds_controller_power_control_queue_remove( - scic_sds_phy_get_controller(this_phy), this_phy + scic_sds_phy_get_controller(sci_phy), sci_phy ); } @@ -1690,17 +1695,17 @@ static void scic_sds_phy_starting_await_sas_power_substate_exit( static void scic_sds_phy_starting_await_sata_power_substate_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; scic_sds_phy_set_starting_substate_handlers( - this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER ); scic_sds_controller_power_control_queue_insert( - scic_sds_phy_get_controller(this_phy), - this_phy + scic_sds_phy_get_controller(sci_phy), + sci_phy ); } @@ -1715,13 +1720,13 @@ static void scic_sds_phy_starting_await_sata_power_substate_enter( static void scic_sds_phy_starting_await_sata_power_substate_exit( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; scic_sds_controller_power_control_queue_remove( - scic_sds_phy_get_controller(this_phy), - this_phy + scic_sds_phy_get_controller(sci_phy), + sci_phy ); } @@ -2115,33 +2120,32 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ /** * - * @this_phy: This is the struct scic_sds_phy object to stop. + * @sci_phy: This is the struct scic_sds_phy object to stop. * * This method will stop the struct scic_sds_phy object. This does not reset the * protocol engine it just suspends it and places it in a state where it will * not cause the end device to power up. none */ static void scu_link_layer_stop_protocol_engine( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { u32 scu_sas_pcfg_value; u32 enable_spinup_value; /* Suspend the protocol engine and place it in a sata spinup hold state */ scu_sas_pcfg_value = - readl(&this_phy->link_layer_registers->phy_configuration); - scu_sas_pcfg_value |= ( - SCU_SAS_PCFG_GEN_BIT(OOB_RESET) - | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) - | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) - ); + readl(&sci_phy->link_layer_registers->phy_configuration); + scu_sas_pcfg_value |= + (SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | + SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) | + SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD)); writel(scu_sas_pcfg_value, - &this_phy->link_layer_registers->phy_configuration); + &sci_phy->link_layer_registers->phy_configuration); /* Disable the notify enable spinup primitives */ - enable_spinup_value = readl(&this_phy->link_layer_registers->notify_enable_spinup_control); + enable_spinup_value = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE); - writel(enable_spinup_value, &this_phy->link_layer_registers->notify_enable_spinup_control); + writel(enable_spinup_value, &sci_phy->link_layer_registers->notify_enable_spinup_control); } /** @@ -2150,17 +2154,18 @@ static void scu_link_layer_stop_protocol_engine( * This method will start the OOB/SN state machine for this struct scic_sds_phy object. */ static void scu_link_layer_start_oob( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { u32 scu_sas_pcfg_value; scu_sas_pcfg_value = - readl(&this_phy->link_layer_registers->phy_configuration); + readl(&sci_phy->link_layer_registers->phy_configuration); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); scu_sas_pcfg_value &= - ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); + ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | + SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); writel(scu_sas_pcfg_value, - &this_phy->link_layer_registers->phy_configuration); + &sci_phy->link_layer_registers->phy_configuration); } /** @@ -2172,7 +2177,7 @@ static void scu_link_layer_start_oob( * hard reset bit set. */ static void scu_link_layer_tx_hard_reset( - struct scic_sds_phy *this_phy) + struct scic_sds_phy *sci_phy) { u32 phy_configuration_value; @@ -2180,17 +2185,18 @@ static void scu_link_layer_tx_hard_reset( * SAS Phys must wait for the HARD_RESET_TX event notification to transition * to the starting state. */ phy_configuration_value = - readl(&this_phy->link_layer_registers->phy_configuration); + readl(&sci_phy->link_layer_registers->phy_configuration); phy_configuration_value |= - (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); + (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | + SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); writel(phy_configuration_value, - &this_phy->link_layer_registers->phy_configuration); + &sci_phy->link_layer_registers->phy_configuration); /* Now take the OOB state machine out of reset */ phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); writel(phy_configuration_value, - &this_phy->link_layer_registers->phy_configuration); + &sci_phy->link_layer_registers->phy_configuration); } /* @@ -2209,11 +2215,11 @@ static void scu_link_layer_tx_hard_reset( static void scic_sds_phy_initial_state_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; - scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_INITIAL); + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_INITIAL); } /** @@ -2273,28 +2279,28 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) static void scic_sds_phy_starting_state_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; - scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STARTING); + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STARTING); - scu_link_layer_stop_protocol_engine(this_phy); - scu_link_layer_start_oob(this_phy); + scu_link_layer_stop_protocol_engine(sci_phy); + scu_link_layer_start_oob(sci_phy); /* We don't know what kind of phy we are going to be just yet */ - this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; - this_phy->bcn_received_while_port_unassigned = false; + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; + sci_phy->bcn_received_while_port_unassigned = false; /* Change over to the starting substate machine to continue */ - sci_base_state_machine_start(&this_phy->starting_substate_machine); + sci_base_state_machine_start(&sci_phy->starting_substate_machine); - if (this_phy->state_machine.previous_state_id + if (sci_phy->state_machine.previous_state_id == SCI_BASE_PHY_STATE_READY) { scic_sds_controller_link_down( - scic_sds_phy_get_controller(this_phy), - scic_sds_phy_get_port(this_phy), - this_phy + scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy ); } } @@ -2312,16 +2318,16 @@ static void scic_sds_phy_starting_state_enter( static void scic_sds_phy_ready_state_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; - scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_READY); + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_READY); scic_sds_controller_link_up( - scic_sds_phy_get_controller(this_phy), - scic_sds_phy_get_port(this_phy), - this_phy + scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy ); } @@ -2336,11 +2342,11 @@ static void scic_sds_phy_ready_state_enter( static void scic_sds_phy_ready_state_exit( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; - scic_sds_phy_suspend(this_phy); + scic_sds_phy_suspend(sci_phy); } /** @@ -2354,26 +2360,28 @@ static void scic_sds_phy_ready_state_exit( static void scic_sds_phy_resetting_state_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; - scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_RESETTING); + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_RESETTING); /* * The phy is being reset, therefore deactivate it from the port. * In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_deactivate_phy(this_phy->owning_port, this_phy, false); + scic_sds_port_deactivate_phy(sci_phy->owning_port, sci_phy, false); - if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { - scu_link_layer_tx_hard_reset(this_phy); + if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + scu_link_layer_tx_hard_reset(sci_phy); } else { /* - * The SCU does not need to have a discrete reset state so just go back to - * the starting state. */ - sci_base_state_machine_change_state(&this_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + * The SCU does not need to have a discrete reset state so + * just go back to the starting state. + */ + sci_base_state_machine_change_state( + &sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); } } @@ -2388,11 +2396,11 @@ static void scic_sds_phy_resetting_state_enter( static void scic_sds_phy_final_state_enter( struct sci_base_object *object) { - struct scic_sds_phy *this_phy; + struct scic_sds_phy *sci_phy; - this_phy = (struct scic_sds_phy *)object; + sci_phy = (struct scic_sds_phy *)object; - scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_FINAL); + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_FINAL); /* Nothing to do here */ } diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 40c1297849f3..a8d7e51bdf7b 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -75,7 +75,7 @@ /** * - * @this_port: This is the port object to which the phy is being assigned. + * @sci_port: This is the port object to which the phy is being assigned. * @phy_index: This is the phy index that is being assigned to the port. * * This method will return a true value if the specified phy can be assigned to @@ -90,30 +90,30 @@ * port */ bool scic_sds_port_is_valid_phy_assignment( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, u32 phy_index) { /* Initialize to invalid value. */ u32 existing_phy_index = SCI_MAX_PHYS; u32 index; - if ((this_port->physical_port_index == 1) && (phy_index != 1)) { + if ((sci_port->physical_port_index == 1) && (phy_index != 1)) { return false; } - if (this_port->physical_port_index == 3 && phy_index != 3) { + if (sci_port->physical_port_index == 3 && phy_index != 3) { return false; } if ( - (this_port->physical_port_index == 2) + (sci_port->physical_port_index == 2) && ((phy_index == 0) || (phy_index == 1)) ) { return false; } for (index = 0; index < SCI_MAX_PHYS; index++) { - if ((this_port->phy_table[index] != NULL) + if ((sci_port->phy_table[index] != NULL) && (index != phy_index)) { existing_phy_index = index; } @@ -124,9 +124,9 @@ bool scic_sds_port_is_valid_phy_assignment( * operating at the same maximum link rate. */ if ( (existing_phy_index < SCI_MAX_PHYS) - && (this_port->owning_controller->user_parameters.sds1.phys[ + && (sci_port->owning_controller->user_parameters.sds1.phys[ phy_index].max_speed_generation != - this_port->owning_controller->user_parameters.sds1.phys[ + sci_port->owning_controller->user_parameters.sds1.phys[ existing_phy_index].max_speed_generation) ) return false; @@ -137,13 +137,13 @@ bool scic_sds_port_is_valid_phy_assignment( /** * This method requests a list (mask) of the phys contained in the supplied SAS * port. - * @this_port: a handle corresponding to the SAS port for which to return the + * @sci_port: a handle corresponding to the SAS port for which to return the * phy mask. * * Return a bit mask indicating which phys are a part of this port. Each bit * corresponds to a phy identifier (e.g. bit 0 = phy id 0). */ -static u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) +static u32 scic_sds_port_get_phys(struct scic_sds_port *sci_port) { u32 index; u32 mask; @@ -151,7 +151,7 @@ static u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) mask = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (this_port->phy_table[index] != NULL) { + if (sci_port->phy_table[index] != NULL) { mask |= (1 << index); } } @@ -161,7 +161,7 @@ static u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) /** * - * @this_port: This is the port object for which to determine if the phy mask + * @sci_port: This is the port object for which to determine if the phy mask * can be supported. * * This method will return a true value if the port's phy mask can be supported @@ -172,25 +172,25 @@ static u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) * port false if this is not a valid phy assignment for the port */ static bool scic_sds_port_is_phy_mask_valid( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, u32 phy_mask) { - if (this_port->physical_port_index == 0) { + if (sci_port->physical_port_index == 0) { if (((phy_mask & 0x0F) == 0x0F) || ((phy_mask & 0x03) == 0x03) || ((phy_mask & 0x01) == 0x01) || (phy_mask == 0)) return true; - } else if (this_port->physical_port_index == 1) { + } else if (sci_port->physical_port_index == 1) { if (((phy_mask & 0x02) == 0x02) || (phy_mask == 0)) return true; - } else if (this_port->physical_port_index == 2) { + } else if (sci_port->physical_port_index == 2) { if (((phy_mask & 0x0C) == 0x0C) || ((phy_mask & 0x04) == 0x04) || (phy_mask == 0)) return true; - } else if (this_port->physical_port_index == 3) { + } else if (sci_port->physical_port_index == 3) { if (((phy_mask & 0x08) == 0x08) || (phy_mask == 0)) return true; @@ -201,7 +201,7 @@ static bool scic_sds_port_is_phy_mask_valid( /** * - * @this_port: This parameter specifies the port from which to return a + * @sci_port: This parameter specifies the port from which to return a * connected phy. * * This method retrieves a currently active (i.e. connected) phy contained in @@ -212,7 +212,7 @@ static bool scic_sds_port_is_phy_mask_valid( * object that is active in the port. */ static struct scic_sds_phy *scic_sds_port_get_a_connected_phy( - struct scic_sds_port *this_port + struct scic_sds_port *sci_port ) { u32 index; struct scic_sds_phy *phy; @@ -221,10 +221,10 @@ static struct scic_sds_phy *scic_sds_port_get_a_connected_phy( /* * Ensure that the phy is both part of the port and currently * connected to the remote end-point. */ - phy = this_port->phy_table[index]; + phy = sci_port->phy_table[index]; if ( (phy != NULL) - && scic_sds_port_active_phy(this_port, phy) + && scic_sds_port_active_phy(sci_port, phy) ) { return phy; } @@ -304,50 +304,50 @@ static enum sci_status scic_sds_port_clear_phy( /** * scic_sds_port_add_phy() - - * @this_port: This parameter specifies the port in which the phy will be added. - * @the_phy: This parameter is the phy which is to be added to the port. + * @sci_port: This parameter specifies the port in which the phy will be added. + * @sci_phy: This parameter is the phy which is to be added to the port. * * This method will add a PHY to the selected port. This method returns an * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status * is failre to add the phy to the port. */ enum sci_status scic_sds_port_add_phy( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - return this_port->state_handlers->add_phy_handler( - this_port, the_phy); + return sci_port->state_handlers->add_phy_handler( + sci_port, sci_phy); } /** * scic_sds_port_remove_phy() - - * @this_port: This parameter specifies the port in which the phy will be added. - * @the_phy: This parameter is the phy which is to be added to the port. + * @sci_port: This parameter specifies the port in which the phy will be added. + * @sci_phy: This parameter is the phy which is to be added to the port. * * This method will remove the PHY from the selected PORT. This method returns * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other * status is failre to add the phy to the port. */ enum sci_status scic_sds_port_remove_phy( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - return this_port->state_handlers->remove_phy_handler( - this_port, the_phy); + return sci_port->state_handlers->remove_phy_handler( + sci_port, sci_phy); } /** * This method requests the SAS address for the supplied SAS port from the SCI * implementation. - * @this_port: a handle corresponding to the SAS port for which to return the + * @sci_port: a handle corresponding to the SAS port for which to return the * SAS address. * @sas_address: This parameter specifies a pointer to a SAS address structure * into which the core will copy the SAS address for the port. * */ void scic_sds_port_get_sas_address( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, struct sci_sas_address *sas_address) { u32 index; @@ -356,15 +356,15 @@ void scic_sds_port_get_sas_address( sas_address->low = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (this_port->phy_table[index] != NULL) { - scic_sds_phy_get_sas_address(this_port->phy_table[index], sas_address); + if (sci_port->phy_table[index] != NULL) { + scic_sds_phy_get_sas_address(sci_port->phy_table[index], sas_address); } } } /** * This method will indicate which protocols are supported by this port. - * @this_port: a handle corresponding to the SAS port for which to return the + * @sci_port: a handle corresponding to the SAS port for which to return the * supported protocols. * @protocols: This parameter specifies a pointer to an IAF protocol field * structure into which the core will copy the protocol values for the port. @@ -373,7 +373,7 @@ void scic_sds_port_get_sas_address( * */ static void scic_sds_port_get_protocols( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, struct sci_sas_identify_address_frame_protocols *protocols) { u8 index; @@ -381,8 +381,8 @@ static void scic_sds_port_get_protocols( protocols->u.all = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (this_port->phy_table[index] != NULL) { - scic_sds_phy_get_protocols(this_port->phy_table[index], protocols); + if (sci_port->phy_table[index] != NULL) { + scic_sds_phy_get_protocols(sci_port->phy_table[index], protocols); } } } @@ -390,7 +390,7 @@ static void scic_sds_port_get_protocols( /** * This method requests the SAS address for the device directly attached to * this SAS port. - * @this_port: a handle corresponding to the SAS port for which to return the + * @sci_port: a handle corresponding to the SAS port for which to return the * SAS address. * @sas_address: This parameter specifies a pointer to a SAS address structure * into which the core will copy the SAS address for the device directly @@ -398,7 +398,7 @@ static void scic_sds_port_get_protocols( * */ void scic_sds_port_get_attached_sas_address( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, struct sci_sas_address *sas_address) { struct sci_sas_identify_address_frame_protocols protocols; @@ -407,7 +407,7 @@ void scic_sds_port_get_attached_sas_address( /* * Ensure that the phy is both part of the port and currently * connected to the remote end-point. */ - phy = scic_sds_port_get_a_connected_phy(this_port); + phy = scic_sds_port_get_a_connected_phy(sci_port); if (phy != NULL) { scic_sds_phy_get_attached_phy_protocols(phy, &protocols); @@ -426,7 +426,7 @@ void scic_sds_port_get_attached_sas_address( /** * This method will indicate which protocols are supported by this remote * device. - * @this_port: a handle corresponding to the SAS port for which to return the + * @sci_port: a handle corresponding to the SAS port for which to return the * supported protocols. * @protocols: This parameter specifies a pointer to an IAF protocol field * structure into which the core will copy the protocol values for the port. @@ -435,7 +435,7 @@ void scic_sds_port_get_attached_sas_address( * */ void scic_sds_port_get_attached_protocols( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, struct sci_sas_identify_address_frame_protocols *protocols) { struct scic_sds_phy *phy; @@ -443,7 +443,7 @@ void scic_sds_port_get_attached_protocols( /* * Ensure that the phy is both part of the port and currently * connected to the remote end-point. */ - phy = scic_sds_port_get_a_connected_phy(this_port); + phy = scic_sds_port_get_a_connected_phy(sci_port); if (phy != NULL) scic_sds_phy_get_attached_phy_protocols(phy, protocols); else @@ -548,7 +548,7 @@ static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port * This method performs initialization of the supplied port. Initialization * includes: - state machine initialization - member variable initialization * - configuring the phy_mask - * @this_port: + * @sci_port: * @transport_layer_registers: * @port_task_scheduler_registers: * @port_configuration_regsiter: @@ -557,14 +557,14 @@ static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port * if the phy being added to the port */ enum sci_status scic_sds_port_initialize( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, void __iomem *port_task_scheduler_registers, void __iomem *port_configuration_regsiter, void __iomem *viit_registers) { - this_port->port_task_scheduler_registers = port_task_scheduler_registers; - this_port->port_pe_configuration_register = port_configuration_regsiter; - this_port->viit_registers = viit_registers; + sci_port->port_task_scheduler_registers = port_task_scheduler_registers; + sci_port->port_pe_configuration_register = port_configuration_regsiter; + sci_port->viit_registers = viit_registers; return SCI_SUCCESS; } @@ -622,27 +622,27 @@ enum sci_status scic_port_hard_reset( /** * This method assigns the direct attached device ID for this port. * - * @param[in] this_port The port for which the direct attached device id is to + * @param[in] sci_port The port for which the direct attached device id is to * be assigned. * @param[in] device_id The direct attached device ID to assign to the port. * This will be the RNi for the device */ void scic_sds_port_setup_transports( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, u32 device_id) { u8 index; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (this_port->active_phy_mask & (1 << index)) - scic_sds_phy_setup_transport(this_port->phy_table[index], device_id); + if (sci_port->active_phy_mask & (1 << index)) + scic_sds_phy_setup_transport(sci_port->phy_table[index], device_id); } } /** * - * @this_port: This is the port on which the phy should be enabled. - * @the_phy: This is the specific phy which to enable. + * @sci_port: This is the port on which the phy should be enabled. + * @sci_phy: This is the specific phy which to enable. * @do_notify_user: This parameter specifies whether to inform the user (via * scic_cb_port_link_up()) as to the fact that a new phy as become ready. * @@ -696,8 +696,8 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, /** * - * @this_port: This is the port on which the phy should be disabled. - * @the_phy: This is the specific phy which to disabled. + * @sci_port: This is the port on which the phy should be disabled. + * @sci_phy: This is the specific phy which to disabled. * * This function will disable the phy and report that the phy is not valid for * this port object. None @@ -766,18 +766,18 @@ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port * This method returns false if the port only has a single phy object assigned. * If there are no phys or more than one phy then the method will return * true. - * @this_port: The port for which the wide port condition is to be checked. + * @sci_port: The port for which the wide port condition is to be checked. * * bool true Is returned if this is a wide ported port. false Is returned if * this is a narrow port. */ -static bool scic_sds_port_is_wide(struct scic_sds_port *this_port) +static bool scic_sds_port_is_wide(struct scic_sds_port *sci_port) { u32 index; u32 phy_count = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (this_port->phy_table[index] != NULL) { + if (sci_port->phy_table[index] != NULL) { phy_count++; } } @@ -790,8 +790,8 @@ static bool scic_sds_port_is_wide(struct scic_sds_port *this_port) * port wants the PHY to continue on to the link up state then the port * layer must return true. If the port object returns false the phy object * must halt its attempt to go link up. - * @this_port: The port associated with the phy object. - * @the_phy: The phy object that is trying to go link up. + * @sci_port: The port associated with the phy object. + * @sci_phy: The phy object that is trying to go link up. * * true if the phy object can continue to the link up condition. true Is * returned if this phy can continue to the ready state. false Is returned if @@ -800,19 +800,19 @@ static bool scic_sds_port_is_wide(struct scic_sds_port *this_port) * devices this could become an invalid port configuration. */ bool scic_sds_port_link_detected( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { struct sci_sas_identify_address_frame_protocols protocols; - scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols); + scic_sds_phy_get_attached_phy_protocols(sci_phy, &protocols); if ( - (this_port->logical_port_index != SCIC_SDS_DUMMY_PORT) + (sci_port->logical_port_index != SCIC_SDS_DUMMY_PORT) && (protocols.u.bits.stp_target) - && scic_sds_port_is_wide(this_port) + && scic_sds_port_is_wide(sci_port) ) { - scic_sds_port_invalid_link_up(this_port, the_phy); + scic_sds_port_invalid_link_up(sci_port, sci_phy); return false; } @@ -823,65 +823,65 @@ bool scic_sds_port_link_detected( /** * This method is the entry point for the phy to inform the port that it is now * in a ready state - * @this_port: + * @sci_port: * * */ void scic_sds_port_link_up( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - the_phy->is_in_link_training = false; + sci_phy->is_in_link_training = false; - this_port->state_handlers->link_up_handler(this_port, the_phy); + sci_port->state_handlers->link_up_handler(sci_port, sci_phy); } /** * This method is the entry point for the phy to inform the port that it is no * longer in a ready state - * @this_port: + * @sci_port: * * */ void scic_sds_port_link_down( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - this_port->state_handlers->link_down_handler(this_port, the_phy); + sci_port->state_handlers->link_down_handler(sci_port, sci_phy); } /** * This method is called to start an IO request on this port. - * @this_port: - * @the_device: - * @the_io_request: + * @sci_port: + * @sci_dev: + * @sci_req: * * enum sci_status */ enum sci_status scic_sds_port_start_io( - struct scic_sds_port *this_port, - struct scic_sds_remote_device *the_device, - struct scic_sds_request *the_io_request) + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) { - return this_port->state_handlers->start_io_handler( - this_port, the_device, the_io_request); + return sci_port->state_handlers->start_io_handler( + sci_port, sci_dev, sci_req); } /** * This method is called to complete an IO request to the port. - * @this_port: - * @the_device: - * @the_io_request: + * @sci_port: + * @sci_dev: + * @sci_req: * * enum sci_status */ enum sci_status scic_sds_port_complete_io( - struct scic_sds_port *this_port, - struct scic_sds_remote_device *the_device, - struct scic_sds_request *the_io_request) + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) { - return this_port->state_handlers->complete_io_handler( - this_port, the_device, the_io_request); + return sci_port->state_handlers->complete_io_handler( + sci_port, sci_dev, sci_req); } /** @@ -945,40 +945,40 @@ static void scic_sds_port_timeout_handler(void *port) * * */ -static void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port) +static void scic_sds_port_update_viit_entry(struct scic_sds_port *sci_port) { struct sci_sas_address sas_address; - scic_sds_port_get_sas_address(this_port, &sas_address); + scic_sds_port_get_sas_address(sci_port, &sas_address); writel(sas_address.high, - &this_port->viit_registers->initiator_sas_address_hi); + &sci_port->viit_registers->initiator_sas_address_hi); writel(sas_address.low, - &this_port->viit_registers->initiator_sas_address_lo); + &sci_port->viit_registers->initiator_sas_address_lo); /* This value get cleared just in case its not already cleared */ - writel(0, &this_port->viit_registers->reserved); + writel(0, &sci_port->viit_registers->reserved); /* We are required to update the status register last */ writel(SCU_VIIT_ENTRY_ID_VIIT | SCU_VIIT_IPPT_INITIATOR | - ((1 << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) | + ((1 << sci_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) | SCU_VIIT_STATUS_ALL_VALID, - &this_port->viit_registers->status); + &sci_port->viit_registers->status); } /** * This method returns the maximum allowed speed for data transfers on this * port. This maximum allowed speed evaluates to the maximum speed of the * slowest phy in the port. - * @this_port: This parameter specifies the port for which to retrieve the + * @sci_port: This parameter specifies the port for which to retrieve the * maximum allowed speed. * * This method returns the maximum negotiated speed of the slowest phy in the * port. */ enum sas_linkrate scic_sds_port_get_max_allowed_speed( - struct scic_sds_port *this_port) + struct scic_sds_port *sci_port) { u16 index; enum sas_linkrate max_allowed_speed = SAS_LINK_RATE_6_0_GBPS; @@ -988,10 +988,10 @@ enum sas_linkrate scic_sds_port_get_max_allowed_speed( * Loop through all of the phys in this port and find the phy with the * lowest maximum link rate. */ for (index = 0; index < SCI_MAX_PHYS; index++) { - phy = this_port->phy_table[index]; + phy = sci_port->phy_table[index]; if ( (phy != NULL) - && (scic_sds_port_active_phy(this_port, phy) == true) + && (scic_sds_port_active_phy(sci_port, phy) == true) && (phy->max_negotiated_speed < max_allowed_speed) ) max_allowed_speed = phy->max_negotiated_speed; @@ -1003,8 +1003,8 @@ enum sas_linkrate scic_sds_port_get_max_allowed_speed( /** * This method passes the event to core user. - * @this_port: The port that a BCN happens. - * @this_phy: The phy that receives BCN. + * @sci_port: The port that a BCN happens. + * @sci_phy: The phy that receives BCN. * */ void scic_sds_port_broadcast_change_received( @@ -1022,7 +1022,7 @@ void scic_sds_port_broadcast_change_received( /** * This API methhod enables the broadcast change notification from underneath * hardware. - * @this_port: The port that a BCN had been disabled from. + * @sci_port: The port that a BCN had been disabled from. * */ void scic_port_enable_broadcast_change_notification( @@ -1134,25 +1134,25 @@ static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( /** * - * @this_port: This is the struct scic_sds_port object that which has a phy that has + * @sci_port: This is the struct scic_sds_port object that which has a phy that has * gone link up. - * @the_phy: This is the struct scic_sds_phy object that has gone link up. + * @sci_phy: This is the struct scic_sds_phy object that has gone link up. * * This method is the ready waiting substate link up handler for the * struct scic_sds_port object. This methos will report the link up condition for * this port and will transition to the ready operational substate. none */ static void scic_sds_port_ready_waiting_substate_link_up_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { /* * Since this is the first phy going link up for the port we can just enable * it and continue. */ - scic_sds_port_activate_phy(this_port, the_phy, true); + scic_sds_port_activate_phy(sci_port, sci_phy, true); sci_base_state_machine_change_state( - &this_port->ready_substate_machine, + &sci_port->ready_substate_machine, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL ); } @@ -1224,19 +1224,19 @@ sci_status scic_sds_port_ready_operational_substate_reset_handler( /** * scic_sds_port_ready_operational_substate_link_up_handler() - - * @this_port: This is the struct scic_sds_port object that which has a phy that has + * @sci_port: This is the struct scic_sds_port object that which has a phy that has * gone link up. - * @the_phy: This is the struct scic_sds_phy object that has gone link up. + * @sci_phy: This is the struct scic_sds_phy object that has gone link up. * * This method is the ready operational substate link up handler for the * struct scic_sds_port object. This function notifies the SCI User that the phy has * gone link up. none */ static void scic_sds_port_ready_operational_substate_link_up_handler( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy) + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - scic_sds_port_general_link_up_handler(this_port, the_phy, true); + scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); } /** @@ -1534,7 +1534,7 @@ scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = /** * - * @this_port: This is the struct scic_sds_port object to suspend. + * @sci_port: This is the struct scic_sds_port object to suspend. * * This method will susped the port task scheduler for this port object. none */ @@ -1602,7 +1602,7 @@ static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) /** * - * @this_port: This is the struct scic_sds_port object to resume. + * @sci_port: This is the struct scic_sds_port object to resume. * * This method will resume the port task scheduler for this port object. none */ @@ -1633,20 +1633,20 @@ scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) static void scic_sds_port_ready_substate_waiting_enter( struct sci_base_object *object) { - struct scic_sds_port *this_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; scic_sds_port_set_ready_state_handlers( - this_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING + sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING ); - scic_sds_port_suspend_port_task_scheduler(this_port); + scic_sds_port_suspend_port_task_scheduler(sci_port); - this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; + sci_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; - if (this_port->active_phy_mask != 0) { + if (sci_port->active_phy_mask != 0) { /* At least one of the phys on the port is ready */ sci_base_state_machine_change_state( - &this_port->ready_substate_machine, + &sci_port->ready_substate_machine, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL ); } @@ -1766,9 +1766,9 @@ static void scic_sds_port_ready_substate_configuring_enter( static void scic_sds_port_ready_substate_configuring_exit( struct sci_base_object *object) { - struct scic_sds_port *this_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = (struct scic_sds_port *)object; - scic_sds_port_suspend_port_task_scheduler(this_port); + scic_sds_port_suspend_port_task_scheduler(sci_port); } /* --------------------------------------------------------------------------- */ @@ -2160,7 +2160,7 @@ scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = /** * - * @this_port: This is the port object which to suspend. + * @sci_port: This is the port object which to suspend. * * This method will enable the SCU Port Task Scheduler for this port object but * will leave the port task scheduler in a suspended state. none @@ -2177,7 +2177,7 @@ scic_sds_port_enable_port_task_scheduler(struct scic_sds_port *port) /** * - * @this_port: This is the port object which to resume. + * @sci_port: This is the port object which to resume. * * This method will disable the SCU port task scheduler for this port object. * none @@ -2263,23 +2263,23 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci static void scic_sds_port_stopped_state_enter( struct sci_base_object *object) { - struct scic_sds_port *this_port; + struct scic_sds_port *sci_port; - this_port = (struct scic_sds_port *)object; + sci_port = (struct scic_sds_port *)object; scic_sds_port_set_base_state_handlers( - this_port, SCI_BASE_PORT_STATE_STOPPED + sci_port, SCI_BASE_PORT_STATE_STOPPED ); if ( SCI_BASE_PORT_STATE_STOPPING - == this_port->state_machine.previous_state_id + == sci_port->state_machine.previous_state_id ) { /* * If we enter this state becasuse of a request to stop * the port then we want to disable the hardwares port * task scheduler. */ - scic_sds_port_disable_port_task_scheduler(this_port); + scic_sds_port_disable_port_task_scheduler(sci_port); } } @@ -2294,12 +2294,12 @@ static void scic_sds_port_stopped_state_enter( static void scic_sds_port_stopped_state_exit( struct sci_base_object *object) { - struct scic_sds_port *this_port; + struct scic_sds_port *sci_port; - this_port = (struct scic_sds_port *)object; + sci_port = (struct scic_sds_port *)object; /* Enable and suspend the port task scheduler */ - scic_sds_port_enable_port_task_scheduler(this_port); + scic_sds_port_enable_port_task_scheduler(sci_port); } /** @@ -2360,12 +2360,12 @@ static void scic_sds_port_ready_state_exit(struct sci_base_object *object) static void scic_sds_port_resetting_state_enter( struct sci_base_object *object) { - struct scic_sds_port *this_port; + struct scic_sds_port *sci_port; - this_port = (struct scic_sds_port *)object; + sci_port = (struct scic_sds_port *)object; scic_sds_port_set_base_state_handlers( - this_port, SCI_BASE_PORT_STATE_RESETTING + sci_port, SCI_BASE_PORT_STATE_RESETTING ); } @@ -2397,12 +2397,12 @@ static inline void scic_sds_port_resetting_state_exit( static void scic_sds_port_stopping_state_enter( struct sci_base_object *object) { - struct scic_sds_port *this_port; + struct scic_sds_port *sci_port; - this_port = (struct scic_sds_port *)object; + sci_port = (struct scic_sds_port *)object; scic_sds_port_set_base_state_handlers( - this_port, SCI_BASE_PORT_STATE_STOPPING + sci_port, SCI_BASE_PORT_STATE_STOPPING ); } diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index c7741e81336e..964e3885dbf2 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -378,77 +378,77 @@ static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *s (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) void scic_sds_port_construct( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, u8 port_index, - struct scic_sds_controller *owning_controller); + struct scic_sds_controller *scic); enum sci_status scic_sds_port_initialize( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, void __iomem *port_task_scheduler_registers, void __iomem *port_configuration_regsiter, void __iomem *viit_registers); enum sci_status scic_sds_port_add_phy( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy); + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); enum sci_status scic_sds_port_remove_phy( - struct scic_sds_port *this_port, - struct scic_sds_phy *the_phy); + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); void scic_sds_port_setup_transports( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, u32 device_id); void scic_sds_port_deactivate_phy( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, bool do_notify_user); bool scic_sds_port_link_detected( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy); + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); void scic_sds_port_link_up( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy); + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); void scic_sds_port_link_down( - struct scic_sds_port *this_port, - struct scic_sds_phy *phy); + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); enum sci_status scic_sds_port_start_io( - struct scic_sds_port *this_port, - struct scic_sds_remote_device *the_device, - struct scic_sds_request *the_io_request); + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req); enum sci_status scic_sds_port_complete_io( - struct scic_sds_port *this_port, - struct scic_sds_remote_device *the_device, - struct scic_sds_request *the_io_request); + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req); enum sas_linkrate scic_sds_port_get_max_allowed_speed( - struct scic_sds_port *this_port); + struct scic_sds_port *sci_port); void scic_sds_port_broadcast_change_received( - struct scic_sds_port *this_port, - struct scic_sds_phy *this_phy); + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); bool scic_sds_port_is_valid_phy_assignment( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, u32 phy_index); void scic_sds_port_get_sas_address( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, struct sci_sas_address *sas_address); void scic_sds_port_get_attached_sas_address( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, struct sci_sas_address *sas_address); void scic_sds_port_get_attached_protocols( - struct scic_sds_port *this_port, + struct scic_sds_port *sci_port, struct sci_sas_identify_address_frame_protocols *protocols); #endif /* _SCIC_SDS_PORT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 0976faeb4064..fa7828d4d975 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -149,17 +149,17 @@ enum sci_status scic_remote_device_da_construct( static void scic_sds_remote_device_get_info_from_smp_discover_response( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, struct smp_response_discover *discover_response) { - /* decode discover_response to set sas_address to this_device. */ - this_device->device_address.high = + /* decode discover_response to set sas_address to sci_dev. */ + sci_dev->device_address.high = discover_response->attached_sas_address.high; - this_device->device_address.low = + sci_dev->device_address.low = discover_response->attached_sas_address.low; - this_device->target_protocols.u.all = discover_response->protocols.u.all; + sci_dev->target_protocols.u.all = discover_response->protocols.u.all; } @@ -168,15 +168,15 @@ enum sci_status scic_remote_device_ea_construct( struct smp_response_discover *discover_response) { enum sci_status status; - struct scic_sds_controller *the_controller; + struct scic_sds_controller *scic; - the_controller = scic_sds_port_get_controller(sci_dev->owning_port); + scic = scic_sds_port_get_controller(sci_dev->owning_port); scic_sds_remote_device_get_info_from_smp_discover_response( sci_dev, discover_response); status = scic_sds_controller_allocate_remote_node_context( - the_controller, sci_dev, &sci_dev->rnc->remote_node_index); + scic, sci_dev, &sci_dev->rnc->remote_node_index); if (status == SCI_SUCCESS) { if (sci_dev->target_protocols.u.bits.attached_ssp_target) { @@ -294,32 +294,32 @@ bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev) /** * - * @this_device: The remote device for which the suspend is being requested. + * @sci_dev: The remote device for which the suspend is being requested. * * This method invokes the remote device suspend state handler. enum sci_status */ enum sci_status scic_sds_remote_device_suspend( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 suspend_type) { - return this_device->state_handlers->suspend_handler(this_device, suspend_type); + return sci_dev->state_handlers->suspend_handler(sci_dev, suspend_type); } /** * - * @this_device: The remote device for which the resume is being requested. + * @sci_dev: The remote device for which the resume is being requested. * * This method invokes the remote device resume state handler. enum sci_status */ enum sci_status scic_sds_remote_device_resume( - struct scic_sds_remote_device *this_device) + struct scic_sds_remote_device *sci_dev) { - return this_device->state_handlers->resume_handler(this_device); + return sci_dev->state_handlers->resume_handler(sci_dev); } /** * - * @this_device: The remote device for which the event handling is being + * @sci_dev: The remote device for which the event handling is being * requested. * @frame_index: This is the frame index that is being processed. * @@ -327,31 +327,31 @@ enum sci_status scic_sds_remote_device_resume( * enum sci_status */ enum sci_status scic_sds_remote_device_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index) { - return this_device->state_handlers->frame_handler(this_device, frame_index); + return sci_dev->state_handlers->frame_handler(sci_dev, frame_index); } /** * - * @this_device: The remote device for which the event handling is being + * @sci_dev: The remote device for which the event handling is being * requested. * @event_code: This is the event code that is to be processed. * * This method invokes the remote device event handler. enum sci_status */ enum sci_status scic_sds_remote_device_event_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code) { - return this_device->state_handlers->event_handler(this_device, event_code); + return sci_dev->state_handlers->event_handler(sci_dev, event_code); } /** * * @controller: The controller that is starting the io request. - * @this_device: The remote device for which the start io handling is being + * @sci_dev: The remote device for which the start io handling is being * requested. * @io_request: The io request that is being started. * @@ -359,17 +359,17 @@ enum sci_status scic_sds_remote_device_event_handler( */ enum sci_status scic_sds_remote_device_start_io( struct scic_sds_controller *controller, - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *io_request) { - return this_device->state_handlers->start_io_handler( - this_device, io_request); + return sci_dev->state_handlers->start_io_handler( + sci_dev, io_request); } /** * * @controller: The controller that is completing the io request. - * @this_device: The remote device for which the complete io handling is being + * @sci_dev: The remote device for which the complete io handling is being * requested. * @io_request: The io request that is being completed. * @@ -377,17 +377,17 @@ enum sci_status scic_sds_remote_device_start_io( */ enum sci_status scic_sds_remote_device_complete_io( struct scic_sds_controller *controller, - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *io_request) { - return this_device->state_handlers->complete_io_handler( - this_device, io_request); + return sci_dev->state_handlers->complete_io_handler( + sci_dev, io_request); } /** * * @controller: The controller that is starting the task request. - * @this_device: The remote device for which the start task handling is being + * @sci_dev: The remote device for which the start task handling is being * requested. * @io_request: The task request that is being started. * @@ -395,17 +395,17 @@ enum sci_status scic_sds_remote_device_complete_io( */ enum sci_status scic_sds_remote_device_start_task( struct scic_sds_controller *controller, - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *io_request) { - return this_device->state_handlers->start_task_handler( - this_device, io_request); + return sci_dev->state_handlers->start_task_handler( + sci_dev, io_request); } /** * * @controller: The controller that is completing the task request. - * @this_device: The remote device for which the complete task handling is + * @sci_dev: The remote device for which the complete task handling is * being requested. * @io_request: The task request that is being completed. * @@ -414,22 +414,22 @@ enum sci_status scic_sds_remote_device_start_task( /** * - * @this_device: + * @sci_dev: * @request: * * This method takes the request and bulids an appropriate SCU context for the * request and then requests the controller to post the request. none */ void scic_sds_remote_device_post_request( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 request) { u32 context; - context = scic_sds_remote_device_build_command_context(this_device, request); + context = scic_sds_remote_device_build_command_context(sci_dev, request); scic_sds_controller_post_request( - scic_sds_remote_device_get_controller(this_device), + scic_sds_remote_device_get_controller(sci_dev), context ); } @@ -437,22 +437,22 @@ void scic_sds_remote_device_post_request( #if !defined(DISABLE_ATAPI) /** * - * @this_device: The device to be checked. + * @sci_dev: The device to be checked. * * This method check the signature fis of a stp device to decide whether a * device is atapi or not. true if a device is atapi device. False if a device * is not atapi. */ bool scic_sds_remote_device_is_atapi( - struct scic_sds_remote_device *this_device) + struct scic_sds_remote_device *sci_dev) { - if (!this_device->target_protocols.u.bits.attached_stp_target) + if (!sci_dev->target_protocols.u.bits.attached_stp_target) return false; - else if (this_device->is_direct_attached) { + else if (sci_dev->is_direct_attached) { struct scic_sds_phy *phy; struct scic_sata_phy_properties properties; struct sata_fis_reg_d2h *signature_fis; - phy = scic_sds_port_get_a_connected_phy(this_device->owning_port); + phy = scic_sds_port_get_a_connected_phy(sci_dev->owning_port); scic_sata_phy_get_properties(phy, &properties); /* decode the signature fis. */ @@ -506,16 +506,16 @@ static void scic_sds_cb_remote_device_rnc_destruct_complete( static void scic_sds_remote_device_resume_complete_handler( void *user_parameter) { - struct scic_sds_remote_device *this_device; + struct scic_sds_remote_device *sci_dev; - this_device = (struct scic_sds_remote_device *)user_parameter; + sci_dev = (struct scic_sds_remote_device *)user_parameter; if ( - sci_base_state_machine_get_state(&this_device->state_machine) + sci_base_state_machine_get_state(&sci_dev->state_machine) != SCI_BASE_REMOTE_DEVICE_STATE_READY ) { sci_base_state_machine_change_state( - &this_device->state_machine, + &sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_READY ); } @@ -532,16 +532,16 @@ static void scic_sds_remote_device_resume_complete_handler( * requests and task requests of all types. none */ void scic_sds_remote_device_start_request( - struct scic_sds_remote_device *this_device, - struct scic_sds_request *the_request, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req, enum sci_status status) { /* We still have a fault in starting the io complete it on the port */ if (status == SCI_SUCCESS) - scic_sds_remote_device_increment_request_count(this_device); + scic_sds_remote_device_increment_request_count(sci_dev); else{ - this_device->owning_port->state_handlers->complete_io_handler( - this_device->owning_port, this_device, the_request + sci_dev->owning_port->state_handlers->complete_io_handler( + sci_dev->owning_port, sci_dev, sci_req ); } } @@ -576,7 +576,7 @@ void scic_sds_remote_device_continue_request(void *dev) /** * This method will terminate all of the IO requests in the controllers IO * request table that were targeted for this device. - * @this_device: This parameter specifies the remote device for which to + * @sci_dev: This parameter specifies the remote device for which to * attempt to terminate all requests. * * This method returns an indication as to whether all requests were @@ -584,24 +584,24 @@ void scic_sds_remote_device_continue_request(void *dev) * this method will return the failure. */ static enum sci_status scic_sds_remote_device_terminate_requests( - struct scic_sds_remote_device *this_device) + struct scic_sds_remote_device *sci_dev) { enum sci_status status = SCI_SUCCESS; enum sci_status terminate_status = SCI_SUCCESS; - struct scic_sds_request *the_request; + struct scic_sds_request *sci_req; u32 index; - u32 request_count = this_device->started_request_count; + u32 request_count = sci_dev->started_request_count; for (index = 0; (index < SCI_MAX_IO_REQUESTS) && (request_count > 0); index++) { - the_request = this_device->owning_port->owning_controller->io_request_table[index]; + sci_req = sci_dev->owning_port->owning_controller->io_request_table[index]; - if ((the_request != NULL) && (the_request->target_device == this_device)) { + if ((sci_req != NULL) && (sci_req->target_device == sci_dev)) { terminate_status = scic_controller_terminate_request( - this_device->owning_port->owning_controller, - this_device, - the_request + sci_dev->owning_port->owning_controller, + sci_dev, + sci_req ); if (terminate_status != SCI_SUCCESS) @@ -684,7 +684,7 @@ enum sci_status scic_sds_remote_device_default_resume_handler( * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE */ static enum sci_status scic_sds_remote_device_core_event_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code, bool is_ready_state) { @@ -694,7 +694,7 @@ static enum sci_status scic_sds_remote_device_core_event_handler( case SCU_EVENT_TYPE_RNC_OPS_MISC: case SCU_EVENT_TYPE_RNC_SUSPEND_TX: case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code); + status = scic_sds_remote_node_context_event_handler(sci_dev->rnc, event_code); break; case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: @@ -702,13 +702,13 @@ static enum sci_status scic_sds_remote_device_core_event_handler( status = SCI_SUCCESS; /* Suspend the associated RNC */ - scic_sds_remote_node_context_suspend(this_device->rnc, + scic_sds_remote_node_context_suspend(sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); - dev_dbg(scirdev_to_dev(this_device), + dev_dbg(scirdev_to_dev(sci_dev), "%s: device: %p event code: %x: %s\n", - __func__, this_device, event_code, + __func__, sci_dev, event_code, (is_ready_state) ? "I_T_Nexus_Timeout event" : "I_T_Nexus_Timeout event in wrong state"); @@ -718,9 +718,9 @@ static enum sci_status scic_sds_remote_device_core_event_handler( /* Else, fall through and treat as unhandled... */ default: - dev_dbg(scirdev_to_dev(this_device), + dev_dbg(scirdev_to_dev(sci_dev), "%s: device: %p event code: %x: %s\n", - __func__, this_device, event_code, + __func__, sci_dev, event_code, (is_ready_state) ? "unexpected event" : "unexpected event in wrong state"); @@ -742,10 +742,10 @@ static enum sci_status scic_sds_remote_device_core_event_handler( * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE */ static enum sci_status scic_sds_remote_device_default_event_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code) { - return scic_sds_remote_device_core_event_handler(this_device, + return scic_sds_remote_device_core_event_handler(sci_dev, event_code, false); } @@ -762,20 +762,20 @@ static enum sci_status scic_sds_remote_device_default_event_handler( * SCI_FAILURE_INVALID_STATE */ enum sci_status scic_sds_remote_device_default_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index) { - dev_warn(scirdev_to_dev(this_device), + dev_warn(scirdev_to_dev(sci_dev), "%s: SCIC Remote Device requested to handle frame %x " "while in wrong state %d\n", __func__, frame_index, sci_base_state_machine_get_state( - &this_device->state_machine)); + &sci_dev->state_machine)); /* Return the frame back to the controller */ scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(this_device), frame_index + scic_sds_remote_device_get_controller(sci_dev), frame_index ); return SCI_FAILURE_INVALID_STATE; @@ -815,7 +815,7 @@ enum sci_status scic_sds_remote_device_default_continue_request_handler( * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE */ enum sci_status scic_sds_remote_device_general_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index) { enum sci_status result; @@ -823,22 +823,22 @@ enum sci_status scic_sds_remote_device_general_frame_handler( struct scic_sds_request *io_request; result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_remote_device_get_controller(this_device)->uf_control), + &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), frame_index, (void **)&frame_header ); if (SCI_SUCCESS == result) { io_request = scic_sds_controller_get_io_request_from_tag( - scic_sds_remote_device_get_controller(this_device), frame_header->tag); + scic_sds_remote_device_get_controller(sci_dev), frame_header->tag); if ((io_request == NULL) - || (io_request->target_device != this_device)) { + || (io_request->target_device != sci_dev)) { /* * We could not map this tag to a valid IO request * Just toss the frame and continue */ scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(this_device), frame_index + scic_sds_remote_device_get_controller(sci_dev), frame_index ); } else { /* The IO request is now in charge of releasing the frame */ @@ -852,17 +852,17 @@ enum sci_status scic_sds_remote_device_general_frame_handler( /** * - * @[in]: this_device This is the device object that is receiving the event. + * @[in]: sci_dev This is the device object that is receiving the event. * @[in]: event_code The event code to process. * * This is a common method for handling events reported to the remote device * from the controller object. enum sci_status */ enum sci_status scic_sds_remote_device_general_event_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code) { - return scic_sds_remote_device_core_event_handler(this_device, + return scic_sds_remote_device_core_event_handler(sci_dev, event_code, true); } @@ -1093,7 +1093,7 @@ static enum sci_status scic_sds_remote_device_ready_state_complete_request_handl /** * - * @this_device: The struct scic_sds_remote_device which is cast into a + * @sci_dev: The struct scic_sds_remote_device which is cast into a * struct scic_sds_remote_device. * * This method will stop a struct scic_sds_remote_device that is already in the @@ -1536,10 +1536,10 @@ static void scic_sds_remote_device_ready_state_exit( static void scic_sds_remote_device_stopping_state_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; SET_STATE_HANDLER( - this_device, + sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING ); @@ -1556,10 +1556,10 @@ static void scic_sds_remote_device_stopping_state_enter( static void scic_sds_remote_device_failed_state_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; SET_STATE_HANDLER( - this_device, + sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_FAILED ); @@ -1576,16 +1576,16 @@ static void scic_sds_remote_device_failed_state_enter( static void scic_sds_remote_device_resetting_state_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; SET_STATE_HANDLER( - this_device, + sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_RESETTING ); scic_sds_remote_node_context_suspend( - this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); + sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); } /** @@ -1599,9 +1599,9 @@ static void scic_sds_remote_device_resetting_state_enter( static void scic_sds_remote_device_resetting_state_exit( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL); + scic_sds_remote_node_context_resume(sci_dev->rnc, NULL, NULL); } /** @@ -1615,10 +1615,10 @@ static void scic_sds_remote_device_resetting_state_exit( static void scic_sds_remote_device_final_state_enter( struct sci_base_object *object) { - struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; SET_STATE_HANDLER( - this_device, + sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_FINAL ); diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index ebb0ac8ef3a6..5d3df92212eb 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -350,25 +350,25 @@ typedef enum sci_status (*scic_sds_remote_device_high_priority_request_complete_ enum sci_io_status); typedef enum sci_status (*scic_sds_remote_device_handler_t)( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); typedef enum sci_status (*scic_sds_remote_device_suspend_handler_t)( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 suspend_type); typedef enum sci_status (*scic_sds_remote_device_resume_handler_t)( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); typedef enum sci_status (*scic_sds_remote_device_frame_handler_t)( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index); typedef enum sci_status (*scic_sds_remote_device_event_handler_t)( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code); typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); /** * struct scic_sds_remote_device_state_handler - This structure conains the @@ -461,8 +461,8 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab * * This macro incrments the request count for this device */ -#define scic_sds_remote_device_increment_request_count(this_device) \ - ((this_device)->started_request_count++) +#define scic_sds_remote_device_increment_request_count(sci_dev) \ + ((sci_dev)->started_request_count++) /** * scic_sds_remote_device_decrement_request_count() - @@ -470,33 +470,33 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab * This macro decrements the request count for this device. This count will * never decrment past 0. */ -#define scic_sds_remote_device_decrement_request_count(this_device) \ - ((this_device)->started_request_count > 0 ? \ - (this_device)->started_request_count-- : 0) +#define scic_sds_remote_device_decrement_request_count(sci_dev) \ + ((sci_dev)->started_request_count > 0 ? \ + (sci_dev)->started_request_count-- : 0) /** * scic_sds_remote_device_get_request_count() - * * This is a helper macro to return the current device request count. */ -#define scic_sds_remote_device_get_request_count(this_device) \ - ((this_device)->started_request_count) +#define scic_sds_remote_device_get_request_count(sci_dev) \ + ((sci_dev)->started_request_count) /** * scic_sds_remote_device_get_port() - * * This macro returns the owning port of this remote device obejct. */ -#define scic_sds_remote_device_get_port(this_device) \ - ((this_device)->owning_port) +#define scic_sds_remote_device_get_port(sci_dev) \ + ((sci_dev)->owning_port) /** * scic_sds_remote_device_get_controller() - * * This macro returns the controller object that contains this device object */ -#define scic_sds_remote_device_get_controller(this_device) \ - scic_sds_port_get_controller(scic_sds_remote_device_get_port(this_device)) +#define scic_sds_remote_device_get_controller(sci_dev) \ + scic_sds_port_get_controller(scic_sds_remote_device_get_port(sci_dev)) /** * scic_sds_remote_device_set_state_handlers() - @@ -504,26 +504,26 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab * This macro sets the remote device state handlers pointer and is set on entry * to each device state. */ -#define scic_sds_remote_device_set_state_handlers(this_device, handlers) \ - ((this_device)->state_handlers = (handlers)) +#define scic_sds_remote_device_set_state_handlers(sci_dev, handlers) \ + ((sci_dev)->state_handlers = (handlers)) /** * scic_sds_remote_device_get_port() - * * This macro returns the owning port of this device */ -#define scic_sds_remote_device_get_port(this_device) \ - ((this_device)->owning_port) +#define scic_sds_remote_device_get_port(sci_dev) \ + ((sci_dev)->owning_port) /** * scic_sds_remote_device_get_sequence() - * * This macro returns the remote device sequence value */ -#define scic_sds_remote_device_get_sequence(this_device) \ +#define scic_sds_remote_device_get_sequence(sci_dev) \ (\ - scic_sds_remote_device_get_controller(this_device)-> \ - remote_device_sequence[(this_device)->rnc->remote_node_index] \ + scic_sds_remote_device_get_controller(sci_dev)-> \ + remote_device_sequence[(sci_dev)->rnc->remote_node_index] \ ) /** @@ -531,11 +531,11 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab * * This macro returns the controllers protocol engine group */ -#define scic_sds_remote_device_get_controller_peg(this_device) \ +#define scic_sds_remote_device_get_controller_peg(sci_dev) \ (\ scic_sds_controller_get_protocol_engine_group(\ scic_sds_port_get_controller(\ - scic_sds_remote_device_get_port(this_device) \ + scic_sds_remote_device_get_port(sci_dev) \ ) \ ) \ ) @@ -545,16 +545,16 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab * * This macro returns the port index for the devices owning port */ -#define scic_sds_remote_device_get_port_index(this_device) \ - (scic_sds_port_get_index(scic_sds_remote_device_get_port(this_device))) +#define scic_sds_remote_device_get_port_index(sci_dev) \ + (scic_sds_port_get_index(scic_sds_remote_device_get_port(sci_dev))) /** * scic_sds_remote_device_get_index() - * * This macro returns the remote node index for this device object */ -#define scic_sds_remote_device_get_index(this_device) \ - ((this_device)->rnc->remote_node_index) +#define scic_sds_remote_device_get_index(sci_dev) \ + ((sci_dev)->rnc->remote_node_index) /** * scic_sds_remote_device_build_command_context() - @@ -579,61 +579,61 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab ((device)->working_request = (request)) enum sci_status scic_sds_remote_device_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index); enum sci_status scic_sds_remote_device_event_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code); enum sci_status scic_sds_remote_device_start_io( struct scic_sds_controller *controller, - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *io_request); enum sci_status scic_sds_remote_device_complete_io( struct scic_sds_controller *controller, - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *io_request); enum sci_status scic_sds_remote_device_resume( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); enum sci_status scic_sds_remote_device_suspend( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 suspend_type); enum sci_status scic_sds_remote_device_start_task( struct scic_sds_controller *controller, - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, struct scic_sds_request *io_request); void scic_sds_remote_device_post_request( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 request); #if !defined(DISABLE_ATAPI) bool scic_sds_remote_device_is_atapi( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); #else /* !defined(DISABLE_ATAPI) */ -#define scic_sds_remote_device_is_atapi(this_device) false +#define scic_sds_remote_device_is_atapi(sci_dev) false #endif /* !defined(DISABLE_ATAPI) */ void scic_sds_remote_device_start_request( - struct scic_sds_remote_device *this_device, - struct scic_sds_request *the_request, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req, enum sci_status status); void scic_sds_remote_device_continue_request(void *sci_dev); enum sci_status scic_sds_remote_device_default_start_handler( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); enum sci_status scic_sds_remote_device_default_fail_handler( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); enum sci_status scic_sds_remote_device_default_destruct_handler( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); enum sci_status scic_sds_remote_device_default_reset_handler( struct scic_sds_remote_device *device); @@ -654,15 +654,15 @@ enum sci_status scic_sds_remote_device_default_continue_request_handler( struct scic_sds_request *request); enum sci_status scic_sds_remote_device_default_suspend_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 suspend_type); enum sci_status scic_sds_remote_device_default_resume_handler( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); enum sci_status scic_sds_remote_device_default_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index); enum sci_status scic_sds_remote_device_ready_state_stop_handler( @@ -672,14 +672,14 @@ enum sci_status scic_sds_remote_device_ready_state_reset_handler( struct scic_sds_remote_device *device); enum sci_status scic_sds_remote_device_general_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index); enum sci_status scic_sds_remote_device_general_event_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code); enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler( - struct scic_sds_remote_device *this_device); + struct scic_sds_remote_device *sci_dev); #endif /* _SCIC_SDS_REMOTE_DEVICE_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c index 81e4ab34dd30..e329296fa386 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.c +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c @@ -67,7 +67,7 @@ /** * - * @this_rnc: The RNC for which the is posted request is being made. + * @sci_rnc: The RNC for which the is posted request is being made. * * This method will return true if the RNC is not in the initial state. In all * other states the RNC is considered active and this will return true. The @@ -79,16 +79,16 @@ /** * - * @this_rnc: The state of the remote node context object to check. + * @sci_rnc: The state of the remote node context object to check. * * This method will return true if the remote node context is in a READY state * otherwise it will return false bool true if the remote node context is in * the ready state. false if the remote node context is not in the ready state. */ bool scic_sds_remote_node_context_is_ready( - struct scic_sds_remote_node_context *this_rnc) + struct scic_sds_remote_node_context *sci_rnc) { - u32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine); + u32 current_state = sci_base_state_machine_get_state(&sci_rnc->state_machine); if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { return true; @@ -99,36 +99,36 @@ bool scic_sds_remote_node_context_is_ready( /** * - * @this_device: The remote device to use to construct the RNC buffer. + * @sci_dev: The remote device to use to construct the RNC buffer. * @rnc: The buffer into which the remote device data will be copied. * * This method will construct the RNC buffer for this remote device object. none */ static void scic_sds_remote_node_context_construct_buffer( - struct scic_sds_remote_node_context *this_rnc) + struct scic_sds_remote_node_context *sci_rnc) { union scu_remote_node_context *rnc; - struct scic_sds_controller *the_controller; + struct scic_sds_controller *scic; - the_controller = scic_sds_remote_device_get_controller(this_rnc->device); + scic = scic_sds_remote_device_get_controller(sci_rnc->device); rnc = scic_sds_controller_get_remote_node_context_buffer( - the_controller, this_rnc->remote_node_index); + scic, sci_rnc->remote_node_index); memset( rnc, 0x00, sizeof(union scu_remote_node_context) - * scic_sds_remote_device_node_count(this_rnc->device) + * scic_sds_remote_device_node_count(sci_rnc->device) ); - rnc->ssp.remote_node_index = this_rnc->remote_node_index; - rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width; + rnc->ssp.remote_node_index = sci_rnc->remote_node_index; + rnc->ssp.remote_node_port_width = sci_rnc->device->device_port_width; rnc->ssp.logical_port_index = - scic_sds_remote_device_get_port_index(this_rnc->device); + scic_sds_remote_device_get_port_index(sci_rnc->device); - rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high); - rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low); + rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(sci_rnc->device->device_address.high); + rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(sci_rnc->device->device_address.low); rnc->ssp.nexus_loss_timer_enable = true; rnc->ssp.check_bit = false; @@ -140,24 +140,24 @@ static void scic_sds_remote_node_context_construct_buffer( if ( - this_rnc->device->target_protocols.u.bits.attached_sata_device - || this_rnc->device->target_protocols.u.bits.attached_stp_target + sci_rnc->device->target_protocols.u.bits.attached_sata_device + || sci_rnc->device->target_protocols.u.bits.attached_stp_target ) { rnc->ssp.connection_occupancy_timeout = - the_controller->user_parameters.sds1.stp_max_occupancy_timeout; + scic->user_parameters.sds1.stp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = - the_controller->user_parameters.sds1.stp_inactivity_timeout; + scic->user_parameters.sds1.stp_inactivity_timeout; } else { rnc->ssp.connection_occupancy_timeout = - the_controller->user_parameters.sds1.ssp_max_occupancy_timeout; + scic->user_parameters.sds1.ssp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = - the_controller->user_parameters.sds1.ssp_inactivity_timeout; + scic->user_parameters.sds1.ssp_inactivity_timeout; } rnc->ssp.initial_arbitration_wait_time = 0; /* Open Address Frame Parameters */ - rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate; + rnc->ssp.oaf_connection_rate = sci_rnc->device->connection_rate; rnc->ssp.oaf_features = 0; rnc->ssp.oaf_source_zone_group = 0; rnc->ssp.oaf_more_compatibility_features = 0; @@ -165,8 +165,8 @@ static void scic_sds_remote_node_context_construct_buffer( /** * - * @this_rnc: - * @the_callback: + * @sci_rnc: + * @callback: * @callback_parameter: * * This method will setup the remote node context object so it will transition @@ -174,52 +174,52 @@ static void scic_sds_remote_node_context_construct_buffer( * transition to its final state then this function does nothing. none */ static void scic_sds_remote_node_context_setup_to_resume( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { - if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { - this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY; - this_rnc->user_callback = the_callback; - this_rnc->user_cookie = callback_parameter; + if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { + sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY; + sci_rnc->user_callback = callback; + sci_rnc->user_cookie = callback_parameter; } } /** * - * @this_rnc: - * @the_callback: + * @sci_rnc: + * @callback: * @callback_parameter: * * This method will setup the remote node context object so it will transistion * to its final state. none */ static void scic_sds_remote_node_context_setup_to_destory( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { - this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; - this_rnc->user_callback = the_callback; - this_rnc->user_cookie = callback_parameter; + sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; + sci_rnc->user_callback = callback; + sci_rnc->user_cookie = callback_parameter; } /** * - * @this_rnc: - * @the_callback: + * @sci_rnc: + * @callback: * * This method will continue to resume a remote node context. This is used in * the states where a resume is requested while a resume is in progress. */ static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { - if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { - this_rnc->user_callback = the_callback; - this_rnc->user_cookie = callback_parameter; + if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { + sci_rnc->user_callback = callback; + sci_rnc->user_cookie = callback_parameter; return SCI_SUCCESS; } @@ -230,16 +230,16 @@ static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( /* --------------------------------------------------------------------------- */ static enum sci_status scic_sds_remote_node_context_default_destruct_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to stop while " "in unexpected state %d\n", __func__, - this_rnc, - sci_base_state_machine_get_state(&this_rnc->state_machine)); + sci_rnc, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); /* * We have decided that the destruct request on the remote node context can not fail @@ -248,101 +248,101 @@ static enum sci_status scic_sds_remote_node_context_default_destruct_handler( } static enum sci_status scic_sds_remote_node_context_default_suspend_handler( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 suspend_type, - scics_sds_remote_node_context_callback the_callback, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to suspend " "while in wrong state %d\n", __func__, - this_rnc, - sci_base_state_machine_get_state(&this_rnc->state_machine)); + sci_rnc, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); return SCI_FAILURE_INVALID_STATE; } static enum sci_status scic_sds_remote_node_context_default_resume_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to resume " "while in wrong state %d\n", __func__, - this_rnc, - sci_base_state_machine_get_state(&this_rnc->state_machine)); + sci_rnc, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); return SCI_FAILURE_INVALID_STATE; } static enum sci_status scic_sds_remote_node_context_default_start_io_handler( - struct scic_sds_remote_node_context *this_rnc, - struct scic_sds_request *the_request) + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) { - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to start io " "0x%p while in wrong state %d\n", __func__, - this_rnc, - the_request, - sci_base_state_machine_get_state(&this_rnc->state_machine)); + sci_rnc, + sci_req, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; } static enum sci_status scic_sds_remote_node_context_default_start_task_handler( - struct scic_sds_remote_node_context *this_rnc, - struct scic_sds_request *the_request) + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) { - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to start " "task 0x%p while in wrong state %d\n", __func__, - this_rnc, - the_request, - sci_base_state_machine_get_state(&this_rnc->state_machine)); + sci_rnc, + sci_req, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); return SCI_FAILURE; } static enum sci_status scic_sds_remote_node_context_default_event_handler( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 event_code) { - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to process " "event 0x%x while in wrong state %d\n", __func__, - this_rnc, + sci_rnc, event_code, - sci_base_state_machine_get_state(&this_rnc->state_machine)); + sci_base_state_machine_get_state(&sci_rnc->state_machine)); return SCI_FAILURE_INVALID_STATE; } /** * - * @this_rnc: The rnc for which the task request is targeted. - * @the_request: The request which is going to be started. + * @sci_rnc: The rnc for which the task request is targeted. + * @sci_req: The request which is going to be started. * * This method determines if the task request can be started by the SCU * hardware. When the RNC is in the ready state any task can be started. * enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_remote_node_context_success_start_task_handler( - struct scic_sds_remote_node_context *this_rnc, - struct scic_sds_request *the_request) + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) { return SCI_SUCCESS; } /** * - * @this_rnc: - * @the_callback: + * @sci_rnc: + * @callback: * @callback_parameter: * * This method handles destruct calls from the various state handlers. The @@ -351,16 +351,16 @@ static enum sci_status scic_sds_remote_node_context_success_start_task_handler( * callback. enum sci_status */ static enum sci_status scic_sds_remote_node_context_general_destruct_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { scic_sds_remote_node_context_setup_to_destory( - this_rnc, the_callback, callback_parameter + sci_rnc, callback, callback_parameter ); sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE ); @@ -370,19 +370,19 @@ static enum sci_status scic_sds_remote_node_context_general_destruct_handler( /* --------------------------------------------------------------------------- */ static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { - if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + if (sci_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { scic_sds_remote_node_context_setup_to_resume( - this_rnc, the_callback, callback_parameter + sci_rnc, callback, callback_parameter ); - scic_sds_remote_node_context_construct_buffer(this_rnc); + scic_sds_remote_node_context_construct_buffer(sci_rnc); sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE ); @@ -395,7 +395,7 @@ static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler /* --------------------------------------------------------------------------- */ static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 event_code) { enum sci_status status; @@ -405,19 +405,19 @@ static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( status = SCI_SUCCESS; sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE ); break; default: status = SCI_FAILURE; - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to " "process unexpected event 0x%x while in posting " "state\n", __func__, - this_rnc, + sci_rnc, event_code); break; } @@ -428,19 +428,19 @@ static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( /* --------------------------------------------------------------------------- */ static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { scic_sds_remote_node_context_setup_to_destory( - this_rnc, the_callback, callback_parameter + sci_rnc, callback, callback_parameter ); return SCI_SUCCESS; } static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 event_code) { enum sci_status status; @@ -448,14 +448,14 @@ static enum sci_status scic_sds_remote_node_context_invalidating_state_event_han if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { status = SCI_SUCCESS; - if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { + if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE ); } else { sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE ); } @@ -466,25 +466,25 @@ static enum sci_status scic_sds_remote_node_context_invalidating_state_event_han /* * We really dont care if the hardware is going to suspend * the device since it's being invalidated anyway */ - dev_dbg(scirdev_to_dev(this_rnc->device), + dev_dbg(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p was " "suspeneded by hardware while being " "invalidated.\n", __func__, - this_rnc); + sci_rnc); status = SCI_SUCCESS; break; default: - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p " "requested to process event 0x%x while " "in state %d.\n", __func__, - this_rnc, + sci_rnc, event_code, sci_base_state_machine_get_state( - &this_rnc->state_machine)); + &sci_rnc->state_machine)); status = SCI_FAILURE; break; } @@ -497,7 +497,7 @@ static enum sci_status scic_sds_remote_node_context_invalidating_state_event_han static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 event_code) { enum sci_status status; @@ -506,7 +506,7 @@ static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler status = SCI_SUCCESS; sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE ); } else { @@ -516,23 +516,23 @@ static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler /* * We really dont care if the hardware is going to suspend * the device since it's being resumed anyway */ - dev_dbg(scirdev_to_dev(this_rnc->device), + dev_dbg(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p was " "suspeneded by hardware while being resumed.\n", __func__, - this_rnc); + sci_rnc); status = SCI_SUCCESS; break; default: - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested " "to process event 0x%x while in state %d.\n", __func__, - this_rnc, + sci_rnc, event_code, sci_base_state_machine_get_state( - &this_rnc->state_machine)); + &sci_rnc->state_machine)); status = SCI_FAILURE; break; } @@ -545,32 +545,32 @@ static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler /** * - * @this_rnc: The remote node context object being suspended. - * @the_callback: The callback when the suspension is complete. + * @sci_rnc: The remote node context object being suspended. + * @callback: The callback when the suspension is complete. * @callback_parameter: The parameter that is to be passed into the callback. * * This method will handle the suspend requests from the ready state. * SCI_SUCCESS */ static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 suspend_type, - scics_sds_remote_node_context_callback the_callback, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { - this_rnc->user_callback = the_callback; - this_rnc->user_cookie = callback_parameter; - this_rnc->suspension_code = suspend_type; + sci_rnc->user_callback = callback; + sci_rnc->user_cookie = callback_parameter; + sci_rnc->suspension_code = suspend_type; if (suspend_type == SCI_SOFTWARE_SUSPENSION) { scic_sds_remote_device_post_request( - this_rnc->device, + sci_rnc->device, SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX ); } sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE ); @@ -579,23 +579,23 @@ static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( /** * - * @this_rnc: The rnc for which the io request is targeted. - * @the_request: The request which is going to be started. + * @sci_rnc: The rnc for which the io request is targeted. + * @sci_req: The request which is going to be started. * * This method determines if the io request can be started by the SCU hardware. * When the RNC is in the ready state any io request can be started. enum sci_status * SCI_SUCCESS */ static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler( - struct scic_sds_remote_node_context *this_rnc, - struct scic_sds_request *the_request) + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) { return SCI_SUCCESS; } static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 event_code) { enum sci_status status; @@ -603,33 +603,33 @@ static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( switch (scu_get_event_type(event_code)) { case SCU_EVENT_TL_RNC_SUSPEND_TX: sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE ); - this_rnc->suspension_code = scu_get_event_specifier(event_code); + sci_rnc->suspension_code = scu_get_event_specifier(event_code); status = SCI_SUCCESS; break; case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE ); - this_rnc->suspension_code = scu_get_event_specifier(event_code); + sci_rnc->suspension_code = scu_get_event_specifier(event_code); status = SCI_SUCCESS; break; default: - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to " "process event 0x%x while in state %d.\n", __func__, - this_rnc, + sci_rnc, event_code, sci_base_state_machine_get_state( - &this_rnc->state_machine)); + &sci_rnc->state_machine)); status = SCI_FAILURE; break; @@ -641,41 +641,41 @@ static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( /* --------------------------------------------------------------------------- */ static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { enum sci_status status; struct smp_discover_response_protocols protocols; scic_sds_remote_node_context_setup_to_resume( - this_rnc, the_callback, callback_parameter + sci_rnc, callback, callback_parameter ); /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ - scic_remote_device_get_protocols(this_rnc->device, &protocols); + scic_remote_device_get_protocols(sci_rnc->device, &protocols); if ( (protocols.u.bits.attached_ssp_target == 1) || (protocols.u.bits.attached_smp_target == 1) ) { sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE ); status = SCI_SUCCESS; } else if (protocols.u.bits.attached_stp_target == 1) { - if (this_rnc->device->is_direct_attached) { + if (sci_rnc->device->is_direct_attached) { /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE ); } else { sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE ); } @@ -690,8 +690,8 @@ static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_ha /** * - * @this_rnc: The remote node context which is to receive the task request. - * @the_request: The task request to be transmitted to to the remote target + * @sci_rnc: The remote node context which is to receive the task request. + * @sci_req: The task request to be transmitted to to the remote target * device. * * This method will report a success or failure attempt to start a new task @@ -700,10 +700,10 @@ static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_ha * enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler( - struct scic_sds_remote_node_context *this_rnc, - struct scic_sds_request *the_request) + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) { - scic_sds_remote_node_context_resume(this_rnc, NULL, NULL); + scic_sds_remote_node_context_resume(sci_rnc, NULL, NULL); return SCI_SUCCESS; } @@ -711,16 +711,16 @@ static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler /* --------------------------------------------------------------------------- */ static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { scic_sds_remote_node_context_setup_to_resume( - this_rnc, the_callback, callback_parameter + sci_rnc, callback, callback_parameter ); sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE ); @@ -735,12 +735,12 @@ static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume * */ static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter) { scic_sds_remote_node_context_setup_to_resume( - this_rnc, the_callback, callback_parameter + sci_rnc, callback, callback_parameter ); return SCI_SUCCESS; @@ -748,8 +748,8 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_resum /** * - * @this_rnc: The remote node context which is to receive the task request. - * @the_request: The task request to be transmitted to to the remote target + * @sci_rnc: The remote node context which is to receive the task request. + * @sci_req: The task request to be transmitted to to the remote target * device. * * This method will report a success or failure attempt to start a new task @@ -758,14 +758,14 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_resum * enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler( - struct scic_sds_remote_node_context *this_rnc, - struct scic_sds_request *the_request) + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) { return SCI_SUCCESS; } static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 event_code) { enum sci_status status; @@ -773,33 +773,33 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_event switch (scu_get_event_type(event_code)) { case SCU_EVENT_TL_RNC_SUSPEND_TX: sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE ); - this_rnc->suspension_code = scu_get_event_specifier(event_code); + sci_rnc->suspension_code = scu_get_event_specifier(event_code); status = SCI_SUCCESS; break; case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: sci_base_state_machine_change_state( - &this_rnc->state_machine, + &sci_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE ); - this_rnc->suspension_code = scu_get_event_specifier(event_code); + sci_rnc->suspension_code = scu_get_event_specifier(event_code); status = SCI_SUCCESS; break; default: - dev_warn(scirdev_to_dev(this_rnc->device), + dev_warn(scirdev_to_dev(sci_rnc->device), "%s: SCIC Remote Node Context 0x%p requested to " "process event 0x%x while in state %d.\n", __func__, - this_rnc, + sci_rnc, event_code, sci_base_state_machine_get_state( - &this_rnc->state_machine)); + &sci_rnc->state_machine)); status = SCI_FAILURE; break; @@ -929,41 +929,41 @@ static void scic_sds_remote_node_context_continue_state_transitions( /** * - * @this_rnc: The remote node context object that is to be validated. + * @sci_rnc: The remote node context object that is to be validated. * * This method will mark the rnc buffer as being valid and post the request to * the hardware. none */ static void scic_sds_remote_node_context_validate_context_buffer( - struct scic_sds_remote_node_context *this_rnc) + struct scic_sds_remote_node_context *sci_rnc) { union scu_remote_node_context *rnc_buffer; rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(this_rnc->device), - this_rnc->remote_node_index + scic_sds_remote_device_get_controller(sci_rnc->device), + sci_rnc->remote_node_index ); rnc_buffer->ssp.is_valid = true; if ( - !this_rnc->device->is_direct_attached - && this_rnc->device->target_protocols.u.bits.attached_stp_target + !sci_rnc->device->is_direct_attached + && sci_rnc->device->target_protocols.u.bits.attached_stp_target ) { scic_sds_remote_device_post_request( - this_rnc->device, + sci_rnc->device, SCU_CONTEXT_COMMAND_POST_RNC_96 ); } else { scic_sds_remote_device_post_request( - this_rnc->device, + sci_rnc->device, SCU_CONTEXT_COMMAND_POST_RNC_32 ); - if (this_rnc->device->is_direct_attached) { + if (sci_rnc->device->is_direct_attached) { scic_sds_port_setup_transports( - this_rnc->device->owning_port, - this_rnc->remote_node_index + sci_rnc->device->owning_port, + sci_rnc->remote_node_index ); } } @@ -971,24 +971,24 @@ static void scic_sds_remote_node_context_validate_context_buffer( /** * - * @this_rnc: The remote node context object that is to be invalidated. + * @sci_rnc: The remote node context object that is to be invalidated. * * This method will update the RNC buffer and post the invalidate request. none */ static void scic_sds_remote_node_context_invalidate_context_buffer( - struct scic_sds_remote_node_context *this_rnc) + struct scic_sds_remote_node_context *sci_rnc) { union scu_remote_node_context *rnc_buffer; rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(this_rnc->device), - this_rnc->remote_node_index + scic_sds_remote_device_get_controller(sci_rnc->device), + sci_rnc->remote_node_index ); rnc_buffer->ssp.is_valid = false; scic_sds_remote_device_post_request( - this_rnc->device, + sci_rnc->device, SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE ); } @@ -1037,17 +1037,17 @@ static void scic_sds_remote_node_context_initial_state_enter( static void scic_sds_remote_node_context_posting_state_enter( struct sci_base_object *object) { - struct scic_sds_remote_node_context *this_rnc; + struct scic_sds_remote_node_context *sci_rnc; - this_rnc = (struct scic_sds_remote_node_context *)object; + sci_rnc = (struct scic_sds_remote_node_context *)object; SET_STATE_HANDLER( - this_rnc, + sci_rnc, scic_sds_remote_node_context_state_handler_table, SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE ); - scic_sds_remote_node_context_validate_context_buffer(this_rnc); + scic_sds_remote_node_context_validate_context_buffer(sci_rnc); } /** diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h index e21abe2c6523..a103f155bcc4 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.h +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h @@ -86,25 +86,25 @@ struct scic_sds_remote_node_context; typedef void (*scics_sds_remote_node_context_callback)(void *); typedef enum sci_status (*scic_sds_remote_node_context_operation)( - struct scic_sds_remote_node_context *this_rnc, - scics_sds_remote_node_context_callback the_callback, + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, void *callback_parameter ); typedef enum sci_status (*scic_sds_remote_node_context_suspend_operation)( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 suspension_type, - scics_sds_remote_node_context_callback the_callback, + scics_sds_remote_node_context_callback callback, void *callback_parameter ); typedef enum sci_status (*scic_sds_remote_node_context_io_request)( - struct scic_sds_remote_node_context *this_rnc, - struct scic_sds_request *the_request + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req ); typedef enum sci_status (*scic_sds_remote_node_context_event_handler)( - struct scic_sds_remote_node_context *this_rnc, + struct scic_sds_remote_node_context *sci_rnc, u32 event_code ); @@ -286,7 +286,7 @@ void scic_sds_remote_node_context_construct( bool scic_sds_remote_node_context_is_ready( - struct scic_sds_remote_node_context *this_rnc); + struct scic_sds_remote_node_context *sci_rnc); #define scic_sds_remote_node_context_get_remote_node_index(rcn) \ ((rnc)->remote_node_index) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index a6ee155c6825..8a608f01ceda 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -226,7 +226,7 @@ static u32 scic_sds_ssp_request_get_object_size(void) /** * This method returns the sgl element pair for the specificed sgl_pair index. - * @this_request: This parameter specifies the IO request for which to retrieve + * @sci_req: This parameter specifies the IO request for which to retrieve * the Scatter-Gather List element pair. * @sgl_pair_index: This parameter specifies the index into the SGL element * pair to be retrieved. @@ -234,12 +234,12 @@ static u32 scic_sds_ssp_request_get_object_size(void) * This method returns a pointer to an struct scu_sgl_element_pair. */ static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 sgl_pair_index ) { struct scu_task_context *task_context; - task_context = (struct scu_task_context *)this_request->task_context_buffer; + task_context = (struct scu_task_context *)sci_req->task_context_buffer; if (sgl_pair_index == 0) { return &task_context->sgl_pair_ab; @@ -247,12 +247,12 @@ static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( return &task_context->sgl_pair_cd; } - return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2]; + return &sci_req->sgl_element_pair_buffer[sgl_pair_index - 2]; } /** * This function will build the SGL list for an IO request. - * @this_request: This parameter specifies the IO request for which to build + * @sci_req: This parameter specifies the IO request for which to build * the Scatter-Gather List. * */ @@ -325,36 +325,36 @@ void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) /** * This method build the remainder of the IO request object. - * @this_request: This parameter specifies the request object being constructed. + * @sci_req: This parameter specifies the request object being constructed. * * The scic_sds_general_request_construct() must be called before this call is * valid. none */ static void scic_sds_ssp_io_request_assign_buffers( - struct scic_sds_request *this_request) + struct scic_sds_request *sci_req) { - this_request->command_buffer = - scic_sds_ssp_request_get_command_buffer(this_request); - this_request->response_buffer = - scic_sds_ssp_request_get_response_buffer(this_request); - this_request->sgl_element_pair_buffer = - scic_sds_ssp_request_get_sgl_element_buffer(this_request); - this_request->sgl_element_pair_buffer = - PTR_ALIGN(this_request->sgl_element_pair_buffer, + sci_req->command_buffer = + scic_sds_ssp_request_get_command_buffer(sci_req); + sci_req->response_buffer = + scic_sds_ssp_request_get_response_buffer(sci_req); + sci_req->sgl_element_pair_buffer = + scic_sds_ssp_request_get_sgl_element_buffer(sci_req); + sci_req->sgl_element_pair_buffer = + PTR_ALIGN(sci_req->sgl_element_pair_buffer, sizeof(struct scu_sgl_element_pair)); - if (this_request->was_tag_assigned_by_user == false) { - this_request->task_context_buffer = - scic_sds_ssp_request_get_task_context_buffer(this_request); - this_request->task_context_buffer = - PTR_ALIGN(this_request->task_context_buffer, + if (sci_req->was_tag_assigned_by_user == false) { + sci_req->task_context_buffer = + scic_sds_ssp_request_get_task_context_buffer(sci_req); + sci_req->task_context_buffer = + PTR_ALIGN(sci_req->task_context_buffer, SMP_CACHE_BYTES); } } /** * This method constructs the SSP Command IU data for this io request object. - * @this_request: This parameter specifies the request object for which the SSP + * @sci_req: This parameter specifies the request object for which the SSP * command information unit is being built. * */ @@ -401,7 +401,7 @@ static void scic_sds_io_request_build_ssp_command_iu( /** * This method constructs the SSP Task IU data for this io request object. - * @this_request: + * @sci_req: * */ static void scic_sds_task_request_build_ssp_task_iu( @@ -430,7 +430,7 @@ static void scic_sds_task_request_build_ssp_task_iu( /** * This method is will fill in the SCU Task Context for any type of SSP request. - * @this_request: + * @sci_req: * @task_context: * */ @@ -474,7 +474,7 @@ static void scu_ssp_reqeust_construct_task_context( task_context->address_modifier = 0; - /* task_context->type.ssp.tag = this_request->io_tag; */ + /* task_context->type.ssp.tag = sci_req->io_tag; */ task_context->task_phase = 0x01; if (sds_request->was_tag_assigned_by_user) { @@ -530,7 +530,7 @@ static void scu_ssp_reqeust_construct_task_context( /** * This method is will fill in the SCU Task Context for a SSP IO request. - * @this_request: + * @sci_req: * */ static void scu_ssp_io_request_construct_task_context( @@ -568,24 +568,24 @@ static void scu_ssp_io_request_construct_task_context( /** * This method will fill in the remainder of the io request object for SSP Task * requests. - * @this_request: + * @sci_req: * */ static void scic_sds_ssp_task_request_assign_buffers( - struct scic_sds_request *this_request) + struct scic_sds_request *sci_req) { /* Assign all of the buffer pointers */ - this_request->command_buffer = - scic_sds_ssp_task_request_get_command_buffer(this_request); - this_request->response_buffer = - scic_sds_ssp_task_request_get_response_buffer(this_request); - this_request->sgl_element_pair_buffer = NULL; - - if (this_request->was_tag_assigned_by_user == false) { - this_request->task_context_buffer = - scic_sds_ssp_task_request_get_task_context_buffer(this_request); - this_request->task_context_buffer = - PTR_ALIGN(this_request->task_context_buffer, SMP_CACHE_BYTES); + sci_req->command_buffer = + scic_sds_ssp_task_request_get_command_buffer(sci_req); + sci_req->response_buffer = + scic_sds_ssp_task_request_get_response_buffer(sci_req); + sci_req->sgl_element_pair_buffer = NULL; + + if (sci_req->was_tag_assigned_by_user == false) { + sci_req->task_context_buffer = + scic_sds_ssp_task_request_get_task_context_buffer(sci_req); + sci_req->task_context_buffer = + PTR_ALIGN(sci_req->task_context_buffer, SMP_CACHE_BYTES); } } @@ -598,18 +598,18 @@ static void scic_sds_ssp_task_request_assign_buffers( * (i.e. non-raw frame) is being utilized to perform task management. -# * control_frame == 1. This ensures that the proper endianess is set so * that the bytes are transmitted in the right order for a task frame. - * @this_request: This parameter specifies the task request object being + * @sci_req: This parameter specifies the task request object being * constructed. * */ static void scu_ssp_task_request_construct_task_context( - struct scic_sds_request *this_request) + struct scic_sds_request *sci_req) { struct scu_task_context *task_context; - task_context = scic_sds_request_get_task_context(this_request); + task_context = scic_sds_request_get_task_context(sci_req); - scu_ssp_reqeust_construct_task_context(this_request, task_context); + scu_ssp_reqeust_construct_task_context(sci_req, task_context); task_context->control_frame = 1; task_context->priority = SCU_TASK_PRIORITY_HIGH; @@ -623,7 +623,7 @@ static void scu_ssp_task_request_construct_task_context( /** * This method constructs the SSP Command IU data for this ssp passthrough * comand request object. - * @this_request: This parameter specifies the request object for which the SSP + * @sci_req: This parameter specifies the request object for which the SSP * command information unit is being built. * * enum sci_status, returns invalid parameter is cdb > 16 @@ -632,7 +632,7 @@ static void scu_ssp_task_request_construct_task_context( /** * This method constructs the SATA request object. - * @this_request: + * @sci_req: * @sat_protocol: * @transfer_length: * @data_direction: @@ -964,7 +964,7 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completi /** * - * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start + * @sci_req: The SCIC_SDS_IO_REQUEST_T object for which the start * operation is to be executed. * @frame_index: The frame index returned by the hardware for the reqeust * object. @@ -992,7 +992,7 @@ enum sci_status scic_sds_io_request_frame_handler( /** * - * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the task start + * @sci_req: The SCIC_SDS_IO_REQUEST_T object for which the task start * operation is to be executed. * * This method invokes the core state task complete handler for the @@ -1007,7 +1007,7 @@ enum sci_status scic_sds_io_request_frame_handler( /** * This method copies response data for requests returning response data * instead of sense data. - * @this_request: This parameter specifies the request object for which to copy + * @sci_req: This parameter specifies the request object for which to copy * the response data. * */ @@ -1161,14 +1161,14 @@ enum sci_status scic_sds_request_started_state_abort_handler( * TC (task context) completions for normal IO request (i.e. Task/Abort * Completions of type 0). This method will update the * SCIC_SDS_IO_REQUEST_T::status field. - * @this_request: This parameter specifies the request for which a completion + * @sci_req: This parameter specifies the request for which a completion * occurred. * @completion_code: This parameter specifies the completion code received from * the SCU. * */ enum sci_status scic_sds_request_started_state_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { u8 data_present; @@ -1181,7 +1181,7 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); break; @@ -1194,20 +1194,20 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( * response stats to see if this is truly a failed request or a good * request that just got completed early. */ struct sci_ssp_response_iu *response = (struct sci_ssp_response_iu *) - this_request->response_buffer; + sci_req->response_buffer; scic_word_copy_with_swap( - this_request->response_buffer, - this_request->response_buffer, + sci_req->response_buffer, + sci_req->response_buffer, sizeof(struct sci_ssp_response_iu) / sizeof(u32) ); if (response->status == 0) { scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY ); } else { scic_sds_request_set_status( - this_request, + sci_req, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); @@ -1217,13 +1217,13 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): scic_word_copy_with_swap( - this_request->response_buffer, - this_request->response_buffer, + sci_req->response_buffer, + sci_req->response_buffer, sizeof(struct sci_ssp_response_iu) / sizeof(u32) ); scic_sds_request_set_status( - this_request, + sci_req, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); @@ -1234,19 +1234,19 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed * / to be received before this completion status is posted? */ response_buffer = - (struct sci_ssp_response_iu *)this_request->response_buffer; + (struct sci_ssp_response_iu *)sci_req->response_buffer; data_present = response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK; if ((data_present == 0x01) || (data_present == 0x02)) { scic_sds_request_set_status( - this_request, + sci_req, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); } else { scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); } break; @@ -1263,15 +1263,15 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): - if (this_request->protocol == SCIC_STP_PROTOCOL) { + if (sci_req->protocol == SCIC_STP_PROTOCOL) { scic_sds_request_set_status( - this_request, + sci_req, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED ); } else { scic_sds_request_set_status( - this_request, + sci_req, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); @@ -1290,7 +1290,7 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): scic_sds_request_set_status( - this_request, + sci_req, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED ); @@ -1314,7 +1314,7 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): default: scic_sds_request_set_status( - this_request, + sci_req, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); @@ -1326,7 +1326,7 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( */ /* In all cases we will treat this as the completion of the IO request. */ - sci_base_state_machine_change_state(&this_request->state_machine, + sci_base_state_machine_change_state(&sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } @@ -1340,7 +1340,7 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( * logged. enum sci_status SCI_SUCCESS SCI_FAILURE_INVALID_PARAMETER_VALUE */ static enum sci_status scic_sds_request_started_state_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; @@ -1348,7 +1348,7 @@ static enum sci_status scic_sds_request_started_state_frame_handler( /* / @todo If this is a response frame we must record that we received it */ status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_request_get_controller(this_request)->uf_control), + &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, (void **)&frame_header ); @@ -1357,37 +1357,37 @@ static enum sci_status scic_sds_request_started_state_frame_handler( struct sci_ssp_response_iu *response_buffer; status = scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_request_get_controller(this_request)->uf_control), + &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, (void **)&response_buffer ); scic_word_copy_with_swap( - this_request->response_buffer, + sci_req->response_buffer, (u32 *)response_buffer, sizeof(struct sci_ssp_response_iu) ); - response_buffer = (struct sci_ssp_response_iu *)this_request->response_buffer; + response_buffer = (struct sci_ssp_response_iu *)sci_req->response_buffer; if ((response_buffer->data_present == 0x01) || (response_buffer->data_present == 0x02)) { scic_sds_request_set_status( - this_request, + sci_req, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); } else scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); } else /* This was not a response frame why did it get forwarded? */ - dev_err(scic_to_dev(this_request->owning_controller), + dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC IO Request 0x%p received unexpected " "frame %d type 0x%02x\n", __func__, - this_request, + sci_req, frame_index, frame_header->frame_type); @@ -1395,7 +1395,7 @@ static enum sci_status scic_sds_request_started_state_frame_handler( * In any case we are done with this frame buffer return it to the * controller */ scic_sds_controller_release_frame( - this_request->owning_controller, frame_index + sci_req->owning_controller, frame_index ); return SCI_SUCCESS; @@ -1460,17 +1460,17 @@ static enum sci_status scic_sds_request_aborting_state_abort_handler( * transitions to the completed state. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED + sci_req, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED ); - sci_base_state_machine_change_state(&this_request->state_machine, + sci_base_state_machine_change_state(&sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; @@ -1491,13 +1491,13 @@ static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( * completion. enum sci_status SCI_SUCCESS */ static enum sci_status scic_sds_request_aborting_state_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 frame_index) { /* TODO: Is it even possible to get an unsolicited frame in the aborting state? */ scic_sds_controller_release_frame( - this_request->owning_controller, frame_index); + sci_req->owning_controller, frame_index); return SCI_SUCCESS; } @@ -1539,10 +1539,10 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han static void scic_sds_request_initial_state_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_request_state_handler_table, SCI_BASE_REQUEST_STATE_INITIAL ); @@ -1559,10 +1559,10 @@ static void scic_sds_request_initial_state_enter( static void scic_sds_request_constructed_state_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_request_state_handler_table, SCI_BASE_REQUEST_STATE_CONSTRUCTED ); @@ -1580,10 +1580,10 @@ static void scic_sds_request_constructed_state_enter( static void scic_sds_request_started_state_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_request_state_handler_table, SCI_BASE_REQUEST_STATE_STARTED ); @@ -1591,8 +1591,8 @@ static void scic_sds_request_started_state_enter( /* * Most of the request state machines have a started substate machine so * start its execution on the entry to the started state. */ - if (this_request->has_started_substate_machine == true) - sci_base_state_machine_start(&this_request->started_substate_machine); + if (sci_req->has_started_substate_machine == true) + sci_base_state_machine_start(&sci_req->started_substate_machine); } /** @@ -1608,10 +1608,10 @@ static void scic_sds_request_started_state_enter( static void scic_sds_request_started_state_exit( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; - if (this_request->has_started_substate_machine == true) - sci_base_state_machine_stop(&this_request->started_substate_machine); + if (sci_req->has_started_substate_machine == true) + sci_base_state_machine_stop(&sci_req->started_substate_machine); } /** @@ -1660,13 +1660,13 @@ static void scic_sds_request_completed_state_enter( static void scic_sds_request_aborting_state_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; /* Setting the abort bit in the Task Context is required by the silicon. */ - this_request->task_context_buffer->abort = 1; + sci_req->task_context_buffer->abort = 1; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_request_state_handler_table, SCI_BASE_REQUEST_STATE_ABORTING ); @@ -1684,10 +1684,10 @@ static void scic_sds_request_aborting_state_enter( static void scic_sds_request_final_state_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_request_state_handler_table, SCI_BASE_REQUEST_STATE_FINAL ); diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 423567a62901..0bb1da81ce85 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -336,32 +336,32 @@ extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substat * * This macro will return the controller for this io request object */ -#define scic_sds_request_get_controller(this_request) \ - ((this_request)->owning_controller) +#define scic_sds_request_get_controller(sci_req) \ + ((sci_req)->owning_controller) /** * scic_sds_request_get_device() - * * This macro will return the device for this io request object */ -#define scic_sds_request_get_device(this_request) \ - ((this_request)->target_device) +#define scic_sds_request_get_device(sci_req) \ + ((sci_req)->target_device) /** * scic_sds_request_get_port() - * * This macro will return the port for this io request object */ -#define scic_sds_request_get_port(this_request) \ - scic_sds_remote_device_get_port(scic_sds_request_get_device(this_request)) +#define scic_sds_request_get_port(sci_req) \ + scic_sds_remote_device_get_port(scic_sds_request_get_device(sci_req)) /** * scic_sds_request_get_post_context() - * * This macro returns the constructed post context result for the io request. */ -#define scic_sds_request_get_post_context(this_request) \ - ((this_request)->post_context) +#define scic_sds_request_get_post_context(sci_req) \ + ((sci_req)->post_context) /** * scic_sds_request_get_task_context() - @@ -433,41 +433,41 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completi * ***************************************************************************** */ void scic_sds_request_build_sgl( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); void scic_sds_stp_request_assign_buffers( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); void scic_sds_smp_request_assign_buffers( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); /* --------------------------------------------------------------------------- */ enum sci_status scic_sds_request_start( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_terminate( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_complete( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); void scic_sds_io_request_copy_response( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_event_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 event_code); enum sci_status scic_sds_io_request_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 frame_index); enum sci_status scic_sds_task_request_terminate( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); /* * ***************************************************************************** @@ -475,10 +475,10 @@ enum sci_status scic_sds_task_request_terminate( * ***************************************************************************** */ enum sci_status scic_sds_request_started_state_abort_handler( - struct scic_sds_request *request); + struct scic_sds_request *sci_req); enum sci_status scic_sds_request_started_state_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code); #endif /* _SCIC_SDS_IO_REQUEST_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index 88c359548c1b..471cb7d1142d 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -142,15 +142,15 @@ scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( struct scic_sds_request *request) { enum sci_status status; - struct scic_sds_request *the_request; + struct scic_sds_request *sci_req; - the_request = (struct scic_sds_request *)request; + sci_req = (struct scic_sds_request *)request; - status = scic_sds_io_request_complete(the_request); + status = scic_sds_io_request_complete(sci_req); if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( - device->owning_port, device, the_request); + device->owning_port, device, sci_req); if (status == SCI_SUCCESS) { scic_sds_remote_device_decrement_request_count(device); @@ -165,7 +165,7 @@ scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( "failed with status %d.\n", __func__, device, - the_request, + sci_req, device->owning_port, status); } @@ -175,13 +175,13 @@ scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( /** * This is frame handler for smp device ready cmd substate. - * @this_device: This is the device object that is receiving the frame. + * @sci_dev: This is the device object that is receiving the frame. * @frame_index: The index for the frame received. * * enum sci_status */ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index) { enum sci_status status; @@ -191,7 +191,7 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl * / in this state. All unsolicited frames are forwarded to the io request * / object. */ status = scic_sds_io_request_frame_handler( - this_device->working_request, + sci_dev->working_request, frame_index ); diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 70bc8d2cf048..f53f21b8b9c0 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -67,7 +67,7 @@ #include "scu_task_context.h" static void scu_smp_request_construct_task_context( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, struct smp_request *smp_request); /** @@ -118,27 +118,27 @@ u32 scic_sds_smp_request_get_object_size(void) /** * This method build the remainder of the IO request object. - * @this_request: This parameter specifies the request object being constructed. + * @sci_req: This parameter specifies the request object being constructed. * * The scic_sds_general_request_construct() must be called before this call is * valid. none */ void scic_sds_smp_request_assign_buffers( - struct scic_sds_request *this_request) + struct scic_sds_request *sci_req) { /* Assign all of the buffer pointers */ - this_request->command_buffer = - scic_sds_smp_request_get_command_buffer(this_request); - this_request->response_buffer = - scic_sds_smp_request_get_response_buffer(this_request); - this_request->sgl_element_pair_buffer = NULL; - - if (this_request->was_tag_assigned_by_user == false) { - this_request->task_context_buffer = - scic_sds_smp_request_get_task_context_buffer(this_request); - this_request->task_context_buffer = - PTR_ALIGN(this_request->task_context_buffer, SMP_CACHE_BYTES); + sci_req->command_buffer = + scic_sds_smp_request_get_command_buffer(sci_req); + sci_req->response_buffer = + scic_sds_smp_request_get_response_buffer(sci_req); + sci_req->sgl_element_pair_buffer = NULL; + + if (sci_req->was_tag_assigned_by_user == false) { + sci_req->task_context_buffer = + scic_sds_smp_request_get_task_context_buffer(sci_req); + sci_req->task_context_buffer = + PTR_ALIGN(sci_req->task_context_buffer, SMP_CACHE_BYTES); } } @@ -163,7 +163,7 @@ void scic_sds_smp_request_assign_buffers( * (i.e. non-raw frame) is being utilized to perform task management. -# * control_frame == 1. This ensures that the proper endianess is set so * that the bytes are transmitted in the right order for a smp request frame. - * @this_request: This parameter specifies the smp request object being + * @sci_req: This parameter specifies the smp request object being * constructed. * */ @@ -295,7 +295,7 @@ static void scu_smp_request_construct_task_context( * for a response frame. It will copy the response data, release the * unsolicited frame, and transition the request to the * SCI_BASE_REQUEST_STATE_COMPLETED state. - * @this_request: This parameter specifies the request for which the + * @sci_req: This parameter specifies the request for which the * unsolicited frame was received. * @frame_index: This parameter indicates the unsolicited frame index that * should contain the response. @@ -305,16 +305,16 @@ static void scu_smp_request_construct_task_context( * indicates successful processing of the TC response. */ static enum sci_status scic_sds_smp_request_await_response_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; void *frame_header; - struct smp_response_header *this_frame_header; - u8 *user_smp_buffer = this_request->response_buffer; + struct smp_response_header *rsp_hdr; + u8 *user_smp_buffer = sci_req->response_buffer; status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_request_get_controller(this_request)->uf_control), + &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, &frame_header ); @@ -325,13 +325,13 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( frame_header, sizeof(struct smp_response_header) / sizeof(u32) ); - this_frame_header = (struct smp_response_header *)user_smp_buffer; + rsp_hdr = (struct smp_response_header *)user_smp_buffer; - if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) { + if (rsp_hdr->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) { void *smp_response_buffer; status = scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_request_get_controller(this_request)->uf_control), + &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, &smp_response_buffer ); @@ -341,23 +341,23 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( smp_response_buffer, sizeof(union smp_response_body) / sizeof(u32) ); - if (this_frame_header->function == SMP_FUNCTION_DISCOVER) { - struct smp_response *this_smp_response; + if (rsp_hdr->function == SMP_FUNCTION_DISCOVER) { + struct smp_response *smp_resp; - this_smp_response = (struct smp_response *)user_smp_buffer; + smp_resp = (struct smp_response *)user_smp_buffer; /* * Some expanders only report an attached SATA device, and * not an STP target. Since the core depends on the STP * target attribute to correctly build I/O, set the bit now * if necessary. */ - if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device - && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) { - this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1; + if (smp_resp->response.discover.protocols.u.bits.attached_sata_device + && !smp_resp->response.discover.protocols.u.bits.attached_stp_target) { + smp_resp->response.discover.protocols.u.bits.attached_stp_target = 1; - dev_dbg(scic_to_dev(this_request->owning_controller), + dev_dbg(scic_to_dev(sci_req->owning_controller), "%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n", - __func__, this_request); + __func__, sci_req); } } @@ -367,40 +367,40 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( /* * copy the smp response to framework smp request's response buffer. - * scic_sds_smp_request_copy_response(this_request); */ + * scic_sds_smp_request_copy_response(sci_req); */ scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION ); } else { /* This was not a response frame why did it get forwarded? */ - dev_err(scic_to_dev(this_request->owning_controller), + dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC SMP Request 0x%p received unexpected frame " "%d type 0x%02x\n", __func__, - this_request, + sci_req, frame_index, - this_frame_header->smp_frame_type); + rsp_hdr->smp_frame_type); scic_sds_request_set_status( - this_request, + sci_req, SCU_TASK_DONE_SMP_FRM_TYPE_ERR, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( - &this_request->state_machine, + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); } scic_sds_controller_release_frame( - this_request->owning_controller, frame_index + sci_req->owning_controller, frame_index ); return SCI_SUCCESS; @@ -411,7 +411,7 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( * This method processes an abnormal TC completion while the SMP request is * waiting for a response frame. It decides what happened to the IO based * on TC completion status. - * @this_request: This parameter specifies the request for which the TC + * @sci_req: This parameter specifies the request for which the TC * completion was received. * @completion_code: This parameter indicates the completion status information * for the TC. @@ -420,7 +420,7 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( * this method always returns success. */ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { @@ -429,11 +429,11 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler * In the AWAIT RESPONSE state, any TC completion is unexpected. * but if the TC has success status, we complete the IO anyway. */ scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->state_machine, + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; @@ -447,11 +447,11 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler * break the connection and set TC completion with one of these SMP_XXX_XX_ERR * status. For these type of error, we ask scic user to retry the request. */ scic_sds_request_set_status( - this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED + sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED ); sci_base_state_machine_change_state( - &this_request->state_machine, + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; @@ -460,13 +460,13 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( - &this_request->state_machine, + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -480,7 +480,7 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler * determine if the SMP request was sent successfully. If the SMP request * was sent successfully, then the state for the SMP request transits to * waiting for a response frame. - * @this_request: This parameter specifies the request for which the TC + * @sci_req: This parameter specifies the request for which the TC * completion was received. * @completion_code: This parameter indicates the completion status information * for the TC. @@ -489,17 +489,17 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler * this method always returns success. */ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->state_machine, + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; @@ -508,13 +508,13 @@ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_ha * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( - &this_request->state_machine, + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -547,10 +547,10 @@ static const struct scic_sds_io_request_state_handler scic_sds_smp_request_start static void scic_sds_smp_request_started_await_response_substate_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_smp_request_started_substate_handler_table, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE ); @@ -568,10 +568,10 @@ static void scic_sds_smp_request_started_await_response_substate_enter( static void scic_sds_smp_request_started_await_tc_completion_substate_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_smp_request_started_substate_handler_table, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION ); diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.h b/drivers/scsi/isci/core/scic_sds_smp_request.h index bcad282ce753..8f34ffe2c236 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.h +++ b/drivers/scsi/isci/core/scic_sds_smp_request.h @@ -62,8 +62,7 @@ u32 scic_sds_smp_request_get_object_size(void); -void scic_sds_smp_request_copy_response( - struct scic_sds_request *this_request); +void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); #endif /* _SCIC_SDS_SMP_REQUEST_T_ */ diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index 4d3a21b6ac03..03676682e6ef 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -67,7 +67,7 @@ * determine if the RAW task management frame was sent successfully. If the * raw frame was sent successfully, then the state for the task request * transitions to waiting for a response frame. - * @this_request: This parameter specifies the request for which the TC + * @sci_req: This parameter specifies the request for which the TC * completion was received. * @completion_code: This parameter indicates the completion status information * for the TC. @@ -76,17 +76,17 @@ * this method always returns success. */ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE ); break; @@ -97,15 +97,15 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi * timeout if the task IU wasn't received successfully. * There is a potential for receiving multiple task responses if we * decide to send the task IU again. */ - dev_warn(scic_to_dev(this_request->owning_controller), + dev_warn(scic_to_dev(sci_req->owning_controller), "%s: TaskRequest:0x%p CompletionCode:%x - " "ACK/NAK timeout\n", __func__, - this_request, + sci_req, completion_code); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE ); break; @@ -115,12 +115,12 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); - sci_base_state_machine_change_state(&this_request->state_machine, + sci_base_state_machine_change_state(&sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -132,7 +132,7 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi * This method is responsible for processing a terminate/abort request for this * TC while the request is waiting for the task management response * unsolicited frame. - * @this_request: This parameter specifies the request for which the + * @sci_req: This parameter specifies the request for which the * termination was requested. * * This method returns an indication as to whether the abort request was @@ -155,7 +155,7 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler * waiting for a response frame. It will copy the response data, release * the unsolicited frame, and transition the request to the * SCI_BASE_REQUEST_STATE_COMPLETED state. - * @this_request: This parameter specifies the request for which the + * @sci_req: This parameter specifies the request for which the * unsolicited frame was received. * @frame_index: This parameter indicates the unsolicited frame index that * should contain the response. @@ -202,10 +202,10 @@ static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_ static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_ssp_task_request_started_substate_handler_table, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION ); @@ -223,10 +223,10 @@ static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_e static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_ssp_task_request_started_substate_handler_table, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE ); diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c index 25c68cef298e..e4d2bf56f491 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c @@ -75,16 +75,16 @@ /** * This method will fill in the SCU Task Context for a PACKET fis. And * construct the request STARTED sub-state machine for Packet Protocol IO. - * @this_request: This parameter specifies the stp packet request object being + * @sci_req: This parameter specifies the stp packet request object being * constructed. * */ enum sci_status scic_sds_stp_packet_request_construct( - struct scic_sds_request *this_request) + struct scic_sds_request *sci_req) { struct sata_fis_reg_h2d *h2d_fis = scic_stp_io_request_get_h2d_reg_address( - this_request + sci_req ); /* @@ -92,17 +92,17 @@ enum sci_status scic_sds_stp_packet_request_construct( * need to make change to Packet Fis features field. */ h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA; - scic_sds_stp_non_ncq_request_construct(this_request); + scic_sds_stp_non_ncq_request_construct(sci_req); /* Build the Packet Fis task context structure */ scu_stp_raw_request_construct_task_context( - (struct scic_sds_stp_request *)this_request, - this_request->task_context_buffer + (struct scic_sds_stp_request *)sci_req, + sci_req->task_context_buffer ); sci_base_state_machine_construct( - &this_request->started_substate_machine, - &this_request->parent.parent, + &sci_req->started_substate_machine, + &sci_req->parent.parent, scic_sds_stp_packet_request_started_substate_table, SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE ); @@ -119,24 +119,24 @@ enum sci_status scic_sds_stp_packet_request_construct( * utilized to perform task management. -# control_frame == 1. This ensures * that the proper endianess is set so that the bytes are transmitted in the * right order for a smp request frame. - * @this_request: This parameter specifies the smp request object being + * @sci_req: This parameter specifies the smp request object being * constructed. * @task_context: The task_context to be reconstruct for packet request command * phase. * */ void scu_stp_packet_request_command_phase_construct_task_context( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, struct scu_task_context *task_context) { void *atapi_cdb; u32 atapi_cdb_length; - struct scic_sds_stp_request *stp_request = (struct scic_sds_stp_request *)this_request; + struct scic_sds_stp_request *stp_request = (struct scic_sds_stp_request *)sci_req; /* * reference: SSTL 1.13.4.2 * task_type, sata_direction */ - if (scic_cb_io_request_get_data_direction(this_request->user_request) + if (scic_cb_io_request_get_data_direction(sci_req->user_request) == SCI_IO_REQUEST_DATA_OUT) { task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT; task_context->sata_direction = 0; @@ -152,15 +152,15 @@ void scu_stp_packet_request_command_phase_construct_task_context( /* * Copy in the command IU with CDB so that the commandIU address doesn't * change. */ - memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); + memset(sci_req->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); atapi_cdb = - scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request); + scic_cb_stp_packet_io_request_get_cdb_address(sci_req->user_request); atapi_cdb_length = - scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request); + scic_cb_stp_packet_io_request_get_cdb_length(sci_req->user_request); - memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); + memcpy(((u8 *)sci_req->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); atapi_cdb_length = max(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length); @@ -175,18 +175,18 @@ void scu_stp_packet_request_command_phase_construct_task_context( /* retry counter */ task_context->stp_retry_count = 0; - if (scic_cb_request_is_initial_construction(this_request->user_request)) { + if (scic_cb_request_is_initial_construction(sci_req->user_request)) { /* data transfer size. */ task_context->transfer_length_bytes = - scic_cb_io_request_get_transfer_length(this_request->user_request); + scic_cb_io_request_get_transfer_length(sci_req->user_request); /* setup sgl */ - scic_sds_request_build_sgl(this_request); + scic_sds_request_build_sgl(sci_req); } else { /* data transfer size, need to be 4 bytes aligned. */ task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2); - scic_sds_stp_packet_internal_request_sense_build_sgl(this_request); + scic_sds_stp_packet_internal_request_sense_build_sgl(sci_req); } } @@ -194,24 +194,24 @@ void scu_stp_packet_request_command_phase_construct_task_context( * This method will fill in the SCU Task Context for a DATA fis containing CDB * in Raw Frame type. The TC for previous Packet fis was already there, we * only need to change the H2D fis content. - * @this_request: This parameter specifies the smp request object being + * @sci_req: This parameter specifies the smp request object being * constructed. * @task_context: The task_context to be reconstruct for packet request command * phase. * */ void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, struct scu_task_context *task_context) { void *atapi_cdb = - scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request); + scic_cb_stp_packet_io_request_get_cdb_address(sci_req->user_request); u32 atapi_cdb_length = - scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request); + scic_cb_stp_packet_io_request_get_cdb_length(sci_req->user_request); - memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); - memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); + memset(sci_req->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); + memcpy(((u8 *)sci_req->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context)); task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; @@ -227,12 +227,12 @@ void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( * *@brief This methods decode the D2H status FIS and retrieve the sense data, * then pass the sense data to user request. * - ***@param[in] this_request The request receive D2H status FIS. + ***@param[in] sci_req The request receive D2H status FIS. ***@param[in] status_fis The D2H status fis to be processed. * */ enum sci_status scic_sds_stp_packet_request_process_status_fis( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, struct sata_fis_reg_d2h *status_fis) { enum sci_status status = SCI_SUCCESS; @@ -249,7 +249,7 @@ enum sci_status scic_sds_stp_packet_request_process_status_fis( * command using this request response buffer, only one sge is * needed. * - ***@param[in] this_request The request receive request sense data. + ***@param[in] sci_req The request receive request sense data. * */ void scic_sds_stp_packet_internal_request_sense_build_sgl( @@ -284,7 +284,7 @@ void scic_sds_stp_packet_internal_request_sense_build_sgl( * determine if the Packet FIS was sent successfully. If the Packet FIS was * sent successfully, then the state for the Packet request transits to * waiting for a PIO SETUP frame. - * @this_request: This parameter specifies the request for which the TC + * @sci_req: This parameter specifies the request for which the TC * completion was received. * @completion_code: This parameter indicates the completion status information * for the TC. @@ -293,7 +293,7 @@ void scic_sds_stp_packet_internal_request_sense_build_sgl( * this method always returns success. */ enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { enum sci_status status = SCI_SUCCESS; @@ -301,11 +301,11 @@ enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE ); break; @@ -315,13 +315,13 @@ enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_ * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; @@ -336,7 +336,7 @@ enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_ * waiting for a PIO SETUP FIS. It will release the unsolicited frame, and * transition the request to the COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE * state. - * @this_request: This parameter specifies the request for which the + * @sci_req: This parameter specifies the request for which the * unsolicited frame was received. * @frame_index: This parameter indicates the unsolicited frame index that * should contain the response. @@ -352,12 +352,12 @@ enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_h enum sci_status status; struct sata_fis_header *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *this_request; + struct scic_sds_stp_request *sci_req; - this_request = (struct scic_sds_stp_request *)request; + sci_req = (struct scic_sds_stp_request *)request; status = scic_sds_unsolicited_frame_control_get_header( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_header ); @@ -369,7 +369,7 @@ enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_h * Get from the frame buffer the PIO Setup Data, although we don't need * any info from this pio setup fis. */ scic_sds_unsolicited_frame_control_get_buffer( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_buffer ); @@ -378,23 +378,23 @@ enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_h * Get the data from the PIO Setup * The SCU Hardware returns first word in the frame_header and the rest * of the data is in the frame buffer so we need to back up one dword */ - this_request->type.packet.device_preferred_cdb_length = + sci_req->type.packet.device_preferred_cdb_length = (u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count; /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame( - this_request->parent.owning_controller, frame_index + sci_req->parent.owning_controller, frame_index ); sci_base_state_machine_change_state( - &this_request->parent.started_substate_machine, + &sci_req->parent.started_substate_machine, SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE ); } else dev_err(scic_to_dev(request->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, this_request, frame_index, status); + __func__, sci_req, frame_index, status); return status; } @@ -406,7 +406,7 @@ enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_h * successfully, then the state for the packet request transits to COMPLETE * state. If not successfuly, the request transits to * COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE. - * @this_request: This parameter specifies the request for which the TC + * @sci_req: This parameter specifies the request for which the TC * completion was received. * @completion_code: This parameter indicates the completion status information * for the TC. @@ -415,64 +415,64 @@ enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_h * this method always returns success. */ enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { enum sci_status status = SCI_SUCCESS; u8 sat_packet_protocol = - scic_cb_request_get_sat_protocol(this_request->user_request); + scic_cb_request_get_sat_protocol(sci_req->user_request); switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); if (sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT ) sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); else sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE ); break; case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): - if (scic_io_request_get_number_of_bytes_transferred(this_request) < - scic_cb_io_request_get_transfer_length(this_request->user_request)) { + if (scic_io_request_get_number_of_bytes_transferred(sci_req) < + scic_cb_io_request_get_transfer_length(sci_req->user_request)) { scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); - status = this_request->sci_status; + status = sci_req->sci_status; } break; case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT): /* In this case, there is no UF coming after. compelte the IO now. */ scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; default: - if (this_request->sci_status != SCI_SUCCESS) { /* The io status was set already. This means an UF for the status + if (sci_req->sci_status != SCI_SUCCESS) { /* The io status was set already. This means an UF for the status * fis was received already. */ @@ -480,28 +480,28 @@ enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc * A device suspension event is expected, we need to have the device * coming out of suspension, then complete the IO. */ sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE ); /* change the device state to ATAPI_ERROR. */ sci_base_state_machine_change_state( - &this_request->target_device->ready_substate_machine, + &sci_req->target_device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR ); - status = this_request->sci_status; + status = sci_req->sci_status; } else { /* If receiving any non-sucess TC status, no UF received yet, then an UF for * the status fis is coming after. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE ); } @@ -514,7 +514,7 @@ enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc /** * This method processes an unsolicited frame. - * @this_request: This parameter specifies the request for which the + * @sci_req: This parameter specifies the request for which the * unsolicited frame was received. * @frame_index: This parameter indicates the unsolicited frame index that * should contain the response. @@ -530,12 +530,12 @@ enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler( enum sci_status status; struct sata_fis_header *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *this_request; + struct scic_sds_stp_request *sci_req; - this_request = (struct scic_sds_stp_request *)request; + sci_req = (struct scic_sds_stp_request *)request; status = scic_sds_unsolicited_frame_control_get_header( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_header ); @@ -547,18 +547,18 @@ enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler( * Get from the frame buffer the PIO Setup Data, although we don't need * any info from this pio setup fis. */ scic_sds_unsolicited_frame_control_get_buffer( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_buffer ); scic_sds_controller_copy_sata_response( - &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer + &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer ); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame( - this_request->parent.owning_controller, frame_index + sci_req->parent.owning_controller, frame_index ); } @@ -568,7 +568,7 @@ enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler( /** * This method processes an unsolicited frame while the packet request is * expecting TC completion. It will process the FIS and construct sense data. - * @this_request: This parameter specifies the request for which the + * @sci_req: This parameter specifies the request for which the * unsolicited frame was received. * @frame_index: This parameter indicates the unsolicited frame index that * should contain the response. @@ -581,7 +581,7 @@ enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_fr struct scic_sds_request *request, u32 frame_index) { - struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; enum sci_status status = scic_sds_stp_packet_request_command_phase_common_frame_handler( @@ -590,17 +590,17 @@ enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_fr if (status == SCI_SUCCESS) { /* The command has completed with error status from target device. */ status = scic_sds_stp_packet_request_process_status_fis( - request, &this_request->d2h_reg_fis); + request, &sci_req->d2h_reg_fis); if (status != SCI_SUCCESS) { scic_sds_request_set_status( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, status ); } else scic_sds_request_set_status( - &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS + &sci_req->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); } @@ -611,7 +611,7 @@ enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_fr /** * This method processes an unsolicited frame while the packet request is * expecting TC completion. It will process the FIS and construct sense data. - * @this_request: This parameter specifies the request for which the + * @sci_req: This parameter specifies the request for which the * unsolicited frame was received. * @frame_index: This parameter indicates the unsolicited frame index that * should contain the response. @@ -628,12 +628,12 @@ enum sci_status scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_ha scic_sds_stp_packet_request_command_phase_common_frame_handler( request, frame_index); - struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; if (status == SCI_SUCCESS) { /* The command has completed with error status from target device. */ status = scic_sds_stp_packet_request_process_status_fis( - request, &this_request->d2h_reg_fis); + request, &sci_req->d2h_reg_fis); if (status != SCI_SUCCESS) { scic_sds_request_set_status( @@ -696,26 +696,26 @@ const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_start void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_packet_request_started_substate_handler_table, SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE ); scic_sds_remote_device_set_working_request( - this_request->target_device, this_request + sci_req->target_device, sci_req ); } void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_packet_request_started_substate_handler_table, SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE ); @@ -724,9 +724,9 @@ void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter( void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; u8 sat_packet_protocol = - scic_cb_request_get_sat_protocol(this_request->user_request); + scic_cb_request_get_sat_protocol(sci_req->user_request); struct scu_task_context *task_context; enum sci_status status; @@ -735,25 +735,25 @@ void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter * Recycle the TC and reconstruct it for sending out data fis containing * CDB. */ task_context = scic_sds_controller_get_task_context_buffer( - this_request->owning_controller, this_request->io_tag); + sci_req->owning_controller, sci_req->io_tag); if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA) scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( - this_request, task_context); + sci_req, task_context); else scu_stp_packet_request_command_phase_construct_task_context( - this_request, task_context); + sci_req, task_context); /* send the new TC out. */ - status = this_request->owning_controller->state_handlers->parent.continue_io_handler( - &this_request->owning_controller->parent, - &this_request->target_device->parent, - &this_request->parent + status = sci_req->owning_controller->state_handlers->parent.continue_io_handler( + &sci_req->owning_controller->parent, + &sci_req->target_device->parent, + &sci_req->parent ); if (status == SCI_SUCCESS) SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_packet_request_started_substate_handler_table, SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE ); @@ -762,10 +762,10 @@ void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_packet_request_started_substate_handler_table, SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE ); @@ -774,10 +774,10 @@ void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter( void scic_sds_stp_packet_request_started_completion_delay_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_packet_request_started_substate_handler_table, SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE ); diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h index eebfff32216b..f6ff5a6f6645 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h @@ -113,14 +113,14 @@ extern const struct scic_sds_io_request_state_handler scic_sds_stp_packet_reques #if !defined(DISABLE_ATAPI) enum sci_status scic_sds_stp_packet_request_construct( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); #else /* !defined(DISABLE_ATAPI) */ #define scic_sds_stp_packet_request_construct(request) SCI_FAILURE #endif /* !defined(DISABLE_ATAPI) */ #if !defined(DISABLE_ATAPI) void scu_stp_packet_request_command_phase_construct_task_context( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, struct scu_task_context *task_context); #else /* !defined(DISABLE_ATAPI) */ #define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc) @@ -128,7 +128,7 @@ void scu_stp_packet_request_command_phase_construct_task_context( #if !defined(DISABLE_ATAPI) void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, struct scu_task_context *task_context); #else /* !defined(DISABLE_ATAPI) */ #define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc) @@ -136,7 +136,7 @@ void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( #if !defined(DISABLE_ATAPI) enum sci_status scic_sds_stp_packet_request_process_status_fis( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, struct sata_fis_reg_d2h *status_fis); #else /* !defined(DISABLE_ATAPI) */ #define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE @@ -144,7 +144,7 @@ enum sci_status scic_sds_stp_packet_request_process_status_fis( #if !defined(DISABLE_ATAPI) void scic_sds_stp_packet_internal_request_sense_build_sgl( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); #else /* !defined(DISABLE_ATAPI) */ #define scic_sds_stp_packet_internal_request_sense_build_sgl(request) #endif /* !defined(DISABLE_ATAPI) */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index a5b1fe3229ce..b15357b2ce08 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -252,18 +252,18 @@ out: * resume the RNC right away. enum sci_status */ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code) { enum sci_status status; - status = scic_sds_remote_device_general_event_handler(this_device, event_code); + status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); if (status == SCI_SUCCESS) { if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { status = scic_sds_remote_node_context_resume( - this_device->rnc, NULL, NULL); + sci_dev->rnc, NULL, NULL); } } @@ -312,21 +312,21 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_ha /** * This method will handle events received while the STP device is in the ready * command substate. - * @this_device: This is the device object that is receiving the event. + * @sci_dev: This is the device object that is receiving the event. * @event_code: The event code to process. * * enum sci_status */ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index) { enum sci_status status; struct sata_fis_header *frame_header; status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_remote_device_get_controller(this_device)->uf_control), + &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), frame_index, (void **)&frame_header ); @@ -334,7 +334,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl if (status == SCI_SUCCESS) { if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { - this_device->not_ready_reason = + sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; /* @@ -343,7 +343,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl */ sci_base_state_machine_change_state( - &this_device->ready_substate_machine, + &sci_dev->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR ); } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && @@ -353,11 +353,11 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl * Some devices return D2H FIS when an NCQ error is detected. * Treat this like an SDB error FIS ready reason. */ - this_device->not_ready_reason = + sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; sci_base_state_machine_change_state( - &this_device->ready_substate_machine, + &sci_dev->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR ); } else { @@ -365,7 +365,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl } scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(this_device), frame_index + scic_sds_remote_device_get_controller(sci_dev), frame_index ); } @@ -393,20 +393,20 @@ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_ha } static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 suspend_type) { enum sci_status status; status = scic_sds_remote_node_context_suspend( - this_device->rnc, suspend_type, NULL, NULL + sci_dev->rnc, suspend_type, NULL, NULL ); return status; } static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 frame_index) { enum sci_status status; @@ -416,7 +416,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handl * / in this state. All unsolicited frames are forwarded to the io request * / object. */ status = scic_sds_io_request_frame_handler( - this_device->working_request, + sci_dev->working_request, frame_index ); @@ -461,14 +461,14 @@ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_com struct scic_sds_remote_device *device, struct scic_sds_request *request) { - struct scic_sds_request *the_request = (struct scic_sds_request *)request; + struct scic_sds_request *sci_req = (struct scic_sds_request *)request; enum sci_status status; - status = scic_sds_io_request_complete(the_request); + status = scic_sds_io_request_complete(sci_req); if (status == SCI_SUCCESS) { status = scic_sds_port_complete_io( - device->owning_port, device, the_request + device->owning_port, device, sci_req ); if (status == SCI_SUCCESS) @@ -482,7 +482,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_com __func__, device->owning_port, device, - the_request, + sci_req, status); return status; @@ -505,20 +505,20 @@ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_com * this device. enum sci_status */ enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( - struct scic_sds_remote_device *this_device, + struct scic_sds_remote_device *sci_dev, u32 event_code) { enum sci_status status; - status = scic_sds_remote_device_general_event_handler(this_device, event_code); + status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); if (status == SCI_SUCCESS) { if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { status = scic_sds_remote_node_context_resume( - this_device->rnc, - this_device->working_request->state_handlers->parent.complete_handler, - (void *)this_device->working_request + sci_dev->rnc, + sci_dev->working_request->state_handlers->parent.complete_handler, + (void *)sci_dev->working_request ); } } @@ -673,30 +673,30 @@ scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *use static void scic_sds_stp_remote_device_ready_idle_substate_enter( struct sci_base_object *device) { - struct scic_sds_remote_device *this_device; + struct scic_sds_remote_device *sci_dev; - this_device = (struct scic_sds_remote_device *)device; + sci_dev = (struct scic_sds_remote_device *)device; SET_STATE_HANDLER( - this_device, + sci_dev, scic_sds_stp_remote_device_ready_substate_handler_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE ); - this_device->working_request = NULL; + sci_dev->working_request = NULL; - if (scic_sds_remote_node_context_is_ready(this_device->rnc)) { + if (scic_sds_remote_node_context_is_ready(sci_dev->rnc)) { /* * Since the RNC is ready, it's alright to finish completion * processing (e.g. signal the remote device is ready). */ scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( - this_device + sci_dev ); } else { scic_sds_remote_node_context_resume( - this_device->rnc, + sci_dev->rnc, scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, - this_device + sci_dev ); } } @@ -759,12 +759,12 @@ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( struct sci_base_object *device) { - struct scic_sds_remote_device *this_device; + struct scic_sds_remote_device *sci_dev; - this_device = (struct scic_sds_remote_device *)device; + sci_dev = (struct scic_sds_remote_device *)device; SET_STATE_HANDLER( - this_device, + sci_dev, scic_sds_stp_remote_device_ready_substate_handler_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET ); @@ -785,12 +785,12 @@ static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( void scic_sds_stp_remote_device_ready_atapi_error_substate_enter( struct sci_base_object *device) { - struct scic_sds_remote_device *this_device; + struct scic_sds_remote_device *sci_dev; - this_device = (struct scic_sds_remote_device *)device; + sci_dev = (struct scic_sds_remote_device *)device; SET_STATE_HANDLER( - this_device, + sci_dev, scic_sds_stp_remote_device_ready_substate_handler_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR ); diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index e4ca4e40ae87..ab01f8d5506b 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -156,7 +156,7 @@ void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) /** * This method is will fill in the SCU Task Context for any type of SATA * request. This is called from the various SATA constructors. - * @this_request: The general IO request object which is to be used in + * @sci_req: The general IO request object which is to be used in * constructing the SCU task context. * @task_context: The buffer pointer for the SCU task context which is being * constructed. @@ -262,15 +262,15 @@ static void scu_sata_reqeust_construct_task_context( /** * - * @this_request: + * @sci_req: * * This method will perform any general sata request construction. What part of * SATA IO request construction is general? none */ static void scic_sds_stp_non_ncq_request_construct( - struct scic_sds_request *this_request) + struct scic_sds_request *sci_req) { - this_request->has_started_substate_machine = true; + sci_req->has_started_substate_machine = true; } /** @@ -338,7 +338,7 @@ enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_ /** * scu_stp_raw_request_construct_task_context - - * @this_request: This parameter specifies the STP request object for which to + * @sci_req: This parameter specifies the STP request object for which to * construct a RAW command frame task context. * @task_context: This parameter specifies the SCU specific task context buffer * to construct. @@ -347,10 +347,10 @@ enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_ * utilizing the raw frame method. none */ static void scu_stp_raw_request_construct_task_context( - struct scic_sds_stp_request *this_request, + struct scic_sds_stp_request *sci_req, struct scu_task_context *task_context) { - scu_sata_reqeust_construct_task_context(&this_request->parent, task_context); + scu_sata_reqeust_construct_task_context(&sci_req->parent, task_context); task_context->control_frame = 0; task_context->priority = SCU_TASK_PRIORITY_NORMAL; @@ -386,7 +386,7 @@ void *scic_stp_io_request_get_d2h_reg_address( /** * - * @this_request: + * @sci_req: * * Get the next SGL element from the request. - Check on which SGL element pair * we are working - if working on SLG pair element A - advance to element B - @@ -430,7 +430,7 @@ static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic /** * - * @this_request: + * @sci_req: * @completion_code: * * This method processes a TC completion. The expected TC completion is for @@ -439,17 +439,17 @@ static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic * SCI_SUCCESS This value is always returned. */ static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE ); break; @@ -459,13 +459,13 @@ static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_han * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( - &this_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -491,10 +491,10 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( enum sci_status status; struct sata_fis_header *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; status = scic_sds_unsolicited_frame_control_get_header( - &this_request->parent.owning_controller->uf_control, + &sci_req->parent.owning_controller->uf_control, frame_index, (void **)&frame_header ); @@ -503,18 +503,18 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( switch (frame_header->fis_type) { case SATA_FIS_TYPE_REGD2H: scic_sds_unsolicited_frame_control_get_buffer( - &this_request->parent.owning_controller->uf_control, + &sci_req->parent.owning_controller->uf_control, frame_index, (void **)&frame_buffer ); scic_sds_controller_copy_sata_response( - &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer + &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer ); /* The command has completed with error */ scic_sds_request_set_status( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); @@ -524,10 +524,10 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( dev_warn(scic_to_dev(request->owning_controller), "%s: IO Request:0x%p Frame Id:%d protocol " "violation occurred\n", - __func__, this_request, frame_index); + __func__, sci_req, frame_index); scic_sds_request_set_status( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_UNEXP_FIS, SCI_FAILURE_PROTOCOL_VIOLATION ); @@ -535,18 +535,18 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( } sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame( - this_request->parent.owning_controller, frame_index); + sci_req->parent.owning_controller, frame_index); } else dev_err(scic_to_dev(request->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, this_request, frame_index, status); + __func__, sci_req, frame_index, status); return status; } @@ -567,26 +567,26 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_non_data_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE ); scic_sds_remote_device_set_working_request( - this_request->target_device, this_request + sci_req->target_device, sci_req ); } static void scic_sds_stp_request_started_non_data_await_d2h_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_non_data_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE ); @@ -624,7 +624,7 @@ enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request /** * - * @this_request: + * @sci_req: * @length: * * This function will transmit DATA_FIS from (current sgl + offset) for input @@ -633,24 +633,24 @@ enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request */ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 length) { - struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_request; + struct scic_sds_stp_request *stp_req = (struct scic_sds_stp_request *)sci_req; struct scu_sgl_element *current_sgl; /* * Recycle the TC and reconstruct it for sending out DATA FIS containing * for the data from current_sgl+offset for the input length */ struct scu_task_context *task_context = scic_sds_controller_get_task_context_buffer( - this_request->owning_controller, - this_request->io_tag + sci_req->owning_controller, + sci_req->io_tag ); - if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) - current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A); + if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) + current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A); else - current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B); + current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B); /* update the TC */ task_context->command_iu_upper = current_sgl->address_upper; @@ -659,17 +659,17 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; /* send the new TC out. */ - return scic_controller_continue_io(this_request); + return scic_controller_continue_io(sci_req); } /** * - * @this_request: + * @sci_req: * * enum sci_status */ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data( - struct scic_sds_request *this_sds_request) + struct scic_sds_request *sci_req) { struct scu_sgl_element *current_sgl; @@ -677,45 +677,45 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data( u32 remaining_bytes_in_current_sgl = 0; enum sci_status status = SCI_SUCCESS; - struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_sds_request; + struct scic_sds_stp_request *stp_req = (struct scic_sds_stp_request *)sci_req; - sgl_offset = this_sds_stp_request->type.pio.request_current.sgl_offset; + sgl_offset = stp_req->type.pio.request_current.sgl_offset; - if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A); - remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->A.length - sgl_offset; + if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A); + remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->A.length - sgl_offset; } else { - current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B); - remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->B.length - sgl_offset; + current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B); + remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->B.length - sgl_offset; } - if (this_sds_stp_request->type.pio.pio_transfer_bytes > 0) { - if (this_sds_stp_request->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { + if (stp_req->type.pio.pio_transfer_bytes > 0) { + if (stp_req->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ - status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(this_sds_request, remaining_bytes_in_current_sgl); + status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, remaining_bytes_in_current_sgl); if (status == SCI_SUCCESS) { - this_sds_stp_request->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; + stp_req->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; /* update the current sgl, sgl_offset and save for future */ - current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_sds_stp_request); + current_sgl = scic_sds_stp_request_pio_get_next_sgl(stp_req); sgl_offset = 0; } - } else if (this_sds_stp_request->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { + } else if (stp_req->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */ - scic_sds_stp_request_pio_data_out_trasmit_data_frame(this_sds_request, this_sds_stp_request->type.pio.pio_transfer_bytes); + scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->type.pio.pio_transfer_bytes); if (status == SCI_SUCCESS) { /* Sgl offset will be adjusted and saved for future */ - sgl_offset += this_sds_stp_request->type.pio.pio_transfer_bytes; - current_sgl->address_lower += this_sds_stp_request->type.pio.pio_transfer_bytes; - this_sds_stp_request->type.pio.pio_transfer_bytes = 0; + sgl_offset += stp_req->type.pio.pio_transfer_bytes; + current_sgl->address_lower += stp_req->type.pio.pio_transfer_bytes; + stp_req->type.pio.pio_transfer_bytes = 0; } } } if (status == SCI_SUCCESS) { - this_sds_stp_request->type.pio.request_current.sgl_offset = sgl_offset; + stp_req->type.pio.request_current.sgl_offset = sgl_offset; } return status; @@ -772,13 +772,13 @@ scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *s /** * - * @this_request: The PIO DATA IN request that is to receive the data. + * @sci_req: The PIO DATA IN request that is to receive the data. * @data_buffer: The buffer to copy from. * * Copy the data buffer to the io request data region. enum sci_status */ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( - struct scic_sds_stp_request *this_request, + struct scic_sds_stp_request *sci_req, u8 *data_buffer) { enum sci_status status; @@ -786,19 +786,19 @@ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( /* * If there is less than 1K remaining in the transfer request * copy just the data for the transfer */ - if (this_request->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { + if (sci_req->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { status = scic_sds_stp_request_pio_data_in_copy_data_buffer( - this_request, data_buffer, this_request->type.pio.pio_transfer_bytes); + sci_req, data_buffer, sci_req->type.pio.pio_transfer_bytes); if (status == SCI_SUCCESS) - this_request->type.pio.pio_transfer_bytes = 0; + sci_req->type.pio.pio_transfer_bytes = 0; } else { /* We are transfering the whole frame so copy */ status = scic_sds_stp_request_pio_data_in_copy_data_buffer( - this_request, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); + sci_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); if (status == SCI_SUCCESS) - this_request->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; + sci_req->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; } return status; @@ -806,13 +806,13 @@ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( /** * - * @this_request: + * @sci_req: * @completion_code: * * enum sci_status */ static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { enum sci_status status = SCI_SUCCESS; @@ -820,11 +820,11 @@ static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completi switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE ); break; @@ -834,13 +834,13 @@ static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completi * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( - &this_request->state_machine, + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; @@ -851,7 +851,7 @@ static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completi /** * - * @this_request: + * @sci_req: * @frame_index: * * enum sci_status @@ -863,12 +863,12 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( enum sci_status status; struct sata_fis_header *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *this_request; + struct scic_sds_stp_request *sci_req; - this_request = (struct scic_sds_stp_request *)request; + sci_req = (struct scic_sds_stp_request *)request; status = scic_sds_unsolicited_frame_control_get_header( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_header ); @@ -878,7 +878,7 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( case SATA_FIS_TYPE_PIO_SETUP: /* Get from the frame buffer the PIO Setup Data */ scic_sds_unsolicited_frame_control_get_buffer( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_buffer ); @@ -887,30 +887,30 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( * Get the data from the PIO Setup * The SCU Hardware returns first word in the frame_header and the rest * of the data is in the frame buffer so we need to back up one dword */ - this_request->type.pio.pio_transfer_bytes = + sci_req->type.pio.pio_transfer_bytes = (u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count; - this_request->type.pio.ending_status = + sci_req->type.pio.ending_status = (u8)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->ending_status; scic_sds_controller_copy_sata_response( - &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer + &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer ); - this_request->d2h_reg_fis.status = - this_request->type.pio.ending_status; + sci_req->d2h_reg_fis.status = + sci_req->type.pio.ending_status; /* The next state is dependent on whether the request was PIO Data-in or Data out */ - if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN) { + if (sci_req->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN) { sci_base_state_machine_change_state( - &this_request->parent.started_substate_machine, + &sci_req->parent.started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE ); - } else if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT) { + } else if (sci_req->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT) { /* Transmit data */ status = scic_sds_stp_request_pio_data_out_transmit_data(request); if (status == SCI_SUCCESS) { sci_base_state_machine_change_state( - &this_request->parent.started_substate_machine, + &sci_req->parent.started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE ); } @@ -919,7 +919,7 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( case SATA_FIS_TYPE_SETDEVBITS: sci_base_state_machine_change_state( - &this_request->parent.started_substate_machine, + &sci_req->parent.started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE ); break; @@ -927,22 +927,22 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( case SATA_FIS_TYPE_REGD2H: if ((frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0) { scic_sds_unsolicited_frame_control_get_buffer( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_buffer ); scic_sds_controller_copy_sata_response( - &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer); + &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer); scic_sds_request_set_status( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); } else { @@ -954,7 +954,7 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( "D2H Register FIS with BSY status " "0x%x\n", __func__, - this_request, + sci_req, frame_header->status); } break; @@ -965,21 +965,21 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( /* Frame is decoded return it to the controller */ scic_sds_controller_release_frame( - this_request->parent.owning_controller, + sci_req->parent.owning_controller, frame_index ); } else dev_err(scic_to_dev(request->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, this_request, frame_index, status); + __func__, sci_req, frame_index, status); return status; } /** * - * @this_request: + * @sci_req: * @frame_index: * * enum sci_status @@ -991,33 +991,33 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler enum sci_status status; struct sata_fis_header *frame_header; struct sata_fis_data *frame_buffer; - struct scic_sds_stp_request *this_request; + struct scic_sds_stp_request *sci_req; - this_request = (struct scic_sds_stp_request *)request; + sci_req = (struct scic_sds_stp_request *)request; status = scic_sds_unsolicited_frame_control_get_header( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_header ); if (status == SCI_SUCCESS) { if (frame_header->fis_type == SATA_FIS_TYPE_DATA) { - if (this_request->type.pio.request_current.sgl_pair == NULL) { - this_request->parent.saved_rx_frame_index = frame_index; - this_request->type.pio.pio_transfer_bytes = 0; + if (sci_req->type.pio.request_current.sgl_pair == NULL) { + sci_req->parent.saved_rx_frame_index = frame_index; + sci_req->type.pio.pio_transfer_bytes = 0; } else { status = scic_sds_unsolicited_frame_control_get_buffer( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_buffer ); - status = scic_sds_stp_request_pio_data_in_copy_data(this_request, (u8 *)frame_buffer); + status = scic_sds_stp_request_pio_data_in_copy_data(sci_req, (u8 *)frame_buffer); /* Frame is decoded return it to the controller */ scic_sds_controller_release_frame( - this_request->parent.owning_controller, + sci_req->parent.owning_controller, frame_index ); } @@ -1027,17 +1027,17 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler * for this data transfer */ if ( (status == SCI_SUCCESS) - && (this_request->type.pio.pio_transfer_bytes == 0) + && (sci_req->type.pio.pio_transfer_bytes == 0) ) { - if ((this_request->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0) { + if ((sci_req->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0) { scic_sds_request_set_status( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); } else { @@ -1053,24 +1053,24 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler "with fis type 0x%02x when expecting a data " "fis.\n", __func__, - this_request, + sci_req, frame_index, frame_header->fis_type); scic_sds_request_set_status( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_GOOD, SCI_FAILURE_IO_REQUIRES_SCSI_ABORT ); sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); /* Frame is decoded return it to the controller */ scic_sds_controller_release_frame( - this_request->parent.owning_controller, + sci_req->parent.owning_controller, frame_index ); } @@ -1078,7 +1078,7 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler dev_err(scic_to_dev(request->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, this_request, frame_index, status); + __func__, sci_req, frame_index, status); return status; } @@ -1086,31 +1086,31 @@ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler /** * - * @this_request: + * @sci_req: * @completion_code: * * enum sci_status */ static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { enum sci_status status = SCI_SUCCESS; bool all_frames_transferred = false; - struct scic_sds_stp_request *this_scic_sds_stp_request = (struct scic_sds_stp_request *)this_request; + struct scic_sds_stp_request *stp_req = (struct scic_sds_stp_request *)sci_req; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): /* Transmit data */ - if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes != 0) { - status = scic_sds_stp_request_pio_data_out_transmit_data(this_request); + if (stp_req->type.pio.pio_transfer_bytes != 0) { + status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); if (status == SCI_SUCCESS) { - if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) + if (stp_req->type.pio.pio_transfer_bytes == 0) all_frames_transferred = true; } - } else if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) { + } else if (stp_req->type.pio.pio_transfer_bytes == 0) { /* * this will happen if the all data is written at the * first time after the pio setup fis is received @@ -1124,7 +1124,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_com * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE * and wait for PIO_SETUP fis / or D2H REg fis. */ sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE ); } @@ -1135,13 +1135,13 @@ static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_com * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( - &this_request->state_machine, + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; @@ -1217,25 +1217,25 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_pio_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE ); scic_sds_remote_device_set_working_request( - this_request->target_device, this_request); + sci_req->target_device, sci_req); } static void scic_sds_stp_request_started_pio_await_frame_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_pio_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE ); @@ -1244,10 +1244,10 @@ static void scic_sds_stp_request_started_pio_await_frame_enter( static void scic_sds_stp_request_started_pio_data_in_await_data_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_pio_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE ); @@ -1256,10 +1256,10 @@ static void scic_sds_stp_request_started_pio_data_in_await_data_enter( static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_pio_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE ); @@ -1333,13 +1333,13 @@ static void scic_sds_stp_request_udma_complete_request( /** * - * @this_request: + * @sci_req: * @frame_index: * * enum sci_status */ static enum sci_status scic_sds_stp_request_udma_general_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; @@ -1347,7 +1347,7 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler( u32 *frame_buffer; status = scic_sds_unsolicited_frame_control_get_header( - &this_request->owning_controller->uf_control, + &sci_req->owning_controller->uf_control, frame_index, (void **)&frame_header ); @@ -1357,20 +1357,20 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler( && (frame_header->fis_type == SATA_FIS_TYPE_REGD2H) ) { scic_sds_unsolicited_frame_control_get_buffer( - &this_request->owning_controller->uf_control, + &sci_req->owning_controller->uf_control, frame_index, (void **)&frame_buffer ); scic_sds_controller_copy_sata_response( - &((struct scic_sds_stp_request *)this_request)->d2h_reg_fis, + &((struct scic_sds_stp_request *)sci_req)->d2h_reg_fis, (u32 *)frame_header, frame_buffer ); } scic_sds_controller_release_frame( - this_request->owning_controller, frame_index); + sci_req->owning_controller, frame_index); return status; } @@ -1378,7 +1378,7 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler( /** * This method process TC completions while in the state where we are waiting * for TC completions. - * @this_request: + * @sci_req: * @completion_code: * * enum sci_status @@ -1388,12 +1388,12 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi u32 completion_code) { enum sci_status status = SCI_SUCCESS; - struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_stp_request_udma_complete_request( - &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS + &sci_req->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); break; @@ -1402,14 +1402,14 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi /* * We must check ther response buffer to see if the D2H Register FIS was * received before we got the TC completion. */ - if (this_request->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H) { + if (sci_req->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H) { scic_sds_remote_device_suspend( - this_request->parent.target_device, + sci_req->parent.target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) ); scic_sds_stp_request_udma_complete_request( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); @@ -1418,7 +1418,7 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi * If we have an error completion status for the TC then we can expect a * D2H register FIS from the device so we must change state to wait for it */ sci_base_state_machine_change_state( - &this_request->parent.started_substate_machine, + &sci_req->parent.started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE ); } @@ -1434,14 +1434,14 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): scic_sds_remote_device_suspend( - this_request->parent.target_device, + sci_req->parent.target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) ); /* Fall through to the default case */ default: /* All other completion status cause the IO to be complete. */ scic_sds_stp_request_udma_complete_request( - &this_request->parent, + &sci_req->parent, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); @@ -1452,17 +1452,17 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi } static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; /* Use the general frame handler to copy the resposne data */ - status = scic_sds_stp_request_udma_general_frame_handler(this_request, frame_index); + status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); if (status == SCI_SUCCESS) { scic_sds_stp_request_udma_complete_request( - this_request, + sci_req, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); @@ -1488,10 +1488,10 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start static void scic_sds_stp_request_started_udma_await_tc_completion_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_udma_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE ); @@ -1507,10 +1507,10 @@ static void scic_sds_stp_request_started_udma_await_tc_completion_enter( static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_udma_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE ); @@ -1548,7 +1548,7 @@ enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci /** * - * @this_request: + * @sci_req: * @completion_code: * * This method processes a TC completion. The expected TC completion is for @@ -1557,17 +1557,17 @@ enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci * SCI_SUCCESS This value is always returned. */ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE ); break; @@ -1577,13 +1577,13 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_com * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( - &this_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -1592,7 +1592,7 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_com /** * - * @this_request: + * @sci_req: * @completion_code: * * This method processes a TC completion. The expected TC completion is for @@ -1601,17 +1601,17 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_com * SCI_SUCCESS This value is always returned. */ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( - this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( - &this_request->started_substate_machine, + &sci_req->started_substate_machine, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE ); break; @@ -1621,12 +1621,12 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_c * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ scic_sds_request_set_status( - this_request, + sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); - sci_base_state_machine_change_state(&this_request->state_machine, + sci_base_state_machine_change_state(&sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -1653,10 +1653,10 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( enum sci_status status; struct sata_fis_header *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; status = scic_sds_unsolicited_frame_control_get_header( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_header ); @@ -1665,18 +1665,18 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( switch (frame_header->fis_type) { case SATA_FIS_TYPE_REGD2H: scic_sds_unsolicited_frame_control_get_buffer( - &(this_request->parent.owning_controller->uf_control), + &(sci_req->parent.owning_controller->uf_control), frame_index, (void **)&frame_buffer ); scic_sds_controller_copy_sata_response( - &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer + &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer ); /* The command has completed with error */ scic_sds_request_set_status( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID ); @@ -1687,11 +1687,11 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( "%s: IO Request:0x%p Frame Id:%d protocol " "violation occurred\n", __func__, - this_request, + sci_req, frame_index); scic_sds_request_set_status( - &this_request->parent, + &sci_req->parent, SCU_TASK_DONE_UNEXP_FIS, SCI_FAILURE_PROTOCOL_VIOLATION ); @@ -1699,18 +1699,18 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( } sci_base_state_machine_change_state( - &this_request->parent.state_machine, + &sci_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame( - this_request->parent.owning_controller, frame_index + sci_req->parent.owning_controller, frame_index ); } else dev_err(scic_to_dev(request->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, this_request, frame_index, status); + __func__, sci_req, frame_index, status); return status; } @@ -1735,40 +1735,40 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_soft_reset_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE ); scic_sds_remote_device_set_working_request( - this_request->target_device, this_request + sci_req->target_device, sci_req ); } static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; struct scu_task_context *task_context; struct sata_fis_reg_h2d *h2d_fis; enum sci_status status; /* Clear the SRST bit */ - h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request); + h2d_fis = scic_stp_io_request_get_h2d_reg_address(sci_req); h2d_fis->control = 0; /* Clear the TC control bit */ task_context = scic_sds_controller_get_task_context_buffer( - this_request->owning_controller, this_request->io_tag); + sci_req->owning_controller, sci_req->io_tag); task_context->control_frame = 0; - status = scic_controller_continue_io(this_request); + status = scic_controller_continue_io(sci_req); if (status == SCI_SUCCESS) { SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_soft_reset_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE ); @@ -1778,10 +1778,10 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( struct sci_base_object *object) { - struct scic_sds_request *this_request = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = (struct scic_sds_request *)object; SET_STATE_HANDLER( - this_request, + sci_req, scic_sds_stp_request_started_soft_reset_substate_handler_table, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE ); diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index a6c02d3cba50..6724c1d759df 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -177,18 +177,18 @@ enum sci_status scic_sds_stp_pio_request_construct( bool copy_rx_frame); enum sci_status scic_sds_stp_udma_request_construct( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 transfer_length, enum dma_data_direction dir); enum sci_status scic_sds_stp_non_data_request_construct( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); enum sci_status scic_sds_stp_soft_reset_request_construct( - struct scic_sds_request *this_request); + struct scic_sds_request *sci_req); enum sci_status scic_sds_stp_ncq_request_construct( - struct scic_sds_request *this_request, + struct scic_sds_request *sci_req, u32 transfer_length, enum dma_data_direction dir); -- cgit v1.2.3 From 31e824ed0d8c84c5232405167b2338ffc071ae8a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 19 Apr 2011 12:32:51 -0700 Subject: isci: rely on irq core for intx multiplexing, and silence screaming intx Remove the extra logic to poll each controller for interrupts, that's the core's job for shared interrupts. While testing noticed that a number of interrupts fire while waiting for the completion tasklet to run, so added an irq-ack. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 26 +++++++++++--------------- drivers/scsi/isci/init.c | 17 +++++++++++------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 927f08892ad6..0d706b2ce25e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -77,23 +77,19 @@ irqreturn_t isci_msix_isr(int vec, void *data) irqreturn_t isci_intx_isr(int vec, void *data) { - struct pci_dev *pdev = data; - struct isci_host *ihost; irqreturn_t ret = IRQ_NONE; - int i; + struct isci_host *ihost = data; + struct scic_sds_controller *scic = ihost->core_controller; - for_each_isci_host(i, ihost, pdev) { - struct scic_sds_controller *scic = ihost->core_controller; - - if (scic_sds_controller_isr(scic)) { - tasklet_schedule(&ihost->completion_tasklet); - ret = IRQ_HANDLED; - } else if (scic_sds_controller_error_isr(scic)) { - spin_lock(&ihost->scic_lock); - scic_sds_controller_error_handler(scic); - spin_unlock(&ihost->scic_lock); - ret = IRQ_HANDLED; - } + if (scic_sds_controller_isr(scic)) { + writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); + tasklet_schedule(&ihost->completion_tasklet); + ret = IRQ_HANDLED; + } else if (scic_sds_controller_error_isr(scic)) { + spin_lock(&ihost->scic_lock); + scic_sds_controller_error_handler(scic); + spin_unlock(&ihost->scic_lock); + ret = IRQ_HANDLED; } return ret; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 015ce94453bb..5a9cd5fbeab9 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -335,6 +335,7 @@ static int num_controllers(struct pci_dev *pdev) static int isci_setup_interrupts(struct pci_dev *pdev) { int err, i, num_msix; + struct isci_host *ihost; struct isci_pci_info *pci_info = to_pci_info(pdev); /* @@ -353,9 +354,9 @@ static int isci_setup_interrupts(struct pci_dev *pdev) for (i = 0; i < num_msix; i++) { int id = i / SCI_NUM_MSI_X_INT; struct msix_entry *msix = &pci_info->msix_entries[i]; - struct isci_host *isci_host = pci_info->hosts[id]; irq_handler_t isr; + ihost = pci_info->hosts[id]; /* odd numbered vectors are error interrupts */ if (i & 1) isr = isci_error_isr; @@ -363,16 +364,16 @@ static int isci_setup_interrupts(struct pci_dev *pdev) isr = isci_msix_isr; err = devm_request_irq(&pdev->dev, msix->vector, isr, 0, - DRV_NAME"-msix", isci_host); + DRV_NAME"-msix", ihost); if (!err) continue; dev_info(&pdev->dev, "msix setup failed falling back to intx\n"); while (i--) { id = i / SCI_NUM_MSI_X_INT; - isci_host = pci_info->hosts[id]; + ihost = pci_info->hosts[id]; msix = &pci_info->msix_entries[i]; - devm_free_irq(&pdev->dev, msix->vector, isci_host); + devm_free_irq(&pdev->dev, msix->vector, ihost); } pci_disable_msix(pdev); goto intx; @@ -380,8 +381,12 @@ static int isci_setup_interrupts(struct pci_dev *pdev) return 0; intx: - err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr, - IRQF_SHARED, DRV_NAME"-intx", pdev); + for_each_isci_host(i, ihost, pdev) { + err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr, + IRQF_SHARED, DRV_NAME"-intx", ihost); + if (err) + break; + } return err; } -- cgit v1.2.3 From 7ab92c9ed22b49a50d9a10bbfdf4ee8ffe62c324 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 19 Apr 2011 13:48:49 -0700 Subject: isci: make a remote_node_context a proper member of a remote_device A rnc object has the same lifetime as its associated remote_device. It might get re-initialized, but a remote device always has an rnc member. Preparation for unifying scic_sds_remote_device and isci_remote_device Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_remote_device.c | 41 ++++++++++------------ drivers/scsi/isci/core/scic_sds_remote_device.h | 6 ++-- drivers/scsi/isci/core/scic_sds_request.c | 2 +- .../scsi/isci/core/scic_sds_smp_remote_device.c | 3 +- drivers/scsi/isci/core/scic_sds_smp_request.c | 9 +++-- .../scsi/isci/core/scic_sds_stp_remote_device.c | 39 +++++++++----------- 6 files changed, 45 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index fa7828d4d975..04295274b71a 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -83,8 +83,7 @@ u32 scic_remote_device_get_object_size(void) { - return sizeof(struct scic_sds_remote_device) - + sizeof(struct scic_sds_remote_node_context); + return sizeof (struct scic_sds_remote_device); } enum sci_status scic_remote_device_da_construct( @@ -111,7 +110,7 @@ enum sci_status scic_remote_device_da_construct( &remote_node_index); if (status == SCI_SUCCESS) { - sci_dev->rnc->remote_node_index = remote_node_index; + sci_dev->rnc.remote_node_index = remote_node_index; scic_sds_port_get_attached_sas_address( sci_dev->owning_port, &sci_dev->device_address); @@ -176,7 +175,7 @@ enum sci_status scic_remote_device_ea_construct( sci_dev, discover_response); status = scic_sds_controller_allocate_remote_node_context( - scic, sci_dev, &sci_dev->rnc->remote_node_index); + scic, sci_dev, &sci_dev->rnc.remote_node_index); if (status == SCI_SUCCESS) { if (sci_dev->target_protocols.u.bits.attached_ssp_target) { @@ -694,7 +693,7 @@ static enum sci_status scic_sds_remote_device_core_event_handler( case SCU_EVENT_TYPE_RNC_OPS_MISC: case SCU_EVENT_TYPE_RNC_SUSPEND_TX: case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - status = scic_sds_remote_node_context_event_handler(sci_dev->rnc, event_code); + status = scic_sds_remote_node_context_event_handler(&sci_dev->rnc, event_code); break; case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: @@ -702,7 +701,7 @@ static enum sci_status scic_sds_remote_device_core_event_handler( status = SCI_SUCCESS; /* Suspend the associated RNC */ - scic_sds_remote_node_context_suspend(sci_dev->rnc, + scic_sds_remote_node_context_suspend(&sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); @@ -889,7 +888,7 @@ static enum sci_status scic_sds_remote_device_stopped_state_start_handler( { enum sci_status status; - status = scic_sds_remote_node_context_resume(sci_dev->rnc, + status = scic_sds_remote_node_context_resume(&sci_dev->rnc, scic_sds_remote_device_resume_complete_handler, sci_dev); if (status == SCI_SUCCESS) @@ -923,8 +922,8 @@ static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( scic = scic_sds_remote_device_get_controller(sci_dev); scic_sds_controller_free_remote_node_context(scic, sci_dev, - sci_dev->rnc->remote_node_index); - sci_dev->rnc->remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + sci_dev->rnc.remote_node_index); + sci_dev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FINAL); @@ -948,7 +947,7 @@ static enum sci_status scic_sds_remote_device_starting_state_stop_handler( /* * Destroy the remote node context */ - scic_sds_remote_node_context_destruct(sci_dev->rnc, + scic_sds_remote_node_context_destruct(&sci_dev->rnc, scic_sds_cb_remote_device_rnc_destruct_complete, sci_dev); /* @@ -971,7 +970,7 @@ enum sci_status scic_sds_remote_device_ready_state_stop_handler( SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); if (sci_dev->started_request_count == 0) { - scic_sds_remote_node_context_destruct(sci_dev->rnc, + scic_sds_remote_node_context_destruct(&sci_dev->rnc, scic_sds_cb_remote_device_rnc_destruct_complete, sci_dev); } else @@ -1016,8 +1015,8 @@ static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( scic_sds_remote_device_get_port(sci_dev), sci_dev, request); if (result == SCI_SUCCESS) { - result = scic_sds_remote_node_context_start_task( - sci_dev->rnc, request); + result = scic_sds_remote_node_context_start_task(&sci_dev->rnc, + request); if (result == SCI_SUCCESS) result = scic_sds_request_start(request); @@ -1046,8 +1045,7 @@ static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( scic_sds_remote_device_get_port(sci_dev), sci_dev, request); if (result == SCI_SUCCESS) { - result = scic_sds_remote_node_context_start_io( - sci_dev->rnc, request); + result = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); if (result == SCI_SUCCESS) result = scic_sds_request_start(request); @@ -1144,7 +1142,7 @@ static enum sci_status scic_sds_remote_device_stopping_state_complete_request_ha scic_sds_remote_device_decrement_request_count(sci_dev); if (scic_sds_remote_device_get_request_count(sci_dev) == 0) - scic_sds_remote_node_context_destruct(sci_dev->rnc, + scic_sds_remote_node_context_destruct(&sci_dev->rnc, scic_sds_cb_remote_device_rnc_destruct_complete, sci_dev); return SCI_SUCCESS; @@ -1491,7 +1489,7 @@ static void scic_sds_remote_device_ready_state_enter(struct sci_base_object *obj scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_READY); - scic->remote_device_sequence[sci_dev->rnc->remote_node_index]++; + scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; if (sci_dev->has_ready_substate_machine) sci_base_state_machine_start(&sci_dev->ready_substate_machine); @@ -1585,7 +1583,7 @@ static void scic_sds_remote_device_resetting_state_enter( ); scic_sds_remote_node_context_suspend( - sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); + &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); } /** @@ -1601,7 +1599,7 @@ static void scic_sds_remote_device_resetting_state_exit( { struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - scic_sds_remote_node_context_resume(sci_dev->rnc, NULL, NULL); + scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); } /** @@ -1661,7 +1659,6 @@ void scic_remote_device_construct(struct scic_sds_port *sci_port, { sci_dev->owning_port = sci_port; sci_dev->started_request_count = 0; - sci_dev->rnc = (struct scic_sds_remote_node_context *) &sci_dev[1]; sci_dev->parent.private = NULL; sci_base_state_machine_construct( @@ -1677,9 +1674,9 @@ void scic_remote_device_construct(struct scic_sds_port *sci_port, scic_sds_remote_node_context_construct( sci_dev, - sci_dev->rnc, + &sci_dev->rnc, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX ); - sci_object_set_association(sci_dev->rnc, sci_dev); + sci_object_set_association(&sci_dev->rnc, sci_dev); } diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index 5d3df92212eb..7f43f3003e81 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -297,7 +297,7 @@ struct scic_sds_remote_device { * This field contains the SCU silicon remote node context specific * information. */ - struct scic_sds_remote_node_context *rnc; + struct scic_sds_remote_node_context rnc; /** * This field contains the stated request count for the remote device. The @@ -523,7 +523,7 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab #define scic_sds_remote_device_get_sequence(sci_dev) \ (\ scic_sds_remote_device_get_controller(sci_dev)-> \ - remote_device_sequence[(sci_dev)->rnc->remote_node_index] \ + remote_device_sequence[(sci_dev)->rnc.remote_node_index] \ ) /** @@ -554,7 +554,7 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab * This macro returns the remote node index for this device object */ #define scic_sds_remote_device_get_index(sci_dev) \ - ((sci_dev)->rnc->remote_node_index) + ((sci_dev)->rnc.remote_node_index) /** * scic_sds_remote_device_build_command_context() - diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 8a608f01ceda..63ebbf39dc90 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -1766,7 +1766,7 @@ enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, scic_sds_general_request_construct(scic, sci_dev, io_tag, user_io_request_object, sci_req); - if (sci_dev->rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) + if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; scic_remote_device_get_protocols(sci_dev, &device_protocol); diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c index 471cb7d1142d..cd55c0a8dae3 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c @@ -87,8 +87,7 @@ static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_h device->owning_port, device, request); if (status == SCI_SUCCESS) { - status = scic_sds_remote_node_context_start_io( - device->rnc, request); + status = scic_sds_remote_node_context_start_io(&device->rnc, request); if (status == SCI_SUCCESS) status = scic_sds_request_start(request); diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index f53f21b8b9c0..3274d62ac3b2 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -173,7 +173,7 @@ static void scu_smp_request_construct_task_context( { dma_addr_t dma_addr; struct scic_sds_controller *controller; - struct scic_sds_remote_device *target_device; + struct scic_sds_remote_device *sci_dev; struct scic_sds_port *target_port; struct scu_task_context *task_context; @@ -185,7 +185,7 @@ static void scu_smp_request_construct_task_context( task_context = scic_sds_request_get_task_context(sds_request); controller = scic_sds_request_get_controller(sds_request); - target_device = scic_sds_request_get_device(sds_request); + sci_dev = scic_sds_request_get_device(sds_request); target_port = scic_sds_request_get_port(sds_request); /* @@ -195,7 +195,7 @@ static void scu_smp_request_construct_task_context( task_context->priority = 0; task_context->initiator_request = 1; task_context->connection_rate = - scic_remote_device_get_connection_rate(target_device); + scic_remote_device_get_connection_rate(sci_dev); task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = @@ -206,8 +206,7 @@ static void scu_smp_request_construct_task_context( task_context->context_type = SCU_TASK_CONTEXT_TYPE; /* 04h */ - task_context->remote_node_index = - sds_request->target_device->rnc->remote_node_index; + task_context->remote_node_index = sci_dev->rnc.remote_node_index; task_context->command_code = 0; task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c index b15357b2ce08..848cb4711b63 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c @@ -150,7 +150,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_h if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_task(device->rnc, request); + status = scic_sds_remote_node_context_start_task(&device->rnc, request); if (status != SCI_SUCCESS) goto out; @@ -173,9 +173,9 @@ static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_h * remote node context state machine will take the correct action when * the remote node context is suspended and later resumed. */ - scic_sds_remote_node_context_suspend(device->rnc, + scic_sds_remote_node_context_suspend(&device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); - scic_sds_remote_node_context_resume(device->rnc, + scic_sds_remote_node_context_resume(&device->rnc, scic_sds_remote_device_continue_request, device); @@ -220,7 +220,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_h if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(sci_dev->rnc, request); + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); if (status != SCI_SUCCESS) goto out; @@ -263,7 +263,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_hand if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { status = scic_sds_remote_node_context_resume( - sci_dev->rnc, NULL, NULL); + &sci_dev->rnc, NULL, NULL); } } @@ -289,19 +289,16 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_ha sci_dev->owning_port, sci_dev, request); + if (status != SCI_SUCCESS) + return status; - if (status == SCI_SUCCESS) { - status = scic_sds_remote_node_context_start_io( - sci_dev->rnc, - request); + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); + if (status != SCI_SUCCESS) + return status; - if (status == SCI_SUCCESS) - status = request->state_handlers->start_handler(request); + status = request->state_handlers->start_handler(request); - scic_sds_remote_device_start_request(sci_dev, - request, - status); - } + scic_sds_remote_device_start_request(sci_dev, request, status); } else status = SCI_FAILURE_INVALID_STATE; @@ -398,9 +395,8 @@ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_han { enum sci_status status; - status = scic_sds_remote_node_context_suspend( - sci_dev->rnc, suspend_type, NULL, NULL - ); + status = scic_sds_remote_node_context_suspend(&sci_dev->rnc, + suspend_type, NULL, NULL); return status; } @@ -685,7 +681,7 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter( sci_dev->working_request = NULL; - if (scic_sds_remote_node_context_is_ready(sci_dev->rnc)) { + if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { /* * Since the RNC is ready, it's alright to finish completion * processing (e.g. signal the remote device is ready). */ @@ -694,10 +690,9 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter( ); } else { scic_sds_remote_node_context_resume( - sci_dev->rnc, + &sci_dev->rnc, scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, - sci_dev - ); + sci_dev); } } -- cgit v1.2.3 From 9614395ea2eed076fa8341df422582b0017d330c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 19 Apr 2011 18:35:58 -0700 Subject: isci: remove rnc->device back pointer Now that they are one in the same object remove the back pointer reference in favor of container_of. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_remote_device.c | 7 +- drivers/scsi/isci/core/scic_sds_remote_device.h | 9 ++ .../scsi/isci/core/scic_sds_remote_node_context.c | 124 +++++++++------------ .../scsi/isci/core/scic_sds_remote_node_context.h | 15 +-- 4 files changed, 65 insertions(+), 90 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 04295274b71a..22788bfcf9c3 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -1672,11 +1672,8 @@ void scic_remote_device_construct(struct scic_sds_port *sci_port, &sci_dev->state_machine ); - scic_sds_remote_node_context_construct( - sci_dev, - &sci_dev->rnc, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX - ); + scic_sds_remote_node_context_construct(&sci_dev->rnc, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); sci_object_set_association(&sci_dev->rnc, sci_dev); } diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h index 7f43f3003e81..bff44b8b83ab 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h @@ -339,6 +339,15 @@ struct scic_sds_remote_device { const struct scic_sds_remote_device_state_handler *state_handlers; }; +static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) +{ + struct scic_sds_remote_device *sci_dev; + + sci_dev = container_of(rnc, typeof(*sci_dev), rnc); + + return sci_dev; +} + typedef enum sci_status (*scic_sds_remote_device_request_handler_t)( struct scic_sds_remote_device *device, struct scic_sds_request *request); diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c index e329296fa386..e1d58f8854f7 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.c +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c @@ -108,27 +108,24 @@ static void scic_sds_remote_node_context_construct_buffer( struct scic_sds_remote_node_context *sci_rnc) { union scu_remote_node_context *rnc; + struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); struct scic_sds_controller *scic; - scic = scic_sds_remote_device_get_controller(sci_rnc->device); + scic = scic_sds_remote_device_get_controller(sci_dev); rnc = scic_sds_controller_get_remote_node_context_buffer( scic, sci_rnc->remote_node_index); - memset( - rnc, - 0x00, - sizeof(union scu_remote_node_context) - * scic_sds_remote_device_node_count(sci_rnc->device) - ); + memset(rnc, 0, sizeof(union scu_remote_node_context) + * scic_sds_remote_device_node_count(sci_dev)); rnc->ssp.remote_node_index = sci_rnc->remote_node_index; - rnc->ssp.remote_node_port_width = sci_rnc->device->device_port_width; + rnc->ssp.remote_node_port_width = sci_dev->device_port_width; rnc->ssp.logical_port_index = - scic_sds_remote_device_get_port_index(sci_rnc->device); + scic_sds_remote_device_get_port_index(sci_dev); - rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(sci_rnc->device->device_address.high); - rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(sci_rnc->device->device_address.low); + rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(sci_dev->device_address.high); + rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(sci_dev->device_address.low); rnc->ssp.nexus_loss_timer_enable = true; rnc->ssp.check_bit = false; @@ -140,8 +137,8 @@ static void scic_sds_remote_node_context_construct_buffer( if ( - sci_rnc->device->target_protocols.u.bits.attached_sata_device - || sci_rnc->device->target_protocols.u.bits.attached_stp_target + sci_dev->target_protocols.u.bits.attached_sata_device + || sci_dev->target_protocols.u.bits.attached_stp_target ) { rnc->ssp.connection_occupancy_timeout = scic->user_parameters.sds1.stp_max_occupancy_timeout; @@ -157,7 +154,7 @@ static void scic_sds_remote_node_context_construct_buffer( rnc->ssp.initial_arbitration_wait_time = 0; /* Open Address Frame Parameters */ - rnc->ssp.oaf_connection_rate = sci_rnc->device->connection_rate; + rnc->ssp.oaf_connection_rate = sci_dev->connection_rate; rnc->ssp.oaf_features = 0; rnc->ssp.oaf_source_zone_group = 0; rnc->ssp.oaf_more_compatibility_features = 0; @@ -234,7 +231,7 @@ static enum sci_status scic_sds_remote_node_context_default_destruct_handler( scics_sds_remote_node_context_callback callback, void *callback_parameter) { - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to stop while " "in unexpected state %d\n", __func__, @@ -253,7 +250,7 @@ static enum sci_status scic_sds_remote_node_context_default_suspend_handler( scics_sds_remote_node_context_callback callback, void *callback_parameter) { - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to suspend " "while in wrong state %d\n", __func__, @@ -268,7 +265,7 @@ static enum sci_status scic_sds_remote_node_context_default_resume_handler( scics_sds_remote_node_context_callback callback, void *callback_parameter) { - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to resume " "while in wrong state %d\n", __func__, @@ -282,7 +279,7 @@ static enum sci_status scic_sds_remote_node_context_default_start_io_handler( struct scic_sds_remote_node_context *sci_rnc, struct scic_sds_request *sci_req) { - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to start io " "0x%p while in wrong state %d\n", __func__, @@ -297,7 +294,7 @@ static enum sci_status scic_sds_remote_node_context_default_start_task_handler( struct scic_sds_remote_node_context *sci_rnc, struct scic_sds_request *sci_req) { - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to start " "task 0x%p while in wrong state %d\n", __func__, @@ -312,7 +309,7 @@ static enum sci_status scic_sds_remote_node_context_default_event_handler( struct scic_sds_remote_node_context *sci_rnc, u32 event_code) { - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to process " "event 0x%x while in wrong state %d\n", __func__, @@ -412,7 +409,7 @@ static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( default: status = SCI_FAILURE; - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to " "process unexpected event 0x%x while in posting " "state\n", @@ -466,7 +463,7 @@ static enum sci_status scic_sds_remote_node_context_invalidating_state_event_han /* * We really dont care if the hardware is going to suspend * the device since it's being invalidated anyway */ - dev_dbg(scirdev_to_dev(sci_rnc->device), + dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p was " "suspeneded by hardware while being " "invalidated.\n", @@ -476,7 +473,7 @@ static enum sci_status scic_sds_remote_node_context_invalidating_state_event_han break; default: - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p " "requested to process event 0x%x while " "in state %d.\n", @@ -516,7 +513,7 @@ static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler /* * We really dont care if the hardware is going to suspend * the device since it's being resumed anyway */ - dev_dbg(scirdev_to_dev(sci_rnc->device), + dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p was " "suspeneded by hardware while being resumed.\n", __func__, @@ -525,7 +522,7 @@ static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler break; default: - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested " "to process event 0x%x while in state %d.\n", __func__, @@ -563,10 +560,8 @@ static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( sci_rnc->suspension_code = suspend_type; if (suspend_type == SCI_SOFTWARE_SUSPENSION) { - scic_sds_remote_device_post_request( - sci_rnc->device, - SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX - ); + scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), + SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); } sci_base_state_machine_change_state( @@ -622,7 +617,7 @@ static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( break; default: - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to " "process event 0x%x while in state %d.\n", __func__, @@ -654,7 +649,7 @@ static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_ha /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ - scic_remote_device_get_protocols(sci_rnc->device, &protocols); + scic_remote_device_get_protocols(rnc_to_dev(sci_rnc), &protocols); if ( (protocols.u.bits.attached_ssp_target == 1) @@ -667,7 +662,7 @@ static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_ha status = SCI_SUCCESS; } else if (protocols.u.bits.attached_stp_target == 1) { - if (sci_rnc->device->is_direct_attached) { + if (rnc_to_dev(sci_rnc)->is_direct_attached) { /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ sci_base_state_machine_change_state( &sci_rnc->state_machine, @@ -792,7 +787,7 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_event break; default: - dev_warn(scirdev_to_dev(sci_rnc->device), + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p requested to " "process event 0x%x while in state %d.\n", __func__, @@ -937,34 +932,26 @@ static void scic_sds_remote_node_context_continue_state_transitions( static void scic_sds_remote_node_context_validate_context_buffer( struct scic_sds_remote_node_context *sci_rnc) { + struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); union scu_remote_node_context *rnc_buffer; rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(sci_rnc->device), + scic_sds_remote_device_get_controller(sci_dev), sci_rnc->remote_node_index ); rnc_buffer->ssp.is_valid = true; - if ( - !sci_rnc->device->is_direct_attached - && sci_rnc->device->target_protocols.u.bits.attached_stp_target - ) { - scic_sds_remote_device_post_request( - sci_rnc->device, - SCU_CONTEXT_COMMAND_POST_RNC_96 - ); + if (!sci_dev->is_direct_attached && + sci_dev->target_protocols.u.bits.attached_stp_target) { + scic_sds_remote_device_post_request(sci_dev, + SCU_CONTEXT_COMMAND_POST_RNC_96); } else { - scic_sds_remote_device_post_request( - sci_rnc->device, - SCU_CONTEXT_COMMAND_POST_RNC_32 - ); + scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_32); - if (sci_rnc->device->is_direct_attached) { - scic_sds_port_setup_transports( - sci_rnc->device->owning_port, - sci_rnc->remote_node_index - ); + if (sci_dev->is_direct_attached) { + scic_sds_port_setup_transports(sci_dev->owning_port, + sci_rnc->remote_node_index); } } } @@ -981,16 +968,13 @@ static void scic_sds_remote_node_context_invalidate_context_buffer( union scu_remote_node_context *rnc_buffer; rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(sci_rnc->device), - sci_rnc->remote_node_index - ); + scic_sds_remote_device_get_controller(rnc_to_dev(sci_rnc)), + sci_rnc->remote_node_index); rnc_buffer->ssp.is_valid = false; - scic_sds_remote_device_post_request( - sci_rnc->device, - SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE - ); + scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), + SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE); } /* @@ -1081,8 +1065,10 @@ static void scic_sds_remote_node_context_resuming_state_enter( { struct scic_sds_remote_node_context *rnc; struct smp_discover_response_protocols protocols; + struct scic_sds_remote_device *sci_dev; rnc = (struct scic_sds_remote_node_context *)object; + sci_dev = rnc_to_dev(rnc); SET_STATE_HANDLER( rnc, @@ -1096,18 +1082,15 @@ static void scic_sds_remote_node_context_resuming_state_enter( * resume because of a target reset we also need to update * the STPTLDARNI register with the RNi of the device */ - scic_remote_device_get_protocols(rnc->device, &protocols); + scic_remote_device_get_protocols(sci_dev, &protocols); - if ((protocols.u.bits.attached_stp_target == 1) && - (rnc->device->is_direct_attached)) { - scic_sds_port_setup_transports( - rnc->device->owning_port, rnc->remote_node_index); + if (protocols.u.bits.attached_stp_target == 1 && + sci_dev->is_direct_attached) { + scic_sds_port_setup_transports(sci_dev->owning_port, + rnc->remote_node_index); } - scic_sds_remote_device_post_request( - rnc->device, - SCU_CONTEXT_COMMAND_POST_RNC_RESUME - ); + scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); } /** @@ -1225,15 +1208,12 @@ static const struct sci_base_state scic_sds_remote_node_context_state_table[] = }, }; -void scic_sds_remote_node_context_construct( - struct scic_sds_remote_device *device, - struct scic_sds_remote_node_context *rnc, - u16 remote_node_index) +void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, + u16 remote_node_index) { memset(rnc, 0, sizeof(struct scic_sds_remote_node_context)); rnc->remote_node_index = remote_node_index; - rnc->device = device; rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; sci_base_state_machine_construct( diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h index a103f155bcc4..b3f2546090dd 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.h +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h @@ -231,15 +231,6 @@ struct scic_sds_remote_node_context { */ struct sci_base_object parent; - /** - * This pointer simply points to the remote device object containing - * this RNC. - * - * @todo Consider making the device pointer the associated object of the - * the parent object. - */ - struct scic_sds_remote_device *device; - /** * This field indicates the remote node index (RNI) associated with * this RNC. @@ -279,10 +270,8 @@ struct scic_sds_remote_node_context { struct scic_sds_remote_node_context_handlers *state_handlers; }; -void scic_sds_remote_node_context_construct( - struct scic_sds_remote_device *device, - struct scic_sds_remote_node_context *rnc, - u16 remote_node_index); +void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, + u16 remote_node_index); bool scic_sds_remote_node_context_is_ready( -- cgit v1.2.3 From 57f20f4ed6fb702339be2ef4dea9d15e6a7d0d07 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 21 Apr 2011 18:14:45 -0700 Subject: isci: unify remote_device data structures Make it explicit that isci_remote_device and scic_sds_remote_device are one in the same object. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_remote_device.h | 12 ------------ drivers/scsi/isci/core/scic_sds_remote_device.c | 15 --------------- drivers/scsi/isci/host.c | 2 +- drivers/scsi/isci/host.h | 11 +---------- drivers/scsi/isci/init.c | 5 +---- drivers/scsi/isci/remote_device.c | 17 +++++++++-------- drivers/scsi/isci/remote_device.h | 9 ++------- drivers/scsi/isci/request.c | 12 +++++------- drivers/scsi/isci/task.c | 20 +++++++++----------- 9 files changed, 28 insertions(+), 75 deletions(-) diff --git a/drivers/scsi/isci/core/scic_remote_device.h b/drivers/scsi/isci/core/scic_remote_device.h index 62fa7fd572c1..23e90af5a01b 100644 --- a/drivers/scsi/isci/core/scic_remote_device.h +++ b/drivers/scsi/isci/core/scic_remote_device.h @@ -86,18 +86,6 @@ enum scic_remote_device_not_ready_reason_code { }; -/** - * scic_remote_device_get_object_size() - This method simply returns the - * maximum memory space needed to store a remote device object. - * - * a positive integer value indicating the size (in bytes) of the remote device - * object. - */ -u32 scic_remote_device_get_object_size( - void); - -struct scic_sds_port; -struct scic_sds_remote_device; /** * scic_remote_device_construct() - This method will perform the construction * common to all remote device objects. diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c index 22788bfcf9c3..d314e2b2088b 100644 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c @@ -71,21 +71,6 @@ #define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT (1000) -/* - * ***************************************************************************** - * * CORE REMOTE DEVICE PRIVATE METHODS - * ***************************************************************************** */ - -/* - * ***************************************************************************** - * * CORE REMOTE DEVICE PUBLIC METHODS - * ***************************************************************************** */ - -u32 scic_remote_device_get_object_size(void) -{ - return sizeof (struct scic_sds_remote_device); -} - enum sci_status scic_remote_device_da_construct( struct scic_sds_remote_device *sci_dev) { diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 0d706b2ce25e..3aceb9219d7b 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -467,7 +467,7 @@ int isci_host_init(struct isci_host *isci_host) isci_phy_init(&isci_host->phys[i], isci_host, i); for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { - struct isci_remote_device *idev = idev_by_id(isci_host, i); + struct isci_remote_device *idev = &isci_host->devices[i]; INIT_LIST_HEAD(&idev->reqs_in_process); INIT_LIST_HEAD(&idev->node); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 6e660744d8d4..21bd7d88e5d8 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -110,18 +110,9 @@ struct isci_host { struct list_head requests_to_errorback; spinlock_t scic_lock; - /* careful only access this via idev_by_id */ - struct isci_remote_device devices[0]; + struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES]; }; -static inline struct isci_remote_device *idev_by_id(struct isci_host *ihost, int i) -{ - void *p = ihost->devices; - - return p + i * (sizeof(struct isci_remote_device) + - scic_remote_device_get_object_size()); -} - /** * struct isci_pci_info - This class represents the pci function containing the * controllers. Depending on PCI SKU, there could be up to 2 controllers in diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 5a9cd5fbeab9..a23ea2c1c7db 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -396,10 +396,7 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) struct Scsi_Host *shost; int err; - isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host) + - SCI_MAX_REMOTE_DEVICES * - (sizeof(struct isci_remote_device) + - scic_remote_device_get_object_size()), GFP_KERNEL); + isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); if (!isci_host) return NULL; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 9301e25dff31..1553221fe4d7 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -87,7 +87,7 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ BUG(); } - scic_remote_device_destruct(to_sci_dev(idev)); + scic_remote_device_destruct(&idev->sci); idev->domain_dev->lldd_dev = NULL; idev->domain_dev = NULL; idev->isci_port = NULL; @@ -117,7 +117,7 @@ static enum sci_status isci_remote_device_construct( /* let the core do it's common constuction. */ scic_remote_device_construct(port->sci_port_handle, - to_sci_dev(isci_device)); + &isci_device->sci); /* let the core do it's device specific constuction. */ if (isci_device->domain_dev->parent && @@ -183,11 +183,11 @@ static enum sci_status isci_remote_device_construct( "%s: parent->dev_type = EDGE_DEV\n", __func__); - status = scic_remote_device_ea_construct(to_sci_dev(isci_device), + status = scic_remote_device_ea_construct(&isci_device->sci, (struct smp_response_discover *)&discover_response); } else - status = scic_remote_device_da_construct(to_sci_dev(isci_device)); + status = scic_remote_device_da_construct(&isci_device->sci); if (status != SCI_SUCCESS) { @@ -200,10 +200,11 @@ static enum sci_status isci_remote_device_construct( return status; } - sci_object_set_association(to_sci_dev(isci_device), isci_device); + /* XXX will be killed with sci_base_object removal */ + sci_object_set_association(&isci_device->sci, isci_device); /* start the device. */ - status = scic_remote_device_start(to_sci_dev(isci_device), + status = scic_remote_device_start(&isci_device->sci, ISCI_REMOTE_DEVICE_START_TIMEOUT); if (status != SCI_SUCCESS) { @@ -245,7 +246,7 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) int i; for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { - idev = idev_by_id(ihost, i); + idev = &ihost->devices[i]; if (!test_and_set_bit(IDEV_ALLOCATED, &idev->flags)) break; } @@ -374,7 +375,7 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem set_bit(IDEV_STOP_PENDING, &idev->flags); spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_stop(to_sci_dev(idev), 50); + status = scic_remote_device_stop(&idev->sci, 50); spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Wait for the stop complete callback. */ diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 9925316ac55a..aeda39568a1c 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -55,9 +55,9 @@ #if !defined(_ISCI_REMOTE_DEVICE_H_) #define _ISCI_REMOTE_DEVICE_H_ +#include "scic_sds_remote_device.h" struct isci_host; -struct scic_sds_remote_device; struct isci_remote_device { enum isci_status status; @@ -70,14 +70,9 @@ struct isci_remote_device { struct list_head node; struct list_head reqs_in_process; spinlock_t state_lock; + struct scic_sds_remote_device sci; }; -static inline struct scic_sds_remote_device *to_sci_dev(struct isci_remote_device *idev) -{ - /* core data is an opaque buffer at the end of the idev */ - return (struct scic_sds_remote_device *) &idev[1]; -} - #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 void isci_remote_device_start_complete(struct isci_host *ihost, diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index a90c299b723a..8d2125b520ea 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -179,7 +179,7 @@ static enum sci_status isci_io_request_build( struct smp_discover_response_protocols dev_protocols; enum sci_status status = SCI_SUCCESS; struct sas_task *task = isci_request_access_task(request); - struct scic_sds_remote_device *sci_device = to_sci_dev(isci_device); + struct scic_sds_remote_device *sci_device = &isci_device->sci; dev_dbg(&isci_host->pdev->dev, "%s: isci_device = 0x%p; request = %p, " @@ -380,7 +380,7 @@ int isci_request_execute( unsigned long flags; isci_device = task->dev->lldd_dev; - sci_device = to_sci_dev(isci_device); + sci_device = &isci_device->sci; /* do common allocation and init of request object. */ ret = isci_request_alloc_io( @@ -1194,11 +1194,9 @@ void isci_request_io_request_complete( ); /* complete the io request to the core. */ - scic_controller_complete_io( - isci_host->core_controller, - to_sci_dev(isci_device), - request->sci_request_handle - ); + scic_controller_complete_io(isci_host->core_controller, + &isci_device->sci, + request->sci_request_handle); /* NULL the request handle so it cannot be completed or * terminated again, and to cause any calls into abort * task to recognize the already completed case. diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c79968db871c..f54f523b8d40 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -282,7 +282,7 @@ static enum sci_status isci_task_request_build( "%s: isci_tmf = %p\n", __func__, isci_tmf); isci_device = isci_tmf->device; - sci_device = to_sci_dev(isci_device); + sci_device = &isci_device->sci; /* do common allocation and init of request object. */ status = isci_request_alloc_tmf( @@ -390,7 +390,7 @@ static void isci_tmf_timeout_cb(void *tmf_request_arg) /* Terminate the TMF transmit request. */ status = scic_controller_terminate_request( request->isci_host->core_controller, - to_sci_dev(request->isci_device), + &request->isci_device->sci, request->sci_request_handle ); @@ -448,7 +448,7 @@ int isci_task_execute_tmf( "%s: isci_device = %p\n", __func__, isci_device); - sci_device = to_sci_dev(isci_device); + sci_device = &isci_device->sci; /* Assign the pointer to the TMF's completion kernel wait structure. */ tmf->complete = &completion; @@ -784,9 +784,8 @@ static void isci_terminate_request_core( needs_cleanup_handling = true; status = scic_controller_terminate_request( isci_host->core_controller, - to_sci_dev(isci_device), - isci_request->sci_request_handle - ); + &isci_device->sci, + isci_request->sci_request_handle); } spin_unlock_irqrestore(&isci_host->scic_lock, flags); @@ -1483,9 +1482,8 @@ void isci_task_request_complete( scic_controller_complete_io( isci_host->core_controller, - to_sci_dev(isci_device), - request->sci_request_handle - ); + &isci_device->sci, + request->sci_request_handle); /* NULL the request handle to make sure it cannot be terminated * or completed again. */ @@ -1611,7 +1609,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) } spin_lock_irqsave(&isci_host->scic_lock, flags); - status = scic_remote_device_reset(to_sci_dev(isci_dev)); + status = scic_remote_device_reset(&isci_dev->sci); if (status != SCI_SUCCESS) { spin_unlock_irqrestore(&isci_host->scic_lock, flags); @@ -1645,7 +1643,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) /* WHAT TO DO HERE IF sas_phy_reset FAILS? */ spin_lock_irqsave(&isci_host->scic_lock, flags); - status = scic_remote_device_reset_complete(to_sci_dev(isci_dev)); + status = scic_remote_device_reset_complete(&isci_dev->sci); spin_unlock_irqrestore(&isci_host->scic_lock, flags); if (status != SCI_SUCCESS) { -- cgit v1.2.3 From 88f3b62ac131e2549b6c262cacbd47e8cca42d6e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 22 Apr 2011 19:18:03 -0700 Subject: isci: move remote_device handling out of the core Now that the core/lldd remote_device data structures are nominally unified merge the corresponding sources into the top-level directory. Also move the remote_node_context infrastructure which has no analog at the lldd level. Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 9 +- drivers/scsi/isci/core/scic_remote_device.h | 282 ---- drivers/scsi/isci/core/scic_sds_controller.c | 3 +- drivers/scsi/isci/core/scic_sds_controller.h | 2 +- drivers/scsi/isci/core/scic_sds_phy.c | 2 +- drivers/scsi/isci/core/scic_sds_port.c | 4 +- drivers/scsi/isci/core/scic_sds_remote_device.c | 1664 -------------------- drivers/scsi/isci/core/scic_sds_remote_device.h | 694 -------- .../scsi/isci/core/scic_sds_remote_node_context.c | 1227 --------------- .../scsi/isci/core/scic_sds_remote_node_context.h | 301 ---- .../scsi/isci/core/scic_sds_remote_node_table.c | 600 ------- .../scsi/isci/core/scic_sds_remote_node_table.h | 195 --- drivers/scsi/isci/core/scic_sds_request.c | 3 +- .../scsi/isci/core/scic_sds_smp_remote_device.c | 315 ---- drivers/scsi/isci/core/scic_sds_smp_request.c | 3 +- .../scsi/isci/core/scic_sds_stp_packet_request.c | 3 +- .../scsi/isci/core/scic_sds_stp_remote_device.c | 818 ---------- drivers/scsi/isci/core/scic_sds_stp_request.c | 3 +- drivers/scsi/isci/core/scu_remote_node_context.h | 229 --- drivers/scsi/isci/host.c | 4 +- drivers/scsi/isci/host.h | 1 - drivers/scsi/isci/init.c | 1 - drivers/scsi/isci/port.c | 1 - drivers/scsi/isci/port.h | 1 + drivers/scsi/isci/probe_roms.c | 1 - drivers/scsi/isci/remote_device.c | 1644 ++++++++++++++++++- drivers/scsi/isci/remote_device.h | 742 ++++++++- drivers/scsi/isci/remote_node_context.c | 1226 ++++++++++++++ drivers/scsi/isci/remote_node_context.h | 301 ++++ drivers/scsi/isci/remote_node_table.c | 600 +++++++ drivers/scsi/isci/remote_node_table.h | 195 +++ drivers/scsi/isci/request.c | 1 - drivers/scsi/isci/sata.c | 3 +- drivers/scsi/isci/scu_remote_node_context.h | 229 +++ drivers/scsi/isci/smp_remote_device.c | 314 ++++ drivers/scsi/isci/stp_remote_device.c | 817 ++++++++++ drivers/scsi/isci/task.c | 5 +- 37 files changed, 6005 insertions(+), 6438 deletions(-) delete mode 100644 drivers/scsi/isci/core/scic_remote_device.h delete mode 100644 drivers/scsi/isci/core/scic_sds_remote_device.c delete mode 100644 drivers/scsi/isci/core/scic_sds_remote_device.h delete mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_context.c delete mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_context.h delete mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_table.c delete mode 100644 drivers/scsi/isci/core/scic_sds_remote_node_table.h delete mode 100644 drivers/scsi/isci/core/scic_sds_smp_remote_device.c delete mode 100644 drivers/scsi/isci/core/scic_sds_stp_remote_device.c delete mode 100644 drivers/scsi/isci/core/scu_remote_node_context.h create mode 100644 drivers/scsi/isci/remote_node_context.c create mode 100644 drivers/scsi/isci/remote_node_context.h create mode 100644 drivers/scsi/isci/remote_node_table.c create mode 100644 drivers/scsi/isci/remote_node_table.h create mode 100644 drivers/scsi/isci/scu_remote_node_context.h create mode 100644 drivers/scsi/isci/smp_remote_device.c create mode 100644 drivers/scsi/isci/stp_remote_device.c diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 522e7a7c062e..ccc8c53f501d 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -10,20 +10,19 @@ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ remote_device.o port.o timers.o \ host.o task.o probe_roms.o \ + stp_remote_device.o \ + smp_remote_device.o \ + remote_node_context.o \ + remote_node_table.o \ core/scic_sds_controller.o \ - core/scic_sds_remote_device.o \ core/scic_sds_request.o \ core/scic_sds_stp_request.o \ core/scic_sds_stp_packet_request.o \ - core/scic_sds_stp_remote_device.o \ core/scic_sds_port.o \ core/scic_sds_port_configuration_agent.o \ core/scic_sds_phy.o \ core/scic_sds_ssp_request.o \ - core/scic_sds_remote_node_context.o \ core/scic_sds_smp_request.o \ - core/scic_sds_smp_remote_device.o \ - core/scic_sds_remote_node_table.o \ core/scic_sds_unsolicited_frame_control.o \ core/sci_base_state_machine.o \ core/sci_util.o diff --git a/drivers/scsi/isci/core/scic_remote_device.h b/drivers/scsi/isci/core/scic_remote_device.h deleted file mode 100644 index 23e90af5a01b..000000000000 --- a/drivers/scsi/isci/core/scic_remote_device.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_REMOTE_DEVICE_H_ -#define _SCIC_REMOTE_DEVICE_H_ - -/** - * This file contains all of the interface methods that can be called by an - * SCIC user on the device object. - * - * - */ - - -#include "sci_status.h" -#include "intel_sas.h" - -struct scic_sds_port; -struct scic_sds_remote_device; - -/** - * - * - * - */ -enum scic_remote_device_not_ready_reason_code { - SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED, - SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED, - SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED, - SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED, - SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED, - - SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX - -}; - -/** - * scic_remote_device_construct() - This method will perform the construction - * common to all remote device objects. - * @sci_port: SAS/SATA port through which this device is accessed. - * @sci_dev: remote device to construct - * - * It isn't necessary to call scic_remote_device_destruct() for device objects - * that have only called this method for construction. Once subsequent - * construction methods have been invoked (e.g. - * scic_remote_device_da_construct()), then destruction should occur. none - */ -void scic_remote_device_construct(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev); - -/** - * scic_remote_device_da_construct() - This method will construct a - * SCIC_REMOTE_DEVICE object for a direct attached (da) device. The - * information (e.g. IAF, Signature FIS, etc.) necessary to build the device - * is known to the SCI Core since it is contained in the scic_phy object. - * @remote_device: This parameter specifies the remote device to be destructed. - * - * The user must have previously called scic_remote_device_construct() Remote - * device objects are a limited resource. As such, they must be protected. - * Thus calls to construct and destruct are mutually exclusive and - * non-reentrant. Indicate if the remote device was successfully constructed. - * SCI_SUCCESS Returned if the device was successfully constructed. - * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been - * constructed. If it's an additional phy for the target, then call - * scic_remote_device_da_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned - * if the supplied parameters necessitate creation of a remote device for which - * the protocol is not supported by the underlying controller hardware. - * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core - * controller associated with the supplied parameters is unable to support - * additional remote devices. - */ -enum sci_status scic_remote_device_da_construct( - struct scic_sds_remote_device *remote_device); - -/** - * scic_remote_device_ea_construct() - This method will construct an - * SCIC_REMOTE_DEVICE object for an expander attached (ea) device from an - * SMP Discover Response. - * @remote_device: This parameter specifies the remote device to be destructed. - * @discover_response: This parameter specifies the SMP Discovery Response to - * be used in device creation. - * - * The user must have previously called scic_remote_device_construct() Remote - * device objects are a limited resource. As such, they must be protected. - * Thus calls to construct and destruct are mutually exclusive and - * non-reentrant. Indicate if the remote device was successfully constructed. - * SCI_SUCCESS Returned if the device was successfully constructed. - * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been - * constructed. If it's an additional phy for the target, then call - * scic_ea_remote_device_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned - * if the supplied parameters necessitate creation of a remote device for which - * the protocol is not supported by the underlying controller hardware. - * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core - * controller associated with the supplied parameters is unable to support - * additional remote devices. - */ -enum sci_status scic_remote_device_ea_construct( - struct scic_sds_remote_device *remote_device, - struct smp_response_discover *discover_response); - -/** - * scic_remote_device_destruct() - This method is utilized to free up a core's - * remote device object. - * @remote_device: This parameter specifies the remote device to be destructed. - * - * Remote device objects are a limited resource. As such, they must be - * protected. Thus calls to construct and destruct are mutually exclusive and - * non-reentrant. The return value shall indicate if the device was - * successfully destructed or if some failure occurred. enum sci_status This value - * is returned if the device is successfully destructed. - * SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied - * device isn't valid (e.g. it's already been destoryed, the handle isn't - * valid, etc.). - */ -enum sci_status scic_remote_device_destruct( - struct scic_sds_remote_device *remote_device); - - - - - -/** - * scic_remote_device_start() - This method will start the supplied remote - * device. This method enables normal IO requests to flow through to the - * remote device. - * @remote_device: This parameter specifies the device to be started. - * @timeout: This parameter specifies the number of milliseconds in which the - * start operation should complete. - * - * An indication of whether the device was successfully started. SCI_SUCCESS - * This value is returned if the device was successfully started. - * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start - * the device when there have been no phys added to it. - */ -enum sci_status scic_remote_device_start( - struct scic_sds_remote_device *remote_device, - u32 timeout); - -/** - * scic_remote_device_stop() - This method will stop both transmission and - * reception of link activity for the supplied remote device. This method - * disables normal IO requests from flowing through to the remote device. - * @remote_device: This parameter specifies the device to be stopped. - * @timeout: This parameter specifies the number of milliseconds in which the - * stop operation should complete. - * - * An indication of whether the device was successfully stopped. SCI_SUCCESS - * This value is returned if the transmission and reception for the device was - * successfully stopped. - */ -enum sci_status scic_remote_device_stop( - struct scic_sds_remote_device *remote_device, - u32 timeout); - -/** - * scic_remote_device_reset() - This method will reset the device making it - * ready for operation. This method must be called anytime the device is - * reset either through a SMP phy control or a port hard reset request. - * @remote_device: This parameter specifies the device to be reset. - * - * This method does not actually cause the device hardware to be reset. This - * method resets the software object so that it will be operational after a - * device hardware reset completes. An indication of whether the device reset - * was accepted. SCI_SUCCESS This value is returned if the device reset is - * started. - */ -enum sci_status scic_remote_device_reset( - struct scic_sds_remote_device *remote_device); - -/** - * scic_remote_device_reset_complete() - This method informs the device object - * that the reset operation is complete and the device can resume operation - * again. - * @remote_device: This parameter specifies the device which is to be informed - * of the reset complete operation. - * - * An indication that the device is resuming operation. SCI_SUCCESS the device - * is resuming operation. - */ -enum sci_status scic_remote_device_reset_complete( - struct scic_sds_remote_device *remote_device); - - - -/** - * scic_remote_device_get_connection_rate() - This method simply returns the - * link rate at which communications to the remote device occur. - * @remote_device: This parameter specifies the device for which to get the - * connection rate. - * - * Return the link rate at which we transfer for the supplied remote device. - */ -enum sas_linkrate scic_remote_device_get_connection_rate( - struct scic_sds_remote_device *remote_device); - -/** - * scic_remote_device_get_protocols() - This method will indicate which - * protocols are supported by this remote device. - * @remote_device: This parameter specifies the device for which to return the - * protocol. - * @protocols: This parameter specifies the output values, from the remote - * device object, which indicate the protocols supported by the supplied - * remote_device. - * - * The type of protocols supported by this device. The values are returned as - * part of a bit mask in order to allow for multi-protocol support. - */ -void scic_remote_device_get_protocols( - struct scic_sds_remote_device *remote_device, - struct smp_discover_response_protocols *protocols); - - -#if !defined(DISABLE_ATAPI) -/** - * scic_remote_device_is_atapi() - - * @this_device: The device whose type is to be decided. - * - * This method first decide whether a device is a stp target, then decode the - * signature fis of a DA STP device to tell whether it is a standard end disk - * or an ATAPI device. bool Indicate a device is ATAPI device or not. - */ -bool scic_remote_device_is_atapi( - struct scic_sds_remote_device *device_handle); -#else /* !defined(DISABLE_ATAPI) */ -#define scic_remote_device_is_atapi(device_handle) false -#endif /* !defined(DISABLE_ATAPI) */ - - -#endif /* _SCIC_REMOTE_DEVICE_H_ */ - diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 63f4cd130d1d..c684d9ec8c97 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -57,13 +57,12 @@ #include "scic_controller.h" #include "scic_phy.h" #include "scic_port.h" -#include "scic_remote_device.h" #include "scic_sds_controller.h" #include "scu_registers.h" #include "scic_sds_phy.h" #include "scic_sds_port_configuration_agent.h" #include "scic_sds_port.h" -#include "scic_sds_remote_device.h" +#include "remote_device.h" #include "scic_sds_request.h" #include "sci_environment.h" #include "sci_util.h" diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 4bb9a43fbe4d..e15c4e2fd76d 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -73,7 +73,7 @@ #include "scic_config_parameters.h" #include "scic_sds_port.h" #include "scic_sds_phy.h" -#include "scic_sds_remote_node_table.h" +#include "remote_node_table.h" #include "scu_registers.h" #include "scu_constants.h" #include "scu_remote_node_context.h" diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 34bd3b25ccf6..09018466f993 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -61,7 +61,7 @@ #include "scic_sds_controller.h" #include "scic_sds_phy.h" #include "scic_sds_port.h" -#include "scic_sds_remote_node_context.h" +#include "remote_node_context.h" #include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index a8d7e51bdf7b..b07e48e2f188 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -60,8 +60,8 @@ #include "scic_sds_controller.h" #include "scic_sds_phy.h" #include "scic_sds_port.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_remote_node_context.h" +#include "remote_device.h" +#include "remote_node_context.h" #include "scic_sds_request.h" #include "sci_environment.h" #include "scu_registers.h" diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c deleted file mode 100644 index d314e2b2088b..000000000000 --- a/drivers/scsi/isci/core/scic_sds_remote_device.c +++ /dev/null @@ -1,1664 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "intel_sas.h" -#include "scic_controller.h" -#include "scic_phy.h" -#include "scic_port.h" -#include "scic_remote_device.h" -#include "scic_sds_controller.h" -#include "scic_sds_phy.h" -#include "scic_sds_port.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_remote_node_context.h" -#include "scic_sds_request.h" -#include "sci_environment.h" -#include "sci_util.h" -#include "scu_event_codes.h" - - -#define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT (1000) - -enum sci_status scic_remote_device_da_construct( - struct scic_sds_remote_device *sci_dev) -{ - enum sci_status status; - u16 remote_node_index; - struct sci_sas_identify_address_frame_protocols protocols; - - /* - * This information is request to determine how many remote node context - * entries will be needed to store the remote node. - */ - scic_sds_port_get_attached_protocols(sci_dev->owning_port, &protocols); - sci_dev->target_protocols.u.all = protocols.u.all; - sci_dev->is_direct_attached = true; -#if !defined(DISABLE_ATAPI) - sci_dev->is_atapi = scic_sds_remote_device_is_atapi(sci_dev); -#endif - - status = scic_sds_controller_allocate_remote_node_context( - sci_dev->owning_port->owning_controller, - sci_dev, - &remote_node_index); - - if (status == SCI_SUCCESS) { - sci_dev->rnc.remote_node_index = remote_node_index; - - scic_sds_port_get_attached_sas_address( - sci_dev->owning_port, &sci_dev->device_address); - - if (sci_dev->target_protocols.u.bits.attached_ssp_target) { - sci_dev->has_ready_substate_machine = false; - } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { - sci_dev->has_ready_substate_machine = true; - - sci_base_state_machine_construct( - &sci_dev->ready_substate_machine, - &sci_dev->parent, - scic_sds_stp_remote_device_ready_substate_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { - sci_dev->has_ready_substate_machine = true; - - /* add the SMP ready substate machine construction here */ - sci_base_state_machine_construct( - &sci_dev->ready_substate_machine, - &sci_dev->parent, - scic_sds_smp_remote_device_ready_substate_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } - - sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed( - sci_dev->owning_port); - - /* / @todo Should I assign the port width by reading all of the phys on the port? */ - sci_dev->device_port_width = 1; - } - - return status; -} - - -static void scic_sds_remote_device_get_info_from_smp_discover_response( - struct scic_sds_remote_device *sci_dev, - struct smp_response_discover *discover_response) -{ - /* decode discover_response to set sas_address to sci_dev. */ - sci_dev->device_address.high = - discover_response->attached_sas_address.high; - - sci_dev->device_address.low = - discover_response->attached_sas_address.low; - - sci_dev->target_protocols.u.all = discover_response->protocols.u.all; -} - - -enum sci_status scic_remote_device_ea_construct( - struct scic_sds_remote_device *sci_dev, - struct smp_response_discover *discover_response) -{ - enum sci_status status; - struct scic_sds_controller *scic; - - scic = scic_sds_port_get_controller(sci_dev->owning_port); - - scic_sds_remote_device_get_info_from_smp_discover_response( - sci_dev, discover_response); - - status = scic_sds_controller_allocate_remote_node_context( - scic, sci_dev, &sci_dev->rnc.remote_node_index); - - if (status == SCI_SUCCESS) { - if (sci_dev->target_protocols.u.bits.attached_ssp_target) { - sci_dev->has_ready_substate_machine = false; - } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { - sci_dev->has_ready_substate_machine = true; - - /* add the SMP ready substate machine construction here */ - sci_base_state_machine_construct( - &sci_dev->ready_substate_machine, - &sci_dev->parent, - scic_sds_smp_remote_device_ready_substate_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { - sci_dev->has_ready_substate_machine = true; - - sci_base_state_machine_construct( - &sci_dev->ready_substate_machine, - &sci_dev->parent, - scic_sds_stp_remote_device_ready_substate_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } - - /* - * For SAS-2 the physical link rate is actually a logical link - * rate that incorporates multiplexing. The SCU doesn't - * incorporate multiplexing and for the purposes of the - * connection the logical link rate is that same as the - * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay - * one another, so this code works for both situations. */ - sci_dev->connection_rate = min_t(u16, - scic_sds_port_get_max_allowed_speed(sci_dev->owning_port), - discover_response->u2.sas1_1.negotiated_physical_link_rate - ); - - /* / @todo Should I assign the port width by reading all of the phys on the port? */ - sci_dev->device_port_width = 1; - } - - return status; -} - -enum sci_status scic_remote_device_destruct( - struct scic_sds_remote_device *sci_dev) -{ - return sci_dev->state_handlers->destruct_handler(sci_dev); -} - - -enum sci_status scic_remote_device_start( - struct scic_sds_remote_device *sci_dev, - u32 timeout) -{ - return sci_dev->state_handlers->start_handler(sci_dev); -} - - -enum sci_status scic_remote_device_stop( - struct scic_sds_remote_device *sci_dev, - u32 timeout) -{ - return sci_dev->state_handlers->stop_handler(sci_dev); -} - - -enum sci_status scic_remote_device_reset( - struct scic_sds_remote_device *sci_dev) -{ - return sci_dev->state_handlers->reset_handler(sci_dev); -} - - -enum sci_status scic_remote_device_reset_complete( - struct scic_sds_remote_device *sci_dev) -{ - return sci_dev->state_handlers->reset_complete_handler(sci_dev); -} - - -enum sas_linkrate scic_remote_device_get_connection_rate( - struct scic_sds_remote_device *sci_dev) -{ - return sci_dev->connection_rate; -} - - -void scic_remote_device_get_protocols( - struct scic_sds_remote_device *sci_dev, - struct smp_discover_response_protocols *pr) -{ - pr->u.all = sci_dev->target_protocols.u.all; -} - -#if !defined(DISABLE_ATAPI) -bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev) -{ - return sci_dev->is_atapi; -} -#endif - - -/* - * ***************************************************************************** - * * SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS - * ***************************************************************************** */ - -/** - * - * - * Remote device timer requirements - */ -#define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0) -#define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES) - - -/** - * - * @sci_dev: The remote device for which the suspend is being requested. - * - * This method invokes the remote device suspend state handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_suspend( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type) -{ - return sci_dev->state_handlers->suspend_handler(sci_dev, suspend_type); -} - -/** - * - * @sci_dev: The remote device for which the resume is being requested. - * - * This method invokes the remote device resume state handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_resume( - struct scic_sds_remote_device *sci_dev) -{ - return sci_dev->state_handlers->resume_handler(sci_dev); -} - -/** - * - * @sci_dev: The remote device for which the event handling is being - * requested. - * @frame_index: This is the frame index that is being processed. - * - * This method invokes the frame handler for the remote device state machine - * enum sci_status - */ -enum sci_status scic_sds_remote_device_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - return sci_dev->state_handlers->frame_handler(sci_dev, frame_index); -} - -/** - * - * @sci_dev: The remote device for which the event handling is being - * requested. - * @event_code: This is the event code that is to be processed. - * - * This method invokes the remote device event handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - return sci_dev->state_handlers->event_handler(sci_dev, event_code); -} - -/** - * - * @controller: The controller that is starting the io request. - * @sci_dev: The remote device for which the start io handling is being - * requested. - * @io_request: The io request that is being started. - * - * This method invokes the remote device start io handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_start_io( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request) -{ - return sci_dev->state_handlers->start_io_handler( - sci_dev, io_request); -} - -/** - * - * @controller: The controller that is completing the io request. - * @sci_dev: The remote device for which the complete io handling is being - * requested. - * @io_request: The io request that is being completed. - * - * This method invokes the remote device complete io handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_complete_io( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request) -{ - return sci_dev->state_handlers->complete_io_handler( - sci_dev, io_request); -} - -/** - * - * @controller: The controller that is starting the task request. - * @sci_dev: The remote device for which the start task handling is being - * requested. - * @io_request: The task request that is being started. - * - * This method invokes the remote device start task handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_start_task( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request) -{ - return sci_dev->state_handlers->start_task_handler( - sci_dev, io_request); -} - -/** - * - * @controller: The controller that is completing the task request. - * @sci_dev: The remote device for which the complete task handling is - * being requested. - * @io_request: The task request that is being completed. - * - * This method invokes the remote device complete task handler. enum sci_status - */ - -/** - * - * @sci_dev: - * @request: - * - * This method takes the request and bulids an appropriate SCU context for the - * request and then requests the controller to post the request. none - */ -void scic_sds_remote_device_post_request( - struct scic_sds_remote_device *sci_dev, - u32 request) -{ - u32 context; - - context = scic_sds_remote_device_build_command_context(sci_dev, request); - - scic_sds_controller_post_request( - scic_sds_remote_device_get_controller(sci_dev), - context - ); -} - -#if !defined(DISABLE_ATAPI) -/** - * - * @sci_dev: The device to be checked. - * - * This method check the signature fis of a stp device to decide whether a - * device is atapi or not. true if a device is atapi device. False if a device - * is not atapi. - */ -bool scic_sds_remote_device_is_atapi( - struct scic_sds_remote_device *sci_dev) -{ - if (!sci_dev->target_protocols.u.bits.attached_stp_target) - return false; - else if (sci_dev->is_direct_attached) { - struct scic_sds_phy *phy; - struct scic_sata_phy_properties properties; - struct sata_fis_reg_d2h *signature_fis; - phy = scic_sds_port_get_a_connected_phy(sci_dev->owning_port); - scic_sata_phy_get_properties(phy, &properties); - - /* decode the signature fis. */ - signature_fis = &(properties.signature_fis); - - if ((signature_fis->sector_count == 0x01) - && (signature_fis->lba_low == 0x01) - && (signature_fis->lba_mid == 0x14) - && (signature_fis->lba_high == 0xEB) - && ((signature_fis->device & 0x5F) == 0x00) - ) { - /* An ATA device supporting the PACKET command set. */ - return true; - } else - return false; - } else { - /* Expander supported ATAPI device is not currently supported. */ - return false; - } -} -#endif - -/** - * - * @user_parameter: This is cast to a remote device object. - * - * This method is called once the remote node context is ready to be freed. - * The remote device can now report that its stop operation is complete. none - */ -static void scic_sds_cb_remote_device_rnc_destruct_complete( - void *user_parameter) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)user_parameter; - - BUG_ON(sci_dev->started_request_count != 0); - - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); -} - -/** - * - * @user_parameter: This is cast to a remote device object. - * - * This method is called once the remote node context has transisitioned to a - * ready state. This is the indication that the remote device object can also - * transition to ready. none - */ -static void scic_sds_remote_device_resume_complete_handler( - void *user_parameter) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)user_parameter; - - if ( - sci_base_state_machine_get_state(&sci_dev->state_machine) - != SCI_BASE_REMOTE_DEVICE_STATE_READY - ) { - sci_base_state_machine_change_state( - &sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_READY - ); - } -} - -/** - * - * @device: This parameter specifies the device for which the request is being - * started. - * @request: This parameter specifies the request being started. - * @status: This parameter specifies the current start operation status. - * - * This method will perform the STP request start processing common to IO - * requests and task requests of all types. none - */ -void scic_sds_remote_device_start_request( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req, - enum sci_status status) -{ - /* We still have a fault in starting the io complete it on the port */ - if (status == SCI_SUCCESS) - scic_sds_remote_device_increment_request_count(sci_dev); - else{ - sci_dev->owning_port->state_handlers->complete_io_handler( - sci_dev->owning_port, sci_dev, sci_req - ); - } -} - - -/** - * - * @request: This parameter specifies the request being continued. - * - * This method will continue to post tc for a STP request. This method usually - * serves as a callback when RNC gets resumed during a task management - * sequence. none - */ -void scic_sds_remote_device_continue_request(void *dev) -{ - struct scic_sds_remote_device *sci_dev = dev; - - /* we need to check if this request is still valid to continue. */ - if (sci_dev->working_request) - scic_controller_continue_io(sci_dev->working_request); -} - -/** - * - * @user_parameter: This is cast to a remote device object. - * - * This method is called once the remote node context has reached a suspended - * state. The remote device can now report that its suspend operation is - * complete. none - */ - -/** - * This method will terminate all of the IO requests in the controllers IO - * request table that were targeted for this device. - * @sci_dev: This parameter specifies the remote device for which to - * attempt to terminate all requests. - * - * This method returns an indication as to whether all requests were - * successfully terminated. If a single request fails to be terminated, then - * this method will return the failure. - */ -static enum sci_status scic_sds_remote_device_terminate_requests( - struct scic_sds_remote_device *sci_dev) -{ - enum sci_status status = SCI_SUCCESS; - enum sci_status terminate_status = SCI_SUCCESS; - struct scic_sds_request *sci_req; - u32 index; - u32 request_count = sci_dev->started_request_count; - - for (index = 0; - (index < SCI_MAX_IO_REQUESTS) && (request_count > 0); - index++) { - sci_req = sci_dev->owning_port->owning_controller->io_request_table[index]; - - if ((sci_req != NULL) && (sci_req->target_device == sci_dev)) { - terminate_status = scic_controller_terminate_request( - sci_dev->owning_port->owning_controller, - sci_dev, - sci_req - ); - - if (terminate_status != SCI_SUCCESS) - status = terminate_status; - - request_count--; - } - } - - return status; -} - -static enum sci_status -default_device_handler(struct scic_sds_remote_device *sci_dev, - const char *func) -{ - dev_warn(scirdev_to_dev(sci_dev), - "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&sci_dev->state_machine)); - return SCI_FAILURE_INVALID_STATE; -} - -enum sci_status scic_sds_remote_device_default_start_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - -static enum sci_status scic_sds_remote_device_default_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - -enum sci_status scic_sds_remote_device_default_fail_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - -enum sci_status scic_sds_remote_device_default_destruct_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - -enum sci_status scic_sds_remote_device_default_reset_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - -enum sci_status scic_sds_remote_device_default_reset_complete_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - -enum sci_status scic_sds_remote_device_default_suspend_handler( - struct scic_sds_remote_device *sci_dev, u32 suspend_type) -{ - return default_device_handler(sci_dev, __func__); -} - -enum sci_status scic_sds_remote_device_default_resume_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - -/** - * - * @device: The struct scic_sds_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @event_code: The event code that the struct scic_sds_controller wants the device - * object to process. - * - * This method is the default event handler. It will call the RNC state - * machine handler for any RNC events otherwise it will log a warning and - * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_remote_device_core_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code, - bool is_ready_state) -{ - enum sci_status status; - - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TYPE_RNC_OPS_MISC: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - status = scic_sds_remote_node_context_event_handler(&sci_dev->rnc, event_code); - break; - case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: - - if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { - status = SCI_SUCCESS; - - /* Suspend the associated RNC */ - scic_sds_remote_node_context_suspend(&sci_dev->rnc, - SCI_SOFTWARE_SUSPENSION, - NULL, NULL); - - dev_dbg(scirdev_to_dev(sci_dev), - "%s: device: %p event code: %x: %s\n", - __func__, sci_dev, event_code, - (is_ready_state) - ? "I_T_Nexus_Timeout event" - : "I_T_Nexus_Timeout event in wrong state"); - - break; - } - /* Else, fall through and treat as unhandled... */ - - default: - dev_dbg(scirdev_to_dev(sci_dev), - "%s: device: %p event code: %x: %s\n", - __func__, sci_dev, event_code, - (is_ready_state) - ? "unexpected event" - : "unexpected event in wrong state"); - status = SCI_FAILURE_INVALID_STATE; - break; - } - - return status; -} -/** - * - * @device: The struct scic_sds_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @event_code: The event code that the struct scic_sds_controller wants the device - * object to process. - * - * This method is the default event handler. It will call the RNC state - * machine handler for any RNC events otherwise it will log a warning and - * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_remote_device_default_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - return scic_sds_remote_device_core_event_handler(sci_dev, - event_code, - false); -} - -/** - * - * @device: The struct scic_sds_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @frame_index: The frame index for which the struct scic_sds_controller wants this - * device object to process. - * - * This method is the default unsolicited frame handler. It logs a warning, - * releases the frame and returns a failure. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_remote_device_default_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - dev_warn(scirdev_to_dev(sci_dev), - "%s: SCIC Remote Device requested to handle frame %x " - "while in wrong state %d\n", - __func__, - frame_index, - sci_base_state_machine_get_state( - &sci_dev->state_machine)); - - /* Return the frame back to the controller */ - scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(sci_dev), frame_index - ); - - return SCI_FAILURE_INVALID_STATE; -} - -enum sci_status scic_sds_remote_device_default_start_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - return default_device_handler(sci_dev, __func__); -} - -enum sci_status scic_sds_remote_device_default_complete_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - return default_device_handler(sci_dev, __func__); -} - -enum sci_status scic_sds_remote_device_default_continue_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - return default_device_handler(sci_dev, __func__); -} - -/** - * - * @device: The struct scic_sds_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @frame_index: The frame index for which the struct scic_sds_controller wants this - * device object to process. - * - * This method is a general ssp frame handler. In most cases the device object - * needs to route the unsolicited frame processing to the io request object. - * This method decodes the tag for the io request object and routes the - * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE - */ -enum sci_status scic_sds_remote_device_general_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status result; - struct sci_ssp_frame_header *frame_header; - struct scic_sds_request *io_request; - - result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), - frame_index, - (void **)&frame_header - ); - - if (SCI_SUCCESS == result) { - io_request = scic_sds_controller_get_io_request_from_tag( - scic_sds_remote_device_get_controller(sci_dev), frame_header->tag); - - if ((io_request == NULL) - || (io_request->target_device != sci_dev)) { - /* - * We could not map this tag to a valid IO request - * Just toss the frame and continue */ - scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(sci_dev), frame_index - ); - } else { - /* The IO request is now in charge of releasing the frame */ - result = io_request->state_handlers->frame_handler( - io_request, frame_index); - } - } - - return result; -} - -/** - * - * @[in]: sci_dev This is the device object that is receiving the event. - * @[in]: event_code The event code to process. - * - * This is a common method for handling events reported to the remote device - * from the controller object. enum sci_status - */ -enum sci_status scic_sds_remote_device_general_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - return scic_sds_remote_device_core_event_handler(sci_dev, - event_code, - true); -} - -/* - * ***************************************************************************** - * * STOPPED STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @device: - * - * This method takes the struct scic_sds_remote_device from a stopped state and - * attempts to start it. The RNC buffer for the device is constructed and the - * device state machine is transitioned to the - * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING. enum sci_status SCI_SUCCESS if there is - * an RNC buffer available to construct the remote device. - * SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer available in - * which to construct the remote device. - */ -static enum sci_status scic_sds_remote_device_stopped_state_start_handler( - struct scic_sds_remote_device *sci_dev) -{ - enum sci_status status; - - status = scic_sds_remote_node_context_resume(&sci_dev->rnc, - scic_sds_remote_device_resume_complete_handler, sci_dev); - - if (status == SCI_SUCCESS) - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STARTING); - - return status; -} - -static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - return SCI_SUCCESS; -} - -/** - * - * @sci_dev: The struct scic_sds_remote_device which is cast into a - * struct scic_sds_remote_device. - * - * This method will destruct a struct scic_sds_remote_device that is in a stopped - * state. This is the only state from which a destruct request will succeed. - * The RNi for this struct scic_sds_remote_device is returned to the free pool and the - * device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( - struct scic_sds_remote_device *sci_dev) -{ - struct scic_sds_controller *scic; - - scic = scic_sds_remote_device_get_controller(sci_dev); - scic_sds_controller_free_remote_node_context(scic, sci_dev, - sci_dev->rnc.remote_node_index); - sci_dev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_FINAL); - - return SCI_SUCCESS; -} - -/* - * ***************************************************************************** - * * STARTING STATE HANDLERS - * ***************************************************************************** */ - -static enum sci_status scic_sds_remote_device_starting_state_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - /* - * This device has not yet started so there had better be no IO requests - */ - BUG_ON(sci_dev->started_request_count != 0); - - /* - * Destroy the remote node context - */ - scic_sds_remote_node_context_destruct(&sci_dev->rnc, - scic_sds_cb_remote_device_rnc_destruct_complete, sci_dev); - - /* - * Transition to the stopping state and wait for the remote node to - * complete being posted and invalidated. - */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); - - return SCI_SUCCESS; -} - -enum sci_status scic_sds_remote_device_ready_state_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - enum sci_status status = SCI_SUCCESS; - - /* Request the parent state machine to transition to the stopping state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); - - if (sci_dev->started_request_count == 0) { - scic_sds_remote_node_context_destruct(&sci_dev->rnc, - scic_sds_cb_remote_device_rnc_destruct_complete, - sci_dev); - } else - status = scic_sds_remote_device_terminate_requests(sci_dev); - - return status; -} - -/** - * - * @device: The struct scic_sds_remote_device object which is cast to a - * struct scic_sds_remote_device object. - * - * This is the ready state device reset handler enum sci_status - */ -enum sci_status scic_sds_remote_device_ready_state_reset_handler( - struct scic_sds_remote_device *sci_dev) -{ - /* Request the parent state machine to transition to the stopping state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING); - - return SCI_SUCCESS; -} - -/* - * This method will attempt to start a task request for this device object. The - * remote device object will issue the start request for the task and if - * successful it will start the request for the port object then increment its - * own requet count. enum sci_status SCI_SUCCESS if the task request is started for - * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request - * object could not get the resources to start. - */ -static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status result; - - /* See if the port is in a state where we can start the IO request */ - result = scic_sds_port_start_io( - scic_sds_remote_device_get_port(sci_dev), sci_dev, request); - - if (result == SCI_SUCCESS) { - result = scic_sds_remote_node_context_start_task(&sci_dev->rnc, - request); - if (result == SCI_SUCCESS) - result = scic_sds_request_start(request); - - scic_sds_remote_device_start_request(sci_dev, request, result); - } - - return result; -} - -/* - * This method will attempt to start an io request for this device object. The - * remote device object will issue the start request for the io and if - * successful it will start the request for the port object then increment its - * own requet count. enum sci_status SCI_SUCCESS if the io request is started for - * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request - * object could not get the resources to start. - */ -static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status result; - - /* See if the port is in a state where we can start the IO request */ - result = scic_sds_port_start_io( - scic_sds_remote_device_get_port(sci_dev), sci_dev, request); - - if (result == SCI_SUCCESS) { - result = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (result == SCI_SUCCESS) - result = scic_sds_request_start(request); - - scic_sds_remote_device_start_request(sci_dev, request, result); - } - - return result; -} - -/* - * This method will complete the request for the remote device object. The - * method will call the completion handler for the request object and if - * successful it will complete the request on the port object then decrement - * its own started_request_count. enum sci_status - */ -static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status result; - - result = scic_sds_request_complete(request); - - if (result != SCI_SUCCESS) - return result; - - /* See if the port is in a state - * where we can start the IO request */ - result = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(sci_dev), - sci_dev, request); - - if (result == SCI_SUCCESS) - scic_sds_remote_device_decrement_request_count(sci_dev); - - return result; -} - -/* - * ***************************************************************************** - * * STOPPING STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @sci_dev: The struct scic_sds_remote_device which is cast into a - * struct scic_sds_remote_device. - * - * This method will stop a struct scic_sds_remote_device that is already in the - * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an error - * since we allow a stop request on a device that is alreay stopping or - * stopped. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( - struct scic_sds_remote_device *device) -{ - /* - * All requests should have been terminated, but if there is an - * attempt to stop a device already in the stopping state, then - * try again to terminate. */ - return scic_sds_remote_device_terminate_requests(device); -} - - -/** - * - * @device: The device object for which the request is completing. - * @request: The task request that is being completed. - * - * This method completes requests for this struct scic_sds_remote_device while it is - * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the - * complete method for the request object and if that is successful the port - * object is called to complete the task request. Then the device object itself - * completes the task request. If struct scic_sds_remote_device started_request_count - * goes to 0 and the invalidate RNC request has completed the device object can - * transition to the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. enum sci_status - */ -static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status = SCI_SUCCESS; - - status = scic_sds_request_complete(request); - - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_port_complete_io(scic_sds_remote_device_get_port(sci_dev), - sci_dev, request); - if (status != SCI_SUCCESS) - return status; - - scic_sds_remote_device_decrement_request_count(sci_dev); - - if (scic_sds_remote_device_get_request_count(sci_dev) == 0) - scic_sds_remote_node_context_destruct(&sci_dev->rnc, - scic_sds_cb_remote_device_rnc_destruct_complete, - sci_dev); - return SCI_SUCCESS; -} - -/** - * - * @device: The struct scic_sds_remote_device which is to be cast into a - * struct scic_sds_remote_device object. - * - * This method will complete the reset operation when the device is in the - * resetting state. enum sci_status - */ -static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( - struct scic_sds_remote_device *sci_dev) -{ - - sci_base_state_machine_change_state( - &sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_READY - ); - - return SCI_SUCCESS; -} - -/** - * - * @device: The struct scic_sds_remote_device which is to be cast into a - * struct scic_sds_remote_device object. - * - * This method will stop the remote device while in the resetting state. - * enum sci_status - */ -static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - sci_base_state_machine_change_state( - &sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING - ); - - return SCI_SUCCESS; -} - -/* - * This method completes requests for this struct scic_sds_remote_device while it is - * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the - * complete method for the request object and if that is successful the port - * object is called to complete the task request. Then the device object itself - * completes the task request. enum sci_status - */ -static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status = SCI_SUCCESS; - - status = scic_sds_request_complete(request); - - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(sci_dev), - sci_dev, request); - - if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(sci_dev); - } - } - - return status; -} - -/* - * ***************************************************************************** - * * FAILED STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @device: The struct scic_sds_remote_device which is to be cast into a - * struct scic_sds_remote_device object. - * - * This method handles the remove request for a failed struct scic_sds_remote_device - * object. The method will transition the device object to the - * SCIC_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status SCI_SUCCESS - */ - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { - [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_default_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .start_handler = scic_sds_remote_device_stopped_state_start_handler, - .stop_handler = scic_sds_remote_device_stopped_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_starting_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, - .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, - .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler, - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_stopping_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_default_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_resetting_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_default_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - } -}; - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it - * immediatly transitions the remote device object to the stopped state. none - */ -static void scic_sds_remote_device_initial_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - - sci_dev = container_of(object, typeof(*sci_dev), parent); - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); - - /* Initial state is a transitional state to the stopped state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it - * sets the stopped state handlers and if this state is entered from the - * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that the - * device stop is complete. none - */ -static void scic_sds_remote_device_stopped_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev; - struct scic_sds_controller *scic; - struct isci_remote_device *idev; - struct isci_host *ihost; - u32 prev_state; - - sci_dev = container_of(object, typeof(*sci_dev), parent); - scic = scic_sds_remote_device_get_controller(sci_dev); - ihost = sci_object_get_association(scic); - idev = sci_object_get_association(sci_dev); - - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); - - /* If we are entering from the stopping state let the SCI User know that - * the stop operation has completed. - */ - prev_state = sci_dev->state_machine.previous_state_id; - if (prev_state == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) - isci_remote_device_stop_complete(ihost, idev, SCI_SUCCESS); - - scic_sds_controller_remote_device_stopped(scic, sci_dev); -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it - * sets the starting state handlers, sets the device not ready, and posts the - * remote node context to the hardware. none - */ -static void scic_sds_remote_device_starting_state_enter(struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STARTING); - - isci_remote_device_not_ready(ihost, idev, - SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); -} - -static void scic_sds_remote_device_starting_state_exit(struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - - /* - * @todo Check the device object for the proper return code for this - * callback - */ - isci_remote_device_start_complete(ihost, idev, SCI_SUCCESS); -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets - * the ready state handlers, and starts the ready substate machine. none - */ -static void scic_sds_remote_device_ready_state_enter(struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - - SET_STATE_HANDLER(sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_READY); - - scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; - - if (sci_dev->has_ready_substate_machine) - sci_base_state_machine_start(&sci_dev->ready_substate_machine); - else - isci_remote_device_ready(ihost, idev); -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the exit function for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does - * nothing. none - */ -static void scic_sds_remote_device_ready_state_exit( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - if (sci_dev->has_ready_substate_machine) - sci_base_state_machine_stop(&sci_dev->ready_substate_machine); - else { - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - - isci_remote_device_not_ready(ihost, idev, - SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); - } -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it - * sets the stopping state handlers and posts an RNC invalidate request to the - * SCU hardware. none - */ -static void scic_sds_remote_device_stopping_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING - ); -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it sets - * the stopping state handlers. none - */ -static void scic_sds_remote_device_failed_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_FAILED - ); -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it - * sets the resetting state handlers. none - */ -static void scic_sds_remote_device_resetting_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING - ); - - scic_sds_remote_node_context_suspend( - &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it - * does nothing. none - */ -static void scic_sds_remote_device_resetting_state_exit( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - - scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); -} - -/** - * - * @object: This is the struct sci_base_object that is cast into a - * struct scic_sds_remote_device. - * - * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets - * the final state handlers. none - */ -static void scic_sds_remote_device_final_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_FINAL - ); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_remote_device_state_table[] = { - [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .enter_state = scic_sds_remote_device_initial_state_enter, - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .enter_state = scic_sds_remote_device_stopped_state_enter, - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .enter_state = scic_sds_remote_device_starting_state_enter, - .exit_state = scic_sds_remote_device_starting_state_exit - }, - [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .enter_state = scic_sds_remote_device_ready_state_enter, - .exit_state = scic_sds_remote_device_ready_state_exit - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .enter_state = scic_sds_remote_device_stopping_state_enter, - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .enter_state = scic_sds_remote_device_failed_state_enter, - }, - [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .enter_state = scic_sds_remote_device_resetting_state_enter, - .exit_state = scic_sds_remote_device_resetting_state_exit - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .enter_state = scic_sds_remote_device_final_state_enter, - }, -}; - -void scic_remote_device_construct(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev) -{ - sci_dev->owning_port = sci_port; - sci_dev->started_request_count = 0; - sci_dev->parent.private = NULL; - - sci_base_state_machine_construct( - &sci_dev->state_machine, - &sci_dev->parent, - scic_sds_remote_device_state_table, - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL - ); - - sci_base_state_machine_start( - &sci_dev->state_machine - ); - - scic_sds_remote_node_context_construct(&sci_dev->rnc, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); - - sci_object_set_association(&sci_dev->rnc, sci_dev); -} diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h deleted file mode 100644 index bff44b8b83ab..000000000000 --- a/drivers/scsi/isci/core/scic_sds_remote_device.h +++ /dev/null @@ -1,694 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_REMOTE_DEVICE_H_ -#define _SCIC_SDS_REMOTE_DEVICE_H_ - -#include "intel_sas.h" -#include "scu_remote_node_context.h" -#include "scic_sds_remote_node_context.h" -#include - -/** - * enum scic_sds_remote_device_states - This enumeration depicts all the states - * for the common remote device state machine. - * - * - */ -enum scic_sds_remote_device_states { - /** - * Simply the initial state for the base remote device state machine. - */ - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL, - - /** - * This state indicates that the remote device has successfully been - * stopped. In this state no new IO operations are permitted. - * This state is entered from the INITIAL state. - * This state is entered from the STOPPING state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED, - - /** - * This state indicates the the remote device is in the process of - * becoming ready (i.e. starting). In this state no new IO operations - * are permitted. - * This state is entered from the STOPPED state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_STARTING, - - /** - * This state indicates the remote device is now ready. Thus, the user - * is able to perform IO operations on the remote device. - * This state is entered from the STARTING state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_READY, - - /** - * This state indicates that the remote device is in the process of - * stopping. In this state no new IO operations are permitted, but - * existing IO operations are allowed to complete. - * This state is entered from the READY state. - * This state is entered from the FAILED state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, - - /** - * This state indicates that the remote device has failed. - * In this state no new IO operations are permitted. - * This state is entered from the INITIALIZING state. - * This state is entered from the READY state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_FAILED, - - /** - * This state indicates the device is being reset. - * In this state no new IO operations are permitted. - * This state is entered from the READY state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, - - /** - * Simply the final state for the base remote device state machine. - */ - SCI_BASE_REMOTE_DEVICE_STATE_FINAL, -}; - -/** - * enum scic_sds_ssp_remote_device_ready_substates - - * - * This is the enumeration of the ready substates for the - * struct scic_sds_remote_device. - */ -enum scic_sds_ssp_remote_device_ready_substates { - /** - * This is the initial state for the remote device ready substate. - */ - SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL, - - /** - * This is the ready operational substate for the remote device. - * This is the normal operational state for a remote device. - */ - SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL, - - /** - * This is the suspended state for the remote device. This is the state - * that the device is placed in when a RNC suspend is received by - * the SCU hardware. - */ - SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED, - - /** - * This is the final state that the device is placed in before a change - * to the base state machine. - */ - SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL, - - SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES -}; - -/** - * enum scic_sds_stp_remote_device_ready_substates - - * - * This is the enumeration for the struct scic_sds_remote_device ready substates - * for the STP remote device. - */ -enum scic_sds_stp_remote_device_ready_substates { - /** - * This is the idle substate for the stp remote device. When there are no - * active IO for the device it is is in this state. - */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, - - /** - * This is the command state for for the STP remote device. This state is - * entered when the device is processing a non-NCQ command. The device object - * will fail any new start IO requests until this command is complete. - */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD, - - /** - * This is the NCQ state for the STP remote device. This state is entered - * when the device is processing an NCQ reuqest. It will remain in this state - * so long as there is one or more NCQ requests being processed. - */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ, - - /** - * This is the NCQ error state for the STP remote device. This state is - * entered when an SDB error FIS is received by the device object while in the - * NCQ state. The device object will only accept a READ LOG command while in - * this state. - */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR, - -#if !defined(DISABLE_ATAPI) - /** - * This is the ATAPI error state for the STP ATAPI remote device. This state is - * entered when ATAPI device sends error status FIS without data while the device - * object is in CMD state. A suspension event is expected in this state. The device - * object will resume right away. - */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR, -#endif - - /** - * This is the READY substate indicates the device is waiting for the RESET task - * coming to be recovered from certain hardware specific error. - */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, -}; - -/** - * enum scic_sds_smp_remote_device_ready_substates - - * - * This is the enumeration of the ready substates for the SMP REMOTE DEVICE. - */ -enum scic_sds_smp_remote_device_ready_substates { - /** - * This is the ready operational substate for the remote device. This is the - * normal operational state for a remote device. - */ - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, - - /** - * This is the suspended state for the remote device. This is the state that - * the device is placed in when a RNC suspend is received by the SCU hardware. - */ - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, -}; - -/** - * struct scic_sds_remote_device - This structure contains the data for an SCU - * implementation of the SCU Core device data. - * - * - */ -struct scic_sds_remote_device { - /** - * The field specifies that the parent object for the base remote - * device is the base object itself. - */ - struct sci_base_object parent; - - /** - * This field contains the information for the base remote device state - * machine. - */ - struct sci_base_state_machine state_machine; - - /** - * This field is the programmed device port width. This value is - * written to the RCN data structure to tell the SCU how many open - * connections this device can have. - */ - u32 device_port_width; - - /** - * This field is the programmed connection rate for this remote device. It is - * used to program the TC with the maximum allowed connection rate. - */ - enum sas_linkrate connection_rate; - - /** - * This field contains the allowed target protocols for this remote device. - */ - struct smp_discover_response_protocols target_protocols; - - /** - * This field contains the device SAS address. - */ - struct sci_sas_address device_address; - - /** - * This filed is assinged the value of true if the device is directly - * attached to the port. - */ - bool is_direct_attached; - -#if !defined(DISABLE_ATAPI) - /** - * This filed is assinged the value of true if the device is an ATAPI - * device. - */ - bool is_atapi; -#endif - - /** - * This filed contains a pointer back to the port to which this device - * is assigned. - */ - struct scic_sds_port *owning_port; - - /** - * This field contains the SCU silicon remote node context specific - * information. - */ - struct scic_sds_remote_node_context rnc; - - /** - * This field contains the stated request count for the remote device. The - * device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all - * requests are complete and the rnc_posted value is false. - */ - u32 started_request_count; - - /** - * This field contains a pointer to the working request object. It is only - * used only for SATA requests since the unsolicited frames we get from the - * hardware have no Tag value to look up the io request object. - */ - struct scic_sds_request *working_request; - - /** - * This field contains the reason for the remote device going not_ready. It is - * assigned in the state handlers and used in the state transition. - */ - u32 not_ready_reason; - - /** - * This field is true if this remote device has an initialzied ready substate - * machine. SSP devices do not have a ready substate machine and STP devices - * have a ready substate machine. - */ - bool has_ready_substate_machine; - - /** - * This field contains the state machine for the ready substate machine for - * this struct scic_sds_remote_device object. - */ - struct sci_base_state_machine ready_substate_machine; - - /** - * This field maintains the set of state handlers for the remote device - * object. These are changed each time the remote device enters a new state. - */ - const struct scic_sds_remote_device_state_handler *state_handlers; -}; - -static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = container_of(rnc, typeof(*sci_dev), rnc); - - return sci_dev; -} - -typedef enum sci_status (*scic_sds_remote_device_request_handler_t)( - struct scic_sds_remote_device *device, - struct scic_sds_request *request); - -typedef enum sci_status (*scic_sds_remote_device_high_priority_request_complete_handler_t)( - struct scic_sds_remote_device *device, - struct scic_sds_request *request, - void *, - enum sci_io_status); - -typedef enum sci_status (*scic_sds_remote_device_handler_t)( - struct scic_sds_remote_device *sci_dev); - -typedef enum sci_status (*scic_sds_remote_device_suspend_handler_t)( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type); - -typedef enum sci_status (*scic_sds_remote_device_resume_handler_t)( - struct scic_sds_remote_device *sci_dev); - -typedef enum sci_status (*scic_sds_remote_device_frame_handler_t)( - struct scic_sds_remote_device *sci_dev, - u32 frame_index); - -typedef enum sci_status (*scic_sds_remote_device_event_handler_t)( - struct scic_sds_remote_device *sci_dev, - u32 event_code); - -typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( - struct scic_sds_remote_device *sci_dev); - -/** - * struct scic_sds_remote_device_state_handler - This structure conains the - * state handlers that are needed to process requests for the SCU remote - * device objects. - * - * - */ -struct scic_sds_remote_device_state_handler { - /** - * The start_handler specifies the method invoked when a user - * attempts to start a remote device. - */ - scic_sds_remote_device_handler_t start_handler; - - /** - * The stop_handler specifies the method invoked when a user attempts to - * stop a remote device. - */ - scic_sds_remote_device_handler_t stop_handler; - - /** - * The fail_handler specifies the method invoked when a remote device - * failure has occurred. A failure may be due to an inability to - * initialize/configure the device. - */ - scic_sds_remote_device_handler_t fail_handler; - - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a remote device. - */ - scic_sds_remote_device_handler_t destruct_handler; - - /** - * The reset handler specifies the method invloked when requesting to - * reset a remote device. - */ - scic_sds_remote_device_handler_t reset_handler; - - /** - * The reset complete handler specifies the method invloked when - * reporting that a reset has completed to the remote device. - */ - scic_sds_remote_device_handler_t reset_complete_handler; - - /** - * The start_io_handler specifies the method invoked when a user - * attempts to start an IO request for a remote device. - */ - scic_sds_remote_device_request_handler_t start_io_handler; - - /** - * The complete_io_handler specifies the method invoked when a user - * attempts to complete an IO request for a remote device. - */ - scic_sds_remote_device_request_handler_t complete_io_handler; - - /** - * The continue_io_handler specifies the method invoked when a user - * attempts to continue an IO request for a remote device. - */ - scic_sds_remote_device_request_handler_t continue_io_handler; - - /** - * The start_task_handler specifies the method invoked when a user - * attempts to start a task management request for a remote device. - */ - scic_sds_remote_device_request_handler_t start_task_handler; - - /** - * The complete_task_handler specifies the method invoked when a user - * attempts to complete a task management request for a remote device. - */ - scic_sds_remote_device_request_handler_t complete_task_handler; - - - scic_sds_remote_device_suspend_handler_t suspend_handler; - scic_sds_remote_device_resume_handler_t resume_handler; - scic_sds_remote_device_event_handler_t event_handler; - scic_sds_remote_device_frame_handler_t frame_handler; -}; - -extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[]; -extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[]; -extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[]; - -/** - * scic_sds_remote_device_increment_request_count() - - * - * This macro incrments the request count for this device - */ -#define scic_sds_remote_device_increment_request_count(sci_dev) \ - ((sci_dev)->started_request_count++) - -/** - * scic_sds_remote_device_decrement_request_count() - - * - * This macro decrements the request count for this device. This count will - * never decrment past 0. - */ -#define scic_sds_remote_device_decrement_request_count(sci_dev) \ - ((sci_dev)->started_request_count > 0 ? \ - (sci_dev)->started_request_count-- : 0) - -/** - * scic_sds_remote_device_get_request_count() - - * - * This is a helper macro to return the current device request count. - */ -#define scic_sds_remote_device_get_request_count(sci_dev) \ - ((sci_dev)->started_request_count) - -/** - * scic_sds_remote_device_get_port() - - * - * This macro returns the owning port of this remote device obejct. - */ -#define scic_sds_remote_device_get_port(sci_dev) \ - ((sci_dev)->owning_port) - -/** - * scic_sds_remote_device_get_controller() - - * - * This macro returns the controller object that contains this device object - */ -#define scic_sds_remote_device_get_controller(sci_dev) \ - scic_sds_port_get_controller(scic_sds_remote_device_get_port(sci_dev)) - -/** - * scic_sds_remote_device_set_state_handlers() - - * - * This macro sets the remote device state handlers pointer and is set on entry - * to each device state. - */ -#define scic_sds_remote_device_set_state_handlers(sci_dev, handlers) \ - ((sci_dev)->state_handlers = (handlers)) - -/** - * scic_sds_remote_device_get_port() - - * - * This macro returns the owning port of this device - */ -#define scic_sds_remote_device_get_port(sci_dev) \ - ((sci_dev)->owning_port) - -/** - * scic_sds_remote_device_get_sequence() - - * - * This macro returns the remote device sequence value - */ -#define scic_sds_remote_device_get_sequence(sci_dev) \ - (\ - scic_sds_remote_device_get_controller(sci_dev)-> \ - remote_device_sequence[(sci_dev)->rnc.remote_node_index] \ - ) - -/** - * scic_sds_remote_device_get_controller_peg() - - * - * This macro returns the controllers protocol engine group - */ -#define scic_sds_remote_device_get_controller_peg(sci_dev) \ - (\ - scic_sds_controller_get_protocol_engine_group(\ - scic_sds_port_get_controller(\ - scic_sds_remote_device_get_port(sci_dev) \ - ) \ - ) \ - ) - -/** - * scic_sds_remote_device_get_port_index() - - * - * This macro returns the port index for the devices owning port - */ -#define scic_sds_remote_device_get_port_index(sci_dev) \ - (scic_sds_port_get_index(scic_sds_remote_device_get_port(sci_dev))) - -/** - * scic_sds_remote_device_get_index() - - * - * This macro returns the remote node index for this device object - */ -#define scic_sds_remote_device_get_index(sci_dev) \ - ((sci_dev)->rnc.remote_node_index) - -/** - * scic_sds_remote_device_build_command_context() - - * - * This macro builds a remote device context for the SCU post request operation - */ -#define scic_sds_remote_device_build_command_context(device, command) \ - ((command) \ - | (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \ - | (scic_sds_remote_device_get_port_index((device)) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \ - | (scic_sds_remote_device_get_index((device))) \ - ) - -/** - * scic_sds_remote_device_set_working_request() - - * - * This macro makes the working request assingment for the remote device - * object. To clear the working request use this macro with a NULL request - * object. - */ -#define scic_sds_remote_device_set_working_request(device, request) \ - ((device)->working_request = (request)) - -enum sci_status scic_sds_remote_device_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index); - -enum sci_status scic_sds_remote_device_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code); - -enum sci_status scic_sds_remote_device_start_io( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request); - -enum sci_status scic_sds_remote_device_complete_io( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request); - -enum sci_status scic_sds_remote_device_resume( - struct scic_sds_remote_device *sci_dev); - -enum sci_status scic_sds_remote_device_suspend( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type); - -enum sci_status scic_sds_remote_device_start_task( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request); - -void scic_sds_remote_device_post_request( - struct scic_sds_remote_device *sci_dev, - u32 request); - -#if !defined(DISABLE_ATAPI) -bool scic_sds_remote_device_is_atapi( - struct scic_sds_remote_device *sci_dev); -#else /* !defined(DISABLE_ATAPI) */ -#define scic_sds_remote_device_is_atapi(sci_dev) false -#endif /* !defined(DISABLE_ATAPI) */ - -void scic_sds_remote_device_start_request( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req, - enum sci_status status); - -void scic_sds_remote_device_continue_request(void *sci_dev); - -enum sci_status scic_sds_remote_device_default_start_handler( - struct scic_sds_remote_device *sci_dev); - -enum sci_status scic_sds_remote_device_default_fail_handler( - struct scic_sds_remote_device *sci_dev); - -enum sci_status scic_sds_remote_device_default_destruct_handler( - struct scic_sds_remote_device *sci_dev); - -enum sci_status scic_sds_remote_device_default_reset_handler( - struct scic_sds_remote_device *device); - -enum sci_status scic_sds_remote_device_default_reset_complete_handler( - struct scic_sds_remote_device *device); - -enum sci_status scic_sds_remote_device_default_start_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request); - -enum sci_status scic_sds_remote_device_default_complete_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request); - -enum sci_status scic_sds_remote_device_default_continue_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request); - -enum sci_status scic_sds_remote_device_default_suspend_handler( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type); - -enum sci_status scic_sds_remote_device_default_resume_handler( - struct scic_sds_remote_device *sci_dev); - - -enum sci_status scic_sds_remote_device_default_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index); - -enum sci_status scic_sds_remote_device_ready_state_stop_handler( - struct scic_sds_remote_device *device); - -enum sci_status scic_sds_remote_device_ready_state_reset_handler( - struct scic_sds_remote_device *device); - -enum sci_status scic_sds_remote_device_general_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index); - -enum sci_status scic_sds_remote_device_general_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code); - -enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler( - struct scic_sds_remote_device *sci_dev); - -#endif /* _SCIC_SDS_REMOTE_DEVICE_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c deleted file mode 100644 index e1d58f8854f7..000000000000 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.c +++ /dev/null @@ -1,1227 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "sci_base_state_machine.h" -#include "scic_remote_device.h" -#include "scic_sds_controller.h" -#include "scic_sds_port.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_remote_node_context.h" -#include "sci_environment.h" -#include "sci_util.h" -#include "scu_event_codes.h" -#include "scu_task_context.h" - - -/** - * - * @sci_rnc: The RNC for which the is posted request is being made. - * - * This method will return true if the RNC is not in the initial state. In all - * other states the RNC is considered active and this will return true. The - * destroy request of the state machine drives the RNC back to the initial - * state. If the state machine changes then this routine will also have to be - * changed. bool true if the state machine is not in the initial state false if - * the state machine is in the initial state - */ - -/** - * - * @sci_rnc: The state of the remote node context object to check. - * - * This method will return true if the remote node context is in a READY state - * otherwise it will return false bool true if the remote node context is in - * the ready state. false if the remote node context is not in the ready state. - */ -bool scic_sds_remote_node_context_is_ready( - struct scic_sds_remote_node_context *sci_rnc) -{ - u32 current_state = sci_base_state_machine_get_state(&sci_rnc->state_machine); - - if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { - return true; - } - - return false; -} - -/** - * - * @sci_dev: The remote device to use to construct the RNC buffer. - * @rnc: The buffer into which the remote device data will be copied. - * - * This method will construct the RNC buffer for this remote device object. none - */ -static void scic_sds_remote_node_context_construct_buffer( - struct scic_sds_remote_node_context *sci_rnc) -{ - union scu_remote_node_context *rnc; - struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); - struct scic_sds_controller *scic; - - scic = scic_sds_remote_device_get_controller(sci_dev); - - rnc = scic_sds_controller_get_remote_node_context_buffer( - scic, sci_rnc->remote_node_index); - - memset(rnc, 0, sizeof(union scu_remote_node_context) - * scic_sds_remote_device_node_count(sci_dev)); - - rnc->ssp.remote_node_index = sci_rnc->remote_node_index; - rnc->ssp.remote_node_port_width = sci_dev->device_port_width; - rnc->ssp.logical_port_index = - scic_sds_remote_device_get_port_index(sci_dev); - - rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(sci_dev->device_address.high); - rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(sci_dev->device_address.low); - - rnc->ssp.nexus_loss_timer_enable = true; - rnc->ssp.check_bit = false; - rnc->ssp.is_valid = false; - rnc->ssp.is_remote_node_context = true; - rnc->ssp.function_number = 0; - - rnc->ssp.arbitration_wait_time = 0; - - - if ( - sci_dev->target_protocols.u.bits.attached_sata_device - || sci_dev->target_protocols.u.bits.attached_stp_target - ) { - rnc->ssp.connection_occupancy_timeout = - scic->user_parameters.sds1.stp_max_occupancy_timeout; - rnc->ssp.connection_inactivity_timeout = - scic->user_parameters.sds1.stp_inactivity_timeout; - } else { - rnc->ssp.connection_occupancy_timeout = - scic->user_parameters.sds1.ssp_max_occupancy_timeout; - rnc->ssp.connection_inactivity_timeout = - scic->user_parameters.sds1.ssp_inactivity_timeout; - } - - rnc->ssp.initial_arbitration_wait_time = 0; - - /* Open Address Frame Parameters */ - rnc->ssp.oaf_connection_rate = sci_dev->connection_rate; - rnc->ssp.oaf_features = 0; - rnc->ssp.oaf_source_zone_group = 0; - rnc->ssp.oaf_more_compatibility_features = 0; -} - -/** - * - * @sci_rnc: - * @callback: - * @callback_parameter: - * - * This method will setup the remote node context object so it will transition - * to its ready state. If the remote node context is already setup to - * transition to its final state then this function does nothing. none - */ -static void scic_sds_remote_node_context_setup_to_resume( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { - sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY; - sci_rnc->user_callback = callback; - sci_rnc->user_cookie = callback_parameter; - } -} - -/** - * - * @sci_rnc: - * @callback: - * @callback_parameter: - * - * This method will setup the remote node context object so it will transistion - * to its final state. none - */ -static void scic_sds_remote_node_context_setup_to_destory( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; - sci_rnc->user_callback = callback; - sci_rnc->user_cookie = callback_parameter; -} - -/** - * - * @sci_rnc: - * @callback: - * - * This method will continue to resume a remote node context. This is used in - * the states where a resume is requested while a resume is in progress. - */ -static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { - sci_rnc->user_callback = callback; - sci_rnc->user_cookie = callback_parameter; - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_STATE; -} - -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_default_destruct_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to stop while " - "in unexpected state %d\n", - __func__, - sci_rnc, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - /* - * We have decided that the destruct request on the remote node context can not fail - * since it is either in the initial/destroyed state or is can be destroyed. */ - return SCI_SUCCESS; -} - -static enum sci_status scic_sds_remote_node_context_default_suspend_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 suspend_type, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to suspend " - "while in wrong state %d\n", - __func__, - sci_rnc, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_remote_node_context_default_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to resume " - "while in wrong state %d\n", - __func__, - sci_rnc, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_remote_node_context_default_start_io_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to start io " - "0x%p while in wrong state %d\n", - __func__, - sci_rnc, - sci_req, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; -} - -static enum sci_status scic_sds_remote_node_context_default_start_task_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to start " - "task 0x%p while in wrong state %d\n", - __func__, - sci_rnc, - sci_req, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE; -} - -static enum sci_status scic_sds_remote_node_context_default_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to process " - "event 0x%x while in wrong state %d\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * - * @sci_rnc: The rnc for which the task request is targeted. - * @sci_req: The request which is going to be started. - * - * This method determines if the task request can be started by the SCU - * hardware. When the RNC is in the ready state any task can be started. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_success_start_task_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - return SCI_SUCCESS; -} - -/** - * - * @sci_rnc: - * @callback: - * @callback_parameter: - * - * This method handles destruct calls from the various state handlers. The - * remote node context can be requested to destroy from any state. If there was - * a user callback it is always replaced with the request to destroy user - * callback. enum sci_status - */ -static enum sci_status scic_sds_remote_node_context_general_destruct_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - scic_sds_remote_node_context_setup_to_destory( - sci_rnc, callback, callback_parameter - ); - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE - ); - - return SCI_SUCCESS; -} - -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - if (sci_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - scic_sds_remote_node_context_setup_to_resume( - sci_rnc, callback, callback_parameter - ); - - scic_sds_remote_node_context_construct_buffer(sci_rnc); - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE - ); - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_STATE; -} - -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_POST_RNC_COMPLETE: - status = SCI_SUCCESS; - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE - ); - break; - - default: - status = SCI_FAILURE; - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to " - "process unexpected event 0x%x while in posting " - "state\n", - __func__, - sci_rnc, - event_code); - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - scic_sds_remote_node_context_setup_to_destory( - sci_rnc, callback, callback_parameter - ); - - return SCI_SUCCESS; -} - -static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { - status = SCI_SUCCESS; - - if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE - ); - } else { - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE - ); - } - } else { - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TYPE_RNC_SUSPEND_TX: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - /* - * We really dont care if the hardware is going to suspend - * the device since it's being invalidated anyway */ - dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p was " - "suspeneded by hardware while being " - "invalidated.\n", - __func__, - sci_rnc); - status = SCI_SUCCESS; - break; - - default: - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p " - "requested to process event 0x%x while " - "in state %d.\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state( - &sci_rnc->state_machine)); - status = SCI_FAILURE; - break; - } - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - - -static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) { - status = SCI_SUCCESS; - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE - ); - } else { - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TYPE_RNC_SUSPEND_TX: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - /* - * We really dont care if the hardware is going to suspend - * the device since it's being resumed anyway */ - dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p was " - "suspeneded by hardware while being resumed.\n", - __func__, - sci_rnc); - status = SCI_SUCCESS; - break; - - default: - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested " - "to process event 0x%x while in state %d.\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state( - &sci_rnc->state_machine)); - status = SCI_FAILURE; - break; - } - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - -/** - * - * @sci_rnc: The remote node context object being suspended. - * @callback: The callback when the suspension is complete. - * @callback_parameter: The parameter that is to be passed into the callback. - * - * This method will handle the suspend requests from the ready state. - * SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 suspend_type, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - sci_rnc->user_callback = callback; - sci_rnc->user_cookie = callback_parameter; - sci_rnc->suspension_code = suspend_type; - - if (suspend_type == SCI_SOFTWARE_SUSPENSION) { - scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), - SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); - } - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE - ); - - return SCI_SUCCESS; -} - -/** - * - * @sci_rnc: The rnc for which the io request is targeted. - * @sci_req: The request which is going to be started. - * - * This method determines if the io request can be started by the SCU hardware. - * When the RNC is in the ready state any io request can be started. enum sci_status - * SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - return SCI_SUCCESS; -} - - -static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TL_RNC_SUSPEND_TX: - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE - ); - - sci_rnc->suspension_code = scu_get_event_specifier(event_code); - status = SCI_SUCCESS; - break; - - case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE - ); - - sci_rnc->suspension_code = scu_get_event_specifier(event_code); - status = SCI_SUCCESS; - break; - - default: - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to " - "process event 0x%x while in state %d.\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state( - &sci_rnc->state_machine)); - - status = SCI_FAILURE; - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - enum sci_status status; - struct smp_discover_response_protocols protocols; - - scic_sds_remote_node_context_setup_to_resume( - sci_rnc, callback, callback_parameter - ); - - /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ - - scic_remote_device_get_protocols(rnc_to_dev(sci_rnc), &protocols); - - if ( - (protocols.u.bits.attached_ssp_target == 1) - || (protocols.u.bits.attached_smp_target == 1) - ) { - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE - ); - - status = SCI_SUCCESS; - } else if (protocols.u.bits.attached_stp_target == 1) { - if (rnc_to_dev(sci_rnc)->is_direct_attached) { - /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE - ); - } else { - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE - ); - } - - status = SCI_SUCCESS; - } else { - status = SCI_FAILURE; - } - - return status; -} - -/** - * - * @sci_rnc: The remote node context which is to receive the task request. - * @sci_req: The task request to be transmitted to to the remote target - * device. - * - * This method will report a success or failure attempt to start a new task - * request to the hardware. Since all task requests are sent on the high - * priority queue they can be sent when the RCN is in a TX suspend state. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - scic_sds_remote_node_context_resume(sci_rnc, NULL, NULL); - - return SCI_SUCCESS; -} - -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - scic_sds_remote_node_context_setup_to_resume( - sci_rnc, callback, callback_parameter - ); - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE - ); - - return SCI_FAILURE_INVALID_STATE; -} - -/* --------------------------------------------------------------------------- */ - -/** - * - * - * - */ -static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - scic_sds_remote_node_context_setup_to_resume( - sci_rnc, callback, callback_parameter - ); - - return SCI_SUCCESS; -} - -/** - * - * @sci_rnc: The remote node context which is to receive the task request. - * @sci_req: The task request to be transmitted to to the remote target - * device. - * - * This method will report a success or failure attempt to start a new task - * request to the hardware. Since all task requests are sent on the high - * priority queue they can be sent when the RCN is in a TX suspend state. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - return SCI_SUCCESS; -} - -static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TL_RNC_SUSPEND_TX: - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE - ); - - sci_rnc->suspension_code = scu_get_event_specifier(event_code); - status = SCI_SUCCESS; - break; - - case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE - ); - - sci_rnc->suspension_code = scu_get_event_specifier(event_code); - status = SCI_SUCCESS; - break; - - default: - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to " - "process event 0x%x while in state %d.\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state( - &sci_rnc->state_machine)); - - status = SCI_FAILURE; - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static struct scic_sds_remote_node_context_handlers -scic_sds_remote_node_context_state_handler_table[ - SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] = -{ - /* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */ - { - scic_sds_remote_node_context_default_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_initial_state_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_default_start_task_handler, - scic_sds_remote_node_context_default_event_handler - }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_continue_to_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_default_start_task_handler, - scic_sds_remote_node_context_posting_state_event_handler - }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */ - { - scic_sds_remote_node_context_invalidating_state_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_continue_to_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_default_start_task_handler, - scic_sds_remote_node_context_invalidating_state_event_handler - }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_continue_to_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_success_start_task_handler, - scic_sds_remote_node_context_resuming_state_event_handler - }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_ready_state_suspend_handler, - scic_sds_remote_node_context_default_resume_handler, - scic_sds_remote_node_context_ready_state_start_io_handler, - scic_sds_remote_node_context_success_start_task_handler, - scic_sds_remote_node_context_ready_state_event_handler - }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_tx_suspended_state_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_suspended_start_task_handler, - scic_sds_remote_node_context_default_event_handler - }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_suspended_start_task_handler, - scic_sds_remote_node_context_default_event_handler - }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_await_suspension_state_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_await_suspension_state_start_task_handler, - scic_sds_remote_node_context_await_suspension_state_event_handler - } -}; - -/* - * ***************************************************************************** - * * REMOTE NODE CONTEXT PRIVATE METHODS - * ***************************************************************************** */ - -/** - * - * - * This method just calls the user callback function and then resets the - * callback. - */ -static void scic_sds_remote_node_context_notify_user( - struct scic_sds_remote_node_context *rnc) -{ - if (rnc->user_callback != NULL) { - (*rnc->user_callback)(rnc->user_cookie); - - rnc->user_callback = NULL; - rnc->user_cookie = NULL; - } -} - -/** - * - * - * This method will continue the remote node context state machine by - * requesting to resume the remote node context state machine from its current - * state. - */ -static void scic_sds_remote_node_context_continue_state_transitions( - struct scic_sds_remote_node_context *rnc) -{ - if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { - rnc->state_handlers->resume_handler( - rnc, rnc->user_callback, rnc->user_cookie - ); - } -} - -/** - * - * @sci_rnc: The remote node context object that is to be validated. - * - * This method will mark the rnc buffer as being valid and post the request to - * the hardware. none - */ -static void scic_sds_remote_node_context_validate_context_buffer( - struct scic_sds_remote_node_context *sci_rnc) -{ - struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); - union scu_remote_node_context *rnc_buffer; - - rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(sci_dev), - sci_rnc->remote_node_index - ); - - rnc_buffer->ssp.is_valid = true; - - if (!sci_dev->is_direct_attached && - sci_dev->target_protocols.u.bits.attached_stp_target) { - scic_sds_remote_device_post_request(sci_dev, - SCU_CONTEXT_COMMAND_POST_RNC_96); - } else { - scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_32); - - if (sci_dev->is_direct_attached) { - scic_sds_port_setup_transports(sci_dev->owning_port, - sci_rnc->remote_node_index); - } - } -} - -/** - * - * @sci_rnc: The remote node context object that is to be invalidated. - * - * This method will update the RNC buffer and post the invalidate request. none - */ -static void scic_sds_remote_node_context_invalidate_context_buffer( - struct scic_sds_remote_node_context *sci_rnc) -{ - union scu_remote_node_context *rnc_buffer; - - rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(rnc_to_dev(sci_rnc)), - sci_rnc->remote_node_index); - - rnc_buffer->ssp.is_valid = false; - - scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), - SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE); -} - -/* - * ***************************************************************************** - * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS - * ***************************************************************************** */ - -/** - * - * - * - */ -static void scic_sds_remote_node_context_initial_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; - - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE - ); - - /* - * Check to see if we have gotten back to the initial state because someone - * requested to destroy the remote node context object. */ - if ( - rnc->state_machine.previous_state_id - == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE - ) { - rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - - scic_sds_remote_node_context_notify_user(rnc); - } -} - -/** - * - * - * - */ -static void scic_sds_remote_node_context_posting_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_node_context *sci_rnc; - - sci_rnc = (struct scic_sds_remote_node_context *)object; - - SET_STATE_HANDLER( - sci_rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE - ); - - scic_sds_remote_node_context_validate_context_buffer(sci_rnc); -} - -/** - * - * - * - */ -static void scic_sds_remote_node_context_invalidating_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; - - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE - ); - - scic_sds_remote_node_context_invalidate_context_buffer(rnc); -} - -/** - * - * - * - */ -static void scic_sds_remote_node_context_resuming_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_node_context *rnc; - struct smp_discover_response_protocols protocols; - struct scic_sds_remote_device *sci_dev; - - rnc = (struct scic_sds_remote_node_context *)object; - sci_dev = rnc_to_dev(rnc); - - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE - ); - - /* - * For direct attached SATA devices we need to clear the TLCR - * NCQ to TCi tag mapping on the phy and in cases where we - * resume because of a target reset we also need to update - * the STPTLDARNI register with the RNi of the device - */ - scic_remote_device_get_protocols(sci_dev, &protocols); - - if (protocols.u.bits.attached_stp_target == 1 && - sci_dev->is_direct_attached) { - scic_sds_port_setup_transports(sci_dev->owning_port, - rnc->remote_node_index); - } - - scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); -} - -/** - * - * - * - */ -static void scic_sds_remote_node_context_ready_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; - - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE - ); - - rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - - if (rnc->user_callback != NULL) { - scic_sds_remote_node_context_notify_user(rnc); - } -} - -/** - * - * - * - */ -static void scic_sds_remote_node_context_tx_suspended_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; - - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE - ); - - scic_sds_remote_node_context_continue_state_transitions(rnc); -} - -/** - * - * - * - */ -static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; - - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE - ); - - scic_sds_remote_node_context_continue_state_transitions(rnc); -} - -/** - * - * - * - */ -static void scic_sds_remote_node_context_await_suspension_state_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; - - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE - ); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_remote_node_context_state_table[] = { - [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { - .enter_state = scic_sds_remote_node_context_initial_state_enter, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { - .enter_state = scic_sds_remote_node_context_posting_state_enter, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { - .enter_state = scic_sds_remote_node_context_invalidating_state_enter, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { - .enter_state = scic_sds_remote_node_context_resuming_state_enter, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { - .enter_state = scic_sds_remote_node_context_ready_state_enter, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { - .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { - .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { - .enter_state = scic_sds_remote_node_context_await_suspension_state_enter, - }, -}; - -void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, - u16 remote_node_index) -{ - memset(rnc, 0, sizeof(struct scic_sds_remote_node_context)); - - rnc->remote_node_index = remote_node_index; - rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - - sci_base_state_machine_construct( - &rnc->state_machine, - &rnc->parent, - scic_sds_remote_node_context_state_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE - ); - - sci_base_state_machine_start(&rnc->state_machine); -} diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h deleted file mode 100644 index b3f2546090dd..000000000000 --- a/drivers/scsi/isci/core/scic_sds_remote_node_context.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ -#define _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ - -/** - * This file contains the structures, constants, and prototypes associated with - * the remote node context in the silicon. It exists to model and manage - * the remote node context in the silicon. - * - * - */ - -#include "sci_base_state.h" -#include "sci_base_state_machine.h" - -/** - * - * - * This constant represents an invalid remote device id, it is used to program - * the STPDARNI register so the driver knows when it has received a SIGNATURE - * FIS from the SCU. - */ -#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF - -#define SCU_HARDWARE_SUSPENSION (0) -#define SCI_SOFTWARE_SUSPENSION (1) - -struct scic_sds_request; -struct scic_sds_remote_device; -struct scic_sds_remote_node_context; - -typedef void (*scics_sds_remote_node_context_callback)(void *); - -typedef enum sci_status (*scic_sds_remote_node_context_operation)( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter - ); - -typedef enum sci_status (*scic_sds_remote_node_context_suspend_operation)( - struct scic_sds_remote_node_context *sci_rnc, - u32 suspension_type, - scics_sds_remote_node_context_callback callback, - void *callback_parameter - ); - -typedef enum sci_status (*scic_sds_remote_node_context_io_request)( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req - ); - -typedef enum sci_status (*scic_sds_remote_node_context_event_handler)( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code - ); - -struct scic_sds_remote_node_context_handlers { - /** - * This handle is invoked to stop the RNC. The callback is invoked when after - * the hardware notification that the RNC has been invalidated. - */ - scic_sds_remote_node_context_operation destruct_handler; - - /** - * This handler is invoked when there is a request to suspend the RNC. The - * callback is invoked after the hardware notification that the remote node is - * suspended. - */ - scic_sds_remote_node_context_suspend_operation suspend_handler; - - /** - * This handler is invoked when there is a request to resume the RNC. The - * callback is invoked when after the RNC has reached the ready state. - */ - scic_sds_remote_node_context_operation resume_handler; - - /** - * This handler is invoked when there is a request to start an io request - * operation. - */ - scic_sds_remote_node_context_io_request start_io_handler; - - /** - * This handler is invoked when there is a request to start a task request - * operation. - */ - scic_sds_remote_node_context_io_request start_task_handler; - - /** - * This handler is invoked where there is an RNC event that must be processed. - */ - scic_sds_remote_node_context_event_handler event_handler; - -}; - -/** - * This is the enumeration of the remote node context states. - */ -enum scis_sds_remote_node_context_states { - /** - * This state is the initial state for a remote node context. On a resume - * request the remote node context will transition to the posting state. - */ - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE, - - /** - * This is a transition state that posts the RNi to the hardware. Once the RNC - * is posted the remote node context will be made ready. - */ - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE, - - /** - * This is a transition state that will post an RNC invalidate to the - * hardware. Once the invalidate is complete the remote node context will - * transition to the posting state. - */ - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE, - - /** - * This is a transition state that will post an RNC resume to the hardare. - * Once the event notification of resume complete is received the remote node - * context will transition to the ready state. - */ - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE, - - /** - * This is the state that the remote node context must be in to accept io - * request operations. - */ - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE, - - /** - * This is the state that the remote node context transitions to when it gets - * a TX suspend notification from the hardware. - */ - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE, - - /** - * This is the state that the remote node context transitions to when it gets - * a TX RX suspend notification from the hardware. - */ - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE, - - /** - * This state is a wait state for the remote node context that waits for a - * suspend notification from the hardware. This state is entered when either - * there is a request to supend the remote node context or when there is a TC - * completion where the remote node will be suspended by the hardware. - */ - SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE, - - SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES - -}; - -/** - * - * - * This enumeration is used to define the end destination state for the remote - * node context. - */ -enum scic_sds_remote_node_context_destination_state { - SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED, - SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY, - SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL -}; - -/** - * struct scic_sds_remote_node_context - This structure contains the data - * associated with the remote node context object. The remote node context - * (RNC) object models the the remote device information necessary to manage - * the silicon RNC. - */ -struct scic_sds_remote_node_context { - /* - * parent object - */ - struct sci_base_object parent; - - /** - * This field indicates the remote node index (RNI) associated with - * this RNC. - */ - u16 remote_node_index; - - /** - * This field is the recored suspension code or the reason for the remote node - * context suspension. - */ - u32 suspension_code; - - /** - * This field is true if the remote node context is resuming from its current - * state. This can cause an automatic resume on receiving a suspension - * notification. - */ - enum scic_sds_remote_node_context_destination_state destination_state; - - /** - * This field contains the callback function that the user requested to be - * called when the requested state transition is complete. - */ - scics_sds_remote_node_context_callback user_callback; - - /** - * This field contains the parameter that is called when the user requested - * state transition is completed. - */ - void *user_cookie; - - /** - * This field contains the data for the object's state machine. - */ - struct sci_base_state_machine state_machine; - - struct scic_sds_remote_node_context_handlers *state_handlers; -}; - -void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, - u16 remote_node_index); - - -bool scic_sds_remote_node_context_is_ready( - struct scic_sds_remote_node_context *sci_rnc); - -#define scic_sds_remote_node_context_get_remote_node_index(rcn) \ - ((rnc)->remote_node_index) - -#define scic_sds_remote_node_context_event_handler(rnc, event_code) \ - ((rnc)->state_handlers->event_handler(rnc, event_code)) - -#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \ - ((rnc)->state_handlers->resume_handler(rnc, callback, parameter)) - -#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \ - ((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter)) - -#define scic_sds_remote_node_context_destruct(rnc, callback, parameter) \ - ((rnc)->state_handlers->destruct_handler(rnc, callback, parameter)) - -#define scic_sds_remote_node_context_start_io(rnc, request) \ - ((rnc)->state_handlers->start_io_handler(rnc, request)) - -#define scic_sds_remote_node_context_start_task(rnc, task) \ - ((rnc)->state_handlers->start_task_handler(rnc, task)) - -#endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.c b/drivers/scsi/isci/core/scic_sds_remote_node_table.c deleted file mode 100644 index 77919a2cf652..000000000000 --- a/drivers/scsi/isci/core/scic_sds_remote_node_table.c +++ /dev/null @@ -1,600 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains the implementation of the SCIC_SDS_REMOTE_NODE_TABLE - * public, protected, and private methods. - * - * - */ -#include "sci_util.h" -#include "sci_environment.h" -#include "scic_sds_remote_node_table.h" -#include "scic_sds_remote_node_context.h" - -/** - * - * @remote_node_table: This is the remote node index table from which the - * selection will be made. - * @group_table_index: This is the index to the group table from which to - * search for an available selection. - * - * This routine will find the bit position in absolute bit terms of the next 32 - * + bit position. If there are available bits in the first u32 then it is - * just bit position. u32 This is the absolute bit position for an available - * group. - */ -static u32 scic_sds_remote_node_table_get_group_index( - struct scic_remote_node_table *remote_node_table, - u32 group_table_index) -{ - u32 dword_index; - u32 *group_table; - u32 bit_index; - - group_table = remote_node_table->remote_node_groups[group_table_index]; - - for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++) { - if (group_table[dword_index] != 0) { - for (bit_index = 0; bit_index < 32; bit_index++) { - if ((group_table[dword_index] & (1 << bit_index)) != 0) { - return (dword_index * 32) + bit_index; - } - } - } - } - - return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX; -} - -/** - * - * @out]: remote_node_table This the remote node table in which to clear the - * selector. - * @set_index: This is the remote node selector in which the change will be - * made. - * @group_index: This is the bit index in the table to be modified. - * - * This method will clear the group index entry in the specified group index - * table. none - */ -static void scic_sds_remote_node_table_clear_group_index( - struct scic_remote_node_table *remote_node_table, - u32 group_table_index, - u32 group_index) -{ - u32 dword_index; - u32 bit_index; - u32 *group_table; - - BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT); - BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32)); - - dword_index = group_index / 32; - bit_index = group_index % 32; - group_table = remote_node_table->remote_node_groups[group_table_index]; - - group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index); -} - -/** - * - * @out]: remote_node_table This the remote node table in which to set the - * selector. - * @group_table_index: This is the remote node selector in which the change - * will be made. - * @group_index: This is the bit position in the table to be modified. - * - * This method will set the group index bit entry in the specified gropu index - * table. none - */ -static void scic_sds_remote_node_table_set_group_index( - struct scic_remote_node_table *remote_node_table, - u32 group_table_index, - u32 group_index) -{ - u32 dword_index; - u32 bit_index; - u32 *group_table; - - BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT); - BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32)); - - dword_index = group_index / 32; - bit_index = group_index % 32; - group_table = remote_node_table->remote_node_groups[group_table_index]; - - group_table[dword_index] = group_table[dword_index] | (1 << bit_index); -} - -/** - * - * @out]: remote_node_table This is the remote node table in which to modify - * the remote node availability. - * @remote_node_index: This is the remote node index that is being returned to - * the table. - * - * This method will set the remote to available in the remote node allocation - * table. none - */ -static void scic_sds_remote_node_table_set_node_index( - struct scic_remote_node_table *remote_node_table, - u32 remote_node_index) -{ - u32 dword_location; - u32 dword_remainder; - u32 slot_normalized; - u32 slot_position; - - BUG_ON( - (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) - <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT) - ); - - dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD; - dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD; - slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32); - slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT; - - remote_node_table->available_remote_nodes[dword_location] |= - 1 << (slot_normalized + slot_position); -} - -/** - * - * @out]: remote_node_table This is the remote node table from which to clear - * the available remote node bit. - * @remote_node_index: This is the remote node index which is to be cleared - * from the table. - * - * This method clears the remote node index from the table of available remote - * nodes. none - */ -static void scic_sds_remote_node_table_clear_node_index( - struct scic_remote_node_table *remote_node_table, - u32 remote_node_index) -{ - u32 dword_location; - u32 dword_remainder; - u32 slot_position; - u32 slot_normalized; - - BUG_ON( - (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) - <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT) - ); - - dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD; - dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD; - slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32); - slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT; - - remote_node_table->available_remote_nodes[dword_location] &= - ~(1 << (slot_normalized + slot_position)); -} - -/** - * - * @out]: remote_node_table The remote node table from which the slot will be - * cleared. - * @group_index: The index for the slot that is to be cleared. - * - * This method clears the entire table slot at the specified slot index. none - */ -static void scic_sds_remote_node_table_clear_group( - struct scic_remote_node_table *remote_node_table, - u32 group_index) -{ - u32 dword_location; - u32 dword_remainder; - u32 dword_value; - - BUG_ON( - (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) - <= (group_index / SCU_STP_REMOTE_NODE_COUNT) - ); - - dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; - dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; - - dword_value = remote_node_table->available_remote_nodes[dword_location]; - dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); - remote_node_table->available_remote_nodes[dword_location] = dword_value; -} - -/** - * - * @remote_node_table: - * - * THis method sets an entire remote node group in the remote node table. - */ -static void scic_sds_remote_node_table_set_group( - struct scic_remote_node_table *remote_node_table, - u32 group_index) -{ - u32 dword_location; - u32 dword_remainder; - u32 dword_value; - - BUG_ON( - (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) - <= (group_index / SCU_STP_REMOTE_NODE_COUNT) - ); - - dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; - dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; - - dword_value = remote_node_table->available_remote_nodes[dword_location]; - dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); - remote_node_table->available_remote_nodes[dword_location] = dword_value; -} - -/** - * - * @remote_node_table: This is the remote node table that for which the group - * value is to be returned. - * @group_index: This is the group index to use to find the group value. - * - * This method will return the group value for the specified group index. The - * bit values at the specified remote node group index. - */ -static u8 scic_sds_remote_node_table_get_group_value( - struct scic_remote_node_table *remote_node_table, - u32 group_index) -{ - u32 dword_location; - u32 dword_remainder; - u32 dword_value; - - dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; - dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; - - dword_value = remote_node_table->available_remote_nodes[dword_location]; - dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); - dword_value = dword_value >> (dword_remainder * 4); - - return (u8)dword_value; -} - -/** - * - * @out]: remote_node_table The remote that which is to be initialized. - * @remote_node_entries: The number of entries to put in the table. - * - * This method will initialize the remote node table for use. none - */ -void scic_sds_remote_node_table_initialize( - struct scic_remote_node_table *remote_node_table, - u32 remote_node_entries) -{ - u32 index; - - /* - * Initialize the raw data we could improve the speed by only initializing - * those entries that we are actually going to be used */ - memset( - remote_node_table->available_remote_nodes, - 0x00, - sizeof(remote_node_table->available_remote_nodes) - ); - - memset( - remote_node_table->remote_node_groups, - 0x00, - sizeof(remote_node_table->remote_node_groups) - ); - - /* Initialize the available remote node sets */ - remote_node_table->available_nodes_array_size = (u16) - (remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD) - + ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0); - - - /* Initialize each full DWORD to a FULL SET of remote nodes */ - for (index = 0; index < remote_node_entries; index++) { - scic_sds_remote_node_table_set_node_index(remote_node_table, index); - } - - remote_node_table->group_array_size = (u16) - (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32)) - + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0); - - for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++) { - /* - * These are all guaranteed to be full slot values so fill them in the - * available sets of 3 remote nodes */ - scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index); - } - - /* Now fill in any remainders that we may find */ - if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) { - scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index); - } else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) { - scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index); - } -} - -/** - * - * @out]: remote_node_table The remote node table from which to allocate a - * remote node. - * @table_index: The group index that is to be used for the search. - * - * This method will allocate a single RNi from the remote node table. The - * table index will determine from which remote node group table to search. - * This search may fail and another group node table can be specified. The - * function is designed to allow a serach of the available single remote node - * group up to the triple remote node group. If an entry is found in the - * specified table the remote node is removed and the remote node groups are - * updated. The RNi value or an invalid remote node context if an RNi can not - * be found. - */ -static u16 scic_sds_remote_node_table_allocate_single_remote_node( - struct scic_remote_node_table *remote_node_table, - u32 group_table_index) -{ - u8 index; - u8 group_value; - u32 group_index; - u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - - group_index = scic_sds_remote_node_table_get_group_index( - remote_node_table, group_table_index); - - /* We could not find an available slot in the table selector 0 */ - if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { - group_value = scic_sds_remote_node_table_get_group_value( - remote_node_table, group_index); - - for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) { - if (((1 << index) & group_value) != 0) { - /* We have selected a bit now clear it */ - remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT - + index); - - scic_sds_remote_node_table_clear_group_index( - remote_node_table, group_table_index, group_index - ); - - scic_sds_remote_node_table_clear_node_index( - remote_node_table, remote_node_index - ); - - if (group_table_index > 0) { - scic_sds_remote_node_table_set_group_index( - remote_node_table, group_table_index - 1, group_index - ); - } - - break; - } - } - } - - return remote_node_index; -} - -/** - * - * @remote_node_table: This is the remote node table from which to allocate the - * remote node entries. - * @group_table_index: THis is the group table index which must equal two (2) - * for this operation. - * - * This method will allocate three consecutive remote node context entries. If - * there are no remaining triple entries the function will return a failure. - * The remote node index that represents three consecutive remote node entries - * or an invalid remote node context if none can be found. - */ -static u16 scic_sds_remote_node_table_allocate_triple_remote_node( - struct scic_remote_node_table *remote_node_table, - u32 group_table_index) -{ - u32 group_index; - u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - - group_index = scic_sds_remote_node_table_get_group_index( - remote_node_table, group_table_index); - - if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { - remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT; - - scic_sds_remote_node_table_clear_group_index( - remote_node_table, group_table_index, group_index - ); - - scic_sds_remote_node_table_clear_group( - remote_node_table, group_index - ); - } - - return remote_node_index; -} - -/** - * - * @remote_node_table: This is the remote node table from which the remote node - * allocation is to take place. - * @remote_node_count: This is ther remote node count which is one of - * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). - * - * This method will allocate a remote node that mataches the remote node count - * specified by the caller. Valid values for remote node count is - * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). u16 This is - * the remote node index that is returned or an invalid remote node context. - */ -u16 scic_sds_remote_node_table_allocate_remote_node( - struct scic_remote_node_table *remote_node_table, - u32 remote_node_count) -{ - u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - - if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { - remote_node_index = - scic_sds_remote_node_table_allocate_single_remote_node( - remote_node_table, 0); - - if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - remote_node_index = - scic_sds_remote_node_table_allocate_single_remote_node( - remote_node_table, 1); - } - - if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - remote_node_index = - scic_sds_remote_node_table_allocate_single_remote_node( - remote_node_table, 2); - } - } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { - remote_node_index = - scic_sds_remote_node_table_allocate_triple_remote_node( - remote_node_table, 2); - } - - return remote_node_index; -} - -/** - * - * @remote_node_table: - * - * This method will free a single remote node index back to the remote node - * table. This routine will update the remote node groups - */ -static void scic_sds_remote_node_table_release_single_remote_node( - struct scic_remote_node_table *remote_node_table, - u16 remote_node_index) -{ - u32 group_index; - u8 group_value; - - group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; - - group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index); - - /* - * Assert that we are not trying to add an entry to a slot that is already - * full. */ - BUG_ON(group_value == SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE); - - if (group_value == 0x00) { - /* - * There are no entries in this slot so it must be added to the single - * slot table. */ - scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index); - } else if ((group_value & (group_value - 1)) == 0) { - /* - * There is only one entry in this slot so it must be moved from the - * single slot table to the dual slot table */ - scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index); - scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index); - } else { - /* - * There are two entries in the slot so it must be moved from the dual - * slot table to the tripple slot table. */ - scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index); - scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index); - } - - scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index); -} - -/** - * - * @remote_node_table: This is the remote node table to which the remote node - * index is to be freed. - * - * This method will release a group of three consecutive remote nodes back to - * the free remote nodes. - */ -static void scic_sds_remote_node_table_release_triple_remote_node( - struct scic_remote_node_table *remote_node_table, - u16 remote_node_index) -{ - u32 group_index; - - group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; - - scic_sds_remote_node_table_set_group_index( - remote_node_table, 2, group_index - ); - - scic_sds_remote_node_table_set_group(remote_node_table, group_index); -} - -/** - * - * @remote_node_table: The remote node table to which the remote node index is - * to be freed. - * @remote_node_count: This is the count of consecutive remote nodes that are - * to be freed. - * - * This method will release the remote node index back into the remote node - * table free pool. - */ -void scic_sds_remote_node_table_release_remote_node_index( - struct scic_remote_node_table *remote_node_table, - u32 remote_node_count, - u16 remote_node_index) -{ - if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { - scic_sds_remote_node_table_release_single_remote_node( - remote_node_table, remote_node_index); - } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { - scic_sds_remote_node_table_release_triple_remote_node( - remote_node_table, remote_node_index); - } -} - diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.h b/drivers/scsi/isci/core/scic_sds_remote_node_table.h deleted file mode 100644 index 9c02a6ccb2fe..000000000000 --- a/drivers/scsi/isci/core/scic_sds_remote_node_table.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_ -#define _SCIC_SDS_REMOTE_NODE_TABLE_H_ - -/** - * This file contains the structures, constants and prototypes used for the - * remote node table. - * - * - */ - -#include "sci_controller_constants.h" - -/** - * - * - * Remote node sets are sets of remote node index in the remtoe node table The - * SCU hardware requires that STP remote node entries take three consecutive - * remote node index so the table is arranged in sets of three. The bits are - * used as 0111 0111 to make a byte and the bits define the set of three remote - * nodes to use as a sequence. - */ -#define SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE 2 - -/** - * - * - * Since the remote node table is organized as DWORDS take the remote node sets - * in bytes and represent them in DWORDs. The lowest ordered bits are the ones - * used in case full DWORD is not being used. i.e. 0000 0000 0000 0000 0111 - * 0111 0111 0111 // if only a single WORD is in use in the DWORD. - */ -#define SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD \ - (sizeof(u32) * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE) -/** - * - * - * This is a count of the numeber of remote nodes that can be represented in a - * byte - */ -#define SCIC_SDS_REMOTE_NODES_PER_BYTE \ - (SCU_STP_REMOTE_NODE_COUNT * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE) - -/** - * - * - * This is a count of the number of remote nodes that can be represented in a - * DWROD - */ -#define SCIC_SDS_REMOTE_NODES_PER_DWORD \ - (sizeof(u32) * SCIC_SDS_REMOTE_NODES_PER_BYTE) - -/** - * - * - * This is the number of bits in a remote node group - */ -#define SCIC_SDS_REMOTE_NODES_BITS_PER_GROUP 4 - -#define SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX (0xFFFFFFFF) -#define SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE (0x07) -#define SCIC_SDS_REMOTE_NODE_TABLE_EMPTY_SLOT_VALUE (0x00) - -/** - * - * - * Expander attached sata remote node count - */ -#define SCU_STP_REMOTE_NODE_COUNT 3 - -/** - * - * - * Expander or direct attached ssp remote node count - */ -#define SCU_SSP_REMOTE_NODE_COUNT 1 - -/** - * - * - * Direct attached STP remote node count - */ -#define SCU_SATA_REMOTE_NODE_COUNT 1 - -/** - * struct scic_remote_node_table - - * - * - */ -struct scic_remote_node_table { - /** - * This field contains the array size in dwords - */ - u16 available_nodes_array_size; - - /** - * This field contains the array size of the - */ - u16 group_array_size; - - /** - * This field is the array of available remote node entries in bits. - * Because of the way STP remote node data is allocated on the SCU hardware - * the remote nodes must occupy three consecutive remote node context - * entries. For ease of allocation and de-allocation we have broken the - * sets of three into a single nibble. When the STP RNi is allocated all - * of the bits in the nibble are cleared. This math results in a table size - * of MAX_REMOTE_NODES / CONSECUTIVE RNi ENTRIES for STP / 2 entries per byte. - */ - u32 available_remote_nodes[ - (SCI_MAX_REMOTE_DEVICES / SCIC_SDS_REMOTE_NODES_PER_DWORD) - + ((SCI_MAX_REMOTE_DEVICES % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0)]; - - /** - * This field is the nibble selector for the above table. There are three - * possible selectors each for fast lookup when trying to find one, two or - * three remote node entries. - */ - u32 remote_node_groups[ - SCU_STP_REMOTE_NODE_COUNT][ - (SCI_MAX_REMOTE_DEVICES / (32 * SCU_STP_REMOTE_NODE_COUNT)) - + ((SCI_MAX_REMOTE_DEVICES % (32 * SCU_STP_REMOTE_NODE_COUNT)) != 0)]; - -}; - -/* --------------------------------------------------------------------------- */ - -void scic_sds_remote_node_table_initialize( - struct scic_remote_node_table *remote_node_table, - u32 remote_node_entries); - -u16 scic_sds_remote_node_table_allocate_remote_node( - struct scic_remote_node_table *remote_node_table, - u32 remote_node_count); - -void scic_sds_remote_node_table_release_remote_node_index( - struct scic_remote_node_table *remote_node_table, - u32 remote_node_count, - u16 remote_node_index); - -#endif /* _SCIC_SDS_REMOTE_NODE_TABLE_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 63ebbf39dc90..dfb94121d445 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -59,11 +59,10 @@ #include "intel_sat.h" #include "scic_controller.h" #include "scic_io_request.h" -#include "scic_remote_device.h" #include "scic_sds_controller.h" #include "scu_registers.h" #include "scic_sds_port.h" -#include "scic_sds_remote_device.h" +#include "remote_device.h" #include "scic_sds_request.h" #include "scic_sds_smp_request.h" #include "scic_sds_stp_request.h" diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c deleted file mode 100644 index cd55c0a8dae3..000000000000 --- a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "scic_remote_device.h" -#include "scic_sds_controller.h" -#include "scic_sds_port.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_request.h" -#include "sci_environment.h" -#include "sci_util.h" -#include "scu_event_codes.h" -#include "scu_task_context.h" - -/* - * ***************************************************************************** - * * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @[in]: device The device the io is sent to. - * @[in]: request The io to start. - * - * This method will handle the start io operation for a SMP device that is in - * the idle state. enum sci_status - */ -static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - - /* Will the port allow the io request to start? */ - status = device->owning_port->state_handlers->start_io_handler( - device->owning_port, device, request); - - if (status == SCI_SUCCESS) { - status = scic_sds_remote_node_context_start_io(&device->rnc, request); - - if (status == SCI_SUCCESS) - status = scic_sds_request_start(request); - - if (status == SCI_SUCCESS) { - device->working_request = request; - - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD - ); - } - - scic_sds_remote_device_start_request(device, request, status); - } - - return status; -} - - -/* - * ****************************************************************************** - * * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS - * ****************************************************************************** */ -/** - * - * @device: This is the device object that is receiving the IO. - * @request: The io to start. - * - * This device is already handling a command it can not accept new commands - * until this one is complete. enum sci_status - */ -static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - return SCI_FAILURE_INVALID_STATE; -} - - -/** - * this is the complete_io_handler for smp device at ready cmd substate. - * @device: This is the device object that is receiving the IO. - * @request: The io to start. - * - * enum sci_status - */ -static enum sci_status -scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - struct scic_sds_request *sci_req; - - sci_req = (struct scic_sds_request *)request; - - status = scic_sds_io_request_complete(sci_req); - - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - device->owning_port, device, sci_req); - - if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(device); - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE - ); - } else - dev_err(scirdev_to_dev(device), - "%s: SCIC SDS Remote Device 0x%p io request " - "0x%p could not be completd on the port 0x%p " - "failed with status %d.\n", - __func__, - device, - sci_req, - device->owning_port, - status); - } - - return status; -} - -/** - * This is frame handler for smp device ready cmd substate. - * @sci_dev: This is the device object that is receiving the frame. - * @frame_index: The index for the frame received. - * - * enum sci_status - */ -static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status status; - - /* - * / The device does not process any UF received from the hardware while - * / in this state. All unsolicited frames are forwarded to the io request - * / object. */ - status = scic_sds_io_request_frame_handler( - sci_dev->working_request, - frame_index - ); - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = { - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, - .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler - } -}; - -/** - * - * @object: This is the struct sci_base_object which is cast into a - * struct scic_sds_remote_device. - * - * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. - * This function sets the ready cmd substate handlers and reports the device as - * ready. none - */ -static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - - SET_STATE_HANDLER(sci_dev, - scic_sds_smp_remote_device_ready_substate_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - - isci_remote_device_ready(ihost, idev); -} - -/** - * - * @object: This is the struct sci_base_object which is cast into a - * struct scic_sds_remote_device. - * - * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This - * function sets the remote device objects ready cmd substate handlers, and - * notify core user that the device is not ready. none - */ -static void scic_sds_smp_remote_device_ready_cmd_substate_enter( - struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - - BUG_ON(sci_dev->working_request == NULL); - - SET_STATE_HANDLER(sci_dev, - scic_sds_smp_remote_device_ready_substate_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - - isci_remote_device_not_ready(ihost, idev, - SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); -} - -/** - * - * @object: This is the struct sci_base_object which is cast into a - * struct scic_sds_remote_device. - * - * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none - */ -static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - sci_dev->working_request = NULL; -} - -/* --------------------------------------------------------------------------- */ - -const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = { - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, - }, - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, - .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, - }, -}; diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 3274d62ac3b2..1790f25758d1 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -56,9 +56,8 @@ #include "intel_sas.h" #include "sci_base_state_machine.h" #include "scic_controller.h" -#include "scic_remote_device.h" #include "scic_sds_controller.h" -#include "scic_sds_remote_device.h" +#include "remote_device.h" #include "scic_sds_request.h" #include "scic_sds_smp_request.h" #include "sci_environment.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c index e4d2bf56f491..1cb77bbb7485 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c @@ -61,9 +61,8 @@ #include "sati_translator_sequence.h" #include "sci_base_state.h" #include "scic_controller.h" -#include "scic_remote_device.h" #include "scic_sds_controller.h" -#include "scic_sds_remote_device.h" +#include "remote_device.h" #include "scic_sds_request.h" #include "scic_sds_stp_packet_request.h" #include "scic_user_callback.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c deleted file mode 100644 index 848cb4711b63..000000000000 --- a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c +++ /dev/null @@ -1,818 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "intel_ata.h" -#include "intel_sata.h" -#include "intel_sat.h" -#include "sci_base_state.h" -#include "scic_remote_device.h" -#include "scic_sds_controller.h" -#include "scic_sds_port.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_request.h" -#include "sci_environment.h" -#include "sci_util.h" -#include "scu_event_codes.h" - -/** - * This method will perform the STP request completion processing common to IO - * requests and task requests of all types - * @device: This parameter specifies the device for which the request is being - * completed. - * @request: This parameter specifies the request being completed. - * - * This method returns an indication as to whether the request processing - * completed successfully. - */ -static enum sci_status scic_sds_stp_remote_device_complete_request( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - - status = scic_sds_io_request_complete(request); - - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - device->owning_port, device, request); - - if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(device); - if (request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - /* - * This request causes hardware error, device needs to be Lun Reset. - * So here we force the state machine to IDLE state so the rest IOs - * can reach RNC state handler, these IOs will be completed by RNC with - * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET - ); - } else if (scic_sds_remote_device_get_request_count(device) == 0) { - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE - ); - } - } - } - - if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(device), - "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " - "could not complete\n", - __func__, - device->owning_port, - device, - request, - status); - - return status; -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * This is the READY NCQ substate handler to start task management request. In - * this routine, we suspend and resume the RNC. - * @device: The target device a task management request towards to. - * @request: The task request. - * - * enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to - * let controller_start_task_handler know that the controller can't post TC for - * task request yet, instead, when RNC gets resumed, a controller_continue_task - * callback will be called. - */ -static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - - /* Will the port allow the io request to start? */ - status = device->owning_port->state_handlers->start_io_handler( - device->owning_port, device, request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_task(&device->rnc, request); - if (status != SCI_SUCCESS) - goto out; - - status = request->state_handlers->start_handler(request); - if (status != SCI_SUCCESS) - goto out; - - /* - * Note: If the remote device state is not IDLE this will replace - * the request that probably resulted in the task management request. - */ - device->working_request = request; - sci_base_state_machine_change_state(&device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - - /* - * The remote node context must cleanup the TCi to NCQ mapping table. - * The only way to do this correctly is to either write to the TLCR - * register or to invalidate and repost the RNC. In either case the - * remote node context state machine will take the correct action when - * the remote node context is suspended and later resumed. - */ - scic_sds_remote_node_context_suspend(&device->rnc, - SCI_SOFTWARE_SUSPENSION, NULL, NULL); - scic_sds_remote_node_context_resume(&device->rnc, - scic_sds_remote_device_continue_request, - device); - -out: - scic_sds_remote_device_start_request(device, request, status); - /* - * We need to let the controller start request handler know that it can't - * post TC yet. We will provide a callback function to post TC when RNC gets - * resumed. - */ - return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * This method will handle the start io operation for a sata device that is in - * the command idle state. - Evalute the type of IO request to be started - - * If its an NCQ request change to NCQ substate - If its any other command - * change to the CMD substate - * @device: - * @request: - * - * If this is a softreset we may want to have a different substate. - * enum sci_status - */ -static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(request); - - - /* Will the port allow the io request to start? */ - status = sci_dev->owning_port->state_handlers->start_io_handler( - sci_dev->owning_port, sci_dev, request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (status != SCI_SUCCESS) - goto out; - - status = request->state_handlers->start_handler(request); - if (status != SCI_SUCCESS) - goto out; - - if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { - sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); - } else { - sci_dev->working_request = request; - sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - } -out: - scic_sds_remote_device_start_request(sci_dev, request, status); - return status; -} - - -/** - * - * @[in]: device The device received event. - * @[in]: event_code The event code. - * - * This method will handle the event for a sata device that is in the idle - * state. We pick up suspension events to handle specifically to this state. We - * resume the RNC right away. enum sci_status - */ -static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - enum sci_status status; - - status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); - - if (status == SCI_SUCCESS) { - if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX - || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { - status = scic_sds_remote_node_context_resume( - &sci_dev->rnc, NULL, NULL); - } - } - - return status; -} - - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS - * ***************************************************************************** */ - -static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(request); - - if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { - status = sci_dev->owning_port->state_handlers->start_io_handler( - sci_dev->owning_port, - sci_dev, - request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (status != SCI_SUCCESS) - return status; - - status = request->state_handlers->start_handler(request); - - scic_sds_remote_device_start_request(sci_dev, request, status); - } else - status = SCI_FAILURE_INVALID_STATE; - - return status; -} - - -/** - * This method will handle events received while the STP device is in the ready - * command substate. - * @sci_dev: This is the device object that is receiving the event. - * @event_code: The event code to process. - * - * enum sci_status - */ - -static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status status; - struct sata_fis_header *frame_header; - - status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), - frame_index, - (void **)&frame_header - ); - - if (status == SCI_SUCCESS) { - if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && - (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { - sci_dev->not_ready_reason = - SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; - - /* - * / @todo Check sactive and complete associated IO - * if any. - */ - - sci_base_state_machine_change_state( - &sci_dev->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR - ); - } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && - (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { - - /* - * Some devices return D2H FIS when an NCQ error is detected. - * Treat this like an SDB error FIS ready reason. - */ - sci_dev->not_ready_reason = - SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; - - sci_base_state_machine_change_state( - &sci_dev->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR - ); - } else { - status = SCI_FAILURE; - } - - scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(sci_dev), frame_index - ); - } - - return status; -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * This device is already handling a command it can not accept new commands - * until this one is complete. - * @device: - * @request: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type) -{ - enum sci_status status; - - status = scic_sds_remote_node_context_suspend(&sci_dev->rnc, - suspend_type, NULL, NULL); - - return status; -} - -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status status; - - /* - * / The device doe not process any UF received from the hardware while - * / in this state. All unsolicited frames are forwarded to the io request - * / object. */ - status = scic_sds_io_request_frame_handler( - sci_dev->working_request, - frame_index - ); - - return status; -} - - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS - * ***************************************************************************** */ - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS - * ***************************************************************************** */ - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS - * ***************************************************************************** */ -static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; -} - - - -/** - * This method will perform the STP request (both io or task) completion - * processing for await reset state. - * @device: This parameter specifies the device for which the request is being - * completed. - * @request: This parameter specifies the request being completed. - * - * This method returns an indication as to whether the request processing - * completed successfully. - */ -static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - struct scic_sds_request *sci_req = (struct scic_sds_request *)request; - enum sci_status status; - - status = scic_sds_io_request_complete(sci_req); - - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - device->owning_port, device, sci_req - ); - - if (status == SCI_SUCCESS) - scic_sds_remote_device_decrement_request_count(device); - } - - if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(device), - "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " - "could not complete\n", - __func__, - device->owning_port, - device, - sci_req, - status); - - return status; -} - -#if !defined(DISABLE_ATAPI) -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @[in]: device The device received event. - * @[in]: event_code The event code. - * - * This method will handle the event for a ATAPI device that is in the ATAPI - * ERROR state. We pick up suspension events to handle specifically to this - * state. We resume the RNC right away. We then complete the outstanding IO to - * this device. enum sci_status - */ -enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - enum sci_status status; - - status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); - - if (status == SCI_SUCCESS) { - if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX - || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { - status = scic_sds_remote_node_context_resume( - sci_dev->rnc, - sci_dev->working_request->state_handlers->parent.complete_handler, - (void *)sci_dev->working_request - ); - } - } - - return status; -} -#endif /* !defined(DISABLE_ATAPI) */ - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, - .complete_io_handler = scic_sds_stp_remote_device_complete_request, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, - .complete_io_handler = scic_sds_stp_remote_device_complete_request, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_stp_remote_device_complete_request, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, -#if !defined(DISABLE_ATAPI) - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_stp_remote_device_complete_request, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, -#endif - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, - .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - } -}; - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS - * ***************************************************************************** */ - -static void -scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *user_cookie) -{ - struct scic_sds_remote_device *sci_dev = user_cookie; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - - /* - * For NCQ operation we do not issue a - * scic_cb_remote_device_not_ready(). As a result, avoid sending - * the ready notification. - */ - if (sci_dev->ready_substate_machine.previous_state_id != - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) - isci_remote_device_ready(ihost, idev); -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY IDLE SUBSTATE - * ***************************************************************************** */ - -/** - * - * @device: This is the SCI base object which is cast into a - * struct scic_sds_remote_device object. - * - */ -static void scic_sds_stp_remote_device_ready_idle_substate_enter( - struct sci_base_object *device) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)device; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE - ); - - sci_dev->working_request = NULL; - - if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { - /* - * Since the RNC is ready, it's alright to finish completion - * processing (e.g. signal the remote device is ready). */ - scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( - sci_dev - ); - } else { - scic_sds_remote_node_context_resume( - &sci_dev->rnc, - scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, - sci_dev); - } -} - -static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - - BUG_ON(sci_dev->working_request == NULL); - - SET_STATE_HANDLER(sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - - isci_remote_device_not_ready(ihost, idev, - SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); -} - -static void scic_sds_stp_remote_device_ready_ncq_substate_enter(struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - SET_STATE_HANDLER(sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); -} - -static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_object *object) -{ - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); - struct isci_remote_device *idev = sci_object_get_association(sci_dev); - - SET_STATE_HANDLER(sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); - - if (sci_dev->not_ready_reason == - SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) - isci_remote_device_not_ready(ihost, idev, sci_dev->not_ready_reason); -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE - * ***************************************************************************** */ - -/** - * The enter routine to READY AWAIT RESET substate. - * @device: This is the SCI base object which is cast into a - * struct scic_sds_remote_device object. - * - */ -static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( - struct sci_base_object *device) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)device; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET - ); -} - -#if !defined(DISABLE_ATAPI) -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE - * ***************************************************************************** */ - -/** - * The enter routine to READY ATAPI ERROR substate. - * @device: This is the SCI base object which is cast into a - * struct scic_sds_remote_device object. - * - */ -void scic_sds_stp_remote_device_ready_atapi_error_substate_enter( - struct sci_base_object *device) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)device; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR - ); -} -#endif /* !defined(DISABLE_ATAPI) */ - -/* --------------------------------------------------------------------------- */ - -const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, - }, -#if !defined(DISABLE_ATAPI) - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { - .enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter, - }, -#endif - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, - }, -}; diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index ab01f8d5506b..59c5f1b8f1f6 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -60,9 +60,8 @@ #include "sci_base_state.h" #include "sci_base_state_machine.h" #include "scic_io_request.h" -#include "scic_remote_device.h" #include "scic_sds_controller.h" -#include "scic_sds_remote_device.h" +#include "remote_device.h" #include "scic_sds_request.h" #include "scic_sds_stp_pio_request.h" #include "scic_sds_stp_request.h" diff --git a/drivers/scsi/isci/core/scu_remote_node_context.h b/drivers/scsi/isci/core/scu_remote_node_context.h deleted file mode 100644 index 33745adc826b..000000000000 --- a/drivers/scsi/isci/core/scu_remote_node_context.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SCU_REMOTE_NODE_CONTEXT_HEADER__ -#define __SCU_REMOTE_NODE_CONTEXT_HEADER__ - -/** - * This file contains the structures and constatns used by the SCU hardware to - * describe a remote node context. - * - * - */ - -/** - * struct ssp_remote_node_context - This structure contains the SCU hardware - * definition for an SSP remote node. - * - * - */ -struct ssp_remote_node_context { - /* WORD 0 */ - - /** - * This field is the remote node index assigned for this remote node. All - * remote nodes must have a unique remote node index. The value of the remote - * node index can not exceed the maximum number of remote nodes reported in - * the SCU device context capacity register. - */ - u32 remote_node_index:12; - u32 reserved0_1:4; - - /** - * This field tells the SCU hardware how many simultaneous connections that - * this remote node will support. - */ - u32 remote_node_port_width:4; - - /** - * This field tells the SCU hardware which logical port to associate with this - * remote node. - */ - u32 logical_port_index:3; - u32 reserved0_2:5; - - /** - * This field will enable the I_T nexus loss timer for this remote node. - */ - u32 nexus_loss_timer_enable:1; - - /** - * This field is the for driver debug only and is not used. - */ - u32 check_bit:1; - - /** - * This field must be set to true when the hardware DMAs the remote node - * context to the hardware SRAM. When the remote node is being invalidated - * this field must be set to false. - */ - u32 is_valid:1; - - /** - * This field must be set to true. - */ - u32 is_remote_node_context:1; - - /* WORD 1 - 2 */ - - /** - * This is the low word of the remote device SAS Address - */ - u32 remote_sas_address_lo; - - /** - * This field is the high word of the remote device SAS Address - */ - u32 remote_sas_address_hi; - - /* WORD 3 */ - /** - * This field reprensets the function number assigned to this remote device. - * This value must match the virtual function number that is being used to - * communicate to the device. - */ - u32 function_number:8; - u32 reserved3_1:8; - - /** - * This field provides the driver a way to cheat on the arbitration wait time - * for this remote node. - */ - u32 arbitration_wait_time:16; - - /* WORD 4 */ - /** - * This field tells the SCU hardware how long this device may occupy the - * connection before it must be closed. - */ - u32 connection_occupancy_timeout:16; - - /** - * This field tells the SCU hardware how long to maintain a connection when - * there are no frames being transmitted on the link. - */ - u32 connection_inactivity_timeout:16; - - /* WORD 5 */ - /** - * This field allows the driver to cheat on the arbitration wait time for this - * remote node. - */ - u32 initial_arbitration_wait_time:16; - - /** - * This field is tells the hardware what to program for the connection rate in - * the open address frame. See the SAS spec for valid values. - */ - u32 oaf_connection_rate:4; - - /** - * This field tells the SCU hardware what to program for the features in the - * open address frame. See the SAS spec for valid values. - */ - u32 oaf_features:4; - - /** - * This field tells the SCU hardware what to use for the source zone group in - * the open address frame. See the SAS spec for more details on zoning. - */ - u32 oaf_source_zone_group:8; - - /* WORD 6 */ - /** - * This field tells the SCU hardware what to use as the more capibilities in - * the open address frame. See the SAS Spec for details. - */ - u32 oaf_more_compatibility_features; - - /* WORD 7 */ - u32 reserved7; - -}; - -/** - * struct stp_remote_node_context - This structure contains the SCU hardware - * definition for a STP remote node. - * - * STP Targets are not yet supported so this definition is a placeholder until - * we do support them. - */ -struct stp_remote_node_context { - /** - * Placeholder data for the STP remote node. - */ - u32 data[8]; - -}; - -/** - * This union combines the SAS and SATA remote node definitions. - * - * union scu_remote_node_context - */ -union scu_remote_node_context { - /** - * SSP Remote Node - */ - struct ssp_remote_node_context ssp; - - /** - * STP Remote Node - */ - struct stp_remote_node_context stp; - -}; - -#endif /* __SCU_REMOTE_NODE_CONTEXT_HEADER__ */ diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 3aceb9219d7b..676bcdbfc316 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -55,14 +55,12 @@ #include "isci.h" #include "scic_io_request.h" -#include "scic_remote_device.h" #include "scic_port.h" - #include "port.h" #include "request.h" #include "host.h" #include "probe_roms.h" -#include "core/scic_sds_controller.h" +#include "scic_sds_controller.h" irqreturn_t isci_msix_isr(int vec, void *data) { diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 21bd7d88e5d8..8dc8d1c46986 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -61,7 +61,6 @@ /*#include "task.h"*/ #include "timers.h" #include "remote_device.h" -#include "scic_remote_device.h" #define DRV_NAME "isci" #define SCI_PCI_BAR_COUNT 2 diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index a23ea2c1c7db..f7ca9e8d9146 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -62,7 +62,6 @@ #include "isci.h" #include "task.h" #include "sci_controller_constants.h" -#include "scic_remote_device.h" #include "sci_environment.h" #include "probe_roms.h" diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index cf78cf0a6749..430b29ed6c7e 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -63,7 +63,6 @@ #include #include "isci.h" #include "scic_io_request.h" -#include "scic_remote_device.h" #include "scic_phy.h" #include "scic_sds_phy.h" #include "scic_port.h" diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 76546fd5b7d0..eeac7bbc9430 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -64,6 +64,7 @@ struct isci_phy; struct isci_host; +struct scic_sds_phy; enum isci_status { diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 2df8d8e5d5ea..933d81109ea4 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -33,7 +33,6 @@ #include "isci.h" #include "task.h" #include "sci_controller_constants.h" -#include "scic_remote_device.h" #include "sci_environment.h" #include "probe_roms.h" diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 1553221fe4d7..6b9ea9022843 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -52,18 +52,1169 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "intel_sas.h" +#include "isci.h" +#include "port.h" +#include "remote_device.h" +#include "request.h" +#include "scic_controller.h" +#include "scic_io_request.h" +#include "scic_phy.h" +#include "scic_port.h" +#include "scic_sds_controller.h" +#include "scic_sds_phy.h" +#include "scic_sds_port.h" +#include "remote_node_context.h" +#include "scic_sds_request.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_event_codes.h" +#include "task.h" + +enum sci_status scic_remote_device_stop( + struct scic_sds_remote_device *sci_dev, + u32 timeout) +{ + return sci_dev->state_handlers->stop_handler(sci_dev); +} + + +enum sci_status scic_remote_device_reset( + struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->state_handlers->reset_handler(sci_dev); +} + + +enum sci_status scic_remote_device_reset_complete( + struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->state_handlers->reset_complete_handler(sci_dev); +} + + +enum sas_linkrate scic_remote_device_get_connection_rate( + struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->connection_rate; +} + + +void scic_remote_device_get_protocols( + struct scic_sds_remote_device *sci_dev, + struct smp_discover_response_protocols *pr) +{ + pr->u.all = sci_dev->target_protocols.u.all; +} + +#if !defined(DISABLE_ATAPI) +bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->is_atapi; +} +#endif + + +/** + * + * + * Remote device timer requirements + */ +#define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0) +#define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES) + + +/** + * + * @sci_dev: The remote device for which the suspend is being requested. + * + * This method invokes the remote device suspend state handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_suspend( + struct scic_sds_remote_device *sci_dev, + u32 suspend_type) +{ + return sci_dev->state_handlers->suspend_handler(sci_dev, suspend_type); +} + +/** + * + * @sci_dev: The remote device for which the event handling is being + * requested. + * @frame_index: This is the frame index that is being processed. + * + * This method invokes the frame handler for the remote device state machine + * enum sci_status + */ +enum sci_status scic_sds_remote_device_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + return sci_dev->state_handlers->frame_handler(sci_dev, frame_index); +} + +/** + * + * @sci_dev: The remote device for which the event handling is being + * requested. + * @event_code: This is the event code that is to be processed. + * + * This method invokes the remote device event handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code) +{ + return sci_dev->state_handlers->event_handler(sci_dev, event_code); +} + +/** + * + * @controller: The controller that is starting the io request. + * @sci_dev: The remote device for which the start io handling is being + * requested. + * @io_request: The io request that is being started. + * + * This method invokes the remote device start io handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_start_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *io_request) +{ + return sci_dev->state_handlers->start_io_handler( + sci_dev, io_request); +} + +/** + * + * @controller: The controller that is completing the io request. + * @sci_dev: The remote device for which the complete io handling is being + * requested. + * @io_request: The io request that is being completed. + * + * This method invokes the remote device complete io handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_complete_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *io_request) +{ + return sci_dev->state_handlers->complete_io_handler( + sci_dev, io_request); +} + +/** + * + * @controller: The controller that is starting the task request. + * @sci_dev: The remote device for which the start task handling is being + * requested. + * @io_request: The task request that is being started. + * + * This method invokes the remote device start task handler. enum sci_status + */ +enum sci_status scic_sds_remote_device_start_task( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *io_request) +{ + return sci_dev->state_handlers->start_task_handler( + sci_dev, io_request); +} + +/** + * + * @controller: The controller that is completing the task request. + * @sci_dev: The remote device for which the complete task handling is + * being requested. + * @io_request: The task request that is being completed. + * + * This method invokes the remote device complete task handler. enum sci_status + */ + +/** + * + * @sci_dev: + * @request: + * + * This method takes the request and bulids an appropriate SCU context for the + * request and then requests the controller to post the request. none + */ +void scic_sds_remote_device_post_request( + struct scic_sds_remote_device *sci_dev, + u32 request) +{ + u32 context; + + context = scic_sds_remote_device_build_command_context(sci_dev, request); + + scic_sds_controller_post_request( + scic_sds_remote_device_get_controller(sci_dev), + context + ); +} + +#if !defined(DISABLE_ATAPI) +/** + * + * @sci_dev: The device to be checked. + * + * This method check the signature fis of a stp device to decide whether a + * device is atapi or not. true if a device is atapi device. False if a device + * is not atapi. + */ +bool scic_sds_remote_device_is_atapi( + struct scic_sds_remote_device *sci_dev) +{ + if (!sci_dev->target_protocols.u.bits.attached_stp_target) + return false; + else if (sci_dev->is_direct_attached) { + struct scic_sds_phy *phy; + struct scic_sata_phy_properties properties; + struct sata_fis_reg_d2h *signature_fis; + phy = scic_sds_port_get_a_connected_phy(sci_dev->owning_port); + scic_sata_phy_get_properties(phy, &properties); + + /* decode the signature fis. */ + signature_fis = &(properties.signature_fis); + + if ((signature_fis->sector_count == 0x01) + && (signature_fis->lba_low == 0x01) + && (signature_fis->lba_mid == 0x14) + && (signature_fis->lba_high == 0xEB) + && ((signature_fis->device & 0x5F) == 0x00) + ) { + /* An ATA device supporting the PACKET command set. */ + return true; + } else + return false; + } else { + /* Expander supported ATAPI device is not currently supported. */ + return false; + } +} +#endif + +/** + * + * @user_parameter: This is cast to a remote device object. + * + * This method is called once the remote node context is ready to be freed. + * The remote device can now report that its stop operation is complete. none + */ +static void scic_sds_cb_remote_device_rnc_destruct_complete( + void *user_parameter) +{ + struct scic_sds_remote_device *sci_dev; + + sci_dev = (struct scic_sds_remote_device *)user_parameter; + + BUG_ON(sci_dev->started_request_count != 0); + + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); +} + +/** + * + * @user_parameter: This is cast to a remote device object. + * + * This method is called once the remote node context has transisitioned to a + * ready state. This is the indication that the remote device object can also + * transition to ready. none + */ +static void scic_sds_remote_device_resume_complete_handler( + void *user_parameter) +{ + struct scic_sds_remote_device *sci_dev; + + sci_dev = (struct scic_sds_remote_device *)user_parameter; + + if ( + sci_base_state_machine_get_state(&sci_dev->state_machine) + != SCI_BASE_REMOTE_DEVICE_STATE_READY + ) { + sci_base_state_machine_change_state( + &sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_READY + ); + } +} + +/** + * + * @device: This parameter specifies the device for which the request is being + * started. + * @request: This parameter specifies the request being started. + * @status: This parameter specifies the current start operation status. + * + * This method will perform the STP request start processing common to IO + * requests and task requests of all types. none + */ +void scic_sds_remote_device_start_request( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req, + enum sci_status status) +{ + /* We still have a fault in starting the io complete it on the port */ + if (status == SCI_SUCCESS) + scic_sds_remote_device_increment_request_count(sci_dev); + else{ + sci_dev->owning_port->state_handlers->complete_io_handler( + sci_dev->owning_port, sci_dev, sci_req + ); + } +} + + +/** + * + * @request: This parameter specifies the request being continued. + * + * This method will continue to post tc for a STP request. This method usually + * serves as a callback when RNC gets resumed during a task management + * sequence. none + */ +void scic_sds_remote_device_continue_request(void *dev) +{ + struct scic_sds_remote_device *sci_dev = dev; + + /* we need to check if this request is still valid to continue. */ + if (sci_dev->working_request) + scic_controller_continue_io(sci_dev->working_request); +} + +/** + * This method will terminate all of the IO requests in the controllers IO + * request table that were targeted for this device. + * @sci_dev: This parameter specifies the remote device for which to + * attempt to terminate all requests. + * + * This method returns an indication as to whether all requests were + * successfully terminated. If a single request fails to be terminated, then + * this method will return the failure. + */ +static enum sci_status scic_sds_remote_device_terminate_requests( + struct scic_sds_remote_device *sci_dev) +{ + enum sci_status status = SCI_SUCCESS; + enum sci_status terminate_status = SCI_SUCCESS; + struct scic_sds_request *sci_req; + u32 index; + u32 request_count = sci_dev->started_request_count; + + for (index = 0; + (index < SCI_MAX_IO_REQUESTS) && (request_count > 0); + index++) { + sci_req = sci_dev->owning_port->owning_controller->io_request_table[index]; + + if ((sci_req != NULL) && (sci_req->target_device == sci_dev)) { + terminate_status = scic_controller_terminate_request( + sci_dev->owning_port->owning_controller, + sci_dev, + sci_req + ); + + if (terminate_status != SCI_SUCCESS) + status = terminate_status; + + request_count--; + } + } + + return status; +} + +static enum sci_status +default_device_handler(struct scic_sds_remote_device *sci_dev, + const char *func) +{ + dev_warn(scirdev_to_dev(sci_dev), + "%s: in wrong state: %d\n", func, + sci_base_state_machine_get_state(&sci_dev->state_machine)); + return SCI_FAILURE_INVALID_STATE; +} + +enum sci_status scic_sds_remote_device_default_start_handler( + struct scic_sds_remote_device *sci_dev) +{ + return default_device_handler(sci_dev, __func__); +} + +static enum sci_status scic_sds_remote_device_default_stop_handler( + struct scic_sds_remote_device *sci_dev) +{ + return default_device_handler(sci_dev, __func__); +} + +enum sci_status scic_sds_remote_device_default_fail_handler( + struct scic_sds_remote_device *sci_dev) +{ + return default_device_handler(sci_dev, __func__); +} + +enum sci_status scic_sds_remote_device_default_destruct_handler( + struct scic_sds_remote_device *sci_dev) +{ + return default_device_handler(sci_dev, __func__); +} + +enum sci_status scic_sds_remote_device_default_reset_handler( + struct scic_sds_remote_device *sci_dev) +{ + return default_device_handler(sci_dev, __func__); +} + +enum sci_status scic_sds_remote_device_default_reset_complete_handler( + struct scic_sds_remote_device *sci_dev) +{ + return default_device_handler(sci_dev, __func__); +} + +enum sci_status scic_sds_remote_device_default_suspend_handler( + struct scic_sds_remote_device *sci_dev, u32 suspend_type) +{ + return default_device_handler(sci_dev, __func__); +} + +enum sci_status scic_sds_remote_device_default_resume_handler( + struct scic_sds_remote_device *sci_dev) +{ + return default_device_handler(sci_dev, __func__); +} + +/** + * + * @device: The struct scic_sds_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @event_code: The event code that the struct scic_sds_controller wants the device + * object to process. + * + * This method is the default event handler. It will call the RNC state + * machine handler for any RNC events otherwise it will log a warning and + * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_remote_device_core_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code, + bool is_ready_state) +{ + enum sci_status status; + + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_OPS_MISC: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + status = scic_sds_remote_node_context_event_handler(&sci_dev->rnc, event_code); + break; + case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: + + if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { + status = SCI_SUCCESS; + + /* Suspend the associated RNC */ + scic_sds_remote_node_context_suspend(&sci_dev->rnc, + SCI_SOFTWARE_SUSPENSION, + NULL, NULL); + + dev_dbg(scirdev_to_dev(sci_dev), + "%s: device: %p event code: %x: %s\n", + __func__, sci_dev, event_code, + (is_ready_state) + ? "I_T_Nexus_Timeout event" + : "I_T_Nexus_Timeout event in wrong state"); + + break; + } + /* Else, fall through and treat as unhandled... */ + + default: + dev_dbg(scirdev_to_dev(sci_dev), + "%s: device: %p event code: %x: %s\n", + __func__, sci_dev, event_code, + (is_ready_state) + ? "unexpected event" + : "unexpected event in wrong state"); + status = SCI_FAILURE_INVALID_STATE; + break; + } + + return status; +} +/** + * + * @device: The struct scic_sds_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @event_code: The event code that the struct scic_sds_controller wants the device + * object to process. + * + * This method is the default event handler. It will call the RNC state + * machine handler for any RNC events otherwise it will log a warning and + * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_remote_device_default_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code) +{ + return scic_sds_remote_device_core_event_handler(sci_dev, + event_code, + false); +} + +/** + * + * @device: The struct scic_sds_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @frame_index: The frame index for which the struct scic_sds_controller wants this + * device object to process. + * + * This method is the default unsolicited frame handler. It logs a warning, + * releases the frame and returns a failure. enum sci_status + * SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_default_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + dev_warn(scirdev_to_dev(sci_dev), + "%s: SCIC Remote Device requested to handle frame %x " + "while in wrong state %d\n", + __func__, + frame_index, + sci_base_state_machine_get_state( + &sci_dev->state_machine)); + + /* Return the frame back to the controller */ + scic_sds_controller_release_frame( + scic_sds_remote_device_get_controller(sci_dev), frame_index + ); + + return SCI_FAILURE_INVALID_STATE; +} + +enum sci_status scic_sds_remote_device_default_start_request_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + return default_device_handler(sci_dev, __func__); +} + +enum sci_status scic_sds_remote_device_default_complete_request_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + return default_device_handler(sci_dev, __func__); +} + +enum sci_status scic_sds_remote_device_default_continue_request_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + return default_device_handler(sci_dev, __func__); +} + +/** + * + * @device: The struct scic_sds_remote_device which is then cast into a + * struct scic_sds_remote_device. + * @frame_index: The frame index for which the struct scic_sds_controller wants this + * device object to process. + * + * This method is a general ssp frame handler. In most cases the device object + * needs to route the unsolicited frame processing to the io request object. + * This method decodes the tag for the io request object and routes the + * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE + */ +enum sci_status scic_sds_remote_device_general_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + enum sci_status result; + struct sci_ssp_frame_header *frame_header; + struct scic_sds_request *io_request; + + result = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), + frame_index, + (void **)&frame_header + ); + + if (SCI_SUCCESS == result) { + io_request = scic_sds_controller_get_io_request_from_tag( + scic_sds_remote_device_get_controller(sci_dev), frame_header->tag); + + if ((io_request == NULL) + || (io_request->target_device != sci_dev)) { + /* + * We could not map this tag to a valid IO request + * Just toss the frame and continue */ + scic_sds_controller_release_frame( + scic_sds_remote_device_get_controller(sci_dev), frame_index + ); + } else { + /* The IO request is now in charge of releasing the frame */ + result = io_request->state_handlers->frame_handler( + io_request, frame_index); + } + } + + return result; +} + +/** + * + * @[in]: sci_dev This is the device object that is receiving the event. + * @[in]: event_code The event code to process. + * + * This is a common method for handling events reported to the remote device + * from the controller object. enum sci_status + */ +enum sci_status scic_sds_remote_device_general_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code) +{ + return scic_sds_remote_device_core_event_handler(sci_dev, + event_code, + true); +} + +/* + * ***************************************************************************** + * * STOPPED STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @device: + * + * This method takes the struct scic_sds_remote_device from a stopped state and + * attempts to start it. The RNC buffer for the device is constructed and the + * device state machine is transitioned to the + * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING. enum sci_status SCI_SUCCESS if there is + * an RNC buffer available to construct the remote device. + * SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer available in + * which to construct the remote device. + */ +static enum sci_status scic_sds_remote_device_stopped_state_start_handler( + struct scic_sds_remote_device *sci_dev) +{ + enum sci_status status; + + status = scic_sds_remote_node_context_resume(&sci_dev->rnc, + scic_sds_remote_device_resume_complete_handler, sci_dev); + + if (status == SCI_SUCCESS) + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STARTING); + + return status; +} + +static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( + struct scic_sds_remote_device *sci_dev) +{ + return SCI_SUCCESS; +} + +/** + * + * @sci_dev: The struct scic_sds_remote_device which is cast into a + * struct scic_sds_remote_device. + * + * This method will destruct a struct scic_sds_remote_device that is in a stopped + * state. This is the only state from which a destruct request will succeed. + * The RNi for this struct scic_sds_remote_device is returned to the free pool and the + * device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( + struct scic_sds_remote_device *sci_dev) +{ + struct scic_sds_controller *scic; + + scic = scic_sds_remote_device_get_controller(sci_dev); + scic_sds_controller_free_remote_node_context(scic, sci_dev, + sci_dev->rnc.remote_node_index); + sci_dev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_FINAL); + + return SCI_SUCCESS; +} + +/* + * ***************************************************************************** + * * STARTING STATE HANDLERS + * ***************************************************************************** */ + +static enum sci_status scic_sds_remote_device_starting_state_stop_handler( + struct scic_sds_remote_device *sci_dev) +{ + /* + * This device has not yet started so there had better be no IO requests + */ + BUG_ON(sci_dev->started_request_count != 0); + + /* + * Destroy the remote node context + */ + scic_sds_remote_node_context_destruct(&sci_dev->rnc, + scic_sds_cb_remote_device_rnc_destruct_complete, sci_dev); + + /* + * Transition to the stopping state and wait for the remote node to + * complete being posted and invalidated. + */ + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); + + return SCI_SUCCESS; +} + +enum sci_status scic_sds_remote_device_ready_state_stop_handler( + struct scic_sds_remote_device *sci_dev) +{ + enum sci_status status = SCI_SUCCESS; + + /* Request the parent state machine to transition to the stopping state */ + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); + + if (sci_dev->started_request_count == 0) { + scic_sds_remote_node_context_destruct(&sci_dev->rnc, + scic_sds_cb_remote_device_rnc_destruct_complete, + sci_dev); + } else + status = scic_sds_remote_device_terminate_requests(sci_dev); + + return status; +} + +/** + * + * @device: The struct scic_sds_remote_device object which is cast to a + * struct scic_sds_remote_device object. + * + * This is the ready state device reset handler enum sci_status + */ +enum sci_status scic_sds_remote_device_ready_state_reset_handler( + struct scic_sds_remote_device *sci_dev) +{ + /* Request the parent state machine to transition to the stopping state */ + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING); + + return SCI_SUCCESS; +} + +/* + * This method will attempt to start a task request for this device object. The + * remote device object will issue the start request for the task and if + * successful it will start the request for the port object then increment its + * own requet count. enum sci_status SCI_SUCCESS if the task request is started for + * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request + * object could not get the resources to start. + */ +static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status result; + + /* See if the port is in a state where we can start the IO request */ + result = scic_sds_port_start_io( + scic_sds_remote_device_get_port(sci_dev), sci_dev, request); + + if (result == SCI_SUCCESS) { + result = scic_sds_remote_node_context_start_task(&sci_dev->rnc, + request); + if (result == SCI_SUCCESS) + result = scic_sds_request_start(request); + + scic_sds_remote_device_start_request(sci_dev, request, result); + } + + return result; +} + +/* + * This method will attempt to start an io request for this device object. The + * remote device object will issue the start request for the io and if + * successful it will start the request for the port object then increment its + * own requet count. enum sci_status SCI_SUCCESS if the io request is started for + * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request + * object could not get the resources to start. + */ +static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status result; + + /* See if the port is in a state where we can start the IO request */ + result = scic_sds_port_start_io( + scic_sds_remote_device_get_port(sci_dev), sci_dev, request); + + if (result == SCI_SUCCESS) { + result = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); + if (result == SCI_SUCCESS) + result = scic_sds_request_start(request); + + scic_sds_remote_device_start_request(sci_dev, request, result); + } + + return result; +} + +/* + * This method will complete the request for the remote device object. The + * method will call the completion handler for the request object and if + * successful it will complete the request on the port object then decrement + * its own started_request_count. enum sci_status + */ +static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status result; + + result = scic_sds_request_complete(request); + + if (result != SCI_SUCCESS) + return result; + + /* See if the port is in a state + * where we can start the IO request */ + result = scic_sds_port_complete_io( + scic_sds_remote_device_get_port(sci_dev), + sci_dev, request); + + if (result == SCI_SUCCESS) + scic_sds_remote_device_decrement_request_count(sci_dev); + + return result; +} + +/* + * ***************************************************************************** + * * STOPPING STATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @sci_dev: The struct scic_sds_remote_device which is cast into a + * struct scic_sds_remote_device. + * + * This method will stop a struct scic_sds_remote_device that is already in the + * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an error + * since we allow a stop request on a device that is alreay stopping or + * stopped. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( + struct scic_sds_remote_device *device) +{ + /* + * All requests should have been terminated, but if there is an + * attempt to stop a device already in the stopping state, then + * try again to terminate. */ + return scic_sds_remote_device_terminate_requests(device); +} -#include "isci.h" -#include "scic_io_request.h" -#include "scic_remote_device.h" -#include "scic_phy.h" -#include "scic_port.h" -#include "port.h" -#include "remote_device.h" -#include "request.h" -#include "task.h" +/** + * + * @device: The device object for which the request is completing. + * @request: The task request that is being completed. + * + * This method completes requests for this struct scic_sds_remote_device while it is + * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the + * complete method for the request object and if that is successful the port + * object is called to complete the task request. Then the device object itself + * completes the task request. If struct scic_sds_remote_device started_request_count + * goes to 0 and the invalidate RNC request has completed the device object can + * transition to the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. enum sci_status + */ +static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status status = SCI_SUCCESS; + + status = scic_sds_request_complete(request); + + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_port_complete_io(scic_sds_remote_device_get_port(sci_dev), + sci_dev, request); + if (status != SCI_SUCCESS) + return status; + + scic_sds_remote_device_decrement_request_count(sci_dev); + + if (scic_sds_remote_device_get_request_count(sci_dev) == 0) + scic_sds_remote_node_context_destruct(&sci_dev->rnc, + scic_sds_cb_remote_device_rnc_destruct_complete, + sci_dev); + return SCI_SUCCESS; +} + +/** + * + * @device: The struct scic_sds_remote_device which is to be cast into a + * struct scic_sds_remote_device object. + * + * This method will complete the reset operation when the device is in the + * resetting state. enum sci_status + */ +static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( + struct scic_sds_remote_device *sci_dev) +{ + + sci_base_state_machine_change_state( + &sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_READY + ); + + return SCI_SUCCESS; +} + +/** + * + * @device: The struct scic_sds_remote_device which is to be cast into a + * struct scic_sds_remote_device object. + * + * This method will stop the remote device while in the resetting state. + * enum sci_status + */ +static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( + struct scic_sds_remote_device *sci_dev) +{ + sci_base_state_machine_change_state( + &sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING + ); + + return SCI_SUCCESS; +} + +/* + * This method completes requests for this struct scic_sds_remote_device while it is + * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the + * complete method for the request object and if that is successful the port + * object is called to complete the task request. Then the device object itself + * completes the task request. enum sci_status + */ +static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status status = SCI_SUCCESS; + + status = scic_sds_request_complete(request); + + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + scic_sds_remote_device_get_port(sci_dev), + sci_dev, request); + + if (status == SCI_SUCCESS) { + scic_sds_remote_device_decrement_request_count(sci_dev); + } + } + + return status; +} + +static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { + [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { + .start_handler = scic_sds_remote_device_stopped_state_start_handler, + .stop_handler = scic_sds_remote_device_stopped_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_starting_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, + .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, + .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_stopping_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_resetting_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + } +}; + +static void scic_sds_remote_device_initial_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + + sci_dev = container_of(object, typeof(*sci_dev), parent); + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); + + /* Initial state is a transitional state to the stopped state */ + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); +} + +/** + * isci_remote_device_change_state() - This function gets the status of the + * remote_device object. + * @isci_device: This parameter points to the isci_remote_device object + * + * status of the object as a isci_status enum. + */ +void isci_remote_device_change_state( + struct isci_remote_device *isci_device, + enum isci_status status) +{ + unsigned long flags; + + spin_lock_irqsave(&isci_device->state_lock, flags); + isci_device->status = status; + spin_unlock_irqrestore(&isci_device->state_lock, flags); +} +/** + * scic_remote_device_destruct() - free remote node context and destruct + * @remote_device: This parameter specifies the remote device to be destructed. + * + * Remote device objects are a limited resource. As such, they must be + * protected. Thus calls to construct and destruct are mutually exclusive and + * non-reentrant. The return value shall indicate if the device was + * successfully destructed or if some failure occurred. enum sci_status This value + * is returned if the device is successfully destructed. + * SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied + * device isn't valid (e.g. it's already been destoryed, the handle isn't + * valid, etc.). + */ +static enum sci_status scic_remote_device_destruct(struct scic_sds_remote_device *sci_dev) +{ + return sci_dev->state_handlers->destruct_handler(sci_dev); +} /** * isci_remote_device_deconstruct() - This function frees an isci_remote_device. @@ -98,6 +1249,418 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ wake_up(&ihost->eventq); } +/** + * isci_remote_device_stop_complete() - This function is called by the scic + * when the remote device stop has completed. We mark the isci device as not + * ready and remove the isci remote device. + * @ihost: This parameter specifies the isci host object. + * @idev: This parameter specifies the remote device. + * @status: This parameter specifies status of the completion. + * + */ +static void isci_remote_device_stop_complete(struct isci_host *ihost, + struct isci_remote_device *idev) +{ + dev_dbg(&ihost->pdev->dev, "%s: complete idev = %p\n", __func__, idev); + + isci_remote_device_change_state(idev, isci_stopped); + + /* after stop, we can tear down resources. */ + isci_remote_device_deconstruct(ihost, idev); +} + +static void scic_sds_remote_device_stopped_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev; + struct scic_sds_controller *scic; + struct isci_remote_device *idev; + struct isci_host *ihost; + u32 prev_state; + + sci_dev = container_of(object, typeof(*sci_dev), parent); + scic = scic_sds_remote_device_get_controller(sci_dev); + ihost = sci_object_get_association(scic); + idev = sci_object_get_association(sci_dev); + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); + + /* If we are entering from the stopping state let the SCI User know that + * the stop operation has completed. + */ + prev_state = sci_dev->state_machine.previous_state_id; + if (prev_state == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) + isci_remote_device_stop_complete(ihost, idev); + + scic_sds_controller_remote_device_stopped(scic, sci_dev); +} + +static void scic_sds_remote_device_starting_state_enter(struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STARTING); + + isci_remote_device_not_ready(ihost, idev, + SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); +} + +static void scic_sds_remote_device_ready_state_enter(struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + SET_STATE_HANDLER(sci_dev, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_READY); + + scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; + + if (sci_dev->has_ready_substate_machine) + sci_base_state_machine_start(&sci_dev->ready_substate_machine); + else + isci_remote_device_ready(ihost, idev); +} + +static void scic_sds_remote_device_ready_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + if (sci_dev->has_ready_substate_machine) + sci_base_state_machine_stop(&sci_dev->ready_substate_machine); + else { + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + isci_remote_device_not_ready(ihost, idev, + SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); + } +} + +static void scic_sds_remote_device_stopping_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + sci_dev, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING + ); +} + +static void scic_sds_remote_device_failed_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + sci_dev, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_FAILED + ); +} + +static void scic_sds_remote_device_resetting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + sci_dev, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING + ); + + scic_sds_remote_node_context_suspend( + &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); +} + +static void scic_sds_remote_device_resetting_state_exit( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + + scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); +} + +static void scic_sds_remote_device_final_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + + SET_STATE_HANDLER( + sci_dev, + scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_FINAL + ); +} + + +static const struct sci_base_state scic_sds_remote_device_state_table[] = { + [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { + .enter_state = scic_sds_remote_device_initial_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { + .enter_state = scic_sds_remote_device_stopped_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { + .enter_state = scic_sds_remote_device_starting_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { + .enter_state = scic_sds_remote_device_ready_state_enter, + .exit_state = scic_sds_remote_device_ready_state_exit + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { + .enter_state = scic_sds_remote_device_stopping_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { + .enter_state = scic_sds_remote_device_failed_state_enter, + }, + [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { + .enter_state = scic_sds_remote_device_resetting_state_enter, + .exit_state = scic_sds_remote_device_resetting_state_exit + }, + [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { + .enter_state = scic_sds_remote_device_final_state_enter, + }, +}; + +/** + * scic_remote_device_construct() - This method will perform the construction + * common to all remote device objects. + * @sci_port: SAS/SATA port through which this device is accessed. + * @sci_dev: remote device to construct + * + * It isn't necessary to call scic_remote_device_destruct() for device objects + * that have only called this method for construction. Once subsequent + * construction methods have been invoked (e.g. + * scic_remote_device_da_construct()), then destruction should occur. none + */ +static void scic_remote_device_construct(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev) +{ + sci_dev->owning_port = sci_port; + sci_dev->started_request_count = 0; + sci_dev->parent.private = NULL; + + sci_base_state_machine_construct( + &sci_dev->state_machine, + &sci_dev->parent, + scic_sds_remote_device_state_table, + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL + ); + + sci_base_state_machine_start( + &sci_dev->state_machine + ); + + scic_sds_remote_node_context_construct(&sci_dev->rnc, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); + + sci_object_set_association(&sci_dev->rnc, sci_dev); +} + +/** + * scic_remote_device_da_construct() - This method will construct a + * SCIC_REMOTE_DEVICE object for a direct attached (da) device. The + * information (e.g. IAF, Signature FIS, etc.) necessary to build the device + * is known to the SCI Core since it is contained in the scic_phy object. + * @remote_device: This parameter specifies the remote device to be destructed. + * + * The user must have previously called scic_remote_device_construct() Remote + * device objects are a limited resource. As such, they must be protected. + * Thus calls to construct and destruct are mutually exclusive and + * non-reentrant. Indicate if the remote device was successfully constructed. + * SCI_SUCCESS Returned if the device was successfully constructed. + * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been + * constructed. If it's an additional phy for the target, then call + * scic_remote_device_da_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned + * if the supplied parameters necessitate creation of a remote device for which + * the protocol is not supported by the underlying controller hardware. + * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core + * controller associated with the supplied parameters is unable to support + * additional remote devices. + */ +static enum sci_status scic_remote_device_da_construct(struct scic_sds_remote_device *sci_dev) +{ + enum sci_status status; + u16 remote_node_index; + struct sci_sas_identify_address_frame_protocols protocols; + + /* + * This information is request to determine how many remote node context + * entries will be needed to store the remote node. + */ + scic_sds_port_get_attached_protocols(sci_dev->owning_port, &protocols); + sci_dev->target_protocols.u.all = protocols.u.all; + sci_dev->is_direct_attached = true; +#if !defined(DISABLE_ATAPI) + sci_dev->is_atapi = scic_sds_remote_device_is_atapi(sci_dev); +#endif + + status = scic_sds_controller_allocate_remote_node_context( + sci_dev->owning_port->owning_controller, + sci_dev, + &remote_node_index); + + if (status == SCI_SUCCESS) { + sci_dev->rnc.remote_node_index = remote_node_index; + + scic_sds_port_get_attached_sas_address( + sci_dev->owning_port, &sci_dev->device_address); + + if (sci_dev->target_protocols.u.bits.attached_ssp_target) { + sci_dev->has_ready_substate_machine = false; + } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { + sci_dev->has_ready_substate_machine = true; + + sci_base_state_machine_construct( + &sci_dev->ready_substate_machine, + &sci_dev->parent, + scic_sds_stp_remote_device_ready_substate_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { + sci_dev->has_ready_substate_machine = true; + + /* add the SMP ready substate machine construction here */ + sci_base_state_machine_construct( + &sci_dev->ready_substate_machine, + &sci_dev->parent, + scic_sds_smp_remote_device_ready_substate_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } + + sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed( + sci_dev->owning_port); + + /* / @todo Should I assign the port width by reading all of the phys on the port? */ + sci_dev->device_port_width = 1; + } + + return status; +} + +static void scic_sds_remote_device_get_info_from_smp_discover_response( + struct scic_sds_remote_device *sci_dev, + struct smp_response_discover *discover_response) +{ + /* decode discover_response to set sas_address to sci_dev. */ + sci_dev->device_address.high = + discover_response->attached_sas_address.high; + + sci_dev->device_address.low = + discover_response->attached_sas_address.low; + + sci_dev->target_protocols.u.all = discover_response->protocols.u.all; +} + +/** + * scic_remote_device_ea_construct() - This method will construct an + * SCIC_REMOTE_DEVICE object for an expander attached (ea) device from an + * SMP Discover Response. + * @remote_device: This parameter specifies the remote device to be destructed. + * @discover_response: This parameter specifies the SMP Discovery Response to + * be used in device creation. + * + * The user must have previously called scic_remote_device_construct() Remote + * device objects are a limited resource. As such, they must be protected. + * Thus calls to construct and destruct are mutually exclusive and + * non-reentrant. Indicate if the remote device was successfully constructed. + * SCI_SUCCESS Returned if the device was successfully constructed. + * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been + * constructed. If it's an additional phy for the target, then call + * scic_ea_remote_device_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned + * if the supplied parameters necessitate creation of a remote device for which + * the protocol is not supported by the underlying controller hardware. + * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core + * controller associated with the supplied parameters is unable to support + * additional remote devices. + */ +static enum sci_status scic_remote_device_ea_construct(struct scic_sds_remote_device *sci_dev, + struct smp_response_discover *discover_response) +{ + enum sci_status status; + struct scic_sds_controller *scic; + + scic = scic_sds_port_get_controller(sci_dev->owning_port); + + scic_sds_remote_device_get_info_from_smp_discover_response( + sci_dev, discover_response); + + status = scic_sds_controller_allocate_remote_node_context( + scic, sci_dev, &sci_dev->rnc.remote_node_index); + + if (status == SCI_SUCCESS) { + if (sci_dev->target_protocols.u.bits.attached_ssp_target) { + sci_dev->has_ready_substate_machine = false; + } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { + sci_dev->has_ready_substate_machine = true; + + /* add the SMP ready substate machine construction here */ + sci_base_state_machine_construct( + &sci_dev->ready_substate_machine, + &sci_dev->parent, + scic_sds_smp_remote_device_ready_substate_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { + sci_dev->has_ready_substate_machine = true; + + sci_base_state_machine_construct( + &sci_dev->ready_substate_machine, + &sci_dev->parent, + scic_sds_stp_remote_device_ready_substate_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } + + /* + * For SAS-2 the physical link rate is actually a logical link + * rate that incorporates multiplexing. The SCU doesn't + * incorporate multiplexing and for the purposes of the + * connection the logical link rate is that same as the + * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay + * one another, so this code works for both situations. */ + sci_dev->connection_rate = min_t(u16, + scic_sds_port_get_max_allowed_speed(sci_dev->owning_port), + discover_response->u2.sas1_1.negotiated_physical_link_rate + ); + + /* / @todo Should I assign the port width by reading all of the phys on the port? */ + sci_dev->device_port_width = 1; + } + + return status; +} + +/** + * scic_remote_device_start() - This method will start the supplied remote + * device. This method enables normal IO requests to flow through to the + * remote device. + * @remote_device: This parameter specifies the device to be started. + * @timeout: This parameter specifies the number of milliseconds in which the + * start operation should complete. + * + * An indication of whether the device was successfully started. SCI_SUCCESS + * This value is returned if the device was successfully started. + * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start + * the device when there have been no phys added to it. + */ +static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *sci_dev, + u32 timeout) +{ + return sci_dev->state_handlers->start_handler(sci_dev); +} /** * isci_remote_device_construct() - This function calls the scic remote device @@ -306,51 +1869,6 @@ void isci_remote_device_not_ready(struct isci_host *ihost, isci_remote_device_change_state(idev, isci_ready); } -/** - * isci_remote_device_stop_complete() - This function is called by the scic - * when the remote device stop has completed. We mark the isci device as not - * ready and remove the isci remote device. - * @isci_host: This parameter specifies the isci host object. - * @isci_device: This parameter specifies the remote device. - * @status: This parameter specifies status of the completion. - * - */ -void isci_remote_device_stop_complete( - struct isci_host *isci_host, - struct isci_remote_device *isci_device, - enum sci_status status) -{ - dev_dbg(&isci_host->pdev->dev, - "%s: complete isci_device = %p, status = 0x%x\n", - __func__, - isci_device, - status); - - isci_remote_device_change_state(isci_device, isci_stopped); - - /* after stop, we can tear down resources. */ - isci_remote_device_deconstruct(isci_host, isci_device); - -} - -/** - * isci_remote_device_start_complete() - This function is called by the scic - * when the remote device start has completed - * @isci_host: This parameter specifies the isci host object. - * @isci_device: This parameter specifies the remote device. - * @status: This parameter specifies status of the completion. - * - */ -void isci_remote_device_start_complete( - struct isci_host *isci_host, - struct isci_remote_device *isci_device, - enum sci_status status) -{ - - -} - - /** * isci_remote_device_stop() - This function is called internally to stop the * remote device. @@ -572,21 +2090,3 @@ void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote } spin_unlock_irqrestore(&ihost->scic_lock, flags); } - -/** - * isci_remote_device_change_state() - This function gets the status of the - * remote_device object. - * @isci_device: This parameter points to the isci_remote_device object - * - * status of the object as a isci_status enum. - */ -void isci_remote_device_change_state( - struct isci_remote_device *isci_device, - enum isci_status status) -{ - unsigned long flags; - - spin_lock_irqsave(&isci_device->state_lock, flags); - isci_device->status = status; - spin_unlock_irqrestore(&isci_device->state_lock, flags); -} diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index aeda39568a1c..9d8fcbf72ded 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -53,11 +53,127 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if !defined(_ISCI_REMOTE_DEVICE_H_) +#ifndef _ISCI_REMOTE_DEVICE_H_ #define _ISCI_REMOTE_DEVICE_H_ -#include "scic_sds_remote_device.h" +#include +#include "sci_status.h" +#include "intel_sas.h" +#include "scu_remote_node_context.h" +#include "remote_node_context.h" +#include "port.h" -struct isci_host; +enum scic_remote_device_not_ready_reason_code { + SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED, + SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED, + SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED, + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED, + SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED, + + SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX + +}; + +struct scic_sds_remote_device { + /** + * The field specifies that the parent object for the base remote + * device is the base object itself. + */ + struct sci_base_object parent; + + /** + * This field contains the information for the base remote device state + * machine. + */ + struct sci_base_state_machine state_machine; + + /** + * This field is the programmed device port width. This value is + * written to the RCN data structure to tell the SCU how many open + * connections this device can have. + */ + u32 device_port_width; + + /** + * This field is the programmed connection rate for this remote device. It is + * used to program the TC with the maximum allowed connection rate. + */ + enum sas_linkrate connection_rate; + + /** + * This field contains the allowed target protocols for this remote device. + */ + struct smp_discover_response_protocols target_protocols; + + /** + * This field contains the device SAS address. + */ + struct sci_sas_address device_address; + + /** + * This filed is assinged the value of true if the device is directly + * attached to the port. + */ + bool is_direct_attached; + +#if !defined(DISABLE_ATAPI) + /** + * This filed is assinged the value of true if the device is an ATAPI + * device. + */ + bool is_atapi; +#endif + + /** + * This filed contains a pointer back to the port to which this device + * is assigned. + */ + struct scic_sds_port *owning_port; + + /** + * This field contains the SCU silicon remote node context specific + * information. + */ + struct scic_sds_remote_node_context rnc; + + /** + * This field contains the stated request count for the remote device. The + * device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all + * requests are complete and the rnc_posted value is false. + */ + u32 started_request_count; + + /** + * This field contains a pointer to the working request object. It is only + * used only for SATA requests since the unsolicited frames we get from the + * hardware have no Tag value to look up the io request object. + */ + struct scic_sds_request *working_request; + + /** + * This field contains the reason for the remote device going not_ready. It is + * assigned in the state handlers and used in the state transition. + */ + u32 not_ready_reason; + + /** + * This field is true if this remote device has an initialzied ready substate + * machine. SSP devices do not have a ready substate machine and STP devices + * have a ready substate machine. + */ + bool has_ready_substate_machine; + + /** + * This field contains the state machine for the ready substate machine for + * this struct scic_sds_remote_device object. + */ + struct sci_base_state_machine ready_substate_machine; + + /** + * This field maintains the set of state handlers for the remote device + * object. These are changed each time the remote device enters a new state. + */ + const struct scic_sds_remote_device_state_handler *state_handlers; +}; struct isci_remote_device { enum isci_status status; @@ -75,12 +191,6 @@ struct isci_remote_device { #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 -void isci_remote_device_start_complete(struct isci_host *ihost, - struct isci_remote_device *idev, - enum sci_status); -void isci_remote_device_stop_complete(struct isci_host *ihost, - struct isci_remote_device *idev, - enum sci_status); enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev); void isci_remote_device_nuke_requests(struct isci_host *ihost, @@ -97,5 +207,619 @@ void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev); void isci_remote_device_change_state(struct isci_remote_device *idev, enum isci_status status); +/** + * scic_remote_device_stop() - This method will stop both transmission and + * reception of link activity for the supplied remote device. This method + * disables normal IO requests from flowing through to the remote device. + * @remote_device: This parameter specifies the device to be stopped. + * @timeout: This parameter specifies the number of milliseconds in which the + * stop operation should complete. + * + * An indication of whether the device was successfully stopped. SCI_SUCCESS + * This value is returned if the transmission and reception for the device was + * successfully stopped. + */ +enum sci_status scic_remote_device_stop( + struct scic_sds_remote_device *remote_device, + u32 timeout); + +/** + * scic_remote_device_reset() - This method will reset the device making it + * ready for operation. This method must be called anytime the device is + * reset either through a SMP phy control or a port hard reset request. + * @remote_device: This parameter specifies the device to be reset. + * + * This method does not actually cause the device hardware to be reset. This + * method resets the software object so that it will be operational after a + * device hardware reset completes. An indication of whether the device reset + * was accepted. SCI_SUCCESS This value is returned if the device reset is + * started. + */ +enum sci_status scic_remote_device_reset( + struct scic_sds_remote_device *remote_device); + +/** + * scic_remote_device_reset_complete() - This method informs the device object + * that the reset operation is complete and the device can resume operation + * again. + * @remote_device: This parameter specifies the device which is to be informed + * of the reset complete operation. + * + * An indication that the device is resuming operation. SCI_SUCCESS the device + * is resuming operation. + */ +enum sci_status scic_remote_device_reset_complete( + struct scic_sds_remote_device *remote_device); + + + +/** + * scic_remote_device_get_connection_rate() - This method simply returns the + * link rate at which communications to the remote device occur. + * @remote_device: This parameter specifies the device for which to get the + * connection rate. + * + * Return the link rate at which we transfer for the supplied remote device. + */ +enum sas_linkrate scic_remote_device_get_connection_rate( + struct scic_sds_remote_device *remote_device); + +/** + * scic_remote_device_get_protocols() - This method will indicate which + * protocols are supported by this remote device. + * @remote_device: This parameter specifies the device for which to return the + * protocol. + * @protocols: This parameter specifies the output values, from the remote + * device object, which indicate the protocols supported by the supplied + * remote_device. + * + * The type of protocols supported by this device. The values are returned as + * part of a bit mask in order to allow for multi-protocol support. + */ +void scic_remote_device_get_protocols( + struct scic_sds_remote_device *remote_device, + struct smp_discover_response_protocols *protocols); + + +#if !defined(DISABLE_ATAPI) +/** + * scic_remote_device_is_atapi() - + * @this_device: The device whose type is to be decided. + * + * This method first decide whether a device is a stp target, then decode the + * signature fis of a DA STP device to tell whether it is a standard end disk + * or an ATAPI device. bool Indicate a device is ATAPI device or not. + */ +bool scic_remote_device_is_atapi( + struct scic_sds_remote_device *device_handle); +#else /* !defined(DISABLE_ATAPI) */ +#define scic_remote_device_is_atapi(device_handle) false +#endif /* !defined(DISABLE_ATAPI) */ + + + +/** + * enum scic_sds_remote_device_states - This enumeration depicts all the states + * for the common remote device state machine. + * + * + */ +enum scic_sds_remote_device_states { + /** + * Simply the initial state for the base remote device state machine. + */ + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL, + + /** + * This state indicates that the remote device has successfully been + * stopped. In this state no new IO operations are permitted. + * This state is entered from the INITIAL state. + * This state is entered from the STOPPING state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED, + + /** + * This state indicates the the remote device is in the process of + * becoming ready (i.e. starting). In this state no new IO operations + * are permitted. + * This state is entered from the STOPPED state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STARTING, + + /** + * This state indicates the remote device is now ready. Thus, the user + * is able to perform IO operations on the remote device. + * This state is entered from the STARTING state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_READY, + + /** + * This state indicates that the remote device is in the process of + * stopping. In this state no new IO operations are permitted, but + * existing IO operations are allowed to complete. + * This state is entered from the READY state. + * This state is entered from the FAILED state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, + + /** + * This state indicates that the remote device has failed. + * In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + * This state is entered from the READY state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_FAILED, + + /** + * This state indicates the device is being reset. + * In this state no new IO operations are permitted. + * This state is entered from the READY state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, + + /** + * Simply the final state for the base remote device state machine. + */ + SCI_BASE_REMOTE_DEVICE_STATE_FINAL, +}; + +/** + * enum scic_sds_ssp_remote_device_ready_substates - + * + * This is the enumeration of the ready substates for the + * struct scic_sds_remote_device. + */ +enum scic_sds_ssp_remote_device_ready_substates { + /** + * This is the initial state for the remote device ready substate. + */ + SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL, + + /** + * This is the ready operational substate for the remote device. + * This is the normal operational state for a remote device. + */ + SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL, + + /** + * This is the suspended state for the remote device. This is the state + * that the device is placed in when a RNC suspend is received by + * the SCU hardware. + */ + SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED, + + /** + * This is the final state that the device is placed in before a change + * to the base state machine. + */ + SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL, + + SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES +}; + +/** + * enum scic_sds_stp_remote_device_ready_substates - + * + * This is the enumeration for the struct scic_sds_remote_device ready substates + * for the STP remote device. + */ +enum scic_sds_stp_remote_device_ready_substates { + /** + * This is the idle substate for the stp remote device. When there are no + * active IO for the device it is is in this state. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, + + /** + * This is the command state for for the STP remote device. This state is + * entered when the device is processing a non-NCQ command. The device object + * will fail any new start IO requests until this command is complete. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD, + + /** + * This is the NCQ state for the STP remote device. This state is entered + * when the device is processing an NCQ reuqest. It will remain in this state + * so long as there is one or more NCQ requests being processed. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ, + + /** + * This is the NCQ error state for the STP remote device. This state is + * entered when an SDB error FIS is received by the device object while in the + * NCQ state. The device object will only accept a READ LOG command while in + * this state. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR, + +#if !defined(DISABLE_ATAPI) + /** + * This is the ATAPI error state for the STP ATAPI remote device. This state is + * entered when ATAPI device sends error status FIS without data while the device + * object is in CMD state. A suspension event is expected in this state. The device + * object will resume right away. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR, +#endif + + /** + * This is the READY substate indicates the device is waiting for the RESET task + * coming to be recovered from certain hardware specific error. + */ + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, +}; + +/** + * enum scic_sds_smp_remote_device_ready_substates - + * + * This is the enumeration of the ready substates for the SMP REMOTE DEVICE. + */ +enum scic_sds_smp_remote_device_ready_substates { + /** + * This is the ready operational substate for the remote device. This is the + * normal operational state for a remote device. + */ + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, + + /** + * This is the suspended state for the remote device. This is the state that + * the device is placed in when a RNC suspend is received by the SCU hardware. + */ + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, +}; + +static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) +{ + struct scic_sds_remote_device *sci_dev; + + sci_dev = container_of(rnc, typeof(*sci_dev), rnc); + + return sci_dev; +} + +typedef enum sci_status (*scic_sds_remote_device_request_handler_t)( + struct scic_sds_remote_device *device, + struct scic_sds_request *request); + +typedef enum sci_status (*scic_sds_remote_device_high_priority_request_complete_handler_t)( + struct scic_sds_remote_device *device, + struct scic_sds_request *request, + void *, + enum sci_io_status); + +typedef enum sci_status (*scic_sds_remote_device_handler_t)( + struct scic_sds_remote_device *sci_dev); + +typedef enum sci_status (*scic_sds_remote_device_suspend_handler_t)( + struct scic_sds_remote_device *sci_dev, + u32 suspend_type); + +typedef enum sci_status (*scic_sds_remote_device_resume_handler_t)( + struct scic_sds_remote_device *sci_dev); + +typedef enum sci_status (*scic_sds_remote_device_frame_handler_t)( + struct scic_sds_remote_device *sci_dev, + u32 frame_index); + +typedef enum sci_status (*scic_sds_remote_device_event_handler_t)( + struct scic_sds_remote_device *sci_dev, + u32 event_code); + +typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( + struct scic_sds_remote_device *sci_dev); + +/** + * struct scic_sds_remote_device_state_handler - This structure conains the + * state handlers that are needed to process requests for the SCU remote + * device objects. + * + * + */ +struct scic_sds_remote_device_state_handler { + /** + * The start_handler specifies the method invoked when a user + * attempts to start a remote device. + */ + scic_sds_remote_device_handler_t start_handler; + + /** + * The stop_handler specifies the method invoked when a user attempts to + * stop a remote device. + */ + scic_sds_remote_device_handler_t stop_handler; + + /** + * The fail_handler specifies the method invoked when a remote device + * failure has occurred. A failure may be due to an inability to + * initialize/configure the device. + */ + scic_sds_remote_device_handler_t fail_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a remote device. + */ + scic_sds_remote_device_handler_t destruct_handler; + + /** + * The reset handler specifies the method invloked when requesting to + * reset a remote device. + */ + scic_sds_remote_device_handler_t reset_handler; + + /** + * The reset complete handler specifies the method invloked when + * reporting that a reset has completed to the remote device. + */ + scic_sds_remote_device_handler_t reset_complete_handler; + + /** + * The start_io_handler specifies the method invoked when a user + * attempts to start an IO request for a remote device. + */ + scic_sds_remote_device_request_handler_t start_io_handler; + + /** + * The complete_io_handler specifies the method invoked when a user + * attempts to complete an IO request for a remote device. + */ + scic_sds_remote_device_request_handler_t complete_io_handler; + + /** + * The continue_io_handler specifies the method invoked when a user + * attempts to continue an IO request for a remote device. + */ + scic_sds_remote_device_request_handler_t continue_io_handler; + + /** + * The start_task_handler specifies the method invoked when a user + * attempts to start a task management request for a remote device. + */ + scic_sds_remote_device_request_handler_t start_task_handler; + + /** + * The complete_task_handler specifies the method invoked when a user + * attempts to complete a task management request for a remote device. + */ + scic_sds_remote_device_request_handler_t complete_task_handler; + + + scic_sds_remote_device_suspend_handler_t suspend_handler; + scic_sds_remote_device_resume_handler_t resume_handler; + scic_sds_remote_device_event_handler_t event_handler; + scic_sds_remote_device_frame_handler_t frame_handler; +}; + +extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[]; +extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[]; +extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[]; + +/** + * scic_sds_remote_device_increment_request_count() - + * + * This macro incrments the request count for this device + */ +#define scic_sds_remote_device_increment_request_count(sci_dev) \ + ((sci_dev)->started_request_count++) + +/** + * scic_sds_remote_device_decrement_request_count() - + * + * This macro decrements the request count for this device. This count will + * never decrment past 0. + */ +#define scic_sds_remote_device_decrement_request_count(sci_dev) \ + ((sci_dev)->started_request_count > 0 ? \ + (sci_dev)->started_request_count-- : 0) + +/** + * scic_sds_remote_device_get_request_count() - + * + * This is a helper macro to return the current device request count. + */ +#define scic_sds_remote_device_get_request_count(sci_dev) \ + ((sci_dev)->started_request_count) + +/** + * scic_sds_remote_device_get_port() - + * + * This macro returns the owning port of this remote device obejct. + */ +#define scic_sds_remote_device_get_port(sci_dev) \ + ((sci_dev)->owning_port) + +/** + * scic_sds_remote_device_get_controller() - + * + * This macro returns the controller object that contains this device object + */ +#define scic_sds_remote_device_get_controller(sci_dev) \ + scic_sds_port_get_controller(scic_sds_remote_device_get_port(sci_dev)) + +/** + * scic_sds_remote_device_set_state_handlers() - + * + * This macro sets the remote device state handlers pointer and is set on entry + * to each device state. + */ +#define scic_sds_remote_device_set_state_handlers(sci_dev, handlers) \ + ((sci_dev)->state_handlers = (handlers)) + +/** + * scic_sds_remote_device_get_port() - + * + * This macro returns the owning port of this device + */ +#define scic_sds_remote_device_get_port(sci_dev) \ + ((sci_dev)->owning_port) + +/** + * scic_sds_remote_device_get_sequence() - + * + * This macro returns the remote device sequence value + */ +#define scic_sds_remote_device_get_sequence(sci_dev) \ + (\ + scic_sds_remote_device_get_controller(sci_dev)-> \ + remote_device_sequence[(sci_dev)->rnc.remote_node_index] \ + ) + +/** + * scic_sds_remote_device_get_controller_peg() - + * + * This macro returns the controllers protocol engine group + */ +#define scic_sds_remote_device_get_controller_peg(sci_dev) \ + (\ + scic_sds_controller_get_protocol_engine_group(\ + scic_sds_port_get_controller(\ + scic_sds_remote_device_get_port(sci_dev) \ + ) \ + ) \ + ) + +/** + * scic_sds_remote_device_get_port_index() - + * + * This macro returns the port index for the devices owning port + */ +#define scic_sds_remote_device_get_port_index(sci_dev) \ + (scic_sds_port_get_index(scic_sds_remote_device_get_port(sci_dev))) + +/** + * scic_sds_remote_device_get_index() - + * + * This macro returns the remote node index for this device object + */ +#define scic_sds_remote_device_get_index(sci_dev) \ + ((sci_dev)->rnc.remote_node_index) + +/** + * scic_sds_remote_device_build_command_context() - + * + * This macro builds a remote device context for the SCU post request operation + */ +#define scic_sds_remote_device_build_command_context(device, command) \ + ((command) \ + | (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \ + | (scic_sds_remote_device_get_port_index((device)) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \ + | (scic_sds_remote_device_get_index((device))) \ + ) + +/** + * scic_sds_remote_device_set_working_request() - + * + * This macro makes the working request assingment for the remote device + * object. To clear the working request use this macro with a NULL request + * object. + */ +#define scic_sds_remote_device_set_working_request(device, request) \ + ((device)->working_request = (request)) + +enum sci_status scic_sds_remote_device_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index); + +enum sci_status scic_sds_remote_device_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code); + +enum sci_status scic_sds_remote_device_start_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *io_request); + +enum sci_status scic_sds_remote_device_complete_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *io_request); + +enum sci_status scic_sds_remote_device_resume( + struct scic_sds_remote_device *sci_dev); + +enum sci_status scic_sds_remote_device_suspend( + struct scic_sds_remote_device *sci_dev, + u32 suspend_type); + +enum sci_status scic_sds_remote_device_start_task( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *io_request); + +void scic_sds_remote_device_post_request( + struct scic_sds_remote_device *sci_dev, + u32 request); + +#if !defined(DISABLE_ATAPI) +bool scic_sds_remote_device_is_atapi( + struct scic_sds_remote_device *sci_dev); +#else /* !defined(DISABLE_ATAPI) */ +#define scic_sds_remote_device_is_atapi(sci_dev) false +#endif /* !defined(DISABLE_ATAPI) */ + +void scic_sds_remote_device_start_request( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req, + enum sci_status status); + +void scic_sds_remote_device_continue_request(void *sci_dev); + +enum sci_status scic_sds_remote_device_default_start_handler( + struct scic_sds_remote_device *sci_dev); + +enum sci_status scic_sds_remote_device_default_fail_handler( + struct scic_sds_remote_device *sci_dev); + +enum sci_status scic_sds_remote_device_default_destruct_handler( + struct scic_sds_remote_device *sci_dev); + +enum sci_status scic_sds_remote_device_default_reset_handler( + struct scic_sds_remote_device *device); + +enum sci_status scic_sds_remote_device_default_reset_complete_handler( + struct scic_sds_remote_device *device); + +enum sci_status scic_sds_remote_device_default_start_request_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request); + +enum sci_status scic_sds_remote_device_default_complete_request_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request); + +enum sci_status scic_sds_remote_device_default_continue_request_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request); + +enum sci_status scic_sds_remote_device_default_suspend_handler( + struct scic_sds_remote_device *sci_dev, + u32 suspend_type); + +enum sci_status scic_sds_remote_device_default_resume_handler( + struct scic_sds_remote_device *sci_dev); + + +enum sci_status scic_sds_remote_device_default_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index); + +enum sci_status scic_sds_remote_device_ready_state_stop_handler( + struct scic_sds_remote_device *device); + +enum sci_status scic_sds_remote_device_ready_state_reset_handler( + struct scic_sds_remote_device *device); + +enum sci_status scic_sds_remote_device_general_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index); + +enum sci_status scic_sds_remote_device_general_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code); + +enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler( + struct scic_sds_remote_device *sci_dev); + + #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c new file mode 100644 index 000000000000..bdf0b5101cfa --- /dev/null +++ b/drivers/scsi/isci/remote_node_context.c @@ -0,0 +1,1226 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sci_base_state_machine.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "remote_device.h" +#include "remote_node_context.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_event_codes.h" +#include "scu_task_context.h" + + +/** + * + * @sci_rnc: The RNC for which the is posted request is being made. + * + * This method will return true if the RNC is not in the initial state. In all + * other states the RNC is considered active and this will return true. The + * destroy request of the state machine drives the RNC back to the initial + * state. If the state machine changes then this routine will also have to be + * changed. bool true if the state machine is not in the initial state false if + * the state machine is in the initial state + */ + +/** + * + * @sci_rnc: The state of the remote node context object to check. + * + * This method will return true if the remote node context is in a READY state + * otherwise it will return false bool true if the remote node context is in + * the ready state. false if the remote node context is not in the ready state. + */ +bool scic_sds_remote_node_context_is_ready( + struct scic_sds_remote_node_context *sci_rnc) +{ + u32 current_state = sci_base_state_machine_get_state(&sci_rnc->state_machine); + + if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { + return true; + } + + return false; +} + +/** + * + * @sci_dev: The remote device to use to construct the RNC buffer. + * @rnc: The buffer into which the remote device data will be copied. + * + * This method will construct the RNC buffer for this remote device object. none + */ +static void scic_sds_remote_node_context_construct_buffer( + struct scic_sds_remote_node_context *sci_rnc) +{ + union scu_remote_node_context *rnc; + struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); + struct scic_sds_controller *scic; + + scic = scic_sds_remote_device_get_controller(sci_dev); + + rnc = scic_sds_controller_get_remote_node_context_buffer( + scic, sci_rnc->remote_node_index); + + memset(rnc, 0, sizeof(union scu_remote_node_context) + * scic_sds_remote_device_node_count(sci_dev)); + + rnc->ssp.remote_node_index = sci_rnc->remote_node_index; + rnc->ssp.remote_node_port_width = sci_dev->device_port_width; + rnc->ssp.logical_port_index = + scic_sds_remote_device_get_port_index(sci_dev); + + rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(sci_dev->device_address.high); + rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(sci_dev->device_address.low); + + rnc->ssp.nexus_loss_timer_enable = true; + rnc->ssp.check_bit = false; + rnc->ssp.is_valid = false; + rnc->ssp.is_remote_node_context = true; + rnc->ssp.function_number = 0; + + rnc->ssp.arbitration_wait_time = 0; + + + if ( + sci_dev->target_protocols.u.bits.attached_sata_device + || sci_dev->target_protocols.u.bits.attached_stp_target + ) { + rnc->ssp.connection_occupancy_timeout = + scic->user_parameters.sds1.stp_max_occupancy_timeout; + rnc->ssp.connection_inactivity_timeout = + scic->user_parameters.sds1.stp_inactivity_timeout; + } else { + rnc->ssp.connection_occupancy_timeout = + scic->user_parameters.sds1.ssp_max_occupancy_timeout; + rnc->ssp.connection_inactivity_timeout = + scic->user_parameters.sds1.ssp_inactivity_timeout; + } + + rnc->ssp.initial_arbitration_wait_time = 0; + + /* Open Address Frame Parameters */ + rnc->ssp.oaf_connection_rate = sci_dev->connection_rate; + rnc->ssp.oaf_features = 0; + rnc->ssp.oaf_source_zone_group = 0; + rnc->ssp.oaf_more_compatibility_features = 0; +} + +/** + * + * @sci_rnc: + * @callback: + * @callback_parameter: + * + * This method will setup the remote node context object so it will transition + * to its ready state. If the remote node context is already setup to + * transition to its final state then this function does nothing. none + */ +static void scic_sds_remote_node_context_setup_to_resume( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { + sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY; + sci_rnc->user_callback = callback; + sci_rnc->user_cookie = callback_parameter; + } +} + +/** + * + * @sci_rnc: + * @callback: + * @callback_parameter: + * + * This method will setup the remote node context object so it will transistion + * to its final state. none + */ +static void scic_sds_remote_node_context_setup_to_destory( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; + sci_rnc->user_callback = callback; + sci_rnc->user_cookie = callback_parameter; +} + +/** + * + * @sci_rnc: + * @callback: + * + * This method will continue to resume a remote node context. This is used in + * the states where a resume is requested while a resume is in progress. + */ +static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { + sci_rnc->user_callback = callback; + sci_rnc->user_cookie = callback_parameter; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_STATE; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_default_destruct_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to stop while " + "in unexpected state %d\n", + __func__, + sci_rnc, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); + + /* + * We have decided that the destruct request on the remote node context can not fail + * since it is either in the initial/destroyed state or is can be destroyed. */ + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_remote_node_context_default_suspend_handler( + struct scic_sds_remote_node_context *sci_rnc, + u32 suspend_type, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to suspend " + "while in wrong state %d\n", + __func__, + sci_rnc, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_remote_node_context_default_resume_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to resume " + "while in wrong state %d\n", + __func__, + sci_rnc, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_remote_node_context_default_start_io_handler( + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) +{ + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to start io " + "0x%p while in wrong state %d\n", + __func__, + sci_rnc, + sci_req, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); + + return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; +} + +static enum sci_status scic_sds_remote_node_context_default_start_task_handler( + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) +{ + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to start " + "task 0x%p while in wrong state %d\n", + __func__, + sci_rnc, + sci_req, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); + + return SCI_FAILURE; +} + +static enum sci_status scic_sds_remote_node_context_default_event_handler( + struct scic_sds_remote_node_context *sci_rnc, + u32 event_code) +{ + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to process " + "event 0x%x while in wrong state %d\n", + __func__, + sci_rnc, + event_code, + sci_base_state_machine_get_state(&sci_rnc->state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +/** + * + * @sci_rnc: The rnc for which the task request is targeted. + * @sci_req: The request which is going to be started. + * + * This method determines if the task request can be started by the SCU + * hardware. When the RNC is in the ready state any task can be started. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_success_start_task_handler( + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) +{ + return SCI_SUCCESS; +} + +/** + * + * @sci_rnc: + * @callback: + * @callback_parameter: + * + * This method handles destruct calls from the various state handlers. The + * remote node context can be requested to destroy from any state. If there was + * a user callback it is always replaced with the request to destroy user + * callback. enum sci_status + */ +static enum sci_status scic_sds_remote_node_context_general_destruct_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + scic_sds_remote_node_context_setup_to_destory( + sci_rnc, callback, callback_parameter + ); + + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE + ); + + return SCI_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + if (sci_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + scic_sds_remote_node_context_setup_to_resume( + sci_rnc, callback, callback_parameter + ); + + scic_sds_remote_node_context_construct_buffer(sci_rnc); + + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE + ); + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_STATE; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( + struct scic_sds_remote_node_context *sci_rnc, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_POST_RNC_COMPLETE: + status = SCI_SUCCESS; + + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE + ); + break; + + default: + status = SCI_FAILURE; + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to " + "process unexpected event 0x%x while in posting " + "state\n", + __func__, + sci_rnc, + event_code); + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + scic_sds_remote_node_context_setup_to_destory( + sci_rnc, callback, callback_parameter + ); + + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler( + struct scic_sds_remote_node_context *sci_rnc, + u32 event_code) +{ + enum sci_status status; + + if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { + status = SCI_SUCCESS; + + if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE + ); + } else { + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE + ); + } + } else { + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + /* + * We really dont care if the hardware is going to suspend + * the device since it's being invalidated anyway */ + dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p was " + "suspeneded by hardware while being " + "invalidated.\n", + __func__, + sci_rnc); + status = SCI_SUCCESS; + break; + + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p " + "requested to process event 0x%x while " + "in state %d.\n", + __func__, + sci_rnc, + event_code, + sci_base_state_machine_get_state( + &sci_rnc->state_machine)); + status = SCI_FAILURE; + break; + } + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + + +static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler( + struct scic_sds_remote_node_context *sci_rnc, + u32 event_code) +{ + enum sci_status status; + + if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) { + status = SCI_SUCCESS; + + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE + ); + } else { + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + /* + * We really dont care if the hardware is going to suspend + * the device since it's being resumed anyway */ + dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p was " + "suspeneded by hardware while being resumed.\n", + __func__, + sci_rnc); + status = SCI_SUCCESS; + break; + + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested " + "to process event 0x%x while in state %d.\n", + __func__, + sci_rnc, + event_code, + sci_base_state_machine_get_state( + &sci_rnc->state_machine)); + status = SCI_FAILURE; + break; + } + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +/** + * + * @sci_rnc: The remote node context object being suspended. + * @callback: The callback when the suspension is complete. + * @callback_parameter: The parameter that is to be passed into the callback. + * + * This method will handle the suspend requests from the ready state. + * SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( + struct scic_sds_remote_node_context *sci_rnc, + u32 suspend_type, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + sci_rnc->user_callback = callback; + sci_rnc->user_cookie = callback_parameter; + sci_rnc->suspension_code = suspend_type; + + if (suspend_type == SCI_SOFTWARE_SUSPENSION) { + scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), + SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); + } + + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE + ); + + return SCI_SUCCESS; +} + +/** + * + * @sci_rnc: The rnc for which the io request is targeted. + * @sci_req: The request which is going to be started. + * + * This method determines if the io request can be started by the SCU hardware. + * When the RNC is in the ready state any io request can be started. enum sci_status + * SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler( + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) +{ + return SCI_SUCCESS; +} + + +static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( + struct scic_sds_remote_node_context *sci_rnc, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TL_RNC_SUSPEND_TX: + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE + ); + + sci_rnc->suspension_code = scu_get_event_specifier(event_code); + status = SCI_SUCCESS; + break; + + case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE + ); + + sci_rnc->suspension_code = scu_get_event_specifier(event_code); + status = SCI_SUCCESS; + break; + + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to " + "process event 0x%x while in state %d.\n", + __func__, + sci_rnc, + event_code, + sci_base_state_machine_get_state( + &sci_rnc->state_machine)); + + status = SCI_FAILURE; + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + enum sci_status status; + struct smp_discover_response_protocols protocols; + + scic_sds_remote_node_context_setup_to_resume( + sci_rnc, callback, callback_parameter + ); + + /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ + + scic_remote_device_get_protocols(rnc_to_dev(sci_rnc), &protocols); + + if ( + (protocols.u.bits.attached_ssp_target == 1) + || (protocols.u.bits.attached_smp_target == 1) + ) { + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE + ); + + status = SCI_SUCCESS; + } else if (protocols.u.bits.attached_stp_target == 1) { + if (rnc_to_dev(sci_rnc)->is_direct_attached) { + /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE + ); + } else { + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE + ); + } + + status = SCI_SUCCESS; + } else { + status = SCI_FAILURE; + } + + return status; +} + +/** + * + * @sci_rnc: The remote node context which is to receive the task request. + * @sci_req: The task request to be transmitted to to the remote target + * device. + * + * This method will report a success or failure attempt to start a new task + * request to the hardware. Since all task requests are sent on the high + * priority queue they can be sent when the RCN is in a TX suspend state. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler( + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) +{ + scic_sds_remote_node_context_resume(sci_rnc, NULL, NULL); + + return SCI_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ + +static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + scic_sds_remote_node_context_setup_to_resume( + sci_rnc, callback, callback_parameter + ); + + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE + ); + + return SCI_FAILURE_INVALID_STATE; +} + +/* --------------------------------------------------------------------------- */ + +/** + * + * + * + */ +static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter) +{ + scic_sds_remote_node_context_setup_to_resume( + sci_rnc, callback, callback_parameter + ); + + return SCI_SUCCESS; +} + +/** + * + * @sci_rnc: The remote node context which is to receive the task request. + * @sci_req: The task request to be transmitted to to the remote target + * device. + * + * This method will report a success or failure attempt to start a new task + * request to the hardware. Since all task requests are sent on the high + * priority queue they can be sent when the RCN is in a TX suspend state. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler( + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) +{ + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler( + struct scic_sds_remote_node_context *sci_rnc, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TL_RNC_SUSPEND_TX: + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE + ); + + sci_rnc->suspension_code = scu_get_event_specifier(event_code); + status = SCI_SUCCESS; + break; + + case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: + sci_base_state_machine_change_state( + &sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE + ); + + sci_rnc->suspension_code = scu_get_event_specifier(event_code); + status = SCI_SUCCESS; + break; + + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p requested to " + "process event 0x%x while in state %d.\n", + __func__, + sci_rnc, + event_code, + sci_base_state_machine_get_state( + &sci_rnc->state_machine)); + + status = SCI_FAILURE; + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static struct scic_sds_remote_node_context_handlers +scic_sds_remote_node_context_state_handler_table[ + SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] = +{ + /* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */ + { + scic_sds_remote_node_context_default_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_initial_state_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_default_start_task_handler, + scic_sds_remote_node_context_default_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_continue_to_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_default_start_task_handler, + scic_sds_remote_node_context_posting_state_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */ + { + scic_sds_remote_node_context_invalidating_state_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_continue_to_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_default_start_task_handler, + scic_sds_remote_node_context_invalidating_state_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_continue_to_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_success_start_task_handler, + scic_sds_remote_node_context_resuming_state_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_ready_state_suspend_handler, + scic_sds_remote_node_context_default_resume_handler, + scic_sds_remote_node_context_ready_state_start_io_handler, + scic_sds_remote_node_context_success_start_task_handler, + scic_sds_remote_node_context_ready_state_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_tx_suspended_state_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_suspended_start_task_handler, + scic_sds_remote_node_context_default_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_suspended_start_task_handler, + scic_sds_remote_node_context_default_event_handler + }, + /* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */ + { + scic_sds_remote_node_context_general_destruct_handler, + scic_sds_remote_node_context_default_suspend_handler, + scic_sds_remote_node_context_await_suspension_state_resume_handler, + scic_sds_remote_node_context_default_start_io_handler, + scic_sds_remote_node_context_await_suspension_state_start_task_handler, + scic_sds_remote_node_context_await_suspension_state_event_handler + } +}; + +/* + * ***************************************************************************** + * * REMOTE NODE CONTEXT PRIVATE METHODS + * ***************************************************************************** */ + +/** + * + * + * This method just calls the user callback function and then resets the + * callback. + */ +static void scic_sds_remote_node_context_notify_user( + struct scic_sds_remote_node_context *rnc) +{ + if (rnc->user_callback != NULL) { + (*rnc->user_callback)(rnc->user_cookie); + + rnc->user_callback = NULL; + rnc->user_cookie = NULL; + } +} + +/** + * + * + * This method will continue the remote node context state machine by + * requesting to resume the remote node context state machine from its current + * state. + */ +static void scic_sds_remote_node_context_continue_state_transitions( + struct scic_sds_remote_node_context *rnc) +{ + if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { + rnc->state_handlers->resume_handler( + rnc, rnc->user_callback, rnc->user_cookie + ); + } +} + +/** + * + * @sci_rnc: The remote node context object that is to be validated. + * + * This method will mark the rnc buffer as being valid and post the request to + * the hardware. none + */ +static void scic_sds_remote_node_context_validate_context_buffer( + struct scic_sds_remote_node_context *sci_rnc) +{ + struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); + union scu_remote_node_context *rnc_buffer; + + rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( + scic_sds_remote_device_get_controller(sci_dev), + sci_rnc->remote_node_index + ); + + rnc_buffer->ssp.is_valid = true; + + if (!sci_dev->is_direct_attached && + sci_dev->target_protocols.u.bits.attached_stp_target) { + scic_sds_remote_device_post_request(sci_dev, + SCU_CONTEXT_COMMAND_POST_RNC_96); + } else { + scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_32); + + if (sci_dev->is_direct_attached) { + scic_sds_port_setup_transports(sci_dev->owning_port, + sci_rnc->remote_node_index); + } + } +} + +/** + * + * @sci_rnc: The remote node context object that is to be invalidated. + * + * This method will update the RNC buffer and post the invalidate request. none + */ +static void scic_sds_remote_node_context_invalidate_context_buffer( + struct scic_sds_remote_node_context *sci_rnc) +{ + union scu_remote_node_context *rnc_buffer; + + rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( + scic_sds_remote_device_get_controller(rnc_to_dev(sci_rnc)), + sci_rnc->remote_node_index); + + rnc_buffer->ssp.is_valid = false; + + scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), + SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE); +} + +/* + * ***************************************************************************** + * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS + * ***************************************************************************** */ + +/** + * + * + * + */ +static void scic_sds_remote_node_context_initial_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE + ); + + /* + * Check to see if we have gotten back to the initial state because someone + * requested to destroy the remote node context object. */ + if ( + rnc->state_machine.previous_state_id + == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE + ) { + rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; + + scic_sds_remote_node_context_notify_user(rnc); + } +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_posting_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *sci_rnc; + + sci_rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + sci_rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE + ); + + scic_sds_remote_node_context_validate_context_buffer(sci_rnc); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_invalidating_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE + ); + + scic_sds_remote_node_context_invalidate_context_buffer(rnc); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_resuming_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + struct smp_discover_response_protocols protocols; + struct scic_sds_remote_device *sci_dev; + + rnc = (struct scic_sds_remote_node_context *)object; + sci_dev = rnc_to_dev(rnc); + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE + ); + + /* + * For direct attached SATA devices we need to clear the TLCR + * NCQ to TCi tag mapping on the phy and in cases where we + * resume because of a target reset we also need to update + * the STPTLDARNI register with the RNi of the device + */ + scic_remote_device_get_protocols(sci_dev, &protocols); + + if (protocols.u.bits.attached_stp_target == 1 && + sci_dev->is_direct_attached) { + scic_sds_port_setup_transports(sci_dev->owning_port, + rnc->remote_node_index); + } + + scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_ready_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE + ); + + rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; + + if (rnc->user_callback != NULL) { + scic_sds_remote_node_context_notify_user(rnc); + } +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_tx_suspended_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE + ); + + scic_sds_remote_node_context_continue_state_transitions(rnc); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE + ); + + scic_sds_remote_node_context_continue_state_transitions(rnc); +} + +/** + * + * + * + */ +static void scic_sds_remote_node_context_await_suspension_state_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_node_context *rnc; + + rnc = (struct scic_sds_remote_node_context *)object; + + SET_STATE_HANDLER( + rnc, + scic_sds_remote_node_context_state_handler_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE + ); +} + +/* --------------------------------------------------------------------------- */ + +static const struct sci_base_state scic_sds_remote_node_context_state_table[] = { + [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { + .enter_state = scic_sds_remote_node_context_initial_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { + .enter_state = scic_sds_remote_node_context_posting_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { + .enter_state = scic_sds_remote_node_context_invalidating_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { + .enter_state = scic_sds_remote_node_context_resuming_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { + .enter_state = scic_sds_remote_node_context_ready_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { + .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { + .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter, + }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { + .enter_state = scic_sds_remote_node_context_await_suspension_state_enter, + }, +}; + +void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, + u16 remote_node_index) +{ + memset(rnc, 0, sizeof(struct scic_sds_remote_node_context)); + + rnc->remote_node_index = remote_node_index; + rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; + + sci_base_state_machine_construct( + &rnc->state_machine, + &rnc->parent, + scic_sds_remote_node_context_state_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE + ); + + sci_base_state_machine_start(&rnc->state_machine); +} diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h new file mode 100644 index 000000000000..b3f2546090dd --- /dev/null +++ b/drivers/scsi/isci/remote_node_context.h @@ -0,0 +1,301 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ +#define _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ + +/** + * This file contains the structures, constants, and prototypes associated with + * the remote node context in the silicon. It exists to model and manage + * the remote node context in the silicon. + * + * + */ + +#include "sci_base_state.h" +#include "sci_base_state_machine.h" + +/** + * + * + * This constant represents an invalid remote device id, it is used to program + * the STPDARNI register so the driver knows when it has received a SIGNATURE + * FIS from the SCU. + */ +#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF + +#define SCU_HARDWARE_SUSPENSION (0) +#define SCI_SOFTWARE_SUSPENSION (1) + +struct scic_sds_request; +struct scic_sds_remote_device; +struct scic_sds_remote_node_context; + +typedef void (*scics_sds_remote_node_context_callback)(void *); + +typedef enum sci_status (*scic_sds_remote_node_context_operation)( + struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter + ); + +typedef enum sci_status (*scic_sds_remote_node_context_suspend_operation)( + struct scic_sds_remote_node_context *sci_rnc, + u32 suspension_type, + scics_sds_remote_node_context_callback callback, + void *callback_parameter + ); + +typedef enum sci_status (*scic_sds_remote_node_context_io_request)( + struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req + ); + +typedef enum sci_status (*scic_sds_remote_node_context_event_handler)( + struct scic_sds_remote_node_context *sci_rnc, + u32 event_code + ); + +struct scic_sds_remote_node_context_handlers { + /** + * This handle is invoked to stop the RNC. The callback is invoked when after + * the hardware notification that the RNC has been invalidated. + */ + scic_sds_remote_node_context_operation destruct_handler; + + /** + * This handler is invoked when there is a request to suspend the RNC. The + * callback is invoked after the hardware notification that the remote node is + * suspended. + */ + scic_sds_remote_node_context_suspend_operation suspend_handler; + + /** + * This handler is invoked when there is a request to resume the RNC. The + * callback is invoked when after the RNC has reached the ready state. + */ + scic_sds_remote_node_context_operation resume_handler; + + /** + * This handler is invoked when there is a request to start an io request + * operation. + */ + scic_sds_remote_node_context_io_request start_io_handler; + + /** + * This handler is invoked when there is a request to start a task request + * operation. + */ + scic_sds_remote_node_context_io_request start_task_handler; + + /** + * This handler is invoked where there is an RNC event that must be processed. + */ + scic_sds_remote_node_context_event_handler event_handler; + +}; + +/** + * This is the enumeration of the remote node context states. + */ +enum scis_sds_remote_node_context_states { + /** + * This state is the initial state for a remote node context. On a resume + * request the remote node context will transition to the posting state. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE, + + /** + * This is a transition state that posts the RNi to the hardware. Once the RNC + * is posted the remote node context will be made ready. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE, + + /** + * This is a transition state that will post an RNC invalidate to the + * hardware. Once the invalidate is complete the remote node context will + * transition to the posting state. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE, + + /** + * This is a transition state that will post an RNC resume to the hardare. + * Once the event notification of resume complete is received the remote node + * context will transition to the ready state. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE, + + /** + * This is the state that the remote node context must be in to accept io + * request operations. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE, + + /** + * This is the state that the remote node context transitions to when it gets + * a TX suspend notification from the hardware. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE, + + /** + * This is the state that the remote node context transitions to when it gets + * a TX RX suspend notification from the hardware. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE, + + /** + * This state is a wait state for the remote node context that waits for a + * suspend notification from the hardware. This state is entered when either + * there is a request to supend the remote node context or when there is a TC + * completion where the remote node will be suspended by the hardware. + */ + SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE, + + SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES + +}; + +/** + * + * + * This enumeration is used to define the end destination state for the remote + * node context. + */ +enum scic_sds_remote_node_context_destination_state { + SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED, + SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY, + SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL +}; + +/** + * struct scic_sds_remote_node_context - This structure contains the data + * associated with the remote node context object. The remote node context + * (RNC) object models the the remote device information necessary to manage + * the silicon RNC. + */ +struct scic_sds_remote_node_context { + /* + * parent object + */ + struct sci_base_object parent; + + /** + * This field indicates the remote node index (RNI) associated with + * this RNC. + */ + u16 remote_node_index; + + /** + * This field is the recored suspension code or the reason for the remote node + * context suspension. + */ + u32 suspension_code; + + /** + * This field is true if the remote node context is resuming from its current + * state. This can cause an automatic resume on receiving a suspension + * notification. + */ + enum scic_sds_remote_node_context_destination_state destination_state; + + /** + * This field contains the callback function that the user requested to be + * called when the requested state transition is complete. + */ + scics_sds_remote_node_context_callback user_callback; + + /** + * This field contains the parameter that is called when the user requested + * state transition is completed. + */ + void *user_cookie; + + /** + * This field contains the data for the object's state machine. + */ + struct sci_base_state_machine state_machine; + + struct scic_sds_remote_node_context_handlers *state_handlers; +}; + +void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, + u16 remote_node_index); + + +bool scic_sds_remote_node_context_is_ready( + struct scic_sds_remote_node_context *sci_rnc); + +#define scic_sds_remote_node_context_get_remote_node_index(rcn) \ + ((rnc)->remote_node_index) + +#define scic_sds_remote_node_context_event_handler(rnc, event_code) \ + ((rnc)->state_handlers->event_handler(rnc, event_code)) + +#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \ + ((rnc)->state_handlers->resume_handler(rnc, callback, parameter)) + +#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \ + ((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter)) + +#define scic_sds_remote_node_context_destruct(rnc, callback, parameter) \ + ((rnc)->state_handlers->destruct_handler(rnc, callback, parameter)) + +#define scic_sds_remote_node_context_start_io(rnc, request) \ + ((rnc)->state_handlers->start_io_handler(rnc, request)) + +#define scic_sds_remote_node_context_start_task(rnc, task) \ + ((rnc)->state_handlers->start_task_handler(rnc, task)) + +#endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ diff --git a/drivers/scsi/isci/remote_node_table.c b/drivers/scsi/isci/remote_node_table.c new file mode 100644 index 000000000000..8886146d9db2 --- /dev/null +++ b/drivers/scsi/isci/remote_node_table.c @@ -0,0 +1,600 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the implementation of the SCIC_SDS_REMOTE_NODE_TABLE + * public, protected, and private methods. + * + * + */ +#include "sci_util.h" +#include "sci_environment.h" +#include "remote_node_table.h" +#include "remote_node_context.h" + +/** + * + * @remote_node_table: This is the remote node index table from which the + * selection will be made. + * @group_table_index: This is the index to the group table from which to + * search for an available selection. + * + * This routine will find the bit position in absolute bit terms of the next 32 + * + bit position. If there are available bits in the first u32 then it is + * just bit position. u32 This is the absolute bit position for an available + * group. + */ +static u32 scic_sds_remote_node_table_get_group_index( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index) +{ + u32 dword_index; + u32 *group_table; + u32 bit_index; + + group_table = remote_node_table->remote_node_groups[group_table_index]; + + for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++) { + if (group_table[dword_index] != 0) { + for (bit_index = 0; bit_index < 32; bit_index++) { + if ((group_table[dword_index] & (1 << bit_index)) != 0) { + return (dword_index * 32) + bit_index; + } + } + } + } + + return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX; +} + +/** + * + * @out]: remote_node_table This the remote node table in which to clear the + * selector. + * @set_index: This is the remote node selector in which the change will be + * made. + * @group_index: This is the bit index in the table to be modified. + * + * This method will clear the group index entry in the specified group index + * table. none + */ +static void scic_sds_remote_node_table_clear_group_index( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index, + u32 group_index) +{ + u32 dword_index; + u32 bit_index; + u32 *group_table; + + BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT); + BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32)); + + dword_index = group_index / 32; + bit_index = group_index % 32; + group_table = remote_node_table->remote_node_groups[group_table_index]; + + group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index); +} + +/** + * + * @out]: remote_node_table This the remote node table in which to set the + * selector. + * @group_table_index: This is the remote node selector in which the change + * will be made. + * @group_index: This is the bit position in the table to be modified. + * + * This method will set the group index bit entry in the specified gropu index + * table. none + */ +static void scic_sds_remote_node_table_set_group_index( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index, + u32 group_index) +{ + u32 dword_index; + u32 bit_index; + u32 *group_table; + + BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT); + BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32)); + + dword_index = group_index / 32; + bit_index = group_index % 32; + group_table = remote_node_table->remote_node_groups[group_table_index]; + + group_table[dword_index] = group_table[dword_index] | (1 << bit_index); +} + +/** + * + * @out]: remote_node_table This is the remote node table in which to modify + * the remote node availability. + * @remote_node_index: This is the remote node index that is being returned to + * the table. + * + * This method will set the remote to available in the remote node allocation + * table. none + */ +static void scic_sds_remote_node_table_set_node_index( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 slot_normalized; + u32 slot_position; + + BUG_ON( + (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) + <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT) + ); + + dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD; + dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD; + slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32); + slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT; + + remote_node_table->available_remote_nodes[dword_location] |= + 1 << (slot_normalized + slot_position); +} + +/** + * + * @out]: remote_node_table This is the remote node table from which to clear + * the available remote node bit. + * @remote_node_index: This is the remote node index which is to be cleared + * from the table. + * + * This method clears the remote node index from the table of available remote + * nodes. none + */ +static void scic_sds_remote_node_table_clear_node_index( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 slot_position; + u32 slot_normalized; + + BUG_ON( + (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) + <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT) + ); + + dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD; + dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD; + slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32); + slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT; + + remote_node_table->available_remote_nodes[dword_location] &= + ~(1 << (slot_normalized + slot_position)); +} + +/** + * + * @out]: remote_node_table The remote node table from which the slot will be + * cleared. + * @group_index: The index for the slot that is to be cleared. + * + * This method clears the entire table slot at the specified slot index. none + */ +static void scic_sds_remote_node_table_clear_group( + struct scic_remote_node_table *remote_node_table, + u32 group_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 dword_value; + + BUG_ON( + (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) + <= (group_index / SCU_STP_REMOTE_NODE_COUNT) + ); + + dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + + dword_value = remote_node_table->available_remote_nodes[dword_location]; + dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); + remote_node_table->available_remote_nodes[dword_location] = dword_value; +} + +/** + * + * @remote_node_table: + * + * THis method sets an entire remote node group in the remote node table. + */ +static void scic_sds_remote_node_table_set_group( + struct scic_remote_node_table *remote_node_table, + u32 group_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 dword_value; + + BUG_ON( + (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) + <= (group_index / SCU_STP_REMOTE_NODE_COUNT) + ); + + dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + + dword_value = remote_node_table->available_remote_nodes[dword_location]; + dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); + remote_node_table->available_remote_nodes[dword_location] = dword_value; +} + +/** + * + * @remote_node_table: This is the remote node table that for which the group + * value is to be returned. + * @group_index: This is the group index to use to find the group value. + * + * This method will return the group value for the specified group index. The + * bit values at the specified remote node group index. + */ +static u8 scic_sds_remote_node_table_get_group_value( + struct scic_remote_node_table *remote_node_table, + u32 group_index) +{ + u32 dword_location; + u32 dword_remainder; + u32 dword_value; + + dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; + + dword_value = remote_node_table->available_remote_nodes[dword_location]; + dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); + dword_value = dword_value >> (dword_remainder * 4); + + return (u8)dword_value; +} + +/** + * + * @out]: remote_node_table The remote that which is to be initialized. + * @remote_node_entries: The number of entries to put in the table. + * + * This method will initialize the remote node table for use. none + */ +void scic_sds_remote_node_table_initialize( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_entries) +{ + u32 index; + + /* + * Initialize the raw data we could improve the speed by only initializing + * those entries that we are actually going to be used */ + memset( + remote_node_table->available_remote_nodes, + 0x00, + sizeof(remote_node_table->available_remote_nodes) + ); + + memset( + remote_node_table->remote_node_groups, + 0x00, + sizeof(remote_node_table->remote_node_groups) + ); + + /* Initialize the available remote node sets */ + remote_node_table->available_nodes_array_size = (u16) + (remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD) + + ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0); + + + /* Initialize each full DWORD to a FULL SET of remote nodes */ + for (index = 0; index < remote_node_entries; index++) { + scic_sds_remote_node_table_set_node_index(remote_node_table, index); + } + + remote_node_table->group_array_size = (u16) + (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32)) + + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0); + + for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++) { + /* + * These are all guaranteed to be full slot values so fill them in the + * available sets of 3 remote nodes */ + scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index); + } + + /* Now fill in any remainders that we may find */ + if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) { + scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index); + } else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) { + scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index); + } +} + +/** + * + * @out]: remote_node_table The remote node table from which to allocate a + * remote node. + * @table_index: The group index that is to be used for the search. + * + * This method will allocate a single RNi from the remote node table. The + * table index will determine from which remote node group table to search. + * This search may fail and another group node table can be specified. The + * function is designed to allow a serach of the available single remote node + * group up to the triple remote node group. If an entry is found in the + * specified table the remote node is removed and the remote node groups are + * updated. The RNi value or an invalid remote node context if an RNi can not + * be found. + */ +static u16 scic_sds_remote_node_table_allocate_single_remote_node( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index) +{ + u8 index; + u8 group_value; + u32 group_index; + u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + + group_index = scic_sds_remote_node_table_get_group_index( + remote_node_table, group_table_index); + + /* We could not find an available slot in the table selector 0 */ + if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { + group_value = scic_sds_remote_node_table_get_group_value( + remote_node_table, group_index); + + for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) { + if (((1 << index) & group_value) != 0) { + /* We have selected a bit now clear it */ + remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT + + index); + + scic_sds_remote_node_table_clear_group_index( + remote_node_table, group_table_index, group_index + ); + + scic_sds_remote_node_table_clear_node_index( + remote_node_table, remote_node_index + ); + + if (group_table_index > 0) { + scic_sds_remote_node_table_set_group_index( + remote_node_table, group_table_index - 1, group_index + ); + } + + break; + } + } + } + + return remote_node_index; +} + +/** + * + * @remote_node_table: This is the remote node table from which to allocate the + * remote node entries. + * @group_table_index: THis is the group table index which must equal two (2) + * for this operation. + * + * This method will allocate three consecutive remote node context entries. If + * there are no remaining triple entries the function will return a failure. + * The remote node index that represents three consecutive remote node entries + * or an invalid remote node context if none can be found. + */ +static u16 scic_sds_remote_node_table_allocate_triple_remote_node( + struct scic_remote_node_table *remote_node_table, + u32 group_table_index) +{ + u32 group_index; + u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + + group_index = scic_sds_remote_node_table_get_group_index( + remote_node_table, group_table_index); + + if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { + remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT; + + scic_sds_remote_node_table_clear_group_index( + remote_node_table, group_table_index, group_index + ); + + scic_sds_remote_node_table_clear_group( + remote_node_table, group_index + ); + } + + return remote_node_index; +} + +/** + * + * @remote_node_table: This is the remote node table from which the remote node + * allocation is to take place. + * @remote_node_count: This is ther remote node count which is one of + * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). + * + * This method will allocate a remote node that mataches the remote node count + * specified by the caller. Valid values for remote node count is + * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). u16 This is + * the remote node index that is returned or an invalid remote node context. + */ +u16 scic_sds_remote_node_table_allocate_remote_node( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_count) +{ + u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + + if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { + remote_node_index = + scic_sds_remote_node_table_allocate_single_remote_node( + remote_node_table, 0); + + if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + remote_node_index = + scic_sds_remote_node_table_allocate_single_remote_node( + remote_node_table, 1); + } + + if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + remote_node_index = + scic_sds_remote_node_table_allocate_single_remote_node( + remote_node_table, 2); + } + } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { + remote_node_index = + scic_sds_remote_node_table_allocate_triple_remote_node( + remote_node_table, 2); + } + + return remote_node_index; +} + +/** + * + * @remote_node_table: + * + * This method will free a single remote node index back to the remote node + * table. This routine will update the remote node groups + */ +static void scic_sds_remote_node_table_release_single_remote_node( + struct scic_remote_node_table *remote_node_table, + u16 remote_node_index) +{ + u32 group_index; + u8 group_value; + + group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; + + group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index); + + /* + * Assert that we are not trying to add an entry to a slot that is already + * full. */ + BUG_ON(group_value == SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE); + + if (group_value == 0x00) { + /* + * There are no entries in this slot so it must be added to the single + * slot table. */ + scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index); + } else if ((group_value & (group_value - 1)) == 0) { + /* + * There is only one entry in this slot so it must be moved from the + * single slot table to the dual slot table */ + scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index); + scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index); + } else { + /* + * There are two entries in the slot so it must be moved from the dual + * slot table to the tripple slot table. */ + scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index); + scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index); + } + + scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index); +} + +/** + * + * @remote_node_table: This is the remote node table to which the remote node + * index is to be freed. + * + * This method will release a group of three consecutive remote nodes back to + * the free remote nodes. + */ +static void scic_sds_remote_node_table_release_triple_remote_node( + struct scic_remote_node_table *remote_node_table, + u16 remote_node_index) +{ + u32 group_index; + + group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; + + scic_sds_remote_node_table_set_group_index( + remote_node_table, 2, group_index + ); + + scic_sds_remote_node_table_set_group(remote_node_table, group_index); +} + +/** + * + * @remote_node_table: The remote node table to which the remote node index is + * to be freed. + * @remote_node_count: This is the count of consecutive remote nodes that are + * to be freed. + * + * This method will release the remote node index back into the remote node + * table free pool. + */ +void scic_sds_remote_node_table_release_remote_node_index( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_count, + u16 remote_node_index) +{ + if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { + scic_sds_remote_node_table_release_single_remote_node( + remote_node_table, remote_node_index); + } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { + scic_sds_remote_node_table_release_triple_remote_node( + remote_node_table, remote_node_index); + } +} + diff --git a/drivers/scsi/isci/remote_node_table.h b/drivers/scsi/isci/remote_node_table.h new file mode 100644 index 000000000000..9c02a6ccb2fe --- /dev/null +++ b/drivers/scsi/isci/remote_node_table.h @@ -0,0 +1,195 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_ +#define _SCIC_SDS_REMOTE_NODE_TABLE_H_ + +/** + * This file contains the structures, constants and prototypes used for the + * remote node table. + * + * + */ + +#include "sci_controller_constants.h" + +/** + * + * + * Remote node sets are sets of remote node index in the remtoe node table The + * SCU hardware requires that STP remote node entries take three consecutive + * remote node index so the table is arranged in sets of three. The bits are + * used as 0111 0111 to make a byte and the bits define the set of three remote + * nodes to use as a sequence. + */ +#define SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE 2 + +/** + * + * + * Since the remote node table is organized as DWORDS take the remote node sets + * in bytes and represent them in DWORDs. The lowest ordered bits are the ones + * used in case full DWORD is not being used. i.e. 0000 0000 0000 0000 0111 + * 0111 0111 0111 // if only a single WORD is in use in the DWORD. + */ +#define SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD \ + (sizeof(u32) * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE) +/** + * + * + * This is a count of the numeber of remote nodes that can be represented in a + * byte + */ +#define SCIC_SDS_REMOTE_NODES_PER_BYTE \ + (SCU_STP_REMOTE_NODE_COUNT * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE) + +/** + * + * + * This is a count of the number of remote nodes that can be represented in a + * DWROD + */ +#define SCIC_SDS_REMOTE_NODES_PER_DWORD \ + (sizeof(u32) * SCIC_SDS_REMOTE_NODES_PER_BYTE) + +/** + * + * + * This is the number of bits in a remote node group + */ +#define SCIC_SDS_REMOTE_NODES_BITS_PER_GROUP 4 + +#define SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX (0xFFFFFFFF) +#define SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE (0x07) +#define SCIC_SDS_REMOTE_NODE_TABLE_EMPTY_SLOT_VALUE (0x00) + +/** + * + * + * Expander attached sata remote node count + */ +#define SCU_STP_REMOTE_NODE_COUNT 3 + +/** + * + * + * Expander or direct attached ssp remote node count + */ +#define SCU_SSP_REMOTE_NODE_COUNT 1 + +/** + * + * + * Direct attached STP remote node count + */ +#define SCU_SATA_REMOTE_NODE_COUNT 1 + +/** + * struct scic_remote_node_table - + * + * + */ +struct scic_remote_node_table { + /** + * This field contains the array size in dwords + */ + u16 available_nodes_array_size; + + /** + * This field contains the array size of the + */ + u16 group_array_size; + + /** + * This field is the array of available remote node entries in bits. + * Because of the way STP remote node data is allocated on the SCU hardware + * the remote nodes must occupy three consecutive remote node context + * entries. For ease of allocation and de-allocation we have broken the + * sets of three into a single nibble. When the STP RNi is allocated all + * of the bits in the nibble are cleared. This math results in a table size + * of MAX_REMOTE_NODES / CONSECUTIVE RNi ENTRIES for STP / 2 entries per byte. + */ + u32 available_remote_nodes[ + (SCI_MAX_REMOTE_DEVICES / SCIC_SDS_REMOTE_NODES_PER_DWORD) + + ((SCI_MAX_REMOTE_DEVICES % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0)]; + + /** + * This field is the nibble selector for the above table. There are three + * possible selectors each for fast lookup when trying to find one, two or + * three remote node entries. + */ + u32 remote_node_groups[ + SCU_STP_REMOTE_NODE_COUNT][ + (SCI_MAX_REMOTE_DEVICES / (32 * SCU_STP_REMOTE_NODE_COUNT)) + + ((SCI_MAX_REMOTE_DEVICES % (32 * SCU_STP_REMOTE_NODE_COUNT)) != 0)]; + +}; + +/* --------------------------------------------------------------------------- */ + +void scic_sds_remote_node_table_initialize( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_entries); + +u16 scic_sds_remote_node_table_allocate_remote_node( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_count); + +void scic_sds_remote_node_table_release_remote_node_index( + struct scic_remote_node_table *remote_node_table, + u32 remote_node_count, + u16 remote_node_index); + +#endif /* _SCIC_SDS_REMOTE_NODE_TABLE_H_ */ diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 8d2125b520ea..ff5c05a19543 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -54,7 +54,6 @@ */ #include "isci.h" -#include "scic_remote_device.h" #include "scic_io_request.h" #include "scic_task_request.h" #include "scic_port.h" diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index c941d9090b8d..53ce0c281bee 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -54,8 +54,7 @@ */ #include "isci.h" -#include "scic_remote_device.h" -#include "scic_sds_remote_device.h" +#include "remote_device.h" #include "scic_io_request.h" #include "scic_task_request.h" #include "task.h" diff --git a/drivers/scsi/isci/scu_remote_node_context.h b/drivers/scsi/isci/scu_remote_node_context.h new file mode 100644 index 000000000000..33745adc826b --- /dev/null +++ b/drivers/scsi/isci/scu_remote_node_context.h @@ -0,0 +1,229 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCU_REMOTE_NODE_CONTEXT_HEADER__ +#define __SCU_REMOTE_NODE_CONTEXT_HEADER__ + +/** + * This file contains the structures and constatns used by the SCU hardware to + * describe a remote node context. + * + * + */ + +/** + * struct ssp_remote_node_context - This structure contains the SCU hardware + * definition for an SSP remote node. + * + * + */ +struct ssp_remote_node_context { + /* WORD 0 */ + + /** + * This field is the remote node index assigned for this remote node. All + * remote nodes must have a unique remote node index. The value of the remote + * node index can not exceed the maximum number of remote nodes reported in + * the SCU device context capacity register. + */ + u32 remote_node_index:12; + u32 reserved0_1:4; + + /** + * This field tells the SCU hardware how many simultaneous connections that + * this remote node will support. + */ + u32 remote_node_port_width:4; + + /** + * This field tells the SCU hardware which logical port to associate with this + * remote node. + */ + u32 logical_port_index:3; + u32 reserved0_2:5; + + /** + * This field will enable the I_T nexus loss timer for this remote node. + */ + u32 nexus_loss_timer_enable:1; + + /** + * This field is the for driver debug only and is not used. + */ + u32 check_bit:1; + + /** + * This field must be set to true when the hardware DMAs the remote node + * context to the hardware SRAM. When the remote node is being invalidated + * this field must be set to false. + */ + u32 is_valid:1; + + /** + * This field must be set to true. + */ + u32 is_remote_node_context:1; + + /* WORD 1 - 2 */ + + /** + * This is the low word of the remote device SAS Address + */ + u32 remote_sas_address_lo; + + /** + * This field is the high word of the remote device SAS Address + */ + u32 remote_sas_address_hi; + + /* WORD 3 */ + /** + * This field reprensets the function number assigned to this remote device. + * This value must match the virtual function number that is being used to + * communicate to the device. + */ + u32 function_number:8; + u32 reserved3_1:8; + + /** + * This field provides the driver a way to cheat on the arbitration wait time + * for this remote node. + */ + u32 arbitration_wait_time:16; + + /* WORD 4 */ + /** + * This field tells the SCU hardware how long this device may occupy the + * connection before it must be closed. + */ + u32 connection_occupancy_timeout:16; + + /** + * This field tells the SCU hardware how long to maintain a connection when + * there are no frames being transmitted on the link. + */ + u32 connection_inactivity_timeout:16; + + /* WORD 5 */ + /** + * This field allows the driver to cheat on the arbitration wait time for this + * remote node. + */ + u32 initial_arbitration_wait_time:16; + + /** + * This field is tells the hardware what to program for the connection rate in + * the open address frame. See the SAS spec for valid values. + */ + u32 oaf_connection_rate:4; + + /** + * This field tells the SCU hardware what to program for the features in the + * open address frame. See the SAS spec for valid values. + */ + u32 oaf_features:4; + + /** + * This field tells the SCU hardware what to use for the source zone group in + * the open address frame. See the SAS spec for more details on zoning. + */ + u32 oaf_source_zone_group:8; + + /* WORD 6 */ + /** + * This field tells the SCU hardware what to use as the more capibilities in + * the open address frame. See the SAS Spec for details. + */ + u32 oaf_more_compatibility_features; + + /* WORD 7 */ + u32 reserved7; + +}; + +/** + * struct stp_remote_node_context - This structure contains the SCU hardware + * definition for a STP remote node. + * + * STP Targets are not yet supported so this definition is a placeholder until + * we do support them. + */ +struct stp_remote_node_context { + /** + * Placeholder data for the STP remote node. + */ + u32 data[8]; + +}; + +/** + * This union combines the SAS and SATA remote node definitions. + * + * union scu_remote_node_context + */ +union scu_remote_node_context { + /** + * SSP Remote Node + */ + struct ssp_remote_node_context ssp; + + /** + * STP Remote Node + */ + struct stp_remote_node_context stp; + +}; + +#endif /* __SCU_REMOTE_NODE_CONTEXT_HEADER__ */ diff --git a/drivers/scsi/isci/smp_remote_device.c b/drivers/scsi/isci/smp_remote_device.c new file mode 100644 index 000000000000..718ddaf49343 --- /dev/null +++ b/drivers/scsi/isci/smp_remote_device.c @@ -0,0 +1,314 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "remote_device.h" +#include "scic_sds_request.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_event_codes.h" +#include "scu_task_context.h" + +/* + * ***************************************************************************** + * * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @[in]: device The device the io is sent to. + * @[in]: request The io to start. + * + * This method will handle the start io operation for a SMP device that is in + * the idle state. enum sci_status + */ +static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + enum sci_status status; + + /* Will the port allow the io request to start? */ + status = device->owning_port->state_handlers->start_io_handler( + device->owning_port, device, request); + + if (status == SCI_SUCCESS) { + status = scic_sds_remote_node_context_start_io(&device->rnc, request); + + if (status == SCI_SUCCESS) + status = scic_sds_request_start(request); + + if (status == SCI_SUCCESS) { + device->working_request = request; + + sci_base_state_machine_change_state( + &device->ready_substate_machine, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD + ); + } + + scic_sds_remote_device_start_request(device, request, status); + } + + return status; +} + + +/* + * ****************************************************************************** + * * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS + * ****************************************************************************** */ +/** + * + * @device: This is the device object that is receiving the IO. + * @request: The io to start. + * + * This device is already handling a command it can not accept new commands + * until this one is complete. enum sci_status + */ +static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + return SCI_FAILURE_INVALID_STATE; +} + + +/** + * this is the complete_io_handler for smp device at ready cmd substate. + * @device: This is the device object that is receiving the IO. + * @request: The io to start. + * + * enum sci_status + */ +static enum sci_status +scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + enum sci_status status; + struct scic_sds_request *sci_req; + + sci_req = (struct scic_sds_request *)request; + + status = scic_sds_io_request_complete(sci_req); + + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + device->owning_port, device, sci_req); + + if (status == SCI_SUCCESS) { + scic_sds_remote_device_decrement_request_count(device); + sci_base_state_machine_change_state( + &device->ready_substate_machine, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE + ); + } else + dev_err(scirdev_to_dev(device), + "%s: SCIC SDS Remote Device 0x%p io request " + "0x%p could not be completd on the port 0x%p " + "failed with status %d.\n", + __func__, + device, + sci_req, + device->owning_port, + status); + } + + return status; +} + +/** + * This is frame handler for smp device ready cmd substate. + * @sci_dev: This is the device object that is receiving the frame. + * @frame_index: The index for the frame received. + * + * enum sci_status + */ +static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + enum sci_status status; + + /* + * / The device does not process any UF received from the hardware while + * / in this state. All unsolicited frames are forwarded to the io request + * / object. */ + status = scic_sds_io_request_frame_handler( + sci_dev->working_request, + frame_index + ); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = { + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, + .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler + } +}; + +/** + * + * @object: This is the struct sci_base_object which is cast into a + * struct scic_sds_remote_device. + * + * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. + * This function sets the ready cmd substate handlers and reports the device as + * ready. none + */ +static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + SET_STATE_HANDLER(sci_dev, + scic_sds_smp_remote_device_ready_substate_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + + isci_remote_device_ready(ihost, idev); +} + +/** + * + * @object: This is the struct sci_base_object which is cast into a + * struct scic_sds_remote_device. + * + * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This + * function sets the remote device objects ready cmd substate handlers, and + * notify core user that the device is not ready. none + */ +static void scic_sds_smp_remote_device_ready_cmd_substate_enter( + struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + BUG_ON(sci_dev->working_request == NULL); + + SET_STATE_HANDLER(sci_dev, + scic_sds_smp_remote_device_ready_substate_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + + isci_remote_device_not_ready(ihost, idev, + SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); +} + +/** + * + * @object: This is the struct sci_base_object which is cast into a + * struct scic_sds_remote_device. + * + * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none + */ +static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + sci_dev->working_request = NULL; +} + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = { + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, + }, + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, + .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, + }, +}; diff --git a/drivers/scsi/isci/stp_remote_device.c b/drivers/scsi/isci/stp_remote_device.c new file mode 100644 index 000000000000..b81f21f47d2a --- /dev/null +++ b/drivers/scsi/isci/stp_remote_device.c @@ -0,0 +1,817 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "intel_ata.h" +#include "intel_sata.h" +#include "intel_sat.h" +#include "sci_base_state.h" +#include "scic_sds_controller.h" +#include "scic_sds_port.h" +#include "remote_device.h" +#include "scic_sds_request.h" +#include "sci_environment.h" +#include "sci_util.h" +#include "scu_event_codes.h" + +/** + * This method will perform the STP request completion processing common to IO + * requests and task requests of all types + * @device: This parameter specifies the device for which the request is being + * completed. + * @request: This parameter specifies the request being completed. + * + * This method returns an indication as to whether the request processing + * completed successfully. + */ +static enum sci_status scic_sds_stp_remote_device_complete_request( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + enum sci_status status; + + status = scic_sds_io_request_complete(request); + + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + device->owning_port, device, request); + + if (status == SCI_SUCCESS) { + scic_sds_remote_device_decrement_request_count(device); + if (request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + /* + * This request causes hardware error, device needs to be Lun Reset. + * So here we force the state machine to IDLE state so the rest IOs + * can reach RNC state handler, these IOs will be completed by RNC with + * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ + sci_base_state_machine_change_state( + &device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET + ); + } else if (scic_sds_remote_device_get_request_count(device) == 0) { + sci_base_state_machine_change_state( + &device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE + ); + } + } + } + + if (status != SCI_SUCCESS) + dev_err(scirdev_to_dev(device), + "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " + "could not complete\n", + __func__, + device->owning_port, + device, + request, + status); + + return status; +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * This is the READY NCQ substate handler to start task management request. In + * this routine, we suspend and resume the RNC. + * @device: The target device a task management request towards to. + * @request: The task request. + * + * enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to + * let controller_start_task_handler know that the controller can't post TC for + * task request yet, instead, when RNC gets resumed, a controller_continue_task + * callback will be called. + */ +static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + enum sci_status status; + + /* Will the port allow the io request to start? */ + status = device->owning_port->state_handlers->start_io_handler( + device->owning_port, device, request); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_task(&device->rnc, request); + if (status != SCI_SUCCESS) + goto out; + + status = request->state_handlers->start_handler(request); + if (status != SCI_SUCCESS) + goto out; + + /* + * Note: If the remote device state is not IDLE this will replace + * the request that probably resulted in the task management request. + */ + device->working_request = request; + sci_base_state_machine_change_state(&device->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + + /* + * The remote node context must cleanup the TCi to NCQ mapping table. + * The only way to do this correctly is to either write to the TLCR + * register or to invalidate and repost the RNC. In either case the + * remote node context state machine will take the correct action when + * the remote node context is suspended and later resumed. + */ + scic_sds_remote_node_context_suspend(&device->rnc, + SCI_SOFTWARE_SUSPENSION, NULL, NULL); + scic_sds_remote_node_context_resume(&device->rnc, + scic_sds_remote_device_continue_request, + device); + +out: + scic_sds_remote_device_start_request(device, request, status); + /* + * We need to let the controller start request handler know that it can't + * post TC yet. We will provide a callback function to post TC when RNC gets + * resumed. + */ + return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * This method will handle the start io operation for a sata device that is in + * the command idle state. - Evalute the type of IO request to be started - + * If its an NCQ request change to NCQ substate - If its any other command + * change to the CMD substate + * @device: + * @request: + * + * If this is a softreset we may want to have a different substate. + * enum sci_status + */ +static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status status; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(request); + + + /* Will the port allow the io request to start? */ + status = sci_dev->owning_port->state_handlers->start_io_handler( + sci_dev->owning_port, sci_dev, request); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); + if (status != SCI_SUCCESS) + goto out; + + status = request->state_handlers->start_handler(request); + if (status != SCI_SUCCESS) + goto out; + + if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { + sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); + } else { + sci_dev->working_request = request; + sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + } +out: + scic_sds_remote_device_start_request(sci_dev, request, status); + return status; +} + + +/** + * + * @[in]: device The device received event. + * @[in]: event_code The event code. + * + * This method will handle the event for a sata device that is in the idle + * state. We pick up suspension events to handle specifically to this state. We + * resume the RNC right away. enum sci_status + */ +static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code) +{ + enum sci_status status; + + status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); + + if (status == SCI_SUCCESS) { + if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX + || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { + status = scic_sds_remote_node_context_resume( + &sci_dev->rnc, NULL, NULL); + } + } + + return status; +} + + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS + * ***************************************************************************** */ + +static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status status; + struct isci_request *isci_request = + (struct isci_request *)sci_object_get_association(request); + + if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { + status = sci_dev->owning_port->state_handlers->start_io_handler( + sci_dev->owning_port, + sci_dev, + request); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); + if (status != SCI_SUCCESS) + return status; + + status = request->state_handlers->start_handler(request); + + scic_sds_remote_device_start_request(sci_dev, request, status); + } else + status = SCI_FAILURE_INVALID_STATE; + + return status; +} + + +/** + * This method will handle events received while the STP device is in the ready + * command substate. + * @sci_dev: This is the device object that is receiving the event. + * @event_code: The event code to process. + * + * enum sci_status + */ + +static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + + status = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), + frame_index, + (void **)&frame_header + ); + + if (status == SCI_SUCCESS) { + if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && + (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { + sci_dev->not_ready_reason = + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + + /* + * / @todo Check sactive and complete associated IO + * if any. + */ + + sci_base_state_machine_change_state( + &sci_dev->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR + ); + } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && + (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { + + /* + * Some devices return D2H FIS when an NCQ error is detected. + * Treat this like an SDB error FIS ready reason. + */ + sci_dev->not_ready_reason = + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + + sci_base_state_machine_change_state( + &sci_dev->ready_substate_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR + ); + } else { + status = SCI_FAILURE; + } + + scic_sds_controller_release_frame( + scic_sds_remote_device_get_controller(sci_dev), frame_index + ); + } + + return status; +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * This device is already handling a command it can not accept new commands + * until this one is complete. + * @device: + * @request: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( + struct scic_sds_remote_device *sci_dev, + u32 suspend_type) +{ + enum sci_status status; + + status = scic_sds_remote_node_context_suspend(&sci_dev->rnc, + suspend_type, NULL, NULL); + + return status; +} + +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + enum sci_status status; + + /* + * / The device doe not process any UF received from the hardware while + * / in this state. All unsolicited frames are forwarded to the io request + * / object. */ + status = scic_sds_io_request_frame_handler( + sci_dev->working_request, + frame_index + ); + + return status; +} + + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS + * ***************************************************************************** */ + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS + * ***************************************************************************** */ + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS + * ***************************************************************************** */ +static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; +} + + + +/** + * This method will perform the STP request (both io or task) completion + * processing for await reset state. + * @device: This parameter specifies the device for which the request is being + * completed. + * @request: This parameter specifies the request being completed. + * + * This method returns an indication as to whether the request processing + * completed successfully. + */ +static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + struct scic_sds_request *sci_req = (struct scic_sds_request *)request; + enum sci_status status; + + status = scic_sds_io_request_complete(sci_req); + + if (status == SCI_SUCCESS) { + status = scic_sds_port_complete_io( + device->owning_port, device, sci_req + ); + + if (status == SCI_SUCCESS) + scic_sds_remote_device_decrement_request_count(device); + } + + if (status != SCI_SUCCESS) + dev_err(scirdev_to_dev(device), + "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " + "could not complete\n", + __func__, + device->owning_port, + device, + sci_req, + status); + + return status; +} + +#if !defined(DISABLE_ATAPI) +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS + * ***************************************************************************** */ + +/** + * + * @[in]: device The device received event. + * @[in]: event_code The event code. + * + * This method will handle the event for a ATAPI device that is in the ATAPI + * ERROR state. We pick up suspension events to handle specifically to this + * state. We resume the RNC right away. We then complete the outstanding IO to + * this device. enum sci_status + */ +enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code) +{ + enum sci_status status; + + status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); + + if (status == SCI_SUCCESS) { + if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX + || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { + status = scic_sds_remote_node_context_resume( + sci_dev->rnc, + sci_dev->working_request->state_handlers->parent.complete_handler, + (void *)sci_dev->working_request + ); + } + } + + return status; +} +#endif /* !defined(DISABLE_ATAPI) */ + +/* --------------------------------------------------------------------------- */ + +static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, +#if !defined(DISABLE_ATAPI) + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, +#endif + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + } +}; + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS + * ***************************************************************************** */ + +static void +scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *user_cookie) +{ + struct scic_sds_remote_device *sci_dev = user_cookie; + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + + /* + * For NCQ operation we do not issue a + * scic_cb_remote_device_not_ready(). As a result, avoid sending + * the ready notification. + */ + if (sci_dev->ready_substate_machine.previous_state_id != + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) + isci_remote_device_ready(ihost, idev); +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY IDLE SUBSTATE + * ***************************************************************************** */ + +/** + * + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +static void scic_sds_stp_remote_device_ready_idle_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *sci_dev; + + sci_dev = (struct scic_sds_remote_device *)device; + + SET_STATE_HANDLER( + sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE + ); + + sci_dev->working_request = NULL; + + if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { + /* + * Since the RNC is ready, it's alright to finish completion + * processing (e.g. signal the remote device is ready). */ + scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( + sci_dev + ); + } else { + scic_sds_remote_node_context_resume( + &sci_dev->rnc, + scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, + sci_dev); + } +} + +static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + BUG_ON(sci_dev->working_request == NULL); + + SET_STATE_HANDLER(sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + + isci_remote_device_not_ready(ihost, idev, + SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); +} + +static void scic_sds_stp_remote_device_ready_ncq_substate_enter(struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + SET_STATE_HANDLER(sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); +} + +static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_object *object) +{ + struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), + parent); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_host *ihost = sci_object_get_association(scic); + struct isci_remote_device *idev = sci_object_get_association(sci_dev); + + SET_STATE_HANDLER(sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + + if (sci_dev->not_ready_reason == + SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) + isci_remote_device_not_ready(ihost, idev, sci_dev->not_ready_reason); +} + +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE + * ***************************************************************************** */ + +/** + * The enter routine to READY AWAIT RESET substate. + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *sci_dev; + + sci_dev = (struct scic_sds_remote_device *)device; + + SET_STATE_HANDLER( + sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET + ); +} + +#if !defined(DISABLE_ATAPI) +/* + * ***************************************************************************** + * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE + * ***************************************************************************** */ + +/** + * The enter routine to READY ATAPI ERROR substate. + * @device: This is the SCI base object which is cast into a + * struct scic_sds_remote_device object. + * + */ +void scic_sds_stp_remote_device_ready_atapi_error_substate_enter( + struct sci_base_object *device) +{ + struct scic_sds_remote_device *sci_dev; + + sci_dev = (struct scic_sds_remote_device *)device; + + SET_STATE_HANDLER( + sci_dev, + scic_sds_stp_remote_device_ready_substate_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR + ); +} +#endif /* !defined(DISABLE_ATAPI) */ + +/* --------------------------------------------------------------------------- */ + +const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { + .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { + .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, + }, +#if !defined(DISABLE_ATAPI) + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { + .enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter, + }, +#endif + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { + .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, + }, +}; diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index f54f523b8d40..e011d668949d 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -56,10 +56,9 @@ #include #include #include "scic_task_request.h" -#include "scic_remote_device.h" #include "scic_io_request.h" -#include "scic_sds_remote_device.h" -#include "scic_sds_remote_node_context.h" +#include "remote_device.h" +#include "remote_node_context.h" #include "isci.h" #include "request.h" #include "sata.h" -- cgit v1.2.3 From b87ee3075b090e1dd0bdf40b295142b606d55e64 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 25 Apr 2011 11:48:29 -0700 Subject: isci: cleanup remote device construction and comments The construction routines scic_remote_device_[de]a_construct both reference the need to call scic_remote_device_construct first. Delete that comment and just have them call it explicitly, also: * move the comments from header to source * delete dead references to scic_[de]a_remote_device_add_phy Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 101 ++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 59 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 6b9ea9022843..70641818f602 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1438,15 +1438,14 @@ static const struct sci_base_state scic_sds_remote_device_state_table[] = { }; /** - * scic_remote_device_construct() - This method will perform the construction - * common to all remote device objects. + * scic_remote_device_construct() - common construction * @sci_port: SAS/SATA port through which this device is accessed. * @sci_dev: remote device to construct * - * It isn't necessary to call scic_remote_device_destruct() for device objects - * that have only called this method for construction. Once subsequent - * construction methods have been invoked (e.g. - * scic_remote_device_da_construct()), then destruction should occur. none + * This routine just performs benign initialization and does not + * allocate the remote_node_context which is left to + * scic_remote_device_[de]a_construct(). scic_remote_device_destruct() + * frees the remote_node_context(s) for the device. */ static void scic_remote_device_construct(struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev) @@ -1473,32 +1472,28 @@ static void scic_remote_device_construct(struct scic_sds_port *sci_port, } /** - * scic_remote_device_da_construct() - This method will construct a - * SCIC_REMOTE_DEVICE object for a direct attached (da) device. The - * information (e.g. IAF, Signature FIS, etc.) necessary to build the device - * is known to the SCI Core since it is contained in the scic_phy object. - * @remote_device: This parameter specifies the remote device to be destructed. - * - * The user must have previously called scic_remote_device_construct() Remote - * device objects are a limited resource. As such, they must be protected. - * Thus calls to construct and destruct are mutually exclusive and - * non-reentrant. Indicate if the remote device was successfully constructed. - * SCI_SUCCESS Returned if the device was successfully constructed. - * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been - * constructed. If it's an additional phy for the target, then call - * scic_remote_device_da_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned - * if the supplied parameters necessitate creation of a remote device for which - * the protocol is not supported by the underlying controller hardware. - * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core - * controller associated with the supplied parameters is unable to support - * additional remote devices. + * scic_remote_device_da_construct() - construct direct attached device. + * + * The information (e.g. IAF, Signature FIS, etc.) necessary to build + * the device is known to the SCI Core since it is contained in the + * scic_phy object. Remote node context(s) is/are a global resource + * allocated by this routine, freed by scic_remote_device_destruct(). + * + * Returns: + * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed. + * SCI_FAILURE_UNSUPPORTED_PROTOCOL - e.g. sas device attached to + * sata-only controller instance. + * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ -static enum sci_status scic_remote_device_da_construct(struct scic_sds_remote_device *sci_dev) +static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev) { enum sci_status status; u16 remote_node_index; struct sci_sas_identify_address_frame_protocols protocols; + scic_remote_device_construct(sci_port, sci_dev); + /* * This information is request to determine how many remote node context * entries will be needed to store the remote node. @@ -1567,34 +1562,26 @@ static void scic_sds_remote_device_get_info_from_smp_discover_response( } /** - * scic_remote_device_ea_construct() - This method will construct an - * SCIC_REMOTE_DEVICE object for an expander attached (ea) device from an - * SMP Discover Response. - * @remote_device: This parameter specifies the remote device to be destructed. - * @discover_response: This parameter specifies the SMP Discovery Response to - * be used in device creation. - * - * The user must have previously called scic_remote_device_construct() Remote - * device objects are a limited resource. As such, they must be protected. - * Thus calls to construct and destruct are mutually exclusive and - * non-reentrant. Indicate if the remote device was successfully constructed. - * SCI_SUCCESS Returned if the device was successfully constructed. - * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been - * constructed. If it's an additional phy for the target, then call - * scic_ea_remote_device_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned - * if the supplied parameters necessitate creation of a remote device for which - * the protocol is not supported by the underlying controller hardware. - * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core - * controller associated with the supplied parameters is unable to support - * additional remote devices. + * scic_remote_device_ea_construct() - construct expander attached device + * @discover_response: data to build remote device + * + * Remote node context(s) is/are a global resource allocated by this + * routine, freed by scic_remote_device_destruct(). + * + * Returns: + * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed. + * SCI_FAILURE_UNSUPPORTED_PROTOCOL - e.g. sas device attached to + * sata-only controller instance. + * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ -static enum sci_status scic_remote_device_ea_construct(struct scic_sds_remote_device *sci_dev, +static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, struct smp_response_discover *discover_response) { + struct scic_sds_controller *scic = sci_port->owning_controller; enum sci_status status; - struct scic_sds_controller *scic; - scic = scic_sds_port_get_controller(sci_dev->owning_port); + scic_remote_device_construct(sci_port, sci_dev); scic_sds_remote_device_get_info_from_smp_discover_response( sci_dev, discover_response); @@ -1632,9 +1619,8 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_remote_de * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay * one another, so this code works for both situations. */ sci_dev->connection_rate = min_t(u16, - scic_sds_port_get_max_allowed_speed(sci_dev->owning_port), - discover_response->u2.sas1_1.negotiated_physical_link_rate - ); + scic_sds_port_get_max_allowed_speed(sci_port), + discover_response->u2.sas1_1.negotiated_physical_link_rate); /* / @todo Should I assign the port width by reading all of the phys on the port? */ sci_dev->device_port_width = 1; @@ -1678,11 +1664,6 @@ static enum sci_status isci_remote_device_construct( { enum sci_status status = SCI_SUCCESS; - /* let the core do it's common constuction. */ - scic_remote_device_construct(port->sci_port_handle, - &isci_device->sci); - - /* let the core do it's device specific constuction. */ if (isci_device->domain_dev->parent && (isci_device->domain_dev->parent->dev_type == EDGE_DEV)) { int i; @@ -1746,11 +1727,13 @@ static enum sci_status isci_remote_device_construct( "%s: parent->dev_type = EDGE_DEV\n", __func__); - status = scic_remote_device_ea_construct(&isci_device->sci, + status = scic_remote_device_ea_construct(port->sci_port_handle, + &isci_device->sci, (struct smp_response_discover *)&discover_response); } else - status = scic_remote_device_da_construct(&isci_device->sci); + status = scic_remote_device_da_construct(port->sci_port_handle, + &isci_device->sci); if (status != SCI_SUCCESS) { -- cgit v1.2.3 From a1a113b0a1ea437daf099b44f8a39e93a02a3f47 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 21 Apr 2011 18:44:45 -0700 Subject: isci: kill smp_discover_response_protocols in favor of domain_device.dev_type This is step 1 of removing the contortions to: 1/ unparse expander phy data into a smp discover frame 2/ open-code-parse the smp discover fram into a domain_device.dev_type equivalent libsas has already spent cycles determining the dev_type, so now that scic_sds_remote_device is unified with isci_remote_device we can directly reference dev_type. This might also change multi-level expander detection as we previously only looked at dev_type == EDGE_DEV and we did not consider the FANOUT_DEV case. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.h | 20 ++--- drivers/scsi/isci/core/scic_sds_port.c | 2 +- drivers/scsi/isci/core/scic_sds_port.h | 4 - drivers/scsi/isci/core/scic_sds_request.c | 24 +++--- drivers/scsi/isci/remote_device.c | 110 ++++++++++++--------------- drivers/scsi/isci/remote_device.h | 34 +++------ drivers/scsi/isci/remote_node_context.c | 63 ++++++--------- drivers/scsi/isci/request.c | 19 +++-- drivers/scsi/isci/task.c | 20 ++--- 9 files changed, 118 insertions(+), 178 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index e15c4e2fd76d..ce81286e52fd 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -74,9 +74,9 @@ #include "scic_sds_port.h" #include "scic_sds_phy.h" #include "remote_node_table.h" +#include "remote_device.h" #include "scu_registers.h" #include "scu_constants.h" -#include "scu_remote_node_context.h" #include "scu_task_context.h" #include "scu_unsolicited_frame.h" #include "scic_sds_unsolicited_frame_control.h" @@ -498,14 +498,16 @@ enum scic_sds_controller_states { #define scic_sds_io_sequence_increment(value) \ ((value) = (((value) + 1) & 0x000F)) -#define scic_sds_remote_device_node_count(device) \ - (\ - (\ - (device)->target_protocols.u.bits.attached_stp_target \ - && ((device)->is_direct_attached != true) \ - ) \ - ? SCU_STP_REMOTE_NODE_COUNT : SCU_SSP_REMOTE_NODE_COUNT \ - ) +/* expander attached sata devices require 3 rnc slots */ +static inline int scic_sds_remote_device_node_count(struct scic_sds_remote_device *sci_dev) +{ + struct domain_device *dev = sci_dev_to_domain(sci_dev); + + if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) && + !sci_dev->is_direct_attached) + return SCU_STP_REMOTE_NODE_COUNT; + return SCU_SSP_REMOTE_NODE_COUNT; +} /** * scic_sds_controller_set_invalid_phy() - diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index b07e48e2f188..057f95a79be9 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -434,7 +434,7 @@ void scic_sds_port_get_attached_sas_address( * multi-protocol support. * */ -void scic_sds_port_get_attached_protocols( +static void scic_sds_port_get_attached_protocols( struct scic_sds_port *sci_port, struct sci_sas_identify_address_frame_protocols *protocols) { diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 964e3885dbf2..59c76cd3902f 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -447,8 +447,4 @@ void scic_sds_port_get_attached_sas_address( struct scic_sds_port *sci_port, struct sci_sas_address *sas_address); -void scic_sds_port_get_attached_protocols( - struct scic_sds_port *sci_port, - struct sci_sas_identify_address_frame_protocols *protocols); - #endif /* _SCIC_SDS_PORT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index dfb94121d445..a66e7b248b24 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -1758,8 +1758,8 @@ enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, struct scic_sds_request *sci_req, struct scic_sds_request **new_scic_io_request_handle) { + struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status = SCI_SUCCESS; - struct smp_discover_response_protocols device_protocol; /* Build the common part of the request */ scic_sds_general_request_construct(scic, sci_dev, io_tag, @@ -1768,19 +1768,16 @@ enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; - scic_remote_device_get_protocols(sci_dev, &device_protocol); - - if (device_protocol.u.bits.attached_ssp_target) { + if (dev->dev_type == SAS_END_DEV) { scic_sds_ssp_io_request_assign_buffers(sci_req); - } else if (device_protocol.u.bits.attached_stp_target) { + } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { scic_sds_stp_request_assign_buffers(sci_req); memset(sci_req->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); - } else if (device_protocol.u.bits.attached_smp_target) { + } else if (dev_is_expander(dev)) { scic_sds_smp_request_assign_buffers(sci_req); memset(sci_req->command_buffer, 0, sizeof(struct smp_request)); - } else { + } else status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - } if (status == SCI_SUCCESS) { memset(sci_req->task_context_buffer, 0, @@ -1798,17 +1795,15 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_request *sci_req, struct scic_sds_request **new_sci_req) { + struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status = SCI_SUCCESS; - struct smp_discover_response_protocols device_protocol; /* Build the common part of the request */ scic_sds_general_request_construct(scic, sci_dev, io_tag, user_io_request_object, sci_req); - scic_remote_device_get_protocols(sci_dev, &device_protocol); - - if (device_protocol.u.bits.attached_ssp_target) { + if (dev->dev_type == SAS_END_DEV) { scic_sds_ssp_task_request_assign_buffers(sci_req); sci_req->has_started_substate_machine = true; @@ -1820,11 +1815,10 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, scic_sds_io_request_started_task_mgmt_substate_table, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION ); - } else if (device_protocol.u.bits.attached_stp_target) { + } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) scic_sds_stp_request_assign_buffers(sci_req); - } else { + else status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - } if (status == SCI_SUCCESS) { sci_req->is_task_management_request = true; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 70641818f602..fc79a5b47f72 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -100,13 +100,6 @@ enum sas_linkrate scic_remote_device_get_connection_rate( } -void scic_remote_device_get_protocols( - struct scic_sds_remote_device *sci_dev, - struct smp_discover_response_protocols *pr) -{ - pr->u.all = sci_dev->target_protocols.u.all; -} - #if !defined(DISABLE_ATAPI) bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev) { @@ -1490,7 +1483,7 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci { enum sci_status status; u16 remote_node_index; - struct sci_sas_identify_address_frame_protocols protocols; + struct domain_device *dev = sci_dev_to_domain(sci_dev); scic_remote_device_construct(sci_port, sci_dev); @@ -1498,53 +1491,46 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci * This information is request to determine how many remote node context * entries will be needed to store the remote node. */ - scic_sds_port_get_attached_protocols(sci_dev->owning_port, &protocols); - sci_dev->target_protocols.u.all = protocols.u.all; sci_dev->is_direct_attached = true; -#if !defined(DISABLE_ATAPI) - sci_dev->is_atapi = scic_sds_remote_device_is_atapi(sci_dev); -#endif + status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller, + sci_dev, + &remote_node_index); - status = scic_sds_controller_allocate_remote_node_context( - sci_dev->owning_port->owning_controller, - sci_dev, - &remote_node_index); + if (status != SCI_SUCCESS) + return status; - if (status == SCI_SUCCESS) { - sci_dev->rnc.remote_node_index = remote_node_index; + sci_dev->rnc.remote_node_index = remote_node_index; - scic_sds_port_get_attached_sas_address( - sci_dev->owning_port, &sci_dev->device_address); + scic_sds_port_get_attached_sas_address(sci_port, &sci_dev->device_address); - if (sci_dev->target_protocols.u.bits.attached_ssp_target) { - sci_dev->has_ready_substate_machine = false; - } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { - sci_dev->has_ready_substate_machine = true; + if (dev->dev_type == SAS_END_DEV) + sci_dev->has_ready_substate_machine = false; + else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { + sci_dev->has_ready_substate_machine = true; - sci_base_state_machine_construct( + sci_base_state_machine_construct( &sci_dev->ready_substate_machine, &sci_dev->parent, scic_sds_stp_remote_device_ready_substate_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { - sci_dev->has_ready_substate_machine = true; + } else if (dev_is_expander(dev)) { + sci_dev->has_ready_substate_machine = true; - /* add the SMP ready substate machine construction here */ - sci_base_state_machine_construct( + /* add the SMP ready substate machine construction here */ + sci_base_state_machine_construct( &sci_dev->ready_substate_machine, &sci_dev->parent, scic_sds_smp_remote_device_ready_substate_table, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } + } else + return SCI_FAILURE_UNSUPPORTED_PROTOCOL; - sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed( - sci_dev->owning_port); + sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(sci_port); - /* / @todo Should I assign the port width by reading all of the phys on the port? */ - sci_dev->device_port_width = 1; - } + /* / @todo Should I assign the port width by reading all of the phys on the port? */ + sci_dev->device_port_width = 1; - return status; + return SCI_SUCCESS; } static void scic_sds_remote_device_get_info_from_smp_discover_response( @@ -1557,8 +1543,6 @@ static void scic_sds_remote_device_get_info_from_smp_discover_response( sci_dev->device_address.low = discover_response->attached_sas_address.low; - - sci_dev->target_protocols.u.all = discover_response->protocols.u.all; } /** @@ -1579,6 +1563,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci struct smp_response_discover *discover_response) { struct scic_sds_controller *scic = sci_port->owning_controller; + struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status; scic_remote_device_construct(sci_port, sci_dev); @@ -1588,43 +1573,42 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci status = scic_sds_controller_allocate_remote_node_context( scic, sci_dev, &sci_dev->rnc.remote_node_index); + if (status != SCI_SUCCESS) + return status; - if (status == SCI_SUCCESS) { - if (sci_dev->target_protocols.u.bits.attached_ssp_target) { - sci_dev->has_ready_substate_machine = false; - } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { - sci_dev->has_ready_substate_machine = true; + if (dev->dev_type == SAS_END_DEV) + sci_dev->has_ready_substate_machine = false; + else if (dev_is_expander(dev)) { + sci_dev->has_ready_substate_machine = true; - /* add the SMP ready substate machine construction here */ - sci_base_state_machine_construct( + /* add the SMP ready substate machine construction here */ + sci_base_state_machine_construct( &sci_dev->ready_substate_machine, &sci_dev->parent, scic_sds_smp_remote_device_ready_substate_table, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { - sci_dev->has_ready_substate_machine = true; + } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { + sci_dev->has_ready_substate_machine = true; - sci_base_state_machine_construct( + sci_base_state_machine_construct( &sci_dev->ready_substate_machine, &sci_dev->parent, scic_sds_stp_remote_device_ready_substate_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } + } - /* - * For SAS-2 the physical link rate is actually a logical link - * rate that incorporates multiplexing. The SCU doesn't - * incorporate multiplexing and for the purposes of the - * connection the logical link rate is that same as the - * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay - * one another, so this code works for both situations. */ - sci_dev->connection_rate = min_t(u16, - scic_sds_port_get_max_allowed_speed(sci_port), + /* + * For SAS-2 the physical link rate is actually a logical link + * rate that incorporates multiplexing. The SCU doesn't + * incorporate multiplexing and for the purposes of the + * connection the logical link rate is that same as the + * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay + * one another, so this code works for both situations. */ + sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(sci_port), discover_response->u2.sas1_1.negotiated_physical_link_rate); - /* / @todo Should I assign the port width by reading all of the phys on the port? */ - sci_dev->device_port_width = 1; - } + /* / @todo Should I assign the port width by reading all of the phys on the port? */ + sci_dev->device_port_width = 1; return status; } @@ -1665,7 +1649,7 @@ static enum sci_status isci_remote_device_construct( enum sci_status status = SCI_SUCCESS; if (isci_device->domain_dev->parent && - (isci_device->domain_dev->parent->dev_type == EDGE_DEV)) { + dev_is_expander(isci_device->domain_dev->parent)) { int i; /* struct smp_response_discover discover_response; */ diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 9d8fcbf72ded..39821601022b 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -99,11 +99,6 @@ struct scic_sds_remote_device { */ enum sas_linkrate connection_rate; - /** - * This field contains the allowed target protocols for this remote device. - */ - struct smp_discover_response_protocols target_protocols; - /** * This field contains the device SAS address. */ @@ -264,23 +259,6 @@ enum sci_status scic_remote_device_reset_complete( enum sas_linkrate scic_remote_device_get_connection_rate( struct scic_sds_remote_device *remote_device); -/** - * scic_remote_device_get_protocols() - This method will indicate which - * protocols are supported by this remote device. - * @remote_device: This parameter specifies the device for which to return the - * protocol. - * @protocols: This parameter specifies the output values, from the remote - * device object, which indicate the protocols supported by the supplied - * remote_device. - * - * The type of protocols supported by this device. The values are returned as - * part of a bit mask in order to allow for multi-protocol support. - */ -void scic_remote_device_get_protocols( - struct scic_sds_remote_device *remote_device, - struct smp_discover_response_protocols *protocols); - - #if !defined(DISABLE_ATAPI) /** * scic_remote_device_is_atapi() - @@ -477,6 +455,18 @@ static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_n return sci_dev; } +static inline struct domain_device *sci_dev_to_domain(struct scic_sds_remote_device *sci_dev) +{ + struct isci_remote_device *idev = container_of(sci_dev, typeof(*idev), sci); + + return idev->domain_dev; +} + +static inline bool dev_is_expander(struct domain_device *dev) +{ + return dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV; +} + typedef enum sci_status (*scic_sds_remote_device_request_handler_t)( struct scic_sds_remote_device *device, struct scic_sds_request *request); diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index bdf0b5101cfa..285232fd5e63 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -106,8 +106,9 @@ bool scic_sds_remote_node_context_is_ready( static void scic_sds_remote_node_context_construct_buffer( struct scic_sds_remote_node_context *sci_rnc) { - union scu_remote_node_context *rnc; struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); + struct domain_device *dev = sci_dev_to_domain(sci_dev); + union scu_remote_node_context *rnc; struct scic_sds_controller *scic; scic = scic_sds_remote_device_get_controller(sci_dev); @@ -134,11 +135,7 @@ static void scic_sds_remote_node_context_construct_buffer( rnc->ssp.arbitration_wait_time = 0; - - if ( - sci_dev->target_protocols.u.bits.attached_sata_device - || sci_dev->target_protocols.u.bits.attached_stp_target - ) { + if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { rnc->ssp.connection_occupancy_timeout = scic->user_parameters.sds1.stp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = @@ -639,45 +636,30 @@ static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_ha scics_sds_remote_node_context_callback callback, void *callback_parameter) { - enum sci_status status; - struct smp_discover_response_protocols protocols; + struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); + struct domain_device *dev = sci_dev_to_domain(sci_dev); + enum sci_status status = SCI_SUCCESS; - scic_sds_remote_node_context_setup_to_resume( - sci_rnc, callback, callback_parameter - ); + scic_sds_remote_node_context_setup_to_resume(sci_rnc, callback, + callback_parameter); /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ - - scic_remote_device_get_protocols(rnc_to_dev(sci_rnc), &protocols); - - if ( - (protocols.u.bits.attached_ssp_target == 1) - || (protocols.u.bits.attached_smp_target == 1) - ) { - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE - ); - - status = SCI_SUCCESS; - } else if (protocols.u.bits.attached_stp_target == 1) { - if (rnc_to_dev(sci_rnc)->is_direct_attached) { + if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev)) + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); + else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { + if (sci_dev->is_direct_attached) { /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ sci_base_state_machine_change_state( &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE - ); + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); } else { sci_base_state_machine_change_state( &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE - ); + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE); } - - status = SCI_SUCCESS; - } else { + } else status = SCI_FAILURE; - } return status; } @@ -932,6 +914,7 @@ static void scic_sds_remote_node_context_validate_context_buffer( struct scic_sds_remote_node_context *sci_rnc) { struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); + struct domain_device *dev = sci_dev_to_domain(sci_dev); union scu_remote_node_context *rnc_buffer; rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( @@ -942,7 +925,7 @@ static void scic_sds_remote_node_context_validate_context_buffer( rnc_buffer->ssp.is_valid = true; if (!sci_dev->is_direct_attached && - sci_dev->target_protocols.u.bits.attached_stp_target) { + (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))) { scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_96); } else { @@ -1063,11 +1046,12 @@ static void scic_sds_remote_node_context_resuming_state_enter( struct sci_base_object *object) { struct scic_sds_remote_node_context *rnc; - struct smp_discover_response_protocols protocols; struct scic_sds_remote_device *sci_dev; + struct domain_device *dev; rnc = (struct scic_sds_remote_node_context *)object; sci_dev = rnc_to_dev(rnc); + dev = sci_dev_to_domain(sci_dev); SET_STATE_HANDLER( rnc, @@ -1081,13 +1065,10 @@ static void scic_sds_remote_node_context_resuming_state_enter( * resume because of a target reset we also need to update * the STPTLDARNI register with the RNi of the device */ - scic_remote_device_get_protocols(sci_dev, &protocols); - - if (protocols.u.bits.attached_stp_target == 1 && - sci_dev->is_direct_attached) { + if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) && + sci_dev->is_direct_attached) scic_sds_port_setup_transports(sci_dev->owning_port, rnc->remote_node_index); - } scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); } diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index ff5c05a19543..281a556f5eeb 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -175,7 +175,6 @@ static enum sci_status isci_io_request_build( struct isci_request *request, struct isci_remote_device *isci_device) { - struct smp_discover_response_protocols dev_protocols; enum sci_status status = SCI_SUCCESS; struct sas_task *task = isci_request_access_task(request); struct scic_sds_remote_device *sci_device = &isci_device->sci; @@ -228,15 +227,19 @@ static enum sci_status isci_io_request_build( sci_object_set_association(request->sci_request_handle, request); - /* Determine protocol and call the appropriate basic constructor */ - scic_remote_device_get_protocols(sci_device, &dev_protocols); - if (dev_protocols.u.bits.attached_ssp_target) + switch (task->task_proto) { + case SAS_PROTOCOL_SMP: + status = isci_smp_request_build(request); + break; + case SAS_PROTOCOL_SSP: status = isci_request_ssp_request_construct(request); - else if (dev_protocols.u.bits.attached_stp_target) + break; + case SAS_PROTOCOL_SATA: + case SAS_PROTOCOL_STP: + case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: status = isci_request_stp_request_construct(request); - else if (dev_protocols.u.bits.attached_smp_target) - status = isci_smp_request_build(request); - else { + break; + default: dev_warn(&isci_host->pdev->dev, "%s: unknown protocol\n", __func__); return SCI_FAILURE; diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index e011d668949d..c6f1ffd713a8 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -273,15 +273,14 @@ static enum sci_status isci_task_request_build( enum sci_status status = SCI_FAILURE; struct isci_request *request = NULL; struct isci_remote_device *isci_device; -/* struct sci_sas_identify_address_frame_protocols dev_protocols; */ - struct smp_discover_response_protocols dev_protocols; - + struct domain_device *dev; dev_dbg(&isci_host->pdev->dev, "%s: isci_tmf = %p\n", __func__, isci_tmf); isci_device = isci_tmf->device; sci_device = &isci_device->sci; + dev = isci_device->domain_dev; /* do common allocation and init of request object. */ status = isci_request_alloc_tmf( @@ -319,16 +318,8 @@ static enum sci_status isci_task_request_build( request ); - scic_remote_device_get_protocols( - sci_device, - &dev_protocols - ); - - /* let the core do it's protocol - * specific construction. - */ - if (dev_protocols.u.bits.attached_ssp_target) { - + /* XXX convert to get this from task->tproto like other drivers */ + if (dev->dev_type == SAS_END_DEV) { isci_tmf->proto = SAS_PROTOCOL_SSP; status = scic_task_request_construct_ssp( request->sci_request_handle @@ -337,8 +328,7 @@ static enum sci_status isci_task_request_build( goto errout; } - if (dev_protocols.u.bits.attached_stp_target) { - + if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { isci_tmf->proto = SAS_PROTOCOL_SATA; status = isci_sata_management_task_request_build(request); -- cgit v1.2.3 From 00d680ef84570bc7aea023772d27e85b0052004c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 25 Apr 2011 14:29:29 -0700 Subject: isci: kill smp_discover_response An lldd need never look at the contents of an smp_discover_response frame. Kill the remaining locations where isci is looking at it: 1/ covering for expanders that do not set the stp_attached bit (already handled by sas_ex_discover_end_dev) 2/ an overkill method to notifiy the rest of the driver about remote_device sas addresses Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 197 -------------------------- drivers/scsi/isci/core/scic_sds_smp_request.c | 20 --- drivers/scsi/isci/remote_device.c | 138 +++--------------- drivers/scsi/isci/remote_node_context.c | 5 +- 4 files changed, 23 insertions(+), 337 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index d9c9f33a7af5..b57f39c2cfc2 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -628,202 +628,6 @@ struct smp_response_report_manufacturer_information { }; -#define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52 -#define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE 116 - -/** - * struct smp_discover_response_protocols - This structure depicts the discover - * response where the supported protocols by the remote phy are specified. - * - * For specific information on each of these individual fields please reference - * the SAS specification Link layer section on address frames. - */ -struct smp_discover_response_protocols { - union { - struct { - u16 attached_sata_host:1; - u16 attached_smp_initiator:1; - u16 attached_stp_initiator:1; - u16 attached_ssp_initiator:1; - u16 reserved3:4; - u16 attached_sata_device:1; - u16 attached_smp_target:1; - u16 attached_stp_target:1; - u16 attached_ssp_target:1; - u16 reserved4:3; - u16 attached_sata_port_selector:1; - } bits; - - u16 all; - } u; - -}; - -/** - * struct SMP_RESPONSE_DISCOVER_FORMAT - This structure defines the SMP phy - * discover response format. It handles both SAS1.1 and SAS 2 definitions. - * The unions indicate locations where the SAS specification versions differ - * from one another. - * - * - */ -struct smp_response_discover { - - union { - struct { - u8 reserved[2]; - } sas1_1; - - struct { - u16 expander_change_count; - } sas2; - - } u1; - - u8 reserved1[3]; - u8 phy_identifier; - u8 reserved2[2]; - - union { - struct { - u16 reserved1:4; - u16 attached_device_type:3; - u16 reserved2:1; - u16 negotiated_physical_link_rate:4; - u16 reserved3:4; - } sas1_1; - - struct { - u16 attached_reason:4; - u16 attached_device_type:3; - u16 reserved2:1; - u16 negotiated_logical_link_rate:4; - u16 reserved3:4; - } sas2; - - } u2; - - struct smp_discover_response_protocols protocols; - struct sci_sas_address sas_address; - struct sci_sas_address attached_sas_address; - - u8 attached_phy_identifier; - - union { - struct { - u8 reserved; - } sas1_1; - - struct { - u8 attached_break_reply_capable:1; - u8 attached_requested_inside_zpsds:1; - u8 attached_inside_zpsds_persistent:1; - u8 reserved1:5; - } sas2; - - } u3; - - u8 reserved_for_identify[6]; - - u32 hardware_min_physical_link_rate:4; - u32 programmed_min_physical_link_rate:4; - u32 hardware_max_physical_link_rate:4; - u32 programmed_max_physical_link_rate:4; - u32 phy_change_count:8; - u32 partial_pathway_timeout_value:4; - u32 reserved5:3; - u32 virtual_phy:1; - - u32 routing_attribute:4; - u32 reserved6:4; - u32 connector_type:7; - u32 reserved7:1; - u32 connector_element_index:8; - u32 connector_physical_link:8; - - u16 reserved8; - u16 vendor_specific; - - union { - struct { - /** - * In the SAS 1.1 specification this structure ends after 52 bytes. - * As a result, the contents of this field should never have a - * real value. It is undefined. - */ - u8 undefined[SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE - - SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE]; - } sas1_1; - - struct { - struct sci_sas_address attached_device_name; - - u32 zoning_enabled:1; - u32 inside_zpsds:1; - u32 zone_group_persistent:1; - u32 reserved1:1; - u32 requested_inside_zpsds:1; - u32 inside_zpsds_persistent:1; - u32 requested_inside_zpsds_changed_by_expander:1; - u32 reserved2:1; - u32 reserved_for_zoning_fields:16; - u32 zone_group:8; - - u8 self_configuration_status; - u8 self_configuration_levels_completed; - u16 reserved_for_self_config_fields; - - struct sci_sas_address self_configuration_sas_address; - - u32 programmed_phy_capabilities; - u32 current_phy_capabilities; - u32 attached_phy_capabilities; - - u32 reserved3; - - u32 reserved4:16; - u32 negotiated_physical_link_rate:4; - u32 reason:4; - u32 hardware_muxing_supported:1; - u32 negotiated_ssc:1; - u32 reserved5:6; - - u32 default_zoning_enabled:1; - u32 reserved6:1; - u32 default_zone_group_persistent:1; - u32 reserved7:1; - u32 default_requested_inside_zpsds:1; - u32 default_inside_zpsds_persistent:1; - u32 reserved8:2; - u32 reserved9:16; - u32 default_zone_group:8; - - u32 saved_zoning_enabled:1; - u32 reserved10:1; - u32 saved_zone_group_persistent:1; - u32 reserved11:1; - u32 saved_requested_inside_zpsds:1; - u32 saved_inside_zpsds_persistent:1; - u32 reserved12:18; - u32 saved_zone_group:8; - - u32 reserved14:2; - u32 shadow_zone_group_persistent:1; - u32 reserved15:1; - u32 shadow_requested_inside_zpsds:1; - u32 shadow_inside_zpsds_persistent:1; - u32 reserved16:18; - u32 shadow_zone_group:8; - - u8 device_slot_number; - u8 device_slot_group_number; - u8 device_slot_group_output_connector[6]; - } sas2; - - } u4; - -}; - /** * struct smp_response_report_phy_sata - This structure depicts the contents of * the SAS SMP REPORT PHY SATA frame. For specific information on each of @@ -857,7 +661,6 @@ struct smp_response_vendor_specific { union smp_response_body { struct smp_response_report_general report_general; struct smp_response_report_manufacturer_information report_manufacturer_information; - struct smp_response_discover discover; struct smp_response_report_phy_sata report_phy_sata; struct smp_response_vendor_specific vendor_specific_response; }; diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 1790f25758d1..d4009e57acaf 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -339,26 +339,6 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( smp_response_buffer, sizeof(union smp_response_body) / sizeof(u32) ); - if (rsp_hdr->function == SMP_FUNCTION_DISCOVER) { - struct smp_response *smp_resp; - - smp_resp = (struct smp_response *)user_smp_buffer; - - /* - * Some expanders only report an attached SATA device, and - * not an STP target. Since the core depends on the STP - * target attribute to correctly build I/O, set the bit now - * if necessary. */ - if (smp_resp->response.discover.protocols.u.bits.attached_sata_device - && !smp_resp->response.discover.protocols.u.bits.attached_stp_target) { - smp_resp->response.discover.protocols.u.bits.attached_stp_target = 1; - - dev_dbg(scic_to_dev(sci_req->owning_controller), - "%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n", - __func__, sci_req); - } - } - /* * Don't need to copy to user space. User instead will refer to * core request's response buffer. */ diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index fc79a5b47f72..5ba3b5dca4d5 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1533,21 +1533,8 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci return SCI_SUCCESS; } -static void scic_sds_remote_device_get_info_from_smp_discover_response( - struct scic_sds_remote_device *sci_dev, - struct smp_response_discover *discover_response) -{ - /* decode discover_response to set sas_address to sci_dev. */ - sci_dev->device_address.high = - discover_response->attached_sas_address.high; - - sci_dev->device_address.low = - discover_response->attached_sas_address.low; -} - /** * scic_remote_device_ea_construct() - construct expander attached device - * @discover_response: data to build remote device * * Remote node context(s) is/are a global resource allocated by this * routine, freed by scic_remote_device_destruct(). @@ -1559,17 +1546,14 @@ static void scic_sds_remote_device_get_info_from_smp_discover_response( * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct smp_response_discover *discover_response) + struct scic_sds_remote_device *sci_dev) { struct scic_sds_controller *scic = sci_port->owning_controller; struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status; scic_remote_device_construct(sci_port, sci_dev); - - scic_sds_remote_device_get_info_from_smp_discover_response( - sci_dev, discover_response); + memcpy(&sci_dev->device_address, dev->sas_addr, SAS_ADDR_SIZE); status = scic_sds_controller_allocate_remote_node_context( scic, sci_dev, &sci_dev->rnc.remote_node_index); @@ -1605,7 +1589,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay * one another, so this code works for both situations. */ sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(sci_port), - discover_response->u2.sas1_1.negotiated_physical_link_rate); + dev->linkrate); /* / @todo Should I assign the port width by reading all of the phys on the port? */ sci_dev->device_port_width = 1; @@ -1632,117 +1616,35 @@ static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *s return sci_dev->state_handlers->start_handler(sci_dev); } -/** - * isci_remote_device_construct() - This function calls the scic remote device - * construct and start functions, it waits on the remote device start - * completion. - * @port: This parameter specifies the isci port with the remote device. - * @isci_device: This parameter specifies the isci remote device - * - * status from the scic calls, the caller to this function should clean up - * resources as appropriate. - */ -static enum sci_status isci_remote_device_construct( - struct isci_port *port, - struct isci_remote_device *isci_device) +static enum sci_status isci_remote_device_construct(struct isci_port *iport, + struct isci_remote_device *idev) { - enum sci_status status = SCI_SUCCESS; - - if (isci_device->domain_dev->parent && - dev_is_expander(isci_device->domain_dev->parent)) { - int i; - - /* struct smp_response_discover discover_response; */ - struct discover_resp discover_response; - struct domain_device *parent = - isci_device->domain_dev->parent; - - struct expander_device *parent_ex = &parent->ex_dev; - - for (i = 0; i < parent_ex->num_phys; i++) { - - struct ex_phy *phy = &parent_ex->ex_phy[i]; - - if ((phy->phy_state == PHY_VACANT) || - (phy->phy_state == PHY_NOT_PRESENT)) - continue; - - if (SAS_ADDR(phy->attached_sas_addr) - == SAS_ADDR(isci_device->domain_dev->sas_addr)) { - - discover_response.attached_dev_type - = phy->attached_dev_type; - discover_response.linkrate - = phy->linkrate; - discover_response.attached_sata_host - = phy->attached_sata_host; - discover_response.attached_sata_dev - = phy->attached_sata_dev; - discover_response.attached_sata_ps - = phy->attached_sata_ps; - discover_response.iproto - = phy->attached_iproto >> 1; - discover_response.tproto - = phy->attached_tproto >> 1; - memcpy( - discover_response.attached_sas_addr, - phy->attached_sas_addr, - SAS_ADDR_SIZE - ); - discover_response.attached_phy_id - = phy->attached_phy_id; - discover_response.change_count - = phy->phy_change_count; - discover_response.routing_attr - = phy->routing_attr; - discover_response.hmin_linkrate - = phy->phy->minimum_linkrate_hw; - discover_response.hmax_linkrate - = phy->phy->maximum_linkrate_hw; - discover_response.pmin_linkrate - = phy->phy->minimum_linkrate; - discover_response.pmax_linkrate - = phy->phy->maximum_linkrate; - } - } - - - dev_dbg(&port->isci_host->pdev->dev, - "%s: parent->dev_type = EDGE_DEV\n", - __func__); - - status = scic_remote_device_ea_construct(port->sci_port_handle, - &isci_device->sci, - (struct smp_response_discover *)&discover_response); - - } else - status = scic_remote_device_da_construct(port->sci_port_handle, - &isci_device->sci); + struct scic_sds_port *sci_port = iport->sci_port_handle; + struct isci_host *ihost = iport->isci_host; + struct domain_device *dev = idev->domain_dev; + enum sci_status status; + if (dev->parent && dev_is_expander(dev->parent)) + status = scic_remote_device_ea_construct(sci_port, &idev->sci); + else + status = scic_remote_device_da_construct(sci_port, &idev->sci); if (status != SCI_SUCCESS) { - dev_dbg(&port->isci_host->pdev->dev, - "%s: scic_remote_device_da_construct failed - " - "isci_device = %p\n", - __func__, - isci_device); + dev_dbg(&ihost->pdev->dev, "%s: construct failed: %d\n", + __func__, status); return status; } /* XXX will be killed with sci_base_object removal */ - sci_object_set_association(&isci_device->sci, isci_device); + sci_object_set_association(&idev->sci, idev); /* start the device. */ - status = scic_remote_device_start(&isci_device->sci, - ISCI_REMOTE_DEVICE_START_TIMEOUT); + status = scic_remote_device_start(&idev->sci, ISCI_REMOTE_DEVICE_START_TIMEOUT); - if (status != SCI_SUCCESS) { - dev_warn(&port->isci_host->pdev->dev, - "%s: scic_remote_device_start failed\n", - __func__); - return status; - } + if (status != SCI_SUCCESS) + dev_warn(&ihost->pdev->dev, "remote device start failed: %d\n", + status); return status; } diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 285232fd5e63..59f878f11f33 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -124,8 +124,9 @@ static void scic_sds_remote_node_context_construct_buffer( rnc->ssp.logical_port_index = scic_sds_remote_device_get_port_index(sci_dev); - rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(sci_dev->device_address.high); - rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(sci_dev->device_address.low); + /* address is always big endian, destination is always little */ + rnc->ssp.remote_sas_address_hi = swab32(sci_dev->device_address.high); + rnc->ssp.remote_sas_address_lo = swab32(sci_dev->device_address.low); rnc->ssp.nexus_loss_timer_enable = true; rnc->ssp.check_bit = false; -- cgit v1.2.3 From a3d568f0dfbb6bc786df04ad13e0b401f80e614c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 26 Apr 2011 09:41:52 -0700 Subject: isci: remove usage of sci_sas_address in scic_sds_remote_device The sas address can be retrieved from the domain device and then converted to the always little-endian format in the remote node context. Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 3 --- drivers/scsi/isci/remote_device.h | 5 ----- drivers/scsi/isci/remote_node_context.c | 8 +++++--- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 5ba3b5dca4d5..1e9e2227820a 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1501,8 +1501,6 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci sci_dev->rnc.remote_node_index = remote_node_index; - scic_sds_port_get_attached_sas_address(sci_port, &sci_dev->device_address); - if (dev->dev_type == SAS_END_DEV) sci_dev->has_ready_substate_machine = false; else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { @@ -1553,7 +1551,6 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci enum sci_status status; scic_remote_device_construct(sci_port, sci_dev); - memcpy(&sci_dev->device_address, dev->sas_addr, SAS_ADDR_SIZE); status = scic_sds_controller_allocate_remote_node_context( scic, sci_dev, &sci_dev->rnc.remote_node_index); diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 39821601022b..f0612d46fe2b 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -99,11 +99,6 @@ struct scic_sds_remote_device { */ enum sas_linkrate connection_rate; - /** - * This field contains the device SAS address. - */ - struct sci_sas_address device_address; - /** * This filed is assinged the value of true if the device is directly * attached to the port. diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 59f878f11f33..e83657d554b7 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -110,6 +110,7 @@ static void scic_sds_remote_node_context_construct_buffer( struct domain_device *dev = sci_dev_to_domain(sci_dev); union scu_remote_node_context *rnc; struct scic_sds_controller *scic; + __le64 sas_addr; scic = scic_sds_remote_device_get_controller(sci_dev); @@ -124,9 +125,10 @@ static void scic_sds_remote_node_context_construct_buffer( rnc->ssp.logical_port_index = scic_sds_remote_device_get_port_index(sci_dev); - /* address is always big endian, destination is always little */ - rnc->ssp.remote_sas_address_hi = swab32(sci_dev->device_address.high); - rnc->ssp.remote_sas_address_lo = swab32(sci_dev->device_address.low); + /* sas address is __be64, context ram format is __le64 */ + sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr)); + rnc->ssp.remote_sas_address_hi = upper_32_bits(sas_addr); + rnc->ssp.remote_sas_address_lo = lower_32_bits(sas_addr); rnc->ssp.nexus_loss_timer_enable = true; rnc->ssp.check_bit = false; -- cgit v1.2.3 From 1f4fa1f958ca678ea021b95c2799b018b2cebc9c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 26 Apr 2011 11:44:06 -0700 Subject: isci: remove scic_sds_remote_device_get_port_index Longer to type than the open-coded equivalent. Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.h | 10 +--------- drivers/scsi/isci/remote_node_context.c | 10 ++++------ 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index f0612d46fe2b..5b82b9fb7be1 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -663,14 +663,6 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab ) \ ) -/** - * scic_sds_remote_device_get_port_index() - - * - * This macro returns the port index for the devices owning port - */ -#define scic_sds_remote_device_get_port_index(sci_dev) \ - (scic_sds_port_get_index(scic_sds_remote_device_get_port(sci_dev))) - /** * scic_sds_remote_device_get_index() - * @@ -687,7 +679,7 @@ extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_tab #define scic_sds_remote_device_build_command_context(device, command) \ ((command) \ | (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \ - | (scic_sds_remote_device_get_port_index((device)) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \ + | ((device)->owning_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \ | (scic_sds_remote_device_get_index((device))) \ ) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index e83657d554b7..291df19f027b 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -108,22 +108,20 @@ static void scic_sds_remote_node_context_construct_buffer( { struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); struct domain_device *dev = sci_dev_to_domain(sci_dev); + int rni = sci_rnc->remote_node_index; union scu_remote_node_context *rnc; struct scic_sds_controller *scic; __le64 sas_addr; scic = scic_sds_remote_device_get_controller(sci_dev); - - rnc = scic_sds_controller_get_remote_node_context_buffer( - scic, sci_rnc->remote_node_index); + rnc = scic_sds_controller_get_remote_node_context_buffer(scic, rni); memset(rnc, 0, sizeof(union scu_remote_node_context) * scic_sds_remote_device_node_count(sci_dev)); - rnc->ssp.remote_node_index = sci_rnc->remote_node_index; + rnc->ssp.remote_node_index = rni; rnc->ssp.remote_node_port_width = sci_dev->device_port_width; - rnc->ssp.logical_port_index = - scic_sds_remote_device_get_port_index(sci_dev); + rnc->ssp.logical_port_index = sci_dev->owning_port->physical_port_index; /* sas address is __be64, context ram format is __le64 */ sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr)); -- cgit v1.2.3 From 3d6e428c0cd8d234bab0ac93aff9ccffacc8bc7e Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 26 Apr 2011 12:31:37 -0700 Subject: isci: removing non-working ATAPI code Removing not used / bit-rotten ATAPI code. This needs to go back and debugged at a later date. Signed-off-by: Dave Jiang [reflow against devel, delete dead sati headers] Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 4 - drivers/scsi/isci/core/sati_device.h | 156 ---- drivers/scsi/isci/core/sati_translator_sequence.h | 304 -------- drivers/scsi/isci/core/sati_types.h | 145 ---- drivers/scsi/isci/core/scic_sds_request.c | 14 - .../scsi/isci/core/scic_sds_stp_packet_request.c | 805 --------------------- .../scsi/isci/core/scic_sds_stp_packet_request.h | 39 - drivers/scsi/isci/remote_device.c | 60 -- drivers/scsi/isci/remote_device.h | 38 - drivers/scsi/isci/stp_remote_device.c | 94 --- 10 files changed, 1659 deletions(-) delete mode 100644 drivers/scsi/isci/core/sati_device.h delete mode 100644 drivers/scsi/isci/core/sati_translator_sequence.h delete mode 100644 drivers/scsi/isci/core/sati_types.h delete mode 100644 drivers/scsi/isci/core/scic_sds_stp_packet_request.c diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index ccc8c53f501d..fc50ba34b13d 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -2,9 +2,6 @@ #generation of silicon EXTRA_CFLAGS += -DSCIC_SDS_4_ENABLED -#temporary until atapi support ready -EXTRA_CFLAGS += -DDISABLE_ATAPI - EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ @@ -17,7 +14,6 @@ isci-objs := init.o phy.o request.o sata.o \ core/scic_sds_controller.o \ core/scic_sds_request.o \ core/scic_sds_stp_request.o \ - core/scic_sds_stp_packet_request.o \ core/scic_sds_port.o \ core/scic_sds_port_configuration_agent.o \ core/scic_sds_phy.o \ diff --git a/drivers/scsi/isci/core/sati_device.h b/drivers/scsi/isci/core/sati_device.h deleted file mode 100644 index 4d1cfde12cae..000000000000 --- a/drivers/scsi/isci/core/sati_device.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SATI_DEVICE_H_ -#define _SATI_DEVICE_H_ - -/** - * This file contains all of the defintions for the SATI remote device object. - * Some translations require information to be remembered on a per device - * basis. This information is stored in the object defined in this file. - * - * - */ - -#include "sati_types.h" -#include "intel_ata.h" - -/** - * enum _SATI_DEVICE_STATE - This enumeration depicts the various states - * possible for the a translation remote device object. - * - * - */ -enum sati_device_state { - SATI_DEVICE_STATE_OPERATIONAL, - SATI_DEVICE_STATE_STOPPED, - SATI_DEVICE_STATE_STANDBY, - SATI_DEVICE_STATE_IDLE, - SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED, - SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS, - SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS, - SATI_DEVICE_STATE_SEQUENCE_INCOMPLETE, - SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION - -}; - -/** - * - * - * SATI_DEVICE_CAPABILITIES These constants define the various capabilities - * that a remote device may support for which there is an impact on translation. - */ -#define SATI_DEVICE_CAP_UDMA_ENABLE 0x00000001 -#define SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE 0x00000002 -#define SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE 0x00000004 -#define SATI_DEVICE_CAP_48BIT_ENABLE 0x00000008 -#define SATI_DEVICE_CAP_DMA_FUA_ENABLE 0x00000010 -#define SATI_DEVICE_CAP_SMART_SUPPORT 0x00000020 -#define SATI_DEVICE_CAP_REMOVABLE_MEDIA 0x00000040 -#define SATI_DEVICE_CAP_SMART_ENABLE 0x00000080 -#define SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE 0x00000100 -#define SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR 0x00000200 -#define SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT 0x00000400 - - -/** - * struct sati_device - The SATI_DEVICE structure define the state of the - * remote device with respect to translation. - * - * - */ -struct sati_device { - /** - * This field simply dictates the state of the SATI device. - */ - enum sati_device_state state; - - /** - * This field indicates features supported by the remote device that - * impact translation execution. - */ - u16 capabilities; - - /** - * This field indicates the depth of the native command queue supported - * by the device. - */ - u8 ncq_depth; - - /** - * This field stores the additional sense code for a unit attention - * condition. - */ - u8 unit_attention_asc; - - /** - * This field indicates the additional sense code qualifier for a unit - * attention condition. - */ - u8 unit_attention_ascq; - -}; - -void sati_device_construct( - struct sati_device *device, - bool is_ncq_enabled, - u8 max_ncq_depth); - -void sati_device_update_capabilities( - struct sati_device *device, - struct ata_identify_device_data *identify); - -#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */ - diff --git a/drivers/scsi/isci/core/sati_translator_sequence.h b/drivers/scsi/isci/core/sati_translator_sequence.h deleted file mode 100644 index 915724c380d9..000000000000 --- a/drivers/scsi/isci/core/sati_translator_sequence.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SATI_TRANSLATOR_SEQUENCE_H_ -#define _SATI_TRANSLATOR_SEQUENCE_H_ - -/** - * This file contains all of the defintions for the SATI translator sequence. - * A translator sequence is simply a defintion for the various sequences of - * commands that occur in this translator. - * - * - */ - -#include "sati_device.h" - -/** - * enum _sati_translator_sequence_type - This enumeration defines the possible - * sequence types for the translator. - * - * - */ -enum sati_translator_sequence_type { - /* SCSI Primary Command (SPC) sequences. */ - SATI_SEQUENCE_REPORT_LUNS, - SATI_SEQUENCE_TEST_UNIT_READY, - SATI_SEQUENCE_INQUIRY_STANDARD, - SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES, - SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER, - SATI_SEQUENCE_INQUIRY_DEVICE_ID, - SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE, - SATI_SEQUENCE_MODE_SENSE_6_CACHING, - SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL, - SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR, - SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT, - SATI_SEQUENCE_MODE_SENSE_6_CONTROL, - SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES, - SATI_SEQUENCE_MODE_SENSE_10_CACHING, - SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL, - SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR, - SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT, - SATI_SEQUENCE_MODE_SENSE_10_CONTROL, - SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES, - SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING, - SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION, - SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL, - - /* Log Sense Sequences */ - SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE, - SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE, - SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE, - SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE, - - /* SCSI Block Command (SBC) sequences. */ - - SATI_SEQUENCE_READ_6, - SATI_SEQUENCE_READ_10, - SATI_SEQUENCE_READ_12, - SATI_SEQUENCE_READ_16, - - SATI_SEQUENCE_READ_CAPACITY_10, - SATI_SEQUENCE_READ_CAPACITY_16, - - SATI_SEQUENCE_SYNCHRONIZE_CACHE, - - SATI_SEQUENCE_VERIFY_10, - SATI_SEQUENCE_VERIFY_12, - SATI_SEQUENCE_VERIFY_16, - - SATI_SEQUENCE_WRITE_6, - SATI_SEQUENCE_WRITE_10, - SATI_SEQUENCE_WRITE_12, - SATI_SEQUENCE_WRITE_16, - - SATI_SEQUENCE_START_STOP_UNIT, - - SATI_SEQUENCE_REASSIGN_BLOCKS, - - /* SCSI Task Requests sequences */ - - SATI_SEQUENCE_LUN_RESET, - - SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS, - SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE, - - SATI_SEQUENCE_WRITE_LONG - -}; - -#define SATI_SEQUENCE_TYPE_READ_MIN SATI_SEQUENCE_READ_6 -#define SATI_SEQUENCE_TYPE_READ_MAX SATI_SEQUENCE_READ_16 - -/** - * - * - * SATI_SEQUENCE_STATES These constants depict the various state values - * associated with a translation sequence. - */ -#define SATI_SEQUENCE_STATE_INITIAL 0 -#define SATI_SEQUENCE_STATE_TRANSLATE_DATA 1 -#define SATI_SEQUENCE_STATE_AWAIT_RESPONSE 2 -#define SATI_SEQUENCE_STATE_FINAL 3 -#define SATI_SEQUENCE_STATE_INCOMPLETE 4 - -/** - * - * - * SATI_DATA_DIRECTIONS These constants depict the various types of data - * directions for a translation sequence. Data can flow in/out (read/write) or - * no data at all. - */ -#define SATI_DATA_DIRECTION_NONE 0 -#define SATI_DATA_DIRECTION_IN 1 -#define SATI_DATA_DIRECTION_OUT 2 - -/** - * struct SATI_MODE_SELECT_PROCESSING_STATE - This structure contains all of - * the current processing states for processing mode select 6 and 10 - * commands' parameter fields. - * - * - */ -struct sati_mode_select_processing_state { - u8 *mode_pages; - u32 mode_page_offset; - u32 mode_pages_size; - u32 size_of_data_processed; - u32 total_ata_command_sent; - u32 ata_command_sent_for_cmp; /* cmp: current mode page */ - bool current_mode_page_processed; -}; - - -enum sati_reassign_blocks_ata_command_status { - SATI_REASSIGN_BLOCKS_READY_TO_SEND, - SATI_REASSIGN_BLOCKS_COMMAND_FAIL, - SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS, -}; - -/** - * struct sati_reassign_blocks_processing_state - This structure contains all - * of the current processing states for processing reassign block command's - * parameter fields. - * - * - */ -struct sati_reassign_blocks_processing_state { - u32 lba_offset; - u32 block_lists_size; - u8 lba_size; - u32 size_of_data_processed; - u32 ata_command_sent_for_current_lba; - bool current_lba_processed; - enum sati_reassign_blocks_ata_command_status ata_command_status; - -}; - -#define SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH 12 - -/** - * struct sati_atapi_data - The SATI_ATAPI_DATA structure is for sati atapi IO - * specific data. - * - * - */ -struct sati_atapi_data { - u8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH]; -}; - -/** - * struct sati_translator_sequence - This structure contains all of the - * translation information associated with a particular request. - * - * - */ -struct sati_translator_sequence { - /** - * This field contains the sequence type determined by the SATI. - */ - u8 type; - - /** - * This field indicates the current state for the sequence. - */ - u8 state; - - /** - * This field indicates the data direction (none, read, or write) for - * the translated request. - */ - u8 data_direction; - - /** - * This field contains the SATA/ATA protocol to be utilized during - * the IO transfer. - */ - u8 protocol; - - /** - * This field is utilized for sequences requiring data translation. - * It specifies the amount of data requested by the caller from the - * operation. It's necessary, because at times the user requests less - * data than is available. Thus, we need to avoid overrunning the - * buffer. - */ - u32 allocation_length; - - /** - * This field specifies the amount of data that will actually be - * transfered across the wire for this ATA request. - */ - u32 ata_transfer_length; - - /** - * This field specifies the amount of data bytes that have been - * set in a translation sequence. It will be incremented every time - * a data byte has been set by a sati translation. - */ - u16 number_data_bytes_set; - - /** - * This field indicates whether or not the sense response has been set - * by the translation sequence. - */ - bool is_sense_response_set; - - /** - * This field specifies the remote device context for which this - * translator sequence is destined. - */ - struct sati_device *device; - - /** - * This field is utilized to provide the translator with memory space - * required for translations that utilize multiple requests. - */ - union { - u32 translated_command; - u32 move_sector_count; - u32 scratch; - struct sati_reassign_blocks_processing_state - reassign_blocks_process_state; - struct sati_mode_select_processing_state process_state; - struct sati_atapi_data sati_atapi_data; - } command_specific_data; - -}; - - - -#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */ - diff --git a/drivers/scsi/isci/core/sati_types.h b/drivers/scsi/isci/core/sati_types.h deleted file mode 100644 index b6159e06c280..000000000000 --- a/drivers/scsi/isci/core/sati_types.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SATI_TYPES_H_ -#define _SATI_TYPES_H_ - -/** - * This file contains various type definitions to be utilized with SCSI to ATA - * Translation Implementation. - * - * - */ - -/** - * enum _SATI_STATUS - This enumeration defines the possible return values from - * the SATI translation methods. - * - * - */ -enum sati_status { - /** - * This indicates that the translation was supported and occurred - * without error. - */ - SATI_SUCCESS, - - /** - * This indicates that the translation was supported, occurred without - * error, and no additional translation is necessary. This is done in - * conditions where the SCSI command doesn't require any interaction with - * the remote device. - */ - SATI_COMPLETE, - - /** - * This indicated everything SATI_COMPLETE does in addition to the response data - * not using all the memory allocated by the OS. - */ - SATI_COMPLETE_IO_DONE_EARLY, - - /** - * This indicates that translator sequence has finished some specific - * command in the sequence, but additional commands are necessary. - */ - SATI_SEQUENCE_INCOMPLETE, - - /** - * This indicates a general failure has occurred for which no further - * specification information is available. - */ - SATI_FAILURE, - - /** - * This indicates that the result of the IO request indicates a - * failure. The caller should reference the corresponding response - * data for further details. - */ - SATI_FAILURE_CHECK_RESPONSE_DATA, - - /** - * This status indicates that the supplied sequence type doesn't map - * to an existing definition. - */ - SATI_FAILURE_INVALID_SEQUENCE_TYPE, - - /** - * This status indicates that the supplied sequence state doesn't match - * the operation being requested by the user. - */ - SATI_FAILURE_INVALID_STATE - -}; - -#if (!defined(DISABLE_SATI_MODE_SENSE) \ - || !defined(DISABLE_SATI_MODE_SELECT) \ - || !defined(DISABLE_SATI_REQUEST_SENSE)) \ - -#if !defined(ENABLE_SATI_MODE_PAGES) -/** - * - * - * This macro enables the common mode page data structures and code. Currently, - * MODE SENSE, MODE SELECT, and REQUEST SENSE all make reference to this common - * code. As a result, enable the common mode page code if any of these 3 are - * being translated. - */ -#define ENABLE_SATI_MODE_PAGES -#endif /* !defined(ENABLE_SATI_MODE_PAGES) */ - -#endif /* MODE_SENSE/SELECT/REQUEST_SENSE */ - -#endif /* _SATI_TYPES_H_ */ - diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index a66e7b248b24..395080d0fc53 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -73,10 +73,6 @@ #include "scu_constants.h" #include "scu_task_context.h" -#if !defined(DISABLE_ATAPI) -#include "scic_sds_stp_packet_request.h" -#endif - /* * **************************************************************************** * * SCIC SDS IO REQUEST CONSTANTS @@ -670,16 +666,6 @@ static enum sci_status scic_io_request_construct_sata(struct scic_sds_request *s status = scic_sds_stp_ncq_request_construct(sci_req, len, dir); break; -#if !defined(DISABLE_ATAPI) - case SAT_PROTOCOL_PACKET_NON_DATA: - case SAT_PROTOCOL_PACKET_DMA_DATA_IN: - case SAT_PROTOCOL_PACKET_DMA_DATA_OUT: - case SAT_PROTOCOL_PACKET_PIO_DATA_IN: - case SAT_PROTOCOL_PACKET_PIO_DATA_OUT: - status = scic_sds_stp_packet_request_construct(sci_req); - break; -#endif - case SAT_PROTOCOL_DMA_QUEUED: case SAT_PROTOCOL_DMA: case SAT_PROTOCOL_DEVICE_DIAGNOSTIC: diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c deleted file mode 100644 index 1cb77bbb7485..000000000000 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#if !defined(DISABLE_ATAPI) - -#include "intel_ata.h" -#include "intel_sas.h" -#include "intel_sata.h" -#include "intel_sat.h" -#include "sati_translator_sequence.h" -#include "sci_base_state.h" -#include "scic_controller.h" -#include "scic_sds_controller.h" -#include "remote_device.h" -#include "scic_sds_request.h" -#include "scic_sds_stp_packet_request.h" -#include "scic_user_callback.h" -#include "sci_util.h" -#include "scu_completion_codes.h" -#include "scu_task_context.h" - - -/** - * This method will fill in the SCU Task Context for a PACKET fis. And - * construct the request STARTED sub-state machine for Packet Protocol IO. - * @sci_req: This parameter specifies the stp packet request object being - * constructed. - * - */ -enum sci_status scic_sds_stp_packet_request_construct( - struct scic_sds_request *sci_req) -{ - struct sata_fis_reg_h2d *h2d_fis = - scic_stp_io_request_get_h2d_reg_address( - sci_req - ); - - /* - * Work around, we currently only support PACKET DMA protocol, so we - * need to make change to Packet Fis features field. */ - h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA; - - scic_sds_stp_non_ncq_request_construct(sci_req); - - /* Build the Packet Fis task context structure */ - scu_stp_raw_request_construct_task_context( - (struct scic_sds_stp_request *)sci_req, - sci_req->task_context_buffer - ); - - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - &sci_req->parent.parent, - scic_sds_stp_packet_request_started_substate_table, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE - ); - - return SCI_SUCCESS; -} - - -/** - * This method will fill in the SCU Task Context for a Packet request command - * phase in PACKET DMA DATA (IN/OUT) type. The following important settings - * are utilized: -# task_type == SCU_TASK_TYPE_PACKET_DMA. This simply - * indicates that a normal request type (i.e. non-raw frame) is being - * utilized to perform task management. -# control_frame == 1. This ensures - * that the proper endianess is set so that the bytes are transmitted in the - * right order for a smp request frame. - * @sci_req: This parameter specifies the smp request object being - * constructed. - * @task_context: The task_context to be reconstruct for packet request command - * phase. - * - */ -void scu_stp_packet_request_command_phase_construct_task_context( - struct scic_sds_request *sci_req, - struct scu_task_context *task_context) -{ - void *atapi_cdb; - u32 atapi_cdb_length; - struct scic_sds_stp_request *stp_request = (struct scic_sds_stp_request *)sci_req; - - /* - * reference: SSTL 1.13.4.2 - * task_type, sata_direction */ - if (scic_cb_io_request_get_data_direction(sci_req->user_request) - == SCI_IO_REQUEST_DATA_OUT) { - task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT; - task_context->sata_direction = 0; - } else { /* todo: for NO_DATA command, we need to send out raw frame. */ - task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN; - task_context->sata_direction = 1; - } - - /* sata header */ - memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context)); - task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; - - /* - * Copy in the command IU with CDB so that the commandIU address doesn't - * change. */ - memset(sci_req->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); - - atapi_cdb = - scic_cb_stp_packet_io_request_get_cdb_address(sci_req->user_request); - - atapi_cdb_length = - scic_cb_stp_packet_io_request_get_cdb_length(sci_req->user_request); - - memcpy(((u8 *)sci_req->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); - - atapi_cdb_length = - max(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length); - - task_context->ssp_command_iu_length = - ((atapi_cdb_length % 4) == 0) ? - (atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1); - - /* task phase is set to TX_CMD */ - task_context->task_phase = 0x1; - - /* retry counter */ - task_context->stp_retry_count = 0; - - if (scic_cb_request_is_initial_construction(sci_req->user_request)) { - /* data transfer size. */ - task_context->transfer_length_bytes = - scic_cb_io_request_get_transfer_length(sci_req->user_request); - - /* setup sgl */ - scic_sds_request_build_sgl(sci_req); - } else { - /* data transfer size, need to be 4 bytes aligned. */ - task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2); - - scic_sds_stp_packet_internal_request_sense_build_sgl(sci_req); - } -} - -/** - * This method will fill in the SCU Task Context for a DATA fis containing CDB - * in Raw Frame type. The TC for previous Packet fis was already there, we - * only need to change the H2D fis content. - * @sci_req: This parameter specifies the smp request object being - * constructed. - * @task_context: The task_context to be reconstruct for packet request command - * phase. - * - */ -void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( - struct scic_sds_request *sci_req, - struct scu_task_context *task_context) -{ - void *atapi_cdb = - scic_cb_stp_packet_io_request_get_cdb_address(sci_req->user_request); - - u32 atapi_cdb_length = - scic_cb_stp_packet_io_request_get_cdb_length(sci_req->user_request); - - memset(sci_req->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); - memcpy(((u8 *)sci_req->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); - - memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context)); - task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; - - /* - * Note the data send out has to be 4 bytes aligned. Or else out hardware will - * patch non-zero bytes and cause the target device unhappy. */ - task_context->transfer_length_bytes = 12; -} - - -/* - * *@brief This methods decode the D2H status FIS and retrieve the sense data, - * then pass the sense data to user request. - * - ***@param[in] sci_req The request receive D2H status FIS. - ***@param[in] status_fis The D2H status fis to be processed. - * - */ -enum sci_status scic_sds_stp_packet_request_process_status_fis( - struct scic_sds_request *sci_req, - struct sata_fis_reg_d2h *status_fis) -{ - enum sci_status status = SCI_SUCCESS; - - /* TODO: Process the error status fis, retrieve sense data. */ - if (status_fis->status & ATA_STATUS_REG_ERROR_BIT) - status = SCI_FAILURE_IO_RESPONSE_VALID; - - return status; -} - -/* - * *@brief This methods builds sgl for internal REQUEST SENSE stp packet - * command using this request response buffer, only one sge is - * needed. - * - ***@param[in] sci_req The request receive request sense data. - * - */ -void scic_sds_stp_packet_internal_request_sense_build_sgl( - struct scic_sds_request *sds_request) -{ - void *sge; - struct scu_sgl_element_pair *scu_sgl_list = NULL; - struct scu_task_context *task_context; - dma_addr_t dma_addr; - - struct sci_ssp_response_iu *rsp_iu = - (struct sci_ssp_response_iu *)sds_request->response_buffer; - - sge = (void *)&rsp_iu->data[0]; - - task_context = - (struct scu_task_context *)sds_request->task_context_buffer; - scu_sgl_list = &task_context->sgl_pair_ab; - - dma_addr = scic_io_request_get_dma_addr(sds_request, sge); - - scu_sgl_list->A.address_upper = upper_32_bits(dma_addr); - scu_sgl_list->A.address_lower = lower_32_bits(dma_addr); - scu_sgl_list->A.length = task_context->transfer_length_bytes; - scu_sgl_list->A.address_modifier = 0; - - SCU_SGL_ZERO(scu_sgl_list->B); -} - -/** - * This method processes the completions transport layer (TL) status to - * determine if the Packet FIS was sent successfully. If the Packet FIS was - * sent successfully, then the state for the Packet request transits to - * waiting for a PIO SETUP frame. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - break; - } - - return status; -} - - -/** - * This method processes an unsolicited frame while the Packet request is - * waiting for a PIO SETUP FIS. It will release the unsolicited frame, and - * transition the request to the COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE - * state. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This method returns an indication of whether the pio setup frame was handled - * successfully or not. SCI_SUCCESS Currently this value is always returned and - * indicates successful processing of the TC response. - */ -enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - enum sci_status status; - struct sata_fis_header *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *sci_req; - - sci_req = (struct scic_sds_stp_request *)request; - - status = scic_sds_unsolicited_frame_control_get_header( - &(sci_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_header - ); - - if (status == SCI_SUCCESS) { - BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_PIO_SETUP); - - /* - * Get from the frame buffer the PIO Setup Data, although we don't need - * any info from this pio setup fis. */ - scic_sds_unsolicited_frame_control_get_buffer( - &(sci_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_buffer - ); - - /* - * Get the data from the PIO Setup - * The SCU Hardware returns first word in the frame_header and the rest - * of the data is in the frame buffer so we need to back up one dword */ - sci_req->type.packet.device_preferred_cdb_length = - (u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count; - - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame( - sci_req->parent.owning_controller, frame_index - ); - - sci_base_state_machine_change_state( - &sci_req->parent.started_substate_machine, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE - ); - } else - dev_err(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, sci_req, frame_index, status); - - return status; -} - - -/** - * This method processes the completions transport layer (TL) status to - * determine if the PACKET command data FIS was sent successfully. If - * successfully, then the state for the packet request transits to COMPLETE - * state. If not successfuly, the request transits to - * COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - u8 sat_packet_protocol = - scic_cb_request_get_sat_protocol(sci_req->user_request); - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - if (sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN - || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT - ) - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - else - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE - ); - break; - - case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): - if (scic_io_request_get_number_of_bytes_transferred(sci_req) < - scic_cb_io_request_get_transfer_length(sci_req->user_request)) { - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY - ); - - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - - status = sci_req->sci_status; - } - break; - - case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT): - /* In this case, there is no UF coming after. compelte the IO now. */ - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - - break; - - default: - if (sci_req->sci_status != SCI_SUCCESS) { /* The io status was set already. This means an UF for the status - * fis was received already. - */ - - /* - * A device suspension event is expected, we need to have the device - * coming out of suspension, then complete the IO. */ - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE - ); - - /* change the device state to ATAPI_ERROR. */ - sci_base_state_machine_change_state( - &sci_req->target_device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR - ); - - status = sci_req->sci_status; - } else { /* If receiving any non-sucess TC status, no UF received yet, then an UF for - * the status fis is coming after. - */ - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE - ); - } - break; - } - - return status; -} - - -/** - * This method processes an unsolicited frame. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This method returns an indication of whether the UF frame was handled - * successfully or not. SCI_SUCCESS Currently this value is always returned and - * indicates successful processing of the TC response. - */ -enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - enum sci_status status; - struct sata_fis_header *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *sci_req; - - sci_req = (struct scic_sds_stp_request *)request; - - status = scic_sds_unsolicited_frame_control_get_header( - &(sci_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_header - ); - - if (status == SCI_SUCCESS) { - BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_REGD2H); - - /* - * Get from the frame buffer the PIO Setup Data, although we don't need - * any info from this pio setup fis. */ - scic_sds_unsolicited_frame_control_get_buffer( - &(sci_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_buffer - ); - - scic_sds_controller_copy_sata_response( - &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer - ); - - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame( - sci_req->parent.owning_controller, frame_index - ); - } - - return status; -} - -/** - * This method processes an unsolicited frame while the packet request is - * expecting TC completion. It will process the FIS and construct sense data. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This method returns an indication of whether the UF frame was handled - * successfully or not. SCI_SUCCESS Currently this value is always returned and - * indicates successful processing of the TC response. - */ -enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; - - enum sci_status status = - scic_sds_stp_packet_request_command_phase_common_frame_handler( - request, frame_index); - - if (status == SCI_SUCCESS) { - /* The command has completed with error status from target device. */ - status = scic_sds_stp_packet_request_process_status_fis( - request, &sci_req->d2h_reg_fis); - - if (status != SCI_SUCCESS) { - scic_sds_request_set_status( - &sci_req->parent, - SCU_TASK_DONE_CHECK_RESPONSE, - status - ); - } else - scic_sds_request_set_status( - &sci_req->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - } - - return status; -} - - -/** - * This method processes an unsolicited frame while the packet request is - * expecting TC completion. It will process the FIS and construct sense data. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This method returns an indication of whether the UF frame was handled - * successfully or not. SCI_SUCCESS Currently this value is always returned and - * indicates successful processing of the TC response. - */ -enum sci_status scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - enum sci_status status = - scic_sds_stp_packet_request_command_phase_common_frame_handler( - request, frame_index); - - struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; - - if (status == SCI_SUCCESS) { - /* The command has completed with error status from target device. */ - status = scic_sds_stp_packet_request_process_status_fis( - request, &sci_req->d2h_reg_fis); - - if (status != SCI_SUCCESS) { - scic_sds_request_set_status( - request, - SCU_TASK_DONE_CHECK_RESPONSE, - status - ); - } else - scic_sds_request_set_status( - request, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - /* - * Always complete the NON_DATA command right away, no need to delay completion - * even an error status fis came from target device. */ - sci_base_state_machine_change_state( - &request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - } - - return status; -} - -enum sci_status scic_sds_stp_packet_request_started_completion_delay_complete_handler( - struct scic_sds_request *request) -{ - sci_base_state_machine_change_state(&request->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - return request->sci_status; -} - -/* --------------------------------------------------------------------------- */ - -const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[] = { - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler, - }, - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = { - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler - }, - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler, - .frame_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler - }, - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = { - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler - }, - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = { - .parent.abort_handler = scic_sds_request_started_state_abort_handler, - .parent.complete_handler = scic_sds_stp_packet_request_started_completion_delay_complete_handler, - }, -}; - -void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter( - struct sci_base_object *object) -{ - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_packet_request_started_substate_handler_table, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req - ); -} - -void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter( - struct sci_base_object *object) -{ - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_packet_request_started_substate_handler_table, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE - ); -} - -void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter( - struct sci_base_object *object) -{ - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; - u8 sat_packet_protocol = - scic_cb_request_get_sat_protocol(sci_req->user_request); - - struct scu_task_context *task_context; - enum sci_status status; - - /* - * Recycle the TC and reconstruct it for sending out data fis containing - * CDB. */ - task_context = scic_sds_controller_get_task_context_buffer( - sci_req->owning_controller, sci_req->io_tag); - - if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA) - scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( - sci_req, task_context); - else - scu_stp_packet_request_command_phase_construct_task_context( - sci_req, task_context); - - /* send the new TC out. */ - status = sci_req->owning_controller->state_handlers->parent.continue_io_handler( - &sci_req->owning_controller->parent, - &sci_req->target_device->parent, - &sci_req->parent - ); - - if (status == SCI_SUCCESS) - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_packet_request_started_substate_handler_table, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE - ); -} - -void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter( - struct sci_base_object *object) -{ - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_packet_request_started_substate_handler_table, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE - ); -} - -void scic_sds_stp_packet_request_started_completion_delay_enter( - struct sci_base_object *object) -{ - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_packet_request_started_substate_handler_table, - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE - ); -} - - -/* --------------------------------------------------------------------------- */ -const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[] = { - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter, - }, - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = { - .enter_state = scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter, - }, - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter, - }, - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = { - .enter_state = scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter, - }, - [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = { - .enter_state scic_sds_stp_packet_request_started_completion_delay_enter, - } -}; - -#endif /* !defined(DISABLE_ATAPI) */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h index f6ff5a6f6645..5d45ef6c2511 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h @@ -104,50 +104,11 @@ enum _scic_sds_stp_packet_request_started_substates { SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE, }; - - -#if !defined(DISABLE_ATAPI) -extern const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[]; -extern const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[]; -#endif /* !defined(DISABLE_ATAPI) */ - -#if !defined(DISABLE_ATAPI) -enum sci_status scic_sds_stp_packet_request_construct( - struct scic_sds_request *sci_req); -#else /* !defined(DISABLE_ATAPI) */ #define scic_sds_stp_packet_request_construct(request) SCI_FAILURE -#endif /* !defined(DISABLE_ATAPI) */ - -#if !defined(DISABLE_ATAPI) -void scu_stp_packet_request_command_phase_construct_task_context( - struct scic_sds_request *sci_req, - struct scu_task_context *task_context); -#else /* !defined(DISABLE_ATAPI) */ #define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc) -#endif /* !defined(DISABLE_ATAPI) */ - -#if !defined(DISABLE_ATAPI) -void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( - struct scic_sds_request *sci_req, - struct scu_task_context *task_context); -#else /* !defined(DISABLE_ATAPI) */ #define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc) -#endif /* !defined(DISABLE_ATAPI) */ - -#if !defined(DISABLE_ATAPI) -enum sci_status scic_sds_stp_packet_request_process_status_fis( - struct scic_sds_request *sci_req, - struct sata_fis_reg_d2h *status_fis); -#else /* !defined(DISABLE_ATAPI) */ #define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE -#endif /* !defined(DISABLE_ATAPI) */ - -#if !defined(DISABLE_ATAPI) -void scic_sds_stp_packet_internal_request_sense_build_sgl( - struct scic_sds_request *sci_req); -#else /* !defined(DISABLE_ATAPI) */ #define scic_sds_stp_packet_internal_request_sense_build_sgl(request) -#endif /* !defined(DISABLE_ATAPI) */ #endif /* _SCIC_SDS_STP_PACKET_REQUEST_H_ */ diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 1e9e2227820a..6d5ab728ccd1 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -99,15 +99,6 @@ enum sas_linkrate scic_remote_device_get_connection_rate( return sci_dev->connection_rate; } - -#if !defined(DISABLE_ATAPI) -bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev) -{ - return sci_dev->is_atapi; -} -#endif - - /** * * @@ -215,16 +206,6 @@ enum sci_status scic_sds_remote_device_start_task( sci_dev, io_request); } -/** - * - * @controller: The controller that is completing the task request. - * @sci_dev: The remote device for which the complete task handling is - * being requested. - * @io_request: The task request that is being completed. - * - * This method invokes the remote device complete task handler. enum sci_status - */ - /** * * @sci_dev: @@ -247,47 +228,6 @@ void scic_sds_remote_device_post_request( ); } -#if !defined(DISABLE_ATAPI) -/** - * - * @sci_dev: The device to be checked. - * - * This method check the signature fis of a stp device to decide whether a - * device is atapi or not. true if a device is atapi device. False if a device - * is not atapi. - */ -bool scic_sds_remote_device_is_atapi( - struct scic_sds_remote_device *sci_dev) -{ - if (!sci_dev->target_protocols.u.bits.attached_stp_target) - return false; - else if (sci_dev->is_direct_attached) { - struct scic_sds_phy *phy; - struct scic_sata_phy_properties properties; - struct sata_fis_reg_d2h *signature_fis; - phy = scic_sds_port_get_a_connected_phy(sci_dev->owning_port); - scic_sata_phy_get_properties(phy, &properties); - - /* decode the signature fis. */ - signature_fis = &(properties.signature_fis); - - if ((signature_fis->sector_count == 0x01) - && (signature_fis->lba_low == 0x01) - && (signature_fis->lba_mid == 0x14) - && (signature_fis->lba_high == 0xEB) - && ((signature_fis->device & 0x5F) == 0x00) - ) { - /* An ATA device supporting the PACKET command set. */ - return true; - } else - return false; - } else { - /* Expander supported ATAPI device is not currently supported. */ - return false; - } -} -#endif - /** * * @user_parameter: This is cast to a remote device object. diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 5b82b9fb7be1..5cceb6c5dc1d 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -105,14 +105,6 @@ struct scic_sds_remote_device { */ bool is_direct_attached; -#if !defined(DISABLE_ATAPI) - /** - * This filed is assinged the value of true if the device is an ATAPI - * device. - */ - bool is_atapi; -#endif - /** * This filed contains a pointer back to the port to which this device * is assigned. @@ -254,22 +246,7 @@ enum sci_status scic_remote_device_reset_complete( enum sas_linkrate scic_remote_device_get_connection_rate( struct scic_sds_remote_device *remote_device); -#if !defined(DISABLE_ATAPI) -/** - * scic_remote_device_is_atapi() - - * @this_device: The device whose type is to be decided. - * - * This method first decide whether a device is a stp target, then decode the - * signature fis of a DA STP device to tell whether it is a standard end disk - * or an ATAPI device. bool Indicate a device is ATAPI device or not. - */ -bool scic_remote_device_is_atapi( - struct scic_sds_remote_device *device_handle); -#else /* !defined(DISABLE_ATAPI) */ #define scic_remote_device_is_atapi(device_handle) false -#endif /* !defined(DISABLE_ATAPI) */ - - /** * enum scic_sds_remote_device_states - This enumeration depicts all the states @@ -405,16 +382,6 @@ enum scic_sds_stp_remote_device_ready_substates { */ SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR, -#if !defined(DISABLE_ATAPI) - /** - * This is the ATAPI error state for the STP ATAPI remote device. This state is - * entered when ATAPI device sends error status FIS without data while the device - * object is in CMD state. A suspension event is expected in this state. The device - * object will resume right away. - */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR, -#endif - /** * This is the READY substate indicates the device is waiting for the RESET task * coming to be recovered from certain hardware specific error. @@ -727,12 +694,7 @@ void scic_sds_remote_device_post_request( struct scic_sds_remote_device *sci_dev, u32 request); -#if !defined(DISABLE_ATAPI) -bool scic_sds_remote_device_is_atapi( - struct scic_sds_remote_device *sci_dev); -#else /* !defined(DISABLE_ATAPI) */ #define scic_sds_remote_device_is_atapi(sci_dev) false -#endif /* !defined(DISABLE_ATAPI) */ void scic_sds_remote_device_start_request( struct scic_sds_remote_device *sci_dev, diff --git a/drivers/scsi/isci/stp_remote_device.c b/drivers/scsi/isci/stp_remote_device.c index b81f21f47d2a..0fbfe52208fa 100644 --- a/drivers/scsi/isci/stp_remote_device.c +++ b/drivers/scsi/isci/stp_remote_device.c @@ -483,47 +483,6 @@ static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_com return status; } -#if !defined(DISABLE_ATAPI) -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @[in]: device The device received event. - * @[in]: event_code The event code. - * - * This method will handle the event for a ATAPI device that is in the ATAPI - * ERROR state. We pick up suspension events to handle specifically to this - * state. We resume the RNC right away. We then complete the outstanding IO to - * this device. enum sci_status - */ -enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - enum sci_status status; - - status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); - - if (status == SCI_SUCCESS) { - if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX - || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { - status = scic_sds_remote_node_context_resume( - sci_dev->rnc, - sci_dev->working_request->state_handlers->parent.complete_handler, - (void *)sci_dev->working_request - ); - } - } - - return status; -} -#endif /* !defined(DISABLE_ATAPI) */ - -/* --------------------------------------------------------------------------- */ - static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { .start_handler = scic_sds_remote_device_default_start_handler, @@ -593,25 +552,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_dev .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, -#if !defined(DISABLE_ATAPI) - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_stp_remote_device_complete_request, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, -#endif [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, @@ -764,35 +704,6 @@ static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( ); } -#if !defined(DISABLE_ATAPI) -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE - * ***************************************************************************** */ - -/** - * The enter routine to READY ATAPI ERROR substate. - * @device: This is the SCI base object which is cast into a - * struct scic_sds_remote_device object. - * - */ -void scic_sds_stp_remote_device_ready_atapi_error_substate_enter( - struct sci_base_object *device) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)device; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR - ); -} -#endif /* !defined(DISABLE_ATAPI) */ - -/* --------------------------------------------------------------------------- */ - const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, @@ -806,11 +717,6 @@ const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, }, -#if !defined(DISABLE_ATAPI) - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { - .enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter, - }, -#endif [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, }, -- cgit v1.2.3 From d37ee7e89a98a583d45fbc8bdd1943cbaf642fd0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 26 Apr 2011 13:19:53 -0700 Subject: isci: allow fallback to option-rom if efi variable retrieval fails If the scu efi driver is disabled but the option-rom is enabled (during an efi boot) allow the code to fallback to scanning legacy option-rom space for the parameters. Reported-by: Yinghai Lu Signed-off-by: Dan Williams --- drivers/scsi/isci/init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index f7ca9e8d9146..10b60ab261e1 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -475,7 +475,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic int err, i; struct isci_host *isci_host; const struct firmware *fw = NULL; - struct isci_orom *orom; + struct isci_orom *orom = NULL; char *source = "(platform)"; check_si_rev(pdev); @@ -487,7 +487,8 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic if (efi_enabled) orom = isci_get_efi_var(pdev); - else + + if (!orom) orom = isci_request_oprom(pdev); for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) { -- cgit v1.2.3 From d2d61433a85f814c7bc0b20993bb39e97f2dde76 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Thu, 21 Apr 2011 05:36:23 +0000 Subject: isci: Remove excessive log noise with expander hot-unplug We are logging excessive output when hot unplug from expander. Moving that to debug. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c6f1ffd713a8..c0ed1b28f3e5 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -183,13 +183,14 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) if (device_status != isci_ready_for_io) { /* Forces a retry from scsi mid layer. */ - dev_warn(&ihost->pdev->dev, - "%s: task %p: isci_host->status = %d, " - "device = %p; device_status = 0x%x\n\n", - __func__, - task, - isci_host_get_state(ihost), - device, device_status); + dev_dbg(&ihost->pdev->dev, + "%s: task %p: isci_host->status = %d, " + "device = %p; device_status = 0x%x\n\n", + __func__, + task, + isci_host_get_state(ihost), + device, + device_status); if (device_status == isci_ready) { /* Indicate QUEUE_FULL so that the scsi midlayer -- cgit v1.2.3 From e76d80579c2b5b4ecac107b83c22ceeb9e23bd1b Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Wed, 27 Apr 2011 17:50:50 +0000 Subject: isci: Implement SCU AFE recipe 10. Updated SCU AFE initialization values accordingly to the recipe 10. Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index c684d9ec8c97..5e8dea57b5ef 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -442,11 +442,20 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s writel(0x0081000f, &scic->scu_registers->afe.afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); + if (is_b0()) { + /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement + * Timer, PM Stagger Timer */ + writel(0x0007BFFF, &scic->scu_registers->afe.afe_pmsn_master_control2); + udelay(AFE_REGISTER_WRITE_DELAY); + } + /* Configure bias currents to normal */ if (is_a0()) writel(0x00005500, &scic->scu_registers->afe.afe_bias_control); - else + else if (is_a2()) writel(0x00005A00, &scic->scu_registers->afe.afe_bias_control); + else if (is_b0()) + writel(0x00005F00, &scic->scu_registers->afe.afe_bias_control); udelay(AFE_REGISTER_WRITE_DELAY); @@ -464,7 +473,7 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s udelay(AFE_REGISTER_WRITE_DELAY); } while ((afe_status & 0x00001000) == 0); - if (is_b0()) { + if (is_a0() || is_a2()) { /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ writel(0x7bcc96ad, &scic->scu_registers->afe.afe_pmsn_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); -- cgit v1.2.3 From 9a0fff7bf0ffd4f57fc71d8075a92008b606eb61 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Thu, 28 Apr 2011 22:06:01 +0000 Subject: isci: Removed struct sci_base_object from state machine. Changed any occurrence of struct sci_base_object into void. Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_state.h | 8 +- drivers/scsi/isci/core/sci_base_state_machine.c | 2 +- drivers/scsi/isci/core/sci_base_state_machine.h | 4 +- drivers/scsi/isci/core/scic_sds_controller.c | 32 +++---- drivers/scsi/isci/core/scic_sds_phy.c | 109 ++++++++++-------------- drivers/scsi/isci/core/scic_sds_port.c | 68 ++++++--------- drivers/scsi/isci/core/scic_sds_request.c | 31 +++---- drivers/scsi/isci/core/scic_sds_smp_request.c | 8 +- drivers/scsi/isci/core/scic_sds_ssp_request.c | 8 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 24 +++--- drivers/scsi/isci/remote_device.c | 28 +++--- drivers/scsi/isci/remote_node_context.c | 22 ++--- drivers/scsi/isci/smp_remote_device.c | 13 ++- drivers/scsi/isci/stp_remote_device.c | 16 ++-- 14 files changed, 152 insertions(+), 221 deletions(-) diff --git a/drivers/scsi/isci/core/sci_base_state.h b/drivers/scsi/isci/core/sci_base_state.h index 4272a6f116de..62d2a7c30f07 100644 --- a/drivers/scsi/isci/core/sci_base_state.h +++ b/drivers/scsi/isci/core/sci_base_state.h @@ -58,13 +58,9 @@ #include "sci_object.h" -typedef void (*sci_base_state_handler_t)( - void - ); +typedef void (*sci_base_state_handler_t)(void); -typedef void (*sci_state_transition_t)( - struct sci_base_object *base_object - ); +typedef void (*sci_state_transition_t)(void *base_object); /** * struct sci_base_state - The base state object abstracts the fields common to diff --git a/drivers/scsi/isci/core/sci_base_state_machine.c b/drivers/scsi/isci/core/sci_base_state_machine.c index bc416d504d7e..a704709eed87 100644 --- a/drivers/scsi/isci/core/sci_base_state_machine.c +++ b/drivers/scsi/isci/core/sci_base_state_machine.c @@ -100,7 +100,7 @@ static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) * */ void sci_base_state_machine_construct(struct sci_base_state_machine *sm, - struct sci_base_object *owner, + void *owner, const struct sci_base_state *state_table, u32 initial_state) { diff --git a/drivers/scsi/isci/core/sci_base_state_machine.h b/drivers/scsi/isci/core/sci_base_state_machine.h index 13f6ee80e15c..c0cf33bbecc8 100644 --- a/drivers/scsi/isci/core/sci_base_state_machine.h +++ b/drivers/scsi/isci/core/sci_base_state_machine.h @@ -94,7 +94,7 @@ struct sci_base_state_machine { * associated. It serves as a cookie to be provided to the state * enter/exit methods. */ - struct sci_base_object *state_machine_owner; + void *state_machine_owner; /** * This field simply indicates the state value for the state machine's @@ -121,7 +121,7 @@ struct sci_base_state_machine { void sci_base_state_machine_construct( struct sci_base_state_machine *this_state_machine, - struct sci_base_object *state_machine_owner, + void *state_machine_owner, const struct sci_base_state *state_table, u32 initial_state); diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 5e8dea57b5ef..135aa3e5e132 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -2882,7 +2882,7 @@ enum sci_status scic_controller_start(struct scic_sds_controller *scic, /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * @object: This is the object which is cast to a struct scic_sds_controller * object. * * This method implements the actions taken by the struct scic_sds_controller on entry @@ -2890,8 +2890,7 @@ enum sci_status scic_controller_start(struct scic_sds_controller *scic, * controllers initial state. none This function should initialze the * controller object. */ -static void scic_sds_controller_initial_state_enter( - struct sci_base_object *object) +static void scic_sds_controller_initial_state_enter(void *object) { struct scic_sds_controller *scic; @@ -2903,15 +2902,14 @@ static void scic_sds_controller_initial_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * @object: This is the object which is cast to a struct scic_sds_controller * object. * * This method implements the actions taken by the struct scic_sds_controller on exit * from the SCI_BASE_CONTROLLER_STATE_STARTING. - This function stops the * controller starting timeout timer. none */ -static inline void scic_sds_controller_starting_state_exit( - struct sci_base_object *object) +static inline void scic_sds_controller_starting_state_exit(void *object) { struct scic_sds_controller *scic = (struct scic_sds_controller *)object; @@ -2920,15 +2918,14 @@ static inline void scic_sds_controller_starting_state_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * @object: This is the object which is cast to a struct scic_sds_controller * object. * * This method implements the actions taken by the struct scic_sds_controller on entry * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the * controllers ready state. none */ -static void scic_sds_controller_ready_state_enter( - struct sci_base_object *object) +static void scic_sds_controller_ready_state_enter(void *object) { struct scic_sds_controller *scic; @@ -2941,14 +2938,13 @@ static void scic_sds_controller_ready_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * @object: This is the object which is cast to a struct scic_sds_controller * object. * * This method implements the actions taken by the struct scic_sds_controller on exit * from the SCI_BASE_CONTROLLER_STATE_READY. - This function does nothing. none */ -static void scic_sds_controller_ready_state_exit( - struct sci_base_object *object) +static void scic_sds_controller_ready_state_exit(void *object) { struct scic_sds_controller *scic; @@ -2960,7 +2956,7 @@ static void scic_sds_controller_ready_state_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller + * @object: This is the object which is cast to a struct scic_sds_controller * object. * * This method implements the actions taken by the struct scic_sds_controller on entry @@ -2968,8 +2964,7 @@ static void scic_sds_controller_ready_state_exit( * controllers ready state. - Stop the phys on this controller - Stop the ports * on this controller - Stop all of the remote devices on this controller none */ -static void scic_sds_controller_stopping_state_enter( - struct sci_base_object *object) +static void scic_sds_controller_stopping_state_enter(void *object) { struct scic_sds_controller *scic; @@ -2983,15 +2978,14 @@ static void scic_sds_controller_stopping_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct + * @object: This is the object which is cast to a struct * scic_sds_controller object. * * This funciton implements the actions taken by the struct scic_sds_controller * on exit from the SCI_BASE_CONTROLLER_STATE_STOPPING. - * This function stops the controller stopping timeout timer. */ -static inline void scic_sds_controller_stopping_state_exit( - struct sci_base_object *object) +static inline void scic_sds_controller_stopping_state_exit(void *object) { struct scic_sds_controller *scic = (struct scic_sds_controller *)object; @@ -2999,7 +2993,7 @@ static inline void scic_sds_controller_stopping_state_exit( isci_timer_stop(scic->timeout_timer); } -static void scic_sds_controller_resetting_state_enter(struct sci_base_object *object) +static void scic_sds_controller_resetting_state_enter(void *object) { struct scic_sds_controller *scic; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 09018466f993..972b977a7c11 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -1556,14 +1556,14 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_ha /** * scic_sds_phy_starting_initial_substate_enter - - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL. - The initial state * handlers are put in place for the struct scic_sds_phy object. - The state is * changed to the wait phy type event notification. none */ -static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_object *object) +static void scic_sds_phy_starting_initial_substate_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -1579,14 +1579,13 @@ static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_object /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN. - Set the * struct scic_sds_phy object state handlers for this state. none */ -static void scic_sds_phy_starting_await_ossp_en_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_ossp_en_substate_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -1599,14 +1598,14 @@ static void scic_sds_phy_starting_await_ossp_en_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - Set the * struct scic_sds_phy object state handlers for this state. none */ static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_phy *sci_phy; @@ -1619,14 +1618,13 @@ static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Set the * struct scic_sds_phy object state handlers for this state. none */ -static void scic_sds_phy_starting_await_iaf_uf_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_iaf_uf_substate_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -1639,15 +1637,14 @@ static void scic_sds_phy_starting_await_iaf_uf_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Set the * struct scic_sds_phy object state handlers for this state. - Add this phy object to * the power control queue none */ -static void scic_sds_phy_starting_await_sas_power_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_sas_power_substate_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -1665,14 +1662,13 @@ static void scic_sds_phy_starting_await_sas_power_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on exiting * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Remove the * struct scic_sds_phy object from the power control queue. none */ -static void scic_sds_phy_starting_await_sas_power_substate_exit( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_sas_power_substate_exit(void *object) { struct scic_sds_phy *sci_phy; @@ -1685,15 +1681,14 @@ static void scic_sds_phy_starting_await_sas_power_substate_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Set the * struct scic_sds_phy object state handlers for this state. - Add this phy object to * the power control queue none */ -static void scic_sds_phy_starting_await_sata_power_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_sata_power_substate_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -1711,14 +1706,13 @@ static void scic_sds_phy_starting_await_sata_power_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on exiting * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Remove the * struct scic_sds_phy object from the power control queue. none */ -static void scic_sds_phy_starting_await_sata_power_substate_exit( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_sata_power_substate_exit(void *object) { struct scic_sds_phy *sci_phy; @@ -1732,15 +1726,13 @@ static void scic_sds_phy_starting_await_sata_power_substate_exit( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This function will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - Set the * struct scic_sds_phy object state handlers for this state. none */ -static void scic_sds_phy_starting_await_sata_phy_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_sata_phy_substate_enter(void *object) { struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; @@ -1754,8 +1746,7 @@ static void scic_sds_phy_starting_await_sata_phy_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy * on exiting @@ -1763,7 +1754,7 @@ static void scic_sds_phy_starting_await_sata_phy_substate_enter( * that was started on entry to await sata phy event notification none */ static inline void scic_sds_phy_starting_await_sata_phy_substate_exit( - struct sci_base_object *object) + void *object) { struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; @@ -1772,14 +1763,13 @@ static inline void scic_sds_phy_starting_await_sata_phy_substate_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - Set the * struct scic_sds_phy object state handlers for this state. none */ -static void scic_sds_phy_starting_await_sata_speed_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_sata_speed_substate_enter(void *object) { struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; @@ -1793,8 +1783,7 @@ static void scic_sds_phy_starting_await_sata_speed_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This function will perform the actions required by the * struct scic_sds_phy on exiting @@ -1802,7 +1791,7 @@ static void scic_sds_phy_starting_await_sata_speed_substate_enter( * that was started on entry to await sata phy event notification none */ static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( - struct sci_base_object *object) + void *object) { struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; @@ -1811,8 +1800,7 @@ static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This function will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Set the @@ -1820,8 +1808,7 @@ static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( * - Start the SIGNATURE FIS * timeout timer none */ -static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) { bool continue_to_ready_state; struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; @@ -1851,8 +1838,7 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This function will perform the actions required by the * struct scic_sds_phy on exiting @@ -1860,7 +1846,7 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter( * FIS timeout timer. none */ static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( - struct sci_base_object *object) + void *object) { struct scic_sds_phy *sci_phy; @@ -1871,14 +1857,14 @@ static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. - Set the struct scic_sds_phy * object state handlers for this state. - Change base state machine to the * ready state. none */ -static void scic_sds_phy_starting_final_substate_enter(struct sci_base_object *object) +static void scic_sds_phy_starting_final_substate_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -2206,14 +2192,13 @@ static void scu_link_layer_tx_hard_reset( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state * handlers for the phy object base state machine initial state. none */ -static void scic_sds_phy_initial_state_enter( - struct sci_base_object *object) +static void scic_sds_phy_initial_state_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -2224,15 +2209,14 @@ static void scic_sds_phy_initial_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This function will perform the actions required by the struct scic_sds_phy on * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state * handlers for the phy object base state machine initial state. - The SCU * hardware is requested to stop the protocol engine. none */ -static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) +static void scic_sds_phy_stopped_state_enter(void *object) { struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); @@ -2266,7 +2250,7 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCI_BASE_PHY_STATE_STARTING. - This function sets the state @@ -2276,8 +2260,7 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_object *object) * state then the struct scic_sds_controller is informed that the phy has gone link * down. none */ -static void scic_sds_phy_starting_state_enter( - struct sci_base_object *object) +static void scic_sds_phy_starting_state_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -2307,7 +2290,7 @@ static void scic_sds_phy_starting_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCI_BASE_PHY_STATE_READY. - This function sets the state @@ -2315,8 +2298,7 @@ static void scic_sds_phy_starting_state_enter( * hardware protocol engine is resumed. - The struct scic_sds_controller is informed * that the phy object has gone link up. none */ -static void scic_sds_phy_ready_state_enter( - struct sci_base_object *object) +static void scic_sds_phy_ready_state_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -2333,14 +2315,13 @@ static void scic_sds_phy_ready_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on exiting * the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU hardware * protocol engine represented by this struct scic_sds_phy object. none */ -static void scic_sds_phy_ready_state_exit( - struct sci_base_object *object) +static void scic_sds_phy_ready_state_exit(void *object) { struct scic_sds_phy *sci_phy; @@ -2351,14 +2332,13 @@ static void scic_sds_phy_ready_state_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCI_BASE_PHY_STATE_RESETTING. - This function sets the state * handlers for the phy object base state machine resetting state. none */ -static void scic_sds_phy_resetting_state_enter( - struct sci_base_object *object) +static void scic_sds_phy_resetting_state_enter(void *object) { struct scic_sds_phy *sci_phy; @@ -2387,14 +2367,13 @@ static void scic_sds_phy_resetting_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. + * @object: This is the object which is cast to a struct scic_sds_phy object. * * This method will perform the actions required by the struct scic_sds_phy on * entering the SCI_BASE_PHY_STATE_FINAL. - This function sets the state * handlers for the phy object base state machine final state. none */ -static void scic_sds_phy_final_state_enter( - struct sci_base_object *object) +static void scic_sds_phy_final_state_enter(void *object) { struct scic_sds_phy *sci_phy; diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 057f95a79be9..1cbf1d6b2f9a 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -1623,15 +1623,14 @@ scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the * port for any ready phys. If there is at least one phy in a ready state then * the port transitions to the ready operational substate. none */ -static void scic_sds_port_ready_substate_waiting_enter( - struct sci_base_object *object) +static void scic_sds_port_ready_substate_waiting_enter(void *object) { struct scic_sds_port *sci_port = (struct scic_sds_port *)object; @@ -1654,16 +1653,14 @@ static void scic_sds_port_ready_substate_waiting_enter( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This function will perform the actions required by the struct scic_sds_port * on entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets * the state handlers for the port object, notifies the SCI User that the port * is ready, and resumes port operations. none */ -static void scic_sds_port_ready_substate_operational_enter( - struct sci_base_object *object) +static void scic_sds_port_ready_substate_operational_enter(void *object) { u32 index; struct scic_sds_port *sci_port = (struct scic_sds_port *)object; @@ -1699,14 +1696,13 @@ static void scic_sds_port_ready_substate_operational_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports * the port not ready and suspends the port task scheduler. none */ -static void scic_sds_port_ready_substate_operational_exit( - struct sci_base_object *object) +static void scic_sds_port_ready_substate_operational_exit(void *object) { struct scic_sds_port *sci_port = (struct scic_sds_port *)object; struct scic_sds_controller *scic = @@ -1731,15 +1727,13 @@ static void scic_sds_port_ready_substate_operational_exit( /** * scic_sds_port_ready_substate_configuring_enter() - - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports * the port not ready and suspends the port task scheduler. none */ -static void scic_sds_port_ready_substate_configuring_enter( - struct sci_base_object *object) +static void scic_sds_port_ready_substate_configuring_enter(void *object) { struct scic_sds_port *sci_port = (struct scic_sds_port *)object; struct scic_sds_controller *scic = @@ -1763,8 +1757,7 @@ static void scic_sds_port_ready_substate_configuring_enter( SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); } -static void scic_sds_port_ready_substate_configuring_exit( - struct sci_base_object *object) +static void scic_sds_port_ready_substate_configuring_exit(void *object) { struct scic_sds_port *sci_port = (struct scic_sds_port *)object; @@ -2253,15 +2246,14 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped * state handlers for the struct scic_sds_port object and disables the port task * scheduler in the hardware. none */ -static void scic_sds_port_stopped_state_enter( - struct sci_base_object *object) +static void scic_sds_port_stopped_state_enter(void *object) { struct scic_sds_port *sci_port; @@ -2285,14 +2277,13 @@ static void scic_sds_port_stopped_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware * port task scheduler. none */ -static void scic_sds_port_stopped_state_exit( - struct sci_base_object *object) +static void scic_sds_port_stopped_state_exit(void *object) { struct scic_sds_port *sci_port; @@ -2304,14 +2295,14 @@ static void scic_sds_port_stopped_state_exit( /** * scic_sds_port_ready_state_enter - - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state * handlers for the struct scic_sds_port object, reports the port object as * not ready and starts the ready substate machine. none */ -static void scic_sds_port_ready_state_enter(struct sci_base_object *object) +static void scic_sds_port_ready_state_enter(void *object) { struct scic_sds_controller *scic; struct scic_sds_port *sci_port; @@ -2340,7 +2331,7 @@ static void scic_sds_port_ready_state_enter(struct sci_base_object *object) sci_base_state_machine_start(&sci_port->ready_substate_machine); } -static void scic_sds_port_ready_state_exit(struct sci_base_object *object) +static void scic_sds_port_ready_state_exit(void *object) { struct scic_sds_port *sci_port; @@ -2351,14 +2342,13 @@ static void scic_sds_port_ready_state_exit(struct sci_base_object *object) /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting * state handlers for the struct scic_sds_port object. none */ -static void scic_sds_port_resetting_state_enter( - struct sci_base_object *object) +static void scic_sds_port_resetting_state_enter(void *object) { struct scic_sds_port *sci_port; @@ -2371,15 +2361,13 @@ static void scic_sds_port_resetting_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This function will perform the actions required by the * struct scic_sds_port on * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none */ -static inline void scic_sds_port_resetting_state_exit( - struct sci_base_object *object) +static inline void scic_sds_port_resetting_state_exit(void *object) { struct scic_sds_port *sci_port = (struct scic_sds_port *)object; @@ -2388,14 +2376,14 @@ static inline void scic_sds_port_resetting_state_exit( /** * - * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. + * @object: This is the void object which is cast to a + * struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping * state handlers for the struct scic_sds_port object. none */ -static void scic_sds_port_stopping_state_enter( - struct sci_base_object *object) +static void scic_sds_port_stopping_state_enter(void *object) { struct scic_sds_port *sci_port; @@ -2408,15 +2396,14 @@ static void scic_sds_port_stopping_state_enter( /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This function will perform the actions required by the * struct scic_sds_port on * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none */ static inline void -scic_sds_port_stopping_state_exit(struct sci_base_object *object) +scic_sds_port_stopping_state_exit(void *object) { struct scic_sds_port *sci_port = (struct scic_sds_port *)object; @@ -2427,15 +2414,14 @@ scic_sds_port_stopping_state_exit(struct sci_base_object *object) /** * - * @object: This is the struct sci_base_object which is cast to a - * struct scic_sds_port object. + * @object: This is the object which is cast to a struct scic_sds_port object. * * This function will perform the actions required by the * struct scic_sds_port on * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping * state handlers for the struct scic_sds_port object. none */ -static void scic_sds_port_failed_state_enter(struct sci_base_object *object) +static void scic_sds_port_failed_state_enter(void *object) { struct scic_sds_port *sci_port = (struct scic_sds_port *)object; struct isci_port *iport = sci_object_get_association(sci_port); diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 395080d0fc53..3ebfb7f8b702 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -1521,8 +1521,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han * base request is constructed. Entry into the initial state sets all handlers * for the io request object to their default handlers. none */ -static void scic_sds_request_initial_state_enter( - struct sci_base_object *object) +static void scic_sds_request_initial_state_enter(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1541,8 +1540,7 @@ static void scic_sds_request_initial_state_enter( * SCI_BASE_REQUEST_STATE_CONSTRUCTED state. The method sets the state handlers * for the the constructed state. none */ -static void scic_sds_request_constructed_state_enter( - struct sci_base_object *object) +static void scic_sds_request_constructed_state_enter(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1556,14 +1554,13 @@ static void scic_sds_request_constructed_state_enter( /** * scic_sds_request_started_state_enter() - * @object: This parameter specifies the base object for which the state - * transition is occuring. This is cast into a SCIC_SDS_IO_REQUEST object. + * transition is occurring. This is cast into a SCIC_SDS_IO_REQUEST object. * * This method implements the actions taken when entering the * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a * SCSI Task request we must enter the started substate machine. none */ -static void scic_sds_request_started_state_enter( - struct sci_base_object *object) +static void scic_sds_request_started_state_enter(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1583,15 +1580,14 @@ static void scic_sds_request_started_state_enter( /** * scic_sds_request_started_state_exit() - * @object: This parameter specifies the base object for which the state - * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST + * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST * object. * * This method implements the actions taken when exiting the * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be * to stop the started substate machine. none */ -static void scic_sds_request_started_state_exit( - struct sci_base_object *object) +static void scic_sds_request_started_state_exit(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1602,7 +1598,7 @@ static void scic_sds_request_started_state_exit( /** * scic_sds_request_completed_state_enter() - * @object: This parameter specifies the base object for which the state - * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST + * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST * object. * * This method implements the actions taken when entering the @@ -1611,8 +1607,7 @@ static void scic_sds_request_started_state_exit( * completion status and convert it to an enum sci_status to return in the * completion callback function. none */ -static void scic_sds_request_completed_state_enter( - struct sci_base_object *object) +static void scic_sds_request_completed_state_enter(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; struct scic_sds_controller *scic = @@ -1636,14 +1631,13 @@ static void scic_sds_request_completed_state_enter( /** * scic_sds_request_aborting_state_enter() - * @object: This parameter specifies the base object for which the state - * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST + * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST * object. * * This method implements the actions taken when entering the * SCI_BASE_REQUEST_STATE_ABORTING state. none */ -static void scic_sds_request_aborting_state_enter( - struct sci_base_object *object) +static void scic_sds_request_aborting_state_enter(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1660,14 +1654,13 @@ static void scic_sds_request_aborting_state_enter( /** * scic_sds_request_final_state_enter() - * @object: This parameter specifies the base object for which the state - * transition is occuring. This is cast into a SCIC_SDS_IO_REQUEST object. + * transition is occurring. This is cast into a SCIC_SDS_IO_REQUEST object. * * This method implements the actions taken when entering the * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the * state handlers in place. none */ -static void scic_sds_request_final_state_enter( - struct sci_base_object *object) +static void scic_sds_request_final_state_enter(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index d4009e57acaf..429973759776 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -518,12 +518,12 @@ static const struct scic_sds_io_request_state_handler scic_sds_smp_request_start * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This * includes setting the IO request state handlers for this sub-state. * @object: This parameter specifies the request object for which the sub-state - * change is occuring. + * change is occurring. * * none. */ static void scic_sds_smp_request_started_await_response_substate_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -539,12 +539,12 @@ static void scic_sds_smp_request_started_await_response_substate_enter( * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state. * This includes setting the SMP request state handlers for this sub-state. * @object: This parameter specifies the request object for which the sub-state - * change is occuring. + * change is occurring. * * none. */ static void scic_sds_smp_request_started_await_tc_completion_substate_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index 03676682e6ef..a7297abdb1bd 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -195,12 +195,12 @@ static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_ * sub-state. This includes setting the IO request state handlers for this * sub-state. * @object: This parameter specifies the request object for which the sub-state - * change is occuring. + * change is occurring. * * none. */ static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -216,12 +216,12 @@ static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_e * SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This * includes setting the IO request state handlers for this sub-state. * @object: This parameter specifies the request object for which the sub-state - * change is occuring. + * change is occurring. * * none. */ static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 59c5f1b8f1f6..2c6b62ee5fe8 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -564,7 +564,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start }; static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -579,8 +579,7 @@ static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( ); } -static void scic_sds_stp_request_started_non_data_await_d2h_enter( - struct sci_base_object *object) +static void scic_sds_stp_request_started_non_data_await_d2h_enter(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1214,7 +1213,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start }; static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1228,8 +1227,7 @@ static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( sci_req->target_device, sci_req); } -static void scic_sds_stp_request_started_pio_await_frame_enter( - struct sci_base_object *object) +static void scic_sds_stp_request_started_pio_await_frame_enter(void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1241,7 +1239,7 @@ static void scic_sds_stp_request_started_pio_await_frame_enter( } static void scic_sds_stp_request_started_pio_data_in_await_data_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1253,7 +1251,7 @@ static void scic_sds_stp_request_started_pio_data_in_await_data_enter( } static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1485,7 +1483,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start }; static void scic_sds_stp_request_started_udma_await_tc_completion_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1504,7 +1502,7 @@ static void scic_sds_stp_request_started_udma_await_tc_completion_enter( * will UF the D2H register FIS to complete the IO. */ static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1732,7 +1730,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start }; static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; @@ -1748,7 +1746,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completio } static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; struct scu_task_context *task_context; @@ -1775,7 +1773,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet } static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_request *sci_req = (struct scic_sds_request *)object; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 6d5ab728ccd1..b23f9a5a085d 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1099,8 +1099,7 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ } }; -static void scic_sds_remote_device_initial_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_device_initial_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; @@ -1202,8 +1201,7 @@ static void isci_remote_device_stop_complete(struct isci_host *ihost, isci_remote_device_deconstruct(ihost, idev); } -static void scic_sds_remote_device_stopped_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_device_stopped_state_enter(void *object) { struct scic_sds_remote_device *sci_dev; struct scic_sds_controller *scic; @@ -1229,7 +1227,7 @@ static void scic_sds_remote_device_stopped_state_enter( scic_sds_controller_remote_device_stopped(scic, sci_dev); } -static void scic_sds_remote_device_starting_state_enter(struct sci_base_object *object) +static void scic_sds_remote_device_starting_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); @@ -1244,7 +1242,7 @@ static void scic_sds_remote_device_starting_state_enter(struct sci_base_object * SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); } -static void scic_sds_remote_device_ready_state_enter(struct sci_base_object *object) +static void scic_sds_remote_device_ready_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); @@ -1264,8 +1262,7 @@ static void scic_sds_remote_device_ready_state_enter(struct sci_base_object *obj isci_remote_device_ready(ihost, idev); } -static void scic_sds_remote_device_ready_state_exit( - struct sci_base_object *object) +static void scic_sds_remote_device_ready_state_exit(void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); @@ -1281,8 +1278,7 @@ static void scic_sds_remote_device_ready_state_exit( } } -static void scic_sds_remote_device_stopping_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_device_stopping_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; @@ -1293,8 +1289,7 @@ static void scic_sds_remote_device_stopping_state_enter( ); } -static void scic_sds_remote_device_failed_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_device_failed_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; @@ -1305,8 +1300,7 @@ static void scic_sds_remote_device_failed_state_enter( ); } -static void scic_sds_remote_device_resetting_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_device_resetting_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; @@ -1320,16 +1314,14 @@ static void scic_sds_remote_device_resetting_state_enter( &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); } -static void scic_sds_remote_device_resetting_state_exit( - struct sci_base_object *object) +static void scic_sds_remote_device_resetting_state_exit(void *object) { struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); } -static void scic_sds_remote_device_final_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_device_final_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 291df19f027b..bc51ecf76b14 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -970,8 +970,7 @@ static void scic_sds_remote_node_context_invalidate_context_buffer( * * */ -static void scic_sds_remote_node_context_initial_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_node_context_initial_state_enter(void *object) { struct scic_sds_remote_node_context *rnc; @@ -1001,8 +1000,7 @@ static void scic_sds_remote_node_context_initial_state_enter( * * */ -static void scic_sds_remote_node_context_posting_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_node_context_posting_state_enter(void *object) { struct scic_sds_remote_node_context *sci_rnc; @@ -1022,8 +1020,7 @@ static void scic_sds_remote_node_context_posting_state_enter( * * */ -static void scic_sds_remote_node_context_invalidating_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_node_context_invalidating_state_enter(void *object) { struct scic_sds_remote_node_context *rnc; @@ -1043,8 +1040,7 @@ static void scic_sds_remote_node_context_invalidating_state_enter( * * */ -static void scic_sds_remote_node_context_resuming_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_node_context_resuming_state_enter(void *object) { struct scic_sds_remote_node_context *rnc; struct scic_sds_remote_device *sci_dev; @@ -1079,8 +1075,7 @@ static void scic_sds_remote_node_context_resuming_state_enter( * * */ -static void scic_sds_remote_node_context_ready_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_node_context_ready_state_enter(void *object) { struct scic_sds_remote_node_context *rnc; @@ -1104,8 +1099,7 @@ static void scic_sds_remote_node_context_ready_state_enter( * * */ -static void scic_sds_remote_node_context_tx_suspended_state_enter( - struct sci_base_object *object) +static void scic_sds_remote_node_context_tx_suspended_state_enter(void *object) { struct scic_sds_remote_node_context *rnc; @@ -1126,7 +1120,7 @@ static void scic_sds_remote_node_context_tx_suspended_state_enter( * */ static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_remote_node_context *rnc; @@ -1147,7 +1141,7 @@ static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( * */ static void scic_sds_remote_node_context_await_suspension_state_enter( - struct sci_base_object *object) + void *object) { struct scic_sds_remote_node_context *rnc; diff --git a/drivers/scsi/isci/smp_remote_device.c b/drivers/scsi/isci/smp_remote_device.c index 718ddaf49343..a38dc90da943 100644 --- a/drivers/scsi/isci/smp_remote_device.c +++ b/drivers/scsi/isci/smp_remote_device.c @@ -237,14 +237,14 @@ static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_dev /** * - * @object: This is the struct sci_base_object which is cast into a + * @object: This is the object which is cast into a * struct scic_sds_remote_device. * * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. * This function sets the ready cmd substate handlers and reports the device as * ready. none */ -static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_object *object) +static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); @@ -261,15 +261,14 @@ static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base /** * - * @object: This is the struct sci_base_object which is cast into a + * @object: This is the object which is cast into a * struct scic_sds_remote_device. * * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This * function sets the remote device objects ready cmd substate handlers, and * notify core user that the device is not ready. none */ -static void scic_sds_smp_remote_device_ready_cmd_substate_enter( - struct sci_base_object *object) +static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); @@ -289,12 +288,12 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter( /** * - * @object: This is the struct sci_base_object which is cast into a + * @object: This is the object which is cast into a * struct scic_sds_remote_device. * * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none */ -static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_object *object) +static void scic_sds_smp_remote_device_ready_cmd_substate_exit(void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); diff --git a/drivers/scsi/isci/stp_remote_device.c b/drivers/scsi/isci/stp_remote_device.c index 0fbfe52208fa..1e6f77331af1 100644 --- a/drivers/scsi/isci/stp_remote_device.c +++ b/drivers/scsi/isci/stp_remote_device.c @@ -601,12 +601,11 @@ scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *use /** * - * @device: This is the SCI base object which is cast into a + * @device: This is the object which is cast into a * struct scic_sds_remote_device object. * */ -static void scic_sds_stp_remote_device_ready_idle_substate_enter( - struct sci_base_object *device) +static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *device) { struct scic_sds_remote_device *sci_dev; @@ -635,7 +634,7 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter( } } -static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_object *object) +static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); @@ -653,7 +652,7 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_ SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } -static void scic_sds_stp_remote_device_ready_ncq_substate_enter(struct sci_base_object *object) +static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); @@ -662,7 +661,8 @@ static void scic_sds_stp_remote_device_ready_ncq_substate_enter(struct sci_base_ SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); } -static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_object *object) +static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( + void *object) { struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); @@ -686,12 +686,12 @@ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci /** * The enter routine to READY AWAIT RESET substate. - * @device: This is the SCI base object which is cast into a + * @device: This is the object which is cast into a * struct scic_sds_remote_device object. * */ static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( - struct sci_base_object *device) + void *device) { struct scic_sds_remote_device *sci_dev; -- cgit v1.2.3 From d3757c3aeb75259e0b86a872e98841a2ea4cb5e8 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Thu, 28 Apr 2011 22:06:06 +0000 Subject: isci: Removed sci_base_object from scic_sds_controller. The 'struct sci_base_object' was removed from the struct scic_sds_controller and was replaced by a pointer to struct isci_host. Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 44 +++++++++------------- drivers/scsi/isci/core/scic_sds_controller.h | 8 ++-- drivers/scsi/isci/core/scic_sds_phy.c | 6 +-- drivers/scsi/isci/core/scic_sds_port.c | 16 ++++---- .../isci/core/scic_sds_port_configuration_agent.c | 2 +- drivers/scsi/isci/core/scic_sds_request.c | 2 +- drivers/scsi/isci/host.c | 2 +- drivers/scsi/isci/port.c | 5 ++- drivers/scsi/isci/remote_device.c | 8 ++-- drivers/scsi/isci/sci_environment.h | 3 +- drivers/scsi/isci/smp_remote_device.c | 4 +- drivers/scsi/isci/stp_remote_device.c | 6 +-- 12 files changed, 49 insertions(+), 57 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 135aa3e5e132..d7c37dc64ac4 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -213,7 +213,7 @@ static void scic_sds_controller_power_control_timer_handler( static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) { - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; scic->power_control.timer = isci_timer_create(ihost, scic, scic_sds_controller_power_control_timer_handler); @@ -584,7 +584,7 @@ static void scic_sds_controller_transition_to_ready( struct scic_sds_controller *scic, enum sci_status status) { - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; if (scic->state_machine.current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) { @@ -602,7 +602,7 @@ static void scic_sds_controller_transition_to_ready( static void scic_sds_controller_timeout_handler(void *_scic) { struct scic_sds_controller *scic = _scic; - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct sci_base_state_machine *sm = &scic->state_machine; if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) @@ -770,7 +770,7 @@ static void scic_sds_controller_phy_startup_timeout_handler(void *_scic) static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic) { - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; scic->phy_startup_timer = isci_timer_create(ihost, scic, @@ -1796,7 +1796,7 @@ void scic_sds_controller_release_frame( */ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) { - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; u16 index; /* Default to APC mode. */ @@ -2662,7 +2662,7 @@ enum sci_status scic_controller_initialize( } - ihost = sci_object_get_association(scic); + ihost = scic->ihost; sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); @@ -2854,7 +2854,7 @@ enum sci_status scic_controller_start(struct scic_sds_controller *scic, /* Assign all the task entries to scic physical function */ scic_sds_controller_assign_task_entries(scic); - /* Now initialze the completion queue */ + /* Now initialize the completion queue */ scic_sds_controller_initialize_completion_queue(scic); /* Initialize the unsolicited frame queue for use */ @@ -2887,14 +2887,12 @@ enum sci_status scic_controller_start(struct scic_sds_controller *scic, * * This method implements the actions taken by the struct scic_sds_controller on entry * to the SCI_BASE_CONTROLLER_STATE_INITIAL. - Set the state handlers to the - * controllers initial state. none This function should initialze the + * controllers initial state. none This function should initialize the * controller object. */ static void scic_sds_controller_initial_state_enter(void *object) { - struct scic_sds_controller *scic; - - scic = (struct scic_sds_controller *)object; + struct scic_sds_controller *scic = object; sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_RESET); @@ -2911,7 +2909,7 @@ static void scic_sds_controller_initial_state_enter(void *object) */ static inline void scic_sds_controller_starting_state_exit(void *object) { - struct scic_sds_controller *scic = (struct scic_sds_controller *)object; + struct scic_sds_controller *scic = object; isci_timer_stop(scic->timeout_timer); } @@ -2927,9 +2925,7 @@ static inline void scic_sds_controller_starting_state_exit(void *object) */ static void scic_sds_controller_ready_state_enter(void *object) { - struct scic_sds_controller *scic; - - scic = (struct scic_sds_controller *)object; + struct scic_sds_controller *scic = object; /* set the default interrupt coalescence number and timeout value. */ scic_controller_set_interrupt_coalescence( @@ -2946,9 +2942,7 @@ static void scic_sds_controller_ready_state_enter(void *object) */ static void scic_sds_controller_ready_state_exit(void *object) { - struct scic_sds_controller *scic; - - scic = (struct scic_sds_controller *)object; + struct scic_sds_controller *scic = object; /* disable interrupt coalescence. */ scic_controller_set_interrupt_coalescence(scic, 0, 0); @@ -2966,9 +2960,7 @@ static void scic_sds_controller_ready_state_exit(void *object) */ static void scic_sds_controller_stopping_state_enter(void *object) { - struct scic_sds_controller *scic; - - scic = (struct scic_sds_controller *)object; + struct scic_sds_controller *scic = object; /* Stop all of the components for this controller */ scic_sds_controller_stop_phys(scic); @@ -2981,23 +2973,21 @@ static void scic_sds_controller_stopping_state_enter(void *object) * @object: This is the object which is cast to a struct * scic_sds_controller object. * - * This funciton implements the actions taken by the struct scic_sds_controller + * This function implements the actions taken by the struct scic_sds_controller * on exit from the SCI_BASE_CONTROLLER_STATE_STOPPING. - * This function stops the controller stopping timeout timer. */ static inline void scic_sds_controller_stopping_state_exit(void *object) { - struct scic_sds_controller *scic = - (struct scic_sds_controller *)object; + struct scic_sds_controller *scic = object; isci_timer_stop(scic->timeout_timer); } static void scic_sds_controller_resetting_state_enter(void *object) { - struct scic_sds_controller *scic; + struct scic_sds_controller *scic = object; - scic = container_of(object, typeof(*scic), parent); scic_sds_controller_reset_hardware(scic); sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_RESET); @@ -3051,7 +3041,7 @@ enum sci_status scic_controller_construct(struct scic_sds_controller *scic, u8 i; sci_base_state_machine_construct(&scic->state_machine, - &scic->parent, scic_sds_controller_state_table, + scic, scic_sds_controller_state_table, SCI_BASE_CONTROLLER_STATE_INITIAL); sci_base_state_machine_start(&scic->state_machine); diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index ce81286e52fd..8e3240de3d92 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -125,17 +125,17 @@ struct scic_power_control { }; +struct isci_host; /** * struct scic_sds_controller - * - * This structure represents the SCU contoller object. + * This structure represents the SCU controller object. */ struct scic_sds_controller { /** - * The field specifies that the parent object for the base controller - * is the base object itself. + * The field specifies that the peer object for the controller. */ - struct sci_base_object parent; + struct isci_host *ihost; /** * This field contains the information for the base controller state diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 972b977a7c11..3b53968abb0a 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -336,7 +336,7 @@ enum sci_status scic_sds_phy_initialize( struct scu_link_layer_registers __iomem *link_layer_registers) { struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; /* Create the SIGNATURE FIS Timeout timer for this phy */ sci_phy->sata_timeout_timer = @@ -1932,7 +1932,7 @@ scic_sds_phy_stopped_state_start_handler(struct scic_sds_phy *sci_phy) struct scic_sds_controller *scic; scic = scic_sds_phy_get_controller(sci_phy), - ihost = sci_object_get_association(scic); + ihost = scic->ihost; /* Create the SIGNATURE FIS Timeout timer for this phy */ sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, @@ -2220,7 +2220,7 @@ static void scic_sds_phy_stopped_state_enter(void *object) { struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; sci_phy = (struct scic_sds_phy *)object; diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 1cbf1d6b2f9a..857482b27ffc 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -657,7 +657,7 @@ static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, { struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct sci_sas_identify_address_frame_protocols protocols; - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; scic_sds_phy_get_attached_phy_protocols(sci_phy, &protocols); @@ -679,7 +679,7 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, { struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_port *iport = sci_object_get_association(sci_port); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_phy *iphy = sci_object_get_association(sci_phy); sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); @@ -1012,7 +1012,7 @@ void scic_sds_port_broadcast_change_received( struct scic_sds_phy *sci_phy) { struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; /* notify the user. */ isci_port_bc_change_received(ihost, sci_port, sci_phy); @@ -1666,7 +1666,7 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) struct scic_sds_port *sci_port = (struct scic_sds_port *)object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_port *iport = sci_object_get_association(sci_port); scic_sds_port_set_ready_state_handlers( @@ -1707,7 +1707,7 @@ static void scic_sds_port_ready_substate_operational_exit(void *object) struct scic_sds_port *sci_port = (struct scic_sds_port *)object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_port *iport = sci_object_get_association(sci_port); /* @@ -1738,7 +1738,7 @@ static void scic_sds_port_ready_substate_configuring_enter(void *object) struct scic_sds_port *sci_port = (struct scic_sds_port *)object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_port *iport = sci_object_get_association(sci_port); scic_sds_port_set_ready_state_handlers( @@ -1825,7 +1825,7 @@ static enum sci_status scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; enum sci_status status = SCI_SUCCESS; u32 phy_mask; @@ -2312,7 +2312,7 @@ static void scic_sds_port_ready_state_enter(void *object) sci_port = container_of(object, typeof(*sci_port), parent); scic = scic_sds_port_get_controller(sci_port); - ihost = sci_object_get_association(scic); + ihost = scic->ihost; iport = sci_object_get_association(sci_port); /* Put the ready state handlers in place though they will not be there long */ diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index a7e3833b1d56..df257ffa0f84 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -821,7 +821,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize( { enum sci_status status = SCI_SUCCESS; enum scic_port_configuration_mode mode; - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; mode = scic->oem_parameters.sds1.controller.mode_type; diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 3ebfb7f8b702..a438ea22315a 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -1612,7 +1612,7 @@ static void scic_sds_request_completed_state_enter(void *object) struct scic_sds_request *sci_req = (struct scic_sds_request *)object; struct scic_sds_controller *scic = scic_sds_request_get_controller(sci_req); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_request *ireq = sci_object_get_association(sci_req); SET_STATE_HANDLER(sci_req, diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 676bcdbfc316..55bfa3dbfb8f 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -365,7 +365,7 @@ int isci_host_init(struct isci_host *isci_host) } isci_host->core_controller = controller; - sci_object_set_association(isci_host->core_controller, isci_host); + controller->ihost = isci_host; spin_lock_init(&isci_host->state_lock); spin_lock_init(&isci_host->scic_lock); spin_lock_init(&isci_host->queue_lock); diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 430b29ed6c7e..c0916b199b70 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -68,6 +68,7 @@ #include "scic_port.h" #include "port.h" #include "request.h" +#include "core/scic_sds_controller.h" static void isci_port_change_state( struct isci_port *isci_port, @@ -472,7 +473,7 @@ void isci_port_invalid_link_up(struct scic_sds_controller *scic, struct scic_sds_port *sci_port, struct scic_sds_phy *phy) { - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; dev_warn(&ihost->pdev->dev, "Invalid link up!\n"); } @@ -481,7 +482,7 @@ void isci_port_stop_complete(struct scic_sds_controller *scic, struct scic_sds_port *sci_port, enum sci_status completion_status) { - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; dev_dbg(&ihost->pdev->dev, "Port stop complete\n"); } diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index b23f9a5a085d..bb696cf11f2c 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1211,7 +1211,7 @@ static void scic_sds_remote_device_stopped_state_enter(void *object) sci_dev = container_of(object, typeof(*sci_dev), parent); scic = scic_sds_remote_device_get_controller(sci_dev); - ihost = sci_object_get_association(scic); + ihost = scic->ihost; idev = sci_object_get_association(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, @@ -1232,7 +1232,7 @@ static void scic_sds_remote_device_starting_state_enter(void *object) struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_remote_device *idev = sci_object_get_association(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, @@ -1247,7 +1247,7 @@ static void scic_sds_remote_device_ready_state_enter(void *object) struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_remote_device *idev = sci_object_get_association(sci_dev); SET_STATE_HANDLER(sci_dev, @@ -1270,7 +1270,7 @@ static void scic_sds_remote_device_ready_state_exit(void *object) sci_base_state_machine_stop(&sci_dev->ready_substate_machine); else { struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_remote_device *idev = sci_object_get_association(sci_dev); isci_remote_device_not_ready(ihost, idev, diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index 8d57f9552e28..6be9274975d0 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -57,6 +57,7 @@ #define _SCI_ENVIRONMENT_H_ #include "isci.h" +#include "core/scic_sds_controller.h" struct scic_sds_controller; struct scic_sds_phy; @@ -65,7 +66,7 @@ struct scic_sds_remote_device; static inline struct device *scic_to_dev(struct scic_sds_controller *scic) { - struct isci_host *isci_host = sci_object_get_association(scic); + struct isci_host *isci_host = scic->ihost; return &isci_host->pdev->dev; } diff --git a/drivers/scsi/isci/smp_remote_device.c b/drivers/scsi/isci/smp_remote_device.c index a38dc90da943..aae5c80c1341 100644 --- a/drivers/scsi/isci/smp_remote_device.c +++ b/drivers/scsi/isci/smp_remote_device.c @@ -249,7 +249,7 @@ static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_remote_device *idev = sci_object_get_association(sci_dev); SET_STATE_HANDLER(sci_dev, @@ -273,7 +273,7 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_remote_device *idev = sci_object_get_association(sci_dev); BUG_ON(sci_dev->working_request == NULL); diff --git a/drivers/scsi/isci/stp_remote_device.c b/drivers/scsi/isci/stp_remote_device.c index 1e6f77331af1..c1c2f9b87cac 100644 --- a/drivers/scsi/isci/stp_remote_device.c +++ b/drivers/scsi/isci/stp_remote_device.c @@ -582,7 +582,7 @@ scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *use struct scic_sds_remote_device *sci_dev = user_cookie; struct isci_remote_device *idev = sci_object_get_association(sci_dev); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; /* * For NCQ operation we do not issue a @@ -639,7 +639,7 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_remote_device *idev = sci_object_get_association(sci_dev); BUG_ON(sci_dev->working_request == NULL); @@ -667,7 +667,7 @@ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), parent); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = sci_object_get_association(scic); + struct isci_host *ihost = scic->ihost; struct isci_remote_device *idev = sci_object_get_association(sci_dev); SET_STATE_HANDLER(sci_dev, -- cgit v1.2.3 From e1e72a00dd9db0cd2b7d106916645626f53c0382 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Thu, 28 Apr 2011 22:06:11 +0000 Subject: isci: Removed sci_base_object from scic_sds_phy. The 'struct sci_base_object' was removed from the struct scic_sds_phy and was replaced by a pointer to struct isci_phy. Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_phy.c | 83 ++++++++++------------------------ drivers/scsi/isci/core/scic_sds_phy.h | 5 +- drivers/scsi/isci/core/scic_sds_port.c | 2 +- drivers/scsi/isci/phy.c | 3 +- drivers/scsi/isci/port.c | 6 +-- drivers/scsi/isci/sci_environment.h | 2 +- 6 files changed, 33 insertions(+), 68 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 3b53968abb0a..c935c0482470 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -1565,9 +1565,7 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_ha */ static void scic_sds_phy_starting_initial_substate_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); @@ -1587,9 +1585,7 @@ static void scic_sds_phy_starting_initial_substate_enter(void *object) */ static void scic_sds_phy_starting_await_ossp_en_substate_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN @@ -1607,9 +1603,7 @@ static void scic_sds_phy_starting_await_ossp_en_substate_enter(void *object) static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN @@ -1626,9 +1620,7 @@ static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( */ static void scic_sds_phy_starting_await_iaf_uf_substate_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF @@ -1646,9 +1638,7 @@ static void scic_sds_phy_starting_await_iaf_uf_substate_enter(void *object) */ static void scic_sds_phy_starting_await_sas_power_substate_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER @@ -1670,9 +1660,7 @@ static void scic_sds_phy_starting_await_sas_power_substate_enter(void *object) */ static void scic_sds_phy_starting_await_sas_power_substate_exit(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_controller_power_control_queue_remove( scic_sds_phy_get_controller(sci_phy), sci_phy @@ -1690,9 +1678,7 @@ static void scic_sds_phy_starting_await_sas_power_substate_exit(void *object) */ static void scic_sds_phy_starting_await_sata_power_substate_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER @@ -1714,9 +1700,7 @@ static void scic_sds_phy_starting_await_sata_power_substate_enter(void *object) */ static void scic_sds_phy_starting_await_sata_power_substate_exit(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_controller_power_control_queue_remove( scic_sds_phy_get_controller(sci_phy), @@ -1734,7 +1718,7 @@ static void scic_sds_phy_starting_await_sata_power_substate_exit(void *object) */ static void scic_sds_phy_starting_await_sata_phy_substate_enter(void *object) { - struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, @@ -1756,7 +1740,7 @@ static void scic_sds_phy_starting_await_sata_phy_substate_enter(void *object) static inline void scic_sds_phy_starting_await_sata_phy_substate_exit( void *object) { - struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; isci_timer_stop(sci_phy->sata_timeout_timer); } @@ -1771,7 +1755,7 @@ static inline void scic_sds_phy_starting_await_sata_phy_substate_exit( */ static void scic_sds_phy_starting_await_sata_speed_substate_enter(void *object) { - struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, @@ -1793,7 +1777,7 @@ static void scic_sds_phy_starting_await_sata_speed_substate_enter(void *object) static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( void *object) { - struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; isci_timer_stop(sci_phy->sata_timeout_timer); } @@ -1811,7 +1795,7 @@ static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) { bool continue_to_ready_state; - struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers( sci_phy, @@ -1848,9 +1832,7 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; isci_timer_stop(sci_phy->sata_timeout_timer); } @@ -1866,9 +1848,7 @@ static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( */ static void scic_sds_phy_starting_final_substate_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = container_of(object, typeof(*sci_phy), parent); + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_starting_substate_handlers(sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); @@ -2200,9 +2180,7 @@ static void scu_link_layer_tx_hard_reset( */ static void scic_sds_phy_initial_state_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_INITIAL); } @@ -2218,12 +2196,10 @@ static void scic_sds_phy_initial_state_enter(void *object) */ static void scic_sds_phy_stopped_state_enter(void *object) { - struct scic_sds_phy *sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); struct isci_host *ihost = scic->ihost; - sci_phy = (struct scic_sds_phy *)object; - /* * @todo We need to get to the controller to place this PE in a * reset state @@ -2262,9 +2238,7 @@ static void scic_sds_phy_stopped_state_enter(void *object) */ static void scic_sds_phy_starting_state_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STARTING); @@ -2300,9 +2274,7 @@ static void scic_sds_phy_starting_state_enter(void *object) */ static void scic_sds_phy_ready_state_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_READY); @@ -2323,9 +2295,7 @@ static void scic_sds_phy_ready_state_enter(void *object) */ static void scic_sds_phy_ready_state_exit(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_suspend(sci_phy); } @@ -2340,9 +2310,7 @@ static void scic_sds_phy_ready_state_exit(void *object) */ static void scic_sds_phy_resetting_state_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_RESETTING); @@ -2375,9 +2343,7 @@ static void scic_sds_phy_resetting_state_enter(void *object) */ static void scic_sds_phy_final_state_enter(void *object) { - struct scic_sds_phy *sci_phy; - - sci_phy = (struct scic_sds_phy *)object; + struct scic_sds_phy *sci_phy = object; scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_FINAL); @@ -2412,9 +2378,8 @@ void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, struct scic_sds_port *owning_port, u8 phy_index) { - sci_phy->parent.private = NULL; sci_base_state_machine_construct(&sci_phy->state_machine, - &sci_phy->parent, + sci_phy, scic_sds_phy_state_table, SCI_BASE_PHY_STATE_INITIAL); @@ -2434,7 +2399,7 @@ void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, /* Initialize the the substate machines */ sci_base_state_machine_construct(&sci_phy->starting_substate_machine, - &sci_phy->parent, + sci_phy, scic_sds_phy_starting_substates, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); } diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index fb99d472ce60..fca95c1c027a 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -217,6 +217,7 @@ enum scic_sds_phy_protocol { SCIC_SDS_MAX_PHY_PROTOCOLS }; +struct isci_phy; /** * struct scic_sds_phy - This structure contains or references all of the data * necessary to represent the core phy object and SCU harware protocol @@ -226,9 +227,9 @@ enum scic_sds_phy_protocol { */ struct scic_sds_phy { /** - * This field depicts the parent object (struct sci_base_object) for the phy. + * This field depicts the peer object for the phy. */ - struct sci_base_object parent; + struct isci_phy *iphy; /** * This field contains the information for the base phy state machine. diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 857482b27ffc..d6339c41c392 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -680,7 +680,7 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_port *iport = sci_object_get_association(sci_port); struct isci_host *ihost = scic->ihost; - struct isci_phy *iphy = sci_object_get_association(sci_phy); + struct isci_phy *iphy = sci_phy->iphy; sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 9e081a4c8a3c..a690b6b664f7 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -57,6 +57,7 @@ #include "phy.h" #include "scic_port.h" #include "scic_config_parameters.h" +#include "core/scic_sds_phy.h" struct scic_sds_phy; extern enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy); @@ -88,8 +89,8 @@ void isci_phy_init( status = scic_controller_get_phy_handle(scic, index, &scic_phy); if (status == SCI_SUCCESS) { - sci_object_set_association(scic_phy, (void *)phy); phy->sci_phy_handle = scic_phy; + scic_phy->iphy = phy; } else dev_err(&isci_host->pdev->dev, "failed scic_controller_get_phy_handle\n"); diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index c0916b199b70..d600b09192e7 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -137,8 +137,7 @@ void isci_port_bc_change_received( struct scic_sds_port *port, struct scic_sds_phy *phy) { - struct isci_phy *isci_phy = - (struct isci_phy *)sci_object_get_association(phy); + struct isci_phy *isci_phy = phy->iphy; dev_dbg(&isci_host->pdev->dev, "%s: isci_phy = %p, sas_phy = %p\n", @@ -170,10 +169,9 @@ void isci_port_link_up( { unsigned long flags; struct scic_port_properties properties; - struct isci_phy *isci_phy - = (struct isci_phy *)sci_object_get_association(phy); struct isci_port *isci_port = (struct isci_port *)sci_object_get_association(port); + struct isci_phy *isci_phy = phy->iphy; enum sci_status call_status; unsigned long success = true; diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index 6be9274975d0..744016dffecb 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -73,7 +73,7 @@ static inline struct device *scic_to_dev(struct scic_sds_controller *scic) static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) { - struct isci_phy *iphy = sci_object_get_association(sci_phy); + struct isci_phy *iphy = sci_phy->iphy; if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host) return NULL; -- cgit v1.2.3 From 115bd1f9e8ee11744818e6eb5351d05ab6a8402e Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Thu, 28 Apr 2011 22:06:16 +0000 Subject: isci: Removed sci_base_object from scic_sds_port. The 'struct sci_base_object' was removed from the struct scic_sds_port and was replaced by a pointer to struct isci_port. Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_port.c | 55 ++++++++++++++-------------------- drivers/scsi/isci/core/scic_sds_port.h | 8 ++--- drivers/scsi/isci/port.c | 5 ++-- drivers/scsi/isci/sci_environment.h | 5 +--- 4 files changed, 29 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index d6339c41c392..3697211e7ca9 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -678,7 +678,7 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, bool do_notify_user) { struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_port *iport = sci_object_get_association(sci_port); + struct isci_port *iport = sci_port->iport; struct isci_host *ihost = scic->ihost; struct isci_phy *iphy = sci_phy->iphy; @@ -1632,7 +1632,7 @@ scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) */ static void scic_sds_port_ready_substate_waiting_enter(void *object) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; scic_sds_port_set_ready_state_handlers( sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING @@ -1663,11 +1663,11 @@ static void scic_sds_port_ready_substate_waiting_enter(void *object) static void scic_sds_port_ready_substate_operational_enter(void *object) { u32 index; - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_host *ihost = scic->ihost; - struct isci_port *iport = sci_object_get_association(sci_port); + struct isci_port *iport = sci_port->iport; scic_sds_port_set_ready_state_handlers( sci_port, @@ -1704,11 +1704,11 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) */ static void scic_sds_port_ready_substate_operational_exit(void *object) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_host *ihost = scic->ihost; - struct isci_port *iport = sci_object_get_association(sci_port); + struct isci_port *iport = sci_port->iport; /* * Kill the dummy task for this port if it has not yet posted @@ -1735,11 +1735,11 @@ static void scic_sds_port_ready_substate_operational_exit(void *object) */ static void scic_sds_port_ready_substate_configuring_enter(void *object) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_host *ihost = scic->ihost; - struct isci_port *iport = sci_object_get_association(sci_port); + struct isci_port *iport = sci_port->iport; scic_sds_port_set_ready_state_handlers( sci_port, @@ -1759,7 +1759,7 @@ static void scic_sds_port_ready_substate_configuring_enter(void *object) static void scic_sds_port_ready_substate_configuring_exit(void *object) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; scic_sds_port_suspend_port_task_scheduler(sci_port); } @@ -2255,9 +2255,7 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci */ static void scic_sds_port_stopped_state_enter(void *object) { - struct scic_sds_port *sci_port; - - sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; scic_sds_port_set_base_state_handlers( sci_port, SCI_BASE_PORT_STATE_STOPPED @@ -2285,9 +2283,7 @@ static void scic_sds_port_stopped_state_enter(void *object) */ static void scic_sds_port_stopped_state_exit(void *object) { - struct scic_sds_port *sci_port; - - sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; /* Enable and suspend the port task scheduler */ scic_sds_port_enable_port_task_scheduler(sci_port); @@ -2305,15 +2301,14 @@ static void scic_sds_port_stopped_state_exit(void *object) static void scic_sds_port_ready_state_enter(void *object) { struct scic_sds_controller *scic; - struct scic_sds_port *sci_port; + struct scic_sds_port *sci_port = object; struct isci_port *iport; struct isci_host *ihost; u32 prev_state; - sci_port = container_of(object, typeof(*sci_port), parent); scic = scic_sds_port_get_controller(sci_port); ihost = scic->ihost; - iport = sci_object_get_association(sci_port); + iport = sci_port->iport; /* Put the ready state handlers in place though they will not be there long */ scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_READY); @@ -2333,9 +2328,8 @@ static void scic_sds_port_ready_state_enter(void *object) static void scic_sds_port_ready_state_exit(void *object) { - struct scic_sds_port *sci_port; + struct scic_sds_port *sci_port = object; - sci_port = container_of(object, typeof(*sci_port), parent); sci_base_state_machine_stop(&sci_port->ready_substate_machine); scic_sds_port_invalidate_dummy_remote_node(sci_port); } @@ -2350,9 +2344,7 @@ static void scic_sds_port_ready_state_exit(void *object) */ static void scic_sds_port_resetting_state_enter(void *object) { - struct scic_sds_port *sci_port; - - sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; scic_sds_port_set_base_state_handlers( sci_port, SCI_BASE_PORT_STATE_RESETTING @@ -2369,7 +2361,7 @@ static void scic_sds_port_resetting_state_enter(void *object) */ static inline void scic_sds_port_resetting_state_exit(void *object) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; isci_timer_stop(sci_port->timer_handle); } @@ -2385,9 +2377,7 @@ static inline void scic_sds_port_resetting_state_exit(void *object) */ static void scic_sds_port_stopping_state_enter(void *object) { - struct scic_sds_port *sci_port; - - sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; scic_sds_port_set_base_state_handlers( sci_port, SCI_BASE_PORT_STATE_STOPPING @@ -2405,7 +2395,7 @@ static void scic_sds_port_stopping_state_enter(void *object) static inline void scic_sds_port_stopping_state_exit(void *object) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; + struct scic_sds_port *sci_port = object; isci_timer_stop(sci_port->timer_handle); @@ -2423,8 +2413,8 @@ scic_sds_port_stopping_state_exit(void *object) */ static void scic_sds_port_failed_state_enter(void *object) { - struct scic_sds_port *sci_port = (struct scic_sds_port *)object; - struct isci_port *iport = sci_object_get_association(sci_port); + struct scic_sds_port *sci_port = object; + struct isci_port *iport = sci_port->iport; scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_FAILED); @@ -2461,16 +2451,15 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, { u32 index; - sci_port->parent.private = NULL; sci_base_state_machine_construct(&sci_port->state_machine, - &sci_port->parent, + sci_port, scic_sds_port_state_table, SCI_BASE_PORT_STATE_STOPPED); sci_base_state_machine_start(&sci_port->state_machine); sci_base_state_machine_construct(&sci_port->ready_substate_machine, - &sci_port->parent, + sci_port, scic_sds_port_ready_substate_table, SCIC_SDS_PORT_READY_SUBSTATE_WAITING); diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 59c76cd3902f..2253a2ced969 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -151,17 +151,17 @@ enum scic_sds_port_states { }; +struct isci_port; /** - * struct scic_sds_port - + * struct scic_sds_port * * The core port object provides the the abstraction for an SCU port. */ struct scic_sds_port { /** - * The field specifies that the parent object for the base controller - * is the base object itself. + * The field specifies the peer object for the port. */ - struct sci_base_object parent; + struct isci_port *iport; /** * This field contains the information for the base port state machine. diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index d600b09192e7..30d6ad895ccf 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -100,8 +100,8 @@ void isci_port_init( isci_port_change_state(isci_port, isci_freed); (void)scic_controller_get_port_handle(controller, index, &scic_port); - sci_object_set_association(scic_port, isci_port); isci_port->sci_port_handle = scic_port; + scic_port->iport = isci_port; } @@ -169,9 +169,8 @@ void isci_port_link_up( { unsigned long flags; struct scic_port_properties properties; - struct isci_port *isci_port - = (struct isci_port *)sci_object_get_association(port); struct isci_phy *isci_phy = phy->iphy; + struct isci_port *isci_port = port->iport; enum sci_status call_status; unsigned long success = true; diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index 744016dffecb..3fb54ddaee1a 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -59,9 +59,6 @@ #include "isci.h" #include "core/scic_sds_controller.h" -struct scic_sds_controller; -struct scic_sds_phy; -struct scic_sds_port; struct scic_sds_remote_device; static inline struct device *scic_to_dev(struct scic_sds_controller *scic) @@ -83,7 +80,7 @@ static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port) { - struct isci_port *iport = sci_object_get_association(sci_port); + struct isci_port *iport = sci_port->iport; if (!iport || !iport->isci_host) return NULL; -- cgit v1.2.3 From 5d937e966d383c4012c19b0e47dc196ba505eb19 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Thu, 28 Apr 2011 22:06:21 +0000 Subject: isci: Removed sci_base_object from scic_sds_remote_device. The 'struct sci_base_object' was removed from the struct scic_sds_remote_device. Signed-off-by: Maciej Patelczyk [cleaned up sci_dev_to_idev] Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 47 ++++++++++++++--------------------- drivers/scsi/isci/remote_device.h | 15 ++++++----- drivers/scsi/isci/sci_environment.h | 7 +++--- drivers/scsi/isci/smp_remote_device.c | 13 ++++------ drivers/scsi/isci/stp_remote_device.c | 19 ++++++-------- 5 files changed, 42 insertions(+), 59 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index bb696cf11f2c..3fc66b2a5992 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1101,9 +1101,8 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ static void scic_sds_remote_device_initial_state_enter(void *object) { - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = object; - sci_dev = container_of(object, typeof(*sci_dev), parent); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); @@ -1203,16 +1202,15 @@ static void isci_remote_device_stop_complete(struct isci_host *ihost, static void scic_sds_remote_device_stopped_state_enter(void *object) { - struct scic_sds_remote_device *sci_dev; + struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic; struct isci_remote_device *idev; struct isci_host *ihost; u32 prev_state; - sci_dev = container_of(object, typeof(*sci_dev), parent); scic = scic_sds_remote_device_get_controller(sci_dev); ihost = scic->ihost; - idev = sci_object_get_association(sci_dev); + idev = sci_dev_to_idev(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); @@ -1229,11 +1227,10 @@ static void scic_sds_remote_device_stopped_state_enter(void *object) static void scic_sds_remote_device_starting_state_enter(void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_STARTING); @@ -1244,11 +1241,10 @@ static void scic_sds_remote_device_starting_state_enter(void *object) static void scic_sds_remote_device_ready_state_enter(void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, @@ -1264,14 +1260,13 @@ static void scic_sds_remote_device_ready_state_enter(void *object) static void scic_sds_remote_device_ready_state_exit(void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; if (sci_dev->has_ready_substate_machine) sci_base_state_machine_stop(&sci_dev->ready_substate_machine); else { struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); @@ -1280,7 +1275,7 @@ static void scic_sds_remote_device_ready_state_exit(void *object) static void scic_sds_remote_device_stopping_state_enter(void *object) { - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = object; SET_STATE_HANDLER( sci_dev, @@ -1291,7 +1286,7 @@ static void scic_sds_remote_device_stopping_state_enter(void *object) static void scic_sds_remote_device_failed_state_enter(void *object) { - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = object; SET_STATE_HANDLER( sci_dev, @@ -1302,7 +1297,7 @@ static void scic_sds_remote_device_failed_state_enter(void *object) static void scic_sds_remote_device_resetting_state_enter(void *object) { - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = object; SET_STATE_HANDLER( sci_dev, @@ -1316,14 +1311,14 @@ static void scic_sds_remote_device_resetting_state_enter(void *object) static void scic_sds_remote_device_resetting_state_exit(void *object) { - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = object; scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); } static void scic_sds_remote_device_final_state_enter(void *object) { - struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; + struct scic_sds_remote_device *sci_dev = object; SET_STATE_HANDLER( sci_dev, @@ -1377,11 +1372,10 @@ static void scic_remote_device_construct(struct scic_sds_port *sci_port, { sci_dev->owning_port = sci_port; sci_dev->started_request_count = 0; - sci_dev->parent.private = NULL; sci_base_state_machine_construct( &sci_dev->state_machine, - &sci_dev->parent, + sci_dev, scic_sds_remote_device_state_table, SCI_BASE_REMOTE_DEVICE_STATE_INITIAL ); @@ -1440,7 +1434,7 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci sci_base_state_machine_construct( &sci_dev->ready_substate_machine, - &sci_dev->parent, + sci_dev, scic_sds_stp_remote_device_ready_substate_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } else if (dev_is_expander(dev)) { @@ -1449,7 +1443,7 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci /* add the SMP ready substate machine construction here */ sci_base_state_machine_construct( &sci_dev->ready_substate_machine, - &sci_dev->parent, + sci_dev, scic_sds_smp_remote_device_ready_substate_table, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } else @@ -1497,7 +1491,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci /* add the SMP ready substate machine construction here */ sci_base_state_machine_construct( &sci_dev->ready_substate_machine, - &sci_dev->parent, + sci_dev, scic_sds_smp_remote_device_ready_substate_table, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { @@ -1505,7 +1499,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci sci_base_state_machine_construct( &sci_dev->ready_substate_machine, - &sci_dev->parent, + sci_dev, scic_sds_stp_remote_device_ready_substate_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } @@ -1565,9 +1559,6 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport, return status; } - /* XXX will be killed with sci_base_object removal */ - sci_object_set_association(&idev->sci, idev); - /* start the device. */ status = scic_remote_device_start(&idev->sci, ISCI_REMOTE_DEVICE_START_TIMEOUT); diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 5cceb6c5dc1d..62623c766388 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -74,12 +74,6 @@ enum scic_remote_device_not_ready_reason_code { }; struct scic_sds_remote_device { - /** - * The field specifies that the parent object for the base remote - * device is the base object itself. - */ - struct sci_base_object parent; - /** * This field contains the information for the base remote device state * machine. @@ -417,11 +411,16 @@ static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_n return sci_dev; } -static inline struct domain_device *sci_dev_to_domain(struct scic_sds_remote_device *sci_dev) +static inline struct isci_remote_device *sci_dev_to_idev(struct scic_sds_remote_device *sci_dev) { struct isci_remote_device *idev = container_of(sci_dev, typeof(*idev), sci); - return idev->domain_dev; + return idev; +} + +static inline struct domain_device *sci_dev_to_domain(struct scic_sds_remote_device *sci_dev) +{ + return sci_dev_to_idev(sci_dev)->domain_dev; } static inline bool dev_is_expander(struct domain_device *dev) diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index 3fb54ddaee1a..41636c34da9e 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -59,7 +59,6 @@ #include "isci.h" #include "core/scic_sds_controller.h" -struct scic_sds_remote_device; static inline struct device *scic_to_dev(struct scic_sds_controller *scic) { @@ -88,9 +87,11 @@ static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port) return &iport->isci_host->pdev->dev; } -static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev) +static inline struct device *scirdev_to_dev( + struct scic_sds_remote_device *sci_dev) { - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = + container_of(sci_dev, typeof(*idev), sci); if (!idev || !idev->isci_port || !idev->isci_port->isci_host) return NULL; diff --git a/drivers/scsi/isci/smp_remote_device.c b/drivers/scsi/isci/smp_remote_device.c index aae5c80c1341..45340a5c99c7 100644 --- a/drivers/scsi/isci/smp_remote_device.c +++ b/drivers/scsi/isci/smp_remote_device.c @@ -246,11 +246,10 @@ static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_dev */ static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_smp_remote_device_ready_substate_handler_table, @@ -270,11 +269,10 @@ static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) */ static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); BUG_ON(sci_dev->working_request == NULL); @@ -295,8 +293,7 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) */ static void scic_sds_smp_remote_device_ready_cmd_substate_exit(void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; sci_dev->working_request = NULL; } diff --git a/drivers/scsi/isci/stp_remote_device.c b/drivers/scsi/isci/stp_remote_device.c index c1c2f9b87cac..d86976469428 100644 --- a/drivers/scsi/isci/stp_remote_device.c +++ b/drivers/scsi/isci/stp_remote_device.c @@ -580,7 +580,7 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *user_cookie) { struct scic_sds_remote_device *sci_dev = user_cookie; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic->ihost; @@ -607,9 +607,7 @@ scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *use */ static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *device) { - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)device; + struct scic_sds_remote_device *sci_dev = device; SET_STATE_HANDLER( sci_dev, @@ -636,11 +634,10 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *device) static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); BUG_ON(sci_dev->working_request == NULL); @@ -654,8 +651,7 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; SET_STATE_HANDLER(sci_dev, scic_sds_stp_remote_device_ready_substate_handler_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); @@ -664,11 +660,10 @@ static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object) static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( void *object) { - struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), - parent); + struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_object_get_association(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_stp_remote_device_ready_substate_handler_table, -- cgit v1.2.3 From af23e85737253624cde84704008be40355ff6922 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Thu, 28 Apr 2011 22:06:26 +0000 Subject: isci: Removed sci_base_object from scic_sds_remote_node_context. The 'struct sci_base_object' was removed from the struct scic_sds_remote_node_context. Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 2 -- drivers/scsi/isci/remote_node_context.c | 33 +++++++++------------------------ drivers/scsi/isci/remote_node_context.h | 5 ----- 3 files changed, 9 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 3fc66b2a5992..2bbc7c20c400 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1386,8 +1386,6 @@ static void scic_remote_device_construct(struct scic_sds_port *sci_port, scic_sds_remote_node_context_construct(&sci_dev->rnc, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); - - sci_object_set_association(&sci_dev->rnc, sci_dev); } /** diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index bc51ecf76b14..49d2dc5374f4 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -972,9 +972,7 @@ static void scic_sds_remote_node_context_invalidate_context_buffer( */ static void scic_sds_remote_node_context_initial_state_enter(void *object) { - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; + struct scic_sds_remote_node_context *rnc = object; SET_STATE_HANDLER( rnc, @@ -1002,9 +1000,7 @@ static void scic_sds_remote_node_context_initial_state_enter(void *object) */ static void scic_sds_remote_node_context_posting_state_enter(void *object) { - struct scic_sds_remote_node_context *sci_rnc; - - sci_rnc = (struct scic_sds_remote_node_context *)object; + struct scic_sds_remote_node_context *sci_rnc = object; SET_STATE_HANDLER( sci_rnc, @@ -1022,9 +1018,7 @@ static void scic_sds_remote_node_context_posting_state_enter(void *object) */ static void scic_sds_remote_node_context_invalidating_state_enter(void *object) { - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; + struct scic_sds_remote_node_context *rnc = object; SET_STATE_HANDLER( rnc, @@ -1042,11 +1036,10 @@ static void scic_sds_remote_node_context_invalidating_state_enter(void *object) */ static void scic_sds_remote_node_context_resuming_state_enter(void *object) { - struct scic_sds_remote_node_context *rnc; + struct scic_sds_remote_node_context *rnc = object; struct scic_sds_remote_device *sci_dev; struct domain_device *dev; - rnc = (struct scic_sds_remote_node_context *)object; sci_dev = rnc_to_dev(rnc); dev = sci_dev_to_domain(sci_dev); @@ -1077,9 +1070,7 @@ static void scic_sds_remote_node_context_resuming_state_enter(void *object) */ static void scic_sds_remote_node_context_ready_state_enter(void *object) { - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; + struct scic_sds_remote_node_context *rnc = object; SET_STATE_HANDLER( rnc, @@ -1101,9 +1092,7 @@ static void scic_sds_remote_node_context_ready_state_enter(void *object) */ static void scic_sds_remote_node_context_tx_suspended_state_enter(void *object) { - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; + struct scic_sds_remote_node_context *rnc = object; SET_STATE_HANDLER( rnc, @@ -1122,9 +1111,7 @@ static void scic_sds_remote_node_context_tx_suspended_state_enter(void *object) static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( void *object) { - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; + struct scic_sds_remote_node_context *rnc = object; SET_STATE_HANDLER( rnc, @@ -1143,9 +1130,7 @@ static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( static void scic_sds_remote_node_context_await_suspension_state_enter( void *object) { - struct scic_sds_remote_node_context *rnc; - - rnc = (struct scic_sds_remote_node_context *)object; + struct scic_sds_remote_node_context *rnc = object; SET_STATE_HANDLER( rnc, @@ -1193,7 +1178,7 @@ void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context sci_base_state_machine_construct( &rnc->state_machine, - &rnc->parent, + rnc, scic_sds_remote_node_context_state_table, SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE ); diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index b3f2546090dd..bc7914beb0c5 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -226,11 +226,6 @@ enum scic_sds_remote_node_context_destination_state { * the silicon RNC. */ struct scic_sds_remote_node_context { - /* - * parent object - */ - struct sci_base_object parent; - /** * This field indicates the remote node index (RNI) associated with * this RNC. -- cgit v1.2.3 From 890cae9b8a7defd87feb1ec77a2affd25bd59cce Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Thu, 28 Apr 2011 22:06:31 +0000 Subject: isci: Removed sci_base_object from scic_sds_request. The 'struct sci_base_object' was removed from the struct scic_sds_request and was replaced by a pointer to struct isci_request. Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_util.c | 5 ++-- drivers/scsi/isci/core/scic_sds_request.c | 42 +++++++++++---------------- drivers/scsi/isci/core/scic_sds_request.h | 6 ++-- drivers/scsi/isci/core/scic_sds_smp_request.c | 6 ++-- drivers/scsi/isci/core/scic_sds_ssp_request.c | 4 +-- drivers/scsi/isci/core/scic_sds_stp_request.c | 30 +++++++++---------- drivers/scsi/isci/request.c | 4 +-- drivers/scsi/isci/stp_remote_device.c | 6 ++-- drivers/scsi/isci/task.c | 7 ++--- 9 files changed, 48 insertions(+), 62 deletions(-) diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c index cb3e9f73828d..ebf0ed919a9f 100644 --- a/drivers/scsi/isci/core/sci_util.c +++ b/drivers/scsi/isci/core/sci_util.c @@ -72,7 +72,7 @@ void scic_word_copy_with_swap( void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr) { - struct isci_request *ireq = sci_object_get_association(sci_req); + struct isci_request *ireq = sci_req->ireq; dma_addr_t offset; BUG_ON(phys_addr < ireq->request_daddr); @@ -87,8 +87,7 @@ void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t ph dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request, void *virt_addr) { - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sds_request); + struct isci_request *isci_request = sds_request->ireq; char *requested_addr = (char *)virt_addr; char *base_addr = (char *)isci_request; diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index a438ea22315a..fba642881092 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -253,8 +253,7 @@ static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( */ void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) { - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sds_request); + struct isci_request *isci_request = sds_request->ireq; struct isci_host *isci_host = isci_request->isci_host; struct sas_task *task = isci_request_access_task(isci_request); struct scatterlist *sg = NULL; @@ -359,8 +358,7 @@ static void scic_sds_io_request_build_ssp_command_iu( struct sci_ssp_command_iu *command_frame; u32 cdb_length; u32 *cdb_buffer; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sds_request); + struct isci_request *isci_request = sds_request->ireq; command_frame = (struct sci_ssp_command_iu *)sds_request->command_buffer; @@ -403,8 +401,7 @@ static void scic_sds_task_request_build_ssp_task_iu( struct scic_sds_request *sds_request) { struct sci_ssp_task_iu *command_frame; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sds_request); + struct isci_request *isci_request = sds_request->ireq; command_frame = (struct sci_ssp_task_iu *)sds_request->command_buffer; @@ -700,8 +697,7 @@ u32 scic_io_request_get_object_size(void) enum sci_status scic_io_request_construct_basic_ssp( struct scic_sds_request *sci_req) { - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sci_req); + struct isci_request *isci_request = sci_req->ireq; sci_req->protocol = SCIC_SSP_PROTOCOL; @@ -744,8 +740,7 @@ enum sci_status scic_io_request_construct_basic_sata( u32 len; enum dma_data_direction dir; bool copy = false; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sci_req); + struct isci_request *isci_request = sci_req->ireq; struct sas_task *task = isci_request_access_task(isci_request); stp_req = container_of(sci_req, typeof(*stp_req), parent); @@ -772,8 +767,7 @@ enum sci_status scic_task_request_construct_sata( { enum sci_status status; u8 sat_protocol; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sci_req); + struct isci_request *isci_request = sci_req->ireq; sat_protocol = isci_sata_get_sat_protocol(isci_request); @@ -1002,8 +996,7 @@ void scic_sds_io_request_copy_response(struct scic_sds_request *sds_request) u32 user_response_length; u32 core_response_length; struct sci_ssp_response_iu *ssp_response; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(sds_request); + struct isci_request *isci_request = sds_request->ireq; ssp_response = (struct sci_ssp_response_iu *)sds_request->response_buffer; @@ -1523,7 +1516,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han */ static void scic_sds_request_initial_state_enter(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1542,7 +1535,7 @@ static void scic_sds_request_initial_state_enter(void *object) */ static void scic_sds_request_constructed_state_enter(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1562,7 +1555,7 @@ static void scic_sds_request_constructed_state_enter(void *object) */ static void scic_sds_request_started_state_enter(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1589,7 +1582,7 @@ static void scic_sds_request_started_state_enter(void *object) */ static void scic_sds_request_started_state_exit(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; if (sci_req->has_started_substate_machine == true) sci_base_state_machine_stop(&sci_req->started_substate_machine); @@ -1609,11 +1602,11 @@ static void scic_sds_request_started_state_exit(void *object) */ static void scic_sds_request_completed_state_enter(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; struct scic_sds_controller *scic = scic_sds_request_get_controller(sci_req); struct isci_host *ihost = scic->ihost; - struct isci_request *ireq = sci_object_get_association(sci_req); + struct isci_request *ireq = sci_req->ireq; SET_STATE_HANDLER(sci_req, scic_sds_request_state_handler_table, @@ -1639,7 +1632,7 @@ static void scic_sds_request_completed_state_enter(void *object) */ static void scic_sds_request_aborting_state_enter(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; /* Setting the abort bit in the Task Context is required by the silicon. */ sci_req->task_context_buffer->abort = 1; @@ -1662,7 +1655,7 @@ static void scic_sds_request_aborting_state_enter(void *object) */ static void scic_sds_request_final_state_enter(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1699,8 +1692,7 @@ static void scic_sds_general_request_construct(struct scic_sds_controller *scic, void *user_io_request_object, struct scic_sds_request *sci_req) { - sci_req->parent.private = NULL; - sci_base_state_machine_construct(&sci_req->state_machine, &sci_req->parent, + sci_base_state_machine_construct(&sci_req->state_machine, sci_req, scic_sds_request_state_table, SCI_BASE_REQUEST_STATE_INITIAL); sci_base_state_machine_start(&sci_req->state_machine); @@ -1790,7 +1782,7 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, /* Construct the started sub-state machine. */ sci_base_state_machine_construct( &sci_req->started_substate_machine, - &sci_req->parent, + sci_req, scic_sds_io_request_started_task_mgmt_substate_table, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION ); diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 0bb1da81ce85..11d5a3ea9da3 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -118,6 +118,7 @@ enum scic_sds_smp_request_started_substates { SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, }; +struct isci_request; /** * struct scic_sds_request - This structure contains or references all of * the data necessary to process a task management or normal IO request. @@ -126,10 +127,9 @@ enum scic_sds_smp_request_started_substates { */ struct scic_sds_request { /** - * The field specifies that the parent object for the base request is the - * base object itself. + * The field specifies that the peer object for the request object. */ - struct sci_base_object parent; + struct isci_request *ireq; /** * This field contains the information for the base request state machine. diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 429973759776..ba29192f7fd0 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -525,7 +525,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_smp_request_start static void scic_sds_smp_request_started_await_response_substate_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -546,7 +546,7 @@ static void scic_sds_smp_request_started_await_response_substate_enter( static void scic_sds_smp_request_started_await_tc_completion_substate_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -590,7 +590,7 @@ enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) /* Construct the started sub-state machine. */ sci_base_state_machine_construct( &sci_req->started_substate_machine, - &sci_req->parent, + sci_req, scic_sds_smp_request_started_substate_table, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE ); diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index a7297abdb1bd..7183ae331d2e 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -202,7 +202,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_ static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -223,7 +223,7 @@ static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_e static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 2c6b62ee5fe8..ec215463092a 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -566,7 +566,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -581,7 +581,7 @@ static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( static void scic_sds_stp_request_started_non_data_await_d2h_enter(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -611,7 +611,7 @@ enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); sci_base_state_machine_construct(&sci_req->started_substate_machine, - &sci_req->parent, + sci_req, scic_sds_stp_request_started_non_data_substate_table, SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE); @@ -1215,7 +1215,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1229,7 +1229,7 @@ static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( static void scic_sds_stp_request_started_pio_await_frame_enter(void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1241,7 +1241,7 @@ static void scic_sds_stp_request_started_pio_await_frame_enter(void *object) static void scic_sds_stp_request_started_pio_data_in_await_data_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1253,7 +1253,7 @@ static void scic_sds_stp_request_started_pio_data_in_await_data_enter( static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1311,7 +1311,7 @@ enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_ } sci_base_state_machine_construct(&sci_req->started_substate_machine, - &sci_req->parent, + sci_req, scic_sds_stp_request_started_pio_substate_table, SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE); @@ -1485,7 +1485,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start static void scic_sds_stp_request_started_udma_await_tc_completion_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1504,7 +1504,7 @@ static void scic_sds_stp_request_started_udma_await_tc_completion_enter( static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1535,7 +1535,7 @@ enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci sci_base_state_machine_construct( &sci_req->started_substate_machine, - &sci_req->parent, + sci_req, scic_sds_stp_request_started_udma_substate_table, SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE ); @@ -1732,7 +1732,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_stp_request_start static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1748,7 +1748,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completio static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; struct scu_task_context *task_context; struct sata_fis_reg_h2d *h2d_fis; enum sci_status status; @@ -1775,7 +1775,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( void *object) { - struct scic_sds_request *sci_req = (struct scic_sds_request *)object; + struct scic_sds_request *sci_req = object; SET_STATE_HANDLER( sci_req, @@ -1806,7 +1806,7 @@ enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_reques scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); sci_base_state_machine_construct(&sci_req->started_substate_machine, - &sci_req->parent, + sci_req, scic_sds_stp_request_started_soft_reset_substate_table, SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 281a556f5eeb..c45e78e41f27 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -61,7 +61,7 @@ #include "request.h" #include "sata.h" #include "scu_completion_codes.h" - +#include "core/scic_sds_request.h" static enum sci_status isci_request_ssp_request_construct( struct isci_request *request) @@ -225,7 +225,7 @@ static enum sci_status isci_io_request_build( return SCI_FAILURE; } - sci_object_set_association(request->sci_request_handle, request); + request->sci_request_handle->ireq = request; switch (task->task_proto) { case SAS_PROTOCOL_SMP: diff --git a/drivers/scsi/isci/stp_remote_device.c b/drivers/scsi/isci/stp_remote_device.c index d86976469428..1853552bc252 100644 --- a/drivers/scsi/isci/stp_remote_device.c +++ b/drivers/scsi/isci/stp_remote_device.c @@ -209,8 +209,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_h struct scic_sds_request *request) { enum sci_status status; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(request); + struct isci_request *isci_request = request->ireq; /* Will the port allow the io request to start? */ @@ -280,8 +279,7 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_ha struct scic_sds_request *request) { enum sci_status status; - struct isci_request *isci_request = - (struct isci_request *)sci_object_get_association(request); + struct isci_request *isci_request = request->ireq; if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { status = sci_dev->owning_port->state_handlers->start_io_handler( diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c0ed1b28f3e5..95f386723212 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -63,7 +63,7 @@ #include "request.h" #include "sata.h" #include "task.h" - +#include "core/scic_sds_request.h" /** * isci_task_refuse() - complete the request to the upper layer driver in * the case where an I/O needs to be completed back in the submit path. @@ -314,10 +314,7 @@ static enum sci_status isci_task_request_build( goto errout; } - sci_object_set_association( - request->sci_request_handle, - request - ); + request->sci_request_handle->ireq = request; /* XXX convert to get this from task->tproto like other drivers */ if (dev->dev_type == SAS_END_DEV) { -- cgit v1.2.3 From be2f41c611b65353fa3ae0c155cf906b348dc864 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Thu, 28 Apr 2011 22:06:36 +0000 Subject: isci: Removed sci_object.h from project. The sci_object.h file was removed. No sci_base_object is now in the code. Reported-by: Christoph Hellwig Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_base_state.h | 2 - drivers/scsi/isci/core/sci_object.h | 98 --------------------------- drivers/scsi/isci/core/scic_io_request.h | 9 +-- drivers/scsi/isci/core/scic_sds_smp_request.c | 3 +- drivers/scsi/isci/isci.h | 1 - 5 files changed, 4 insertions(+), 109 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_object.h diff --git a/drivers/scsi/isci/core/sci_base_state.h b/drivers/scsi/isci/core/sci_base_state.h index 62d2a7c30f07..d64efac1f090 100644 --- a/drivers/scsi/isci/core/sci_base_state.h +++ b/drivers/scsi/isci/core/sci_base_state.h @@ -56,8 +56,6 @@ #ifndef _SCI_BASE_STATE_H_ #define _SCI_BASE_STATE_H_ -#include "sci_object.h" - typedef void (*sci_base_state_handler_t)(void); typedef void (*sci_state_transition_t)(void *base_object); diff --git a/drivers/scsi/isci/core/sci_object.h b/drivers/scsi/isci/core/sci_object.h deleted file mode 100644 index 801b01bc8964..000000000000 --- a/drivers/scsi/isci/core/sci_object.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_OBJECT_H_ -#define _SCI_OBJECT_H_ - -/** - * This file contains all of the method and constants associated with the SCI - * base object. The SCI base object is the class from which all other - * objects derive in the Storage Controller Interface. - * - * - */ - - -#include "sci_status.h" - -/** - * struct sci_base_object - all core objects must include this as their - * first member to permit the casting below - * - * TODO: unwind this assumption, convert these routines and callers to pass a struct - * sci_base_object pointer without casting, or convert 'private' to the - * expected type per-object - * - */ -struct sci_base_object { - void *private; -}; - -static inline void *sci_object_get_association(void *obj) -{ - struct sci_base_object *base = obj; - - return base->private; -} - -static inline void sci_object_set_association(void *obj, void *private) -{ - struct sci_base_object *base = obj; - - base->private = private; -} - -#endif /* _SCI_OBJECT_H_ */ - diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h index 1ac530d2d3bd..16022636fed0 100644 --- a/drivers/scsi/isci/core/scic_io_request.h +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -161,8 +161,7 @@ enum sci_status scic_io_request_construct( * if the remote_device does not support the SSP protocol. * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not * properly set the association between the SCIC IO request and the user's IO - * request. Please refer to the sci_object_set_association() routine for more - * information. + * request. */ enum sci_status scic_io_request_construct_basic_ssp( struct scic_sds_request *scic_io_request); @@ -184,8 +183,7 @@ enum sci_status scic_io_request_construct_basic_ssp( * if the remote_device does not support the STP protocol. * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not * properly set the association between the SCIC IO request and the user's IO - * request. Please refer to the sci_object_set_association() routine for more - * information. + * request. */ enum sci_status scic_io_request_construct_basic_sata( struct scic_sds_request *scic_io_request); @@ -206,8 +204,7 @@ enum sci_status scic_io_request_construct_basic_sata( * if the remote_device does not support the SMP protocol. * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not * properly set the association between the SCIC IO request and the user's IO - * request. Please refer to the sci_object_set_association() routine for more - * information. + * request. */ enum sci_status scic_io_request_construct_smp( struct scic_sds_request *scic_io_request); diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index ba29192f7fd0..fff86687c8bf 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -574,8 +574,7 @@ static const struct sci_base_state scic_sds_smp_request_started_substate_table[] * if the remote_device does not support the SMP protocol. * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not * properly set the association between the SCIC IO request and the user's IO - * request. Please refer to the sci_object_set_association() routine for more - * information. + * request. */ enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) { diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index ac292d2a75de..60c84627c13e 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -65,7 +65,6 @@ #include #include -#include "core/sci_object.h" #include "scic_controller.h" #include "host.h" #include "timers.h" -- cgit v1.2.3 From ab2e8f7d07f577ee39228fb3454b9f29eab0f312 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 27 Apr 2011 16:32:45 -0700 Subject: isci: merge remote_device substates into a single state machine A substate is just a state, so uplevel the smp and stp device substates. Three tricks at work here: 1/ scic_sds_remote_device_ready_state_enter: needs to know the the device type so it can immediately transition to a stp or smp ready substate. 2/ scic_sds_remote_device_ready_state_exit: needs to know the device type. In the ssp case the device is no longer ready, in the stp, and smp case we have simply exited to a ready "substate". 3/ scic_sds_remote_device_resume_complete_handler: The one location where we directly check the current state against SCI_BASE_REMOTE_DEVICE_STATE_READY needed to comprehend the possible ready substates. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 2 - drivers/scsi/isci/remote_device.c | 1240 ++++++++++++++++++++++++--------- drivers/scsi/isci/remote_device.h | 208 +----- drivers/scsi/isci/smp_remote_device.c | 310 --------- drivers/scsi/isci/stp_remote_device.c | 716 ------------------- 5 files changed, 940 insertions(+), 1536 deletions(-) delete mode 100644 drivers/scsi/isci/smp_remote_device.c delete mode 100644 drivers/scsi/isci/stp_remote_device.c diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index fc50ba34b13d..c27d25999123 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -7,8 +7,6 @@ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ remote_device.o port.o timers.o \ host.o task.o probe_roms.o \ - stp_remote_device.o \ - smp_remote_device.o \ remote_node_context.o \ remote_node_table.o \ core/scic_sds_controller.o \ diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 2bbc7c20c400..f6da85e3f2af 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "intel_sas.h" +#include "intel_ata.h" #include "isci.h" #include "port.h" #include "remote_device.h" @@ -71,6 +72,65 @@ #include "scu_event_codes.h" #include "task.h" +/** + * isci_remote_device_change_state() - This function gets the status of the + * remote_device object. + * @isci_device: This parameter points to the isci_remote_device object + * + * status of the object as a isci_status enum. + */ +void isci_remote_device_change_state( + struct isci_remote_device *isci_device, + enum isci_status status) +{ + unsigned long flags; + + spin_lock_irqsave(&isci_device->state_lock, flags); + isci_device->status = status; + spin_unlock_irqrestore(&isci_device->state_lock, flags); +} + +/** + * isci_remote_device_not_ready() - This function is called by the scic when + * the remote device is not ready. We mark the isci device as ready (not + * "ready_for_io") and signal the waiting proccess. + * @isci_host: This parameter specifies the isci host object. + * @isci_device: This parameter specifies the remote device + * + */ +static void isci_remote_device_not_ready(struct isci_host *ihost, + struct isci_remote_device *idev, u32 reason) +{ + dev_dbg(&ihost->pdev->dev, + "%s: isci_device = %p\n", __func__, idev); + + if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) + isci_remote_device_change_state(idev, isci_stopping); + else + /* device ready is actually a "not ready for io" state. */ + isci_remote_device_change_state(idev, isci_ready); +} + +/** + * isci_remote_device_ready() - This function is called by the scic when the + * remote device is ready. We mark the isci device as ready and signal the + * waiting proccess. + * @ihost: our valid isci_host + * @idev: remote device + * + */ +static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev) +{ + dev_dbg(&ihost->pdev->dev, + "%s: idev = %p\n", __func__, idev); + + isci_remote_device_change_state(idev, isci_ready_for_io); + if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags)) + wake_up(&ihost->eventq); +} + + + enum sci_status scic_remote_device_stop( struct scic_sds_remote_device *sci_dev, u32 timeout) @@ -228,49 +288,43 @@ void scic_sds_remote_device_post_request( ); } -/** - * - * @user_parameter: This is cast to a remote device object. - * - * This method is called once the remote node context is ready to be freed. +/* called once the remote node context is ready to be freed. * The remote device can now report that its stop operation is complete. none */ -static void scic_sds_cb_remote_device_rnc_destruct_complete( - void *user_parameter) +static void scic_sds_cb_remote_device_rnc_destruct_complete(void *_dev) { - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)user_parameter; + struct scic_sds_remote_device *sci_dev = _dev; BUG_ON(sci_dev->started_request_count != 0); - sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); } -/** - * - * @user_parameter: This is cast to a remote device object. - * - * This method is called once the remote node context has transisitioned to a +/* called once the remote node context has transisitioned to a * ready state. This is the indication that the remote device object can also - * transition to ready. none + * transition to ready. */ -static void scic_sds_remote_device_resume_complete_handler( - void *user_parameter) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)user_parameter; - - if ( - sci_base_state_machine_get_state(&sci_dev->state_machine) - != SCI_BASE_REMOTE_DEVICE_STATE_READY - ) { - sci_base_state_machine_change_state( - &sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_READY - ); +static void scic_sds_remote_device_resume_complete_handler(void *_dev) +{ + struct scic_sds_remote_device *sci_dev = _dev; + enum scic_sds_remote_device_states state; + + state = sci_dev->state_machine.current_state_id; + switch (state) { + case SCI_BASE_REMOTE_DEVICE_STATE_READY: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + break; + default: + /* go 'ready' if we are not already in a ready state */ + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_READY); + break; } } @@ -284,7 +338,7 @@ static void scic_sds_remote_device_resume_complete_handler( * This method will perform the STP request start processing common to IO * requests and task requests of all types. none */ -void scic_sds_remote_device_start_request( +static void scic_sds_remote_device_start_request( struct scic_sds_remote_device *sci_dev, struct scic_sds_request *sci_req, enum sci_status status) @@ -308,7 +362,7 @@ void scic_sds_remote_device_start_request( * serves as a callback when RNC gets resumed during a task management * sequence. none */ -void scic_sds_remote_device_continue_request(void *dev) +static void scic_sds_remote_device_continue_request(void *dev) { struct scic_sds_remote_device *sci_dev = dev; @@ -368,7 +422,7 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, return SCI_FAILURE_INVALID_STATE; } -enum sci_status scic_sds_remote_device_default_start_handler( +static enum sci_status scic_sds_remote_device_default_start_handler( struct scic_sds_remote_device *sci_dev) { return default_device_handler(sci_dev, __func__); @@ -380,37 +434,37 @@ static enum sci_status scic_sds_remote_device_default_stop_handler( return default_device_handler(sci_dev, __func__); } -enum sci_status scic_sds_remote_device_default_fail_handler( +static enum sci_status scic_sds_remote_device_default_fail_handler( struct scic_sds_remote_device *sci_dev) { return default_device_handler(sci_dev, __func__); } -enum sci_status scic_sds_remote_device_default_destruct_handler( +static enum sci_status scic_sds_remote_device_default_destruct_handler( struct scic_sds_remote_device *sci_dev) { return default_device_handler(sci_dev, __func__); } -enum sci_status scic_sds_remote_device_default_reset_handler( +static enum sci_status scic_sds_remote_device_default_reset_handler( struct scic_sds_remote_device *sci_dev) { return default_device_handler(sci_dev, __func__); } -enum sci_status scic_sds_remote_device_default_reset_complete_handler( +static enum sci_status scic_sds_remote_device_default_reset_complete_handler( struct scic_sds_remote_device *sci_dev) { return default_device_handler(sci_dev, __func__); } -enum sci_status scic_sds_remote_device_default_suspend_handler( +static enum sci_status scic_sds_remote_device_default_suspend_handler( struct scic_sds_remote_device *sci_dev, u32 suspend_type) { return default_device_handler(sci_dev, __func__); } -enum sci_status scic_sds_remote_device_default_resume_handler( +static enum sci_status scic_sds_remote_device_default_resume_handler( struct scic_sds_remote_device *sci_dev) { return default_device_handler(sci_dev, __func__); @@ -505,7 +559,7 @@ static enum sci_status scic_sds_remote_device_default_event_handler( * releases the frame and returns a failure. enum sci_status * SCI_FAILURE_INVALID_STATE */ -enum sci_status scic_sds_remote_device_default_frame_handler( +static enum sci_status scic_sds_remote_device_default_frame_handler( struct scic_sds_remote_device *sci_dev, u32 frame_index) { @@ -525,21 +579,21 @@ enum sci_status scic_sds_remote_device_default_frame_handler( return SCI_FAILURE_INVALID_STATE; } -enum sci_status scic_sds_remote_device_default_start_request_handler( +static enum sci_status scic_sds_remote_device_default_start_request_handler( struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { return default_device_handler(sci_dev, __func__); } -enum sci_status scic_sds_remote_device_default_complete_request_handler( +static enum sci_status scic_sds_remote_device_default_complete_request_handler( struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { return default_device_handler(sci_dev, __func__); } -enum sci_status scic_sds_remote_device_default_continue_request_handler( +static enum sci_status scic_sds_remote_device_default_continue_request_handler( struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) { @@ -558,7 +612,7 @@ enum sci_status scic_sds_remote_device_default_continue_request_handler( * This method decodes the tag for the io request object and routes the * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE */ -enum sci_status scic_sds_remote_device_general_frame_handler( +static enum sci_status scic_sds_remote_device_general_frame_handler( struct scic_sds_remote_device *sci_dev, u32 frame_index) { @@ -602,7 +656,7 @@ enum sci_status scic_sds_remote_device_general_frame_handler( * This is a common method for handling events reported to the remote device * from the controller object. enum sci_status */ -enum sci_status scic_sds_remote_device_general_event_handler( +static enum sci_status scic_sds_remote_device_general_event_handler( struct scic_sds_remote_device *sci_dev, u32 event_code) { @@ -705,7 +759,7 @@ static enum sci_status scic_sds_remote_device_starting_state_stop_handler( return SCI_SUCCESS; } -enum sci_status scic_sds_remote_device_ready_state_stop_handler( +static enum sci_status scic_sds_remote_device_ready_state_stop_handler( struct scic_sds_remote_device *sci_dev) { enum sci_status status = SCI_SUCCESS; @@ -731,7 +785,7 @@ enum sci_status scic_sds_remote_device_ready_state_stop_handler( * * This is the ready state device reset handler enum sci_status */ -enum sci_status scic_sds_remote_device_ready_state_reset_handler( +static enum sci_status scic_sds_remote_device_ready_state_reset_handler( struct scic_sds_remote_device *sci_dev) { /* Request the parent state machine to transition to the stopping state */ @@ -893,34 +947,15 @@ static enum sci_status scic_sds_remote_device_stopping_state_complete_request_ha return SCI_SUCCESS; } -/** - * - * @device: The struct scic_sds_remote_device which is to be cast into a - * struct scic_sds_remote_device object. - * - * This method will complete the reset operation when the device is in the - * resetting state. enum sci_status - */ static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( struct scic_sds_remote_device *sci_dev) { - - sci_base_state_machine_change_state( - &sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_READY - ); + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_READY); return SCI_SUCCESS; } -/** - * - * @device: The struct scic_sds_remote_device which is to be cast into a - * struct scic_sds_remote_device object. - * - * This method will stop the remote device while in the resetting state. - * enum sci_status - */ static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( struct scic_sds_remote_device *sci_dev) { @@ -932,12 +967,11 @@ static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( return SCI_SUCCESS; } -/* - * This method completes requests for this struct scic_sds_remote_device while it is - * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the - * complete method for the request object and if that is successful the port - * object is called to complete the task request. Then the device object itself - * completes the task request. enum sci_status +/* complete requests for this device while it is in the + * SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the complete + * method for the request object and if that is successful the port object is + * called to complete the task request. Then the device object itself completes + * the task request. enum sci_status */ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( struct scic_sds_remote_device *sci_dev, @@ -960,173 +994,665 @@ static enum sci_status scic_sds_remote_device_resetting_state_complete_request_h return status; } -static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { - [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_default_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .start_handler = scic_sds_remote_device_stopped_state_start_handler, - .stop_handler = scic_sds_remote_device_stopped_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_starting_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, - .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, - .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler, - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_stopping_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_default_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_resetting_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_default_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_default_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - } -}; - -static void scic_sds_remote_device_initial_state_enter(void *object) +static enum sci_status scic_sds_stp_remote_device_complete_request(struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) { - struct scic_sds_remote_device *sci_dev = object; + enum sci_status status; - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); + status = scic_sds_io_request_complete(sci_req); + if (status != SCI_SUCCESS) + goto out; - /* Initial state is a transitional state to the stopped state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); + status = scic_sds_port_complete_io(sci_dev->owning_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + goto out; + + scic_sds_remote_device_decrement_request_count(sci_dev); + if (sci_req->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + /* This request causes hardware error, device needs to be Lun Reset. + * So here we force the state machine to IDLE state so the rest IOs + * can reach RNC state handler, these IOs will be completed by RNC with + * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". + */ + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET); + } else if (scic_sds_remote_device_get_request_count(sci_dev) == 0) + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + + + out: + if (status != SCI_SUCCESS) + dev_err(scirdev_to_dev(sci_dev), + "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " + "could not complete\n", __func__, sci_dev->owning_port, + sci_dev, sci_req, status); + + return status; } -/** - * isci_remote_device_change_state() - This function gets the status of the - * remote_device object. - * @isci_device: This parameter points to the isci_remote_device object +/* scic_sds_stp_remote_device_ready_substate_start_request_handler - start stp + * @device: The target device a task management request towards to. + * @request: The task request. * - * status of the object as a isci_status enum. + * This is the READY NCQ substate handler to start task management request. In + * this routine, we suspend and resume the RNC. enum sci_status Always return + * SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to let + * controller_start_task_handler know that the controller can't post TC for + * task request yet, instead, when RNC gets resumed, a controller_continue_task + * callback will be called. */ -void isci_remote_device_change_state( - struct isci_remote_device *isci_device, - enum isci_status status) +static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + enum sci_status status; + + /* Will the port allow the io request to start? */ + status = device->owning_port->state_handlers->start_io_handler( + device->owning_port, device, request); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_task(&device->rnc, request); + if (status != SCI_SUCCESS) + goto out; + + status = request->state_handlers->start_handler(request); + if (status != SCI_SUCCESS) + goto out; + + /* + * Note: If the remote device state is not IDLE this will replace + * the request that probably resulted in the task management request. + */ + device->working_request = request; + sci_base_state_machine_change_state(&device->state_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + + /* + * The remote node context must cleanup the TCi to NCQ mapping table. + * The only way to do this correctly is to either write to the TLCR + * register or to invalidate and repost the RNC. In either case the + * remote node context state machine will take the correct action when + * the remote node context is suspended and later resumed. + */ + scic_sds_remote_node_context_suspend(&device->rnc, + SCI_SOFTWARE_SUSPENSION, NULL, NULL); + scic_sds_remote_node_context_resume(&device->rnc, + scic_sds_remote_device_continue_request, + device); + +out: + scic_sds_remote_device_start_request(device, request, status); + /* + * We need to let the controller start request handler know that it can't + * post TC yet. We will provide a callback function to post TC when RNC gets + * resumed. + */ + return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; +} + +/* handle the start io operation for a sata device that is in the command idle + * state. - Evalute the type of IO request to be started - If its an NCQ + * request change to NCQ substate - If its any other command change to the CMD + * substate + * + * If this is a softreset we may want to have a different substate. + */ +static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status status; + struct isci_request *isci_request = request->ireq; + enum scic_sds_remote_device_states new_state; + + /* Will the port allow the io request to start? */ + status = sci_dev->owning_port->state_handlers->start_io_handler( + sci_dev->owning_port, sci_dev, request); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); + if (status != SCI_SUCCESS) + goto out; + + status = request->state_handlers->start_handler(request); + if (status != SCI_SUCCESS) + goto out; + + if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) + new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ; + else { + sci_dev->working_request = request; + new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD; + } + sci_base_state_machine_change_state(&sci_dev->state_machine, new_state); +out: + scic_sds_remote_device_start_request(sci_dev, request, status); + return status; +} + + +static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( + struct scic_sds_remote_device *sci_dev, + u32 event_code) +{ + enum sci_status status; + + status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); + if (status != SCI_SUCCESS) + return status; + + /* We pick up suspension events to handle specifically to this state. We + * resume the RNC right away. enum sci_status + */ + if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || + scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) + status = scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); + + return status; +} + +static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *request) +{ + enum sci_status status; + struct isci_request *isci_request = request->ireq; + scic_sds_port_io_request_handler_t start_io; + + if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { + start_io = sci_dev->owning_port->state_handlers->start_io_handler; + status = start_io(sci_dev->owning_port, sci_dev, request); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); + if (status != SCI_SUCCESS) + return status; + + status = request->state_handlers->start_handler(request); + + scic_sds_remote_device_start_request(sci_dev, request, status); + } else + status = SCI_FAILURE_INVALID_STATE; + + return status; +} + +static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + enum sci_status status; + struct sata_fis_header *frame_header; + struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + if (status != SCI_SUCCESS) + return status; + + if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && + (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { + sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + + /* TODO Check sactive and complete associated IO if any. */ + + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && + (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { + /* + * Some devices return D2H FIS when an NCQ error is detected. + * Treat this like an SDB error FIS ready reason. + */ + sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + } else + status = SCI_FAILURE; + + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + /* device is already handling a command it can not accept new commands + * until this one is complete. + */ + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( + struct scic_sds_remote_device *sci_dev, + u32 suspend_type) +{ + enum sci_status status; + + status = scic_sds_remote_node_context_suspend(&sci_dev->rnc, + suspend_type, NULL, NULL); + + return status; +} + +static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + /* The device doe not process any UF received from the hardware while + * in this state. All unsolicited frames are forwarded to the io + * request object. + */ + return scic_sds_io_request_frame_handler(sci_dev->working_request, + frame_index); +} + +static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; +} + +static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + struct scic_sds_request *sci_req = request; + enum sci_status status; + + status = scic_sds_io_request_complete(sci_req); + if (status != SCI_SUCCESS) + goto out; + + status = scic_sds_port_complete_io(device->owning_port, device, sci_req); + if (status != SCI_SUCCESS) + goto out; + + scic_sds_remote_device_decrement_request_count(device); + out: + if (status != SCI_SUCCESS) + dev_err(scirdev_to_dev(device), + "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " + "could not complete\n", + __func__, device->owning_port, device, sci_req, status); + + return status; +} + +static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) +{ + struct scic_sds_remote_device *sci_dev = _dev; + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); + struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + + /* For NCQ operation we do not issue a isci_remote_device_not_ready(). + * As a result, avoid sending the ready notification. + */ + if (sci_dev->state_machine.previous_state_id != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) + isci_remote_device_ready(scic->ihost, idev); +} + +static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + enum sci_status status; + + /* Will the port allow the io request to start? */ + status = sci_dev->owning_port->state_handlers->start_io_handler( + sci_dev->owning_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_request_start(sci_req); + if (status != SCI_SUCCESS) + return status; + + sci_dev->working_request = sci_req; + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + + scic_sds_remote_device_start_request(sci_dev, sci_req, status); + + return status; +} + +static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( + struct scic_sds_remote_device *device, + struct scic_sds_request *request) +{ + /* device is already handling a command it can not accept new commands + * until this one is complete. + */ + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status +scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + enum sci_status status; + + status = scic_sds_io_request_complete(sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_port_complete_io(sci_dev->owning_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) { + dev_err(scirdev_to_dev(sci_dev), + "%s: SCIC SDS Remote Device 0x%p io request " + "0x%p could not be completd on the port 0x%p " + "failed with status %d.\n", __func__, sci_dev, sci_req, + sci_dev->owning_port, status); + return status; + } + + scic_sds_remote_device_decrement_request_count(sci_dev); + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + + return status; +} + +static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( + struct scic_sds_remote_device *sci_dev, + u32 frame_index) +{ + enum sci_status status; + + /* The device does not process any UF received from the hardware while + * in this state. All unsolicited frames are forwarded to the io request + * object. + */ + status = scic_sds_io_request_frame_handler( + sci_dev->working_request, + frame_index + ); + + return status; +} + +static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { + [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { + .start_handler = scic_sds_remote_device_stopped_state_start_handler, + .stop_handler = scic_sds_remote_device_stopped_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_starting_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, + .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, + .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_stp_remote_device_complete_request, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_ready_state_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, + .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, + .complete_task_handler = scic_sds_stp_remote_device_complete_request, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + }, + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_ready_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, + .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_stopping_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_general_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_resetting_state_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_general_frame_handler + }, + [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { + .start_handler = scic_sds_remote_device_default_start_handler, + .stop_handler = scic_sds_remote_device_default_stop_handler, + .fail_handler = scic_sds_remote_device_default_fail_handler, + .destruct_handler = scic_sds_remote_device_default_destruct_handler, + .reset_handler = scic_sds_remote_device_default_reset_handler, + .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, + .start_io_handler = scic_sds_remote_device_default_start_request_handler, + .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, + .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, + .start_task_handler = scic_sds_remote_device_default_start_request_handler, + .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, + .suspend_handler = scic_sds_remote_device_default_suspend_handler, + .resume_handler = scic_sds_remote_device_default_resume_handler, + .event_handler = scic_sds_remote_device_default_event_handler, + .frame_handler = scic_sds_remote_device_default_frame_handler + } +}; + +static void scic_sds_remote_device_initial_state_enter(void *object) { - unsigned long flags; + struct scic_sds_remote_device *sci_dev = object; - spin_lock_irqsave(&isci_device->state_lock, flags); - isci_device->status = status; - spin_unlock_irqrestore(&isci_device->state_lock, flags); + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); + + /* Initial state is a transitional state to the stopped state */ + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); } /** @@ -1242,9 +1768,8 @@ static void scic_sds_remote_device_starting_state_enter(void *object) static void scic_sds_remote_device_ready_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); + struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + struct domain_device *dev = sci_dev_to_domain(sci_dev); SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, @@ -1252,23 +1777,26 @@ static void scic_sds_remote_device_ready_state_enter(void *object) scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; - if (sci_dev->has_ready_substate_machine) - sci_base_state_machine_start(&sci_dev->ready_substate_machine); - else - isci_remote_device_ready(ihost, idev); + if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } else if (dev_is_expander(dev)) { + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + } else + isci_remote_device_ready(scic->ihost, sci_dev_to_idev(sci_dev)); } static void scic_sds_remote_device_ready_state_exit(void *object) { struct scic_sds_remote_device *sci_dev = object; - if (sci_dev->has_ready_substate_machine) - sci_base_state_machine_stop(&sci_dev->ready_substate_machine); - else { - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = scic->ihost; + struct domain_device *dev = sci_dev_to_domain(sci_dev); + + if (dev->dev_type == SAS_END_DEV) { + struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - isci_remote_device_not_ready(ihost, idev, + isci_remote_device_not_ready(scic->ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); } } @@ -1327,6 +1855,101 @@ static void scic_sds_remote_device_final_state_enter(void *object) ); } +static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *object) +{ + struct scic_sds_remote_device *sci_dev = object; + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + + sci_dev->working_request = NULL; + if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { + /* + * Since the RNC is ready, it's alright to finish completion + * processing (e.g. signal the remote device is ready). */ + scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(sci_dev); + } else { + scic_sds_remote_node_context_resume(&sci_dev->rnc, + scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, + sci_dev); + } +} + +static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) +{ + struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + + BUG_ON(sci_dev->working_request == NULL); + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + + isci_remote_device_not_ready(scic->ihost, sci_dev_to_idev(sci_dev), + SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); +} + +static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object) +{ + struct scic_sds_remote_device *sci_dev = object; + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); +} + +static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(void *object) +{ + struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + + if (sci_dev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) + isci_remote_device_not_ready(scic->ihost, idev, + sci_dev->not_ready_reason); +} + +static void scic_sds_stp_remote_device_ready_await_reset_substate_enter(void *object) +{ + struct scic_sds_remote_device *sci_dev = object; + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET); +} + +static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) +{ + struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + + isci_remote_device_ready(scic->ihost, sci_dev_to_idev(sci_dev)); +} + +static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) +{ + struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + + BUG_ON(sci_dev->working_request == NULL); + + SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + + isci_remote_device_not_ready(scic->ihost, sci_dev_to_idev(sci_dev), + SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); +} + +static void scic_sds_smp_remote_device_ready_cmd_substate_exit(void *object) +{ + struct scic_sds_remote_device *sci_dev = object; + + sci_dev->working_request = NULL; +} static const struct sci_base_state scic_sds_remote_device_state_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { @@ -1342,6 +1965,28 @@ static const struct sci_base_state scic_sds_remote_device_state_table[] = { .enter_state = scic_sds_remote_device_ready_state_enter, .exit_state = scic_sds_remote_device_ready_state_exit }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { + .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { + .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, + }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { + .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, + }, + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, + }, + [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, + .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, + }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { .enter_state = scic_sds_remote_device_stopping_state_enter, }, @@ -1406,7 +2051,6 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci struct scic_sds_remote_device *sci_dev) { enum sci_status status; - u16 remote_node_index; struct domain_device *dev = sci_dev_to_domain(sci_dev); scic_remote_device_construct(sci_port, sci_dev); @@ -1418,33 +2062,15 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci sci_dev->is_direct_attached = true; status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller, sci_dev, - &remote_node_index); + &sci_dev->rnc.remote_node_index); if (status != SCI_SUCCESS) return status; - sci_dev->rnc.remote_node_index = remote_node_index; - - if (dev->dev_type == SAS_END_DEV) - sci_dev->has_ready_substate_machine = false; - else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { - sci_dev->has_ready_substate_machine = true; - - sci_base_state_machine_construct( - &sci_dev->ready_substate_machine, - sci_dev, - scic_sds_stp_remote_device_ready_substate_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } else if (dev_is_expander(dev)) { - sci_dev->has_ready_substate_machine = true; - - /* add the SMP ready substate machine construction here */ - sci_base_state_machine_construct( - &sci_dev->ready_substate_machine, - sci_dev, - scic_sds_smp_remote_device_ready_substate_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } else + if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || + (dev->tproto & SAS_PROTOCOL_STP) || dev_is_expander(dev)) + /* pass */; + else return SCI_FAILURE_UNSUPPORTED_PROTOCOL; sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(sci_port); @@ -1470,37 +2096,22 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev) { - struct scic_sds_controller *scic = sci_port->owning_controller; struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status; scic_remote_device_construct(sci_port, sci_dev); - status = scic_sds_controller_allocate_remote_node_context( - scic, sci_dev, &sci_dev->rnc.remote_node_index); + status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller, + sci_dev, + &sci_dev->rnc.remote_node_index); if (status != SCI_SUCCESS) return status; - if (dev->dev_type == SAS_END_DEV) - sci_dev->has_ready_substate_machine = false; - else if (dev_is_expander(dev)) { - sci_dev->has_ready_substate_machine = true; - - /* add the SMP ready substate machine construction here */ - sci_base_state_machine_construct( - &sci_dev->ready_substate_machine, - sci_dev, - scic_sds_smp_remote_device_ready_substate_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { - sci_dev->has_ready_substate_machine = true; - - sci_base_state_machine_construct( - &sci_dev->ready_substate_machine, - sci_dev, - scic_sds_stp_remote_device_ready_substate_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - } + if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || + (dev->tproto & SAS_PROTOCOL_STP) || dev_is_expander(dev)) + /* pass */; + else + return SCI_FAILURE_UNSUPPORTED_PROTOCOL; /* * For SAS-2 the physical link rate is actually a logical link @@ -1515,7 +2126,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci /* / @todo Should I assign the port width by reading all of the phys on the port? */ sci_dev->device_port_width = 1; - return status; + return SCI_SUCCESS; } /** @@ -1617,45 +2228,6 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) return idev; } -/** - * isci_remote_device_ready() - This function is called by the scic when the - * remote device is ready. We mark the isci device as ready and signal the - * waiting proccess. - * @ihost: our valid isci_host - * @idev: remote device - * - */ -void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev) -{ - dev_dbg(&ihost->pdev->dev, - "%s: idev = %p\n", __func__, idev); - - isci_remote_device_change_state(idev, isci_ready_for_io); - if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags)) - wake_up(&ihost->eventq); -} - -/** - * isci_remote_device_not_ready() - This function is called by the scic when - * the remote device is not ready. We mark the isci device as ready (not - * "ready_for_io") and signal the waiting proccess. - * @isci_host: This parameter specifies the isci host object. - * @isci_device: This parameter specifies the remote device - * - */ -void isci_remote_device_not_ready(struct isci_host *ihost, - struct isci_remote_device *idev, u32 reason) -{ - dev_dbg(&ihost->pdev->dev, - "%s: isci_device = %p\n", __func__, idev); - - if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) - isci_remote_device_change_state(idev, isci_stopping); - else - /* device ready is actually a "not ready for io" state. */ - isci_remote_device_change_state(idev, isci_ready); -} - /** * isci_remote_device_stop() - This function is called internally to stop the * remote device. diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 62623c766388..dda217a6bd3a 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -68,9 +68,7 @@ enum scic_remote_device_not_ready_reason_code { SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED, SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED, SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED, - SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX - }; struct scic_sds_remote_device { @@ -131,19 +129,6 @@ struct scic_sds_remote_device { */ u32 not_ready_reason; - /** - * This field is true if this remote device has an initialzied ready substate - * machine. SSP devices do not have a ready substate machine and STP devices - * have a ready substate machine. - */ - bool has_ready_substate_machine; - - /** - * This field contains the state machine for the ready substate machine for - * this struct scic_sds_remote_device object. - */ - struct sci_base_state_machine ready_substate_machine; - /** * This field maintains the set of state handlers for the remote device * object. These are changed each time the remote device enters a new state. @@ -171,10 +156,6 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev); void isci_remote_device_nuke_requests(struct isci_host *ihost, struct isci_remote_device *idev); -void isci_remote_device_ready(struct isci_host *ihost, - struct isci_remote_device *idev); -void isci_remote_device_not_ready(struct isci_host *ihost, - struct isci_remote_device *idev, u32 reason); void isci_remote_device_gone(struct domain_device *domain_dev); int isci_remote_device_found(struct domain_device *domain_dev); bool isci_device_is_reset_pending(struct isci_host *ihost, @@ -277,77 +258,6 @@ enum scic_sds_remote_device_states { */ SCI_BASE_REMOTE_DEVICE_STATE_READY, - /** - * This state indicates that the remote device is in the process of - * stopping. In this state no new IO operations are permitted, but - * existing IO operations are allowed to complete. - * This state is entered from the READY state. - * This state is entered from the FAILED state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, - - /** - * This state indicates that the remote device has failed. - * In this state no new IO operations are permitted. - * This state is entered from the INITIALIZING state. - * This state is entered from the READY state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_FAILED, - - /** - * This state indicates the device is being reset. - * In this state no new IO operations are permitted. - * This state is entered from the READY state. - */ - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, - - /** - * Simply the final state for the base remote device state machine. - */ - SCI_BASE_REMOTE_DEVICE_STATE_FINAL, -}; - -/** - * enum scic_sds_ssp_remote_device_ready_substates - - * - * This is the enumeration of the ready substates for the - * struct scic_sds_remote_device. - */ -enum scic_sds_ssp_remote_device_ready_substates { - /** - * This is the initial state for the remote device ready substate. - */ - SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL, - - /** - * This is the ready operational substate for the remote device. - * This is the normal operational state for a remote device. - */ - SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL, - - /** - * This is the suspended state for the remote device. This is the state - * that the device is placed in when a RNC suspend is received by - * the SCU hardware. - */ - SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED, - - /** - * This is the final state that the device is placed in before a change - * to the base state machine. - */ - SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL, - - SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES -}; - -/** - * enum scic_sds_stp_remote_device_ready_substates - - * - * This is the enumeration for the struct scic_sds_remote_device ready substates - * for the STP remote device. - */ -enum scic_sds_stp_remote_device_ready_substates { /** * This is the idle substate for the stp remote device. When there are no * active IO for the device it is is in this state. @@ -381,14 +291,7 @@ enum scic_sds_stp_remote_device_ready_substates { * coming to be recovered from certain hardware specific error. */ SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, -}; -/** - * enum scic_sds_smp_remote_device_ready_substates - - * - * This is the enumeration of the ready substates for the SMP REMOTE DEVICE. - */ -enum scic_sds_smp_remote_device_ready_substates { /** * This is the ready operational substate for the remote device. This is the * normal operational state for a remote device. @@ -400,6 +303,35 @@ enum scic_sds_smp_remote_device_ready_substates { * the device is placed in when a RNC suspend is received by the SCU hardware. */ SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, + + /** + * This state indicates that the remote device is in the process of + * stopping. In this state no new IO operations are permitted, but + * existing IO operations are allowed to complete. + * This state is entered from the READY state. + * This state is entered from the FAILED state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, + + /** + * This state indicates that the remote device has failed. + * In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + * This state is entered from the READY state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_FAILED, + + /** + * This state indicates the device is being reset. + * In this state no new IO operations are permitted. + * This state is entered from the READY state. + */ + SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, + + /** + * Simply the final state for the base remote device state machine. + */ + SCI_BASE_REMOTE_DEVICE_STATE_FINAL, }; static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) @@ -541,10 +473,6 @@ struct scic_sds_remote_device_state_handler { scic_sds_remote_device_frame_handler_t frame_handler; }; -extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[]; -extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[]; -extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[]; - /** * scic_sds_remote_device_increment_request_count() - * @@ -672,92 +600,24 @@ enum sci_status scic_sds_remote_device_start_io( struct scic_sds_remote_device *sci_dev, struct scic_sds_request *io_request); -enum sci_status scic_sds_remote_device_complete_io( +enum sci_status scic_sds_remote_device_start_task( struct scic_sds_controller *controller, struct scic_sds_remote_device *sci_dev, struct scic_sds_request *io_request); -enum sci_status scic_sds_remote_device_resume( - struct scic_sds_remote_device *sci_dev); +enum sci_status scic_sds_remote_device_complete_io( + struct scic_sds_controller *controller, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *io_request); enum sci_status scic_sds_remote_device_suspend( struct scic_sds_remote_device *sci_dev, u32 suspend_type); -enum sci_status scic_sds_remote_device_start_task( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request); - void scic_sds_remote_device_post_request( struct scic_sds_remote_device *sci_dev, u32 request); #define scic_sds_remote_device_is_atapi(sci_dev) false -void scic_sds_remote_device_start_request( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req, - enum sci_status status); - -void scic_sds_remote_device_continue_request(void *sci_dev); - -enum sci_status scic_sds_remote_device_default_start_handler( - struct scic_sds_remote_device *sci_dev); - -enum sci_status scic_sds_remote_device_default_fail_handler( - struct scic_sds_remote_device *sci_dev); - -enum sci_status scic_sds_remote_device_default_destruct_handler( - struct scic_sds_remote_device *sci_dev); - -enum sci_status scic_sds_remote_device_default_reset_handler( - struct scic_sds_remote_device *device); - -enum sci_status scic_sds_remote_device_default_reset_complete_handler( - struct scic_sds_remote_device *device); - -enum sci_status scic_sds_remote_device_default_start_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request); - -enum sci_status scic_sds_remote_device_default_complete_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request); - -enum sci_status scic_sds_remote_device_default_continue_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request); - -enum sci_status scic_sds_remote_device_default_suspend_handler( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type); - -enum sci_status scic_sds_remote_device_default_resume_handler( - struct scic_sds_remote_device *sci_dev); - - -enum sci_status scic_sds_remote_device_default_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index); - -enum sci_status scic_sds_remote_device_ready_state_stop_handler( - struct scic_sds_remote_device *device); - -enum sci_status scic_sds_remote_device_ready_state_reset_handler( - struct scic_sds_remote_device *device); - -enum sci_status scic_sds_remote_device_general_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index); - -enum sci_status scic_sds_remote_device_general_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code); - -enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler( - struct scic_sds_remote_device *sci_dev); - - - #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ diff --git a/drivers/scsi/isci/smp_remote_device.c b/drivers/scsi/isci/smp_remote_device.c deleted file mode 100644 index 45340a5c99c7..000000000000 --- a/drivers/scsi/isci/smp_remote_device.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "scic_sds_controller.h" -#include "scic_sds_port.h" -#include "remote_device.h" -#include "scic_sds_request.h" -#include "sci_environment.h" -#include "sci_util.h" -#include "scu_event_codes.h" -#include "scu_task_context.h" - -/* - * ***************************************************************************** - * * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @[in]: device The device the io is sent to. - * @[in]: request The io to start. - * - * This method will handle the start io operation for a SMP device that is in - * the idle state. enum sci_status - */ -static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - - /* Will the port allow the io request to start? */ - status = device->owning_port->state_handlers->start_io_handler( - device->owning_port, device, request); - - if (status == SCI_SUCCESS) { - status = scic_sds_remote_node_context_start_io(&device->rnc, request); - - if (status == SCI_SUCCESS) - status = scic_sds_request_start(request); - - if (status == SCI_SUCCESS) { - device->working_request = request; - - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD - ); - } - - scic_sds_remote_device_start_request(device, request, status); - } - - return status; -} - - -/* - * ****************************************************************************** - * * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS - * ****************************************************************************** */ -/** - * - * @device: This is the device object that is receiving the IO. - * @request: The io to start. - * - * This device is already handling a command it can not accept new commands - * until this one is complete. enum sci_status - */ -static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - return SCI_FAILURE_INVALID_STATE; -} - - -/** - * this is the complete_io_handler for smp device at ready cmd substate. - * @device: This is the device object that is receiving the IO. - * @request: The io to start. - * - * enum sci_status - */ -static enum sci_status -scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - struct scic_sds_request *sci_req; - - sci_req = (struct scic_sds_request *)request; - - status = scic_sds_io_request_complete(sci_req); - - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - device->owning_port, device, sci_req); - - if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(device); - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE - ); - } else - dev_err(scirdev_to_dev(device), - "%s: SCIC SDS Remote Device 0x%p io request " - "0x%p could not be completd on the port 0x%p " - "failed with status %d.\n", - __func__, - device, - sci_req, - device->owning_port, - status); - } - - return status; -} - -/** - * This is frame handler for smp device ready cmd substate. - * @sci_dev: This is the device object that is receiving the frame. - * @frame_index: The index for the frame received. - * - * enum sci_status - */ -static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status status; - - /* - * / The device does not process any UF received from the hardware while - * / in this state. All unsolicited frames are forwarded to the io request - * / object. */ - status = scic_sds_io_request_frame_handler( - sci_dev->working_request, - frame_index - ); - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_remote_device_state_handler scic_sds_smp_remote_device_ready_substate_handler_table[] = { - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_default_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, - .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_remote_device_default_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler - } -}; - -/** - * - * @object: This is the object which is cast into a - * struct scic_sds_remote_device. - * - * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. - * This function sets the ready cmd substate handlers and reports the device as - * ready. none - */ -static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - - SET_STATE_HANDLER(sci_dev, - scic_sds_smp_remote_device_ready_substate_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - - isci_remote_device_ready(ihost, idev); -} - -/** - * - * @object: This is the object which is cast into a - * struct scic_sds_remote_device. - * - * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This - * function sets the remote device objects ready cmd substate handlers, and - * notify core user that the device is not ready. none - */ -static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - - BUG_ON(sci_dev->working_request == NULL); - - SET_STATE_HANDLER(sci_dev, - scic_sds_smp_remote_device_ready_substate_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - - isci_remote_device_not_ready(ihost, idev, - SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); -} - -/** - * - * @object: This is the object which is cast into a - * struct scic_sds_remote_device. - * - * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none - */ -static void scic_sds_smp_remote_device_ready_cmd_substate_exit(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - sci_dev->working_request = NULL; -} - -/* --------------------------------------------------------------------------- */ - -const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = { - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, - }, - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, - .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, - }, -}; diff --git a/drivers/scsi/isci/stp_remote_device.c b/drivers/scsi/isci/stp_remote_device.c deleted file mode 100644 index 1853552bc252..000000000000 --- a/drivers/scsi/isci/stp_remote_device.c +++ /dev/null @@ -1,716 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "intel_ata.h" -#include "intel_sata.h" -#include "intel_sat.h" -#include "sci_base_state.h" -#include "scic_sds_controller.h" -#include "scic_sds_port.h" -#include "remote_device.h" -#include "scic_sds_request.h" -#include "sci_environment.h" -#include "sci_util.h" -#include "scu_event_codes.h" - -/** - * This method will perform the STP request completion processing common to IO - * requests and task requests of all types - * @device: This parameter specifies the device for which the request is being - * completed. - * @request: This parameter specifies the request being completed. - * - * This method returns an indication as to whether the request processing - * completed successfully. - */ -static enum sci_status scic_sds_stp_remote_device_complete_request( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - - status = scic_sds_io_request_complete(request); - - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - device->owning_port, device, request); - - if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(device); - if (request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - /* - * This request causes hardware error, device needs to be Lun Reset. - * So here we force the state machine to IDLE state so the rest IOs - * can reach RNC state handler, these IOs will be completed by RNC with - * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET - ); - } else if (scic_sds_remote_device_get_request_count(device) == 0) { - sci_base_state_machine_change_state( - &device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE - ); - } - } - } - - if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(device), - "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " - "could not complete\n", - __func__, - device->owning_port, - device, - request, - status); - - return status; -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * This is the READY NCQ substate handler to start task management request. In - * this routine, we suspend and resume the RNC. - * @device: The target device a task management request towards to. - * @request: The task request. - * - * enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to - * let controller_start_task_handler know that the controller can't post TC for - * task request yet, instead, when RNC gets resumed, a controller_continue_task - * callback will be called. - */ -static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - - /* Will the port allow the io request to start? */ - status = device->owning_port->state_handlers->start_io_handler( - device->owning_port, device, request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_task(&device->rnc, request); - if (status != SCI_SUCCESS) - goto out; - - status = request->state_handlers->start_handler(request); - if (status != SCI_SUCCESS) - goto out; - - /* - * Note: If the remote device state is not IDLE this will replace - * the request that probably resulted in the task management request. - */ - device->working_request = request; - sci_base_state_machine_change_state(&device->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - - /* - * The remote node context must cleanup the TCi to NCQ mapping table. - * The only way to do this correctly is to either write to the TLCR - * register or to invalidate and repost the RNC. In either case the - * remote node context state machine will take the correct action when - * the remote node context is suspended and later resumed. - */ - scic_sds_remote_node_context_suspend(&device->rnc, - SCI_SOFTWARE_SUSPENSION, NULL, NULL); - scic_sds_remote_node_context_resume(&device->rnc, - scic_sds_remote_device_continue_request, - device); - -out: - scic_sds_remote_device_start_request(device, request, status); - /* - * We need to let the controller start request handler know that it can't - * post TC yet. We will provide a callback function to post TC when RNC gets - * resumed. - */ - return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * This method will handle the start io operation for a sata device that is in - * the command idle state. - Evalute the type of IO request to be started - - * If its an NCQ request change to NCQ substate - If its any other command - * change to the CMD substate - * @device: - * @request: - * - * If this is a softreset we may want to have a different substate. - * enum sci_status - */ -static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status; - struct isci_request *isci_request = request->ireq; - - - /* Will the port allow the io request to start? */ - status = sci_dev->owning_port->state_handlers->start_io_handler( - sci_dev->owning_port, sci_dev, request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (status != SCI_SUCCESS) - goto out; - - status = request->state_handlers->start_handler(request); - if (status != SCI_SUCCESS) - goto out; - - if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { - sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); - } else { - sci_dev->working_request = request; - sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - } -out: - scic_sds_remote_device_start_request(sci_dev, request, status); - return status; -} - - -/** - * - * @[in]: device The device received event. - * @[in]: event_code The event code. - * - * This method will handle the event for a sata device that is in the idle - * state. We pick up suspension events to handle specifically to this state. We - * resume the RNC right away. enum sci_status - */ -static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - enum sci_status status; - - status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); - - if (status == SCI_SUCCESS) { - if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX - || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { - status = scic_sds_remote_node_context_resume( - &sci_dev->rnc, NULL, NULL); - } - } - - return status; -} - - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS - * ***************************************************************************** */ - -static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status; - struct isci_request *isci_request = request->ireq; - - if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { - status = sci_dev->owning_port->state_handlers->start_io_handler( - sci_dev->owning_port, - sci_dev, - request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (status != SCI_SUCCESS) - return status; - - status = request->state_handlers->start_handler(request); - - scic_sds_remote_device_start_request(sci_dev, request, status); - } else - status = SCI_FAILURE_INVALID_STATE; - - return status; -} - - -/** - * This method will handle events received while the STP device is in the ready - * command substate. - * @sci_dev: This is the device object that is receiving the event. - * @event_code: The event code to process. - * - * enum sci_status - */ - -static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status status; - struct sata_fis_header *frame_header; - - status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), - frame_index, - (void **)&frame_header - ); - - if (status == SCI_SUCCESS) { - if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && - (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { - sci_dev->not_ready_reason = - SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; - - /* - * / @todo Check sactive and complete associated IO - * if any. - */ - - sci_base_state_machine_change_state( - &sci_dev->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR - ); - } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && - (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { - - /* - * Some devices return D2H FIS when an NCQ error is detected. - * Treat this like an SDB error FIS ready reason. - */ - sci_dev->not_ready_reason = - SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; - - sci_base_state_machine_change_state( - &sci_dev->ready_substate_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR - ); - } else { - status = SCI_FAILURE; - } - - scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(sci_dev), frame_index - ); - } - - return status; -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS - * ***************************************************************************** */ - -/** - * This device is already handling a command it can not accept new commands - * until this one is complete. - * @device: - * @request: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type) -{ - enum sci_status status; - - status = scic_sds_remote_node_context_suspend(&sci_dev->rnc, - suspend_type, NULL, NULL); - - return status; -} - -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status status; - - /* - * / The device doe not process any UF received from the hardware while - * / in this state. All unsolicited frames are forwarded to the io request - * / object. */ - status = scic_sds_io_request_frame_handler( - sci_dev->working_request, - frame_index - ); - - return status; -} - - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS - * ***************************************************************************** */ - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS - * ***************************************************************************** */ - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS - * ***************************************************************************** */ -static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; -} - - - -/** - * This method will perform the STP request (both io or task) completion - * processing for await reset state. - * @device: This parameter specifies the device for which the request is being - * completed. - * @request: This parameter specifies the request being completed. - * - * This method returns an indication as to whether the request processing - * completed successfully. - */ -static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - struct scic_sds_request *sci_req = (struct scic_sds_request *)request; - enum sci_status status; - - status = scic_sds_io_request_complete(sci_req); - - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - device->owning_port, device, sci_req - ); - - if (status == SCI_SUCCESS) - scic_sds_remote_device_decrement_request_count(device); - } - - if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(device), - "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " - "could not complete\n", - __func__, - device->owning_port, - device, - sci_req, - status); - - return status; -} - -static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, - .frame_handler = scic_sds_remote_device_default_frame_handler - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, - .complete_io_handler = scic_sds_stp_remote_device_complete_request, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, - .complete_io_handler = scic_sds_stp_remote_device_complete_request, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_remote_device_default_start_request_handler, - .complete_io_handler = scic_sds_stp_remote_device_complete_request, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .start_handler = scic_sds_remote_device_default_start_handler, - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, - .fail_handler = scic_sds_remote_device_default_fail_handler, - .destruct_handler = scic_sds_remote_device_default_destruct_handler, - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, - .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, - .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, - .complete_task_handler = scic_sds_stp_remote_device_complete_request, - .suspend_handler = scic_sds_remote_device_default_suspend_handler, - .resume_handler = scic_sds_remote_device_default_resume_handler, - .event_handler = scic_sds_remote_device_general_event_handler, - .frame_handler = scic_sds_remote_device_general_frame_handler - } -}; - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS - * ***************************************************************************** */ - -static void -scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *user_cookie) -{ - struct scic_sds_remote_device *sci_dev = user_cookie; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = scic->ihost; - - /* - * For NCQ operation we do not issue a - * scic_cb_remote_device_not_ready(). As a result, avoid sending - * the ready notification. - */ - if (sci_dev->ready_substate_machine.previous_state_id != - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) - isci_remote_device_ready(ihost, idev); -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY IDLE SUBSTATE - * ***************************************************************************** */ - -/** - * - * @device: This is the object which is cast into a - * struct scic_sds_remote_device object. - * - */ -static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *device) -{ - struct scic_sds_remote_device *sci_dev = device; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE - ); - - sci_dev->working_request = NULL; - - if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { - /* - * Since the RNC is ready, it's alright to finish completion - * processing (e.g. signal the remote device is ready). */ - scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( - sci_dev - ); - } else { - scic_sds_remote_node_context_resume( - &sci_dev->rnc, - scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, - sci_dev); - } -} - -static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - - BUG_ON(sci_dev->working_request == NULL); - - SET_STATE_HANDLER(sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - - isci_remote_device_not_ready(ihost, idev, - SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); -} - -static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - SET_STATE_HANDLER(sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); -} - -static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( - void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = scic->ihost; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - - SET_STATE_HANDLER(sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); - - if (sci_dev->not_ready_reason == - SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) - isci_remote_device_not_ready(ihost, idev, sci_dev->not_ready_reason); -} - -/* - * ***************************************************************************** - * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE - * ***************************************************************************** */ - -/** - * The enter routine to READY AWAIT RESET substate. - * @device: This is the object which is cast into a - * struct scic_sds_remote_device object. - * - */ -static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( - void *device) -{ - struct scic_sds_remote_device *sci_dev; - - sci_dev = (struct scic_sds_remote_device *)device; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_stp_remote_device_ready_substate_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET - ); -} - -const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, - }, -}; -- cgit v1.2.3 From 8f304c36ee415600c6bbc5de300e6fa3dbe59d6d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 29 Apr 2011 13:20:30 -0700 Subject: isci: kill scic_remote_device_get_connection_rate A function call to dereference a pointer is a tad much. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_request.c | 3 +-- drivers/scsi/isci/core/scic_sds_smp_request.c | 3 +-- drivers/scsi/isci/core/scic_sds_stp_request.c | 3 +-- drivers/scsi/isci/remote_device.c | 13 ------------- drivers/scsi/isci/remote_device.h | 13 ------------- 5 files changed, 3 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index fba642881092..ffc16072d1da 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -443,8 +443,7 @@ static void scu_ssp_reqeust_construct_task_context( task_context->abort = 0; task_context->priority = 0; task_context->initiator_request = 1; - task_context->connection_rate = - scic_remote_device_get_connection_rate(target_device); + task_context->connection_rate = target_device->connection_rate; task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index fff86687c8bf..2815da288750 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -193,8 +193,7 @@ static void scu_smp_request_construct_task_context( */ task_context->priority = 0; task_context->initiator_request = 1; - task_context->connection_rate = - scic_remote_device_get_connection_rate(sci_dev); + task_context->connection_rate = sci_dev->connection_rate; task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index ec215463092a..8c980235ea41 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -181,8 +181,7 @@ static void scu_sata_reqeust_construct_task_context( task_context->abort = 0; task_context->priority = SCU_TASK_PRIORITY_NORMAL; task_context->initiator_request = 1; - task_context->connection_rate = - scic_remote_device_get_connection_rate(target_device); + task_context->connection_rate = target_device->connection_rate; task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index f6da85e3f2af..834a3feaca63 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -152,22 +152,9 @@ enum sci_status scic_remote_device_reset_complete( return sci_dev->state_handlers->reset_complete_handler(sci_dev); } - -enum sas_linkrate scic_remote_device_get_connection_rate( - struct scic_sds_remote_device *sci_dev) -{ - return sci_dev->connection_rate; -} - -/** - * - * - * Remote device timer requirements - */ #define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0) #define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES) - /** * * @sci_dev: The remote device for which the suspend is being requested. diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index dda217a6bd3a..fd24df31abd2 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -208,19 +208,6 @@ enum sci_status scic_remote_device_reset( enum sci_status scic_remote_device_reset_complete( struct scic_sds_remote_device *remote_device); - - -/** - * scic_remote_device_get_connection_rate() - This method simply returns the - * link rate at which communications to the remote device occur. - * @remote_device: This parameter specifies the device for which to get the - * connection rate. - * - * Return the link rate at which we transfer for the supplied remote device. - */ -enum sas_linkrate scic_remote_device_get_connection_rate( - struct scic_sds_remote_device *remote_device); - #define scic_remote_device_is_atapi(device_handle) false /** -- cgit v1.2.3 From f619fffb4070a577524fd9eb68cea484d86d2b97 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 10:13:04 -0700 Subject: isci: fix remote_device start_io regressions While reducing indentation commits 7ab92c9e "isci: make a remote_node_context a proper member of a remote_device", 0879e6a6 "isci: merge remote_device substates into a single state machine" broke handling of situations where i/o's successfully started at the port level need to terminated when the remote_node declines to start the i/o. Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 834a3feaca63..3e567bf84c74 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1157,10 +1157,8 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_ha return status; status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (status != SCI_SUCCESS) - return status; - - status = request->state_handlers->start_handler(request); + if (status == SCI_SUCCESS) + status = request->state_handlers->start_handler(request); scic_sds_remote_device_start_request(sci_dev, request, status); } else @@ -1302,16 +1300,17 @@ static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_h status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); if (status != SCI_SUCCESS) - return status; + goto out; status = scic_sds_request_start(sci_req); if (status != SCI_SUCCESS) - return status; + goto out; sci_dev->working_request = sci_req; sci_base_state_machine_change_state(&sci_dev->state_machine, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + out: scic_sds_remote_device_start_request(sci_dev, sci_req, status); return status; -- cgit v1.2.3 From eb229671b1310c996dba7b78e21a9a9474edccdc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 14:05:57 -0700 Subject: isci: unify remote_device start_handlers Implement all states in scic_remote_device_start() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 77 +++++++++++---------------------------- drivers/scsi/isci/remote_device.h | 6 --- 2 files changed, 21 insertions(+), 62 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 3e567bf84c74..80eccdc1090f 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -291,7 +291,7 @@ static void scic_sds_cb_remote_device_rnc_destruct_complete(void *_dev) * ready state. This is the indication that the remote device object can also * transition to ready. */ -static void scic_sds_remote_device_resume_complete_handler(void *_dev) +static void remote_device_resume_done(void *_dev) { struct scic_sds_remote_device *sci_dev = _dev; enum scic_sds_remote_device_states state; @@ -409,12 +409,6 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_start_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - static enum sci_status scic_sds_remote_device_default_stop_handler( struct scic_sds_remote_device *sci_dev) { @@ -652,38 +646,6 @@ static enum sci_status scic_sds_remote_device_general_event_handler( true); } -/* - * ***************************************************************************** - * * STOPPED STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @device: - * - * This method takes the struct scic_sds_remote_device from a stopped state and - * attempts to start it. The RNC buffer for the device is constructed and the - * device state machine is transitioned to the - * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING. enum sci_status SCI_SUCCESS if there is - * an RNC buffer available to construct the remote device. - * SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer available in - * which to construct the remote device. - */ -static enum sci_status scic_sds_remote_device_stopped_state_start_handler( - struct scic_sds_remote_device *sci_dev) -{ - enum sci_status status; - - status = scic_sds_remote_node_context_resume(&sci_dev->rnc, - scic_sds_remote_device_resume_complete_handler, sci_dev); - - if (status == SCI_SUCCESS) - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STARTING); - - return status; -} - static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( struct scic_sds_remote_device *sci_dev) { @@ -1373,7 +1335,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_default_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1390,7 +1351,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .start_handler = scic_sds_remote_device_stopped_state_start_handler, .stop_handler = scic_sds_remote_device_stopped_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, @@ -1407,7 +1367,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_starting_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1424,7 +1383,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1441,7 +1399,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1458,7 +1415,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1475,7 +1431,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1492,7 +1447,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1509,7 +1463,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1526,7 +1479,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1543,7 +1495,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1560,7 +1511,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_stopping_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1577,7 +1527,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_default_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1594,7 +1543,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_resetting_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -1611,7 +1559,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .start_handler = scic_sds_remote_device_default_start_handler, .stop_handler = scic_sds_remote_device_default_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, @@ -2129,9 +2076,27 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci * the device when there have been no phys added to it. */ static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *sci_dev, - u32 timeout) + u32 timeout) { - return sci_dev->state_handlers->start_handler(sci_dev); + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_status status; + + if (state != SCI_BASE_REMOTE_DEVICE_STATE_STOPPED) { + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + status = scic_sds_remote_node_context_resume(&sci_dev->rnc, + remote_device_resume_done, + sci_dev); + if (status != SCI_SUCCESS) + return status; + + sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_STARTING); + + return SCI_SUCCESS; } static enum sci_status isci_remote_device_construct(struct isci_port *iport, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index fd24df31abd2..b778e0b49e33 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The start_handler specifies the method invoked when a user - * attempts to start a remote device. - */ - scic_sds_remote_device_handler_t start_handler; - /** * The stop_handler specifies the method invoked when a user attempts to * stop a remote device. -- cgit v1.2.3 From ec5756699b705c179a0680985e3d18a093f93fae Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 14:19:25 -0700 Subject: isci: unify remote_device stop_handlers Implement all states in scic_remote_device_stop() and delete the state handlers. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 254 +++++++++++++------------------------- drivers/scsi/isci/remote_device.h | 6 - 2 files changed, 83 insertions(+), 177 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 80eccdc1090f..d779939a6175 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -129,13 +129,91 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote wake_up(&ihost->eventq); } +/* called once the remote node context is ready to be freed. + * The remote device can now report that its stop operation is complete. none + */ +static void rnc_destruct_done(void *_dev) +{ + struct scic_sds_remote_device *sci_dev = _dev; + BUG_ON(sci_dev->started_request_count != 0); + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); +} -enum sci_status scic_remote_device_stop( - struct scic_sds_remote_device *sci_dev, - u32 timeout) +static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds_remote_device *sci_dev) { - return sci_dev->state_handlers->stop_handler(sci_dev); + struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + u32 i, request_count = sci_dev->started_request_count; + enum sci_status status = SCI_SUCCESS; + + for (i = 0; i < SCI_MAX_IO_REQUESTS && i < request_count; i++) { + struct scic_sds_request *sci_req; + enum sci_status s; + + sci_req = scic->io_request_table[i]; + if (!sci_req || sci_req->target_device != sci_dev) + continue; + s = scic_controller_terminate_request(scic, sci_dev, sci_req); + if (s != SCI_SUCCESS) + status = s; + } + + return status; +} + +enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev, + u32 timeout) +{ + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + + switch (state) { + case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: + case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: + case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + default: + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: + return SCI_SUCCESS; + case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: + /* device not started so there had better be no requests */ + BUG_ON(sci_dev->started_request_count != 0); + scic_sds_remote_node_context_destruct(&sci_dev->rnc, + rnc_destruct_done, sci_dev); + /* Transition to the stopping state and wait for the + * remote node to complete being posted and invalidated. + */ + sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); + return SCI_SUCCESS; + case SCI_BASE_REMOTE_DEVICE_STATE_READY: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); + if (sci_dev->started_request_count == 0) { + scic_sds_remote_node_context_destruct(&sci_dev->rnc, + rnc_destruct_done, sci_dev); + return SCI_SUCCESS; + } else + return scic_sds_remote_device_terminate_requests(sci_dev); + break; + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: + /* All requests should have been terminated, but if there is an + * attempt to stop a device already in the stopping state, then + * try again to terminate. + */ + return scic_sds_remote_device_terminate_requests(sci_dev); + case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: + sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); + return SCI_SUCCESS; + } } @@ -275,18 +353,6 @@ void scic_sds_remote_device_post_request( ); } -/* called once the remote node context is ready to be freed. - * The remote device can now report that its stop operation is complete. none - */ -static void scic_sds_cb_remote_device_rnc_destruct_complete(void *_dev) -{ - struct scic_sds_remote_device *sci_dev = _dev; - - BUG_ON(sci_dev->started_request_count != 0); - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); -} - /* called once the remote node context has transisitioned to a * ready state. This is the indication that the remote device object can also * transition to ready. @@ -358,47 +424,6 @@ static void scic_sds_remote_device_continue_request(void *dev) scic_controller_continue_io(sci_dev->working_request); } -/** - * This method will terminate all of the IO requests in the controllers IO - * request table that were targeted for this device. - * @sci_dev: This parameter specifies the remote device for which to - * attempt to terminate all requests. - * - * This method returns an indication as to whether all requests were - * successfully terminated. If a single request fails to be terminated, then - * this method will return the failure. - */ -static enum sci_status scic_sds_remote_device_terminate_requests( - struct scic_sds_remote_device *sci_dev) -{ - enum sci_status status = SCI_SUCCESS; - enum sci_status terminate_status = SCI_SUCCESS; - struct scic_sds_request *sci_req; - u32 index; - u32 request_count = sci_dev->started_request_count; - - for (index = 0; - (index < SCI_MAX_IO_REQUESTS) && (request_count > 0); - index++) { - sci_req = sci_dev->owning_port->owning_controller->io_request_table[index]; - - if ((sci_req != NULL) && (sci_req->target_device == sci_dev)) { - terminate_status = scic_controller_terminate_request( - sci_dev->owning_port->owning_controller, - sci_dev, - sci_req - ); - - if (terminate_status != SCI_SUCCESS) - status = terminate_status; - - request_count--; - } - } - - return status; -} - static enum sci_status default_device_handler(struct scic_sds_remote_device *sci_dev, const char *func) @@ -409,12 +434,6 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - static enum sci_status scic_sds_remote_device_default_fail_handler( struct scic_sds_remote_device *sci_dev) { @@ -646,12 +665,6 @@ static enum sci_status scic_sds_remote_device_general_event_handler( true); } -static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - return SCI_SUCCESS; -} - /** * * @sci_dev: The struct scic_sds_remote_device which is cast into a @@ -679,54 +692,6 @@ static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( return SCI_SUCCESS; } -/* - * ***************************************************************************** - * * STARTING STATE HANDLERS - * ***************************************************************************** */ - -static enum sci_status scic_sds_remote_device_starting_state_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - /* - * This device has not yet started so there had better be no IO requests - */ - BUG_ON(sci_dev->started_request_count != 0); - - /* - * Destroy the remote node context - */ - scic_sds_remote_node_context_destruct(&sci_dev->rnc, - scic_sds_cb_remote_device_rnc_destruct_complete, sci_dev); - - /* - * Transition to the stopping state and wait for the remote node to - * complete being posted and invalidated. - */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); - - return SCI_SUCCESS; -} - -static enum sci_status scic_sds_remote_device_ready_state_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - enum sci_status status = SCI_SUCCESS; - - /* Request the parent state machine to transition to the stopping state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); - - if (sci_dev->started_request_count == 0) { - scic_sds_remote_node_context_destruct(&sci_dev->rnc, - scic_sds_cb_remote_device_rnc_destruct_complete, - sci_dev); - } else - status = scic_sds_remote_device_terminate_requests(sci_dev); - - return status; -} - /** * * @device: The struct scic_sds_remote_device object which is cast to a @@ -832,32 +797,6 @@ static enum sci_status scic_sds_remote_device_ready_state_complete_request_handl return result; } -/* - * ***************************************************************************** - * * STOPPING STATE HANDLERS - * ***************************************************************************** */ - -/** - * - * @sci_dev: The struct scic_sds_remote_device which is cast into a - * struct scic_sds_remote_device. - * - * This method will stop a struct scic_sds_remote_device that is already in the - * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an error - * since we allow a stop request on a device that is alreay stopping or - * stopped. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( - struct scic_sds_remote_device *device) -{ - /* - * All requests should have been terminated, but if there is an - * attempt to stop a device already in the stopping state, then - * try again to terminate. */ - return scic_sds_remote_device_terminate_requests(device); -} - - /** * * @device: The device object for which the request is completing. @@ -891,8 +830,7 @@ static enum sci_status scic_sds_remote_device_stopping_state_complete_request_ha if (scic_sds_remote_device_get_request_count(sci_dev) == 0) scic_sds_remote_node_context_destruct(&sci_dev->rnc, - scic_sds_cb_remote_device_rnc_destruct_complete, - sci_dev); + rnc_destruct_done, sci_dev); return SCI_SUCCESS; } @@ -905,17 +843,6 @@ static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_han return SCI_SUCCESS; } -static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( - struct scic_sds_remote_device *sci_dev) -{ - sci_base_state_machine_change_state( - &sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING - ); - - return SCI_SUCCESS; -} - /* complete requests for this device while it is in the * SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the complete * method for the request object and if that is successful the port object is @@ -1335,7 +1262,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .stop_handler = scic_sds_remote_device_default_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, @@ -1351,7 +1277,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .stop_handler = scic_sds_remote_device_stopped_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, @@ -1367,7 +1292,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .stop_handler = scic_sds_remote_device_starting_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, @@ -1383,7 +1307,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, @@ -1399,7 +1322,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, @@ -1415,7 +1337,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, @@ -1431,7 +1352,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, @@ -1447,7 +1367,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, @@ -1463,7 +1382,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, @@ -1479,7 +1397,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, @@ -1495,7 +1412,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .stop_handler = scic_sds_remote_device_ready_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, @@ -1511,7 +1427,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .stop_handler = scic_sds_remote_device_stopping_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, @@ -1527,7 +1442,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .stop_handler = scic_sds_remote_device_default_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, @@ -1543,7 +1457,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .stop_handler = scic_sds_remote_device_resetting_state_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, @@ -1559,7 +1472,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .stop_handler = scic_sds_remote_device_default_stop_handler, .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index b778e0b49e33..ca8c5d16f790 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The stop_handler specifies the method invoked when a user attempts to - * stop a remote device. - */ - scic_sds_remote_device_handler_t stop_handler; - /** * The fail_handler specifies the method invoked when a remote device * failure has occurred. A failure may be due to an inability to -- cgit v1.2.3 From 1a6de2562b38e1e0e74c468554111ac54c062928 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 14:35:43 -0700 Subject: isci: kill remote_device fail_handler This is just unused infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 21 --------------------- drivers/scsi/isci/remote_device.h | 7 ------- 2 files changed, 28 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index d779939a6175..5141a924149c 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -434,12 +434,6 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_fail_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - static enum sci_status scic_sds_remote_device_default_destruct_handler( struct scic_sds_remote_device *sci_dev) { @@ -1262,7 +1256,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1277,7 +1270,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1292,7 +1284,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1307,7 +1298,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1322,7 +1312,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1337,7 +1326,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1352,7 +1340,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1367,7 +1354,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1382,7 +1368,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1397,7 +1382,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1412,7 +1396,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1427,7 +1410,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1442,7 +1424,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, @@ -1457,7 +1438,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, @@ -1472,7 +1452,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .fail_handler = scic_sds_remote_device_default_fail_handler, .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index ca8c5d16f790..dd8ac514cfd4 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,13 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The fail_handler specifies the method invoked when a remote device - * failure has occurred. A failure may be due to an inability to - * initialize/configure the device. - */ - scic_sds_remote_device_handler_t fail_handler; - /** * The destruct_handler specifies the method invoked when attempting to * destruct a remote device. -- cgit v1.2.3 From b8d82f6cdd0f04ddfa877d8d886e56ebd8526d25 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 14:38:26 -0700 Subject: isci: unify remote_device destruct_handlers Implement all states in scic_remote_device_destruct() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 66 ++++++++++----------------------------- drivers/scsi/isci/remote_device.h | 6 ---- 2 files changed, 17 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 5141a924149c..dd66c0e8ac27 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -434,12 +434,6 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_destruct_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - static enum sci_status scic_sds_remote_device_default_reset_handler( struct scic_sds_remote_device *sci_dev) { @@ -659,33 +653,6 @@ static enum sci_status scic_sds_remote_device_general_event_handler( true); } -/** - * - * @sci_dev: The struct scic_sds_remote_device which is cast into a - * struct scic_sds_remote_device. - * - * This method will destruct a struct scic_sds_remote_device that is in a stopped - * state. This is the only state from which a destruct request will succeed. - * The RNi for this struct scic_sds_remote_device is returned to the free pool and the - * device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( - struct scic_sds_remote_device *sci_dev) -{ - struct scic_sds_controller *scic; - - scic = scic_sds_remote_device_get_controller(sci_dev); - scic_sds_controller_free_remote_node_context(scic, sci_dev, - sci_dev->rnc.remote_node_index); - sci_dev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_FINAL); - - return SCI_SUCCESS; -} - /** * * @device: The struct scic_sds_remote_device object which is cast to a @@ -1256,7 +1223,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, @@ -1270,7 +1236,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, @@ -1284,7 +1249,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, @@ -1298,7 +1262,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, @@ -1312,7 +1275,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, @@ -1326,7 +1288,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, @@ -1340,7 +1301,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, @@ -1354,7 +1314,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, @@ -1368,7 +1327,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, @@ -1382,7 +1340,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, @@ -1396,7 +1353,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, @@ -1410,7 +1366,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, @@ -1424,7 +1379,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, @@ -1438,7 +1392,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, @@ -1452,7 +1405,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .destruct_handler = scic_sds_remote_device_default_destruct_handler, .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, @@ -1494,7 +1446,23 @@ static void scic_sds_remote_device_initial_state_enter(void *object) */ static enum sci_status scic_remote_device_destruct(struct scic_sds_remote_device *sci_dev) { - return sci_dev->state_handlers->destruct_handler(sci_dev); + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + struct scic_sds_controller *scic; + + if (state != SCI_BASE_REMOTE_DEVICE_STATE_STOPPED) { + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + scic = sci_dev->owning_port->owning_controller; + scic_sds_controller_free_remote_node_context(scic, sci_dev, + sci_dev->rnc.remote_node_index); + sci_dev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_FINAL); + + return SCI_SUCCESS; } /** diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index dd8ac514cfd4..d09e3f273edb 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a remote device. - */ - scic_sds_remote_device_handler_t destruct_handler; - /** * The reset handler specifies the method invloked when requesting to * reset a remote device. -- cgit v1.2.3 From 4fd0d2e9bf5152456952ad7c5b6f3d8565de7737 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 14:48:54 -0700 Subject: isci: unify remote_device reset_handlers Implement all states in scic_remote_device_reset() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 69 +++++++++++++++------------------------ drivers/scsi/isci/remote_device.h | 6 ---- 2 files changed, 27 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index dd66c0e8ac27..d8968f32ad9a 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -216,11 +216,34 @@ enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev, } } - -enum sci_status scic_remote_device_reset( - struct scic_sds_remote_device *sci_dev) +enum sci_status scic_remote_device_reset(struct scic_sds_remote_device *sci_dev) { - return sci_dev->state_handlers->reset_handler(sci_dev); + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + + switch (state) { + case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: + case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: + case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: + case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: + case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + default: + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + case SCI_BASE_REMOTE_DEVICE_STATE_READY: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_RESETTING); + return SCI_SUCCESS; + } } @@ -434,12 +457,6 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_reset_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - static enum sci_status scic_sds_remote_device_default_reset_complete_handler( struct scic_sds_remote_device *sci_dev) { @@ -653,23 +670,6 @@ static enum sci_status scic_sds_remote_device_general_event_handler( true); } -/** - * - * @device: The struct scic_sds_remote_device object which is cast to a - * struct scic_sds_remote_device object. - * - * This is the ready state device reset handler enum sci_status - */ -static enum sci_status scic_sds_remote_device_ready_state_reset_handler( - struct scic_sds_remote_device *sci_dev) -{ - /* Request the parent state machine to transition to the stopping state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING); - - return SCI_SUCCESS; -} - /* * This method will attempt to start a task request for this device object. The * remote device object will issue the start request for the task and if @@ -1223,7 +1223,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1236,7 +1235,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1249,7 +1247,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1262,7 +1259,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, @@ -1275,7 +1271,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1288,7 +1283,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, @@ -1301,7 +1295,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, @@ -1314,7 +1307,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, @@ -1327,7 +1319,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .reset_handler = scic_sds_remote_device_ready_state_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, @@ -1340,7 +1331,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1353,7 +1343,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, @@ -1366,7 +1355,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, @@ -1379,7 +1367,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1392,7 +1379,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, @@ -1405,7 +1391,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .reset_handler = scic_sds_remote_device_default_reset_handler, .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index d09e3f273edb..ab7a4c85f6de 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The reset handler specifies the method invloked when requesting to - * reset a remote device. - */ - scic_sds_remote_device_handler_t reset_handler; - /** * The reset complete handler specifies the method invloked when * reporting that a reset has completed to the remote device. -- cgit v1.2.3 From 815151826553f875846ebba9696777a424ee62e5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 14:53:00 -0700 Subject: isci: unify remote_device reset_complete_handlers Implement all states in scic_remote_device_reset_complete() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 49 ++++++++++----------------------------- drivers/scsi/isci/remote_device.h | 6 ----- 2 files changed, 12 insertions(+), 43 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index d8968f32ad9a..658781dd65e6 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -246,15 +246,20 @@ enum sci_status scic_remote_device_reset(struct scic_sds_remote_device *sci_dev) } } - -enum sci_status scic_remote_device_reset_complete( - struct scic_sds_remote_device *sci_dev) +enum sci_status scic_remote_device_reset_complete(struct scic_sds_remote_device *sci_dev) { - return sci_dev->state_handlers->reset_complete_handler(sci_dev); -} + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + + if (state != SCI_BASE_REMOTE_DEVICE_STATE_RESETTING) { + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + } -#define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0) -#define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES) + sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_READY); + return SCI_SUCCESS; +} /** * @@ -457,12 +462,6 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_reset_complete_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - static enum sci_status scic_sds_remote_device_default_suspend_handler( struct scic_sds_remote_device *sci_dev, u32 suspend_type) { @@ -795,15 +794,6 @@ static enum sci_status scic_sds_remote_device_stopping_state_complete_request_ha return SCI_SUCCESS; } -static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( - struct scic_sds_remote_device *sci_dev) -{ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_READY); - - return SCI_SUCCESS; -} - /* complete requests for this device while it is in the * SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the complete * method for the request object and if that is successful the port object is @@ -1223,7 +1213,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1235,7 +1224,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1247,7 +1235,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1259,7 +1246,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1271,7 +1257,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1283,7 +1268,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1295,7 +1279,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1307,7 +1290,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1319,7 +1301,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1331,7 +1312,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1343,7 +1323,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1355,7 +1334,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1367,7 +1345,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1379,7 +1356,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, @@ -1391,7 +1367,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index ab7a4c85f6de..51094352d952 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The reset complete handler specifies the method invloked when - * reporting that a reset has completed to the remote device. - */ - scic_sds_remote_device_handler_t reset_complete_handler; - /** * The start_io_handler specifies the method invoked when a user * attempts to start an IO request for a remote device. -- cgit v1.2.3 From 1860655706ee5a7e3f3adeebd4927fed98860462 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 14:57:11 -0700 Subject: isci: unify remote_device start_io_handlers Implement all states in scic_sds_remote_device_start_io() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 334 ++++++++++++++------------------------ drivers/scsi/isci/remote_device.h | 6 - 2 files changed, 125 insertions(+), 215 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 658781dd65e6..f4ba5be00c03 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -305,22 +305,132 @@ enum sci_status scic_sds_remote_device_event_handler( return sci_dev->state_handlers->event_handler(sci_dev, event_code); } -/** - * - * @controller: The controller that is starting the io request. - * @sci_dev: The remote device for which the start io handling is being - * requested. - * @io_request: The io request that is being started. - * - * This method invokes the remote device start io handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_start_io( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request) +static void scic_sds_remote_device_start_request(struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req, + enum sci_status status) { - return sci_dev->state_handlers->start_io_handler( - sci_dev, io_request); + struct scic_sds_port *sci_port = sci_dev->owning_port; + + /* cleanup requests that failed after starting on the port */ + if (status != SCI_SUCCESS) + scic_sds_port_complete_io(sci_port, sci_dev, sci_req); + else + scic_sds_remote_device_increment_request_count(sci_dev); +} + +enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + struct scic_sds_port *sci_port = sci_dev->owning_port; + enum sci_status status; + + switch (state) { + case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: + case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: + case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: + case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: + case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + default: + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + case SCI_BASE_REMOTE_DEVICE_STATE_READY: + /* attempt to start an io request for this device object. The remote + * device object will issue the start request for the io and if + * successful it will start the request for the port object then + * increment its own request count. + */ + status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + if (status != SCI_SUCCESS) + break; + + status = scic_sds_request_start(sci_req); + break; + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: { + /* handle the start io operation for a sata device that is in + * the command idle state. - Evalute the type of IO request to + * be started - If its an NCQ request change to NCQ substate - + * If its any other command change to the CMD substate + * + * If this is a softreset we may want to have a different + * substate. + */ + enum scic_sds_remote_device_states new_state; + + status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + if (status != SCI_SUCCESS) + break; + + status = sci_req->state_handlers->start_handler(sci_req); + if (status != SCI_SUCCESS) + break; + + if (isci_sata_get_sat_protocol(sci_req->ireq) == SAT_PROTOCOL_FPDMA) + new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ; + else { + sci_dev->working_request = sci_req; + new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD; + } + sci_base_state_machine_change_state(sm, new_state); + break; + } + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: + if (isci_sata_get_sat_protocol(sci_req->ireq) == SAT_PROTOCOL_FPDMA) { + status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + if (status != SCI_SUCCESS) + break; + + status = sci_req->state_handlers->start_handler(sci_req); + } else + return SCI_FAILURE_INVALID_STATE; + break; + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + if (status != SCI_SUCCESS) + break; + + status = scic_sds_request_start(sci_req); + if (status != SCI_SUCCESS) + break; + + sci_dev->working_request = sci_req; + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + break; + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + /* device is already handling a command it can not accept new commands + * until this one is complete. + */ + return SCI_FAILURE_INVALID_STATE; + } + + scic_sds_remote_device_start_request(sci_dev, sci_req, status); + return status; } /** @@ -409,32 +519,6 @@ static void remote_device_resume_done(void *_dev) } } -/** - * - * @device: This parameter specifies the device for which the request is being - * started. - * @request: This parameter specifies the request being started. - * @status: This parameter specifies the current start operation status. - * - * This method will perform the STP request start processing common to IO - * requests and task requests of all types. none - */ -static void scic_sds_remote_device_start_request( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req, - enum sci_status status) -{ - /* We still have a fault in starting the io complete it on the port */ - if (status == SCI_SUCCESS) - scic_sds_remote_device_increment_request_count(sci_dev); - else{ - sci_dev->owning_port->state_handlers->complete_io_handler( - sci_dev->owning_port, sci_dev, sci_req - ); - } -} - - /** * * @request: This parameter specifies the request being continued. @@ -699,35 +783,6 @@ static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( return result; } -/* - * This method will attempt to start an io request for this device object. The - * remote device object will issue the start request for the io and if - * successful it will start the request for the port object then increment its - * own requet count. enum sci_status SCI_SUCCESS if the io request is started for - * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request - * object could not get the resources to start. - */ -static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status result; - - /* See if the port is in a state where we can start the IO request */ - result = scic_sds_port_start_io( - scic_sds_remote_device_get_port(sci_dev), sci_dev, request); - - if (result == SCI_SUCCESS) { - result = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (result == SCI_SUCCESS) - result = scic_sds_request_start(request); - - scic_sds_remote_device_start_request(sci_dev, request, result); - } - - return result; -} - /* * This method will complete the request for the remote device object. The * method will call the completion handler for the request object and if @@ -920,48 +975,6 @@ out: return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; } -/* handle the start io operation for a sata device that is in the command idle - * state. - Evalute the type of IO request to be started - If its an NCQ - * request change to NCQ substate - If its any other command change to the CMD - * substate - * - * If this is a softreset we may want to have a different substate. - */ -static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status; - struct isci_request *isci_request = request->ireq; - enum scic_sds_remote_device_states new_state; - - /* Will the port allow the io request to start? */ - status = sci_dev->owning_port->state_handlers->start_io_handler( - sci_dev->owning_port, sci_dev, request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (status != SCI_SUCCESS) - goto out; - - status = request->state_handlers->start_handler(request); - if (status != SCI_SUCCESS) - goto out; - - if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) - new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ; - else { - sci_dev->working_request = request; - new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD; - } - sci_base_state_machine_change_state(&sci_dev->state_machine, new_state); -out: - scic_sds_remote_device_start_request(sci_dev, request, status); - return status; -} - - static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( struct scic_sds_remote_device *sci_dev, u32 event_code) @@ -982,31 +995,6 @@ static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_hand return status; } -static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status; - struct isci_request *isci_request = request->ireq; - scic_sds_port_io_request_handler_t start_io; - - if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { - start_io = sci_dev->owning_port->state_handlers->start_io_handler; - status = start_io(sci_dev->owning_port, sci_dev, request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); - if (status == SCI_SUCCESS) - status = request->state_handlers->start_handler(request); - - scic_sds_remote_device_start_request(sci_dev, request, status); - } else - status = SCI_FAILURE_INVALID_STATE; - - return status; -} - static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(struct scic_sds_remote_device *sci_dev, u32 frame_index) { @@ -1046,16 +1034,6 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl return status; } -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - /* device is already handling a command it can not accept new commands - * until this one is complete. - */ - return SCI_FAILURE_INVALID_STATE; -} - static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( struct scic_sds_remote_device *sci_dev, u32 suspend_type) @@ -1080,13 +1058,6 @@ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handl frame_index); } -static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; -} - static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( struct scic_sds_remote_device *device, struct scic_sds_request *request) @@ -1126,46 +1097,6 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl isci_remote_device_ready(scic->ihost, idev); } -static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - enum sci_status status; - - /* Will the port allow the io request to start? */ - status = sci_dev->owning_port->state_handlers->start_io_handler( - sci_dev->owning_port, sci_dev, sci_req); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); - if (status != SCI_SUCCESS) - goto out; - - status = scic_sds_request_start(sci_req); - if (status != SCI_SUCCESS) - goto out; - - sci_dev->working_request = sci_req; - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - - out: - scic_sds_remote_device_start_request(sci_dev, sci_req, status); - - return status; -} - -static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - /* device is already handling a command it can not accept new commands - * until this one is complete. - */ - return SCI_FAILURE_INVALID_STATE; -} - static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(struct scic_sds_remote_device *sci_dev, struct scic_sds_request *sci_req) @@ -1213,7 +1144,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, @@ -1224,7 +1154,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, @@ -1235,7 +1164,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, @@ -1246,7 +1174,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, @@ -1257,7 +1184,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, @@ -1268,7 +1194,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, @@ -1279,7 +1204,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, @@ -1290,7 +1214,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, @@ -1301,7 +1224,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, @@ -1312,7 +1234,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_io_handler = scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, @@ -1323,7 +1244,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, @@ -1334,7 +1254,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, @@ -1345,7 +1264,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, @@ -1356,7 +1274,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, @@ -1367,7 +1284,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .start_io_handler = scic_sds_remote_device_default_start_request_handler, .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 51094352d952..58ce41af9e66 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The start_io_handler specifies the method invoked when a user - * attempts to start an IO request for a remote device. - */ - scic_sds_remote_device_request_handler_t start_io_handler; - /** * The complete_io_handler specifies the method invoked when a user * attempts to complete an IO request for a remote device. -- cgit v1.2.3 From 10a09e64be2580ceef8539629fb953b7d94fa35f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 15:33:43 -0700 Subject: isci: unify remote_device complete_io_handlers Implement all states in scic_sds_remote_device_complete_io() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 168 +++++++++++++++++++------------------- drivers/scsi/isci/remote_device.h | 6 -- 2 files changed, 85 insertions(+), 89 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index f4ba5be00c03..a6247675c5c7 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -433,22 +433,92 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic return status; } -/** - * - * @controller: The controller that is completing the io request. - * @sci_dev: The remote device for which the complete io handling is being - * requested. - * @io_request: The io request that is being completed. - * - * This method invokes the remote device complete io handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_complete_io( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request) +static enum sci_status common_complete_io(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) { - return sci_dev->state_handlers->complete_io_handler( - sci_dev, io_request); + enum sci_status status; + + status = scic_sds_request_complete(sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_port_complete_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + return status; + + scic_sds_remote_device_decrement_request_count(sci_dev); + return status; +} + +enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + struct scic_sds_port *sci_port = sci_dev->owning_port; + enum sci_status status; + + switch (state) { + case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: + case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: + case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + default: + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + case SCI_BASE_REMOTE_DEVICE_STATE_READY: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: + status = common_complete_io(sci_port, sci_dev, sci_req); + break; + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + status = common_complete_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + break; + + if (sci_req->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + /* This request causes hardware error, device needs to be Lun Reset. + * So here we force the state machine to IDLE state so the rest IOs + * can reach RNC state handler, these IOs will be completed by RNC with + * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". + */ + sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET); + } else if (scic_sds_remote_device_get_request_count(sci_dev) == 0) + sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + break; + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + status = common_complete_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + break; + sci_base_state_machine_change_state(sm, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + break; + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: + status = common_complete_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + break; + + if (scic_sds_remote_device_get_request_count(sci_dev) == 0) + scic_sds_remote_node_context_destruct(&sci_dev->rnc, + rnc_destruct_done, + sci_dev); + break; + } + + if (status != SCI_SUCCESS) + dev_err(scirdev_to_dev(sci_dev), + "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " + "could not complete\n", __func__, sci_port, + sci_dev, sci_req, status); + + return status; } /** @@ -1058,32 +1128,6 @@ static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handl frame_index); } -static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - struct scic_sds_request *sci_req = request; - enum sci_status status; - - status = scic_sds_io_request_complete(sci_req); - if (status != SCI_SUCCESS) - goto out; - - status = scic_sds_port_complete_io(device->owning_port, device, sci_req); - if (status != SCI_SUCCESS) - goto out; - - scic_sds_remote_device_decrement_request_count(device); - out: - if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(device), - "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " - "could not complete\n", - __func__, device->owning_port, device, sci_req, status); - - return status; -} - static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) { struct scic_sds_remote_device *sci_dev = _dev; @@ -1097,33 +1141,6 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl isci_remote_device_ready(scic->ihost, idev); } -static enum sci_status -scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - enum sci_status status; - - status = scic_sds_io_request_complete(sci_req); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_port_complete_io(sci_dev->owning_port, sci_dev, sci_req); - if (status != SCI_SUCCESS) { - dev_err(scirdev_to_dev(sci_dev), - "%s: SCIC SDS Remote Device 0x%p io request " - "0x%p could not be completd on the port 0x%p " - "failed with status %d.\n", __func__, sci_dev, sci_req, - sci_dev->owning_port, status); - return status; - } - - scic_sds_remote_device_decrement_request_count(sci_dev); - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - - return status; -} - static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( struct scic_sds_remote_device *sci_dev, u32 frame_index) @@ -1144,7 +1161,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1154,7 +1170,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1164,7 +1179,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1174,7 +1188,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, @@ -1184,7 +1197,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1194,7 +1206,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, @@ -1204,7 +1215,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, @@ -1214,7 +1224,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .complete_io_handler = scic_sds_stp_remote_device_complete_request, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, @@ -1224,7 +1233,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, @@ -1234,7 +1242,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1244,7 +1251,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .complete_io_handler = scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1254,7 +1260,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, @@ -1264,7 +1269,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, @@ -1274,7 +1278,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, @@ -1284,7 +1287,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 58ce41af9e66..64767656ee0d 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The complete_io_handler specifies the method invoked when a user - * attempts to complete an IO request for a remote device. - */ - scic_sds_remote_device_request_handler_t complete_io_handler; - /** * The continue_io_handler specifies the method invoked when a user * attempts to continue an IO request for a remote device. -- cgit v1.2.3 From c027a20bf3fa831fed70b1662e526be04447ab07 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 15:46:18 -0700 Subject: isci: kill remote_device continue_io_handler This is unused infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 22 ---------------------- drivers/scsi/isci/remote_device.h | 6 ------ 2 files changed, 28 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index a6247675c5c7..3580c0a5a719 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -751,13 +751,6 @@ static enum sci_status scic_sds_remote_device_default_complete_request_handler( return default_device_handler(sci_dev, __func__); } -static enum sci_status scic_sds_remote_device_default_continue_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - return default_device_handler(sci_dev, __func__); -} - /** * * @device: The struct scic_sds_remote_device which is then cast into a @@ -1161,7 +1154,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1170,7 +1162,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1179,7 +1170,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1188,7 +1178,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1197,7 +1186,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1206,7 +1194,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, @@ -1215,7 +1202,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1224,7 +1210,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1233,7 +1218,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1242,7 +1226,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1251,7 +1234,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1260,7 +1242,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1269,7 +1250,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1278,7 +1258,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, @@ -1287,7 +1266,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 64767656ee0d..04a2b54a0dd5 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The continue_io_handler specifies the method invoked when a user - * attempts to continue an IO request for a remote device. - */ - scic_sds_remote_device_request_handler_t continue_io_handler; - /** * The start_task_handler specifies the method invoked when a user * attempts to start a task management request for a remote device. -- cgit v1.2.3 From 84b9b029bc4121c43294e27aeaa0350a6d07450c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 15:53:25 -0700 Subject: isci: unify remote_device start_task_handlers Implement all states in scic_sds_remote_device_start_task() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 236 +++++++++++++++----------------------- drivers/scsi/isci/remote_device.h | 6 - 2 files changed, 90 insertions(+), 152 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 3580c0a5a719..3e7e95200a1e 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -521,22 +521,97 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s return status; } -/** - * - * @controller: The controller that is starting the task request. - * @sci_dev: The remote device for which the start task handling is being - * requested. - * @io_request: The task request that is being started. - * - * This method invokes the remote device start task handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_start_task( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request) +static void scic_sds_remote_device_continue_request(void *dev) +{ + struct scic_sds_remote_device *sci_dev = dev; + + /* we need to check if this request is still valid to continue. */ + if (sci_dev->working_request) + scic_controller_continue_io(sci_dev->working_request); +} + +enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) { - return sci_dev->state_handlers->start_task_handler( - sci_dev, io_request); + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + struct scic_sds_port *sci_port = sci_dev->owning_port; + enum sci_status status; + + switch (state) { + case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: + case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: + case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: + case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: + case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + default: + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, sci_req); + if (status != SCI_SUCCESS) + goto out; + + status = sci_req->state_handlers->start_handler(sci_req); + if (status != SCI_SUCCESS) + goto out; + + /* Note: If the remote device state is not IDLE this will + * replace the request that probably resulted in the task + * management request. + */ + sci_dev->working_request = sci_req; + sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + + /* The remote node context must cleanup the TCi to NCQ mapping + * table. The only way to do this correctly is to either write + * to the TLCR register or to invalidate and repost the RNC. In + * either case the remote node context state machine will take + * the correct action when the remote node context is suspended + * and later resumed. + */ + scic_sds_remote_node_context_suspend(&sci_dev->rnc, + SCI_SOFTWARE_SUSPENSION, NULL, NULL); + scic_sds_remote_node_context_resume(&sci_dev->rnc, + scic_sds_remote_device_continue_request, + sci_dev); + + out: + scic_sds_remote_device_start_request(sci_dev, sci_req, status); + /* We need to let the controller start request handler know that + * it can't post TC yet. We will provide a callback function to + * post TC when RNC gets resumed. + */ + return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; + case SCI_BASE_REMOTE_DEVICE_STATE_READY: + status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + if (status != SCI_SUCCESS) + return status; + + status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, sci_req); + if (status != SCI_SUCCESS) + break; + + status = scic_sds_request_start(sci_req); + break; + } + scic_sds_remote_device_start_request(sci_dev, sci_req, status); + + return status; } /** @@ -589,23 +664,6 @@ static void remote_device_resume_done(void *_dev) } } -/** - * - * @request: This parameter specifies the request being continued. - * - * This method will continue to post tc for a STP request. This method usually - * serves as a callback when RNC gets resumed during a task management - * sequence. none - */ -static void scic_sds_remote_device_continue_request(void *dev) -{ - struct scic_sds_remote_device *sci_dev = dev; - - /* we need to check if this request is still valid to continue. */ - if (sci_dev->working_request) - scic_controller_continue_io(sci_dev->working_request); -} - static enum sci_status default_device_handler(struct scic_sds_remote_device *sci_dev, const char *func) @@ -737,13 +795,6 @@ static enum sci_status scic_sds_remote_device_default_frame_handler( return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_start_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - return default_device_handler(sci_dev, __func__); -} - static enum sci_status scic_sds_remote_device_default_complete_request_handler( struct scic_sds_remote_device *sci_dev, struct scic_sds_request *request) @@ -816,36 +867,6 @@ static enum sci_status scic_sds_remote_device_general_event_handler( true); } -/* - * This method will attempt to start a task request for this device object. The - * remote device object will issue the start request for the task and if - * successful it will start the request for the port object then increment its - * own requet count. enum sci_status SCI_SUCCESS if the task request is started for - * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request - * object could not get the resources to start. - */ -static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status result; - - /* See if the port is in a state where we can start the IO request */ - result = scic_sds_port_start_io( - scic_sds_remote_device_get_port(sci_dev), sci_dev, request); - - if (result == SCI_SUCCESS) { - result = scic_sds_remote_node_context_start_task(&sci_dev->rnc, - request); - if (result == SCI_SUCCESS) - result = scic_sds_request_start(request); - - scic_sds_remote_device_start_request(sci_dev, request, result); - } - - return result; -} - /* * This method will complete the request for the remote device object. The * method will call the completion handler for the request object and if @@ -976,68 +997,6 @@ static enum sci_status scic_sds_stp_remote_device_complete_request(struct scic_s return status; } -/* scic_sds_stp_remote_device_ready_substate_start_request_handler - start stp - * @device: The target device a task management request towards to. - * @request: The task request. - * - * This is the READY NCQ substate handler to start task management request. In - * this routine, we suspend and resume the RNC. enum sci_status Always return - * SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to let - * controller_start_task_handler know that the controller can't post TC for - * task request yet, instead, when RNC gets resumed, a controller_continue_task - * callback will be called. - */ -static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( - struct scic_sds_remote_device *device, - struct scic_sds_request *request) -{ - enum sci_status status; - - /* Will the port allow the io request to start? */ - status = device->owning_port->state_handlers->start_io_handler( - device->owning_port, device, request); - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_remote_node_context_start_task(&device->rnc, request); - if (status != SCI_SUCCESS) - goto out; - - status = request->state_handlers->start_handler(request); - if (status != SCI_SUCCESS) - goto out; - - /* - * Note: If the remote device state is not IDLE this will replace - * the request that probably resulted in the task management request. - */ - device->working_request = request; - sci_base_state_machine_change_state(&device->state_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - - /* - * The remote node context must cleanup the TCi to NCQ mapping table. - * The only way to do this correctly is to either write to the TLCR - * register or to invalidate and repost the RNC. In either case the - * remote node context state machine will take the correct action when - * the remote node context is suspended and later resumed. - */ - scic_sds_remote_node_context_suspend(&device->rnc, - SCI_SOFTWARE_SUSPENSION, NULL, NULL); - scic_sds_remote_node_context_resume(&device->rnc, - scic_sds_remote_device_continue_request, - device); - -out: - scic_sds_remote_device_start_request(device, request, status); - /* - * We need to let the controller start request handler know that it can't - * post TC yet. We will provide a callback function to post TC when RNC gets - * resumed. - */ - return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; -} - static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( struct scic_sds_remote_device *sci_dev, u32 event_code) @@ -1154,7 +1113,6 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1162,7 +1120,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1170,7 +1127,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1178,7 +1134,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1186,7 +1141,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1194,7 +1148,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1202,7 +1155,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1210,7 +1162,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1218,7 +1169,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1226,7 +1176,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1234,7 +1183,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1242,7 +1190,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1250,7 +1197,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1258,7 +1204,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, @@ -1266,7 +1211,6 @@ static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_ .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .start_task_handler = scic_sds_remote_device_default_start_request_handler, .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 04a2b54a0dd5..fb2b0079fe75 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,12 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The start_task_handler specifies the method invoked when a user - * attempts to start a task management request for a remote device. - */ - scic_sds_remote_device_request_handler_t start_task_handler; - /** * The complete_task_handler specifies the method invoked when a user * attempts to complete a task management request for a remote device. -- cgit v1.2.3 From e4a867bb4a7617dc1067e1c41627782f3c6c284c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 16:01:05 -0700 Subject: isci: kill remote_device complete_task_handler This is unused infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 152 -------------------------------------- drivers/scsi/isci/remote_device.h | 7 -- 2 files changed, 159 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 3e7e95200a1e..3344f38355cd 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -795,13 +795,6 @@ static enum sci_status scic_sds_remote_device_default_frame_handler( return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_complete_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - return default_device_handler(sci_dev, __func__); -} - /** * * @device: The struct scic_sds_remote_device which is then cast into a @@ -867,136 +860,6 @@ static enum sci_status scic_sds_remote_device_general_event_handler( true); } -/* - * This method will complete the request for the remote device object. The - * method will call the completion handler for the request object and if - * successful it will complete the request on the port object then decrement - * its own started_request_count. enum sci_status - */ -static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status result; - - result = scic_sds_request_complete(request); - - if (result != SCI_SUCCESS) - return result; - - /* See if the port is in a state - * where we can start the IO request */ - result = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(sci_dev), - sci_dev, request); - - if (result == SCI_SUCCESS) - scic_sds_remote_device_decrement_request_count(sci_dev); - - return result; -} - -/** - * - * @device: The device object for which the request is completing. - * @request: The task request that is being completed. - * - * This method completes requests for this struct scic_sds_remote_device while it is - * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the - * complete method for the request object and if that is successful the port - * object is called to complete the task request. Then the device object itself - * completes the task request. If struct scic_sds_remote_device started_request_count - * goes to 0 and the invalidate RNC request has completed the device object can - * transition to the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. enum sci_status - */ -static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status = SCI_SUCCESS; - - status = scic_sds_request_complete(request); - - if (status != SCI_SUCCESS) - return status; - - status = scic_sds_port_complete_io(scic_sds_remote_device_get_port(sci_dev), - sci_dev, request); - if (status != SCI_SUCCESS) - return status; - - scic_sds_remote_device_decrement_request_count(sci_dev); - - if (scic_sds_remote_device_get_request_count(sci_dev) == 0) - scic_sds_remote_node_context_destruct(&sci_dev->rnc, - rnc_destruct_done, sci_dev); - return SCI_SUCCESS; -} - -/* complete requests for this device while it is in the - * SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the complete - * method for the request object and if that is successful the port object is - * called to complete the task request. Then the device object itself completes - * the task request. enum sci_status - */ -static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *request) -{ - enum sci_status status = SCI_SUCCESS; - - status = scic_sds_request_complete(request); - - if (status == SCI_SUCCESS) { - status = scic_sds_port_complete_io( - scic_sds_remote_device_get_port(sci_dev), - sci_dev, request); - - if (status == SCI_SUCCESS) { - scic_sds_remote_device_decrement_request_count(sci_dev); - } - } - - return status; -} - -static enum sci_status scic_sds_stp_remote_device_complete_request(struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - enum sci_status status; - - status = scic_sds_io_request_complete(sci_req); - if (status != SCI_SUCCESS) - goto out; - - status = scic_sds_port_complete_io(sci_dev->owning_port, sci_dev, sci_req); - if (status != SCI_SUCCESS) - goto out; - - scic_sds_remote_device_decrement_request_count(sci_dev); - if (sci_req->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - /* This request causes hardware error, device needs to be Lun Reset. - * So here we force the state machine to IDLE state so the rest IOs - * can reach RNC state handler, these IOs will be completed by RNC with - * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". - */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET); - } else if (scic_sds_remote_device_get_request_count(sci_dev) == 0) - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - - - out: - if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(sci_dev), - "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " - "could not complete\n", __func__, sci_dev->owning_port, - sci_dev, sci_req, status); - - return status; -} - static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( struct scic_sds_remote_device *sci_dev, u32 event_code) @@ -1113,105 +976,90 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .complete_task_handler = scic_sds_stp_remote_device_complete_request, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index fb2b0079fe75..dbfb13e2851d 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,13 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - /** - * The complete_task_handler specifies the method invoked when a user - * attempts to complete a task management request for a remote device. - */ - scic_sds_remote_device_request_handler_t complete_task_handler; - - scic_sds_remote_device_suspend_handler_t suspend_handler; scic_sds_remote_device_resume_handler_t resume_handler; scic_sds_remote_device_event_handler_t event_handler; -- cgit v1.2.3 From 323f0ec0fc72670f71210ba89611f6a1ec234394 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 16:15:47 -0700 Subject: isci: unify remote_device suspend_handlers Implement all states in scic_sds_remote_device_suspend() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 56 +++++++++------------------------------ drivers/scsi/isci/remote_device.h | 1 - 2 files changed, 13 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 3344f38355cd..97ea8748335d 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -261,17 +261,20 @@ enum sci_status scic_remote_device_reset_complete(struct scic_sds_remote_device return SCI_SUCCESS; } -/** - * - * @sci_dev: The remote device for which the suspend is being requested. - * - * This method invokes the remote device suspend state handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_suspend( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type) +enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sci_dev, + u32 suspend_type) { - return sci_dev->state_handlers->suspend_handler(sci_dev, suspend_type); + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + + if (state != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD) { + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + return scic_sds_remote_node_context_suspend(&sci_dev->rnc, + suspend_type, NULL, NULL); } /** @@ -674,12 +677,6 @@ default_device_handler(struct scic_sds_remote_device *sci_dev, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_device_default_suspend_handler( - struct scic_sds_remote_device *sci_dev, u32 suspend_type) -{ - return default_device_handler(sci_dev, __func__); -} - static enum sci_status scic_sds_remote_device_default_resume_handler( struct scic_sds_remote_device *sci_dev) { @@ -919,18 +916,6 @@ static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handl return status; } -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type) -{ - enum sci_status status; - - status = scic_sds_remote_node_context_suspend(&sci_dev->rnc, - suspend_type, NULL, NULL); - - return status; -} - static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( struct scic_sds_remote_device *sci_dev, u32 frame_index) @@ -976,91 +961,76 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .suspend_handler = scic_sds_remote_device_default_suspend_handler, .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index dbfb13e2851d..f0cabd013bd8 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,7 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - scic_sds_remote_device_suspend_handler_t suspend_handler; scic_sds_remote_device_resume_handler_t resume_handler; scic_sds_remote_device_event_handler_t event_handler; scic_sds_remote_device_frame_handler_t frame_handler; -- cgit v1.2.3 From 978edfef46415badd28974a3e85119e2b764d236 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 16:20:54 -0700 Subject: isci: kill remote_device resume_handler This is unused infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 31 ------------------------------- drivers/scsi/isci/remote_device.h | 1 - 2 files changed, 32 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 97ea8748335d..26c5253530ea 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -667,22 +667,6 @@ static void remote_device_resume_done(void *_dev) } } -static enum sci_status -default_device_handler(struct scic_sds_remote_device *sci_dev, - const char *func) -{ - dev_warn(scirdev_to_dev(sci_dev), - "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&sci_dev->state_machine)); - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_remote_device_default_resume_handler( - struct scic_sds_remote_device *sci_dev) -{ - return default_device_handler(sci_dev, __func__); -} - /** * * @device: The struct scic_sds_remote_device which is then cast into a @@ -961,77 +945,62 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .resume_handler = scic_sds_remote_device_default_resume_handler, .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler } diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index f0cabd013bd8..bb8d17391c95 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,7 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - scic_sds_remote_device_resume_handler_t resume_handler; scic_sds_remote_device_event_handler_t event_handler; scic_sds_remote_device_frame_handler_t frame_handler; }; -- cgit v1.2.3 From e622571f0f05986b23eba566b73b3abeb5d847d3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 16:26:09 -0700 Subject: isci: unify remote_device event_handlers Implement all states in scic_sds_remote_device_event() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 241 +++++++++++++------------------------- drivers/scsi/isci/remote_device.h | 1 - 2 files changed, 82 insertions(+), 160 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 26c5253530ea..53f4ecfddce4 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -293,19 +293,84 @@ enum sci_status scic_sds_remote_device_frame_handler( return sci_dev->state_handlers->frame_handler(sci_dev, frame_index); } -/** - * - * @sci_dev: The remote device for which the event handling is being - * requested. - * @event_code: This is the event code that is to be processed. - * - * This method invokes the remote device event handler. enum sci_status - */ -enum sci_status scic_sds_remote_device_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) +static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev) { - return sci_dev->state_handlers->event_handler(sci_dev, event_code); + + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + + switch (state) { + case SCI_BASE_REMOTE_DEVICE_STATE_READY: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + return true; + default: + return false; + } +} + +enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_device *sci_dev, + u32 event_code) +{ + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_status status; + + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_OPS_MISC: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + status = scic_sds_remote_node_context_event_handler(&sci_dev->rnc, event_code); + break; + case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: + if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { + status = SCI_SUCCESS; + + /* Suspend the associated RNC */ + scic_sds_remote_node_context_suspend(&sci_dev->rnc, + SCI_SOFTWARE_SUSPENSION, + NULL, NULL); + + dev_dbg(scirdev_to_dev(sci_dev), + "%s: device: %p event code: %x: %s\n", + __func__, sci_dev, event_code, + is_remote_device_ready(sci_dev) + ? "I_T_Nexus_Timeout event" + : "I_T_Nexus_Timeout event in wrong state"); + + break; + } + /* Else, fall through and treat as unhandled... */ + default: + dev_dbg(scirdev_to_dev(sci_dev), + "%s: device: %p event code: %x: %s\n", + __func__, sci_dev, event_code, + is_remote_device_ready(sci_dev) + ? "unexpected event" + : "unexpected event in wrong state"); + status = SCI_FAILURE_INVALID_STATE; + break; + } + + if (status != SCI_SUCCESS) + return status; + + if (state == SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE) { + + /* We pick up suspension events to handle specifically to this + * state. We resume the RNC right away. + */ + if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || + scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) + status = scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); + } + + return status; } static void scic_sds_remote_device_start_request(struct scic_sds_remote_device *sci_dev, @@ -646,103 +711,13 @@ void scic_sds_remote_device_post_request( static void remote_device_resume_done(void *_dev) { struct scic_sds_remote_device *sci_dev = _dev; - enum scic_sds_remote_device_states state; - state = sci_dev->state_machine.current_state_id; - switch (state) { - case SCI_BASE_REMOTE_DEVICE_STATE_READY: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - break; - default: - /* go 'ready' if we are not already in a ready state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_READY); - break; - } -} + if (is_remote_device_ready(sci_dev)) + return; -/** - * - * @device: The struct scic_sds_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @event_code: The event code that the struct scic_sds_controller wants the device - * object to process. - * - * This method is the default event handler. It will call the RNC state - * machine handler for any RNC events otherwise it will log a warning and - * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_remote_device_core_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code, - bool is_ready_state) -{ - enum sci_status status; - - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TYPE_RNC_OPS_MISC: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - status = scic_sds_remote_node_context_event_handler(&sci_dev->rnc, event_code); - break; - case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: - - if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { - status = SCI_SUCCESS; - - /* Suspend the associated RNC */ - scic_sds_remote_node_context_suspend(&sci_dev->rnc, - SCI_SOFTWARE_SUSPENSION, - NULL, NULL); - - dev_dbg(scirdev_to_dev(sci_dev), - "%s: device: %p event code: %x: %s\n", - __func__, sci_dev, event_code, - (is_ready_state) - ? "I_T_Nexus_Timeout event" - : "I_T_Nexus_Timeout event in wrong state"); - - break; - } - /* Else, fall through and treat as unhandled... */ - - default: - dev_dbg(scirdev_to_dev(sci_dev), - "%s: device: %p event code: %x: %s\n", - __func__, sci_dev, event_code, - (is_ready_state) - ? "unexpected event" - : "unexpected event in wrong state"); - status = SCI_FAILURE_INVALID_STATE; - break; - } - - return status; -} -/** - * - * @device: The struct scic_sds_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @event_code: The event code that the struct scic_sds_controller wants the device - * object to process. - * - * This method is the default event handler. It will call the RNC state - * machine handler for any RNC events otherwise it will log a warning and - * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_remote_device_default_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - return scic_sds_remote_device_core_event_handler(sci_dev, - event_code, - false); + /* go 'ready' if we are not already in a ready state */ + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCI_BASE_REMOTE_DEVICE_STATE_READY); } /** @@ -824,43 +799,6 @@ static enum sci_status scic_sds_remote_device_general_frame_handler( return result; } -/** - * - * @[in]: sci_dev This is the device object that is receiving the event. - * @[in]: event_code The event code to process. - * - * This is a common method for handling events reported to the remote device - * from the controller object. enum sci_status - */ -static enum sci_status scic_sds_remote_device_general_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - return scic_sds_remote_device_core_event_handler(sci_dev, - event_code, - true); -} - -static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( - struct scic_sds_remote_device *sci_dev, - u32 event_code) -{ - enum sci_status status; - - status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); - if (status != SCI_SUCCESS) - return status; - - /* We pick up suspension events to handle specifically to this state. We - * resume the RNC right away. enum sci_status - */ - if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || - scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) - status = scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); - - return status; -} - static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(struct scic_sds_remote_device *sci_dev, u32 frame_index) { @@ -945,63 +883,48 @@ static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handl static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .event_handler = scic_sds_remote_device_general_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .event_handler = scic_sds_remote_device_default_event_handler, .frame_handler = scic_sds_remote_device_default_frame_handler } }; diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index bb8d17391c95..e376ec2ff369 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,7 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - scic_sds_remote_device_event_handler_t event_handler; scic_sds_remote_device_frame_handler_t frame_handler; }; -- cgit v1.2.3 From 01bec7788db9d1bb2c594d1f1916096ce6299f38 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 16:51:11 -0700 Subject: isci: unify remote_device frame_handlers Implement all states in scic_sds_remote_device_frame() and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 265 +++++++++++++------------------------- drivers/scsi/isci/remote_device.h | 1 - 2 files changed, 89 insertions(+), 177 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 53f4ecfddce4..0295349b40e5 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -277,20 +277,96 @@ enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sc suspend_type, NULL, NULL); } -/** - * - * @sci_dev: The remote device for which the event handling is being - * requested. - * @frame_index: This is the frame index that is being processed. - * - * This method invokes the frame handler for the remote device state machine - * enum sci_status - */ -enum sci_status scic_sds_remote_device_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) +enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_device *sci_dev, + u32 frame_index) { - return sci_dev->state_handlers->frame_handler(sci_dev, frame_index); + struct sci_base_state_machine *sm = &sci_dev->state_machine; + enum scic_sds_remote_device_states state = sm->current_state_id; + struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + enum sci_status status; + + switch (state) { + case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: + case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + default: + dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + __func__, state); + /* Return the frame back to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + return SCI_FAILURE_INVALID_STATE; + case SCI_BASE_REMOTE_DEVICE_STATE_READY: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: + case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: + case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: { + struct scic_sds_request *sci_req; + struct sci_ssp_frame_header *hdr; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&hdr); + if (status != SCI_SUCCESS) + return status; + + sci_req = scic_sds_controller_get_io_request_from_tag(scic, hdr->tag); + if (sci_req && sci_req->target_device == sci_dev) { + /* The IO request is now in charge of releasing the frame */ + status = sci_req->state_handlers->frame_handler(sci_req, + frame_index); + } else { + /* We could not map this tag to a valid IO + * request Just toss the frame and continue + */ + scic_sds_controller_release_frame(scic, frame_index); + } + break; + } + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: { + struct sata_fis_header *hdr; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&hdr); + if (status != SCI_SUCCESS) + return status; + + if (hdr->fis_type == SATA_FIS_TYPE_SETDEVBITS && + (hdr->status & ATA_STATUS_REG_ERROR_BIT)) { + sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + + /* TODO Check sactive and complete associated IO if any. */ + sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + } else if (hdr->fis_type == SATA_FIS_TYPE_REGD2H && + (hdr->status & ATA_STATUS_REG_ERROR_BIT)) { + /* + * Some devices return D2H FIS when an NCQ error is detected. + * Treat this like an SDB error FIS ready reason. + */ + sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + sci_base_state_machine_change_state(&sci_dev->state_machine, + SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + } else + status = SCI_FAILURE; + + scic_sds_controller_release_frame(scic, frame_index); + break; + } + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + /* The device does not process any UF received from the hardware while + * in this state. All unsolicited frames are forwarded to the io request + * object. + */ + status = scic_sds_io_request_frame_handler(sci_dev->working_request, frame_index); + break; + } + + return status; } static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev) @@ -720,136 +796,6 @@ static void remote_device_resume_done(void *_dev) SCI_BASE_REMOTE_DEVICE_STATE_READY); } -/** - * - * @device: The struct scic_sds_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @frame_index: The frame index for which the struct scic_sds_controller wants this - * device object to process. - * - * This method is the default unsolicited frame handler. It logs a warning, - * releases the frame and returns a failure. enum sci_status - * SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_remote_device_default_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - dev_warn(scirdev_to_dev(sci_dev), - "%s: SCIC Remote Device requested to handle frame %x " - "while in wrong state %d\n", - __func__, - frame_index, - sci_base_state_machine_get_state( - &sci_dev->state_machine)); - - /* Return the frame back to the controller */ - scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(sci_dev), frame_index - ); - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * - * @device: The struct scic_sds_remote_device which is then cast into a - * struct scic_sds_remote_device. - * @frame_index: The frame index for which the struct scic_sds_controller wants this - * device object to process. - * - * This method is a general ssp frame handler. In most cases the device object - * needs to route the unsolicited frame processing to the io request object. - * This method decodes the tag for the io request object and routes the - * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_remote_device_general_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status result; - struct sci_ssp_frame_header *frame_header; - struct scic_sds_request *io_request; - - result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), - frame_index, - (void **)&frame_header - ); - - if (SCI_SUCCESS == result) { - io_request = scic_sds_controller_get_io_request_from_tag( - scic_sds_remote_device_get_controller(sci_dev), frame_header->tag); - - if ((io_request == NULL) - || (io_request->target_device != sci_dev)) { - /* - * We could not map this tag to a valid IO request - * Just toss the frame and continue */ - scic_sds_controller_release_frame( - scic_sds_remote_device_get_controller(sci_dev), frame_index - ); - } else { - /* The IO request is now in charge of releasing the frame */ - result = io_request->state_handlers->frame_handler( - io_request, frame_index); - } - } - - return result; -} - -static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status status; - struct sata_fis_header *frame_header; - struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - if (status != SCI_SUCCESS) - return status; - - if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && - (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { - sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; - - /* TODO Check sactive and complete associated IO if any. */ - - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); - } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && - (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { - /* - * Some devices return D2H FIS when an NCQ error is detected. - * Treat this like an SDB error FIS ready reason. - */ - sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; - - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); - } else - status = SCI_FAILURE; - - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - /* The device doe not process any UF received from the hardware while - * in this state. All unsolicited frames are forwarded to the io - * request object. - */ - return scic_sds_io_request_frame_handler(sci_dev->working_request, - frame_index); -} - static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) { struct scic_sds_remote_device *sci_dev = _dev; @@ -863,69 +809,36 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl isci_remote_device_ready(scic->ihost, idev); } -static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( - struct scic_sds_remote_device *sci_dev, - u32 frame_index) -{ - enum sci_status status; - - /* The device does not process any UF received from the hardware while - * in this state. All unsolicited frames are forwarded to the io request - * object. - */ - status = scic_sds_io_request_frame_handler( - sci_dev->working_request, - frame_index - ); - - return status; -} - static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - .frame_handler = scic_sds_remote_device_general_frame_handler, }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - .frame_handler = scic_sds_remote_device_default_frame_handler }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - .frame_handler = scic_sds_remote_device_general_frame_handler }, [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .frame_handler = scic_sds_remote_device_default_frame_handler } }; diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index e376ec2ff369..1577b126aedc 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -386,7 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( * */ struct scic_sds_remote_device_state_handler { - scic_sds_remote_device_frame_handler_t frame_handler; }; /** -- cgit v1.2.3 From 971cc2ff90875a4ca28b7da5b91a408cc8151fdc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 1 May 2011 16:58:46 -0700 Subject: isci: kill scic_sds_remote_device.state_handlers Remove the now unused state_handler infrastructure for remote_devices. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 136 ++------------------------------------ drivers/scsi/isci/remote_device.h | 56 ---------------- 2 files changed, 5 insertions(+), 187 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 0295349b40e5..a23ebe85773e 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -809,46 +809,10 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl isci_remote_device_ready(scic->ihost, idev); } -static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { - [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { - }, - [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { - }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - }, - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { - }, - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { - }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - }, - [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - } -}; - static void scic_sds_remote_device_initial_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); - /* Initial state is a transitional state to the stopped state */ sci_base_state_machine_change_state(&sci_dev->state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); @@ -953,9 +917,6 @@ static void scic_sds_remote_device_stopped_state_enter(void *object) ihost = scic->ihost; idev = sci_dev_to_idev(sci_dev); - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); - /* If we are entering from the stopping state let the SCI User know that * the stop operation has completed. */ @@ -973,9 +934,6 @@ static void scic_sds_remote_device_starting_state_enter(void *object) struct isci_host *ihost = scic->ihost; struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STARTING); - isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); } @@ -986,10 +944,6 @@ static void scic_sds_remote_device_ready_state_enter(void *object) struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; struct domain_device *dev = sci_dev_to_domain(sci_dev); - SET_STATE_HANDLER(sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_READY); - scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { @@ -1016,38 +970,10 @@ static void scic_sds_remote_device_ready_state_exit(void *object) } } -static void scic_sds_remote_device_stopping_state_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING - ); -} - -static void scic_sds_remote_device_failed_state_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_FAILED - ); -} - static void scic_sds_remote_device_resetting_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING - ); - scic_sds_remote_node_context_suspend( &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); } @@ -1059,24 +985,10 @@ static void scic_sds_remote_device_resetting_state_exit(void *object) scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); } -static void scic_sds_remote_device_final_state_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - - SET_STATE_HANDLER( - sci_dev, - scic_sds_remote_device_state_handler_table, - SCI_BASE_REMOTE_DEVICE_STATE_FINAL - ); -} - static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - sci_dev->working_request = NULL; if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { /* @@ -1097,51 +1009,26 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) BUG_ON(sci_dev->working_request == NULL); - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - isci_remote_device_not_ready(scic->ihost, sci_dev_to_idev(sci_dev), SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } -static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); -} - static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); - if (sci_dev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) isci_remote_device_not_ready(scic->ihost, idev, sci_dev->not_ready_reason); } -static void scic_sds_stp_remote_device_ready_await_reset_substate_enter(void *object) -{ - struct scic_sds_remote_device *sci_dev = object; - - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET); -} - static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); - isci_remote_device_ready(scic->ihost, sci_dev_to_idev(sci_dev)); } @@ -1152,9 +1039,6 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) BUG_ON(sci_dev->working_request == NULL); - SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); - isci_remote_device_not_ready(scic->ihost, sci_dev_to_idev(sci_dev), SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); } @@ -1186,15 +1070,11 @@ static const struct sci_base_state scic_sds_remote_device_state_table[] = { [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { - .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, - }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { }, [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { - .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, - }, + [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { }, [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, }, @@ -1202,19 +1082,13 @@ static const struct sci_base_state scic_sds_remote_device_state_table[] = { .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { - .enter_state = scic_sds_remote_device_stopping_state_enter, - }, - [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { - .enter_state = scic_sds_remote_device_failed_state_enter, - }, + [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { }, + [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { }, [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { .enter_state = scic_sds_remote_device_resetting_state_enter, .exit_state = scic_sds_remote_device_resetting_state_exit }, - [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { - .enter_state = scic_sds_remote_device_final_state_enter, - }, + [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { }, }; /** diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 1577b126aedc..18f7f9663661 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -128,12 +128,6 @@ struct scic_sds_remote_device { * assigned in the state handlers and used in the state transition. */ u32 not_ready_reason; - - /** - * This field maintains the set of state handlers for the remote device - * object. These are changed each time the remote device enters a new state. - */ - const struct scic_sds_remote_device_state_handler *state_handlers; }; struct isci_remote_device { @@ -347,47 +341,6 @@ static inline bool dev_is_expander(struct domain_device *dev) return dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV; } -typedef enum sci_status (*scic_sds_remote_device_request_handler_t)( - struct scic_sds_remote_device *device, - struct scic_sds_request *request); - -typedef enum sci_status (*scic_sds_remote_device_high_priority_request_complete_handler_t)( - struct scic_sds_remote_device *device, - struct scic_sds_request *request, - void *, - enum sci_io_status); - -typedef enum sci_status (*scic_sds_remote_device_handler_t)( - struct scic_sds_remote_device *sci_dev); - -typedef enum sci_status (*scic_sds_remote_device_suspend_handler_t)( - struct scic_sds_remote_device *sci_dev, - u32 suspend_type); - -typedef enum sci_status (*scic_sds_remote_device_resume_handler_t)( - struct scic_sds_remote_device *sci_dev); - -typedef enum sci_status (*scic_sds_remote_device_frame_handler_t)( - struct scic_sds_remote_device *sci_dev, - u32 frame_index); - -typedef enum sci_status (*scic_sds_remote_device_event_handler_t)( - struct scic_sds_remote_device *sci_dev, - u32 event_code); - -typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)( - struct scic_sds_remote_device *sci_dev); - -/** - * struct scic_sds_remote_device_state_handler - This structure conains the - * state handlers that are needed to process requests for the SCU remote - * device objects. - * - * - */ -struct scic_sds_remote_device_state_handler { -}; - /** * scic_sds_remote_device_increment_request_count() - * @@ -430,15 +383,6 @@ struct scic_sds_remote_device_state_handler { #define scic_sds_remote_device_get_controller(sci_dev) \ scic_sds_port_get_controller(scic_sds_remote_device_get_port(sci_dev)) -/** - * scic_sds_remote_device_set_state_handlers() - - * - * This macro sets the remote device state handlers pointer and is set on entry - * to each device state. - */ -#define scic_sds_remote_device_set_state_handlers(sci_dev, handlers) \ - ((sci_dev)->state_handlers = (handlers)) - /** * scic_sds_remote_device_get_port() - * -- cgit v1.2.3 From d6f6404c038b004fdb93f0676db934d69c524f7e Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Fri, 22 Apr 2011 06:39:48 +0000 Subject: isci: Removing unused define SCIC_SDS_4_ENABLED Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 4 ---- drivers/scsi/isci/core/intel_sas.h | 2 -- drivers/scsi/isci/core/sci_controller_constants.h | 9 --------- 3 files changed, 15 deletions(-) diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index c27d25999123..78ba0fc3548a 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -1,7 +1,3 @@ -#TODO kill SCIC_SDS_4_ENABLED it is always true for this -#generation of silicon -EXTRA_CFLAGS += -DSCIC_SDS_4_ENABLED - EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index b57f39c2cfc2..c12e6d4f4d7d 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -151,7 +151,6 @@ struct sci_sas_identify_address_frame { */ struct sas_capabilities { union { -#if defined (SCIC_SDS_4_ENABLED) struct { /** * The SAS specification indicates the start bit shall always be set to @@ -172,7 +171,6 @@ struct sas_capabilities { u32 reserved2:17; u32 parity:1; } bits; -#endif /* (SCIC_SDS_4_ENABLED) */ u32 all; } u; diff --git a/drivers/scsi/isci/core/sci_controller_constants.h b/drivers/scsi/isci/core/sci_controller_constants.h index 06c34c7bdd5f..2525c26d7c08 100644 --- a/drivers/scsi/isci/core/sci_controller_constants.h +++ b/drivers/scsi/isci/core/sci_controller_constants.h @@ -65,9 +65,6 @@ * */ - -#ifdef SCIC_SDS_4_ENABLED - #ifndef SCI_MAX_PHYS /** * @@ -188,12 +185,6 @@ #define SCI_MIN_SCATTER_GATHER_ELEMENTS 1 #endif -#else /* SCIC_SDS_4_ENABLED */ - -#error "SCI Core configuration left unspecified (e.g. SCIC_SDS_4_ENABLED)" - -#endif /* SCIC_SDS_4_ENABLED */ - /** * * -- cgit v1.2.3 From c6d42257899505ea1982eba4c5e8bc7981e63e07 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 4 May 2011 13:49:32 -0700 Subject: isci: remove compile-time (Kconfig) silicon configuration Pre-production silicon support is deprecated, and will be removed completely in the future. Signed-off-by: Dan Williams --- drivers/scsi/Kconfig | 18 ------------------ drivers/scsi/isci/init.c | 8 +------- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index e18938bebcd3..8d9dae89f065 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -843,24 +843,6 @@ config SCSI_ISCI The experimental tag will be removed after the driver exits alpha -choice - prompt "Default Silicon Revision" - depends on SCSI_ISCI - default PBG_HBA_A2 - # temporary A-step silicon is pre-production - -config PBG_HBA_BETA - bool "B0" - -config PBG_HBA_A2 - bool "A2" - -config PBG_HBA_A0 - bool "A0" - -endchoice - - config SCSI_GENERIC_NCR5380 tristate "Generic NCR5380/53c400 SCSI PIO support" depends on ISA && SCSI diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 10b60ab261e1..6c2d686fe7c0 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -87,15 +87,9 @@ MODULE_DEVICE_TABLE(pci, isci_id_table); /* linux isci specific settings */ -#if defined(CONFIG_PBG_HBA_A0) -int isci_si_rev = ISCI_SI_REVA0; -#elif defined(CONFIG_PBG_HBA_A2) int isci_si_rev = ISCI_SI_REVA2; -#else -int isci_si_rev = ISCI_SI_REVB0; -#endif module_param(isci_si_rev, int, 0); -MODULE_PARM_DESC(isci_si_rev, "override default si rev (0: A0 1: A2 2: B0)"); +MODULE_PARM_DESC(isci_si_rev, "(deprecated) override default si rev (0: A0 1: A2 2: B0)"); unsigned char no_outbound_task_to = 20; module_param(no_outbound_task_to, byte, 0); -- cgit v1.2.3 From f2f300806fe186a6c45020a444667755edcce672 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 15:02:02 -0700 Subject: isci: Convert SATA fis data structures to Linux native Converting of sata_fis_reg_d2h to dev_to_host_fis Converting of sata_fis_reg_h2d to host_to_dev_fis Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sata.h | 56 --------------------------- drivers/scsi/isci/core/scic_phy.h | 6 +-- drivers/scsi/isci/core/scic_sds_controller.c | 15 +++---- drivers/scsi/isci/core/scic_sds_phy.c | 9 ++--- drivers/scsi/isci/core/scic_sds_phy.h | 2 +- drivers/scsi/isci/core/scic_sds_request.c | 4 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 17 ++++---- drivers/scsi/isci/core/scic_sds_stp_request.h | 2 +- drivers/scsi/isci/phy.h | 5 +-- drivers/scsi/isci/port.c | 7 +--- drivers/scsi/isci/sata.c | 8 ++-- drivers/scsi/isci/task.c | 6 +-- 12 files changed, 35 insertions(+), 102 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sata.h b/drivers/scsi/isci/core/intel_sata.h index 47390d54064d..977354d7b843 100644 --- a/drivers/scsi/isci/core/intel_sata.h +++ b/drivers/scsi/isci/core/intel_sata.h @@ -101,62 +101,6 @@ struct sata_fis_header { u32 error:8; }; - -/** - * struct sata_fis_reg_h2d - This is the definition for a SATA Host to Device - * Register FIS. - * - * - */ -struct sata_fis_reg_h2d { - u32 fis_type:8; /* word 0 */ - u32 pm_port:4; - u32 reserved0:3; - u32 command_flag:1; - u32 command:8; - u32 features:8; - u32 lba_low:8; /* word 1 */ - u32 lba_mid:8; - u32 lba_high:8; - u32 device:8; - u32 lba_low_exp:8; /* word 2 */ - u32 lba_mid_exp:8; - u32 lba_high_exp:8; - u32 features_exp:8; - u32 sector_count:8; /* word 3 */ - u32 sector_count_exp:8; - u32 reserved1:8; - u32 control:8; - u32 reserved2; /* word 4 */ -}; - -/** - * struct sata_fis_reg_d2h - SATA Device To Host FIS - * - * - */ -struct sata_fis_reg_d2h { - u32 fis_type:8; /* word 0 */ - u32 pm_port:4; - u32 reserved0:2; - u32 irq:1; - u32 reserved1:1; - u32 status:8; - u32 error:8; - u8 lba_low; /* word 1 */ - u8 lba_mid; - u8 lba_high; - u8 device; - u8 lba_low_exp; /* word 2 */ - u8 lba_mid_exp; - u8 lba_high_exp; - u8 reserved; - u8 sector_count; /* word 3 */ - u8 sector_count_exp; - u16 reserved2; - u32 reserved3; -}; - /** * * diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 784c5b5c105b..6fe39ccedf0b 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -64,11 +64,11 @@ */ +#include +#include #include "sci_status.h" - #include "intel_sata.h" #include "intel_sas.h" -#include struct scic_sds_phy; struct scic_sds_port; @@ -141,7 +141,7 @@ struct scic_sata_phy_properties { * This field delineates the signature FIS received from the * attached target. */ - struct sata_fis_reg_d2h signature_fis; + struct dev_to_host_fis signature_fis; /** * This field specifies to the user if a port selector is connected diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index d7c37dc64ac4..0b76fc75996f 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -54,6 +54,7 @@ */ #include +#include #include "scic_controller.h" #include "scic_phy.h" #include "scic_port.h" @@ -1754,17 +1755,11 @@ void scic_sds_controller_copy_sata_response( void *frame_header, void *frame_buffer) { - memcpy( - response_buffer, - frame_header, - sizeof(u32) - ); + memcpy(response_buffer, frame_header, sizeof(u32)); - memcpy( - (char *)((char *)response_buffer + sizeof(u32)), - frame_buffer, - sizeof(struct sata_fis_reg_d2h) - sizeof(u32) - ); + memcpy(response_buffer + sizeof(u32), + frame_buffer, + sizeof(struct dev_to_host_fis) - sizeof(u32)); } /** diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index c935c0482470..1b35b1ac1f8d 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "intel_ata.h" #include "intel_sata.h" #include "sci_base_state.h" @@ -620,11 +621,9 @@ enum sci_status scic_sata_phy_get_properties( struct scic_sata_phy_properties *properties) { if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { - memcpy( - &properties->signature_fis, - &sci_phy->phy_type.sata.signature_fis_buffer, - sizeof(struct sata_fis_reg_d2h) - ); + memcpy(&properties->signature_fis, + &sci_phy->phy_type.sata.signature_fis_buffer, + sizeof(struct dev_to_host_fis)); /* / @todo add support for port selectors. */ properties->is_port_selector_present = false; diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index fca95c1c027a..c9fa2071f9b2 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -280,7 +280,7 @@ struct scic_sds_phy { } sas; struct { - struct sata_fis_reg_d2h signature_fis_buffer; + struct dev_to_host_fis signature_fis_buffer; } sata; diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index ffc16072d1da..13067659a8c6 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -53,7 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#include #include "intel_sas.h" #include "intel_sata.h" #include "intel_sat.h" @@ -1742,7 +1742,7 @@ enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, scic_sds_ssp_io_request_assign_buffers(sci_req); } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { scic_sds_stp_request_assign_buffers(sci_req); - memset(sci_req->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); + memset(sci_req->command_buffer, 0, sizeof(struct host_to_dev_fis)); } else if (dev_is_expander(dev)) { scic_sds_smp_request_assign_buffers(sci_req); memset(sci_req->command_buffer, 0, sizeof(struct smp_request)); diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 8c980235ea41..1cd111c42ede 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -79,7 +79,7 @@ * request memory */ #define scic_sds_stp_request_get_h2d_reg_buffer(memory) \ - ((struct sata_fis_reg_h2d *)(\ + ((struct host_to_dev_fis *)(\ ((char *)(memory)) + sizeof(struct scic_sds_stp_request) \ )) @@ -90,9 +90,9 @@ * request memory */ #define scic_sds_stp_request_get_response_buffer(memory) \ - ((struct sata_fis_reg_d2h *)(\ + ((struct dev_to_host_fis *)(\ ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \ - + sizeof(struct sata_fis_reg_h2d) \ + + sizeof(struct host_to_dev_fis) \ )) /** @@ -127,8 +127,8 @@ u32 scic_sds_stp_request_get_object_size(void) { return sizeof(struct scic_sds_stp_request) - + sizeof(struct sata_fis_reg_h2d) - + sizeof(struct sata_fis_reg_d2h) + + sizeof(struct host_to_dev_fis) + + sizeof(struct dev_to_host_fis) + sizeof(struct scu_task_context) + SMP_CACHE_BYTES + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; @@ -205,7 +205,7 @@ static void scu_sata_reqeust_construct_task_context( task_context->task_phase = 0x01; task_context->ssp_command_iu_length = - (sizeof(struct sata_fis_reg_h2d) - sizeof(u32)) / sizeof(u32); + (sizeof(struct host_to_dev_fis) - sizeof(u32)) / sizeof(u32); /* Set the first word of the H2D REG FIS */ task_context->type.words[0] = *(u32 *)sds_request->command_buffer; @@ -354,7 +354,8 @@ static void scu_stp_raw_request_construct_task_context( task_context->priority = SCU_TASK_PRIORITY_NORMAL; task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; task_context->type.stp.fis_type = SATA_FIS_TYPE_REGH2D; - task_context->transfer_length_bytes = sizeof(struct sata_fis_reg_h2d) - sizeof(u32); + task_context->transfer_length_bytes = + sizeof(struct host_to_dev_fis) - sizeof(u32); } void scic_stp_io_request_set_ncq_tag( @@ -1749,7 +1750,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet { struct scic_sds_request *sci_req = object; struct scu_task_context *task_context; - struct sata_fis_reg_h2d *h2d_fis; + struct host_to_dev_fis *h2d_fis; enum sci_status status; /* Clear the SRST bit */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index 6724c1d759df..807bc4eeb821 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -69,7 +69,7 @@ struct scic_sds_stp_request { struct scic_sds_request parent; - struct sata_fis_reg_d2h d2h_reg_fis; + struct dev_to_host_fis d2h_reg_fis; union { u32 ncq; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 44b727f1c455..3fe1a8a13169 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -59,6 +59,7 @@ #include "port.h" #include "host.h" +#include #include @@ -79,10 +80,8 @@ struct isci_phy { u8 sas_addr[SAS_ADDR_SIZE]; union { - u8 aif[sizeof(struct sci_sas_identify_address_frame)]; - u8 fis[sizeof(struct sata_fis_reg_d2h)]; - + struct dev_to_host_fis fis; } frame_rcvd; }; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 30d6ad895ccf..5b38f2f963e0 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -205,11 +205,8 @@ void isci_port_link_up( */ BUG_ON(call_status != SCI_SUCCESS); - memcpy(isci_phy->frame_rcvd.fis, - &sata_phy_properties.signature_fis, - sizeof(struct sata_fis_reg_d2h)); - - isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sata_fis_reg_d2h); + isci_phy->frame_rcvd.fis = sata_phy_properties.signature_fis; + isci_phy->sas_phy.frame_rcvd_size = sizeof(struct dev_to_host_fis); /* * For direct-attached SATA devices, the SCI core will diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 53ce0c281bee..08374505832e 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "isci.h" #include "remote_device.h" #include "scic_io_request.h" @@ -142,11 +143,10 @@ void isci_sata_set_ncq_tag( * * none. */ -void isci_request_process_stp_response( - struct sas_task *task, - void *response_buffer) +void isci_request_process_stp_response(struct sas_task *task, + void *response_buffer) { - struct sata_fis_reg_d2h *d2h_reg_fis = (struct sata_fis_reg_d2h *)response_buffer; + struct dev_to_host_fis *d2h_reg_fis = response_buffer; struct task_status_struct *ts = &task->task_status; struct ata_task_resp *resp = (void *)&ts->buf[0]; diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 95f386723212..f9a1c41a5ce8 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1452,10 +1452,8 @@ void isci_task_request_complete( memcpy(&tmf->resp.d2h_fis, scic_stp_io_request_get_d2h_reg_address( - request->sci_request_handle - ), - sizeof(struct sata_fis_reg_d2h) - ); + request->sci_request_handle), + sizeof(struct dev_to_host_fis)); } /* Manage the timer if it is still running. */ -- cgit v1.2.3 From e76d6180da436edf2cc3538cbed1f5b02b614613 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 15:02:03 -0700 Subject: isci: Convert ATA defines to Linux native defines * Removing all intel_sata and intel_ata defines * Removing the usage of SAT_PROTOCOL_*. We can get everything from sas_task * Moved SATA FIS types to local sas.h. These defines will have to go into include/scsi/sas.h eventually. * Added offsets for SATA FIS header in order to grab the values Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_ata.h | 554 -------------------------- drivers/scsi/isci/core/intel_sas.h | 3 +- drivers/scsi/isci/core/intel_sat.h | 95 ----- drivers/scsi/isci/core/intel_sata.h | 224 ----------- drivers/scsi/isci/core/scic_phy.h | 1 - drivers/scsi/isci/core/scic_sds_phy.c | 23 +- drivers/scsi/isci/core/scic_sds_phy.h | 1 - drivers/scsi/isci/core/scic_sds_request.c | 125 +++--- drivers/scsi/isci/core/scic_sds_stp_request.c | 366 +++++++++-------- drivers/scsi/isci/core/scic_sds_stp_request.h | 8 +- drivers/scsi/isci/remote_device.c | 23 +- drivers/scsi/isci/sas.h | 72 ++++ drivers/scsi/isci/sata.c | 75 +--- drivers/scsi/isci/sata.h | 4 - 14 files changed, 337 insertions(+), 1237 deletions(-) delete mode 100644 drivers/scsi/isci/core/intel_ata.h delete mode 100644 drivers/scsi/isci/core/intel_sat.h delete mode 100644 drivers/scsi/isci/core/intel_sata.h create mode 100644 drivers/scsi/isci/sas.h diff --git a/drivers/scsi/isci/core/intel_ata.h b/drivers/scsi/isci/core/intel_ata.h deleted file mode 100644 index 48b297e50bd0..000000000000 --- a/drivers/scsi/isci/core/intel_ata.h +++ /dev/null @@ -1,554 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file defines all of the ATA related constants, enumerations, and types. - * Please note that this file does not necessarily contain an exhaustive - * list of all constants, commands, sub-commands, etc. - * - * - */ - -#ifndef _ATA_H_ -#define _ATA_H_ - -#include - -/** - * - * - * ATA_COMMAND_CODES These constants depict the various ATA command codes - * defined in the ATA/ATAPI specification. - */ -#define ATA_IDENTIFY_DEVICE 0xEC -#define ATA_CHECK_POWER_MODE 0xE5 -#define ATA_STANDBY 0xE2 -#define ATA_STANDBY_IMMED 0xE0 -#define ATA_IDLE_IMMED 0xE1 -#define ATA_IDLE 0xE3 -#define ATA_FLUSH_CACHE 0xE7 -#define ATA_FLUSH_CACHE_EXT 0xEA -#define ATA_READ_DMA_EXT 0x25 -#define ATA_READ_DMA 0xC8 -#define ATA_READ_SECTORS_EXT 0x24 -#define ATA_READ_SECTORS 0x20 -#define ATA_WRITE_DMA_EXT 0x35 -#define ATA_WRITE_DMA 0xCA -#define ATA_WRITE_SECTORS_EXT 0x34 -#define ATA_WRITE_SECTORS 0x30 -#define ATA_WRITE_UNCORRECTABLE 0x45 -#define ATA_READ_VERIFY_SECTORS 0x40 -#define ATA_READ_VERIFY_SECTORS_EXT 0x42 -#define ATA_READ_BUFFER 0xE4 -#define ATA_WRITE_BUFFER 0xE8 -#define ATA_EXECUTE_DEVICE_DIAG 0x90 -#define ATA_SET_FEATURES 0xEF -#define ATA_SMART 0xB0 -#define ATA_PACKET_IDENTIFY 0xA1 -#define ATA_PACKET 0xA0 -#define ATA_READ_FPDMA 0x60 -#define ATA_WRITE_FPDMA 0x61 -#define ATA_READ_LOG_EXT 0x2F -#define ATA_NOP 0x00 -#define ATA_DEVICE_RESET 0x08 -#define ATA_MEDIA_EJECT 0xED - -/** - * - * - * ATA_SMART_SUB_COMMAND_CODES These constants define the ATA SMART command - * sub-codes that can be executed. - */ -#define ATA_SMART_SUB_CMD_ENABLE 0xD8 -#define ATA_SMART_SUB_CMD_DISABLE 0xD9 -#define ATA_SMART_SUB_CMD_RETURN_STATUS 0xDA -#define ATA_SMART_SUB_CMD_READ_LOG 0xD5 - -/** - * - * - * ATA_SET_FEATURES_SUB_COMMAND_CODES These constants define the ATA SET - * FEATURES command sub-codes that can be executed. - */ -#define ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE 0x02 -#define ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE 0x82 -#define ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD 0x55 -#define ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD 0xAA -#define ATA_SET_FEATURES_SUB_CMD_SET_TRANSFER_MODE 0x3 - -/** - * - * - * ATA_READ_LOG_EXT_PAGE_CODES This is a list of log page codes available for - * use. - */ -#define ATA_LOG_PAGE_NCQ_ERROR 0x10 -#define ATA_LOG_PAGE_SMART_SELF_TEST 0x06 -#define ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST 0x07 - -/** - * - * - * ATA_LOG_PAGE_NCQ_ERROR_CONSTANTS These constants define standard values for - * use when requesting the NCQ error log page. - */ -#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR 0 -#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR_COUNT 1 - -/** - * - * - * ATA_STATUS_REGISTER_BITS The following are status register bit definitions - * per ATA/ATAPI-7. - */ -#define ATA_STATUS_REG_BSY_BIT 0x80 -#define ATA_STATUS_REG_DEVICE_FAULT_BIT 0x20 -#define ATA_STATUS_REG_ERROR_BIT 0x01 - -/** - * - * - * ATA_ERROR_REGISTER_BITS The following are error register bit definitions per - * ATA/ATAPI-7. - */ -#define ATA_ERROR_REG_NO_MEDIA_BIT 0x02 -#define ATA_ERROR_REG_ABORT_BIT 0x04 -#define ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT 0x08 -#define ATA_ERROR_REG_ID_NOT_FOUND_BIT 0x10 -#define ATA_ERROR_REG_MEDIA_CHANGE_BIT 0x20 -#define ATA_ERROR_REG_UNCORRECTABLE_BIT 0x40 -#define ATA_ERROR_REG_WRITE_PROTECTED_BIT 0x40 -#define ATA_ERROR_REG_ICRC_BIT 0x80 - -/** - * - * - * ATA_CONTROL_REGISTER_BITS The following are control register bit definitions - * per ATA/ATAPI-7 - */ -#define ATA_CONTROL_REG_INTERRUPT_ENABLE_BIT 0x02 -#define ATA_CONTROL_REG_SOFT_RESET_BIT 0x04 -#define ATA_CONTROL_REG_HIGH_ORDER_BYTE_BIT 0x80 - -/** - * - * - * ATA_DEVICE_HEAD_REGISTER_BITS The following are device/head register bit - * definitions per ATA/ATAPI-7. - */ -#define ATA_DEV_HEAD_REG_LBA_MODE_ENABLE 0x40 -#define ATA_DEV_HEAD_REG_FUA_ENABLE 0x80 - -/** - * - * - * ATA_IDENTIFY_DEVICE_FIELD_LENGTHS The following constants define the number - * of bytes contained in various fields found in the IDENTIFY DEVICE data - * structure. - */ -#define ATA_IDENTIFY_SERIAL_NUMBER_LEN 20 -#define ATA_IDENTIFY_MODEL_NUMBER_LEN 40 -#define ATA_IDENTIFY_FW_REVISION_LEN 8 -#define ATA_IDENTIFY_48_LBA_LEN 8 -#define ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN 30 -#define ATA_IDENTIFY_WWN_LEN 8 - -/** - * - * - * ATA_IDENTIFY_DEVICE_FIELD_MASKS The following constants define bit masks - * utilized to determine if a feature is supported/enabled or if a bit is - * simply set inside of the IDENTIFY DEVICE data structre. - */ -#define ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE 0x0080 -#define ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE 0x0100 -#define ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE 0x2000 -#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE 0x0001 -#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE 0x0400 -#define ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE 0x0100 -#define ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE 0x0001 -#define ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE 0x0100 -#define ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE 0x001F -#define ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE 0x0100 -#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK 0x000F -#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE 0x2000 -#define ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT 0x0004 -#define ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED 0x0002 - -/** - * - * - * ATAPI_IDENTIFY_DEVICE_FIELD_MASKS These constants define the various bit - * definitions for the fields in the PACKET IDENTIFY DEVICE data structure. - */ -#define ATAPI_IDENTIFY_16BYTE_CMD_PCKT_ENABLE 0x01 - -/** - * - * - * ATA_PACKET_FEATURE_BITS These constants define the various bit definitions - * for the ATA PACKET feature register. - */ -#define ATA_PACKET_FEATURE_DMA 0x01 -#define ATA_PACKET_FEATURE_OVL 0x02 -#define ATA_PACKET_FEATURE_DMADIR 0x04 - -/** - * - * - * ATA_Device_Power_Mode_Values These constants define the power mode values - * returned by ATA_Check_Power_Mode - */ -#define ATA_STANDBY_POWER_MODE 0x00 -#define ATA_IDLE_POWER_MODE 0x80 -#define ATA_ACTIVE_POWER_MODE 0xFF - -/** - * - * - * ATA_WRITE_UNCORRECTIABLE feature field values These constants define the - * Write Uncorrectable feature values used with the SATI translation. - */ -#define ATA_WRITE_UNCORRECTABLE_PSUEDO 0x55 -#define ATA_WRITE_UNCORRECTABLE_FLAGGED 0xAA - - - -/** - * struct ATA_IDENTIFY_DEVICE - This structure depicts the ATA IDENTIFY DEVICE - * data format. - * - * - */ -struct ata_identify_device_data { - u16 general_config_bits; /* word 00 */ - u16 obsolete0; /* word 01 (num cylinders) */ - u16 vendor_specific_config_bits; /* word 02 */ - u16 obsolete1; /* word 03 (num heads) */ - u16 retired1[2]; /* words 04-05 */ - u16 obsolete2; /* word 06 (sectors / track) */ - u16 reserved_for_compact_flash1[2]; /* words 07-08 */ - u16 retired0; /* word 09 */ - u8 serial_number[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; /* word 10-19 */ - u16 retired2[2]; /* words 20-21 */ - u16 obsolete4; /* word 22 */ - u8 firmware_revision[ATA_IDENTIFY_FW_REVISION_LEN]; /* words 23-26 */ - u8 model_number[ATA_IDENTIFY_MODEL_NUMBER_LEN]; /* words 27-46 */ - u16 max_sectors_per_multiple; /* word 47 */ - u16 reserved0; /* word 48 */ - u16 capabilities1; /* word 49 */ - u16 capabilities2; /* word 50 */ - u16 obsolete5[2]; /* words 51-52 */ - u16 validity_bits; /* word 53 */ - u16 obsolete6[5]; /* - * words 54-58 Used to be: - * current cylinders, - * current heads, - * current sectors/Track, - * current capacity */ - u16 current_max_sectors_per_multiple; /* word 59 */ - u8 total_num_sectors[4]; /* words 60-61 */ - u16 obsolete7; /* word 62 */ - u16 multi_word_dma_mode; /* word 63 */ - u16 pio_modes_supported; /* word 64 */ - u16 min_multiword_dma_transfer_cycle; /* word 65 */ - u16 rec_min_multiword_dma_transfer_cycle; /* word 66 */ - u16 min_pio_transfer_no_flow_ctrl; /* word 67 */ - u16 min_pio_transfer_with_flow_ctrl; /* word 68 */ - u16 reserved1[2]; /* words 69-70 */ - u16 reserved2[4]; /* words 71-74 */ - u16 queue_depth; /* word 75 */ - u16 serial_ata_capabilities; /* word 76 */ - u16 serial_ata_reserved; /* word 77 */ - u16 serial_ata_features_supported; /* word 78 */ - u16 serial_ata_features_enabled; /* word 79 */ - u16 major_version_number; /* word 80 */ - u16 minor_version_number; /* word 81 */ - u16 command_set_supported0; /* word 82 */ - u16 command_set_supported1; /* word 83 */ - u16 command_set_supported_extention; /* word 84 */ - u16 command_set_enabled0; /* word 85 */ - u16 command_set_enabled1; /* word 86 */ - u16 command_set_default; /* word 87 */ - u16 ultra_dma_mode; /* word 88 */ - u16 security_erase_completion_time; /* word 89 */ - u16 enhanced_security_erase_time; /* word 90 */ - u16 current_power_mgmt_value; /* word 91 */ - u16 master_password_revision; /* word 92 */ - u16 hardware_reset_result; /* word 93 */ - u16 current_acoustic_management_value; /* word 94 */ - u16 stream_min_request_size; /* word 95 */ - u16 stream_transfer_time; /* word 96 */ - u16 stream_access_latency; /* word 97 */ - u16 stream_performance_granularity[2]; /* words 98-99 */ - u8 max_48bit_lba[ATA_IDENTIFY_48_LBA_LEN]; /* words 100-103 */ - u16 streaming_transfer_time; /* word 104 */ - u16 reserved3; /* word 105 */ - u16 physical_logical_sector_info; /* word 106 */ - u16 acoustic_test_interseek_delay; /* word 107 */ - u8 world_wide_name[ATA_IDENTIFY_WWN_LEN]; /* words 108-111 */ - u8 reserved_for_wwn_extention[ATA_IDENTIFY_WWN_LEN]; /* words 112-115 */ - u16 reserved4; /* word 116 */ - u8 words_per_logical_sector[4]; /* words 117-118 */ - u16 command_set_supported2; /* word 119 */ - u16 reserved5[7]; /* words 120-126 */ - u16 removable_media_status; /* word 127 */ - u16 security_status; /* word 128 */ - u16 vendor_specific1[31]; /* words 129-159 */ - u16 cfa_power_mode1; /* word 160 */ - u16 reserved_for_compact_flash2[7]; /* words 161-167 */ - u16 device_nominal_form_factor; /* word 168 */ - u16 reserved_for_compact_flash3[7]; /* words 169-175 */ - u16 current_media_serial_number[ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN]; /* words 176-205 */ - u16 reserved6[3]; /* words 206-208 */ - u16 logical_sector_alignment; /* words 209 */ - u16 reserved7[7]; /* words 210-216 */ - u16 nominal_media_rotation_rate; /* word 217 */ - u16 reserved8[37]; /* words 218-254 */ - u16 integrity_word; /* word 255 */ - -}; - -#define ATA_IDENTIFY_DEVICE_GET_OFFSET(field_name) \ - ((unsigned long)&(((struct ata_identify_device_data *)0)->field_name)) -#define ATA_IDENTIFY_DEVICE_WCE_ENABLE 0x20 -#define ATA_IDENTIFY_DEVICE_RA_ENABLE 0x40 - -/** - * struct ATAPI_IDENTIFY_PACKET_DATA - The following structure depicts the - * ATA-ATAPI 7 version of the IDENTIFY PACKET DEVICE data structure. - * - * - */ -struct atapi_identify_packet_device { - u16 generalConfigBits; /* word 00 */ - u16 reserved0; /* word 01 (num cylinders) */ - u16 uniqueConfigBits; /* word 02 */ - u16 reserved1[7]; /* words 03 - 09 */ - u8 serialNumber[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; /* word 10-19 */ - u16 reserved2[3]; /* words 20-22 */ - u8 firmwareRevision[ATA_IDENTIFY_FW_REVISION_LEN]; /* words 23-26 */ - u8 modelNumber[ATA_IDENTIFY_MODEL_NUMBER_LEN]; /* words 27-46 */ - u16 reserved4[2]; /* words 47-48 */ - u16 capabilities1; /* word 49 */ - u16 capabilities2; /* word 50 */ - u16 obsolete0[2]; /* words 51-52 */ - u16 validityBits; /* word 53 */ - u16 reserved[8]; /* words 54-61 */ - - u16 DMADIRBitRequired; /* word 62, page2 */ - u16 multiWordDmaMode; /* word 63 */ - u16 pioModesSupported; /* word 64 */ - u16 minMultiwordDmaTransferCycle; /* word 65 */ - u16 recMinMultiwordDmaTransferCycle; /* word 66 */ - u16 minPioTransferNoFlowCtrl; /* word 67 */ - u16 minPioTransferWithFlowCtrl; /* word 68 */ - u16 reserved6[2]; /* words 69-70 */ - u16 nsFromPACKETReceiptToBusRelease; /* word 71 */ - u16 nsFromSERVICEReceiptToBSYreset; /* wore 72 */ - u16 reserved7[2]; /* words 73-74 */ - u16 queueDepth; /* word 75 */ - u16 serialAtaCapabilities; /* word 76 */ - u16 serialAtaReserved; /* word 77 */ - u16 serialAtaFeaturesSupported; /* word 78 */ - u16 serialAtaFeaturesEnabled; /* word 79 */ - - u16 majorVersionNumber; /* word 80, page3 */ - u16 minorVersionNumber; /* word 81 */ - u16 commandSetSupported0; /* word 82 */ - u16 commandSetSupported1; /* word 83 */ - - u16 commandSetSupportedExtention; /* word 84, page4 */ - u16 commandSetEnabled0; /* word 85 */ - u16 commandSetEnabled1; /* word 86 */ - u16 commandSetDefault; /* word 87 */ - - u16 ultraDmaMode; /* word 88, page5 */ - u16 reserved8[4]; /* words 89 - 92 */ - - u16 hardwareResetResult; /* word 93, page6 */ - u16 currentAcousticManagementValue; /* word 94 */ - u16 reserved9[30]; /* words 95-124 */ - u16 ATAPIByteCount0Behavior; /* word 125 */ - u16 obsolete1; /* word 126 */ - u16 removableMediaStatus; /* word 127, */ - - u16 securityStatus; /* word 128, page7 */ - u16 vendorSpecific1[31]; /* words 129-159 */ - u16 reservedForCompactFlash[16]; /* words 160-175 */ - u16 reserved10[79]; /* words 176-254 */ - u16 integrityWord; /* word 255 */ -}; - -/** - * struct ata_extended_smart_self_test_log - The following structure depicts - * the ATA-8 version of the Extended SMART self test log page descriptor - * entry. - * - * - */ -union ata_descriptor_entry { - struct DESCRIPTOR_ENTRY { - u8 lba_field; - u8 status_byte; - u8 time_stamp_low; - u8 time_stamp_high; - u8 checkpoint_byte; - u8 failing_lba_low; - u8 failing_lba_mid; - u8 failing_lba_high; - u8 failing_lba_low_ext; - u8 failing_lba_mid_ext; - u8 failing_lba_high_ext; - - u8 vendor_specific1; - u8 vendor_specific2; - u8 vendor_specific3; - u8 vendor_specific4; - u8 vendor_specific5; - u8 vendor_specific6; - u8 vendor_specific7; - u8 vendor_specific8; - u8 vendor_specific9; - u8 vendor_specific10; - u8 vendor_specific11; - u8 vendor_specific12; - u8 vendor_specific13; - u8 vendor_specific14; - u8 vendor_specific15; - } DESCRIPTOR_ENTRY; - - u8 descriptor_entry[26]; - -}; - -/** - * struct ata_extended_smart_self_test_log - The following structure depicts - * the ATA-8 version of the SMART self test log page descriptor entry. - * - * - */ -union ata_smart_descriptor_entry { - struct SMART_DESCRIPTOR_ENTRY { - u8 lba_field; - u8 status_byte; - u8 time_stamp_low; - u8 time_stamp_high; - u8 checkpoint_byte; - u8 failing_lba_low; - u8 failing_lba_mid; - u8 failing_lba_high; - u8 failing_lba_low_ext; - - u8 vendor_specific1; - u8 vendor_specific2; - u8 vendor_specific3; - u8 vendor_specific4; - u8 vendor_specific5; - u8 vendor_specific6; - u8 vendor_specific7; - u8 vendor_specific8; - u8 vendor_specific9; - u8 vendor_specific10; - u8 vendor_specific11; - u8 vendor_specific12; - u8 vendor_specific13; - u8 vendor_specific14; - u8 vendor_specific15; - } SMART_DESCRIPTOR_ENTRY; - - u8 smart_descriptor_entry[24]; - -}; - -/** - * struct ata_extended_smart_self_test_log - The following structure depicts - * the ATA-8 version of the Extended SMART self test log page. - * - * - */ -struct ata_extended_smart_self_test_log { - u8 self_test_log_data_structure_revision_number; /* byte 0 */ - u8 reserved0; /* byte 1 */ - u8 self_test_descriptor_index[2]; /* byte 2-3 */ - - union ata_descriptor_entry descriptor_entrys[19]; /* bytes 4-497 */ - - u8 vendor_specific[2]; /* byte 498-499 */ - u8 reserved1[11]; /* byte 500-510 */ - u8 data_structure_checksum; /* byte 511 */ - -}; - -/** - * struct ata_extended_smart_self_test_log - The following structure depicts - * the ATA-8 version of the SMART self test log page. - * - * - */ -struct ata_smart_self_test_log { - u8 self_test_log_data_structure_revision_number[2]; /* bytes 0-1 */ - - union ata_smart_descriptor_entry descriptor_entrys[21]; /* bytes 2-505 */ - - u8 vendor_specific[2]; /* byte 506-507 */ - u8 self_test_index; /* byte 508 */ - u8 reserved1[2]; /* byte 509-510 */ - u8 data_structure_checksum; /* byte 511 */ - -}; - -#endif /* _ATA_H_ */ - diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index c12e6d4f4d7d..119eb5b3094a 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -62,8 +62,7 @@ * * */ - -#include "intel_sata.h" +#include #include "intel_scsi.h" /** diff --git a/drivers/scsi/isci/core/intel_sat.h b/drivers/scsi/isci/core/intel_sat.h deleted file mode 100644 index c4d78ed35cf1..000000000000 --- a/drivers/scsi/isci/core/intel_sat.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SAT_H_ -#define _SAT_H_ - -/** - * This file contains constants and constructs defined in the SCSI to ATA - * Translation (SAT) T10 standard. For more information please refer to - * www.t10.org. - * - * - */ - -/** - * - * - * SAT_PROTOCOLS These constants indicate the various protocol values that can - * be supported in a SAT translator. - */ -#define SAT_PROTOCOL_ATA_HARD_RESET 0 -#define SAT_PROTOCOL_SOFT_RESET 1 -#define SAT_PROTOCOL_NON_DATA 3 -#define SAT_PROTOCOL_PIO_DATA_IN 4 -#define SAT_PROTOCOL_PIO_DATA_OUT 5 -#define SAT_PROTOCOL_DMA 6 -#define SAT_PROTOCOL_DMA_QUEUED 7 -#define SAT_PROTOCOL_DEVICE_DIAGNOSTIC 8 -#define SAT_PROTOCOL_DEVICE_RESET 9 -#define SAT_PROTOCOL_UDMA_DATA_IN 10 -#define SAT_PROTOCOL_UDMA_DATA_OUT 11 -#define SAT_PROTOCOL_FPDMA 12 -#define SAT_PROTOCOL_RETURN_RESPONSE_INFO 15 - -#define SAT_PROTOCOL_PACKET 0x10 -#define SAT_PROTOCOL_PACKET_NON_DATA (SAT_PROTOCOL_PACKET | 0x0) -#define SAT_PROTOCOL_PACKET_DMA_DATA_IN (SAT_PROTOCOL_PACKET | 0x1) -#define SAT_PROTOCOL_PACKET_DMA_DATA_OUT (SAT_PROTOCOL_PACKET | 0x2) -#define SAT_PROTOCOL_PACKET_PIO_DATA_IN (SAT_PROTOCOL_PACKET | 0x3) -#define SAT_PROTOCOL_PACKET_PIO_DATA_OUT (SAT_PROTOCOL_PACKET | 0x4) - -#endif /* _SAT_H_ */ - diff --git a/drivers/scsi/isci/core/intel_sata.h b/drivers/scsi/isci/core/intel_sata.h deleted file mode 100644 index 977354d7b843..000000000000 --- a/drivers/scsi/isci/core/intel_sata.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SATA_H_ -#define _SATA_H_ - -#include - -/** - * This file defines all of the SATA releated constants, enumerations, and - * types. Please note that this file does not necessarily contain an - * exhaustive list of all contants and commands. - * - * - */ - -/** - * - * - * SATA FIS Types These constants depict the various SATA FIS types devined in - * the serial ATA specification. - */ -#define SATA_FIS_TYPE_REGH2D 0x27 -#define SATA_FIS_TYPE_REGD2H 0x34 -#define SATA_FIS_TYPE_SETDEVBITS 0xA1 -#define SATA_FIS_TYPE_DMA_ACTIVATE 0x39 -#define SATA_FIS_TYPE_DMA_SETUP 0x41 -#define SATA_FIS_TYPE_BIST_ACTIVATE 0x58 -#define SATA_FIS_TYPE_PIO_SETUP 0x5F -#define SATA_FIS_TYPE_DATA 0x46 - -#define SATA_REGISTER_FIS_SIZE 0x20 - -/** - * struct sata_fis_header - This is the common definition for a SATA FIS Header - * word. A different header word is defined for any FIS type that does not - * use the standard header. - * - * - */ -struct sata_fis_header { - u32 fis_type:8; /* word 0 */ - u32 pm_port:4; - u32 reserved:1; - u32 direction_flag:1; /* direction */ - u32 interrupt_flag:1; - u32 command_flag:1; /* command, auto_activate, or notification */ - u32 status:8; - u32 error:8; -}; - -/** - * - * - * Status field bit definitions - */ -#define SATA_FIS_STATUS_DEVBITS_MASK (0x77) - -/** - * struct sata_fis_set_dev_bits - SATA Set Device Bits FIS - * - * - */ -struct sata_fis_set_dev_bits { - u32 fis_type:8; /* word 0 */ - u32 pm_port:4; - u32 reserved0:2; - u32 irq:1; - u32 notification:1; - u32 status_low:4; - u32 status_high:4; - u32 error:8; - u32 s_active; /* word 1 */ -}; - -/** - * struct sata_fis_dma_activate - SATA DMA Activate FIS - * - * - */ -struct sata_fis_dma_activate { - u32 fis_type:8; /* word 0 */ - u32 pm_port:4; - u32 reserved0:24; -}; - -/** - * - * - * The lower 5 bits in the DMA Buffer ID Low field of the DMA Setup are used to - * communicate the command tag. - */ -#define SATA_DMA_SETUP_TAG_ENABLE 0x1F - -#define SATA_DMA_SETUP_AUTO_ACT_ENABLE 0x80 - -/** - * struct sata_fis_dma_setup - SATA DMA Setup FIS - * - * - */ -struct sata_fis_dma_setup { - u32 fis_type:8; /* word 0 */ - u32 pm_port:4; - u32 reserved_00:1; - u32 direction:1; - u32 irq:1; - u32 auto_activate:1; - u32 reserved_01:16; - u32 dma_buffer_id_low; /* word 1 */ - u32 dma_buffer_id_high; /* word 2 */ - u32 reserved0; /* word 3 */ - u32 dma_buffer_offset; /* word 4 */ - u32 dma_transfer_count; /* word 5 */ - u32 reserved1; /* word 6 */ -}; - -/** - * struct sata_fis_bist_activate - SATA BIST Activate FIS - * - * - */ -struct sata_fis_bist_activate { - u32 fis_type:8; /* word 0 */ - u32 reserved0:8; - u32 pattern_definition:8; - u32 reserved1:8; - u32 data1; /* word 1 */ - u32 data2; /* word 1 */ -}; - -/* - * SATA PIO Setup FIS - */ -struct sata_fis_pio_setup { - u32 fis_type:8; /* word 0 */ - u32 pm_port:4; - u32 reserved_00:1; - u32 direction:1; - u32 irq:1; - u32 reserved_01:1; - u32 status:8; - u32 error:8; - u32 lba_low:8; /* word 1 */ - u32 lba_mid:8; - u32 lba_high:8; - u32 device:8; - u32 lba_low_exp:8; /* word 2 */ - u32 lba_mid_exp:8; - u32 lba_high_exp:8; - u32 reserved:8; - u32 sector_count:8; /* word 3 */ - u32 sector_count_exp:8; - u32 reserved1:8; - u32 ending_status:8; - u32 transfter_count:16; /* word 4 */ - u32 reserved3:16; -}; - -/** - * struct sata_fis_data - SATA Data FIS - * - * - */ -struct sata_fis_data { - u32 fis_type:8; /* word 0 */ - u32 pm_port:4; - u32 reserved0:24; - u8 data[4]; /* word 1 */ -}; - -#endif /* _SATA_H_ */ diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 6fe39ccedf0b..d8c4bf1a958a 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -67,7 +67,6 @@ #include #include #include "sci_status.h" -#include "intel_sata.h" #include "intel_sas.h" struct scic_sds_phy; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 1b35b1ac1f8d..0f292f1be2bb 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -54,8 +54,7 @@ */ #include -#include "intel_ata.h" -#include "intel_sata.h" +#include "sas.h" #include "sci_base_state.h" #include "sci_base_state_machine.h" #include "scic_phy.h" @@ -1279,23 +1278,19 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle u32 frame_index) { enum sci_status result; - u32 *frame_words; - struct sata_fis_header *fis_frame_header; + struct dev_to_host_fis *frame_header; u32 *fis_frame_data; result = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_phy_get_controller(sci_phy)->uf_control), frame_index, - (void **)&frame_words); + (void **)&frame_header); - if (result != SCI_SUCCESS) { + if (result != SCI_SUCCESS) return result; - } - - fis_frame_header = (struct sata_fis_header *)frame_words; - if ((fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H) && - !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT)) { + if ((frame_header->fis_type == FIS_REGD2H) && + !(frame_header->status & ATA_BUSY)) { scic_sds_unsolicited_frame_control_get_buffer( &(scic_sds_phy_get_controller(sci_phy)->uf_control), frame_index, @@ -1303,10 +1298,10 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle scic_sds_controller_copy_sata_response( &sci_phy->phy_type.sata.signature_fis_buffer, - frame_words, + frame_header, fis_frame_data); - /* We got the IAF we can now go to the await spinup semaphore state */ + /* got IAF we can now go to the await spinup semaphore state */ sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); @@ -1318,7 +1313,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle __func__, frame_index); - /* Regardless of the result release this frame since we are done with it */ + /* Regardless of the result we are done with this frame with it */ scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), frame_index); diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index c9fa2071f9b2..22b3119ec7fd 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -56,7 +56,6 @@ #ifndef _SCIC_SDS_PHY_H_ #define _SCIC_SDS_PHY_H_ -#include "intel_sata.h" #include "intel_sas.h" #include "scu_registers.h" #include "sci_base_state_machine.h" diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 13067659a8c6..31df5267c096 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -55,8 +55,6 @@ #include #include "intel_sas.h" -#include "intel_sata.h" -#include "intel_sat.h" #include "scic_controller.h" #include "scic_io_request.h" #include "scic_sds_controller.h" @@ -631,51 +629,55 @@ static void scu_ssp_task_request_construct_task_context( * * enum sci_status */ -static enum sci_status scic_io_request_construct_sata(struct scic_sds_request *sci_req, - u8 proto, u32 len, - enum dma_data_direction dir, - bool copy) +static enum sci_status +scic_io_request_construct_sata(struct scic_sds_request *sci_req, + u32 len, + enum dma_data_direction dir, + bool copy) { enum sci_status status = SCI_SUCCESS; + struct isci_request *ireq = sci_req->ireq; + struct sas_task *task = isci_request_access_task(ireq); + + /* check for management protocols */ + if (ireq->ttype == tmf_task) { + struct isci_tmf *tmf = isci_request_access_tmf(ireq); + + if (tmf->tmf_code == isci_tmf_sata_srst_high || + tmf->tmf_code == isci_tmf_sata_srst_low) + return scic_sds_stp_soft_reset_request_construct(sci_req); + else { + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: Request 0x%p received un-handled SAT " + "management protocol 0x%x.\n", + __func__, sci_req, tmf->tmf_code); + + return SCI_FAILURE; + } + } - switch (proto) { - case SAT_PROTOCOL_PIO_DATA_IN: - case SAT_PROTOCOL_PIO_DATA_OUT: - status = scic_sds_stp_pio_request_construct(sci_req, proto, copy); - break; - - case SAT_PROTOCOL_UDMA_DATA_IN: - case SAT_PROTOCOL_UDMA_DATA_OUT: - status = scic_sds_stp_udma_request_construct(sci_req, len, dir); - break; + if (!sas_protocol_ata(task->task_proto)) { + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: Non-ATA protocol in SATA path: 0x%x\n", + __func__, + task->task_proto); + return SCI_FAILURE; - case SAT_PROTOCOL_ATA_HARD_RESET: - case SAT_PROTOCOL_SOFT_RESET: - status = scic_sds_stp_soft_reset_request_construct(sci_req); - break; + } - case SAT_PROTOCOL_NON_DATA: - status = scic_sds_stp_non_data_request_construct(sci_req); - break; + /* non data */ + if (task->data_dir == DMA_NONE) + return scic_sds_stp_non_data_request_construct(sci_req); - case SAT_PROTOCOL_FPDMA: - status = scic_sds_stp_ncq_request_construct(sci_req, len, dir); - break; + /* NCQ */ + if (task->ata_task.use_ncq) + return scic_sds_stp_ncq_request_construct(sci_req, len, dir); - case SAT_PROTOCOL_DMA_QUEUED: - case SAT_PROTOCOL_DMA: - case SAT_PROTOCOL_DEVICE_DIAGNOSTIC: - case SAT_PROTOCOL_DEVICE_RESET: - case SAT_PROTOCOL_RETURN_RESPONSE_INFO: - default: - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p received un-handled " - "SAT Protocl %d.\n", - __func__, sci_req, proto); - - status = SCI_FAILURE; - break; - } + /* DMA */ + if (task->ata_task.dma_xfer) + return scic_sds_stp_udma_request_construct(sci_req, len, dir); + else /* PIO */ + return scic_sds_stp_pio_request_construct(sci_req, copy); return status; } @@ -735,7 +737,6 @@ enum sci_status scic_io_request_construct_basic_sata( { enum sci_status status; struct scic_sds_stp_request *stp_req; - u8 proto; u32 len; enum dma_data_direction dir; bool copy = false; @@ -748,10 +749,9 @@ enum sci_status scic_io_request_construct_basic_sata( len = isci_request_io_request_get_transfer_length(isci_request); dir = isci_request_io_request_get_data_direction(isci_request); - proto = isci_sata_get_sat_protocol(isci_request); copy = (task->data_dir == DMA_NONE) ? false : true; - status = scic_io_request_construct_sata(sci_req, proto, len, dir, copy); + status = scic_io_request_construct_sata(sci_req, len, dir, copy); if (status == SCI_SUCCESS) sci_base_state_machine_change_state(&sci_req->state_machine, @@ -764,33 +764,30 @@ enum sci_status scic_io_request_construct_basic_sata( enum sci_status scic_task_request_construct_sata( struct scic_sds_request *sci_req) { - enum sci_status status; - u8 sat_protocol; - struct isci_request *isci_request = sci_req->ireq; - - sat_protocol = isci_sata_get_sat_protocol(isci_request); + enum sci_status status = SCI_SUCCESS; + struct isci_request *ireq = sci_req->ireq; - switch (sat_protocol) { - case SAT_PROTOCOL_ATA_HARD_RESET: - case SAT_PROTOCOL_SOFT_RESET: - status = scic_sds_stp_soft_reset_request_construct(sci_req); - break; + /* check for management protocols */ + if (ireq->ttype == tmf_task) { + struct isci_tmf *tmf = isci_request_access_tmf(ireq); - default: - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p received un-handled SAT " - "Protocl %d.\n", - __func__, - sci_req, - sat_protocol); + if (tmf->tmf_code == isci_tmf_sata_srst_high || + tmf->tmf_code == isci_tmf_sata_srst_low) { + status = scic_sds_stp_soft_reset_request_construct(sci_req); + } else { + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: Request 0x%p received un-handled SAT " + "Protocol 0x%x.\n", + __func__, sci_req, tmf->tmf_code); - status = SCI_FAILURE; - break; + return SCI_FAILURE; + } } if (status == SCI_SUCCESS) - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return status; } diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 1cd111c42ede..b3ad33bc4221 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -53,10 +53,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include "intel_ata.h" -#include "intel_sata.h" -#include "intel_sat.h" +#include +#include "sas.h" #include "sci_base_state.h" #include "sci_base_state_machine.h" #include "scic_io_request.h" @@ -136,7 +134,8 @@ u32 scic_sds_stp_request_get_object_size(void) void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) { - struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); sci_req->command_buffer = scic_sds_stp_request_get_h2d_reg_buffer(stp_req); sci_req->response_buffer = scic_sds_stp_request_get_response_buffer(stp_req); @@ -353,7 +352,7 @@ static void scu_stp_raw_request_construct_task_context( task_context->control_frame = 0; task_context->priority = SCU_TASK_PRIORITY_NORMAL; task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; - task_context->type.stp.fis_type = SATA_FIS_TYPE_REGH2D; + task_context->type.stp.fis_type = FIS_REGH2D; task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32); } @@ -484,68 +483,65 @@ static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_han * if the received frame was processed successfully. */ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( - struct scic_sds_request *request, + struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; - struct sata_fis_header *frame_header; + struct dev_to_host_fis *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); status = scic_sds_unsolicited_frame_control_get_header( - &sci_req->parent.owning_controller->uf_control, + &stp_req->parent.owning_controller->uf_control, frame_index, - (void **)&frame_header - ); + (void **)&frame_header); if (status == SCI_SUCCESS) { switch (frame_header->fis_type) { - case SATA_FIS_TYPE_REGD2H: + case FIS_REGD2H: scic_sds_unsolicited_frame_control_get_buffer( - &sci_req->parent.owning_controller->uf_control, + &stp_req->parent.owning_controller->uf_control, frame_index, - (void **)&frame_buffer - ); + (void **)&frame_buffer); scic_sds_controller_copy_sata_response( - &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer - ); + &stp_req->d2h_reg_fis, + (u32 *)frame_header, + frame_buffer); /* The command has completed with error */ scic_sds_request_set_status( - &sci_req->parent, + &stp_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); + SCI_FAILURE_IO_RESPONSE_VALID); break; default: - dev_warn(scic_to_dev(request->owning_controller), + dev_warn(scic_to_dev(sci_req->owning_controller), "%s: IO Request:0x%p Frame Id:%d protocol " "violation occurred\n", - __func__, sci_req, frame_index); + __func__, stp_req, frame_index); scic_sds_request_set_status( - &sci_req->parent, + &stp_req->parent, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION - ); + SCI_FAILURE_PROTOCOL_VIOLATION); break; } sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &stp_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame( - sci_req->parent.owning_controller, frame_index); + stp_req->parent.owning_controller, frame_index); } else - dev_err(scic_to_dev(request->owning_controller), + dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, sci_req, frame_index, status); + __func__, stp_req, frame_index, status); return status; } @@ -603,7 +599,8 @@ static const struct sci_base_state scic_sds_stp_request_started_non_data_substat enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req) { - struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); scic_sds_stp_non_ncq_request_construct(sci_req); @@ -634,7 +631,8 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( struct scic_sds_request *sci_req, u32 length) { - struct scic_sds_stp_request *stp_req = (struct scic_sds_stp_request *)sci_req; + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); struct scu_sgl_element *current_sgl; /* @@ -654,7 +652,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( task_context->command_iu_upper = current_sgl->address_upper; task_context->command_iu_lower = current_sgl->address_lower; task_context->transfer_length_bytes = length; - task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; + task_context->type.stp.fis_type = FIS_DATA; /* send the new TC out. */ return scic_controller_continue_io(sci_req); @@ -675,7 +673,8 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data( u32 remaining_bytes_in_current_sgl = 0; enum sci_status status = SCI_SUCCESS; - struct scic_sds_stp_request *stp_req = (struct scic_sds_stp_request *)sci_req; + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); sgl_offset = stp_req->type.pio.request_current.sgl_offset; @@ -855,122 +854,126 @@ static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completi * enum sci_status */ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( - struct scic_sds_request *request, + struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; - struct sata_fis_header *frame_header; + struct dev_to_host_fis *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *sci_req; - - sci_req = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + struct isci_request *ireq = sci_req->ireq; + struct sas_task *task = isci_request_access_task(ireq); status = scic_sds_unsolicited_frame_control_get_header( - &(sci_req->parent.owning_controller->uf_control), + &(stp_req->parent.owning_controller->uf_control), frame_index, - (void **)&frame_header - ); + (void **)&frame_header); if (status == SCI_SUCCESS) { switch (frame_header->fis_type) { - case SATA_FIS_TYPE_PIO_SETUP: + case FIS_PIO_SETUP: /* Get from the frame buffer the PIO Setup Data */ scic_sds_unsolicited_frame_control_get_buffer( - &(sci_req->parent.owning_controller->uf_control), + &(stp_req->parent.owning_controller->uf_control), frame_index, - (void **)&frame_buffer - ); + (void **)&frame_buffer); - /* - * Get the data from the PIO Setup - * The SCU Hardware returns first word in the frame_header and the rest - * of the data is in the frame buffer so we need to back up one dword */ - sci_req->type.pio.pio_transfer_bytes = - (u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count; - sci_req->type.pio.ending_status = - (u8)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->ending_status; + /* Get the data from the PIO Setup The SCU Hardware + * returns first word in the frame_header and the rest + * of the data is in the frame buffer so we need to back + * up one dword + */ + + /* transfer_count: first 16bits in the 4th dword */ + stp_req->type.pio.pio_transfer_bytes = + frame_buffer[3] & 0xffff; + + /* ending_status: 4th byte in the 3rd dword */ + stp_req->type.pio.ending_status = + (frame_buffer[2] >> 24) & 0xff; scic_sds_controller_copy_sata_response( - &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer - ); + &stp_req->d2h_reg_fis, + (u32 *)frame_header, + frame_buffer); - sci_req->d2h_reg_fis.status = - sci_req->type.pio.ending_status; + stp_req->d2h_reg_fis.status = + stp_req->type.pio.ending_status; - /* The next state is dependent on whether the request was PIO Data-in or Data out */ - if (sci_req->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN) { + /* The next state is dependent on whether the + * request was PIO Data-in or Data out + */ + if (task->data_dir == DMA_FROM_DEVICE) { sci_base_state_machine_change_state( - &sci_req->parent.started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE - ); - } else if (sci_req->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT) { + &stp_req->parent.started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); + } else if (task->data_dir == DMA_TO_DEVICE) { /* Transmit data */ - status = scic_sds_stp_request_pio_data_out_transmit_data(request); + status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); if (status == SCI_SUCCESS) { sci_base_state_machine_change_state( - &sci_req->parent.started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE - ); + &stp_req->parent.started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); } } break; - case SATA_FIS_TYPE_SETDEVBITS: + case FIS_SETDEVBITS: sci_base_state_machine_change_state( - &sci_req->parent.started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); + &stp_req->parent.started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); break; - case SATA_FIS_TYPE_REGD2H: - if ((frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0) { + case FIS_REGD2H: + if ((frame_header->status & ATA_BUSY) == 0) { scic_sds_unsolicited_frame_control_get_buffer( - &(sci_req->parent.owning_controller->uf_control), + &(stp_req->parent.owning_controller->uf_control), frame_index, - (void **)&frame_buffer - ); + (void **)&frame_buffer); scic_sds_controller_copy_sata_response( - &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer); + &stp_req->d2h_reg_fis, + (u32 *)frame_header, + frame_buffer); scic_sds_request_set_status( - &sci_req->parent, + &stp_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); + SCI_FAILURE_IO_RESPONSE_VALID); sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &stp_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); } else { - /* - * Now why is the drive sending a D2H Register FIS when it is still busy? - * Do nothing since we are still in the right state. */ - dev_dbg(scic_to_dev(request->owning_controller), + /* Now why is the drive sending a D2H Register + * FIS when it is still busy? + * Do nothing since we are still in the right + * state. + */ + dev_dbg(scic_to_dev(sci_req->owning_controller), "%s: SCIC PIO Request 0x%p received " "D2H Register FIS with BSY status " "0x%x\n", __func__, - sci_req, + stp_req, frame_header->status); } break; default: + /* FIXME: what do we do here? */ break; } /* Frame is decoded return it to the controller */ scic_sds_controller_release_frame( - sci_req->parent.owning_controller, - frame_index - ); + stp_req->parent.owning_controller, + frame_index); } else - dev_err(scic_to_dev(request->owning_controller), + dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, sci_req, frame_index, status); + __func__, stp_req, frame_index, status); return status; } @@ -983,100 +986,94 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( * enum sci_status */ static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler( - struct scic_sds_request *request, + struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; - struct sata_fis_header *frame_header; + struct dev_to_host_fis *frame_header; struct sata_fis_data *frame_buffer; - struct scic_sds_stp_request *sci_req; - - sci_req = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); status = scic_sds_unsolicited_frame_control_get_header( - &(sci_req->parent.owning_controller->uf_control), + &(stp_req->parent.owning_controller->uf_control), frame_index, - (void **)&frame_header - ); + (void **)&frame_header); if (status == SCI_SUCCESS) { - if (frame_header->fis_type == SATA_FIS_TYPE_DATA) { - if (sci_req->type.pio.request_current.sgl_pair == NULL) { - sci_req->parent.saved_rx_frame_index = frame_index; - sci_req->type.pio.pio_transfer_bytes = 0; + if (frame_header->fis_type == FIS_DATA) { + if (stp_req->type.pio.request_current.sgl_pair == + NULL) { + stp_req->parent.saved_rx_frame_index = + frame_index; + stp_req->type.pio.pio_transfer_bytes = 0; } else { status = scic_sds_unsolicited_frame_control_get_buffer( - &(sci_req->parent.owning_controller->uf_control), + &(stp_req->parent.owning_controller->uf_control), frame_index, - (void **)&frame_buffer - ); + (void **)&frame_buffer); - status = scic_sds_stp_request_pio_data_in_copy_data(sci_req, (u8 *)frame_buffer); + status = scic_sds_stp_request_pio_data_in_copy_data( + stp_req, + (u8 *)frame_buffer); /* Frame is decoded return it to the controller */ scic_sds_controller_release_frame( - sci_req->parent.owning_controller, - frame_index - ); + stp_req->parent.owning_controller, + frame_index); } /* - * Check for the end of the transfer, are there more bytes remaining - * for this data transfer */ - if ( - (status == SCI_SUCCESS) - && (sci_req->type.pio.pio_transfer_bytes == 0) - ) { - if ((sci_req->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0) { + * Check for the end of the transfer, are there more + * bytes remaining for this data transfer + */ + if ((status == SCI_SUCCESS) && + (stp_req->type.pio.pio_transfer_bytes == 0)) { + if ((stp_req->type.pio.ending_status & + ATA_BUSY) == 0) { scic_sds_request_set_status( - &sci_req->parent, + &stp_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); + SCI_FAILURE_IO_RESPONSE_VALID); sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &stp_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); } else { sci_base_state_machine_change_state( - &request->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); + &sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); } } } else { - dev_err(scic_to_dev(request->owning_controller), + dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC PIO Request 0x%p received frame %d " "with fis type 0x%02x when expecting a data " "fis.\n", __func__, - sci_req, + stp_req, frame_index, frame_header->fis_type); scic_sds_request_set_status( - &sci_req->parent, + &stp_req->parent, SCU_TASK_DONE_GOOD, - SCI_FAILURE_IO_REQUIRES_SCSI_ABORT - ); + SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); sci_base_state_machine_change_state( - &sci_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + &stp_req->parent.state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); /* Frame is decoded return it to the controller */ scic_sds_controller_release_frame( - sci_req->parent.owning_controller, - frame_index - ); + stp_req->parent.owning_controller, + frame_index); } } else - dev_err(scic_to_dev(request->owning_controller), + dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, sci_req, frame_index, status); + __func__, stp_req, frame_index, status); return status; } @@ -1094,10 +1091,10 @@ static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_com struct scic_sds_request *sci_req, u32 completion_code) { - enum sci_status status = SCI_SUCCESS; - bool all_frames_transferred = false; - - struct scic_sds_stp_request *stp_req = (struct scic_sds_stp_request *)sci_req; + enum sci_status status = SCI_SUCCESS; + bool all_frames_transferred = false; + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): @@ -1279,11 +1276,12 @@ static const struct sci_base_state scic_sds_stp_request_started_pio_substate_tab } }; -enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, - u8 sat_protocol, - bool copy_rx_frame) +enum sci_status +scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, + bool copy_rx_frame) { - struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; scic_sds_stp_non_ncq_request_construct(sci_req); @@ -1297,7 +1295,6 @@ enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_ pio->request_current.sgl_offset = 0; pio->request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; - pio->sat_protocol = sat_protocol; if (copy_rx_frame) { scic_sds_request_build_sgl(sci_req); @@ -1340,30 +1337,25 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler( u32 frame_index) { enum sci_status status; - struct sata_fis_header *frame_header; + struct dev_to_host_fis *frame_header; u32 *frame_buffer; status = scic_sds_unsolicited_frame_control_get_header( &sci_req->owning_controller->uf_control, frame_index, - (void **)&frame_header - ); + (void **)&frame_header); - if ( - (status == SCI_SUCCESS) - && (frame_header->fis_type == SATA_FIS_TYPE_REGD2H) - ) { + if ((status == SCI_SUCCESS) && + (frame_header->fis_type == FIS_REGD2H)) { scic_sds_unsolicited_frame_control_get_buffer( &sci_req->owning_controller->uf_control, frame_index, - (void **)&frame_buffer - ); + (void **)&frame_buffer); scic_sds_controller_copy_sata_response( &((struct scic_sds_stp_request *)sci_req)->d2h_reg_fis, (u32 *)frame_header, - frame_buffer - ); + frame_buffer); } scic_sds_controller_release_frame( @@ -1399,7 +1391,7 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi /* * We must check ther response buffer to see if the D2H Register FIS was * received before we got the TC completion. */ - if (sci_req->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H) { + if (sci_req->d2h_reg_fis.fis_type == FIS_REGD2H) { scic_sds_remote_device_suspend( sci_req->parent.target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) @@ -1648,35 +1640,34 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( u32 frame_index) { enum sci_status status; - struct sata_fis_header *frame_header; + struct dev_to_host_fis *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *stp_req = + (struct scic_sds_stp_request *)request; status = scic_sds_unsolicited_frame_control_get_header( - &(sci_req->parent.owning_controller->uf_control), + &(stp_req->parent.owning_controller->uf_control), frame_index, - (void **)&frame_header - ); + (void **)&frame_header); if (status == SCI_SUCCESS) { switch (frame_header->fis_type) { - case SATA_FIS_TYPE_REGD2H: + case FIS_REGD2H: scic_sds_unsolicited_frame_control_get_buffer( - &(sci_req->parent.owning_controller->uf_control), + &(stp_req->parent.owning_controller->uf_control), frame_index, - (void **)&frame_buffer - ); + (void **)&frame_buffer); scic_sds_controller_copy_sata_response( - &sci_req->d2h_reg_fis, (u32 *)frame_header, frame_buffer - ); + &stp_req->d2h_reg_fis, + (u32 *)frame_header, + frame_buffer); /* The command has completed with error */ scic_sds_request_set_status( - &sci_req->parent, + &stp_req->parent, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); + SCI_FAILURE_IO_RESPONSE_VALID); break; default: @@ -1684,30 +1675,28 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( "%s: IO Request:0x%p Frame Id:%d protocol " "violation occurred\n", __func__, - sci_req, + stp_req, frame_index); scic_sds_request_set_status( - &sci_req->parent, + &stp_req->parent, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION - ); + SCI_FAILURE_PROTOCOL_VIOLATION); break; } sci_base_state_machine_change_state( - &sci_req->parent.state_machine, + &stp_req->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame( - sci_req->parent.owning_controller, frame_index - ); + stp_req->parent.owning_controller, frame_index); } else dev_err(scic_to_dev(request->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", - __func__, sci_req, frame_index, status); + __func__, stp_req, frame_index, status); return status; } @@ -1798,7 +1787,8 @@ static const struct sci_base_state scic_sds_stp_request_started_soft_reset_subst enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req) { - struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); scic_sds_stp_non_ncq_request_construct(sci_req); diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index 807bc4eeb821..50cb48ef554e 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -57,7 +57,7 @@ #define _SCIC_SDS_STP_REQUEST_T_ #include -#include "intel_sata.h" +#include #include "scic_sds_request.h" /** @@ -111,11 +111,6 @@ struct scic_sds_stp_request { */ u8 ending_error; - /** - * Protocol Type. This is filled in by core during IO Request construction type. - */ - u8 sat_protocol; - struct scic_sds_request_pio_sgl { struct scu_sgl_element_pair *sgl_pair; u8 sgl_set; @@ -173,7 +168,6 @@ u32 scic_sds_stp_request_get_object_size(void); enum sci_status scic_sds_stp_pio_request_construct( struct scic_sds_request *scic_io_request, - u8 sat_protocol, bool copy_rx_frame); enum sci_status scic_sds_stp_udma_request_construct( diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index a23ebe85773e..e766b27bdc19 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -53,7 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "intel_sas.h" -#include "intel_ata.h" +#include "sas.h" #include "isci.h" #include "port.h" #include "remote_device.h" @@ -327,7 +327,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi break; } case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: { - struct sata_fis_header *hdr; + struct dev_to_host_fis *hdr; status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, frame_index, @@ -335,14 +335,14 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi if (status != SCI_SUCCESS) return status; - if (hdr->fis_type == SATA_FIS_TYPE_SETDEVBITS && - (hdr->status & ATA_STATUS_REG_ERROR_BIT)) { + if (hdr->fis_type == FIS_SETDEVBITS && + (hdr->status & ATA_ERR)) { sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; /* TODO Check sactive and complete associated IO if any. */ sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); - } else if (hdr->fis_type == SATA_FIS_TYPE_REGD2H && - (hdr->status & ATA_STATUS_REG_ERROR_BIT)) { + } else if (hdr->fis_type == FIS_REGD2H && + (hdr->status & ATA_ERR)) { /* * Some devices return D2H FIS when an NCQ error is detected. * Treat this like an SDB error FIS ready reason. @@ -469,6 +469,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic struct sci_base_state_machine *sm = &sci_dev->state_machine; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_port *sci_port = sci_dev->owning_port; + struct isci_request *ireq = sci_req->ireq; enum sci_status status; switch (state) { @@ -510,6 +511,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic * substate. */ enum scic_sds_remote_device_states new_state; + struct sas_task *task = isci_request_access_task(ireq); status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); if (status != SCI_SUCCESS) @@ -523,7 +525,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic if (status != SCI_SUCCESS) break; - if (isci_sata_get_sat_protocol(sci_req->ireq) == SAT_PROTOCOL_FPDMA) + if (task->ata_task.use_ncq) new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ; else { sci_dev->working_request = sci_req; @@ -532,8 +534,10 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic sci_base_state_machine_change_state(sm, new_state); break; } - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: - if (isci_sata_get_sat_protocol(sci_req->ireq) == SAT_PROTOCOL_FPDMA) { + case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: { + struct sas_task *task = isci_request_access_task(ireq); + + if (task->ata_task.use_ncq) { status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); if (status != SCI_SUCCESS) return status; @@ -546,6 +550,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic } else return SCI_FAILURE_INVALID_STATE; break; + } case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h new file mode 100644 index 000000000000..05af8bd61453 --- /dev/null +++ b/drivers/scsi/isci/sas.h @@ -0,0 +1,72 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_SAS_H_ +#define _SCI_SAS_H_ +/* + * SATA FIS Types These constants depict the various SATA FIS types devined in + * the serial ATA specification. + * XXX: This needs to go into + */ +#define FIS_REGH2D 0x27 +#define FIS_REGD2H 0x34 +#define FIS_SETDEVBITS 0xA1 +#define FIS_DMA_ACTIVATE 0x39 +#define FIS_DMA_SETUP 0x41 +#define FIS_BIST_ACTIVATE 0x58 +#define FIS_PIO_SETUP 0x5F +#define FIS_DATA 0x46 + +#endif diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 08374505832e..a08fcf511908 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -61,11 +61,6 @@ #include "task.h" #include "request.h" #include "sata.h" -#include "intel_sat.h" -#include "intel_ata.h" - -static u8 isci_sata_get_management_task_protocol(struct isci_tmf *tmf); - /** * isci_sata_task_to_fis_copy() - This function gets the host_to_dev_fis from @@ -158,7 +153,7 @@ void isci_request_process_stp_response(struct sas_task *task, * If the device fault bit is set in the status register, then * set the sense data and return. */ - if (d2h_reg_fis->status & ATA_STATUS_REG_DEVICE_FAULT_BIT) + if (d2h_reg_fis->status & ATA_DF) ts->stat = SAS_PROTO_RESPONSE; else ts->stat = SAM_STAT_GOOD; @@ -166,74 +161,6 @@ void isci_request_process_stp_response(struct sas_task *task, ts->resp = SAS_TASK_COMPLETE; } -/** - * isci_sata_get_sat_protocol() - retrieve the sat protocol for the request - * @isci_request: ata request - * - * Note: temporary implementation until expert mode removes the callback - * - */ -u8 isci_sata_get_sat_protocol(struct isci_request *isci_request) -{ - struct sas_task *task; - struct domain_device *dev; - - dev_dbg(&isci_request->isci_host->pdev->dev, - "%s: isci_request = %p, ttype = %d\n", - __func__, isci_request, isci_request->ttype); - - if (tmf_task == isci_request->ttype) { - struct isci_tmf *tmf = isci_request_access_tmf(isci_request); - - return isci_sata_get_management_task_protocol(tmf); - } - - task = isci_request_access_task(isci_request); - dev = task->dev; - - if (!sas_protocol_ata(task->task_proto)) { - WARN(1, "unhandled task protocol\n"); - return SAT_PROTOCOL_NON_DATA; - } - - if (task->data_dir == DMA_NONE) - return SAT_PROTOCOL_NON_DATA; - - /* the "_IN" protocol types are equivalent to their "_OUT" - * analogs as far as the core is concerned - */ - if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { - if (task->ata_task.dma_xfer) - return SAT_PROTOCOL_PACKET_DMA_DATA_IN; - else - return SAT_PROTOCOL_PACKET_PIO_DATA_IN; - } - - if (task->ata_task.use_ncq) - return SAT_PROTOCOL_FPDMA; - - if (task->ata_task.dma_xfer) - return SAT_PROTOCOL_UDMA_DATA_IN; - else - return SAT_PROTOCOL_PIO_DATA_IN; -} - -static u8 isci_sata_get_management_task_protocol( - struct isci_tmf *tmf) -{ - u8 ret = 0; - - pr_warn("tmf = %p, func = %d\n", tmf, tmf->tmf_code); - - if ((tmf->tmf_code == isci_tmf_sata_srst_high) || - (tmf->tmf_code == isci_tmf_sata_srst_low)) { - pr_warn("%s: tmf->tmf_code == TMF_LU_RESET\n", __func__); - ret = SAT_PROTOCOL_SOFT_RESET; - } - - return ret; -} - enum sci_status isci_sata_management_task_request_build( struct isci_request *isci_request) { diff --git a/drivers/scsi/isci/sata.h b/drivers/scsi/isci/sata.h index b6ba25b52d2c..1b89f1f75770 100644 --- a/drivers/scsi/isci/sata.h +++ b/drivers/scsi/isci/sata.h @@ -53,10 +53,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "intel_sat.h" - - - struct host_to_dev_fis *isci_sata_task_to_fis_copy( struct sas_task *task); -- cgit v1.2.3 From 4b7ebd05fc074ac2ffdc803232d83f3593d4f548 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 15:37:52 -0700 Subject: isci: Convert SAS identify address frame to Linux Native format Convert struct sci_sas_identify_address_frame to struct sas_identify_frame Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 29 ------------ drivers/scsi/isci/core/scic_phy.h | 2 +- drivers/scsi/isci/core/scic_sds_phy.c | 86 +++++++++-------------------------- drivers/scsi/isci/core/scic_sds_phy.h | 2 +- drivers/scsi/isci/phy.h | 2 +- drivers/scsi/isci/port.c | 12 ++--- 6 files changed, 27 insertions(+), 106 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index 119eb5b3094a..61a5ececdd52 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -111,35 +111,6 @@ struct sci_sas_identify_address_frame_protocols { }; -/** - * struct sci_sas_identify_address_frame - This structure depicts the contents - * of the SAS IDENTIFY ADDRESS FRAME (IAF). - * - * For specific information on each of these individual fields please reference - * the SAS specification Link layer section on address frames. - */ -struct sci_sas_identify_address_frame { - u16 address_frame_type:4; - u16 device_type:3; - u16 reserved1:1; - u16 reason:4; - u16 reserved2:4; - - struct sci_sas_identify_address_frame_protocols protocols; - - struct sci_sas_address device_name; - struct sci_sas_address sas_address; - - u32 phy_identifier:8; - u32 break_reply_capable:1; - u32 requested_in_zpsds:1; - u32 in_zpsds_persistent:1; - u32 reserved5:21; - - u32 reserved6[4]; - -}; - /** * struct sas_capabilities - This structure depicts the various SAS * capabilities supported by the directly attached target device. For diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index d8c4bf1a958a..4e4a6b1f9953 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -119,7 +119,7 @@ struct scic_sas_phy_properties { * This field delineates the Identify Address Frame received * from the remote end point. */ - struct sci_sas_identify_address_frame received_iaf; + struct sas_identify_frame rcvd_iaf; /** * This field delineates the Phy capabilities structure received diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 0f292f1be2bb..672e81b57711 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -411,15 +411,7 @@ static void scic_sds_phy_suspend( SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); } -/** - * - * @sci_phy: The phy object to resume. - * - * This function will perform the register reads/writes required to resume the - * SCU hardware protocol engine. none - */ -void scic_sds_phy_resume( - struct scic_sds_phy *sci_phy) +void scic_sds_phy_resume(struct scic_sds_phy *sci_phy) { u32 scu_sas_pcfg_value; @@ -430,47 +422,22 @@ void scic_sds_phy_resume( &sci_phy->link_layer_registers->phy_configuration); } -/** - * This method returns the local sas address assigned to this phy. - * @sci_phy: This parameter specifies the phy for which to retrieve the local - * SAS address. - * @sas_address: This parameter specifies the location into which to copy the - * local SAS address. - * - */ -void scic_sds_phy_get_sas_address( - struct scic_sds_phy *sci_phy, - struct sci_sas_address *sas_address) +void scic_sds_phy_get_sas_address(struct scic_sds_phy *sci_phy, + struct sci_sas_address *sas_address) { sas_address->high = readl(&sci_phy->link_layer_registers->source_sas_address_high); sas_address->low = readl(&sci_phy->link_layer_registers->source_sas_address_low); } -/** - * This method returns the remote end-point (i.e. attached) sas address - * assigned to this phy. - * @sci_phy: This parameter specifies the phy for which to retrieve the remote - * end-point SAS address. - * @sas_address: This parameter specifies the location into which to copy the - * remote end-point SAS address. - * - */ -void scic_sds_phy_get_attached_sas_address( - struct scic_sds_phy *sci_phy, - struct sci_sas_address *sas_address) +void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy, + struct sci_sas_address *sas_address) { - sas_address->high - = sci_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high; - sas_address->low - = sci_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low; + struct sas_identify_frame *iaf; + + iaf = &sci_phy->phy_type.sas.identify_address_frame_buffer; + memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); } -/** - * This method returns the supported protocols assigned to this phy - * @sci_phy: - * - * - */ void scic_sds_phy_get_protocols( struct scic_sds_phy *sci_phy, struct sci_sas_identify_address_frame_protocols *protocols) @@ -481,17 +448,6 @@ void scic_sds_phy_get_protocols( 0x0000FFFF); } -/** - * - * @sci_phy: The parameter is the phy object for which the attached phy - * protcols are to be returned. - * - * This method returns the supported protocols for the attached phy. If this - * is a SAS phy the protocols are returned from the identify address frame. If - * this is a SATA phy then protocols are made up and the target phy is an STP - * target phy. The caller will get the entire set of bits for the protocol - * value. - */ void scic_sds_phy_get_attached_phy_protocols( struct scic_sds_phy *sci_phy, struct sci_sas_identify_address_frame_protocols *protocols) @@ -499,8 +455,10 @@ void scic_sds_phy_get_attached_phy_protocols( protocols->u.all = 0; if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { - protocols->u.all = - sci_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all; + struct sas_identify_frame *iaf; + + iaf = &sci_phy->phy_type.sas.identify_address_frame_buffer; + memcpy(&protocols->u.all, &iaf->initiator_bits, 2); } else if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { protocols->u.bits.stp_target = 1; } @@ -599,11 +557,9 @@ enum sci_status scic_sas_phy_get_properties( struct scic_sas_phy_properties *properties) { if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { - memcpy( - &properties->received_iaf, - &sci_phy->phy_type.sas.identify_address_frame_buffer, - sizeof(struct sci_sas_identify_address_frame) - ); + memcpy(&properties->rcvd_iaf, + &sci_phy->phy_type.sas.identify_address_frame_buffer, + sizeof(struct sas_identify_frame)); properties->received_capabilities.u.all = readl(&sci_phy->link_layer_registers->receive_phycap); @@ -1203,7 +1159,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler { enum sci_status result; u32 *frame_words; - struct sci_sas_identify_address_frame *identify_frame; + struct sas_identify_frame *identify_frame; result = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_phy_get_controller(sci_phy)->uf_control), @@ -1215,9 +1171,9 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler } frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]); - identify_frame = (struct sci_sas_identify_address_frame *)frame_words; + identify_frame = (struct sas_identify_frame *)frame_words; - if (identify_frame->address_frame_type == 0) { + if (identify_frame->frame_type == 0) { u32 state; /* Byte swap the rest of the frame so we can make @@ -1231,9 +1187,9 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler memcpy(&sci_phy->phy_type.sas.identify_address_frame_buffer, identify_frame, - sizeof(struct sci_sas_identify_address_frame)); + sizeof(struct sas_identify_frame)); - if (identify_frame->protocols.u.bits.smp_target) { + if (identify_frame->smp_tport) { /* We got the IAF for an expander PHY go to the final state since * there are no power requirements for expander phys. */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 22b3119ec7fd..7bf95539b2a0 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -274,7 +274,7 @@ struct scic_sds_phy { union { struct { - struct sci_sas_identify_address_frame identify_address_frame_buffer; + struct sas_identify_frame identify_address_frame_buffer; } sas; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 3fe1a8a13169..3100fd87c788 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -80,7 +80,7 @@ struct isci_phy { u8 sas_addr[SAS_ADDR_SIZE]; union { - u8 aif[sizeof(struct sci_sas_identify_address_frame)]; + struct sas_identify_frame iaf; struct dev_to_host_fis fis; } frame_rcvd; }; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 5b38f2f963e0..0a1577327d61 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -236,18 +236,12 @@ void isci_port_link_up( BUG_ON(call_status != SCI_SUCCESS); - memcpy(isci_phy->frame_rcvd.aif, - &(sas_phy_properties.received_iaf), - sizeof(struct sci_sas_identify_address_frame)); - - isci_phy->sas_phy.frame_rcvd_size - = sizeof(struct sci_sas_identify_address_frame); + isci_phy->frame_rcvd.iaf = sas_phy_properties.rcvd_iaf; + isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame); /* Copy the attached SAS address from the IAF */ memcpy(isci_phy->sas_phy.attached_sas_addr, - ((struct sas_identify_frame *) - (&isci_phy->frame_rcvd.aif))->sas_addr, - SAS_ADDR_SIZE); + isci_phy->frame_rcvd.iaf.sas_addr, SAS_ADDR_SIZE); } else { dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__); -- cgit v1.2.3 From 1dea554fce698b7e8ad03cab1525f41cd6c28092 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 16:13:17 -0700 Subject: isci: Collapsing of phy_type data structure Collapsing of struct scic_sds_phy phy_type data structure Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_phy.c | 12 ++++++------ drivers/scsi/isci/core/scic_sds_phy.h | 12 ++---------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 672e81b57711..0e381cff25a9 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -434,7 +434,7 @@ void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy, { struct sas_identify_frame *iaf; - iaf = &sci_phy->phy_type.sas.identify_address_frame_buffer; + iaf = &sci_phy->phy_type.sas_id_frame; memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); } @@ -457,7 +457,7 @@ void scic_sds_phy_get_attached_phy_protocols( if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { struct sas_identify_frame *iaf; - iaf = &sci_phy->phy_type.sas.identify_address_frame_buffer; + iaf = &sci_phy->phy_type.sas_id_frame; memcpy(&protocols->u.all, &iaf->initiator_bits, 2); } else if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { protocols->u.bits.stp_target = 1; @@ -558,7 +558,7 @@ enum sci_status scic_sas_phy_get_properties( { if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { memcpy(&properties->rcvd_iaf, - &sci_phy->phy_type.sas.identify_address_frame_buffer, + &sci_phy->phy_type.sas_id_frame, sizeof(struct sas_identify_frame)); properties->received_capabilities.u.all = @@ -577,7 +577,7 @@ enum sci_status scic_sata_phy_get_properties( { if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { memcpy(&properties->signature_fis, - &sci_phy->phy_type.sata.signature_fis_buffer, + &sci_phy->phy_type.sata_sig_fis, sizeof(struct dev_to_host_fis)); /* / @todo add support for port selectors. */ @@ -1185,7 +1185,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]); frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]); - memcpy(&sci_phy->phy_type.sas.identify_address_frame_buffer, + memcpy(&sci_phy->phy_type.sas_id_frame, identify_frame, sizeof(struct sas_identify_frame)); @@ -1253,7 +1253,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle (void **)&fis_frame_data); scic_sds_controller_copy_sata_response( - &sci_phy->phy_type.sata.signature_fis_buffer, + &sci_phy->phy_type.sata_sig_fis, frame_header, fis_frame_data); diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 7bf95539b2a0..47b2194574a0 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -273,16 +273,8 @@ struct scic_sds_phy { bool is_in_link_training; union { - struct { - struct sas_identify_frame identify_address_frame_buffer; - - } sas; - - struct { - struct dev_to_host_fis signature_fis_buffer; - - } sata; - + struct sas_identify_frame sas_id_frame; + struct dev_to_host_fis sata_sig_fis; } phy_type; /** -- cgit v1.2.3 From ed0e24830e7b744d0d0ae5936740f1cdbd0ec5ba Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 16:16:44 -0700 Subject: isci: renaming sas_capabilities to scic_phy_cap This seems to be a data structure that represents the phy capabilities register from the hardware and has nothing to do with SAS data structs. Moving and fixup Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 36 -------------------------------- drivers/scsi/isci/core/scic_phy.h | 30 ++++++++++++++++++++++++++- drivers/scsi/isci/core/scic_sds_phy.c | 39 +++++++++++++++++++---------------- 3 files changed, 50 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index 61a5ececdd52..91c30cfee21d 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -111,42 +111,6 @@ struct sci_sas_identify_address_frame_protocols { }; -/** - * struct sas_capabilities - This structure depicts the various SAS - * capabilities supported by the directly attached target device. For - * specific information on each of these individual fields please reference - * the SAS specification Phy layer section on speed negotiation windows. - * - * - */ -struct sas_capabilities { - union { - struct { - /** - * The SAS specification indicates the start bit shall always be set to - * 1. This implementation will have the start bit set to 0 if the - * PHY CAPABILITIES were either not received or speed negotiation failed. - */ - u32 start:1; - u32 tx_ssc_type:1; - u32 reserved1:2; - u32 requested_logical_link_rate:4; - - u32 gen1_without_ssc_supported:1; - u32 gen1_with_ssc_supported:1; - u32 gen2_without_ssc_supported:1; - u32 gen2_with_ssc_supported:1; - u32 gen3_without_ssc_supported:1; - u32 gen3_with_ssc_supported:1; - u32 reserved2:17; - u32 parity:1; - } bits; - - u32 all; - } u; - -}; - /** * enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS * specification defined task attribute values for a command information diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 4e4a6b1f9953..8fcd3a4c5744 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -75,6 +75,34 @@ struct scic_sds_port; enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy); +struct scic_phy_cap { + union { + struct { + /* + * The SAS specification indicates the start bit shall + * always be set to + * 1. This implementation will have the start bit set + * to 0 if the PHY CAPABILITIES were either not + * received or speed negotiation failed. + */ + u8 start:1; + u8 tx_ssc_type:1; + u8 res1:2; + u8 req_logical_linkrate:4; + + u32 gen1_no_ssc:1; + u32 gen1_ssc:1; + u32 gen2_no_ssc:1; + u32 gen2_ssc:1; + u32 gen3_no_ssc:1; + u32 gen3_ssc:1; + u32 res2:17; + u32 parity:1; + }; + u32 all; + }; +} __packed; + /** * struct scic_phy_properties - This structure defines the properties common to * all phys that can be retrieved. @@ -125,7 +153,7 @@ struct scic_sas_phy_properties { * This field delineates the Phy capabilities structure received * from the remote end point. */ - struct sas_capabilities received_capabilities; + struct scic_phy_cap rcvd_cap; }; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 0e381cff25a9..bd2b30587703 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -122,12 +122,15 @@ static enum sci_status scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, struct scu_link_layer_registers __iomem *link_layer_registers) { - struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + struct scic_sds_controller *scic = + sci_phy->owning_port->owning_controller; int phy_idx = sci_phy->phy_index; - struct sci_phy_user_params *phy_user = &scic->user_parameters.sds1.phys[phy_idx]; - struct sci_phy_oem_params *phy_oem = &scic->oem_parameters.sds1.phys[phy_idx]; + struct sci_phy_user_params *phy_user = + &scic->user_parameters.sds1.phys[phy_idx]; + struct sci_phy_oem_params *phy_oem = + &scic->oem_parameters.sds1.phys[phy_idx]; u32 phy_configuration; - struct sas_capabilities phy_capabilities; + struct scic_phy_cap phy_cap; u32 parity_check = 0; u32 parity_count = 0; u32 llctl, link_rate; @@ -146,7 +149,8 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, &sci_phy->link_layer_registers->transmit_identification); /* Write the device SAS Address */ - writel(0xFEDCBA98, &sci_phy->link_layer_registers->sas_device_name_high); + writel(0xFEDCBA98, + &sci_phy->link_layer_registers->sas_device_name_high); writel(phy_idx, &sci_phy->link_layer_registers->sas_device_name_low); /* Write the source SAS Address */ @@ -170,21 +174,21 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, &sci_phy->link_layer_registers->phy_configuration); /* Configure the SNW capabilities */ - phy_capabilities.u.all = 0; - phy_capabilities.u.bits.start = 1; - phy_capabilities.u.bits.gen3_without_ssc_supported = 1; - phy_capabilities.u.bits.gen2_without_ssc_supported = 1; - phy_capabilities.u.bits.gen1_without_ssc_supported = 1; + phy_cap.all = 0; + phy_cap.start = 1; + phy_cap.gen3_no_ssc = 1; + phy_cap.gen2_no_ssc = 1; + phy_cap.gen1_no_ssc = 1; if (scic->oem_parameters.sds1.controller.do_enable_ssc == true) { - phy_capabilities.u.bits.gen3_with_ssc_supported = 1; - phy_capabilities.u.bits.gen2_with_ssc_supported = 1; - phy_capabilities.u.bits.gen1_with_ssc_supported = 1; + phy_cap.gen3_ssc = 1; + phy_cap.gen2_ssc = 1; + phy_cap.gen1_ssc = 1; } /* * The SAS specification indicates that the phy_capabilities that * are transmitted shall have an even parity. Calculate the parity. */ - parity_check = phy_capabilities.u.all; + parity_check = phy_cap.all; while (parity_check != 0) { if (parity_check & 0x1) parity_count++; @@ -195,10 +199,9 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, * If parity indicates there are an odd number of bits set, then * set the parity bit to 1 in the phy capabilities. */ if ((parity_count % 2) != 0) - phy_capabilities.u.bits.parity = 1; + phy_cap.parity = 1; - writel(phy_capabilities.u.all, - &sci_phy->link_layer_registers->phy_capabilities); + writel(phy_cap.all, &sci_phy->link_layer_registers->phy_capabilities); /* Set the enable spinup period but disable the ability to send * notify enable spinup @@ -561,7 +564,7 @@ enum sci_status scic_sas_phy_get_properties( &sci_phy->phy_type.sas_id_frame, sizeof(struct sas_identify_frame)); - properties->received_capabilities.u.all = + properties->rcvd_cap.all = readl(&sci_phy->link_layer_registers->receive_phycap); return SCI_SUCCESS; -- cgit v1.2.3 From 0cfa890e5a8a9e3b01b75c17a7856cf96e026e27 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 17:44:54 -0700 Subject: isci: Fixup SSP command IU and task IU Fixup of SSP command IU and SSP task IU to something that looks like Linux Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 47 ------------ drivers/scsi/isci/core/scic_sds_request.c | 108 ++++++++++---------------- drivers/scsi/isci/request.c | 121 ------------------------------ drivers/scsi/isci/sas.h | 34 +++++++++ drivers/scsi/isci/task.c | 49 ------------ 5 files changed, 74 insertions(+), 285 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index 91c30cfee21d..f7301aa14f02 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -160,53 +160,6 @@ enum sci_sas_frame_type { SCI_SAS_TASK_FRAME = 0x16 }; -/** - * struct sci_ssp_command_iu - This structure depicts the contents of the SSP - * COMMAND INFORMATION UNIT. For specific information on each of these - * individual fields please reference the SAS specification SSP transport - * layer section. - * - * - */ -struct sci_ssp_command_iu { - u32 lun_upper; - u32 lun_lower; - - u32 additional_cdb_length:6; - u32 reserved0:2; - u32 reserved1:8; - u32 enable_first_burst:1; - u32 task_priority:4; - u32 task_attribute:3; - u32 reserved2:8; - - u32 cdb[4]; - -}; - -/** - * struct sci_ssp_task_iu - This structure depicts the contents of the SSP TASK - * INFORMATION UNIT. For specific information on each of these individual - * fields please reference the SAS specification SSP transport layer section. - * - * - */ -struct sci_ssp_task_iu { - u32 lun_upper; - u32 lun_lower; - - u32 reserved0:8; - u32 task_function:8; - u32 reserved1:8; - u32 reserved2:8; - - u32 reserved3:16; - u32 task_tag:16; - - u32 reserved4[3]; - -}; - #define SSP_RESPONSE_IU_MAX_DATA 64 #define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK (0x03) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 31df5267c096..b6d1333e01fd 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -54,6 +54,7 @@ */ #include +#include "sas.h" #include "intel_sas.h" #include "scic_controller.h" #include "scic_io_request.h" @@ -98,7 +99,7 @@ */ #define scic_ssp_io_request_get_object_size() \ (\ - sizeof(struct sci_ssp_command_iu) \ + sizeof(struct ssp_cmd_iu) \ + sizeof(struct sci_ssp_response_iu) \ ) @@ -109,7 +110,7 @@ * memory */ #define scic_sds_ssp_request_get_command_buffer(memory) \ - ((struct sci_ssp_command_iu *)(\ + ((struct ssp_cmd_iu *)(\ ((char *)(memory)) + sizeof(struct scic_sds_request) \ )) @@ -122,7 +123,7 @@ #define scic_sds_ssp_request_get_response_buffer(memory) \ ((struct sci_ssp_response_iu *)(\ ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \ - + sizeof(struct sci_ssp_command_iu) \ + + sizeof(struct ssp_cmd_iu) \ )) /** @@ -158,7 +159,7 @@ */ #define scic_ssp_task_request_get_object_size() \ (\ - sizeof(struct sci_ssp_task_iu) \ + sizeof(struct ssp_task_iu) \ + sizeof(struct sci_ssp_response_iu) \ ) @@ -169,7 +170,7 @@ * memory. Yes its the same as the above macro except for the name. */ #define scic_sds_ssp_task_request_get_command_buffer(memory) \ - ((struct sci_ssp_task_iu *)(\ + ((struct ssp_task_iu *)(\ ((char *)(memory)) + sizeof(struct scic_sds_request) \ )) @@ -182,7 +183,7 @@ #define scic_sds_ssp_task_request_get_response_buffer(memory) \ ((struct sci_ssp_response_iu *)(\ ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \ - + sizeof(struct sci_ssp_task_iu) \ + + sizeof(struct ssp_task_iu) \ )) /** @@ -344,80 +345,49 @@ static void scic_sds_ssp_io_request_assign_buffers( } } -/** - * This method constructs the SSP Command IU data for this io request object. - * @sci_req: This parameter specifies the request object for which the SSP - * command information unit is being built. - * - */ -static void scic_sds_io_request_build_ssp_command_iu( - struct scic_sds_request *sds_request) +static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) { - struct sci_ssp_command_iu *command_frame; - u32 cdb_length; - u32 *cdb_buffer; - struct isci_request *isci_request = sds_request->ireq; - - command_frame = - (struct sci_ssp_command_iu *)sds_request->command_buffer; - - command_frame->lun_upper = 0; - command_frame->lun_lower = - isci_request_ssp_io_request_get_lun(isci_request); - - ((u32 *)command_frame)[2] = 0; + struct ssp_cmd_iu *cmd_iu; + struct isci_request *ireq = sci_req->ireq; + struct sas_task *task = isci_request_access_task(ireq); - cdb_length = isci_request_ssp_io_request_get_cdb_length(isci_request); - cdb_buffer = (u32 *)isci_request_ssp_io_request_get_cdb_address( - isci_request); + cmd_iu = sci_req->command_buffer; - if (cdb_length > 16) { - command_frame->additional_cdb_length = cdb_length - 16; - } + memcpy(cmd_iu->LUN, task->ssp_task.LUN, 8); + cmd_iu->add_cdb_len = 0; + cmd_iu->_r_a = 0; + cmd_iu->_r_b = 0; + cmd_iu->en_fburst = 0; /* unsupported */ + cmd_iu->task_prio = task->ssp_task.task_prio; + cmd_iu->task_attr = task->ssp_task.task_attr; + cmd_iu->_r_c = 0; - /* / @todo Is it ok to leave junk at the end of the cdb buffer? */ scic_word_copy_with_swap( - (u32 *)(&command_frame->cdb), - (u32 *)(cdb_buffer), - (cdb_length + 3) / sizeof(u32) - ); - - command_frame->enable_first_burst = 0; - command_frame->task_priority = - isci_request_ssp_io_request_get_command_priority(isci_request); - command_frame->task_attribute = - isci_request_ssp_io_request_get_task_attribute(isci_request); + (u32 *)(&cmd_iu->cdb), + (u32 *)task->ssp_task.cdb, + sizeof(task->ssp_task.cdb) / sizeof(u32)); } - -/** - * This method constructs the SSP Task IU data for this io request object. - * @sci_req: - * - */ -static void scic_sds_task_request_build_ssp_task_iu( - struct scic_sds_request *sds_request) +static void scic_sds_task_request_build_ssp_task_iu(struct scic_sds_request *sci_req) { - struct sci_ssp_task_iu *command_frame; - struct isci_request *isci_request = sds_request->ireq; + struct ssp_task_iu *task_iu; + struct isci_request *ireq = sci_req->ireq; + struct sas_task *task = isci_request_access_task(ireq); + struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - command_frame = - (struct sci_ssp_task_iu *)sds_request->command_buffer; + task_iu = sci_req->command_buffer; - command_frame->lun_upper = 0; - command_frame->lun_lower = isci_request_ssp_io_request_get_lun( - isci_request); + memset(task_iu, 0, sizeof(struct ssp_task_iu)); - ((u32 *)command_frame)[2] = 0; + memcpy(task_iu->LUN, task->ssp_task.LUN, 8); - command_frame->task_function = - isci_task_ssp_request_get_function(isci_request); - command_frame->task_tag = - isci_task_ssp_request_get_io_tag_to_manage( - isci_request); + task_iu->task_func = isci_tmf->tmf_code; + task_iu->task_tag = + (ireq->ttype == tmf_task) ? + isci_tmf->io_tag : + SCI_CONTROLLER_INVALID_IO_TAG; } - /** * This method is will fill in the SCU Task Context for any type of SSP request. * @sci_req: @@ -533,7 +503,8 @@ static void scu_ssp_io_request_construct_task_context( scu_ssp_reqeust_construct_task_context(sci_req, task_context); - task_context->ssp_command_iu_length = sizeof(struct sci_ssp_command_iu) / sizeof(u32); + task_context->ssp_command_iu_length = + sizeof(struct ssp_cmd_iu) / sizeof(u32); task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME; switch (dir) { @@ -605,7 +576,8 @@ static void scu_ssp_task_request_construct_task_context( task_context->task_type = SCU_TASK_TYPE_RAW_FRAME; task_context->transfer_length_bytes = 0; task_context->type.ssp.frame_type = SCI_SAS_TASK_FRAME; - task_context->ssp_command_iu_length = sizeof(struct sci_ssp_task_iu) / sizeof(u32); + task_context->ssp_command_iu_length = + sizeof(struct ssp_task_iu) / sizeof(u32); } diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c45e78e41f27..501df3ca4280 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1241,124 +1241,3 @@ enum dma_data_direction isci_request_io_request_get_data_direction( return task->data_dir; } - -/** - * isci_request_sge_get_address_field() - This function is called by the sci - * core to retrieve the address field contents for a given sge. - * @request: This parameter is the isci_request object. - * @sge_address: This parameter is the sge. - * - * physical address in the specified sge. - */ - - -/** - * isci_request_sge_get_length_field() - This function is called by the sci - * core to retrieve the length field contents for a given sge. - * @request: This parameter is the isci_request object. - * @sge_address: This parameter is the sge. - * - * length field value in the specified sge. - */ - - -/** - * isci_request_ssp_io_request_get_cdb_address() - This function is called by - * the sci core to retrieve the cdb address for a given request. - * @request: This parameter is the isci_request object. - * - * cdb address for specified request. - */ -void *isci_request_ssp_io_request_get_cdb_address( - struct isci_request *request) -{ - struct sas_task *task = isci_request_access_task(request); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: request->task->ssp_task.cdb = %p\n", - __func__, - task->ssp_task.cdb); - return task->ssp_task.cdb; -} - - -/** - * isci_request_ssp_io_request_get_cdb_length() - This function is called by - * the sci core to retrieve the cdb length for a given request. - * @request: This parameter is the isci_request object. - * - * cdb length for specified request. - */ -u32 isci_request_ssp_io_request_get_cdb_length( - struct isci_request *request) -{ - return 16; -} - - -/** - * isci_request_ssp_io_request_get_lun() - This function is called by the sci - * core to retrieve the lun for a given request. - * @request: This parameter is the isci_request object. - * - * lun for specified request. - */ -u32 isci_request_ssp_io_request_get_lun( - struct isci_request *request) -{ - struct sas_task *task = isci_request_access_task(request); - -#ifdef DEBUG - int i; - - for (i = 0; i < 8; i++) - dev_dbg(&request->isci_host->pdev->dev, - "%s: task->ssp_task.LUN[%d] = %x\n", - __func__, i, task->ssp_task.LUN[i]); - -#endif - - return task->ssp_task.LUN[0]; -} - - -/** - * isci_request_ssp_io_request_get_task_attribute() - This function is called - * by the sci core to retrieve the task attribute for a given request. - * @request: This parameter is the isci_request object. - * - * task attribute for specified request. - */ -u32 isci_request_ssp_io_request_get_task_attribute( - struct isci_request *request) -{ - struct sas_task *task = isci_request_access_task(request); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: request->task->ssp_task.task_attr = %x\n", - __func__, - task->ssp_task.task_attr); - - return task->ssp_task.task_attr; -} - - -/** - * isci_request_ssp_io_request_get_command_priority() - This function is called - * by the sci core to retrieve the command priority for a given request. - * @request: This parameter is the isci_request object. - * - * command priority for specified request. - */ -u32 isci_request_ssp_io_request_get_command_priority( - struct isci_request *request) -{ - struct sas_task *task = isci_request_access_task(request); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: request->task->ssp_task.task_prio = %x\n", - __func__, - task->ssp_task.task_prio); - - return task->ssp_task.task_prio; -} diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index 05af8bd61453..21ddd63924eb 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h @@ -69,4 +69,38 @@ #define FIS_PIO_SETUP 0x5F #define FIS_DATA 0x46 +/* + * contents of the SSP COMMAND INFORMATION UNIT. + * For specific information on each of these individual fields please + * reference the SAS specification SSP transport layer section. + * XXX: This needs to go into + */ +struct ssp_cmd_iu { + u8 LUN[8]; + u8 add_cdb_len:6; + u8 _r_a:2; + u8 _r_b; + u8 en_fburst:1; + u8 task_prio:4; + u8 task_attr:3; + u8 _r_c; + + u8 cdb[16]; +} __packed; + +/* + * contents of the SSP TASK INFORMATION UNIT. + * For specific information on each of these individual fields please + * reference the SAS specification SSP transport layer section. + * XXX: This needs to go into + */ +struct ssp_task_iu { + u8 LUN[8]; + u8 _r_a; + u8 task_func; + u8 _r_b[4]; + u16 task_tag; + u8 _r_c[12]; +} __packed; + #endif diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index f9a1c41a5ce8..c4db95933d41 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1481,55 +1481,6 @@ void isci_task_request_complete( complete(tmf_complete); } - -/** - * isci_task_ssp_request_get_lun() - This function is called by the sci core to - * retrieve the lun for a given task request. - * @request: This parameter is the isci_request object. - * - * lun for specified task request. - */ - -/** - * isci_task_ssp_request_get_function() - This function is called by the sci - * core to retrieve the function for a given task request. - * @request: This parameter is the isci_request object. - * - * function code for specified task request. - */ -u8 isci_task_ssp_request_get_function(struct isci_request *request) -{ - struct isci_tmf *isci_tmf = isci_request_access_tmf(request); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: func = %d\n", __func__, isci_tmf->tmf_code); - - return isci_tmf->tmf_code; -} - -/** - * isci_task_ssp_request_get_io_tag_to_manage() - This function is called by - * the sci core to retrieve the io tag for a given task request. - * @request: This parameter is the isci_request object. - * - * io tag for specified task request. - */ -u16 isci_task_ssp_request_get_io_tag_to_manage(struct isci_request *request) -{ - u16 io_tag = SCI_CONTROLLER_INVALID_IO_TAG; - - if (tmf_task == request->ttype) { - struct isci_tmf *tmf = isci_request_access_tmf(request); - io_tag = tmf->io_tag; - } - - dev_dbg(&request->isci_host->pdev->dev, - "%s: request = %p, io_tag = %d\n", - __func__, request, io_tag); - - return io_tag; -} - /** * isci_task_ssp_request_get_response_data_address() - This function is called * by the sci core to retrieve the response data address for a given task -- cgit v1.2.3 From af5ae89350840b9d724fc4fb81d928673bffdd4d Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 17:53:24 -0700 Subject: isci: Convert of sci_ssp_response_iu to ssp_response_iu Converting to Linux native format. However the isci driver does a lot of the calculation based on the max size of this data structure and the Linux data structure only has a pointer to the response data. Thus the sizeof(struct ssp_response_iu) will be incorrect and we need to define the max size. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 46 ------ drivers/scsi/isci/core/scic_sds_request.c | 222 +++++++++++--------------- drivers/scsi/isci/core/scic_sds_stp_request.c | 2 +- drivers/scsi/isci/sas.h | 3 + drivers/scsi/isci/task.c | 100 ++++-------- drivers/scsi/isci/task.h | 20 +-- 6 files changed, 141 insertions(+), 252 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index f7301aa14f02..3d4ca12df5ff 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -160,52 +160,6 @@ enum sci_sas_frame_type { SCI_SAS_TASK_FRAME = 0x16 }; -#define SSP_RESPONSE_IU_MAX_DATA 64 - -#define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK (0x03) - - -#define sci_ssp_get_sense_data_length(sense_data_length_buffer) \ - SCIC_BUILD_DWORD(sense_data_length_buffer) - -#define sci_ssp_get_response_data_length(response_data_length_buffer) \ - SCIC_BUILD_DWORD(response_data_length_buffer) - -/** - * struct sci_ssp_response_iu - This structure depicts the contents of the SSP - * RESPONSE INFORMATION UNIT. For specific information on each of these - * individual fields please reference the SAS specification SSP transport - * layer section. - * - * - */ -struct sci_ssp_response_iu { - u8 reserved0[8]; - - u8 retry_delay_timer[2]; - u8 data_present; - u8 status; - - u8 reserved1[4]; - u8 sense_data_length[4]; - u8 response_data_length[4]; - - u32 data[SSP_RESPONSE_IU_MAX_DATA]; - -}; - -/** - * enum _SCI_SAS_DATA_PRESENT_TYPE - This enumeration depicts the SAS - * specification defined SSP data present types in struct sci_ssp_response_iu. - * - * - */ -enum sci_ssp_response_iu_data_present_type { - SCI_SSP_RESPONSE_IU_NO_DATA = 0x00, - SCI_SSP_RESPONSE_IU_RESPONSE_DATA = 0x01, - SCI_SSP_RESPONSE_IU_SENSE_DATA = 0x02 -}; - /** * struct sci_ssp_frame_header - This structure depicts the contents of an SSP * frame header. For specific information on the individual fields please diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index b6d1333e01fd..ef59e019398e 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -100,7 +100,7 @@ #define scic_ssp_io_request_get_object_size() \ (\ sizeof(struct ssp_cmd_iu) \ - + sizeof(struct sci_ssp_response_iu) \ + + SSP_RESP_IU_MAX_SIZE \ ) /** @@ -121,7 +121,7 @@ * memory */ #define scic_sds_ssp_request_get_response_buffer(memory) \ - ((struct sci_ssp_response_iu *)(\ + ((struct ssp_response_iu *)(\ ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \ + sizeof(struct ssp_cmd_iu) \ )) @@ -135,7 +135,7 @@ #define scic_sds_ssp_request_get_task_context_buffer(memory) \ ((struct scu_task_context *)(\ ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \ - + sizeof(struct sci_ssp_response_iu) \ + + SSP_RESP_IU_MAX_SIZE \ )) /** @@ -160,7 +160,7 @@ #define scic_ssp_task_request_get_object_size() \ (\ sizeof(struct ssp_task_iu) \ - + sizeof(struct sci_ssp_response_iu) \ + + SSP_RESP_IU_MAX_SIZE \ ) /** @@ -181,7 +181,7 @@ * request memory. */ #define scic_sds_ssp_task_request_get_response_buffer(memory) \ - ((struct sci_ssp_response_iu *)(\ + ((struct ssp_response_iu *)(\ ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \ + sizeof(struct ssp_task_iu) \ )) @@ -194,7 +194,7 @@ #define scic_sds_ssp_task_request_get_task_context_buffer(memory) \ ((struct scu_task_context *)(\ ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \ - + sizeof(struct sci_ssp_response_iu) \ + + SSP_RESP_IU_MAX_SIZE \ )) @@ -937,52 +937,29 @@ enum sci_status scic_sds_io_request_frame_handler( return SCI_FAILURE_INVALID_STATE; } -/** - * - * @sci_req: The SCIC_SDS_IO_REQUEST_T object for which the task start - * operation is to be executed. - * - * This method invokes the core state task complete handler for the - * SCIC_SDS_IO_REQUEST_T object. enum sci_status - */ - /* - * **************************************************************************** - * * SCIC SDS PROTECTED METHODS - * **************************************************************************** */ - -/** - * This method copies response data for requests returning response data + * This function copies response data for requests returning response data * instead of sense data. * @sci_req: This parameter specifies the request object for which to copy * the response data. - * */ -void scic_sds_io_request_copy_response(struct scic_sds_request *sds_request) +void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) { - void *response_buffer; - u32 user_response_length; - u32 core_response_length; - struct sci_ssp_response_iu *ssp_response; - struct isci_request *isci_request = sds_request->ireq; - - ssp_response = - (struct sci_ssp_response_iu *)sds_request->response_buffer; - - response_buffer = - isci_task_ssp_request_get_response_data_address( - isci_request); + void *resp_buf; + u32 len; + struct ssp_response_iu *ssp_response; + struct isci_request *ireq = sci_req->ireq; + struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - user_response_length = - isci_task_ssp_request_get_response_data_length( - isci_request); + ssp_response = sci_req->response_buffer; - core_response_length = sci_ssp_get_response_data_length( - ssp_response->response_data_length); + resp_buf = &isci_tmf->resp.resp_iu; - user_response_length = min(user_response_length, core_response_length); + len = min_t(u32, + SSP_RESP_IU_MAX_SIZE, + be32_to_cpu(ssp_response->response_data_len)); - memcpy(response_buffer, ssp_response->data, user_response_length); + memcpy(resp_buf, ssp_response->resp_data, len); } /* @@ -1102,7 +1079,7 @@ enum sci_status scic_sds_request_started_state_abort_handler( return SCI_SUCCESS; } -/** +/* * scic_sds_request_started_state_tc_completion_handler() - This method process * TC (task context) completions for normal IO request (i.e. Task/Abort * Completions of type 0). This method will update the @@ -1113,50 +1090,51 @@ enum sci_status scic_sds_request_started_state_abort_handler( * the SCU. * */ -enum sci_status scic_sds_request_started_state_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) +enum sci_status +scic_sds_request_started_state_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) { - u8 data_present; - struct sci_ssp_response_iu *response_buffer; + u8 datapres; + struct ssp_response_iu *resp_iu; - /** - * @todo Any SDMA return code of other than 0 is bad + /* + * TODO: Any SDMA return code of other than 0 is bad * decode 0x003C0000 to determine SDMA status */ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): { /* - * There are times when the SCU hardware will return an early response - * because the io request specified more data than is returned by the - * target device (mode pages, inquiry data, etc.). We must check the - * response stats to see if this is truly a failed request or a good - * request that just got completed early. */ - struct sci_ssp_response_iu *response = (struct sci_ssp_response_iu *) - sci_req->response_buffer; + * There are times when the SCU hardware will return an early + * response because the io request specified more data than is + * returned by the target device (mode pages, inquiry data, + * etc.). We must check the response stats to see if this is + * truly a failed request or a good request that just got + * completed early. + */ + struct ssp_response_iu *resp = sci_req->response_buffer; scic_word_copy_with_swap( sci_req->response_buffer, sci_req->response_buffer, - sizeof(struct sci_ssp_response_iu) / sizeof(u32) - ); + SSP_RESP_IU_MAX_SIZE / sizeof(u32)); - if (response->status == 0) { + if (resp->status == 0) { scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY - ); + sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS_IO_DONE_EARLY); } else { scic_sds_request_set_status( sci_req, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); + SCI_FAILURE_IO_RESPONSE_VALID); } } break; @@ -1165,36 +1143,31 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( scic_word_copy_with_swap( sci_req->response_buffer, sci_req->response_buffer, - sizeof(struct sci_ssp_response_iu) / sizeof(u32) - ); + SSP_RESP_IU_MAX_SIZE / sizeof(u32)); scic_sds_request_set_status( sci_req, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); + SCI_FAILURE_IO_RESPONSE_VALID); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR): /* - * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed - * / to be received before this completion status is posted? */ - response_buffer = - (struct sci_ssp_response_iu *)sci_req->response_buffer; - data_present = - response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK; - - if ((data_present == 0x01) || (data_present == 0x02)) { + * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame + * guaranteed to be received before this completion status is + * posted? + */ + resp_iu = sci_req->response_buffer; + datapres = resp_iu->datapres; + + if ((datapres == 0x01) || (datapres == 0x02)) { scic_sds_request_set_status( sci_req, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); - } else { + SCI_FAILURE_IO_RESPONSE_VALID); + } else scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - } + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; /* only stp device gets suspended. */ @@ -1212,15 +1185,15 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( if (sci_req->protocol == SCIC_STP_PROTOCOL) { scic_sds_request_set_status( sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED - ); + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); } else { scic_sds_request_set_status( sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); } break; @@ -1237,9 +1210,9 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): scic_sds_request_set_status( sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED - ); + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); break; /* neither ssp nor stp gets suspended. */ @@ -1261,19 +1234,20 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( default: scic_sds_request_set_status( sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); break; } - /** - * @todo This is probably wrong for ACK/NAK timeout conditions + /* + * TODO: This is probably wrong for ACK/NAK timeout conditions */ - /* In all cases we will treat this as the completion of the IO request. */ - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + /* In all cases we will treat this as the completion of the IO req. */ + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } @@ -1285,49 +1259,42 @@ enum sci_status scic_sds_request_started_state_tc_completion_handler( * at completion time. If the frame type is not a response buffer an error is * logged. enum sci_status SCI_SUCCESS SCI_FAILURE_INVALID_PARAMETER_VALUE */ -static enum sci_status scic_sds_request_started_state_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) +static enum sci_status +scic_sds_request_started_state_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) { enum sci_status status; struct sci_ssp_frame_header *frame_header; - /* / @todo If this is a response frame we must record that we received it */ status = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, - (void **)&frame_header - ); + (void **)&frame_header); if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME) { - struct sci_ssp_response_iu *response_buffer; + struct ssp_response_iu *resp_iu; status = scic_sds_unsolicited_frame_control_get_buffer( &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, - (void **)&response_buffer - ); + (void **)&resp_iu); - scic_word_copy_with_swap( - sci_req->response_buffer, - (u32 *)response_buffer, - sizeof(struct sci_ssp_response_iu) - ); + scic_word_copy_with_swap(sci_req->response_buffer, + (u32 *)resp_iu, + SSP_RESP_IU_MAX_SIZE); - response_buffer = (struct sci_ssp_response_iu *)sci_req->response_buffer; + resp_iu = sci_req->response_buffer; - if ((response_buffer->data_present == 0x01) || - (response_buffer->data_present == 0x02)) { + if ((resp_iu->datapres == 0x01) || + (resp_iu->datapres == 0x02)) { scic_sds_request_set_status( sci_req, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); } else scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - } else + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); + } else { /* This was not a response frame why did it get forwarded? */ dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC IO Request 0x%p received unexpected " @@ -1336,13 +1303,14 @@ static enum sci_status scic_sds_request_started_state_frame_handler( sci_req, frame_index, frame_header->frame_type); + } /* * In any case we are done with this frame buffer return it to the - * controller */ + * controller + */ scic_sds_controller_release_frame( - sci_req->owning_controller, frame_index - ); + sci_req->owning_controller, frame_index); return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index b3ad33bc4221..8569dba6c68b 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -102,7 +102,7 @@ #define scic_sds_stp_request_get_task_context_buffer(memory) \ ((struct scu_task_context *)(\ ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \ - + sizeof(struct sci_ssp_response_iu) \ + + SSP_RESP_IU_MAX_SIZE \ )) /** diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index 21ddd63924eb..1a1e9bc125c3 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h @@ -69,6 +69,9 @@ #define FIS_PIO_SETUP 0x5F #define FIS_DATA 0x46 +/**************************************************************************/ +#define SSP_RESP_IU_MAX_SIZE 280 + /* * contents of the SSP COMMAND INFORMATION UNIT. * For specific information on each of these individual fields please diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c4db95933d41..8449d8abd66a 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -55,6 +55,7 @@ #include #include +#include "sas.h" #include "scic_task_request.h" #include "scic_io_request.h" #include "remote_device.h" @@ -63,7 +64,8 @@ #include "request.h" #include "sata.h" #include "task.h" -#include "core/scic_sds_request.h" +#include "scic_sds_stp_request.h" + /** * isci_task_refuse() - complete the request to the upper layer driver in * the case where an I/O needs to be completed back in the submit path. @@ -1411,108 +1413,74 @@ int isci_task_query_task( return TMF_RESP_FUNC_SUCC; } -/** +/* * isci_task_request_complete() - This function is called by the sci core when * an task request completes. - * @isci_host: This parameter specifies the ISCI host object - * @request: This parameter is the completed isci_request object. + * @ihost: This parameter specifies the ISCI host object + * @ireq: This parameter is the completed isci_request object. * @completion_status: This parameter specifies the completion status from the * sci core. * * none. */ -void isci_task_request_complete( - struct isci_host *isci_host, - struct isci_request *request, - enum sci_task_status completion_status) +void +isci_task_request_complete(struct isci_host *ihost, + struct isci_request *ireq, + enum sci_task_status completion_status) { - struct isci_remote_device *isci_device = request->isci_device; + struct isci_remote_device *idev = ireq->isci_device; enum isci_request_status old_state; - struct isci_tmf *tmf = isci_request_access_tmf(request); + struct isci_tmf *tmf = isci_request_access_tmf(ireq); struct completion *tmf_complete; + struct scic_sds_request *sci_req = ireq->sci_request_handle; + struct scic_sds_stp_request *stp_req = + container_of(sci_req, typeof(*stp_req), parent); - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: request = %p, status=%d\n", - __func__, request, completion_status); + __func__, ireq, completion_status); - old_state = isci_request_change_state(request, completed); + old_state = isci_request_change_state(ireq, completed); tmf->status = completion_status; - request->complete_in_target = true; - - if (SAS_PROTOCOL_SSP == tmf->proto) { + ireq->complete_in_target = true; + if (tmf->proto == SAS_PROTOCOL_SSP) { memcpy(&tmf->resp.resp_iu, - scic_io_request_get_response_iu_address( - request->sci_request_handle - ), - sizeof(struct sci_ssp_response_iu)); - - } else if (SAS_PROTOCOL_SATA == tmf->proto) { - + sci_req->response_buffer, + SSP_RESP_IU_MAX_SIZE); + } else if (tmf->proto == SAS_PROTOCOL_SATA) { memcpy(&tmf->resp.d2h_fis, - scic_stp_io_request_get_d2h_reg_address( - request->sci_request_handle), + &stp_req->d2h_reg_fis, sizeof(struct dev_to_host_fis)); } /* Manage the timer if it is still running. */ if (tmf->timeout_timer) { - isci_del_timer(isci_host, tmf->timeout_timer); + isci_del_timer(ihost, tmf->timeout_timer); tmf->timeout_timer = NULL; } /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; - scic_controller_complete_io( - isci_host->core_controller, - &isci_device->sci, - request->sci_request_handle); - /* NULL the request handle to make sure it cannot be terminated + scic_controller_complete_io(ihost->core_controller, + &idev->sci, + ireq->sci_request_handle); + + /* + * NULL the request handle to make sure it cannot be terminated * or completed again. */ - request->sci_request_handle = NULL; + ireq->sci_request_handle = NULL; - isci_request_change_state(request, unallocated); - list_del_init(&request->dev_node); + isci_request_change_state(ireq, unallocated); + list_del_init(&ireq->dev_node); /* The task management part completes last. */ complete(tmf_complete); } -/** - * isci_task_ssp_request_get_response_data_address() - This function is called - * by the sci core to retrieve the response data address for a given task - * request. - * @request: This parameter is the isci_request object. - * - * response data address for specified task request. - */ -void *isci_task_ssp_request_get_response_data_address( - struct isci_request *request) -{ - struct isci_tmf *isci_tmf = isci_request_access_tmf(request); - - return &isci_tmf->resp.resp_iu; -} - -/** - * isci_task_ssp_request_get_response_data_length() - This function is called - * by the sci core to retrieve the response data length for a given task - * request. - * @request: This parameter is the isci_request object. - * - * response data length for specified task request. - */ -u32 isci_task_ssp_request_get_response_data_length( - struct isci_request *request) -{ - struct isci_tmf *isci_tmf = isci_request_access_tmf(request); - - return sizeof(isci_tmf->resp.resp_iu); -} - /** * isci_bus_reset_handler() - This function performs a target reset of the * device referenced by "cmd'. This function is exported through the diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index c5afd1cfbde7..77cc54dbe81f 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -99,7 +99,7 @@ struct isci_tmf { struct completion *complete; enum sas_protocol proto; union { - struct sci_ssp_response_iu resp_iu; + struct ssp_response_iu resp_iu; struct dev_to_host_fis d2h_fis; } resp; unsigned char lun[8]; @@ -120,8 +120,7 @@ struct isci_tmf { }; -static inline void isci_print_tmf( - struct isci_tmf *tmf) +static inline void isci_print_tmf(struct isci_tmf *tmf) { if (SAS_PROTOCOL_SATA == tmf->proto) dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev, @@ -144,16 +143,13 @@ static inline void isci_print_tmf( "tmf->resp.resp_iu.data[3] = %x\n", __func__, tmf->status, - tmf->resp.resp_iu.data_present, + tmf->resp.resp_iu.datapres, tmf->resp.resp_iu.status, - (tmf->resp.resp_iu.response_data_length[0] << 24) + - (tmf->resp.resp_iu.response_data_length[1] << 16) + - (tmf->resp.resp_iu.response_data_length[2] << 8) + - tmf->resp.resp_iu.response_data_length[3], - tmf->resp.resp_iu.data[0], - tmf->resp.resp_iu.data[1], - tmf->resp.resp_iu.data[2], - tmf->resp.resp_iu.data[3]); + be32_to_cpu(tmf->resp.resp_iu.response_data_len), + tmf->resp.resp_iu.resp_data[0], + tmf->resp.resp_iu.resp_data[1], + tmf->resp.resp_iu.resp_data[2], + tmf->resp.resp_iu.resp_data[3]); } -- cgit v1.2.3 From 2ec53eb4d5b301e5c9c386da5685894d572772a5 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 18:01:22 -0700 Subject: isci: Fixup of smp request The struct smp_request data structure has be fixed up for Linux consumption. This probably should go to scsi/sas.h eventually. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 156 +------------------------- drivers/scsi/isci/core/scic_sds_request.c | 41 ++++--- drivers/scsi/isci/core/scic_sds_smp_request.c | 104 ++++++++--------- drivers/scsi/isci/request.c | 48 ++++---- drivers/scsi/isci/sas.h | 107 ++++++++++++++++++ 5 files changed, 196 insertions(+), 260 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index 3d4ca12df5ff..d10c3824dbe4 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -198,20 +198,6 @@ struct sci_ssp_frame_header { }; -/** - * struct smp_request_header - This structure defines the contents of an SMP - * Request header. - * - * For specific information on each of these individual fields please reference - * the SAS specification. - */ -struct smp_request_header { - u8 smp_frame_type; /* byte 0 */ - u8 function; /* byte 1 */ - u8 allocated_response_length; /* byte 2 */ - u8 request_length; /* byte 3 */ -}; - /** * struct smp_response_header - This structure depicts the contents of the SAS * SMP DISCOVER RESPONSE frame. For specific information on each of these @@ -227,136 +213,6 @@ struct smp_response_header { u8 response_length; /* byte 3 */ }; -/** - * struct smp_request_general - This structure defines the contents of an SMP - * Request that is comprised of the struct smp_request_header and a CRC. - * - * For specific information on each of these individual fields please reference - * the SAS specification. - */ -struct smp_request_general { - u32 crc; /* bytes 4-7 */ - -}; - -/** - * struct smp_request_phy_identifier - This structure defines the contents of - * an SMP Request that is comprised of the struct smp_request_header and a phy - * identifier. Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA. - * - * For specific information on each of these individual fields please reference - * the SAS specification. - */ -struct smp_request_phy_identifier { - u32 reserved_byte4_7; /* bytes 4-7 */ - - u32 ignore_zone_group:1; /* byte 8 */ - u32 reserved_byte8:7; - - u32 phy_identifier:8; /* byte 9 */ - u32 reserved_byte10:8; /* byte 10 */ - u32 reserved_byte11:8; /* byte 11 */ - -}; - -/** - * struct smp_request_configure_route_information - This structure defines the - * contents of an SMP Configure Route Information request. - * - * For specific information on each of these individual fields please reference - * the SAS specification. - */ -struct smp_request_configure_route_information { - u32 expected_expander_change_count:16; /* bytes 4-5 */ - u32 expander_route_index_high:8; - u32 expander_route_index:8; /* bytes 6-7 */ - - u32 reserved_byte8:8; /* bytes 8 */ - u32 phy_identifier:8; /* bytes 9 */ - u32 reserved_byte_10_11:16; /* bytes 10-11 */ - - u32 reserved_byte_12_bit_0_6:7; - u32 disable_route_entry:1; /* byte 12 */ - u32 reserved_byte_13_15:24; /* bytes 13-15 */ - - u32 routed_sas_address[2]; /* bytes 16-23 */ - u8 reserved_byte_24_39[16]; /* bytes 24-39 */ - -}; - -/** - * struct smp_request_phy_control - This structure defines the contents of an - * SMP Phy Controler request. - * - * For specific information on each of these individual fields please reference - * the SAS specification. - */ -struct smp_request_phy_control { - u16 expected_expander_change_count; /* byte 4-5 */ - - u16 reserved_byte_6_7; /* byte 6-7 */ - u8 reserved_byte_8; /* byte 8 */ - - u8 phy_identifier; /* byte 9 */ - u8 phy_operation; /* byte 10 */ - - u8 update_partial_pathway_timeout_value:1; - u8 reserved_byte_11_bit_1_7:7; /* byte 11 */ - - u8 reserved_byte_12_23[12]; /* byte 12-23 */ - - u8 attached_device_name[8]; /* byte 24-31 */ - - u8 reserved_byte_32_bit_3_0:4; /* byte 32 */ - u8 programmed_minimum_physical_link_rate:4; - - u8 reserved_byte_33_bit_3_0:4; /* byte 33 */ - u8 programmed_maximum_physical_link_rate:4; - - u16 reserved_byte_34_35; /* byte 34-35 */ - - u8 partial_pathway_timeout_value:4; - u8 reserved_byte_36_bit_4_7:4; /* byte 36 */ - - u16 reserved_byte_37_38; /* byte 37-38 */ - u8 reserved_byte_39; /* byte 39 */ - -}; - -/** - * struct smp_request_vendor_specific - This structure depicts the vendor - * specific space for SMP request. - * - * - */ - #define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016 -struct smp_request_vendor_specific { - u8 request_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH]; -}; - -/** - * struct smp_request - This structure simply unionizes the existing request - * structures into a common request type. - * - * - */ -struct smp_request { - struct smp_request_header header; - - union { /* bytes 4-N */ - struct smp_request_general report_general; - struct smp_request_phy_identifier discover; - struct smp_request_general report_manufacturer_information; - struct smp_request_phy_identifier report_phy_sata; - struct smp_request_phy_control phy_control; - struct smp_request_phy_identifier report_phy_error_log; - struct smp_request_phy_identifier report_route_information; - struct smp_request_configure_route_information configure_route_information; - struct smp_request_vendor_specific vendor_specific_request; - } request; - -}; - /** * struct smp_response_report_general - This structure depicts the SMP Report @@ -493,6 +349,7 @@ struct smp_response_report_phy_sata { }; +#define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016 struct smp_response_vendor_specific { u8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH]; }; @@ -517,17 +374,6 @@ struct smp_response { }; -/* SMP Request Functions */ -#define SMP_FUNCTION_REPORT_GENERAL 0x00 -#define SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION 0x01 -#define SMP_FUNCTION_DISCOVER 0x10 -#define SMP_FUNCTION_REPORT_PHY_ERROR_LOG 0x11 -#define SMP_FUNCTION_REPORT_PHY_SATA 0x12 -#define SMP_FUNCTION_REPORT_ROUTE_INFORMATION 0X13 -#define SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION 0X90 -#define SMP_FUNCTION_PHY_CONTROL 0x91 -#define SMP_FUNCTION_PHY_TEST 0x92 - #define SMP_FRAME_TYPE_REQUEST 0x40 #define SMP_FRAME_TYPE_RESPONSE 0x41 diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index ef59e019398e..8eb3c7e59ec5 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -1658,38 +1658,47 @@ static void scic_sds_general_request_construct(struct scic_sds_controller *scic, } } -enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - u16 io_tag, - void *user_io_request_object, - struct scic_sds_request *sci_req, - struct scic_sds_request **new_scic_io_request_handle) +enum sci_status +scic_io_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, + void *user_req, + struct scic_sds_request *sci_req, + struct scic_sds_request **new_sci_req) { struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, io_tag, - user_io_request_object, sci_req); + scic_sds_general_request_construct(scic, + sci_dev, + io_tag, + user_req, + sci_req); - if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) + if (sci_dev->rnc.remote_node_index == + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; - if (dev->dev_type == SAS_END_DEV) { + if (dev->dev_type == SAS_END_DEV) scic_sds_ssp_io_request_assign_buffers(sci_req); - } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { + else if ((dev->dev_type == SATA_DEV) || + (dev->tproto & SAS_PROTOCOL_STP)) { scic_sds_stp_request_assign_buffers(sci_req); - memset(sci_req->command_buffer, 0, sizeof(struct host_to_dev_fis)); + memset(sci_req->command_buffer, + 0, + sizeof(struct host_to_dev_fis)); } else if (dev_is_expander(dev)) { scic_sds_smp_request_assign_buffers(sci_req); - memset(sci_req->command_buffer, 0, sizeof(struct smp_request)); + memset(sci_req->command_buffer, 0, sizeof(struct smp_req)); } else status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; if (status == SCI_SUCCESS) { - memset(sci_req->task_context_buffer, 0, - SCI_FIELD_OFFSET(struct scu_task_context, sgl_pair_ab)); - *new_scic_io_request_handle = sci_req; + memset(sci_req->task_context_buffer, + 0, + SCI_FIELD_OFFSET(struct scu_task_context, sgl_pair_ab)); + *new_sci_req = sci_req; } return status; diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 2815da288750..7d7bd2e29d8f 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "sas.h" #include "intel_sas.h" #include "sci_base_state_machine.h" #include "scic_controller.h" @@ -67,7 +68,7 @@ static void scu_smp_request_construct_task_context( struct scic_sds_request *sci_req, - struct smp_request *smp_request); + struct smp_req *smp_req); /** * @@ -77,7 +78,7 @@ static void scu_smp_request_construct_task_context( u32 scic_sds_smp_request_get_object_size(void) { return sizeof(struct scic_sds_request) - + sizeof(struct smp_request) + + sizeof(struct smp_req) + sizeof(struct smp_response) + sizeof(struct scu_task_context) + SMP_CACHE_BYTES; @@ -100,7 +101,7 @@ u32 scic_sds_smp_request_get_object_size(void) */ #define scic_sds_smp_request_get_response_buffer(memory) \ (((char *)(scic_sds_smp_request_get_command_buffer(memory))) \ - + sizeof(struct smp_request)) + + sizeof(struct smp_req)) /** * scic_sds_smp_request_get_task_context_buffer() - @@ -142,21 +143,8 @@ void scic_sds_smp_request_assign_buffers( } -/** - * This method is called by the SCI user to build an SMP pass-through IO - * request. - * @scic_smp_request: This parameter specifies the handle to the io request - * object to be built. - * @passthru_cb: This parameter specifies the pointer to the callback structure - * that contains the function pointers - * - * - The user must have previously called scic_io_request_construct() on the - * supplied IO request. Indicate if the controller successfully built the IO - * request. - */ - -/** - * This method will fill in the SCU Task Context for a SMP request. The +/* + * This function will fill in the SCU Task Context for a SMP request. The * following important settings are utilized: -# task_type == * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type * (i.e. non-raw frame) is being utilized to perform task management. -# @@ -166,26 +154,26 @@ void scic_sds_smp_request_assign_buffers( * constructed. * */ -static void scu_smp_request_construct_task_context( - struct scic_sds_request *sds_request, - struct smp_request *smp_request) +static void +scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, + struct smp_req *smp_req) { dma_addr_t dma_addr; - struct scic_sds_controller *controller; + struct scic_sds_controller *scic; struct scic_sds_remote_device *sci_dev; - struct scic_sds_port *target_port; + struct scic_sds_port *sci_port; struct scu_task_context *task_context; /* byte swap the smp request. */ - scic_word_copy_with_swap(sds_request->command_buffer, - (u32 *)smp_request, - sizeof(struct smp_request) / sizeof(u32)); + scic_word_copy_with_swap(sci_req->command_buffer, + (u32 *)smp_req, + sizeof(struct smp_req) / sizeof(u32)); - task_context = scic_sds_request_get_task_context(sds_request); + task_context = scic_sds_request_get_task_context(sci_req); - controller = scic_sds_request_get_controller(sds_request); - sci_dev = scic_sds_request_get_device(sds_request); - target_port = scic_sds_request_get_port(sds_request); + scic = scic_sds_request_get_controller(sci_req); + sci_dev = scic_sds_request_get_device(sci_req); + sci_port = scic_sds_request_get_port(sci_req); /* * Fill in the TC with the its required data @@ -195,9 +183,8 @@ static void scu_smp_request_construct_task_context( task_context->initiator_request = 1; task_context->connection_rate = sci_dev->connection_rate; task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(controller); - task_context->logical_port_index = - scic_sds_port_get_index(target_port); + scic_sds_controller_get_protocol_engine_group(scic); + task_context->logical_port_index = scic_sds_port_get_index(sci_port); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; task_context->abort = 0; task_context->valid = SCU_TASK_CONTEXT_VALID; @@ -220,8 +207,7 @@ static void scu_smp_request_construct_task_context( task_context->address_modifier = 0; /* 10h */ - task_context->ssp_command_iu_length = - smp_request->header.request_length; + task_context->ssp_command_iu_length = smp_req->req_len; /* 14h */ task_context->transfer_length_bytes = 0; @@ -231,7 +217,7 @@ static void scu_smp_request_construct_task_context( * since commandIU has been build by framework at this point, we just * copy the frist DWord from command IU to this location. */ memcpy((void *)(&task_context->type.smp), - sds_request->command_buffer, + sci_req->command_buffer, sizeof(u32)); /* @@ -241,19 +227,18 @@ static void scu_smp_request_construct_task_context( */ task_context->task_phase = 0; - if (sds_request->was_tag_assigned_by_user) { + if (sci_req->was_tag_assigned_by_user) { /* * Build the task context now since we have already read * the data */ - sds_request->post_context = + sci_req->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << + (scic_sds_controller_get_protocol_engine_group(scic) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << + (scic_sds_port_get_index(sci_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sds_request->io_tag)); + scic_sds_io_tag_get_index(sci_req->io_tag)); } else { /* * Build the task context now since we have already read @@ -261,12 +246,11 @@ static void scu_smp_request_construct_task_context( * I/O tag index is not assigned because we have to wait * until we get a TCi. */ - sds_request->post_context = + sci_req->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << + (scic_sds_controller_get_protocol_engine_group(scic) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << + (scic_sds_port_get_index(sci_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); } @@ -274,9 +258,9 @@ static void scu_smp_request_construct_task_context( * Copy the physical address for the command buffer to the SCU Task * Context command buffer should not contain command header. */ - dma_addr = scic_io_request_get_dma_addr(sds_request, + dma_addr = scic_io_request_get_dma_addr(sci_req, (char *) - (sds_request->command_buffer) + + (sci_req->command_buffer) + sizeof(u32)); task_context->command_iu_upper = upper_32_bits(dma_addr); @@ -577,7 +561,7 @@ static const struct sci_base_state scic_sds_smp_request_started_substate_table[] */ enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) { - struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); + struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); if (!smp_req) return SCI_FAILURE_INSUFFICIENT_RESOURCES; @@ -600,18 +584,18 @@ enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) * Look at the SMP requests' header fields; for certain SAS 1.x SMP * functions under SAS 2.0, a zero request length really indicates * a non-zero default length. */ - if (smp_req->header.request_length == 0) { - switch (smp_req->header.function) { - case SMP_FUNCTION_DISCOVER: - case SMP_FUNCTION_REPORT_PHY_ERROR_LOG: - case SMP_FUNCTION_REPORT_PHY_SATA: - case SMP_FUNCTION_REPORT_ROUTE_INFORMATION: - smp_req->header.request_length = 2; + if (smp_req->req_len == 0) { + switch (smp_req->func) { + case SMP_DISCOVER: + case SMP_REPORT_PHY_ERR_LOG: + case SMP_REPORT_PHY_SATA: + case SMP_REPORT_ROUTE_INFO: + smp_req->req_len = 2; break; - case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION: - case SMP_FUNCTION_PHY_CONTROL: - case SMP_FUNCTION_PHY_TEST: - smp_req->header.request_length = 9; + case SMP_CONF_ROUTE_INFO: + case SMP_PHY_CONTROL: + case SMP_PHY_TEST_FUNCTION: + smp_req->req_len = 9; break; /* Default - zero is a valid default for 2.0. */ } diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 501df3ca4280..36adc1589efa 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -61,7 +61,8 @@ #include "request.h" #include "sata.h" #include "scu_completion_codes.h" -#include "core/scic_sds_request.h" +#include "scic_sds_request.h" +#include "sas.h" static enum sci_status isci_request_ssp_request_construct( struct isci_request *request) @@ -113,47 +114,37 @@ static enum sci_status isci_request_stp_request_construct( return status; } -/** - * isci_smp_request_build() - This function builds the smp request object. - * @isci_host: This parameter specifies the ISCI host object - * @request: This parameter points to the isci_request object allocated in the +/* + * isci_smp_request_build() - This function builds the smp request. + * @ireq: This parameter points to the isci_request allocated in the * request construct function. - * @sci_device: This parameter is the handle for the sci core's remote device - * object that is the destination for this request. * * SCI_SUCCESS on successfull completion, or specific failure code. */ -static enum sci_status isci_smp_request_build( - struct isci_request *request) +static enum sci_status isci_smp_request_build(struct isci_request *ireq) { enum sci_status status = SCI_FAILURE; - struct sas_task *task = isci_request_access_task(request); + struct sas_task *task = isci_request_access_task(ireq); + struct scic_sds_request *sci_req = ireq->sci_request_handle; + void *cmd_iu = sci_req->command_buffer; - void *command_iu_address = - scic_io_request_get_command_iu_address( - request->sci_request_handle - ); + dev_dbg(&ireq->isci_host->pdev->dev, + "%s: request = %p\n", __func__, ireq); - dev_dbg(&request->isci_host->pdev->dev, - "%s: request = %p\n", - __func__, - request); - dev_dbg(&request->isci_host->pdev->dev, + dev_dbg(&ireq->isci_host->pdev->dev, "%s: smp_req len = %d\n", __func__, task->smp_task.smp_req.length); /* copy the smp_command to the address; */ sg_copy_to_buffer(&task->smp_task.smp_req, 1, - (char *)command_iu_address, - sizeof(struct smp_request) - ); + (char *)cmd_iu, + sizeof(struct smp_req)); - status = scic_io_request_construct_smp(request->sci_request_handle); + status = scic_io_request_construct_smp(sci_req); if (status != SCI_SUCCESS) - dev_warn(&request->isci_host->pdev->dev, - "%s: scic_io_request_construct_smp failed with " - "status = %d\n", + dev_warn(&ireq->isci_host->pdev->dev, + "%s: failed with status = %d\n", __func__, status); @@ -1073,9 +1064,8 @@ void isci_request_io_request_complete( sg_copy_from_buffer( &task->smp_task.smp_resp, 1, command_iu_address - + sizeof(struct smp_request), - sizeof(struct smp_resp) - ); + + sizeof(struct smp_req), + sizeof(struct smp_resp)); } else if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) { diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index 1a1e9bc125c3..f5d7e6a51070 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h @@ -55,6 +55,9 @@ #ifndef _SCI_SAS_H_ #define _SCI_SAS_H_ + +#include + /* * SATA FIS Types These constants depict the various SATA FIS types devined in * the serial ATA specification. @@ -106,4 +109,108 @@ struct ssp_task_iu { u8 _r_c[12]; } __packed; + +/* + * struct smp_req_phy_id - This structure defines the contents of + * an SMP Request that is comprised of the struct smp_request_header and a + * phy identifier. + * Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA. + * + * For specific information on each of these individual fields please reference + * the SAS specification. + */ +struct smp_req_phy_id { + u8 _r_a[4]; /* bytes 4-7 */ + + u8 ign_zone_grp:1; /* byte 8 */ + u8 _r_b:7; + + u8 phy_id; /* byte 9 */ + u8 _r_c; /* byte 10 */ + u8 _r_d; /* byte 11 */ +} __packed; + +/* + * struct smp_req_config_route_info - This structure defines the + * contents of an SMP Configure Route Information request. + * + * For specific information on each of these individual fields please reference + * the SAS specification. + */ +struct smp_req_conf_rtinfo { + u16 exp_change_cnt; /* bytes 4-5 */ + u8 exp_rt_idx_hi; /* byte 6 */ + u8 exp_rt_idx; /* byte 7 */ + + u8 _r_a; /* byte 8 */ + u8 phy_id; /* byte 9 */ + u16 _r_b; /* bytes 10-11 */ + + u8 _r_c:7; /* byte 12 */ + u8 dis_rt_entry:1; + u8 _r_d[3]; /* bytes 13-15 */ + + u8 rt_sas_addr[8]; /* bytes 16-23 */ + u8 _r_e[16]; /* bytes 24-39 */ +} __packed; + +/* + * struct smp_req_phycntl - This structure defines the contents of an + * SMP Phy Controller request. + * + * For specific information on each of these individual fields please reference + * the SAS specification. + */ +struct smp_req_phycntl { + u16 exp_change_cnt; /* byte 4-5 */ + + u8 _r_a[3]; /* bytes 6-8 */ + + u8 phy_id; /* byte 9 */ + u8 phy_op; /* byte 10 */ + + u8 upd_pathway:1; /* byte 11 */ + u8 _r_b:7; + + u8 _r_c[12]; /* byte 12-23 */ + + u8 att_dev_name[8]; /* byte 24-31 */ + + u8 _r_d:4; /* byte 32 */ + u8 min_linkrate:4; + + u8 _r_e:4; /* byte 33 */ + u8 max_linkrate:4; + + u8 _r_f[2]; /* byte 34-35 */ + + u8 pathway:4; /* byte 36 */ + u8 _r_g:4; + + u8 _r_h[3]; /* bytes 37-39 */ +} __packed; + +#define SMP_REQ_VENDOR_SPECIFIC_MAX_LEN 1016 + +/* + * struct smp_req - This structure simply unionizes the existing request + * structures into a common request type. + * + * XXX: This data structure may need to go to scsi/sas.h + */ +struct smp_req { + u8 type; /* byte 0 */ + u8 func; /* byte 1 */ + u8 alloc_resp_len; /* byte 2 */ + u8 req_len; /* byte 3 */ + + union { /* bytes 4-N */ + u32 smp_req_gen; + struct smp_req_phy_id phy_id; + struct smp_req_phycntl phy_cntl; + struct smp_req_conf_rtinfo conf_rt_info; + u8 vendor[SMP_REQ_VENDOR_SPECIFIC_MAX_LEN]; + }; +} __packed; + #endif -- cgit v1.2.3 From d20930a2b3271b233f4bef3c59ce602dfc9e5d83 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 18:07:09 -0700 Subject: isci: Converting smp_response to Linux native smp_resp Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 178 -------------------------- drivers/scsi/isci/core/scic_sds_smp_request.c | 77 +++++------ drivers/scsi/isci/sas.h | 2 + 3 files changed, 34 insertions(+), 223 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index d10c3824dbe4..58bf1fb9b2f5 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -198,184 +198,6 @@ struct sci_ssp_frame_header { }; -/** - * struct smp_response_header - This structure depicts the contents of the SAS - * SMP DISCOVER RESPONSE frame. For specific information on each of these - * individual fields please reference the SAS specification Link layer - * section on address frames. - * - * - */ -struct smp_response_header { - u8 smp_frame_type; /* byte 0 */ - u8 function; /* byte 1 */ - u8 function_result; /* byte 2 */ - u8 response_length; /* byte 3 */ -}; - - -/** - * struct smp_response_report_general - This structure depicts the SMP Report - * General for expander devices. It adheres to the SAS-2.1 specification. - * - * For specific information on each of these individual fields please reference - * the SAS specification Application layer section on SMP. - */ -struct smp_response_report_general { - u16 expander_change_count; /* byte 4-5 */ - u16 expander_route_indexes; /* byte 6-7 */ - - u32 reserved_byte8:7; /* byte 8 bit 0-6 */ - u32 long_response:1; /* byte 8 bit 7 */ - - u32 number_of_phys:8; /* byte 9 */ - - u32 configurable_route_table:1; /* byte 10 */ - u32 configuring:1; - u32 configures_others:1; - u32 open_reject_retry_supported:1; - u32 stp_continue_awt:1; - u32 self_configuring:1; - u32 zone_configuring:1; - u32 table_to_table_supported:1; - - u32 reserved_byte11:8; /* byte 11 */ - - u32 enclosure_logical_identifier_high; /* byte 12-15 */ - u32 enclosure_logical_identifier_low; /* byte 16-19 */ - - u32 reserved_byte20_23; - u32 reserved_byte24_27; - -}; - -struct smp_response_report_general_long { - struct smp_response_report_general sas1_1; - - struct { - u16 reserved1; - u16 stp_bus_inactivity_time_limit; - u16 stp_max_connect_time_limit; - u16 stp_smp_i_t_nexus_loss_time; - - u32 zoning_enabled:1; - u32 zoning_supported:1; - u32 physicaL_presence_asserted:1; - u32 zone_locked:1; - u32 reserved2:1; - u32 num_zone_groups:3; - u32 saving_zoning_enabled_supported:3; - u32 saving_zone_perms_table_supported:1; - u32 saving_zone_phy_info_supported:1; - u32 saving_zone_manager_password_supported:1; - u32 saving:1; - u32 reserved3:1; - u32 max_number_routed_sas_addresses:16; - - struct sci_sas_address active_zone_manager_sas_address; - - u16 zone_lock_inactivity_time_limit; - u16 reserved4; - - u8 reserved5; - u8 first_enclosure_connector_element_index; - u8 number_of_enclosure_connector_element_indices; - u8 reserved6; - - u32 reserved7:7; - u32 reduced_functionality:1; - u32 time_to_reduce_functionality:8; - u32 initial_time_to_reduce_functionality:8; - u8 max_reduced_functionality_time; - - u16 last_self_config_status_descriptor_index; - u16 max_number_of_stored_self_config_status_descriptors; - - u16 last_phy_event_list_descriptor_index; - u16 max_number_of_stored_phy_event_list_descriptors; - } sas2; - -}; - -/** - * struct smp_response_report_manufacturer_information - This structure depicts - * the SMP report manufacturer information for expander devices. It adheres - * to the SAS-2.1 specification. - * - * For specific information on each of these individual fields please reference - * the SAS specification Application layer section on SMP. - */ -struct smp_response_report_manufacturer_information { - u32 expander_change_count:16; /* bytes 4-5 */ - u32 reserved1:16; - - u32 sas1_1_format:1; - u32 reserved2:31; - - u8 vendor_id[8]; - u8 product_id[16]; - u8 product_revision_level[4]; - u8 component_vendor_id[8]; - u8 component_id[2]; - u8 component_revision_level; - u8 reserved3; - u8 vendor_specific[8]; - -}; - -/** - * struct smp_response_report_phy_sata - This structure depicts the contents of - * the SAS SMP REPORT PHY SATA frame. For specific information on each of - * these individual fields please reference the SAS specification Link layer - * section on address frames. - * - * - */ -struct smp_response_report_phy_sata { - u32 ignored_byte_4_7; /* bytes 4-7 */ - - u32 affiliations_valid:1; - u32 affiliations_supported:1; - u32 reserved_byte11:6; /* byte 11 */ - u32 ignored_byte10:8; /* byte 10 */ - u32 phy_identifier:8; /* byte 9 */ - u32 reserved_byte_8:8; /* byte 8 */ - - u32 reserved_12_15; - u32 stp_sas_address[2]; - u8 device_to_host_fis[20]; - u32 reserved_44_47; - u32 affiliated_stp_initiator_sas_address[2]; - -}; - -#define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016 -struct smp_response_vendor_specific { - u8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH]; -}; - -union smp_response_body { - struct smp_response_report_general report_general; - struct smp_response_report_manufacturer_information report_manufacturer_information; - struct smp_response_report_phy_sata report_phy_sata; - struct smp_response_vendor_specific vendor_specific_response; -}; - -/** - * struct smp_response - This structure simply unionizes the existing response - * structures into a common response type. - * - * - */ -struct smp_response { - struct smp_response_header header; - - union smp_response_body response; - -}; - -#define SMP_FRAME_TYPE_REQUEST 0x40 -#define SMP_FRAME_TYPE_RESPONSE 0x41 #define PHY_OPERATION_NOP 0x00 #define PHY_OPERATION_LINK_RESET 0x01 diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 7d7bd2e29d8f..e6cfcbba9f9d 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "sas.h" #include "intel_sas.h" #include "sci_base_state_machine.h" @@ -79,7 +80,7 @@ u32 scic_sds_smp_request_get_object_size(void) { return sizeof(struct scic_sds_request) + sizeof(struct smp_req) - + sizeof(struct smp_response) + + sizeof(struct smp_resp) + sizeof(struct scu_task_context) + SMP_CACHE_BYTES; } @@ -111,7 +112,7 @@ u32 scic_sds_smp_request_get_object_size(void) #define scic_sds_smp_request_get_task_context_buffer(memory) \ ((struct scu_task_context *)(\ ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \ - + sizeof(struct smp_response) \ + + sizeof(struct smp_resp) \ )) @@ -271,8 +272,8 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, task_context->response_iu_lower = 0; } -/** - * This method processes an unsolicited frame while the SMP request is waiting +/* + * This function processes an unsolicited frame while the SMP request is waiting * for a response frame. It will copy the response data, release the * unsolicited frame, and transition the request to the * SCI_BASE_REQUEST_STATE_COMPLETED state. @@ -281,63 +282,52 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, * @frame_index: This parameter indicates the unsolicited frame index that * should contain the response. * - * This method returns an indication of whether the response frame was handled + * This function returns an indication of whether the response frame was handled * successfully or not. SCI_SUCCESS Currently this value is always returned and * indicates successful processing of the TC response. */ -static enum sci_status scic_sds_smp_request_await_response_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) +static enum sci_status +scic_sds_smp_request_await_response_frame_handler( + struct scic_sds_request *sci_req, + u32 frame_index) { enum sci_status status; void *frame_header; - struct smp_response_header *rsp_hdr; - u8 *user_smp_buffer = sci_req->response_buffer; + struct smp_resp *rsp_hdr; + u8 *usr_smp_buf = sci_req->response_buffer; status = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, - &frame_header - ); + &frame_header); /* byte swap the header. */ - scic_word_copy_with_swap( - (u32 *)user_smp_buffer, - frame_header, - sizeof(struct smp_response_header) / sizeof(u32) - ); - rsp_hdr = (struct smp_response_header *)user_smp_buffer; + scic_word_copy_with_swap((u32 *)usr_smp_buf, + frame_header, + SMP_RESP_HDR_SZ / sizeof(u32)); - if (rsp_hdr->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) { - void *smp_response_buffer; + rsp_hdr = (struct smp_resp *)usr_smp_buf; + + if (rsp_hdr->frame_type == SMP_RESPONSE) { + void *smp_resp; status = scic_sds_unsolicited_frame_control_get_buffer( &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, - &smp_response_buffer - ); + &smp_resp); scic_word_copy_with_swap( - (u32 *)(user_smp_buffer + sizeof(struct smp_response_header)), - smp_response_buffer, - sizeof(union smp_response_body) / sizeof(u32) - ); - /* - * Don't need to copy to user space. User instead will refer to - * core request's response buffer. */ - - /* - * copy the smp response to framework smp request's response buffer. - * scic_sds_smp_request_copy_response(sci_req); */ + (u32 *)(usr_smp_buf + SMP_RESP_HDR_SZ), + smp_resp, + (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / + sizeof(u32)); scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_base_state_machine_change_state( &sci_req->started_substate_machine, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION - ); + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); } else { /* This was not a response frame why did it get forwarded? */ dev_err(scic_to_dev(sci_req->owning_controller), @@ -346,23 +336,20 @@ static enum sci_status scic_sds_smp_request_await_response_frame_handler( __func__, sci_req, frame_index, - rsp_hdr->smp_frame_type); + rsp_hdr->frame_type); scic_sds_request_set_status( sci_req, SCU_TASK_DONE_SMP_FRM_TYPE_ERR, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); sci_base_state_machine_change_state( &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + SCI_BASE_REQUEST_STATE_COMPLETED); } - scic_sds_controller_release_frame( - sci_req->owning_controller, frame_index - ); + scic_sds_controller_release_frame(sci_req->owning_controller, + frame_index); return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index f5d7e6a51070..83eab4671958 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h @@ -213,4 +213,6 @@ struct smp_req { }; } __packed; +#define SMP_RESP_HDR_SZ 4 + #endif -- cgit v1.2.3 From f700ad4331d55df729a36b2602c4abe2d855036f Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 18:08:35 -0700 Subject: isci: remove redundant copies of IAF We need to remove the extra copies of identify address frame that's being kept around. We only need the one copy that libsas is using. Signed-off-by: Dave Jiang [further cleanups] Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_phy.h | 43 ---------------------- drivers/scsi/isci/core/scic_sds_phy.c | 69 ++++++----------------------------- drivers/scsi/isci/core/scic_sds_phy.h | 5 --- drivers/scsi/isci/phy.h | 3 -- drivers/scsi/isci/port.c | 27 -------------- 5 files changed, 11 insertions(+), 136 deletions(-) diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 8fcd3a4c5744..3f43e8d69c4f 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -287,47 +287,4 @@ enum scic_phy_counter_id { SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR }; - -/** - * scic_sas_phy_get_properties() - This method will enable the user to retrieve - * information specific to a SAS phy, such as: the received identify address - * frame, received phy capabilities, etc. - * @phy: this parameter specifies the phy for which to retrieve properties. - * @properties: This parameter specifies the properties structure into which to - * copy the requested information. - * - * This method returns an indication as to whether the SAS phy properties were - * successfully retrieved. SCI_SUCCESS This value is returned if the SAS - * properties are successfully retrieved. SCI_FAILURE This value is returned if - * the SAS properties are not successfully retrieved (e.g. It's not a SAS Phy). - */ -enum sci_status scic_sas_phy_get_properties( - struct scic_sds_phy *phy, - struct scic_sas_phy_properties *properties); - -/** - * scic_sata_phy_get_properties() - This method will enable the user to - * retrieve information specific to a SATA phy, such as: the received - * signature FIS, if a port selector is present, etc. - * @phy: this parameter specifies the phy for which to retrieve properties. - * @properties: This parameter specifies the properties structure into which to - * copy the requested information. - * - * This method returns an indication as to whether the SATA phy properties were - * successfully retrieved. SCI_SUCCESS This value is returned if the SATA - * properties are successfully retrieved. SCI_FAILURE This value is returned if - * the SATA properties are not successfully retrieved (e.g. It's not a SATA - * Phy). - */ -enum sci_status scic_sata_phy_get_properties( - struct scic_sds_phy *phy, - struct scic_sata_phy_properties *properties); - - - - - - - #endif /* _SCIC_PHY_H_ */ - diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index bd2b30587703..4afdb422ab98 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -436,8 +436,9 @@ void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy, struct sci_sas_address *sas_address) { struct sas_identify_frame *iaf; + struct isci_phy *iphy = sci_phy->iphy; - iaf = &sci_phy->phy_type.sas_id_frame; + iaf = &iphy->frame_rcvd.iaf; memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); } @@ -458,13 +459,13 @@ void scic_sds_phy_get_attached_phy_protocols( protocols->u.all = 0; if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + struct isci_phy *iphy = sci_phy->iphy; struct sas_identify_frame *iaf; - iaf = &sci_phy->phy_type.sas_id_frame; + iaf = &iphy->frame_rcvd.iaf; memcpy(&protocols->u.all, &iaf->initiator_bits, 2); - } else if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { + } else if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) protocols->u.bits.stp_target = 1; - } } /* @@ -549,49 +550,6 @@ enum sci_status scic_sds_phy_consume_power_handler( return sci_phy->state_handlers->consume_power_handler(sci_phy); } -/* - * ***************************************************************************** - * * SCIC PHY Public Methods - * ***************************************************************************** */ - - -enum sci_status scic_sas_phy_get_properties( - struct scic_sds_phy *sci_phy, - struct scic_sas_phy_properties *properties) -{ - if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { - memcpy(&properties->rcvd_iaf, - &sci_phy->phy_type.sas_id_frame, - sizeof(struct sas_identify_frame)); - - properties->rcvd_cap.all = - readl(&sci_phy->link_layer_registers->receive_phycap); - - return SCI_SUCCESS; - } - - return SCI_FAILURE; -} - - -enum sci_status scic_sata_phy_get_properties( - struct scic_sds_phy *sci_phy, - struct scic_sata_phy_properties *properties) -{ - if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { - memcpy(&properties->signature_fis, - &sci_phy->phy_type.sata_sig_fis, - sizeof(struct dev_to_host_fis)); - - /* / @todo add support for port selectors. */ - properties->is_port_selector_present = false; - - return SCI_SUCCESS; - } - - return SCI_FAILURE; -} - /* * ***************************************************************************** * * SCIC SDS PHY HELPER FUNCTIONS @@ -1163,6 +1121,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler enum sci_status result; u32 *frame_words; struct sas_identify_frame *identify_frame; + struct isci_phy *iphy = sci_phy->iphy; result = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_phy_get_controller(sci_phy)->uf_control), @@ -1188,9 +1147,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]); frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]); - memcpy(&sci_phy->phy_type.sas_id_frame, - identify_frame, - sizeof(struct sas_identify_frame)); + memcpy(&iphy->frame_rcvd.iaf, identify_frame, sizeof(*identify_frame)); if (identify_frame->smp_tport) { /* We got the IAF for an expander PHY go to the final state since @@ -1239,6 +1196,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle enum sci_status result; struct dev_to_host_fis *frame_header; u32 *fis_frame_data; + struct isci_phy *iphy = sci_phy->iphy; result = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_phy_get_controller(sci_phy)->uf_control), @@ -1255,10 +1213,9 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle frame_index, (void **)&fis_frame_data); - scic_sds_controller_copy_sata_response( - &sci_phy->phy_type.sata_sig_fis, - frame_header, - fis_frame_data); + scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, + frame_header, + fis_frame_data); /* got IAF we can now go to the await spinup semaphore state */ sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, @@ -2330,7 +2287,6 @@ static const struct sci_base_state scic_sds_phy_state_table[] = { void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, struct scic_sds_port *owning_port, u8 phy_index) { - sci_base_state_machine_construct(&sci_phy->state_machine, sci_phy, scic_sds_phy_state_table, @@ -2347,9 +2303,6 @@ void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; sci_phy->sata_timeout_timer = NULL; - /* Clear out the identification buffer data */ - memset(&sci_phy->phy_type, 0, sizeof(sci_phy->phy_type)); - /* Initialize the the substate machines */ sci_base_state_machine_construct(&sci_phy->starting_substate_machine, sci_phy, diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 47b2194574a0..e91f28316c00 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -272,11 +272,6 @@ struct scic_sds_phy { */ bool is_in_link_training; - union { - struct sas_identify_frame sas_id_frame; - struct dev_to_host_fis sata_sig_fis; - } phy_type; - /** * This field contains a reference to the timer utilized in detecting * when a signature FIS timeout has occurred. The signature FIS is the diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 3100fd87c788..d4c4975546e3 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -71,11 +71,8 @@ */ struct isci_phy { - struct scic_sds_phy *sci_phy_handle; - struct asd_sas_phy sas_phy; - struct sas_identify_frame *frame; struct isci_port *isci_port; u8 sas_addr[SAS_ADDR_SIZE]; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 0a1577327d61..96a2002dadea 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -171,7 +171,6 @@ void isci_port_link_up( struct scic_port_properties properties; struct isci_phy *isci_phy = phy->iphy; struct isci_port *isci_port = port->iport; - enum sci_status call_status; unsigned long success = true; BUG_ON(isci_phy->isci_port != NULL); @@ -191,21 +190,7 @@ void isci_port_link_up( if (properties.remote.protocols.u.bits.stp_target) { u64 attached_sas_address; - struct scic_sata_phy_properties sata_phy_properties; - isci_phy->sas_phy.oob_mode = SATA_OOB_MODE; - - /* Get a copy of the signature fis for libsas */ - call_status = scic_sata_phy_get_properties(phy, - &sata_phy_properties); - - /* - * XXX I am concerned about this "assert". shouldn't we - * handle the return appropriately? - */ - BUG_ON(call_status != SCI_SUCCESS); - - isci_phy->frame_rcvd.fis = sata_phy_properties.signature_fis; isci_phy->sas_phy.frame_rcvd_size = sizeof(struct dev_to_host_fis); /* @@ -225,24 +210,12 @@ void isci_port_link_up( } else if (properties.remote.protocols.u.bits.ssp_target || properties.remote.protocols.u.bits.smp_target) { - - struct scic_sas_phy_properties sas_phy_properties; - isci_phy->sas_phy.oob_mode = SAS_OOB_MODE; - - /* Get a copy of the identify address frame for libsas */ - call_status = scic_sas_phy_get_properties(phy, - &sas_phy_properties); - - BUG_ON(call_status != SCI_SUCCESS); - - isci_phy->frame_rcvd.iaf = sas_phy_properties.rcvd_iaf; isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame); /* Copy the attached SAS address from the IAF */ memcpy(isci_phy->sas_phy.attached_sas_addr, isci_phy->frame_rcvd.iaf.sas_addr, SAS_ADDR_SIZE); - } else { dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__); success = false; -- cgit v1.2.3 From d7b90fc3436fa6d5b5251eec3128386af1a4d7b8 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 18:22:33 -0700 Subject: isci: fixup SAS iaf protocols data structure Moved the actual data structure that's read from the phy register to phy header. Removed the parsing of identify address frame protocol bits as that seemed not necessary and we can use existing information. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 27 ---------- drivers/scsi/isci/core/scic_phy.h | 26 ++++++--- drivers/scsi/isci/core/scic_port.h | 4 +- drivers/scsi/isci/core/scic_sds_phy.c | 28 ++-------- drivers/scsi/isci/core/scic_sds_phy.h | 9 ++-- drivers/scsi/isci/core/scic_sds_port.c | 97 ++++++++++------------------------ drivers/scsi/isci/port.c | 6 +-- 7 files changed, 59 insertions(+), 138 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index 58bf1fb9b2f5..f2d5ca1c72ed 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -84,33 +84,6 @@ struct sci_sas_address { }; -/** - * struct sci_sas_identify_address_frame_protocols - This structure depicts the - * contents of bytes 2 and 3 in the SAS IDENTIFY ADDRESS FRAME (IAF). - * - * For specific information on each of these individual fields please reference - * the SAS specification Link layer section on address frames. - */ -struct sci_sas_identify_address_frame_protocols { - union { - struct { - u16 restricted1:1; - u16 smp_initiator:1; - u16 stp_initiator:1; - u16 ssp_initiator:1; - u16 reserved3:4; - u16 restricted2:1; - u16 smp_target:1; - u16 stp_target:1; - u16 ssp_target:1; - u16 reserved4:4; - } bits; - - u16 all; - } u; - -}; - /** * enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS * specification defined task attribute values for a command information diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 3f43e8d69c4f..451d7977bf6d 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -103,6 +103,26 @@ struct scic_phy_cap { }; } __packed; +/* this data structure reflects the link layer transmit identification reg */ +struct scic_phy_proto { + union { + struct { + u16 _r_a:1; + u16 smp_iport:1; + u16 stp_iport:1; + u16 ssp_iport:1; + u16 _r_b:4; + u16 _r_c:1; + u16 smp_tport:1; + u16 stp_tport:1; + u16 ssp_tport:1; + u16 _r_d:4; + }; + u16 all; + }; +} __packed; + + /** * struct scic_phy_properties - This structure defines the properties common to * all phys that can be retrieved. @@ -123,17 +143,11 @@ struct scic_phy_properties { */ enum sas_linkrate negotiated_link_rate; - /** - * This field indicates the protocols supported by the phy. - */ - struct sci_sas_identify_address_frame_protocols protocols; - /** * This field specifies the index of the phy in relation to other * phys within the controller. This index is zero relative. */ u8 index; - }; /** diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h index 56d05073f9c5..4ae9b6cdf04f 100644 --- a/drivers/scsi/isci/core/scic_port.h +++ b/drivers/scsi/isci/core/scic_port.h @@ -57,6 +57,7 @@ #define _SCIC_PORT_H_ #include "sci_status.h" +#include "scic_phy.h" #include "intel_sas.h" struct scic_sds_port; @@ -72,8 +73,7 @@ enum scic_port_not_ready_reason_code { struct scic_port_end_point_properties { struct sci_sas_address sas_address; - struct sci_sas_identify_address_frame_protocols protocols; - + struct scic_phy_proto protocols; }; struct scic_port_properties { diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 4afdb422ab98..b9d6fc7e8ae0 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -442,37 +442,15 @@ void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy, memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); } -void scic_sds_phy_get_protocols( - struct scic_sds_phy *sci_phy, - struct sci_sas_identify_address_frame_protocols *protocols) +void scic_sds_phy_get_protocols(struct scic_sds_phy *sci_phy, + struct scic_phy_proto *protocols) { - protocols->u.all = + protocols->all = (u16)(readl(&sci_phy-> link_layer_registers->transmit_identification) & 0x0000FFFF); } -void scic_sds_phy_get_attached_phy_protocols( - struct scic_sds_phy *sci_phy, - struct sci_sas_identify_address_frame_protocols *protocols) -{ - protocols->u.all = 0; - - if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { - struct isci_phy *iphy = sci_phy->iphy; - struct sas_identify_frame *iaf; - - iaf = &iphy->frame_rcvd.iaf; - memcpy(&protocols->u.all, &iaf->initiator_bits, 2); - } else if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) - protocols->u.bits.stp_target = 1; -} - -/* - * ***************************************************************************** - * * SCIC SDS PHY Handler Redirects - * ***************************************************************************** */ - /** * This method will attempt to start the phy object. This request is only valid * when the phy is in the stopped state diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index e91f28316c00..b0cebdc669eb 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -57,6 +57,7 @@ #define _SCIC_SDS_PHY_H_ #include "intel_sas.h" +#include "scic_phy.h" #include "scu_registers.h" #include "sci_base_state_machine.h" #include @@ -438,11 +439,7 @@ void scic_sds_phy_get_attached_sas_address( struct sci_sas_address *sas_address); void scic_sds_phy_get_protocols( - struct scic_sds_phy *this_phy, - struct sci_sas_identify_address_frame_protocols *protocols); - -void scic_sds_phy_get_attached_phy_protocols( - struct scic_sds_phy *this_phy, - struct sci_sas_identify_address_frame_protocols *protocols); + struct scic_sds_phy *sci_phy, + struct scic_phy_proto *protocols); #endif /* _SCIC_SDS_PHY_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 3697211e7ca9..05bc3bff4f6f 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "sas.h" #include "intel_sas.h" #include "scic_controller.h" #include "scic_phy.h" @@ -362,33 +363,32 @@ void scic_sds_port_get_sas_address( } } -/** - * This method will indicate which protocols are supported by this port. +/* + * This function will indicate which protocols are supported by this port. * @sci_port: a handle corresponding to the SAS port for which to return the * supported protocols. - * @protocols: This parameter specifies a pointer to an IAF protocol field - * structure into which the core will copy the protocol values for the port. - * The values are returned as part of a bit mask in order to allow for - * multi-protocol support. - * + * @protocols: This parameter specifies a pointer to a data structure + * which the core will copy the protocol values for the port from the + * transmit_identification register. */ -static void scic_sds_port_get_protocols( - struct scic_sds_port *sci_port, - struct sci_sas_identify_address_frame_protocols *protocols) +static void +scic_sds_port_get_protocols(struct scic_sds_port *sci_port, + struct scic_phy_proto *protocols) { u8 index; - protocols->u.all = 0; + protocols->all = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { if (sci_port->phy_table[index] != NULL) { - scic_sds_phy_get_protocols(sci_port->phy_table[index], protocols); + scic_sds_phy_get_protocols(sci_port->phy_table[index], + protocols); } } } -/** - * This method requests the SAS address for the device directly attached to +/* + * This function requests the SAS address for the device directly attached to * this SAS port. * @sci_port: a handle corresponding to the SAS port for which to return the * SAS address. @@ -401,21 +401,20 @@ void scic_sds_port_get_attached_sas_address( struct scic_sds_port *sci_port, struct sci_sas_address *sas_address) { - struct sci_sas_identify_address_frame_protocols protocols; - struct scic_sds_phy *phy; + struct scic_sds_phy *sci_phy; /* * Ensure that the phy is both part of the port and currently - * connected to the remote end-point. */ - phy = scic_sds_port_get_a_connected_phy(sci_port); - if (phy != NULL) { - scic_sds_phy_get_attached_phy_protocols(phy, &protocols); - - if (!protocols.u.bits.stp_target) { - scic_sds_phy_get_attached_sas_address(phy, sas_address); + * connected to the remote end-point. + */ + sci_phy = scic_sds_port_get_a_connected_phy(sci_port); + if (sci_phy) { + if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) { + scic_sds_phy_get_attached_sas_address(sci_phy, + sas_address); } else { - scic_sds_phy_get_sas_address(phy, sas_address); - sas_address->low += phy->phy_index; + scic_sds_phy_get_sas_address(sci_phy, sas_address); + sas_address->low += sci_phy->phy_index; } } else { sas_address->high = 0; @@ -423,33 +422,6 @@ void scic_sds_port_get_attached_sas_address( } } -/** - * This method will indicate which protocols are supported by this remote - * device. - * @sci_port: a handle corresponding to the SAS port for which to return the - * supported protocols. - * @protocols: This parameter specifies a pointer to an IAF protocol field - * structure into which the core will copy the protocol values for the port. - * The values are returned as part of a bit mask in order to allow for - * multi-protocol support. - * - */ -static void scic_sds_port_get_attached_protocols( - struct scic_sds_port *sci_port, - struct sci_sas_identify_address_frame_protocols *protocols) -{ - struct scic_sds_phy *phy; - - /* - * Ensure that the phy is both part of the port and currently - * connected to the remote end-point. */ - phy = scic_sds_port_get_a_connected_phy(sci_port); - if (phy != NULL) - scic_sds_phy_get_attached_phy_protocols(phy, protocols); - else - protocols->u.all = 0; -} - /** * scic_sds_port_construct_dummy_rnc() - create dummy rnc for si workaround * @@ -595,7 +567,6 @@ enum sci_status scic_port_get_properties( scic_sds_port_get_sas_address(port, &prop->local.sas_address); scic_sds_port_get_protocols(port, &prop->local.protocols); scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address); - scic_sds_port_get_attached_protocols(port, &prop->remote.protocols); return SCI_SUCCESS; } @@ -655,14 +626,10 @@ static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy, bool do_notify_user) { - struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct sci_sas_identify_address_frame_protocols protocols; + struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic->ihost; - scic_sds_phy_get_attached_phy_protocols(sci_phy, &protocols); - - /* If this is sata port then the phy has already been resumed */ - if (!protocols.u.bits.stp_target) + if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) scic_sds_phy_resume(sci_phy); sci_port->active_phy_mask |= 1 << sci_phy->phy_index; @@ -803,15 +770,9 @@ bool scic_sds_port_link_detected( struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy) { - struct sci_sas_identify_address_frame_protocols protocols; - - scic_sds_phy_get_attached_phy_protocols(sci_phy, &protocols); - - if ( - (sci_port->logical_port_index != SCIC_SDS_DUMMY_PORT) - && (protocols.u.bits.stp_target) - && scic_sds_port_is_wide(sci_port) - ) { + if ((sci_port->logical_port_index != SCIC_SDS_DUMMY_PORT) && + (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && + scic_sds_port_is_wide(sci_port)) { scic_sds_port_invalid_link_up(sci_port, sci_phy); return false; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 96a2002dadea..2decafbeb968 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -187,7 +187,7 @@ void isci_port_link_up( scic_port_get_properties(port, &properties); - if (properties.remote.protocols.u.bits.stp_target) { + if (phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { u64 attached_sas_address; isci_phy->sas_phy.oob_mode = SATA_OOB_MODE; @@ -207,9 +207,7 @@ void isci_port_link_up( memcpy(&isci_phy->sas_phy.attached_sas_addr, &attached_sas_address, sizeof(attached_sas_address)); - - } else if (properties.remote.protocols.u.bits.ssp_target || - properties.remote.protocols.u.bits.smp_target) { + } else if (phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { isci_phy->sas_phy.oob_mode = SAS_OOB_MODE; isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame); -- cgit v1.2.3 From 51a57cff7ca0549bcf87cbb36086269978f42568 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 18:28:32 -0700 Subject: isci: Remove SCIC_SWAP_DWORD() Use Linux native swab32() call instead of SCIC_SWAP_DWORD(). We need to swab() because the hardware munges the data into a "big-endian dword" stream which is byte-swapped from the sas definition regardless of host endian. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_util.c | 13 --------- drivers/scsi/isci/core/sci_util.h | 38 ++++++++++--------------- drivers/scsi/isci/core/scic_sds_phy.c | 40 ++++++++++----------------- drivers/scsi/isci/core/scic_sds_request.c | 39 +++++++++++++------------- drivers/scsi/isci/core/scic_sds_smp_request.c | 21 +++++++------- 5 files changed, 60 insertions(+), 91 deletions(-) diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c index ebf0ed919a9f..0c75d14240a1 100644 --- a/drivers/scsi/isci/core/sci_util.c +++ b/drivers/scsi/isci/core/sci_util.c @@ -57,19 +57,6 @@ #include "sci_util.h" #include "sci_environment.h" -void scic_word_copy_with_swap( - u32 *destination, - u32 *source, - u32 word_count) -{ - while (word_count--) { - *destination = SCIC_SWAP_DWORD(*source); - - source++; - destination++; - } -} - void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr) { struct isci_request *ireq = sci_req->ireq; diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h index b6f43e27c615..4e9c3189cf95 100644 --- a/drivers/scsi/isci/core/sci_util.h +++ b/drivers/scsi/isci/core/sci_util.h @@ -56,22 +56,8 @@ #ifndef _SCI_UTIL_H_ #define _SCI_UTIL_H_ -#include #include "scic_sds_request.h" -/** - * SCIC_SWAP_DWORD() - - * - * Normal byte swap macro - */ -#define SCIC_SWAP_DWORD(x) \ - (\ - (((x) >> 24) & 0x000000FF) \ - | (((x) >> 8) & 0x0000FF00) \ - | (((x) << 8) & 0x00FF0000) \ - | (((x) << 24) & 0xFF000000) \ - ) - #define SCIC_BUILD_DWORD(char_buffer) \ (\ ((char_buffer)[0] << 24) \ @@ -87,17 +73,23 @@ ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) /** - * scic_word_copy_with_swap() - Copy the data from source to destination and - * swap the bytes during the copy. - * @destination: This parameter specifies the destination address to which the - * data is to be copied. - * @source: This parameter specifies the source address from which data is to - * be copied. - * @word_count: This parameter specifies the number of 32-bit words to copy and - * byte swap. + * sci_swab32_cpy - convert between scsi and scu-hardware byte format + * @dest: receive the 4-byte endian swapped version of src + * @src: word aligned source buffer * + * scu hardware handles SSP/SMP control, response, and unidentified + * frames in "big endian dword" order. Regardless of host endian this + * is always a swab32()-per-dword conversion of the standard definition, + * i.e. single byte fields swapped and multi-byte fields in little- + * endian */ -void scic_word_copy_with_swap(u32 *destination, u32 *source, u32 word_count); +static inline void sci_swab32_cpy(void *_dest, void *_src, ssize_t word_cnt) +{ + u32 *dest = _dest, *src = _src; + + while (--word_cnt >= 0) + dest[word_cnt] = swab32(src[word_cnt]); +} void *scic_request_get_virt_addr(struct scic_sds_request *sds_request, dma_addr_t phys_addr); diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index b9d6fc7e8ae0..18dc14a8f0ba 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -1098,7 +1098,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler { enum sci_status result; u32 *frame_words; - struct sas_identify_frame *identify_frame; + struct sas_identify_frame iaf; struct isci_phy *iphy = sci_phy->iphy; result = scic_sds_unsolicited_frame_control_get_header( @@ -1106,38 +1106,29 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler frame_index, (void **)&frame_words); - if (result != SCI_SUCCESS) { + if (result != SCI_SUCCESS) return result; - } - - frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]); - identify_frame = (struct sas_identify_frame *)frame_words; - if (identify_frame->frame_type == 0) { + sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32)); + if (iaf.frame_type == 0) { u32 state; - /* Byte swap the rest of the frame so we can make - * a copy of the buffer - */ - frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]); - frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]); - frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]); - frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]); - frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]); - - memcpy(&iphy->frame_rcvd.iaf, identify_frame, sizeof(*identify_frame)); - - if (identify_frame->smp_tport) { - /* We got the IAF for an expander PHY go to the final state since - * there are no power requirements for expander phys. + memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf)); + if (iaf.smp_tport) { + /* We got the IAF for an expander PHY go to the final + * state since there are no power requirements for + * expander phys. */ state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; } else { - /* We got the IAF we can now go to the await spinup semaphore state */ + /* We got the IAF we can now go to the await spinup + * semaphore state + */ state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; } - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, - state); + sci_base_state_machine_change_state( + &sci_phy->starting_substate_machine, + state); result = SCI_SUCCESS; } else dev_warn(sciphy_to_dev(sci_phy), @@ -1146,7 +1137,6 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler __func__, frame_index); - /* Regardless of the result release this frame since we are done with it */ scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), frame_index); diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 8eb3c7e59ec5..e9c69d451f43 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -362,10 +362,8 @@ static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sc cmd_iu->task_attr = task->ssp_task.task_attr; cmd_iu->_r_c = 0; - scic_word_copy_with_swap( - (u32 *)(&cmd_iu->cdb), - (u32 *)task->ssp_task.cdb, - sizeof(task->ssp_task.cdb) / sizeof(u32)); + sci_swab32_cpy(&cmd_iu->cdb, task->ssp_task.cdb, + sizeof(task->ssp_task.cdb) / sizeof(u32)); } static void scic_sds_task_request_build_ssp_task_iu(struct scic_sds_request *sci_req) @@ -1120,10 +1118,11 @@ scic_sds_request_started_state_tc_completion_handler( * completed early. */ struct ssp_response_iu *resp = sci_req->response_buffer; - scic_word_copy_with_swap( - sci_req->response_buffer, - sci_req->response_buffer, - SSP_RESP_IU_MAX_SIZE / sizeof(u32)); + ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); + + sci_swab32_cpy(sci_req->response_buffer, + sci_req->response_buffer, + word_cnt); if (resp->status == 0) { scic_sds_request_set_status( @@ -1140,16 +1139,18 @@ scic_sds_request_started_state_tc_completion_handler( break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): - scic_word_copy_with_swap( - sci_req->response_buffer, - sci_req->response_buffer, - SSP_RESP_IU_MAX_SIZE / sizeof(u32)); + { + ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); + sci_swab32_cpy(sci_req->response_buffer, + sci_req->response_buffer, + word_cnt); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); break; + } case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR): /* @@ -1273,15 +1274,15 @@ scic_sds_request_started_state_frame_handler(struct scic_sds_request *sci_req, if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME) { struct ssp_response_iu *resp_iu; + ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); status = scic_sds_unsolicited_frame_control_get_buffer( &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, (void **)&resp_iu); - scic_word_copy_with_swap(sci_req->response_buffer, - (u32 *)resp_iu, - SSP_RESP_IU_MAX_SIZE); + sci_swab32_cpy(sci_req->response_buffer, + resp_iu, word_cnt); resp_iu = sci_req->response_buffer; diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index e6cfcbba9f9d..bca51a72ee86 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -164,11 +164,11 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, struct scic_sds_remote_device *sci_dev; struct scic_sds_port *sci_port; struct scu_task_context *task_context; + ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); /* byte swap the smp request. */ - scic_word_copy_with_swap(sci_req->command_buffer, - (u32 *)smp_req, - sizeof(struct smp_req) / sizeof(u32)); + sci_swab32_cpy(sci_req->command_buffer, smp_req, + word_cnt); task_context = scic_sds_request_get_task_context(sci_req); @@ -295,6 +295,7 @@ scic_sds_smp_request_await_response_frame_handler( void *frame_header; struct smp_resp *rsp_hdr; u8 *usr_smp_buf = sci_req->response_buffer; + ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); status = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_request_get_controller(sci_req)->uf_control), @@ -302,9 +303,7 @@ scic_sds_smp_request_await_response_frame_handler( &frame_header); /* byte swap the header. */ - scic_word_copy_with_swap((u32 *)usr_smp_buf, - frame_header, - SMP_RESP_HDR_SZ / sizeof(u32)); + sci_swab32_cpy(usr_smp_buf, frame_header, word_cnt); rsp_hdr = (struct smp_resp *)usr_smp_buf; @@ -316,11 +315,11 @@ scic_sds_smp_request_await_response_frame_handler( frame_index, &smp_resp); - scic_word_copy_with_swap( - (u32 *)(usr_smp_buf + SMP_RESP_HDR_SZ), - smp_resp, - (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / - sizeof(u32)); + word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / + sizeof(u32); + + sci_swab32_cpy(usr_smp_buf + SMP_RESP_HDR_SZ, + smp_resp, word_cnt); scic_sds_request_set_status( sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); -- cgit v1.2.3 From 2d9c2240e0bad47e8d08091016b537287a263976 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 18:45:05 -0700 Subject: isci: Using Linux SSP frame header Removing of struct sci_ssp_frame_header and migrate to struct ssp_frame_hdr. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 39 ---------------------------- drivers/scsi/isci/core/scic_sds_controller.c | 22 +++------------- drivers/scsi/isci/core/scic_sds_controller.h | 6 ++--- drivers/scsi/isci/core/scic_sds_request.c | 11 +++++--- drivers/scsi/isci/remote_device.c | 12 ++++++--- 5 files changed, 22 insertions(+), 68 deletions(-) diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h index f2d5ca1c72ed..156694fc8dee 100644 --- a/drivers/scsi/isci/core/intel_sas.h +++ b/drivers/scsi/isci/core/intel_sas.h @@ -133,45 +133,6 @@ enum sci_sas_frame_type { SCI_SAS_TASK_FRAME = 0x16 }; -/** - * struct sci_ssp_frame_header - This structure depicts the contents of an SSP - * frame header. For specific information on the individual fields please - * reference the SAS specification transport layer SSP frame format. - * - * - */ -struct sci_ssp_frame_header { - /* Word 0 */ - u32 hashed_destination_address:24; - u32 frame_type:8; - - /* Word 1 */ - u32 hashed_source_address:24; - u32 reserved1_0:8; - - /* Word 2 */ - u32 reserved2_2:6; - u32 fill_bytes:2; - u32 reserved2_1:3; - u32 tlr_control:2; - u32 retry_data_frames:1; - u32 retransmit:1; - u32 changing_data_pointer:1; - u32 reserved2_0:16; - - /* Word 3 */ - u32 uiResv4; - - /* Word 4 */ - u16 target_port_transfer_tag; - u16 tag; - - /* Word 5 */ - u32 data_offset; - -}; - - #define PHY_OPERATION_NOP 0x00 #define PHY_OPERATION_LINK_RESET 0x01 #define PHY_OPERATION_HARD_RESET 0x02 diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 0b76fc75996f..3fe73cbc0524 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1619,25 +1619,9 @@ struct scu_task_context *scic_sds_controller_get_task_context_buffer( return NULL; } -/** - * This method returnst the sequence value from the io tag value - * @scic: - * @io_tag: - * - * u16 - */ - -/** - * This method returns the IO request associated with the tag value - * @scic: - * @io_tag: - * - * SCIC_SDS_IO_REQUEST_T* NULL if there is no valid IO request at the tag value - */ -struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( - struct scic_sds_controller *scic, - u16 io_tag - ) { +struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, + u16 io_tag) +{ u16 task_index; u16 task_sequence; diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 8e3240de3d92..08aee06c124d 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -556,10 +556,8 @@ union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffe struct scic_sds_controller *this_controller, u16 node_id); -struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( - struct scic_sds_controller *this_controller, - u16 io_tag); - +struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, + u16 io_tag); struct scu_task_context *scic_sds_controller_get_task_context_buffer( struct scic_sds_controller *this_controller, diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index e9c69d451f43..f34ca3d8ee33 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -1265,14 +1265,19 @@ scic_sds_request_started_state_frame_handler(struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; - struct sci_ssp_frame_header *frame_header; + u32 *frame_header; + struct ssp_frame_hdr ssp_hdr; + ssize_t word_cnt; status = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_request_get_controller(sci_req)->uf_control), frame_index, (void **)&frame_header); - if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME) { + word_cnt = sizeof(struct ssp_frame_hdr) / sizeof(u32); + sci_swab32_cpy(&ssp_hdr, frame_header, word_cnt); + + if (ssp_hdr.frame_type == SSP_RESPONSE) { struct ssp_response_iu *resp_iu; ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); @@ -1303,7 +1308,7 @@ scic_sds_request_started_state_frame_handler(struct scic_sds_request *sci_req, __func__, sci_req, frame_index, - frame_header->frame_type); + ssp_hdr.frame_type); } /* diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index e766b27bdc19..89cdd0a05abc 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -52,6 +52,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "intel_sas.h" #include "sas.h" #include "isci.h" @@ -305,15 +306,20 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: { struct scic_sds_request *sci_req; - struct sci_ssp_frame_header *hdr; + struct ssp_frame_hdr hdr; + void *frame_header; + ssize_t word_cnt; status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, frame_index, - (void **)&hdr); + &frame_header); if (status != SCI_SUCCESS) return status; - sci_req = scic_sds_controller_get_io_request_from_tag(scic, hdr->tag); + word_cnt = sizeof(hdr) / sizeof(u32); + sci_swab32_cpy(&hdr, frame_header, word_cnt); + + sci_req = scic_request_by_tag(scic, be16_to_cpu(hdr.tag)); if (sci_req && sci_req->target_device == sci_dev) { /* The IO request is now in charge of releasing the frame */ status = sci_req->state_handlers->frame_handler(sci_req, -- cgit v1.2.3 From 8694e79287ad92e351feceededeb6804babb6d9a Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 May 2011 19:01:01 -0700 Subject: isci: removing intel_*.h headers Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/intel_sas.h | 178 -------- drivers/scsi/isci/core/intel_scsi.h | 474 --------------------- drivers/scsi/isci/core/scic_config_parameters.h | 1 - drivers/scsi/isci/core/scic_io_request.h | 6 +- drivers/scsi/isci/core/scic_phy.h | 1 - drivers/scsi/isci/core/scic_port.h | 2 +- drivers/scsi/isci/core/scic_sds_phy.h | 2 +- drivers/scsi/isci/core/scic_sds_port.c | 2 - drivers/scsi/isci/core/scic_sds_port.h | 2 +- drivers/scsi/isci/core/scic_sds_request.c | 6 +- drivers/scsi/isci/core/scic_sds_request.h | 1 - drivers/scsi/isci/core/scic_sds_smp_request.c | 2 - drivers/scsi/isci/core/scic_sds_smp_request.h | 1 - drivers/scsi/isci/core/scic_sds_ssp_request.c | 1 - .../scsi/isci/core/scic_sds_stp_packet_request.h | 1 - drivers/scsi/isci/remote_device.c | 2 - drivers/scsi/isci/remote_device.h | 1 - drivers/scsi/isci/sas.h | 10 + 18 files changed, 17 insertions(+), 676 deletions(-) delete mode 100644 drivers/scsi/isci/core/intel_sas.h delete mode 100644 drivers/scsi/isci/core/intel_scsi.h diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h deleted file mode 100644 index 156694fc8dee..000000000000 --- a/drivers/scsi/isci/core/intel_sas.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _INTEL_SAS_H_ -#define _INTEL_SAS_H_ - -/** - * This file contains all of the definitions relating to structures, constants, - * etc. defined by the SAS specification. - * - * - */ -#include -#include "intel_scsi.h" - -/** - * struct sci_sas_address - This structure depicts how a SAS address is - * represented by SCI. - * - * - */ -struct sci_sas_address { - /** - * This member contains the higher 32-bits of the SAS address. - */ - u32 high; - - /** - * This member contains the lower 32-bits of the SAS address. - */ - u32 low; - -}; - -/** - * enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS - * specification defined task attribute values for a command information - * unit. - * - * - */ -enum sci_sas_task_attribute { - SCI_SAS_SIMPLE_ATTRIBUTE = 0, - SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE = 1, - SCI_SAS_ORDERED_ATTRIBUTE = 2, - SCI_SAS_ACA_ATTRIBUTE = 4, -}; - -/** - * enum _SCI_SAS_TASK_MGMT_FUNCTION - This enumeration depicts the SAM/SAS - * specification defined task management functions. - * - * This HARD_RESET function listed here is not actually defined as a task - * management function in the industry standard. - */ -enum sci_sas_task_mgmt_function { - SCI_SAS_ABORT_TASK = SCSI_TASK_REQUEST_ABORT_TASK, - SCI_SAS_ABORT_TASK_SET = SCSI_TASK_REQUEST_ABORT_TASK_SET, - SCI_SAS_CLEAR_TASK_SET = SCSI_TASK_REQUEST_CLEAR_TASK_SET, - SCI_SAS_LOGICAL_UNIT_RESET = SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET, - SCI_SAS_I_T_NEXUS_RESET = SCSI_TASK_REQUEST_I_T_NEXUS_RESET, - SCI_SAS_CLEAR_ACA = SCSI_TASK_REQUEST_CLEAR_ACA, - SCI_SAS_QUERY_TASK = SCSI_TASK_REQUEST_QUERY_TASK, - SCI_SAS_QUERY_TASK_SET = SCSI_TASK_REQUEST_QUERY_TASK_SET, - SCI_SAS_QUERY_ASYNCHRONOUS_EVENT = SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION, - SCI_SAS_HARD_RESET = 0xFF -}; - - -/** - * enum _SCI_SAS_FRAME_TYPE - This enumeration depicts the SAS specification - * defined SSP frame types. - * - * - */ -enum sci_sas_frame_type { - SCI_SAS_DATA_FRAME = 0x01, - SCI_SAS_XFER_RDY_FRAME = 0x05, - SCI_SAS_COMMAND_FRAME = 0x06, - SCI_SAS_RESPONSE_FRAME = 0x07, - SCI_SAS_TASK_FRAME = 0x16 -}; - -#define PHY_OPERATION_NOP 0x00 -#define PHY_OPERATION_LINK_RESET 0x01 -#define PHY_OPERATION_HARD_RESET 0x02 -#define PHY_OPERATION_DISABLE 0x03 -#define PHY_OPERATION_CLEAR_ERROR_LOG 0x05 -#define PHY_OPERATION_CLEAR_AFFILIATION 0x06 - -#define NPLR_PHY_ENABLED_UNK_LINK_RATE 0x00 -#define NPLR_PHY_DISABLED 0x01 -#define NPLR_PHY_ENABLED_SPD_NEG_FAILED 0x02 -#define NPLR_PHY_ENABLED_SATA_HOLD 0x03 -#define NPLR_PHY_ENABLED_1_5G 0x08 -#define NPLR_PHY_ENABLED_3_0G 0x09 - -/* SMP Function Result values. */ -#define SMP_RESULT_FUNCTION_ACCEPTED 0x00 -#define SMP_RESULT_UNKNOWN_FUNCTION 0x01 -#define SMP_RESULT_FUNCTION_FAILED 0x02 -#define SMP_RESULT_INVALID_REQUEST_FRAME_LEN 0x03 -#define SMP_RESULT_INAVALID_EXPANDER_CHANGE_COUNT 0x04 -#define SMP_RESULT_BUSY 0x05 -#define SMP_RESULT_INCOMPLETE_DESCRIPTOR_LIST 0x06 -#define SMP_RESULT_PHY_DOES_NOT_EXIST 0x10 -#define SMP_RESULT_INDEX_DOES_NOT_EXIST 0x11 -#define SMP_RESULT_PHY_DOES_NOT_SUPPORT_SATA 0x12 -#define SMP_RESULT_UNKNOWN_PHY_OPERATION 0x13 -#define SMP_RESULT_UNKNOWN_PHY_TEST_FUNCTION 0x14 -#define SMP_RESULT_PHY_TEST_IN_PROGRESS 0x15 -#define SMP_RESULT_PHY_VACANT 0x16 - -/* Attached Device Types */ -#define SMP_NO_DEVICE_ATTACHED 0 -#define SMP_END_DEVICE_ONLY 1 -#define SMP_EDGE_EXPANDER_DEVICE 2 -#define SMP_FANOUT_EXPANDER_DEVICE 3 - -/* Expander phy routine attribute */ -#define DIRECT_ROUTING_ATTRIBUTE 0 -#define SUBTRACTIVE_ROUTING_ATTRIBUTE 1 -#define TABLE_ROUTING_ATTRIBUTE 2 - -#endif /* _INTEL_SAS_H_ */ - diff --git a/drivers/scsi/isci/core/intel_scsi.h b/drivers/scsi/isci/core/intel_scsi.h deleted file mode 100644 index 1e45d3c98127..000000000000 --- a/drivers/scsi/isci/core/intel_scsi.h +++ /dev/null @@ -1,474 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file defines all of the SCSI related constants, enumerations, and - * types. Please note that this file does not necessarily contain an - * exhaustive list of all constants, commands, sub-commands, etc. - * - * - */ - -#ifndef _SCSI_H__ -#define _SCSI_H__ - - -/* - * ****************************************************************************** - * * C O N S T A N T S A N D M A C R O S - * ****************************************************************************** */ - -/** - * enum _SCSI_TASK_MGMT_REQUEST_CODES - This enumberation contains the - * constants to be used for SCSI task management request codes. SAM does - * not specify any particular values for these codes so constants used here - * are the same as those specified in SAS. - * - * - */ -enum scsi_task_mgmt_request_codes { - SCSI_TASK_REQUEST_ABORT_TASK = 0x01, - SCSI_TASK_REQUEST_ABORT_TASK_SET = 0x02, - SCSI_TASK_REQUEST_CLEAR_TASK_SET = 0x04, - SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET = 0x08, - SCSI_TASK_REQUEST_I_T_NEXUS_RESET = 0x10, - SCSI_TASK_REQUEST_CLEAR_ACA = 0x40, - SCSI_TASK_REQUEST_QUERY_TASK = 0x80, - SCSI_TASK_REQUEST_QUERY_TASK_SET = 0x81, - SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION = 0x82, - -}; - -/** - * enum _SCSI_TASK_MGMT_RESPONSE_CODES - This enumeration contains all of the - * SCSI task management response codes. - * - * - */ -enum scsi_task_mgmt_response_codes { - SCSI_TASK_MGMT_FUNC_COMPLETE = 0, - SCSI_INVALID_FRAME = 2, - SCSI_TASK_MGMT_FUNC_NOT_SUPPORTED = 4, - SCSI_TASK_MGMT_FUNC_FAILED = 5, - SCSI_TASK_MGMT_FUNC_SUCCEEDED = 8, - SCSI_INVALID_LUN = 9 -}; - -/** - * enum _SCSI_SENSE_RESPONSE_CODE - this enumeration depicts the types of sense - * data responses as per SPC-3. - * - * - */ -enum scsi_sense_response_code { - SCSI_FIXED_CURRENT_RESPONSE_CODE = 0x70, - SCSI_FIXED_DEFERRED_RESPONSE_CODE = 0x71, - SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE = 0x72, - SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE = 0x73 - -}; - -/* - * This constant represents the valid bit located in byte 0 of a FIXED - * format sense data. */ -#define SCSI_FIXED_SENSE_DATA_VALID_BIT 0x80 - -#define SCSI_FIXED_SENSE_DATA_BASE_LENGTH 18 - -/* This value is used in the DATAPRES field of the SCSI Response IU. */ -#define SCSI_RESPONSE_DATA_PRES_SENSE_DATA 0x02 - -/** - * - * - * SCSI_SENSE_KEYS These constants delineate all of the SCSI protocol sense key - * constants - */ -#define SCSI_SENSE_NO_SENSE 0x00 -#define SCSI_SENSE_RECOVERED_ERROR 0x01 -#define SCSI_SENSE_NOT_READY 0x02 -#define SCSI_SENSE_MEDIUM_ERROR 0x03 -#define SCSI_SENSE_HARDWARE_ERROR 0x04 -#define SCSI_SENSE_ILLEGAL_REQUEST 0x05 -#define SCSI_SENSE_UNIT_ATTENTION 0x06 -#define SCSI_SENSE_DATA_PROTECT 0x07 -#define SCSI_SENSE_BLANK_CHECK 0x08 -#define SCSI_SENSE_VENDOR_SPECIFIC 0x09 -#define SCSI_SENSE_COPY_ABORTED 0x0A -#define SCSI_SENSE_ABORTED_COMMAND 0x0B -#define SCSI_SENSE_VOLUME_OVERFLOW 0x0D -#define SCSI_SENSE_MISCOMPARE 0x0E - -/** - * - * - * SCSI_ADDITIONAL_SENSE_CODES These constants delineate all of the SCSI - * protocol additional sense code constants. - */ -#define SCSI_ASC_NO_ADDITIONAL_SENSE 0x00 -#define SCSI_ASC_INITIALIZING_COMMAND_REQUIRED 0x04 -#define SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS 0x04 -#define SCSI_ASC_LUN_FORMAT_IN_PROGRESS 0x04 -#define SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION 0x05 -#define SCSI_ASC_UNRECOVERED_READ_ERROR 0x11 -#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20 -#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21 -#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24 -#define SCSI_ASC_INVALID_FIELD_IN_PARM_LIST 0x26 -#define SCSI_ASC_WRITE_PROTECTED 0x27 -#define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28 -#define SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED 0x39 -#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A -#define SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44 -#define SCSI_ASC_IU_CRC_ERROR_DETECTED 0x47 -#define SCSI_ASC_MEDIUM_REMOVAL_REQUEST 0x5A -#define SCSI_ASC_COMMAND_SEQUENCE_ERROR 0x2C -#define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED 0x53 -#define SCSI_ASC_HARDWARE_IMPENDING_FAILURE 0x5D -#define SCSI_ASC_POWER_STATE_CHANGE 0x5E -#define SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT 0x40 -#define SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED 0x67 - -/** - * - * - * SCSI_ADDITIONAL_SENSE_CODE_QUALIFIERS This enumeration contains all of the - * used SCSI protocol additional sense code qualifier constants. - */ -#define SCSI_ASCQ_NO_ADDITIONAL_SENSE 0x00 -#define SCSI_ASCQ_INVALID_FIELD_IN_CDB 0x00 -#define SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 0x00 -#define SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION 0x00 -#define SCSI_ASCQ_INTERNAL_TARGET_FAILURE 0x00 -#define SCSI_ASCQ_LBA_OUT_OF_RANGE 0x00 -#define SCSI_ASCQ_MEDIUM_NOT_PRESENT 0x00 -#define SCSI_ASCQ_NOT_READY_TO_READY_CHANGE 0x00 -#define SCSI_ASCQ_WRITE_PROTECTED 0x00 -#define SCSI_ASCQ_UNRECOVERED_READ_ERROR 0x00 -#define SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED 0x00 -#define SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE 0x00 -#define SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST 0x01 -#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 -#define SCSI_ASCQ_IU_CRC_ERROR_DETECTED 0x03 -#define SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS 0x04 -#define SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS 0x09 -#define SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE 0x10 -#define SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND 0x03 -#define SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND 0x04 -#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE 0x42 -#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY 0x43 -#define SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED 0x0B -#define SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 0x04 - - - -/** - * - * - * SCSI_STATUS_CODES These constants define all of the used SCSI status values. - */ -#define SCSI_STATUS_GOOD 0x00 -#define SCSI_STATUS_CHECK_CONDITION 0x02 -#define SCSI_STATUS_CONDITION_MET 0x04 -#define SCSI_STATUS_BUSY 0x08 -#define SCSI_STATUS_TASKFULL 0x28 -#define SCSI_STATUS_ACA 0x30 -#define SCSI_STATUS_ABORT 0x40 - -/** - * - * - * SCSI_OPERATION_CODES These constants delineate all of the SCSI - * command/operation codes. - */ -#define SCSI_INQUIRY 0x12 -#define SCSI_READ_CAPACITY_10 0x25 -#define SCSI_SERVICE_ACTION_IN_16 0x9E -#define SCSI_TEST_UNIT_READY 0x00 -#define SCSI_START_STOP_UNIT 0x1B -#define SCSI_SYNCHRONIZE_CACHE_10 0x35 -#define SCSI_SYNCHRONIZE_CACHE_16 0x91 -#define SCSI_REQUEST_SENSE 0x03 -#define SCSI_REPORT_LUNS 0xA0 -#define SCSI_REASSIGN_BLOCKS 0x07 -#define SCSI_READ_6 0x08 -#define SCSI_READ_10 0x28 -#define SCSI_READ_12 0xA8 -#define SCSI_READ_16 0x88 -#define SCSI_WRITE_6 0x0A -#define SCSI_WRITE_10 0x2A -#define SCSI_WRITE_12 0xAA -#define SCSI_WRITE_16 0x8A -#define SCSI_VERIFY_10 0x2F -#define SCSI_VERIFY_12 0xAF -#define SCSI_VERIFY_16 0x8F -#define SCSI_SEEK_6 0x01 -#define SCSI_SEEK_10 0x02 -#define SCSI_WRITE_VERIFY 0x2E -#define SCSI_FORMAT_UNIT 0x04 -#define SCSI_READ_BUFFER 0x3C -#define SCSI_WRITE_BUFFER 0x3B -#define SCSI_SEND_DIAGNOSTIC 0x1D -#define SCSI_RECEIVE_DIAGNOSTIC 0x1C -#define SCSI_MODE_SENSE_6 0x1A -#define SCSI_MODE_SENSE_10 0x5A -#define SCSI_MODE_SELECT_6 0x15 -#define SCSI_MODE_SELECT_10 0x55 -#define SCSI_MAINTENANCE_IN 0xA3 -#define SCSI_LOG_SENSE 0x4D -#define SCSI_LOG_SELECT 0x4C -#define SCSI_RESERVE_6 0x16 -#define SCSI_RESERVE_10 0x56 -#define SCSI_RELEASE_6 0x17 -#define SCSI_RELEASE_10 0x57 -#define SCSI_ATA_PASSTHRU_12 0xA1 -#define SCSI_ATA_PASSTHRU_16 0x85 -#define SCSI_WRITE_LONG_10 0x3F -#define SCSI_WRITE_LONG_16 0x9F -#define SCSI_PERSISTENT_RESERVE_IN 0x5E -#define SCSI_PERSISTENT_RESERVE_OUT 0x5F - -/** - * - * - * SCSI_SERVICE_ACTION_IN_CODES Service action in operations. - */ -#define SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16 0x10 - -#define SCSI_SERVICE_ACTION_MASK 0x1f - -/** - * - * - * SCSI_MAINTENANCE_IN_SERVICE_ACTION_CODES MAINTENANCE IN service action codes. - */ -#define SCSI_REPORT_TASK_MGMT 0x0D -#define SCSI_REPORT_OP_CODES 0x0C - -/** - * - * - * SCSI_MODE_PAGE_CONTROLS These constants delineate all of the used SCSI Mode - * Page control values. - */ -#define SCSI_MODE_SENSE_PC_CURRENT 0x0 -#define SCSI_MODE_SENSE_PC_CHANGEABLE 0x1 -#define SCSI_MODE_SENSE_PC_DEFAULT 0x2 -#define SCSI_MODE_SENSE_PC_SAVED 0x3 - -#define SCSI_MODE_SENSE_PC_SHIFT 0x06 -#define SCSI_MODE_SENSE_PAGE_CODE_ENABLE 0x3F -#define SCSI_MODE_SENSE_DBD_ENABLE 0x08 -#define SCSI_MODE_SENSE_LLBAA_ENABLE 0x10 - -/** - * - * - * SCSI_MODE_PAGE_CODES These constants delineate all of the used SCSI Mode - * Page codes. - */ -#define SCSI_MODE_PAGE_READ_WRITE_ERROR 0x01 -#define SCSI_MODE_PAGE_DISCONNECT_RECONNECT 0x02 -#define SCSI_MODE_PAGE_CACHING 0x08 -#define SCSI_MODE_PAGE_CONTROL 0x0A -#define SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT 0x19 -#define SCSI_MODE_PAGE_POWER_CONDITION 0x1A -#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL 0x1C -#define SCSI_MODE_PAGE_ALL_PAGES 0x3F - -#define SCSI_MODE_SENSE_ALL_SUB_PAGES_CODE 0xFF -#define SCSI_MODE_SENSE_NO_SUB_PAGES_CODE 0x0 -#define SCSI_MODE_SENSE_PROTOCOL_PORT_NUM_SUBPAGES 0x1 -#define SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT 0x04 -#define SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT 0x20 -#define SCSI_MODE_PAGE_DEXCPT_ENABLE 0x08 -#define SCSI_MODE_SENSE_HEADER_FUA_ENABLE 0x10 -#define SCSI_MODE_PAGE_POWER_CONDITION_STANDBY 0x1 -#define SCSI_MODE_PAGE_POWER_CONDITION_IDLE 0x2 - -#define SCSI_MODE_SENSE_6_HEADER_LENGTH 4 -#define SCSI_MODE_SENSE_10_HEADER_LENGTH 8 -#define SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH 8 -#define SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH 16 - -#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE 0x08 -#define SCSI_MODE_PAGE_19_SAS_ID 0x6 -#define SCSI_MODE_PAGE_19_SUB1_PAGE_NUM 0x1 -#define SCSI_MODE_PAGE_19_SUB1_PC 0x59 - -#define SCSI_MODE_HEADER_MEDIUM_TYPE_SBC 0x00 - -/* Mode Select constrains related masks value */ -#define SCSI_MODE_SELECT_PF_BIT 0x1 -#define SCSI_MODE_SELECT_PF_MASK 0x10 -#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE 0x6 -#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK 0x0F -#define SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK 0x40 -#define SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK 0x80 -#define SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK 0x40 -#define SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK 0x1F -#define SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS 0xC1 -#define SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST 0x84 -#define SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC 0xF1 -#define SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER 0xF0 -#define SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP 0x38 -#define SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO 0x47 - - -#define SCSI_CONTROL_BYTE_NACA_BIT_ENABLE 0x04 -#define SCSI_MOVE_FUA_BIT_ENABLE 0x08 -#define SCSI_READ_CAPACITY_PMI_BIT_ENABLE 0x01 -#define SCSI_READ_CAPACITY_10_DATA_LENGTH 8 -#define SCSI_READ_CAPACITY_16_DATA_LENGTH 32 - -/* Inquiry constants */ -#define SCSI_INQUIRY_EVPD_ENABLE 0x01 -#define SCSI_INQUIRY_PAGE_CODE_OFFSET 0x02 -#define SCSI_INQUIRY_SUPPORTED_PAGES_PAGE 0x00 -#define SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE 0x80 -#define SCSI_INQUIRY_DEVICE_ID_PAGE 0x83 -#define SCSI_INQUIRY_ATA_INFORMATION_PAGE 0x89 -#define SCSI_INQUIRY_BLOCK_DEVICE_PAGE 0xB1 -#define SCSI_INQUIRY_BLOCK_DEVICE_LENGTH 0x3C -#define SCSI_INQUIRY_STANDARD_ALLOCATION_LENGTH 0x24 /* 36 */ - -#define SCSI_REQUEST_SENSE_ALLOCATION_LENGTH 0xFC /* 252 */ - -/** Defines the log page codes that are use in gathing Smart data - */ -#define SCSI_LOG_PAGE_SUPPORTED_PAGES 0x00 -#define SCSI_LOG_PAGE_INFORMATION_EXCEPTION 0x2F -#define SCSI_LOG_PAGE_SELF_TEST 0x10 - -/** - * - * - * SCSI_INQUIRY_VPD The following are constants used with vital product data - * inquiry pages. Values are already shifted into the proper nibble location. - */ -#define SCSI_PIV_ENABLE 0x80 -#define SCSI_LUN_ASSOCIATION 0x00 -#define SCSI_TARGET_PORT_ASSOCIATION 0x10 - -#define SCSI_VEN_UNIQUE_IDENTIFIER_TYPE 0x00 -#define SCSI_NAA_IDENTIFIER_TYPE 0x03 - -#define SCSI_T10_IDENTIFIER_TYPE 0x01 -#define SCSI_BINARY_CODE_SET 0x01 -#define SCSI_ASCII_CODE_SET 0x02 -#define SCSI_FC_PROTOCOL_IDENTIFIER 0x00 -#define SCSI_SAS_PROTOCOL_IDENTIFIER 0x60 - -#define SCSI_VERIFY_BYTCHK_ENABLED 0x02 - -#define SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED 0x02 -/** - * - * - * SCSI_START_STOP_UNIT_POWER_CONDITION_CODES The following are SCSI Start Stop - * Unit command Power Condition codes. - */ -#define SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID 0x0 -#define SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE 0x1 -#define SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE 0x2 -#define SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY 0x3 -#define SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL 0x7 -#define SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL 0xB - -#define SCSI_START_STOP_UNIT_IMMED_MASK 0x1 -#define SCSI_START_STOP_UNIT_IMMED_SHIFT 0 - -#define SCSI_START_STOP_UNIT_START_BIT_MASK 0x1 -#define SCSI_START_STOP_UNIT_START_BIT_SHIFT 0 - -#define SCSI_START_STOP_UNIT_LOEJ_BIT_MASK 0x2 -#define SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT 1 - -#define SCSI_START_STOP_UNIT_NO_FLUSH_MASK 0x4 -#define SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT 2 - -#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK 0xF -#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT 0 - -#define SCSI_START_STOP_UNIT_POWER_CONDITION_MASK 0xF0 -#define SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT 4 - -#define SCSI_LOG_SENSE_PC_FIELD_MASK 0xC0 -#define SCSI_LOG_SENSE_PC_FIELD_SHIFT 6 - -#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK 0x3F -#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT 0 - -/** - * - * - * MRIE - Method of reporting informational exceptions codes - */ -#define NO_REPORTING_INFO_EXCEPTION_CONDITION 0x0 -#define ASYNCHRONOUS_EVENT_REPORTING 0x1 -#define ESTABLISH_UNIT_ATTENTION_CONDITION 0x2 -#define CONDITIONALLY_GENERATE_RECOVERED_ERROR 0x3 -#define UNCONDITIONALLY_GENERATE_RECOVERED_ERROR 0x4 -#define GENERATE_NO_SENSE 0x5 -#define REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6 - -#define SCSI_INFORMATION_EXCEPTION_DEXCPT_BIT 0x08 - -/* Reassign Blocks masks */ -#define SCSI_REASSIGN_BLOCKS_LONGLBA_BIT 0x02 -#define SCSI_REASSIGN_BLOCKS_LONGLIST_BIT 0x01 - -#endif /* _SCSI_H_ */ - diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index 716abfcd0c23..ea09d0bd2d1b 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -66,7 +66,6 @@ #include "sci_status.h" -#include "intel_sas.h" #include "sci_controller_constants.h" #include "probe_roms.h" diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h index 16022636fed0..6ddf3801daf8 100644 --- a/drivers/scsi/isci/core/scic_io_request.h +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -63,9 +63,8 @@ * Determine the failure situations and return values. */ - +#include #include "sci_status.h" -#include "intel_sas.h" struct scic_sds_request; struct scic_sds_remote_device; @@ -110,8 +109,7 @@ typedef enum { * * Return the size of the SCI IO request object. */ -u32 scic_io_request_get_object_size( - void); +u32 scic_io_request_get_object_size(void); /** * scic_io_request_construct() - This method is called by the SCI user to diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 451d7977bf6d..1fb49f02162b 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -67,7 +67,6 @@ #include #include #include "sci_status.h" -#include "intel_sas.h" struct scic_sds_phy; struct scic_sds_port; diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h index 4ae9b6cdf04f..44a8ea887151 100644 --- a/drivers/scsi/isci/core/scic_port.h +++ b/drivers/scsi/isci/core/scic_port.h @@ -56,9 +56,9 @@ #ifndef _SCIC_PORT_H_ #define _SCIC_PORT_H_ +#include "sas.h" #include "sci_status.h" #include "scic_phy.h" -#include "intel_sas.h" struct scic_sds_port; diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index b0cebdc669eb..b6a0ed1045df 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -56,7 +56,7 @@ #ifndef _SCIC_SDS_PHY_H_ #define _SCIC_SDS_PHY_H_ -#include "intel_sas.h" +#include "sas.h" #include "scic_phy.h" #include "scu_registers.h" #include "sci_base_state_machine.h" diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 05bc3bff4f6f..0c89fc1c09f8 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -53,8 +53,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "sas.h" -#include "intel_sas.h" #include "scic_controller.h" #include "scic_phy.h" #include "scic_port.h" diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 2253a2ced969..115cbe3129a8 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -57,8 +57,8 @@ #define _SCIC_SDS_PORT_H_ #include +#include "sas.h" #include "sci_controller_constants.h" -#include "intel_sas.h" #include "scu_registers.h" #define SCIC_SDS_DUMMY_PORT 0xFF diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index f34ca3d8ee33..85e40ce96e96 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -54,8 +54,6 @@ */ #include -#include "sas.h" -#include "intel_sas.h" #include "scic_controller.h" #include "scic_io_request.h" #include "scic_sds_controller.h" @@ -503,7 +501,7 @@ static void scu_ssp_io_request_construct_task_context( task_context->ssp_command_iu_length = sizeof(struct ssp_cmd_iu) / sizeof(u32); - task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME; + task_context->type.ssp.frame_type = SSP_COMMAND; switch (dir) { case DMA_FROM_DEVICE: @@ -573,7 +571,7 @@ static void scu_ssp_task_request_construct_task_context( task_context->priority = SCU_TASK_PRIORITY_HIGH; task_context->task_type = SCU_TASK_TYPE_RAW_FRAME; task_context->transfer_length_bytes = 0; - task_context->type.ssp.frame_type = SCI_SAS_TASK_FRAME; + task_context->type.ssp.frame_type = SSP_TASK; task_context->ssp_command_iu_length = sizeof(struct ssp_task_iu) / sizeof(u32); } diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 11d5a3ea9da3..b83d89362909 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -66,7 +66,6 @@ #include "scic_io_request.h" #include "sci_base_state_machine.h" #include "scu_task_context.h" -#include "intel_sas.h" struct scic_sds_controller; struct scic_sds_remote_device; diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index bca51a72ee86..1f8773d3b793 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -54,8 +54,6 @@ */ #include -#include "sas.h" -#include "intel_sas.h" #include "sci_base_state_machine.h" #include "scic_controller.h" #include "scic_sds_controller.h" diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.h b/drivers/scsi/isci/core/scic_sds_smp_request.h index 8f34ffe2c236..f432b7a182cd 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.h +++ b/drivers/scsi/isci/core/scic_sds_smp_request.h @@ -55,7 +55,6 @@ #ifndef _SCIC_SDS_SMP_REQUEST_T_ #define _SCIC_SDS_SMP_REQUEST_T_ -#include "intel_sas.h" #include "scic_sds_request.h" diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index 7183ae331d2e..18bf3874d6ac 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -53,7 +53,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "intel_sas.h" #include "sci_base_state_machine.h" #include "scic_controller.h" #include "scic_sds_controller.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h index 5d45ef6c2511..e94d689e5103 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h @@ -55,7 +55,6 @@ #ifndef _SCIC_SDS_STP_PACKET_REQUEST_H_ #define _SCIC_SDS_STP_PACKET_REQUEST_H_ -#include "intel_sas.h" #include "scic_sds_stp_request.h" /** diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 89cdd0a05abc..15c1e6c3b223 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -53,8 +53,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include -#include "intel_sas.h" -#include "sas.h" #include "isci.h" #include "port.h" #include "remote_device.h" diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 18f7f9663661..c7db4998b8f9 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -57,7 +57,6 @@ #define _ISCI_REMOTE_DEVICE_H_ #include #include "sci_status.h" -#include "intel_sas.h" #include "scu_remote_node_context.h" #include "remote_node_context.h" #include "port.h" diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index 83eab4671958..822a8dbd19ca 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h @@ -215,4 +215,14 @@ struct smp_req { #define SMP_RESP_HDR_SZ 4 +/* + * struct sci_sas_address - This structure depicts how a SAS address is + * represented by SCI. + * XXX convert this to u8 [SAS_ADDR_SIZE] like the rest of libsas + * + */ +struct sci_sas_address { + u32 high; + u32 low; +}; #endif -- cgit v1.2.3 From 5b3f2bd877382eaf4b5a7d90fdec72ef14b9ec97 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 5 May 2011 17:47:44 -0700 Subject: isci: fix ata locking Upstream commit a29b5dad "libata: fix locking for sas paths" switched libsas ata locking to the ata_host lock. We need to do the same when returning ata tasks from the execute path. Signed-off-by: Dan Williams --- drivers/scsi/isci/task.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index 77cc54dbe81f..aa2458658d1e 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -344,26 +344,26 @@ isci_task_set_completion_status( * @status: This parameter is the status code for the completed task. * */ -static inline void isci_execpath_callback( - struct isci_host *ihost, - struct sas_task *task, - void (*func)(struct sas_task *)) +static inline void isci_execpath_callback(struct isci_host *ihost, + struct sas_task *task, + void (*func)(struct sas_task *)) { - unsigned long flags; + struct domain_device *dev = task->dev; + + if (dev_is_sata(dev) && task->uldd_task) { + unsigned long flags; - if (dev_is_sata(task->dev) && task->uldd_task) { /* Since we are still in the submit path, and since - * libsas takes the host lock on behalf of SATA - * devices before I/O starts (in the non-discovery case), - * we need to unlock before we can call the callback function. - */ + * libsas takes the host lock on behalf of SATA + * devices before I/O starts (in the non-discovery case), + * we need to unlock before we can call the callback function. + */ raw_local_irq_save(flags); - spin_unlock(ihost->shost->host_lock); + spin_unlock(dev->sata_dev.ap->lock); func(task); - spin_lock(ihost->shost->host_lock); + spin_lock(dev->sata_dev.ap->lock); raw_local_irq_restore(flags); } else func(task); } - #endif /* !defined(_SCI_TASK_H_) */ -- cgit v1.2.3 From d06b487b78f28a02efdcdcc9ec295bf230b9d0e8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 2 May 2011 13:59:25 -0700 Subject: isci: implement I_T_nexus_reset This is a requirement for 2.6.39's new libata eh. Still some questions about lldd_dev_gone racing against dev->lldd_dev lookups, but we are at least no more broken than mvsas in this regard. We also short-circuit I_T_nexus_reset invocations from the device discovery path (IDEV_EH similar to MVS_DEV_EH) to filter out the resulting domain rediscoveries triggered by the reset. Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 1 + drivers/scsi/isci/remote_device.h | 1 + drivers/scsi/isci/task.c | 138 ++++++++++++++++++++------------------ 3 files changed, 76 insertions(+), 64 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 15c1e6c3b223..ee6fe1db8f99 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -891,6 +891,7 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ clear_bit(IDEV_START_PENDING, &idev->flags); clear_bit(IDEV_STOP_PENDING, &idev->flags); + clear_bit(IDEV_EH, &idev->flags); wake_up(&ihost->eventq); } diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index c7db4998b8f9..2e433b7f16b3 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -134,6 +134,7 @@ struct isci_remote_device { #define IDEV_START_PENDING 0 #define IDEV_STOP_PENDING 1 #define IDEV_ALLOCATED 2 + #define IDEV_EH 3 unsigned long flags; struct isci_port *isci_port; struct domain_device *domain_dev; diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 8449d8abd66a..3a3f54677e5b 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1022,9 +1022,11 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", __func__, domain_device, isci_host, isci_device); - if (isci_device != NULL) + if (isci_device != NULL) { device_stopping = (isci_device->status == isci_stopping) || (isci_device->status == isci_stopped); + set_bit(IDEV_EH, &isci_device->flags); + } /* If there is a device reset pending on any request in the * device's list, fail this LUN reset request in order to @@ -1069,12 +1071,6 @@ int isci_task_clear_nexus_ha(struct sas_ha_struct *ha) return TMF_RESP_FUNC_FAILED; } -int isci_task_I_T_nexus_reset(struct domain_device *dev) -{ - return TMF_RESP_FUNC_FAILED; -} - - /* Task Management Functions. Must be called from process context. */ /** @@ -1171,6 +1167,12 @@ int isci_task_abort_task(struct sas_task *task) device_stopping = (isci_device->status == isci_stopping) || (isci_device->status == isci_stopped); + /* XXX need to fix device lookup lifetime (needs to be done + * under scic_lock, among other things...), but for now assume + * the device is available like the above code + */ + set_bit(IDEV_EH, &isci_device->flags); + /* This version of the driver will fail abort requests for * SATA/STP. Failing the abort request this way will cause the * SCSI error handler thread to escalate to LUN reset @@ -1481,86 +1483,94 @@ isci_task_request_complete(struct isci_host *ihost, complete(tmf_complete); } -/** - * isci_bus_reset_handler() - This function performs a target reset of the - * device referenced by "cmd'. This function is exported through the - * "struct scsi_host_template" structure such that it is called when an I/O - * recovery process has escalated to a target reset. Note that this function - * is called from the scsi error handler event thread, so may block on calls. - * @scsi_cmd: This parameter specifies the target to be reset. - * - * SUCCESS if the reset process was successful, else FAILED. - */ -int isci_bus_reset_handler(struct scsi_cmnd *cmd) +static int isci_reset_device(struct domain_device *dev, int hard_reset) { - struct domain_device *dev = cmd_to_domain_dev(cmd); - struct isci_host *isci_host = dev_to_ihost(dev); - unsigned long flags = 0; + struct isci_remote_device *idev = dev->lldd_dev; + struct sas_phy *phy = sas_find_local_phy(dev); + struct isci_host *ihost = dev_to_ihost(dev); enum sci_status status; - int base_status; - struct isci_remote_device *isci_dev = dev->lldd_dev; + unsigned long flags; + int rc; - dev_dbg(&isci_host->pdev->dev, - "%s: cmd %p, isci_dev %p\n", - __func__, cmd, isci_dev); + dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); - if (!isci_dev) { - dev_warn(&isci_host->pdev->dev, - "%s: isci_dev is GONE!\n", + if (!idev) { + dev_warn(&ihost->pdev->dev, + "%s: idev is GONE!\n", __func__); return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */ } - spin_lock_irqsave(&isci_host->scic_lock, flags); - status = scic_remote_device_reset(&isci_dev->sci); + spin_lock_irqsave(&ihost->scic_lock, flags); + status = scic_remote_device_reset(&idev->sci); if (status != SCI_SUCCESS) { - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); - scmd_printk(KERN_WARNING, cmd, - "%s: scic_remote_device_reset(%p) returned %d!\n", - __func__, isci_dev, status); + dev_warn(&ihost->pdev->dev, + "%s: scic_remote_device_reset(%p) returned %d!\n", + __func__, idev, status); return TMF_RESP_FUNC_FAILED; } - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Make sure all pending requests are able to be fully terminated. */ - isci_device_clear_reset_pending(isci_host, isci_dev); + isci_device_clear_reset_pending(ihost, idev); - /* Terminate in-progress I/O now. */ - isci_remote_device_nuke_requests(isci_host, isci_dev); + rc = sas_phy_reset(phy, hard_reset); + msleep(2000); /* just like mvsas */ - /* Call into the libsas default handler (which calls sas_phy_reset). */ - base_status = sas_eh_bus_reset_handler(cmd); + /* Terminate in-progress I/O now. */ + isci_remote_device_nuke_requests(ihost, idev); - if (base_status != SUCCESS) { + spin_lock_irqsave(&ihost->scic_lock, flags); + status = scic_remote_device_reset_complete(&idev->sci); + spin_unlock_irqrestore(&ihost->scic_lock, flags); - /* There can be cases where the resets to individual devices - * behind an expander will fail because of an unplug of the - * expander itself. - */ - scmd_printk(KERN_WARNING, cmd, - "%s: sas_eh_bus_reset_handler(%p) returned %d!\n", - __func__, cmd, base_status); + if (status != SCI_SUCCESS) { + dev_warn(&ihost->pdev->dev, + "%s: scic_remote_device_reset_complete(%p) " + "returned %d!\n", __func__, idev, status); } - /* WHAT TO DO HERE IF sas_phy_reset FAILS? */ - spin_lock_irqsave(&isci_host->scic_lock, flags); - status = scic_remote_device_reset_complete(&isci_dev->sci); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev); - if (status != SCI_SUCCESS) { - scmd_printk(KERN_WARNING, cmd, - "%s: scic_remote_device_reset_complete(%p) " - "returned %d!\n", - __func__, isci_dev, status); - } - /* WHAT TO DO HERE IF scic_remote_device_reset_complete FAILS? */ + return rc; +} - dev_dbg(&isci_host->pdev->dev, - "%s: cmd %p, isci_dev %p complete.\n", - __func__, cmd, isci_dev); +int isci_task_I_T_nexus_reset(struct domain_device *dev) +{ + struct isci_host *ihost = dev_to_ihost(dev); + int ret = TMF_RESP_FUNC_FAILED, hard_reset = 1; + struct isci_remote_device *idev; + unsigned long flags; + + /* XXX mvsas is not protecting against ->lldd_dev_gone(), are we + * being too paranoid, or is mvsas busted?! + */ + spin_lock_irqsave(&ihost->scic_lock, flags); + idev = dev->lldd_dev; + if (!idev || !test_bit(IDEV_EH, &idev->flags)) + ret = TMF_RESP_FUNC_COMPLETE; + spin_unlock_irqrestore(&ihost->scic_lock, flags); + + if (ret == TMF_RESP_FUNC_COMPLETE) + return ret; + + if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) + hard_reset = 0; + + return isci_reset_device(dev, hard_reset); +} + +int isci_bus_reset_handler(struct scsi_cmnd *cmd) +{ + struct domain_device *dev = sdev_to_domain_dev(cmd->device); + int hard_reset = 1; + + if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) + hard_reset = 0; - return TMF_RESP_FUNC_COMPLETE; + return isci_reset_device(dev, hard_reset); } -- cgit v1.2.3 From cc3dbd0a9178865d4444f8e28b51715808e9ac85 Mon Sep 17 00:00:00 2001 From: Artur Wojcik Date: Wed, 4 May 2011 07:58:16 +0000 Subject: isci: unify isci_host data structures Make it explicit that isci_host and scic_sds_controller are one in the same object. Signed-off-by: Artur Wojcik [removed ->ihost back pointer] Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 22 +++------- drivers/scsi/isci/core/scic_sds_controller.h | 6 --- drivers/scsi/isci/core/scic_sds_phy.c | 6 +-- drivers/scsi/isci/core/scic_sds_port.c | 34 ++++++--------- .../isci/core/scic_sds_port_configuration_agent.c | 9 +--- drivers/scsi/isci/core/scic_sds_request.c | 2 +- drivers/scsi/isci/host.c | 51 ++++++++-------------- drivers/scsi/isci/host.h | 12 ++++- drivers/scsi/isci/init.c | 4 +- drivers/scsi/isci/phy.c | 5 +-- drivers/scsi/isci/phy.h | 2 - drivers/scsi/isci/port.c | 29 +----------- drivers/scsi/isci/port.h | 5 --- drivers/scsi/isci/remote_device.c | 30 ++++++------- drivers/scsi/isci/request.c | 6 +-- drivers/scsi/isci/sci_environment.h | 4 +- drivers/scsi/isci/task.c | 15 +++---- drivers/scsi/isci/task.h | 4 +- 18 files changed, 83 insertions(+), 163 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 3fe73cbc0524..ea510411460c 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -214,7 +214,7 @@ static void scic_sds_controller_power_control_timer_handler( static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) { - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); scic->power_control.timer = isci_timer_create(ihost, scic, scic_sds_controller_power_control_timer_handler); @@ -585,7 +585,7 @@ static void scic_sds_controller_transition_to_ready( struct scic_sds_controller *scic, enum sci_status status) { - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); if (scic->state_machine.current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) { @@ -603,7 +603,7 @@ static void scic_sds_controller_transition_to_ready( static void scic_sds_controller_timeout_handler(void *_scic) { struct scic_sds_controller *scic = _scic; - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); struct sci_base_state_machine *sm = &scic->state_machine; if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) @@ -771,7 +771,7 @@ static void scic_sds_controller_phy_startup_timeout_handler(void *_scic) static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic) { - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); scic->phy_startup_timer = isci_timer_create(ihost, scic, @@ -1775,7 +1775,7 @@ void scic_sds_controller_release_frame( */ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) { - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); u16 index; /* Default to APC mode. */ @@ -2619,17 +2619,12 @@ static enum sci_status scic_controller_set_interrupt_coalescence( } -struct scic_sds_controller *scic_controller_alloc(struct device *dev) -{ - return devm_kzalloc(dev, sizeof(struct scic_sds_controller), GFP_KERNEL); -} -enum sci_status scic_controller_initialize( - struct scic_sds_controller *scic) +enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) { struct sci_base_state_machine *sm = &scic->state_machine; enum sci_status result = SCI_SUCCESS; - struct isci_host *ihost; + struct isci_host *ihost = scic_to_ihost(scic); u32 index, state; if (scic->state_machine.current_state_id != @@ -2640,9 +2635,6 @@ enum sci_status scic_controller_initialize( return SCI_FAILURE_INVALID_STATE; } - - ihost = scic->ihost; - sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); scic->timeout_timer = isci_timer_create(ihost, diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 08aee06c124d..0a9bb8b77256 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -125,18 +125,12 @@ struct scic_power_control { }; -struct isci_host; /** * struct scic_sds_controller - * * This structure represents the SCU controller object. */ struct scic_sds_controller { - /** - * The field specifies that the peer object for the controller. - */ - struct isci_host *ihost; - /** * This field contains the information for the base controller state * machine. diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 18dc14a8f0ba..8f1e3db6bb2e 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -339,7 +339,7 @@ enum sci_status scic_sds_phy_initialize( struct scu_link_layer_registers __iomem *link_layer_registers) { struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); /* Create the SIGNATURE FIS Timeout timer for this phy */ sci_phy->sata_timeout_timer = @@ -1790,7 +1790,7 @@ scic_sds_phy_stopped_state_start_handler(struct scic_sds_phy *sci_phy) struct scic_sds_controller *scic; scic = scic_sds_phy_get_controller(sci_phy), - ihost = scic->ihost; + ihost = scic_to_ihost(scic); /* Create the SIGNATURE FIS Timeout timer for this phy */ sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, @@ -2076,7 +2076,7 @@ static void scic_sds_phy_stopped_state_enter(void *object) { struct scic_sds_phy *sci_phy = object; struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); /* * @todo We need to get to the controller to place this PE in a diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 0c89fc1c09f8..04a56c5a68d9 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -625,7 +625,7 @@ static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, bool do_notify_user) { struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) scic_sds_phy_resume(sci_phy); @@ -644,7 +644,7 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, { struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_port *iport = sci_port->iport; - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); struct isci_phy *iphy = sci_phy->iphy; sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); @@ -667,12 +667,10 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, * This function will disable the phy and report that the phy is not valid for * this port object. None */ -static void scic_sds_port_invalid_link_up( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) +static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - struct scic_sds_controller *scic = - scic_sds_port_get_controller(sci_port); + struct scic_sds_controller *scic = sci_port->owning_controller; /* * Check to see if we have alreay reported this link as bad and if @@ -681,7 +679,7 @@ static void scic_sds_port_invalid_link_up( */ if ((scic->invalid_phy_mask & (1 << sci_phy->phy_index)) == 0) { scic_sds_controller_set_invalid_phy(scic, sci_phy); - isci_port_invalid_link_up(scic, sci_port, sci_phy); + dev_warn(&scic_to_ihost(scic)->pdev->dev, "Invalid link up!\n"); } } @@ -971,7 +969,7 @@ void scic_sds_port_broadcast_change_received( struct scic_sds_phy *sci_phy) { struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); /* notify the user. */ isci_port_bc_change_received(ihost, sci_port, sci_phy); @@ -1625,7 +1623,7 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) struct scic_sds_port *sci_port = object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port->iport; scic_sds_port_set_ready_state_handlers( @@ -1666,7 +1664,7 @@ static void scic_sds_port_ready_substate_operational_exit(void *object) struct scic_sds_port *sci_port = object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port->iport; /* @@ -1697,7 +1695,7 @@ static void scic_sds_port_ready_substate_configuring_enter(void *object) struct scic_sds_port *sci_port = object; struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port->iport; scic_sds_port_set_ready_state_handlers( @@ -1784,7 +1782,7 @@ static enum sci_status scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); enum sci_status status = SCI_SUCCESS; u32 phy_mask; @@ -2259,16 +2257,12 @@ static void scic_sds_port_stopped_state_exit(void *object) */ static void scic_sds_port_ready_state_enter(void *object) { - struct scic_sds_controller *scic; struct scic_sds_port *sci_port = object; - struct isci_port *iport; - struct isci_host *ihost; + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + struct isci_port *iport = sci_port->iport; u32 prev_state; - scic = scic_sds_port_get_controller(sci_port); - ihost = scic->ihost; - iport = sci_port->iport; - /* Put the ready state handlers in place though they will not be there long */ scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_READY); diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index df257ffa0f84..6b1f4a0ad990 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -808,20 +808,13 @@ void scic_sds_port_configuration_agent_construct( } } -/** - * - * @controller: This is the controller object for which the port agent is being - * initialized. - * - * This method will construct the port configuration agent for this controller. - */ enum sci_status scic_sds_port_configuration_agent_initialize( struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent) { enum sci_status status = SCI_SUCCESS; enum scic_port_configuration_mode mode; - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); mode = scic->oem_parameters.sds1.controller.mode_type; diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 85e40ce96e96..6286decd62e5 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -1545,7 +1545,7 @@ static void scic_sds_request_completed_state_enter(void *object) struct scic_sds_request *sci_req = object; struct scic_sds_controller *scic = scic_sds_request_get_controller(sci_req); - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); struct isci_request *ireq = sci_req->ireq; SET_STATE_HANDLER(sci_req, diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 55bfa3dbfb8f..d180ad8a8bcf 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -65,9 +65,8 @@ irqreturn_t isci_msix_isr(int vec, void *data) { struct isci_host *ihost = data; - struct scic_sds_controller *scic = ihost->core_controller; - if (scic_sds_controller_isr(scic)) + if (scic_sds_controller_isr(&ihost->sci)) tasklet_schedule(&ihost->completion_tasklet); return IRQ_HANDLED; @@ -77,7 +76,7 @@ irqreturn_t isci_intx_isr(int vec, void *data) { irqreturn_t ret = IRQ_NONE; struct isci_host *ihost = data; - struct scic_sds_controller *scic = ihost->core_controller; + struct scic_sds_controller *scic = &ihost->sci; if (scic_sds_controller_isr(scic)) { writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); @@ -96,10 +95,9 @@ irqreturn_t isci_intx_isr(int vec, void *data) irqreturn_t isci_error_isr(int vec, void *data) { struct isci_host *ihost = data; - struct scic_sds_controller *scic = ihost->core_controller; - if (scic_sds_controller_error_isr(scic)) - scic_sds_controller_error_handler(scic); + if (scic_sds_controller_error_isr(&ihost->sci)) + scic_sds_controller_error_handler(&ihost->sci); return IRQ_HANDLED; } @@ -145,21 +143,20 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) void isci_host_scan_start(struct Scsi_Host *shost) { struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha; - struct scic_sds_controller *scic = ihost->core_controller; - unsigned long tmo = scic_controller_get_suggested_start_timeout(scic); + unsigned long tmo = scic_controller_get_suggested_start_timeout(&ihost->sci); set_bit(IHOST_START_PENDING, &ihost->flags); spin_lock_irq(&ihost->scic_lock); - scic_controller_start(scic, tmo); - scic_controller_enable_interrupts(scic); + scic_controller_start(&ihost->sci, tmo); + scic_controller_enable_interrupts(&ihost->sci); spin_unlock_irq(&ihost->scic_lock); } void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) { isci_host_change_state(ihost, isci_stopped); - scic_controller_disable_interrupts(ihost->core_controller); + scic_controller_disable_interrupts(&ihost->sci); clear_bit(IHOST_STOP_PENDING, &ihost->flags); wake_up(&ihost->eventq); } @@ -188,7 +185,7 @@ static void isci_host_completion_routine(unsigned long data) spin_lock_irq(&isci_host->scic_lock); - scic_sds_controller_completion_handler(isci_host->core_controller); + scic_sds_controller_completion_handler(&isci_host->sci); /* Take the lists of completed I/Os from the host. */ @@ -276,7 +273,6 @@ static void isci_host_completion_routine(unsigned long data) void isci_host_deinit(struct isci_host *ihost) { - struct scic_sds_controller *scic = ihost->core_controller; int i; isci_host_change_state(ihost, isci_stopping); @@ -293,11 +289,11 @@ void isci_host_deinit(struct isci_host *ihost) set_bit(IHOST_STOP_PENDING, &ihost->flags); spin_lock_irq(&ihost->scic_lock); - scic_controller_stop(scic, SCIC_CONTROLLER_STOP_TIMEOUT); + scic_controller_stop(&ihost->sci, SCIC_CONTROLLER_STOP_TIMEOUT); spin_unlock_irq(&ihost->scic_lock); wait_for_stop(ihost); - scic_controller_reset(scic); + scic_controller_reset(&ihost->sci); isci_timer_list_destroy(ihost); } @@ -347,25 +343,12 @@ int isci_host_init(struct isci_host *isci_host) { int err = 0, i; enum sci_status status; - struct scic_sds_controller *controller; union scic_oem_parameters oem; union scic_user_parameters scic_user_params; struct isci_pci_info *pci_info = to_pci_info(isci_host->pdev); isci_timer_list_construct(isci_host); - controller = scic_controller_alloc(&isci_host->pdev->dev); - - if (!controller) { - dev_err(&isci_host->pdev->dev, - "%s: failed (%d)\n", - __func__, - err); - return -ENOMEM; - } - - isci_host->core_controller = controller; - controller->ihost = isci_host; spin_lock_init(&isci_host->state_lock); spin_lock_init(&isci_host->scic_lock); spin_lock_init(&isci_host->queue_lock); @@ -374,7 +357,7 @@ int isci_host_init(struct isci_host *isci_host) isci_host_change_state(isci_host, isci_starting); isci_host->can_queue = ISCI_CAN_QUEUE_VAL; - status = scic_controller_construct(controller, scu_base(isci_host), + status = scic_controller_construct(&isci_host->sci, scu_base(isci_host), smu_base(isci_host)); if (status != SCI_SUCCESS) { @@ -393,7 +376,7 @@ int isci_host_init(struct isci_host *isci_host) * parameters */ isci_user_parameters_get(isci_host, &scic_user_params); - status = scic_user_parameters_set(isci_host->core_controller, + status = scic_user_parameters_set(&isci_host->sci, &scic_user_params); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -402,7 +385,7 @@ int isci_host_init(struct isci_host *isci_host) return -ENODEV; } - scic_oem_parameters_get(controller, &oem); + scic_oem_parameters_get(&isci_host->sci, &oem); /* grab any OEM parameters specified in orom */ if (pci_info->orom) { @@ -416,7 +399,7 @@ int isci_host_init(struct isci_host *isci_host) } } - status = scic_oem_parameters_set(isci_host->core_controller, &oem); + status = scic_oem_parameters_set(&isci_host->sci, &oem); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, "%s: scic_oem_parameters_set failed\n", @@ -431,7 +414,7 @@ int isci_host_init(struct isci_host *isci_host) INIT_LIST_HEAD(&isci_host->requests_to_errorback); spin_lock_irq(&isci_host->scic_lock); - status = scic_controller_initialize(isci_host->core_controller); + status = scic_controller_initialize(&isci_host->sci); spin_unlock_irq(&isci_host->scic_lock); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -441,7 +424,7 @@ int isci_host_init(struct isci_host *isci_host) return -ENODEV; } - err = scic_controller_mem_init(isci_host->core_controller); + err = scic_controller_mem_init(&isci_host->sci); if (err) return err; diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 8dc8d1c46986..00e4854e20d9 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -58,7 +58,7 @@ #define _SCI_HOST_H_ #include "phy.h" -/*#include "task.h"*/ +#include "scic_sds_controller.h" #include "timers.h" #include "remote_device.h" @@ -75,7 +75,7 @@ #define SCIC_CONTROLLER_STOP_TIMEOUT 5000 struct isci_host { - struct scic_sds_controller *core_controller; + struct scic_sds_controller sci; union scic_oem_parameters oem_parameters; int id; /* unique within a given pci device */ @@ -219,6 +219,14 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev) return dev->port->ha->lldd_ha; } +static inline struct isci_host *scic_to_ihost(struct scic_sds_controller *scic) +{ + /* XXX delete after merging scic_sds_contoller and isci_host */ + struct isci_host *ihost = container_of(scic, typeof(*ihost), sci); + + return ihost; +} + /** * isci_host_scan_finished() - * diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 6c2d686fe7c0..a5d5c0b97d00 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -268,7 +268,7 @@ static void isci_unregister(struct isci_host *isci_host) static int __devinit isci_pci_init(struct pci_dev *pdev) { - int err, bar_num, bar_mask; + int err, bar_num, bar_mask = 0; void __iomem * const *iomap; err = pcim_enable_device(pdev); @@ -556,7 +556,7 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev) for_each_isci_host(i, isci_host, pdev) { isci_unregister(isci_host); isci_host_deinit(isci_host); - scic_controller_disable_interrupts(isci_host->core_controller); + scic_controller_disable_interrupts(&isci_host->sci); } } diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index a690b6b664f7..160790a0de0e 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -79,7 +79,6 @@ void isci_phy_init( struct isci_host *isci_host, int index) { - struct scic_sds_controller *scic = isci_host->core_controller; struct scic_sds_phy *scic_phy; union scic_oem_parameters oem; enum sci_status status = SCI_SUCCESS; @@ -87,7 +86,7 @@ void isci_phy_init( /*--------------- SCU_Phy Initialization Stuff -----------------------*/ - status = scic_controller_get_phy_handle(scic, index, &scic_phy); + status = scic_controller_get_phy_handle(&isci_host->sci, index, &scic_phy); if (status == SCI_SUCCESS) { phy->sci_phy_handle = scic_phy; scic_phy->iphy = phy; @@ -95,7 +94,7 @@ void isci_phy_init( dev_err(&isci_host->pdev->dev, "failed scic_controller_get_phy_handle\n"); - scic_oem_parameters_get(scic, &oem); + scic_oem_parameters_get(&isci_host->sci, &oem); sas_addr = oem.sds1.phys[index].sas_address.high; sas_addr <<= 32; sas_addr |= oem.sds1.phys[index].sas_address.low; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index d4c4975546e3..21f6050eadbe 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -85,8 +85,6 @@ struct isci_phy { #define to_isci_phy(p) \ container_of(p, struct isci_phy, sas_phy); -struct isci_host; - void isci_phy_init( struct isci_phy *phy, struct isci_host *isci_host, diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 2decafbeb968..8d96a10341b1 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -90,7 +90,6 @@ void isci_port_init( int index) { struct scic_sds_port *scic_port; - struct scic_sds_controller *controller = isci_host->core_controller; INIT_LIST_HEAD(&isci_port->remote_dev_list); INIT_LIST_HEAD(&isci_port->domain_dev_list); @@ -99,7 +98,7 @@ void isci_port_init( isci_port->isci_host = isci_host; isci_port_change_state(isci_port, isci_freed); - (void)scic_controller_get_port_handle(controller, index, &scic_port); + (void)scic_controller_get_port_handle(&isci_host->sci, index, &scic_port); isci_port->sci_port_handle = scic_port; scic_port->iport = isci_port; } @@ -415,33 +414,9 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor return ret; } -/** - * isci_port_invalid_link_up() - This function informs the SCI Core user that - * a phy/link became ready, but the phy is not allowed in the port. In some - * situations the underlying hardware only allows for certain phy to port - * mappings. If these mappings are violated, then this API is invoked. - * @controller: This parameter represents the controller which contains the - * port. - * @port: This parameter specifies the SCI port object for which the callback - * is being invoked. - * @phy: This parameter specifies the phy that came ready, but the phy can't be - * a valid member of the port. - * - */ -void isci_port_invalid_link_up(struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, - struct scic_sds_phy *phy) -{ - struct isci_host *ihost = scic->ihost; - - dev_warn(&ihost->pdev->dev, "Invalid link up!\n"); -} - void isci_port_stop_complete(struct scic_sds_controller *scic, struct scic_sds_port *sci_port, enum sci_status completion_status) { - struct isci_host *ihost = scic->ihost; - - dev_dbg(&ihost->pdev->dev, "Port stop complete\n"); + dev_dbg(&scic_to_ihost(scic)->pdev->dev, "Port stop complete\n"); } diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index eeac7bbc9430..ac1ac86ead6f 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -147,11 +147,6 @@ void isci_port_hard_reset_complete( int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy); -void isci_port_invalid_link_up( - struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, - struct scic_sds_phy *phy); - void isci_port_stop_complete( struct scic_sds_controller *scic, struct scic_sds_port *sci_port, diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index ee6fe1db8f99..734d028448b0 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -815,7 +815,7 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl * As a result, avoid sending the ready notification. */ if (sci_dev->state_machine.previous_state_id != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) - isci_remote_device_ready(scic->ihost, idev); + isci_remote_device_ready(scic_to_ihost(scic), idev); } static void scic_sds_remote_device_initial_state_enter(void *object) @@ -918,21 +918,16 @@ static void isci_remote_device_stop_complete(struct isci_host *ihost, static void scic_sds_remote_device_stopped_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; - struct scic_sds_controller *scic; - struct isci_remote_device *idev; - struct isci_host *ihost; + struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); u32 prev_state; - scic = scic_sds_remote_device_get_controller(sci_dev); - ihost = scic->ihost; - idev = sci_dev_to_idev(sci_dev); - /* If we are entering from the stopping state let the SCI User know that * the stop operation has completed. */ prev_state = sci_dev->state_machine.previous_state_id; if (prev_state == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) - isci_remote_device_stop_complete(ihost, idev); + isci_remote_device_stop_complete(scic_to_ihost(scic), idev); scic_sds_controller_remote_device_stopped(scic, sci_dev); } @@ -941,7 +936,7 @@ static void scic_sds_remote_device_starting_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_host *ihost = scic->ihost; + struct isci_host *ihost = scic_to_ihost(scic); struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); isci_remote_device_not_ready(ihost, idev, @@ -952,7 +947,8 @@ static void scic_sds_remote_device_ready_state_enter(void *object) { struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); + struct domain_device *dev = idev->domain_dev; scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; @@ -963,7 +959,7 @@ static void scic_sds_remote_device_ready_state_enter(void *object) sci_base_state_machine_change_state(&sci_dev->state_machine, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); } else - isci_remote_device_ready(scic->ihost, sci_dev_to_idev(sci_dev)); + isci_remote_device_ready(scic_to_ihost(scic), idev); } static void scic_sds_remote_device_ready_state_exit(void *object) @@ -975,7 +971,7 @@ static void scic_sds_remote_device_ready_state_exit(void *object) struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - isci_remote_device_not_ready(scic->ihost, idev, + isci_remote_device_not_ready(scic_to_ihost(scic), idev, SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); } } @@ -1019,7 +1015,7 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) BUG_ON(sci_dev->working_request == NULL); - isci_remote_device_not_ready(scic->ihost, sci_dev_to_idev(sci_dev), + isci_remote_device_not_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev), SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } @@ -1030,7 +1026,7 @@ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(void *obje struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); if (sci_dev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) - isci_remote_device_not_ready(scic->ihost, idev, + isci_remote_device_not_ready(scic_to_ihost(scic), idev, sci_dev->not_ready_reason); } @@ -1039,7 +1035,7 @@ static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) struct scic_sds_remote_device *sci_dev = object; struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - isci_remote_device_ready(scic->ihost, sci_dev_to_idev(sci_dev)); + isci_remote_device_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev)); } static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) @@ -1049,7 +1045,7 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) BUG_ON(sci_dev->working_request == NULL); - isci_remote_device_not_ready(scic->ihost, sci_dev_to_idev(sci_dev), + isci_remote_device_not_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev), SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); } diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 36adc1589efa..0521c045d43b 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -201,7 +201,7 @@ static enum sci_status isci_io_request_build( * we will let the core allocate the IO tag. */ status = scic_io_request_construct( - isci_host->core_controller, + &isci_host->sci, sci_device, SCI_CONTROLLER_INVALID_IO_TAG, request, @@ -394,7 +394,7 @@ int isci_request_execute( /* send the request, let the core assign the IO TAG. */ status = scic_controller_start_io( - isci_host->core_controller, + &isci_host->sci, sci_device, request->sci_request_handle, SCI_CONTROLLER_INVALID_IO_TAG @@ -1186,7 +1186,7 @@ void isci_request_io_request_complete( ); /* complete the io request to the core. */ - scic_controller_complete_io(isci_host->core_controller, + scic_controller_complete_io(&isci_host->sci, &isci_device->sci, request->sci_request_handle); /* NULL the request handle so it cannot be completed or diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index 41636c34da9e..8394f60c5c2b 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -62,9 +62,7 @@ static inline struct device *scic_to_dev(struct scic_sds_controller *scic) { - struct isci_host *isci_host = scic->ihost; - - return &isci_host->pdev->dev; + return &scic_to_ihost(scic)->pdev->dev; } static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 3a3f54677e5b..cabad0b03ee5 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -299,7 +299,7 @@ static enum sci_status isci_task_request_build( /* let the core do it's construct. */ status = scic_task_request_construct( - isci_host->core_controller, + &isci_host->sci, sci_device, SCI_CONTROLLER_INVALID_IO_TAG, request, @@ -378,7 +378,7 @@ static void isci_tmf_timeout_cb(void *tmf_request_arg) /* Terminate the TMF transmit request. */ status = scic_controller_terminate_request( - request->isci_host->core_controller, + &request->isci_host->sci, &request->isci_device->sci, request->sci_request_handle ); @@ -469,7 +469,7 @@ int isci_task_execute_tmf( /* start the TMF io. */ status = scic_controller_start_task( - isci_host->core_controller, + &isci_host->sci, sci_device, request->sci_request_handle, SCI_CONTROLLER_INVALID_IO_TAG @@ -772,7 +772,7 @@ static void isci_terminate_request_core( was_terminated = true; needs_cleanup_handling = true; status = scic_controller_terminate_request( - isci_host->core_controller, + &isci_host->sci, &isci_device->sci, isci_request->sci_request_handle); } @@ -1466,12 +1466,9 @@ isci_task_request_complete(struct isci_host *ihost, /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; - scic_controller_complete_io(ihost->core_controller, - &idev->sci, + scic_controller_complete_io(&ihost->sci, &idev->sci, ireq->sci_request_handle); - - /* - * NULL the request handle to make sure it cannot be terminated + /* NULL the request handle to make sure it cannot be terminated * or completed again. */ ireq->sci_request_handle = NULL; diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index aa2458658d1e..ecc5f1395063 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -52,14 +52,12 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#if !defined(_ISCI_TASK_H_) +#ifndef _ISCI_TASK_H_ #define _ISCI_TASK_H_ #include struct isci_request; -struct isci_host; /** * enum isci_tmf_cb_state - This enum defines the possible states in which the -- cgit v1.2.3 From 9286a1959ce7f3df3c1a8e33eb9b210078318dc8 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Fri, 6 May 2011 02:17:37 +0000 Subject: isci: Removing unnecessary functions in request.c No need for wrappers, just access sas_task directly. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_request.c | 24 +++++++++++----------- drivers/scsi/isci/request.c | 34 ------------------------------- drivers/scsi/isci/request.h | 25 ----------------------- 3 files changed, 12 insertions(+), 71 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 6286decd62e5..52692a16449d 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -666,19 +666,20 @@ u32 scic_io_request_get_object_size(void) enum sci_status scic_io_request_construct_basic_ssp( struct scic_sds_request *sci_req) { - struct isci_request *isci_request = sci_req->ireq; + struct isci_request *ireq = sci_req->ireq; + struct sas_task *task = isci_request_access_task(ireq); sci_req->protocol = SCIC_SSP_PROTOCOL; - scu_ssp_io_request_construct_task_context( - sci_req, - isci_request_io_request_get_data_direction(isci_request), - isci_request_io_request_get_transfer_length(isci_request)); + scu_ssp_io_request_construct_task_context(sci_req, + task->data_dir, + task->total_xfer_len); scic_sds_io_request_build_ssp_command_iu(sci_req); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return SCI_SUCCESS; } @@ -705,8 +706,6 @@ enum sci_status scic_io_request_construct_basic_sata( { enum sci_status status; struct scic_sds_stp_request *stp_req; - u32 len; - enum dma_data_direction dir; bool copy = false; struct isci_request *isci_request = sci_req->ireq; struct sas_task *task = isci_request_access_task(isci_request); @@ -715,11 +714,12 @@ enum sci_status scic_io_request_construct_basic_sata( sci_req->protocol = SCIC_STP_PROTOCOL; - len = isci_request_io_request_get_transfer_length(isci_request); - dir = isci_request_io_request_get_data_direction(isci_request); copy = (task->data_dir == DMA_NONE) ? false : true; - status = scic_io_request_construct_sata(sci_req, len, dir, copy); + status = scic_io_request_construct_sata(sci_req, + task->total_xfer_len, + task->data_dir, + copy); if (status == SCI_SUCCESS) sci_base_state_machine_change_state(&sci_req->state_machine, diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 0521c045d43b..e01c2c98f4e9 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1197,37 +1197,3 @@ void isci_request_io_request_complete( isci_host_can_dequeue(isci_host, 1); } - -/** - * isci_request_io_request_get_transfer_length() - This function is called by - * the sci core to retrieve the transfer length for a given request. - * @request: This parameter is the isci_request object. - * - * length of transfer for specified request. - */ -u32 isci_request_io_request_get_transfer_length(struct isci_request *request) -{ - struct sas_task *task = isci_request_access_task(request); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: total_xfer_len: %d\n", - __func__, - task->total_xfer_len); - return task->total_xfer_len; -} - - -/** - * isci_request_io_request_get_data_direction() - This function is called by - * the sci core to retrieve the data direction for a given request. - * @request: This parameter is the isci_request object. - * - * data direction for specified request. - */ -enum dma_data_direction isci_request_io_request_get_data_direction( - struct isci_request *request) -{ - struct sas_task *task = isci_request_access_task(request); - - return task->data_dir; -} diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 642b21166fc6..9c97715e54d8 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -343,11 +343,6 @@ void isci_request_io_request_complete( struct isci_request *request, enum sci_io_status completion_status); -u32 isci_request_io_request_get_transfer_length( - struct isci_request *request); - -enum dma_data_direction isci_request_io_request_get_data_direction(struct isci_request *req); - /** * isci_request_io_request_get_next_sge() - This function is called by the sci * core to retrieve the next sge for a given request. @@ -391,26 +386,6 @@ static inline void *isci_request_io_request_get_next_sge( } - -void *isci_request_ssp_io_request_get_cdb_address( - struct isci_request *request); - -u32 isci_request_ssp_io_request_get_cdb_length( - struct isci_request *request); - -u32 isci_request_ssp_io_request_get_lun( - struct isci_request *request); - -u32 isci_request_ssp_io_request_get_task_attribute( - struct isci_request *request); - -u32 isci_request_ssp_io_request_get_command_priority( - struct isci_request *request); - - - - - void isci_terminate_pending_requests( struct isci_host *isci_host, struct isci_remote_device *isci_device, -- cgit v1.2.3 From ed30c275dd9fc5c603081144db5df3110f258534 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 5 May 2011 01:11:43 +0000 Subject: isci: kill scic_controller_get_port_handle function This function is just overkill and its usage is inconsistent. Replace with inlined code. Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_controller.h | 5 --- drivers/scsi/isci/core/scic_sds_controller.c | 30 ------------------ .../isci/core/scic_sds_port_configuration_agent.c | 31 +++++++----------- drivers/scsi/isci/port.c | 37 ++++++++-------------- 4 files changed, 25 insertions(+), 78 deletions(-) diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 23c7b5c004f4..50ba155a6c7c 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -120,11 +120,6 @@ enum sci_status scic_controller_complete_io( struct scic_sds_remote_device *remote_device, struct scic_sds_request *io_request); -enum sci_status scic_controller_get_port_handle( - struct scic_sds_controller *controller, - u8 port_index, - struct scic_sds_port **port_handle); - enum sci_status scic_controller_get_phy_handle( struct scic_sds_controller *controller, u8 phy_index, diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index ea510411460c..b59548254e24 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -2154,36 +2154,6 @@ enum sci_task_status scic_controller_start_task( return status; } -/** - * scic_controller_get_port_handle() - This method simply provides the user - * with a unique handle for a given SAS/SATA core port index. - * @controller: This parameter represents the handle to the controller object - * from which to retrieve a port (SAS or SATA) handle. - * @port_index: This parameter specifies the port index in the controller for - * which to retrieve the port handle. 0 <= port_index < maximum number of - * phys. - * @port_handle: This parameter specifies the retrieved port handle to be - * provided to the caller. - * - * Indicate if the retrieval of the port handle was successful. SCI_SUCCESS - * This value is returned if the retrieval was successful. - * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port id is - * not in the supported range. - */ -enum sci_status scic_controller_get_port_handle( - struct scic_sds_controller *scic, - u8 port_index, - struct scic_sds_port **port_handle) -{ - if (port_index < scic->logical_port_entries) { - *port_handle = &scic->port_table[port_index]; - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_PORT; -} - /** * scic_controller_get_phy_handle() - This method simply provides the user with * a unique handle for a given SAS/SATA phy index/identifier. diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index 6b1f4a0ad990..6b2fb445a8f7 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -123,11 +123,10 @@ static s32 sci_sas_address_compare( * NULL if there is no matching port for the phy. */ static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( - struct scic_sds_controller *controller, + struct scic_sds_controller *scic, struct scic_sds_phy *phy) { - u8 port_index; - struct scic_sds_port *port_handle; + u8 i; struct sci_sas_address port_sas_address; struct sci_sas_address port_attached_device_address; struct sci_sas_address phy_sas_address; @@ -136,24 +135,20 @@ static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( /* * Since this phy can be a member of a wide port check to see if one or * more phys match the sent and received SAS address as this phy in which - * case it should participate in the same port. */ + * case it should participate in the same port. + */ scic_sds_phy_get_sas_address(phy, &phy_sas_address); scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); - for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { - if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS) { - struct scic_sds_port *port = (struct scic_sds_port *)port_handle; + for (i = 0; i < scic->logical_port_entries; i++) { + struct scic_sds_port *port = &scic->port_table[i]; - scic_sds_port_get_sas_address(port, &port_sas_address); - scic_sds_port_get_attached_sas_address(port, &port_attached_device_address); + scic_sds_port_get_sas_address(port, &port_sas_address); + scic_sds_port_get_attached_sas_address(port, &port_attached_device_address); - if ( - (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0) - && (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) - ) { - return port; - } - } + if ((sci_sas_address_compare(port_sas_address, phy_sas_address) == 0) && + (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0)) + return port; } return NULL; @@ -568,7 +563,6 @@ static void scic_sds_apc_agent_configure_ports( u8 port_index; enum sci_status status; struct scic_sds_port *port; - struct scic_sds_port *port_handle; enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; port = scic_sds_port_configuration_agent_find_port(controller, phy); @@ -590,9 +584,8 @@ static void scic_sds_apc_agent_configure_ports( port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index; port_index++ ) { - scic_controller_get_port_handle(controller, port_index, &port_handle); - port = (struct scic_sds_port *)port_handle; + port = &controller->port_table[port_index]; /* First we must make sure that this PHY can be added to this Port. */ if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) { diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 8d96a10341b1..6110306e8e23 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -76,31 +76,20 @@ static void isci_port_change_state( -/** - * isci_port_init() - This function initializes the given isci_port object. - * @isci_port: This parameter specifies the port object to be initialized. - * @isci_host: This parameter specifies parent controller object for the port. - * @index: This parameter specifies which SCU port the isci_port associates - * with. Generally, SCU port 0 relates to isci_port 0, etc. - * - */ -void isci_port_init( - struct isci_port *isci_port, - struct isci_host *isci_host, - int index) +void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index) { - struct scic_sds_port *scic_port; - - INIT_LIST_HEAD(&isci_port->remote_dev_list); - INIT_LIST_HEAD(&isci_port->domain_dev_list); - spin_lock_init(&isci_port->state_lock); - init_completion(&isci_port->start_complete); - isci_port->isci_host = isci_host; - isci_port_change_state(isci_port, isci_freed); - - (void)scic_controller_get_port_handle(&isci_host->sci, index, &scic_port); - isci_port->sci_port_handle = scic_port; - scic_port->iport = isci_port; + struct scic_sds_port *sci_port; + + INIT_LIST_HEAD(&iport->remote_dev_list); + INIT_LIST_HEAD(&iport->domain_dev_list); + spin_lock_init(&iport->state_lock); + init_completion(&iport->start_complete); + iport->isci_host = ihost; + isci_port_change_state(iport, isci_freed); + + sci_port = &ihost->sci.port_table[index]; + iport->sci_port_handle = sci_port; + sci_port->iport = iport; } -- cgit v1.2.3 From b9988b8e7fcd80404c60462dc223df8c1f31550d Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 5 May 2011 01:11:49 +0000 Subject: isci: remove scic_sds_port_increment_request_count Removes excessive encapsulation function. Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_port.c | 3 +-- drivers/scsi/isci/core/scic_sds_port.h | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 04a56c5a68d9..e1c873406e50 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -1232,8 +1232,7 @@ static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler struct scic_sds_remote_device *device, struct scic_sds_request *io_request) { - scic_sds_port_increment_request_count(port); - + port->started_request_count++; return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 115cbe3129a8..213d42330b4b 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -359,11 +359,6 @@ struct scic_sds_port_state_handler { ((this_port)->physical_port_index) -static inline void scic_sds_port_increment_request_count(struct scic_sds_port *sci_port) -{ - sci_port->started_request_count++; -} - static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) { if (WARN_ONCE(sci_port->started_request_count == 0, -- cgit v1.2.3 From a98a7426bc91700ac8613701daf8470efe2ad2d2 Mon Sep 17 00:00:00 2001 From: Jacek Danecki Date: Tue, 3 May 2011 04:21:07 +0000 Subject: isci: rnc state machine table c99 conversion This makes the subsequent patches to delete rnc->state_handler more clear. Signed-off-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_node_context.c | 124 +++++++++++++++----------------- drivers/scsi/isci/remote_node_context.h | 5 +- 2 files changed, 58 insertions(+), 71 deletions(-) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 49d2dc5374f4..5e85a18a06de 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -788,80 +788,70 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_event /* --------------------------------------------------------------------------- */ static struct scic_sds_remote_node_context_handlers -scic_sds_remote_node_context_state_handler_table[ - SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] = -{ - /* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */ - { - scic_sds_remote_node_context_default_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_initial_state_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_default_start_task_handler, - scic_sds_remote_node_context_default_event_handler +scic_sds_remote_node_context_state_handler_table[] = { + [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { + .destruct_handler = scic_sds_remote_node_context_default_destruct_handler, + .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, + .resume_handler = scic_sds_remote_node_context_initial_state_resume_handler, + .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, + .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, + .event_handler = scic_sds_remote_node_context_default_event_handler }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_continue_to_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_default_start_task_handler, - scic_sds_remote_node_context_posting_state_event_handler + [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { + .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, + .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, + .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, + .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, + .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, + .event_handler = scic_sds_remote_node_context_posting_state_event_handler }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */ - { - scic_sds_remote_node_context_invalidating_state_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_continue_to_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_default_start_task_handler, - scic_sds_remote_node_context_invalidating_state_event_handler + [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { + .destruct_handler = scic_sds_remote_node_context_invalidating_state_destruct_handler, + .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, + .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, + .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, + .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, + .event_handler = scic_sds_remote_node_context_invalidating_state_event_handler }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_continue_to_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_success_start_task_handler, - scic_sds_remote_node_context_resuming_state_event_handler + [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { + .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, + .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, + .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, + .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, + .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, + .event_handler = scic_sds_remote_node_context_resuming_state_event_handler }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_ready_state_suspend_handler, - scic_sds_remote_node_context_default_resume_handler, - scic_sds_remote_node_context_ready_state_start_io_handler, - scic_sds_remote_node_context_success_start_task_handler, - scic_sds_remote_node_context_ready_state_event_handler + [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { + .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, + .suspend_handler = scic_sds_remote_node_context_ready_state_suspend_handler, + .resume_handler = scic_sds_remote_node_context_default_resume_handler, + .start_io_handler = scic_sds_remote_node_context_ready_state_start_io_handler, + .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, + .event_handler = scic_sds_remote_node_context_ready_state_event_handler }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_tx_suspended_state_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_suspended_start_task_handler, - scic_sds_remote_node_context_default_event_handler + [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { + .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, + .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, + .resume_handler = scic_sds_remote_node_context_tx_suspended_state_resume_handler, + .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, + .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, + .event_handler = scic_sds_remote_node_context_default_event_handler }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_suspended_start_task_handler, - scic_sds_remote_node_context_default_event_handler + [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { + .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, + .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, + .resume_handler = scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, + .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, + .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, + .event_handler = scic_sds_remote_node_context_default_event_handler }, - /* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */ - { - scic_sds_remote_node_context_general_destruct_handler, - scic_sds_remote_node_context_default_suspend_handler, - scic_sds_remote_node_context_await_suspension_state_resume_handler, - scic_sds_remote_node_context_default_start_io_handler, - scic_sds_remote_node_context_await_suspension_state_start_task_handler, - scic_sds_remote_node_context_await_suspension_state_event_handler + [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { + .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, + .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, + .resume_handler = scic_sds_remote_node_context_await_suspension_state_resume_handler, + .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, + .start_task_handler = scic_sds_remote_node_context_await_suspension_state_start_task_handler, + .event_handler = scic_sds_remote_node_context_await_suspension_state_event_handler } }; diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index bc7914beb0c5..540a49a9c94d 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -201,10 +201,7 @@ enum scis_sds_remote_node_context_states { * there is a request to supend the remote node context or when there is a TC * completion where the remote node will be suspended by the hardware. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE, - - SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES - + SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE }; /** -- cgit v1.2.3 From 4b33981ade7cf723f3f32809e34192376c9a10f8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 6 May 2011 17:36:38 -0700 Subject: isci: unify phy data structures Make scic_sds_phy a member of isci_phy and merge their lifetimes which means removing the phy table from scic_sds_controller in favor of the one at that isci_host level. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 100 +++------- drivers/scsi/isci/core/scic_sds_controller.h | 6 - drivers/scsi/isci/core/scic_sds_phy.c | 6 +- drivers/scsi/isci/core/scic_sds_phy.h | 6 - drivers/scsi/isci/core/scic_sds_port.c | 2 +- .../isci/core/scic_sds_port_configuration_agent.c | 209 ++++++++++----------- drivers/scsi/isci/phy.c | 86 +++------ drivers/scsi/isci/phy.h | 41 ++-- drivers/scsi/isci/port.c | 42 ++--- drivers/scsi/isci/sci_environment.h | 2 +- 10 files changed, 187 insertions(+), 313 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index b59548254e24..4ad31550c8ae 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -673,6 +673,7 @@ static void scic_sds_controller_phy_timer_stop(struct scic_sds_controller *scic) */ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic) { + struct isci_host *ihost = scic_to_ihost(scic); struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; struct scic_sds_phy *sci_phy; enum sci_status status; @@ -688,7 +689,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro u8 index; for (index = 0; index < SCI_MAX_PHYS; index++) { - sci_phy = &scic->phy_table[index]; + sci_phy = &ihost->phys[index].sci; state = sci_phy->state_machine.current_state_id; if (!scic_sds_phy_get_port(sci_phy)) @@ -719,7 +720,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro scic_sds_controller_phy_timer_stop(scic); } } else { - sci_phy = &scic->phy_table[scic->next_phy_to_start]; + sci_phy = &ihost->phys[scic->next_phy_to_start].sci; if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { if (scic_sds_phy_get_port(sci_phy) == NULL) { @@ -748,7 +749,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro "to stop phy %d because of status " "%d.\n", __func__, - scic->phy_table[scic->next_phy_to_start].phy_index, + ihost->phys[scic->next_phy_to_start].sci.phy_index, status); } @@ -792,23 +793,22 @@ static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller u32 index; enum sci_status status; enum sci_status phy_status; + struct isci_host *ihost = scic_to_ihost(scic); status = SCI_SUCCESS; for (index = 0; index < SCI_MAX_PHYS; index++) { - phy_status = scic_sds_phy_stop(&scic->phy_table[index]); + phy_status = scic_sds_phy_stop(&ihost->phys[index].sci); - if ( - (phy_status != SCI_SUCCESS) - && (phy_status != SCI_FAILURE_INVALID_STATE) - ) { + if (phy_status != SCI_SUCCESS && + phy_status != SCI_FAILURE_INVALID_STATE) { status = SCI_FAILURE; dev_warn(scic_to_dev(scic), "%s: Controller stop operation failed to stop " "phy %d because of status %d.\n", __func__, - scic->phy_table[index].phy_index, phy_status); + ihost->phys[index].sci.phy_index, phy_status); } } @@ -1069,21 +1069,13 @@ static void scic_sds_controller_sdma_completion( } } -/** - * - * @scic: - * @completion_entry: - * - * This method processes an unsolicited frame message. This is called from - * within the controller completion handler. none - */ -static void scic_sds_controller_unsolicited_frame( - struct scic_sds_controller *scic, - u32 completion_entry) +static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *scic, + u32 completion_entry) { u32 index; u32 frame_index; + struct isci_host *ihost = scic_to_ihost(scic); struct scu_unsolicited_frame_header *frame_header; struct scic_sds_phy *phy; struct scic_sds_remote_device *device; @@ -1092,10 +1084,8 @@ static void scic_sds_controller_unsolicited_frame( frame_index = SCU_GET_FRAME_INDEX(completion_entry); - frame_header - = scic->uf_control.buffers.array[frame_index].header; - scic->uf_control.buffers.array[frame_index].state - = UNSOLICITED_FRAME_IN_USE; + frame_header = scic->uf_control.buffers.array[frame_index].header; + scic->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE; if (SCU_GET_FRAME_ERROR(completion_entry)) { /* @@ -1108,10 +1098,8 @@ static void scic_sds_controller_unsolicited_frame( if (frame_header->is_address_frame) { index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &scic->phy_table[index]; - if (phy != NULL) { - result = scic_sds_phy_frame_handler(phy, frame_index); - } + phy = &ihost->phys[index].sci; + result = scic_sds_phy_frame_handler(phy, frame_index); } else { index = SCU_GET_COMPLETION_INDEX(completion_entry); @@ -1122,7 +1110,7 @@ static void scic_sds_controller_unsolicited_frame( * device that has not yet been created. In either case forwared * the frame to the PE and let it take care of the frame data. */ index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &scic->phy_table[index]; + phy = &ihost->phys[index].sci; result = scic_sds_phy_frame_handler(phy, frame_index); } else { if (index < scic->remote_node_entries) @@ -1144,21 +1132,14 @@ static void scic_sds_controller_unsolicited_frame( } } -/** - * This method processes an event completion entry. This is called from within - * the controller completion handler. - * @scic: - * @completion_entry: - * - */ -static void scic_sds_controller_event_completion( - struct scic_sds_controller *scic, - u32 completion_entry) +static void scic_sds_controller_event_completion(struct scic_sds_controller *scic, + u32 completion_entry) { - u32 index; + struct isci_host *ihost = scic_to_ihost(scic); struct scic_sds_request *io_request; struct scic_sds_remote_device *device; struct scic_sds_phy *phy; + u32 index; index = SCU_GET_COMPLETION_INDEX(completion_entry); @@ -1237,7 +1218,7 @@ static void scic_sds_controller_event_completion( * we get the event notification. This is a type 4 event. */ case SCU_EVENT_TYPE_OSSP_EVENT: index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &scic->phy_table[index]; + phy = &ihost->phys[index].sci; scic_sds_phy_event_handler(phy, completion_entry); break; @@ -2154,38 +2135,6 @@ enum sci_task_status scic_controller_start_task( return status; } -/** - * scic_controller_get_phy_handle() - This method simply provides the user with - * a unique handle for a given SAS/SATA phy index/identifier. - * @controller: This parameter represents the handle to the controller object - * from which to retrieve a phy (SAS or SATA) handle. - * @phy_index: This parameter specifies the phy index in the controller for - * which to retrieve the phy handle. 0 <= phy_index < maximum number of phys. - * @phy_handle: This parameter specifies the retrieved phy handle to be - * provided to the caller. - * - * Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This - * value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY - * This value is returned if the supplied phy id is not in the supported range. - */ -enum sci_status scic_controller_get_phy_handle( - struct scic_sds_controller *scic, - u8 phy_index, - struct scic_sds_phy **phy_handle) -{ - if (phy_index < ARRAY_SIZE(scic->phy_table)) { - *phy_handle = &scic->phy_table[phy_index]; - - return SCI_SUCCESS; - } - - dev_err(scic_to_dev(scic), - "%s: Controller:0x%p PhyId:0x%x invalid phy index\n", - __func__, scic, phy_index); - - return SCI_FAILURE_INVALID_PHY; -} - /** * scic_controller_allocate_io_tag() - This method will allocate a tag from the * pool of free IO tags. Direct allocation of IO tags by the SCI Core user @@ -2724,7 +2673,7 @@ enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS); index++) { result = scic_sds_phy_initialize( - &scic->phy_table[index], + &ihost->phys[index].sci, &scic->scu_registers->peg0.pe[index].tl, &scic->scu_registers->peg0.pe[index].ll); } @@ -2979,6 +2928,7 @@ enum sci_status scic_controller_construct(struct scic_sds_controller *scic, void __iomem *scu_base, void __iomem *smu_base) { + struct isci_host *ihost = scic_to_ihost(scic); u8 i; sci_base_state_machine_construct(&scic->state_machine, @@ -3000,7 +2950,7 @@ enum sci_status scic_controller_construct(struct scic_sds_controller *scic, /* Construct the phys for this controller */ for (i = 0; i < SCI_MAX_PHYS; i++) { /* Add all the PHYs to the dummy port */ - scic_sds_phy_construct(&scic->phy_table[i], + scic_sds_phy_construct(&ihost->phys[i].sci, &scic->port_table[SCI_MAX_PORTS], i); } diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 0a9bb8b77256..aaaf15ab7cfb 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -167,12 +167,6 @@ struct scic_sds_controller { */ struct scic_sds_port port_table[SCI_MAX_PORTS + 1]; - /** - * This field is the array of phy objects that are controlled by this - * controller object. - */ - struct scic_sds_phy phy_table[SCI_MAX_PHYS]; - /** * This field is the array of device objects that are currently constructed * for this controller object. This table is used as a fast lookup of device diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 8f1e3db6bb2e..f0f4c74e4619 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -436,7 +436,7 @@ void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy, struct sci_sas_address *sas_address) { struct sas_identify_frame *iaf; - struct isci_phy *iphy = sci_phy->iphy; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); iaf = &iphy->frame_rcvd.iaf; memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); @@ -1099,7 +1099,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler enum sci_status result; u32 *frame_words; struct sas_identify_frame iaf; - struct isci_phy *iphy = sci_phy->iphy; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); result = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_phy_get_controller(sci_phy)->uf_control), @@ -1164,7 +1164,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle enum sci_status result; struct dev_to_host_fis *frame_header; u32 *fis_frame_data; - struct isci_phy *iphy = sci_phy->iphy; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); result = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_phy_get_controller(sci_phy)->uf_control), diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index b6a0ed1045df..c40c09b0c726 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -217,7 +217,6 @@ enum scic_sds_phy_protocol { SCIC_SDS_MAX_PHY_PROTOCOLS }; -struct isci_phy; /** * struct scic_sds_phy - This structure contains or references all of the data * necessary to represent the core phy object and SCU harware protocol @@ -226,11 +225,6 @@ struct isci_phy; * */ struct scic_sds_phy { - /** - * This field depicts the peer object for the phy. - */ - struct isci_phy *iphy; - /** * This field contains the information for the base phy state machine. */ diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index e1c873406e50..84b8abb421a3 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -645,7 +645,7 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_port *iport = sci_port->iport; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_phy *iphy = sci_phy->iphy; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index 6b2fb445a8f7..aa7ac95ecbc6 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -170,32 +170,27 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( struct scic_sds_controller *controller, struct scic_sds_port_configuration_agent *port_agent) { + struct isci_host *ihost = scic_to_ihost(controller); struct sci_sas_address first_address; struct sci_sas_address second_address; /* * Sanity check the max ranges for all the phys the max index * is always equal to the port range index */ - if ( - (port_agent->phy_valid_port_range[0].max_index != 0) - || (port_agent->phy_valid_port_range[1].max_index != 1) - || (port_agent->phy_valid_port_range[2].max_index != 2) - || (port_agent->phy_valid_port_range[3].max_index != 3) - ) { + if (port_agent->phy_valid_port_range[0].max_index != 0 || + port_agent->phy_valid_port_range[1].max_index != 1 || + port_agent->phy_valid_port_range[2].max_index != 2 || + port_agent->phy_valid_port_range[3].max_index != 3) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } /* * This is a request to configure a single x4 port or at least attempt * to make all the phys into a single port */ - if ( - (port_agent->phy_valid_port_range[0].min_index == 0) - && (port_agent->phy_valid_port_range[1].min_index == 0) - && (port_agent->phy_valid_port_range[2].min_index == 0) - && (port_agent->phy_valid_port_range[3].min_index == 0) - ) { + if (port_agent->phy_valid_port_range[0].min_index == 0 && + port_agent->phy_valid_port_range[1].min_index == 0 && + port_agent->phy_valid_port_range[2].min_index == 0 && + port_agent->phy_valid_port_range[3].min_index == 0) return SCI_SUCCESS; - } /* * This is a degenerate case where phy 1 and phy 2 are assigned @@ -210,8 +205,8 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * PE0 and PE3 can never have the same SAS Address unless they * are part of the same x4 wide port and we have already checked * for this condition. */ - scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address); - scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address); + scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -221,12 +216,10 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * PE0 and PE1 are configured into a 2x1 ports make sure that the * SAS Address for PE0 and PE2 are different since they can not be * part of the same port. */ - if ( - (port_agent->phy_valid_port_range[0].min_index == 0) - && (port_agent->phy_valid_port_range[1].min_index == 1) - ) { - scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address); - scic_sds_phy_get_sas_address(&controller->phy_table[2], &second_address); + if (port_agent->phy_valid_port_range[0].min_index == 0 && + port_agent->phy_valid_port_range[1].min_index == 1) { + scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[2].sci, &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -237,12 +230,10 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * PE2 and PE3 are configured into a 2x1 ports make sure that the * SAS Address for PE1 and PE3 are different since they can not be * part of the same port. */ - if ( - (port_agent->phy_valid_port_range[2].min_index == 2) - && (port_agent->phy_valid_port_range[3].min_index == 3) - ) { - scic_sds_phy_get_sas_address(&controller->phy_table[1], &first_address); - scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address); + if (port_agent->phy_valid_port_range[2].min_index == 2 && + port_agent->phy_valid_port_range[3].min_index == 3) { + scic_sds_phy_get_sas_address(&ihost->phys[1].sci, &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -267,6 +258,7 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( struct scic_sds_controller *controller, struct scic_sds_port_configuration_agent *port_agent) { + struct isci_host *ihost = scic_to_ihost(controller); u32 phy_mask; u32 assigned_phy_mask; struct sci_sas_address sas_address; @@ -281,68 +273,64 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask; - if (phy_mask != 0) { - /* - * Make sure that one or more of the phys were not already assinged to - * a different port. */ - if ((phy_mask & ~assigned_phy_mask) == 0) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } + if (!phy_mask) + continue; + /* + * Make sure that one or more of the phys were not already assinged to + * a different port. */ + if ((phy_mask & ~assigned_phy_mask) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } - /* Find the starting phy index for this round through the loop */ - for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { - if ((1 << phy_index) & phy_mask) { - scic_sds_phy_get_sas_address( - &controller->phy_table[phy_index], &sas_address - ); + /* Find the starting phy index for this round through the loop */ + for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { + if ((phy_mask & (1 << phy_index)) == 0) + continue; + scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + &sas_address); - /* - * The phy_index can be used as the starting point for the - * port range since the hardware starts all logical ports - * the same as the PE index. */ - port_agent->phy_valid_port_range[phy_index].min_index = port_index; - port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - - if (phy_index != port_index) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } + /* + * The phy_index can be used as the starting point for the + * port range since the hardware starts all logical ports + * the same as the PE index. */ + port_agent->phy_valid_port_range[phy_index].min_index = port_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - break; - } + if (phy_index != port_index) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } - /* - * See how many additional phys are being added to this logical port. - * Note: We have not moved the current phy_index so we will actually - * compare the startting phy with itself. - * This is expected and required to add the phy to the port. */ - while (phy_index < SCI_MAX_PHYS) { - if ((1 << phy_index) & phy_mask) { - scic_sds_phy_get_sas_address( - &controller->phy_table[phy_index], &phy_assigned_address - ); - - if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { - /* - * The phy mask specified that this phy is part of the same port - * as the starting phy and it is not so fail this configuration */ - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } + break; + } - port_agent->phy_valid_port_range[phy_index].min_index = port_index; - port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + /* + * See how many additional phys are being added to this logical port. + * Note: We have not moved the current phy_index so we will actually + * compare the startting phy with itself. + * This is expected and required to add the phy to the port. */ + while (phy_index < SCI_MAX_PHYS) { + if ((phy_mask & (1 << phy_index)) == 0) + continue; + scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + &phy_assigned_address); + + if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { + /* + * The phy mask specified that this phy is part of the same port + * as the starting phy and it is not so fail this configuration */ + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } - scic_sds_port_add_phy( - &controller->port_table[port_index], - &controller->phy_table[phy_index] - ); + port_agent->phy_valid_port_range[phy_index].min_index = port_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - assigned_phy_mask |= (1 << phy_index); - } + scic_sds_port_add_phy(&controller->port_table[port_index], + &ihost->phys[phy_index].sci); - phy_index++; - } + assigned_phy_mask |= (1 << phy_index); } + + phy_index++; } return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); @@ -355,12 +343,12 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( * device objects before a new series of link up notifications because a link * down has allowed a better port configuration. */ -static void scic_sds_mpc_agent_timeout_handler( - void *object) +static void scic_sds_mpc_agent_timeout_handler(void *object) { u8 index; - struct scic_sds_controller *controller = (struct scic_sds_controller *)object; - struct scic_sds_port_configuration_agent *port_agent = &controller->port_agent; + struct scic_sds_controller *scic = object; + struct isci_host *ihost = scic_to_ihost(scic); + struct scic_sds_port_configuration_agent *port_agent = &scic->port_agent; u16 configure_phy_mask; port_agent->timer_pending = false; @@ -369,13 +357,12 @@ static void scic_sds_mpc_agent_timeout_handler( configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; for (index = 0; index < SCI_MAX_PHYS; index++) { + struct scic_sds_phy *sci_phy = &ihost->phys[index].sci; + if (configure_phy_mask & (1 << index)) { - port_agent->link_up_handler( - controller, - port_agent, - scic_sds_phy_get_port(&controller->phy_table[index]), - &controller->phy_table[index] - ); + port_agent->link_up_handler(scic, port_agent, + scic_sds_phy_get_port(sci_phy), + sci_phy); } } } @@ -489,6 +476,7 @@ static enum sci_status scic_sds_apc_agent_validate_phy_configuration( u8 port_index; struct sci_sas_address sas_address; struct sci_sas_address phy_assigned_address; + struct isci_host *ihost = scic_to_ihost(controller); phy_index = 0; @@ -496,14 +484,12 @@ static enum sci_status scic_sds_apc_agent_validate_phy_configuration( port_index = phy_index; /* Get the assigned SAS Address for the first PHY on the controller. */ - scic_sds_phy_get_sas_address( - &controller->phy_table[phy_index], &sas_address - ); + scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + &sas_address); while (++phy_index < SCI_MAX_PHYS) { - scic_sds_phy_get_sas_address( - &controller->phy_table[phy_index], &phy_assigned_address - ); + scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + &phy_assigned_address); /* Verify each of the SAS address are all the same for every PHY */ if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) { @@ -739,33 +725,30 @@ static void scic_sds_apc_agent_link_down( } } -/** - * - * - * This routine will try to configure the phys into ports when the timer fires. - */ -static void scic_sds_apc_agent_timeout_handler( - void *object) +/* configure the phys into ports when the timer fires */ +static void scic_sds_apc_agent_timeout_handler(void *object) { u32 index; struct scic_sds_port_configuration_agent *port_agent; - struct scic_sds_controller *controller = (struct scic_sds_controller *)object; + struct scic_sds_controller *scic = object; + struct isci_host *ihost = scic_to_ihost(scic); u16 configure_phy_mask; - port_agent = scic_sds_controller_get_port_configuration_agent(controller); + port_agent = scic_sds_controller_get_port_configuration_agent(scic); port_agent->timer_pending = false; configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; - if (configure_phy_mask != 0x00) { - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (configure_phy_mask & (1 << index)) { - scic_sds_apc_agent_configure_ports( - controller, port_agent, &controller->phy_table[index], false - ); - } - } + if (!configure_phy_mask) + return; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if ((configure_phy_mask & (1 << index)) == 0) + continue; + + scic_sds_apc_agent_configure_ports(scic, port_agent, + &ihost->phys[index].sci, false); } } diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 160790a0de0e..328004918329 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -63,61 +63,35 @@ struct scic_sds_phy; extern enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy); extern enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy); -/** - * isci_phy_init() - This function is called by the probe function to - * initialize the phy objects. This func assumes that the isci_port objects - * associated with the SCU have been initialized. - * @isci_phy: This parameter specifies the isci_phy object to initialize - * @isci_host: This parameter specifies the parent SCU host object for this - * isci_phy - * @index: This parameter specifies which SCU phy associates with this - * isci_phy. Generally, SCU phy 0 relates isci_phy 0, etc. - * - */ -void isci_phy_init( - struct isci_phy *phy, - struct isci_host *isci_host, - int index) +void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index) { - struct scic_sds_phy *scic_phy; union scic_oem_parameters oem; - enum sci_status status = SCI_SUCCESS; - u64 sas_addr; - - /*--------------- SCU_Phy Initialization Stuff -----------------------*/ - - status = scic_controller_get_phy_handle(&isci_host->sci, index, &scic_phy); - if (status == SCI_SUCCESS) { - phy->sci_phy_handle = scic_phy; - scic_phy->iphy = phy; - } else - dev_err(&isci_host->pdev->dev, - "failed scic_controller_get_phy_handle\n"); - - scic_oem_parameters_get(&isci_host->sci, &oem); - sas_addr = oem.sds1.phys[index].sas_address.high; - sas_addr <<= 32; - sas_addr |= oem.sds1.phys[index].sas_address.low; - swab64s(&sas_addr); - - memcpy(phy->sas_addr, &sas_addr, sizeof(sas_addr)); - - phy->isci_port = NULL; - phy->sas_phy.enabled = 0; - phy->sas_phy.id = index; - phy->sas_phy.sas_addr = &phy->sas_addr[0]; - phy->sas_phy.frame_rcvd = (u8 *)&phy->frame_rcvd; - phy->sas_phy.ha = &isci_host->sas_ha; - phy->sas_phy.lldd_phy = phy; - phy->sas_phy.enabled = 1; - phy->sas_phy.class = SAS; - phy->sas_phy.iproto = SAS_PROTOCOL_ALL; - phy->sas_phy.tproto = 0; - phy->sas_phy.type = PHY_TYPE_PHYSICAL; - phy->sas_phy.role = PHY_ROLE_INITIATOR; - phy->sas_phy.oob_mode = OOB_NOT_CONNECTED; - phy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN; - memset((u8 *)&phy->frame_rcvd, 0, sizeof(phy->frame_rcvd)); + u64 sci_sas_addr; + __be64 sas_addr; + + scic_oem_parameters_get(&ihost->sci, &oem); + sci_sas_addr = oem.sds1.phys[index].sas_address.high; + sci_sas_addr <<= 32; + sci_sas_addr |= oem.sds1.phys[index].sas_address.low; + sas_addr = cpu_to_be64(sci_sas_addr); + memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr)); + + iphy->isci_port = NULL; + iphy->sas_phy.enabled = 0; + iphy->sas_phy.id = index; + iphy->sas_phy.sas_addr = &iphy->sas_addr[0]; + iphy->sas_phy.frame_rcvd = (u8 *)&iphy->frame_rcvd; + iphy->sas_phy.ha = &ihost->sas_ha; + iphy->sas_phy.lldd_phy = iphy; + iphy->sas_phy.enabled = 1; + iphy->sas_phy.class = SAS; + iphy->sas_phy.iproto = SAS_PROTOCOL_ALL; + iphy->sas_phy.tproto = 0; + iphy->sas_phy.type = PHY_TYPE_PHYSICAL; + iphy->sas_phy.role = PHY_ROLE_INITIATOR; + iphy->sas_phy.oob_mode = OOB_NOT_CONNECTED; + iphy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN; + memset(&iphy->frame_rcvd, 0, sizeof(iphy->frame_rcvd)); } @@ -147,14 +121,14 @@ int isci_phy_control(struct asd_sas_phy *sas_phy, switch (func) { case PHY_FUNC_DISABLE: spin_lock_irqsave(&ihost->scic_lock, flags); - scic_sds_phy_stop(iphy->sci_phy_handle); + scic_sds_phy_stop(&iphy->sci); spin_unlock_irqrestore(&ihost->scic_lock, flags); break; case PHY_FUNC_LINK_RESET: spin_lock_irqsave(&ihost->scic_lock, flags); - scic_sds_phy_stop(iphy->sci_phy_handle); - scic_sds_phy_start(iphy->sci_phy_handle); + scic_sds_phy_stop(&iphy->sci); + scic_sds_phy_start(&iphy->sci); spin_unlock_irqrestore(&ihost->scic_lock, flags); break; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 21f6050eadbe..93ec2d4a9c30 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -54,24 +54,17 @@ */ -#if !defined(_ISCI_PHY_H_) +#ifndef _ISCI_PHY_H_ #define _ISCI_PHY_H_ -#include "port.h" -#include "host.h" #include #include - - -/** - * struct isci_phy - This class implements the ISCI specific representation of - * the phy object. - * - * - */ +#include "scic_sds_phy.h" +#include "port.h" +#include "host.h" struct isci_phy { - struct scic_sds_phy *sci_phy_handle; + struct scic_sds_phy sci; struct asd_sas_phy sas_phy; struct isci_port *isci_port; u8 sas_addr[SAS_ADDR_SIZE]; @@ -82,17 +75,21 @@ struct isci_phy { } frame_rcvd; }; -#define to_isci_phy(p) \ - container_of(p, struct isci_phy, sas_phy); +static inline struct isci_phy *to_isci_phy(struct asd_sas_phy *sas_phy) +{ + struct isci_phy *iphy = container_of(sas_phy, typeof(*iphy), sas_phy); + + return iphy; +} + +static inline struct isci_phy *sci_phy_to_iphy(struct scic_sds_phy *sci_phy) +{ + struct isci_phy *iphy = container_of(sci_phy, typeof(*iphy), sci); -void isci_phy_init( - struct isci_phy *phy, - struct isci_host *isci_host, - int index); + return iphy; +} -int isci_phy_control( - struct asd_sas_phy *phy, - enum phy_func func, - void *buf); +void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index); +int isci_phy_control(struct asd_sas_phy *phy, enum phy_func func, void *buf); #endif /* !defined(_ISCI_PHY_H_) */ diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 6110306e8e23..5e87fedb5676 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -120,44 +120,26 @@ static void isci_port_change_state( spin_unlock_irqrestore(&isci_port->state_lock, flags); } -void isci_port_bc_change_received( - struct isci_host *isci_host, - struct scic_sds_port *port, - struct scic_sds_phy *phy) +void isci_port_bc_change_received(struct isci_host *ihost, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { - struct isci_phy *isci_phy = phy->iphy; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - dev_dbg(&isci_host->pdev->dev, - "%s: isci_phy = %p, sas_phy = %p\n", - __func__, - isci_phy, - &isci_phy->sas_phy); - - isci_host->sas_ha.notify_port_event( - &isci_phy->sas_phy, - PORTE_BROADCAST_RCVD - ); + dev_dbg(&ihost->pdev->dev, "%s: iphy = %p, sas_phy = %p\n", + __func__, iphy, &iphy->sas_phy); - scic_port_enable_broadcast_change_notification(port); + ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); + scic_port_enable_broadcast_change_notification(sci_port); } -/** - * isci_port_link_up() - This function is called by the sci core when a link - * becomes active. the identify address frame is retrieved from the core and - * a notify port event is sent to libsas. - * @isci_host: This parameter specifies the isci host object. - * @port: This parameter specifies the sci port with the active link. - * @phy: This parameter specifies the sci phy with the active link. - * - */ -void isci_port_link_up( - struct isci_host *isci_host, - struct scic_sds_port *port, - struct scic_sds_phy *phy) +void isci_port_link_up(struct isci_host *isci_host, + struct scic_sds_port *port, + struct scic_sds_phy *phy) { unsigned long flags; struct scic_port_properties properties; - struct isci_phy *isci_phy = phy->iphy; + struct isci_phy *isci_phy = sci_phy_to_iphy(phy); struct isci_port *isci_port = port->iport; unsigned long success = true; diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index 8394f60c5c2b..bb07ed31b51c 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -67,7 +67,7 @@ static inline struct device *scic_to_dev(struct scic_sds_controller *scic) static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) { - struct isci_phy *iphy = sci_phy->iphy; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host) return NULL; -- cgit v1.2.3 From e531381e2f8a68b8737c63c7bb890ad80b2470bd Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 May 2011 10:11:43 -0700 Subject: isci: unify port data structures Make scic_sds_port a member of isci_port and merge their lifetimes which means removing the port table from scic_sds_controller in favor of the one at the isci_host level. Merge ihost->sas_ports into ihost->ports. _ Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 19 +++++----- drivers/scsi/isci/core/scic_sds_controller.h | 7 ---- drivers/scsi/isci/core/scic_sds_port.c | 44 +++++++++------------- drivers/scsi/isci/core/scic_sds_port.h | 5 --- .../isci/core/scic_sds_port_configuration_agent.c | 18 +++++---- drivers/scsi/isci/host.c | 6 +-- drivers/scsi/isci/host.h | 7 +--- drivers/scsi/isci/init.c | 4 +- drivers/scsi/isci/port.c | 41 +++++++------------- drivers/scsi/isci/port.h | 25 +++++------- drivers/scsi/isci/remote_device.c | 2 +- drivers/scsi/isci/sci_environment.h | 2 +- 12 files changed, 67 insertions(+), 113 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 4ad31550c8ae..4179bdf3eda7 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -623,9 +623,10 @@ static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller u32 index; enum sci_status port_status; enum sci_status status = SCI_SUCCESS; + struct isci_host *ihost = scic_to_ihost(scic); for (index = 0; index < scic->logical_port_entries; index++) { - struct scic_sds_port *sci_port = &scic->port_table[index]; + struct scic_sds_port *sci_port = &ihost->ports[index].sci; scic_sds_port_handler_t stop; stop = sci_port->state_handlers->stop_handler; @@ -2686,7 +2687,7 @@ enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) (result == SCI_SUCCESS); index++) { result = scic_sds_port_initialize( - &scic->port_table[index], + &ihost->ports[index].sci, &scic->scu_registers->peg0.ptsg.port[index], &scic->scu_registers->peg0.ptsg.protocol_engine, &scic->scu_registers->peg0.viit[index]); @@ -2709,8 +2710,9 @@ enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) } enum sci_status scic_controller_start(struct scic_sds_controller *scic, - u32 timeout) + u32 timeout) { + struct isci_host *ihost = scic_to_ihost(scic); enum sci_status result; u16 index; @@ -2752,10 +2754,9 @@ enum sci_status scic_controller_start(struct scic_sds_controller *scic, /* Start all of the ports on this controller */ for (index = 0; index < scic->logical_port_entries; index++) { - struct scic_sds_port *sci_port = &scic->port_table[index]; + struct scic_sds_port *sci_port = &ihost->ports[index].sci; - result = sci_port->state_handlers->start_handler( - sci_port); + result = sci_port->state_handlers->start_handler(sci_port); if (result) return result; } @@ -2944,14 +2945,14 @@ enum sci_status scic_controller_construct(struct scic_sds_controller *scic, /* Construct the ports for this controller */ for (i = 0; i < SCI_MAX_PORTS; i++) - scic_sds_port_construct(&scic->port_table[i], i, scic); - scic_sds_port_construct(&scic->port_table[i], SCIC_SDS_DUMMY_PORT, scic); + scic_sds_port_construct(&ihost->ports[i].sci, i, scic); + scic_sds_port_construct(&ihost->ports[i].sci, SCIC_SDS_DUMMY_PORT, scic); /* Construct the phys for this controller */ for (i = 0; i < SCI_MAX_PHYS; i++) { /* Add all the PHYs to the dummy port */ scic_sds_phy_construct(&ihost->phys[i].sci, - &scic->port_table[SCI_MAX_PORTS], i); + &ihost->ports[SCI_MAX_PORTS].sci, i); } scic->invalid_phy_mask = 0; diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index aaaf15ab7cfb..0d5047319cbf 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -160,13 +160,6 @@ struct scic_sds_controller { */ struct scic_sds_port_configuration_agent port_agent; - /** - * This field is the array of port objects that are controlled by this - * controller object. There is one dummy port object also contained within - * this controller object. - */ - struct scic_sds_port port_table[SCI_MAX_PORTS + 1]; - /** * This field is the array of device objects that are currently constructed * for this controller object. This table is used as a fast lookup of device diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 84b8abb421a3..01288dd44fb6 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -283,18 +283,14 @@ static enum sci_status scic_sds_port_clear_phy( struct scic_sds_phy *phy) { /* Make sure that this phy is part of this port */ - if ( - (port->phy_table[phy->phy_index] == phy) - && (scic_sds_phy_get_port(phy) == port) - ) { - /* Yep it is assigned to this port so remove it */ - scic_sds_phy_set_port( - phy, - &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS] - ); + if (port->phy_table[phy->phy_index] == phy && + scic_sds_phy_get_port(phy) == port) { + struct scic_sds_controller *scic = port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + /* Yep it is assigned to this port so remove it */ + scic_sds_phy_set_port(phy, &ihost->ports[SCI_MAX_PORTS].sci); port->phy_table[phy->phy_index] = NULL; - return SCI_SUCCESS; } @@ -643,7 +639,7 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, bool do_notify_user) { struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_port *iport = sci_port->iport; + struct isci_port *iport = sci_port_to_iport(sci_port); struct isci_host *ihost = scic_to_ihost(scic); struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); @@ -1620,10 +1616,9 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) { u32 index; struct scic_sds_port *sci_port = object; - struct scic_sds_controller *scic = - scic_sds_port_get_controller(sci_port); + struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port->iport; + struct isci_port *iport = sci_port_to_iport(sci_port); scic_sds_port_set_ready_state_handlers( sci_port, @@ -1661,10 +1656,9 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) static void scic_sds_port_ready_substate_operational_exit(void *object) { struct scic_sds_port *sci_port = object; - struct scic_sds_controller *scic = - scic_sds_port_get_controller(sci_port); + struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port->iport; + struct isci_port *iport = sci_port_to_iport(sci_port); /* * Kill the dummy task for this port if it has not yet posted @@ -1692,10 +1686,9 @@ static void scic_sds_port_ready_substate_operational_exit(void *object) static void scic_sds_port_ready_substate_configuring_enter(void *object) { struct scic_sds_port *sci_port = object; - struct scic_sds_controller *scic = - scic_sds_port_get_controller(sci_port); + struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port->iport; + struct isci_port *iport = sci_port_to_iport(sci_port); scic_sds_port_set_ready_state_handlers( sci_port, @@ -2259,7 +2252,7 @@ static void scic_sds_port_ready_state_enter(void *object) struct scic_sds_port *sci_port = object; struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port->iport; + struct isci_port *iport = sci_port_to_iport(sci_port); u32 prev_state; /* Put the ready state handlers in place though they will not be there long */ @@ -2366,7 +2359,7 @@ scic_sds_port_stopping_state_exit(void *object) static void scic_sds_port_failed_state_enter(void *object) { struct scic_sds_port *sci_port = object; - struct isci_port *iport = sci_port->iport; + struct isci_port *iport = sci_port_to_iport(sci_port); scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_FAILED); @@ -2398,11 +2391,9 @@ static const struct sci_base_state scic_sds_port_state_table[] = { } }; -void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, +void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, struct scic_sds_controller *scic) { - u32 index; - sci_base_state_machine_construct(&sci_port->state_machine, sci_port, scic_sds_port_state_table, @@ -2416,7 +2407,7 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, SCIC_SDS_PORT_READY_SUBSTATE_WAITING); sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; - sci_port->physical_port_index = port_index; + sci_port->physical_port_index = index; sci_port->active_phy_mask = 0; sci_port->owning_controller = scic; @@ -2428,7 +2419,6 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 port_index, sci_port->reserved_tci = SCU_DUMMY_INDEX; sci_port->timer_handle = NULL; - sci_port->port_task_scheduler_registers = NULL; for (index = 0; index < SCI_MAX_PHYS; index++) diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 213d42330b4b..3633561b686a 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -151,17 +151,12 @@ enum scic_sds_port_states { }; -struct isci_port; /** * struct scic_sds_port * * The core port object provides the the abstraction for an SCU port. */ struct scic_sds_port { - /** - * The field specifies the peer object for the port. - */ - struct isci_port *iport; /** * This field contains the information for the base port state machine. diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index aa7ac95ecbc6..2d3d067396d3 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -141,14 +141,15 @@ static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); for (i = 0; i < scic->logical_port_entries; i++) { - struct scic_sds_port *port = &scic->port_table[i]; + struct isci_host *ihost = scic_to_ihost(scic); + struct scic_sds_port *sci_port = &ihost->ports[i].sci; - scic_sds_port_get_sas_address(port, &port_sas_address); - scic_sds_port_get_attached_sas_address(port, &port_attached_device_address); + scic_sds_port_get_sas_address(sci_port, &port_sas_address); + scic_sds_port_get_attached_sas_address(sci_port, &port_attached_device_address); - if ((sci_sas_address_compare(port_sas_address, phy_sas_address) == 0) && - (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0)) - return port; + if (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0 && + sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) + return sci_port; } return NULL; @@ -324,7 +325,7 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - scic_sds_port_add_phy(&controller->port_table[port_index], + scic_sds_port_add_phy(&ihost->ports[port_index].sci, &ihost->phys[phy_index].sci); assigned_phy_mask |= (1 << phy_index); @@ -550,6 +551,7 @@ static void scic_sds_apc_agent_configure_ports( enum sci_status status; struct scic_sds_port *port; enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; + struct isci_host *ihost = scic_to_ihost(controller); port = scic_sds_port_configuration_agent_find_port(controller, phy); @@ -571,7 +573,7 @@ static void scic_sds_apc_agent_configure_ports( port_index++ ) { - port = &controller->port_table[port_index]; + port = &ihost->ports[port_index].sci; /* First we must make sure that this PHY can be added to this Port. */ if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) { diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index d180ad8a8bcf..cdd99304c363 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -277,10 +277,10 @@ void isci_host_deinit(struct isci_host *ihost) isci_host_change_state(ihost, isci_stopping); for (i = 0; i < SCI_MAX_PORTS; i++) { - struct isci_port *port = &ihost->isci_ports[i]; + struct isci_port *iport = &ihost->ports[i]; struct isci_remote_device *idev, *d; - list_for_each_entry_safe(idev, d, &port->remote_dev_list, node) { + list_for_each_entry_safe(idev, d, &iport->remote_dev_list, node) { isci_remote_device_change_state(idev, isci_stopping); isci_remote_device_stop(ihost, idev); } @@ -442,7 +442,7 @@ int isci_host_init(struct isci_host *isci_host) return -ENOMEM; for (i = 0; i < SCI_MAX_PORTS; i++) - isci_port_init(&isci_host->isci_ports[i], isci_host, i); + isci_port_init(&isci_host->ports[i], isci_host, i); for (i = 0; i < SCI_MAX_PHYS; i++) isci_phy_init(&isci_host->phys[i], isci_host, i); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 00e4854e20d9..5a414c31a877 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -84,12 +84,7 @@ struct isci_host { struct dma_pool *dma_pool; unsigned int dma_pool_alloc_size; struct isci_phy phys[SCI_MAX_PHYS]; - - /* isci_ports and sas_ports are implicitly parallel to the - * ports maintained by the core - */ - struct isci_port isci_ports[SCI_MAX_PORTS]; - struct asd_sas_port sas_ports[SCI_MAX_PORTS]; + struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ struct sas_ha_struct sas_ha; int can_queue; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index a5d5c0b97d00..522d39f9e132 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -221,8 +221,8 @@ static int isci_register_sas_ha(struct isci_host *isci_host) /* set the array of phy and port structs. */ for (i = 0; i < SCI_MAX_PHYS; i++) { - sas_phys[i] = &(isci_host->phys[i].sas_phy); - sas_ports[i] = &(isci_host->sas_ports[i]); + sas_phys[i] = &isci_host->phys[i].sas_phy; + sas_ports[i] = &isci_host->ports[i].sas_port; } sas_ha->sas_phy = sas_phys; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 5e87fedb5676..35e2e517f671 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -70,29 +70,30 @@ #include "request.h" #include "core/scic_sds_controller.h" -static void isci_port_change_state( - struct isci_port *isci_port, - enum isci_status status); +static void isci_port_change_state(struct isci_port *iport, enum isci_status status) +{ + unsigned long flags; + dev_dbg(&iport->isci_host->pdev->dev, + "%s: iport = %p, state = 0x%x\n", + __func__, iport, status); + /* XXX pointless lock */ + spin_lock_irqsave(&iport->state_lock, flags); + iport->status = status; + spin_unlock_irqrestore(&iport->state_lock, flags); +} void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index) { - struct scic_sds_port *sci_port; - INIT_LIST_HEAD(&iport->remote_dev_list); INIT_LIST_HEAD(&iport->domain_dev_list); spin_lock_init(&iport->state_lock); init_completion(&iport->start_complete); iport->isci_host = ihost; isci_port_change_state(iport, isci_freed); - - sci_port = &ihost->sci.port_table[index]; - iport->sci_port_handle = sci_port; - sci_port->iport = iport; } - /** * isci_port_get_state() - This function gets the status of the port object. * @isci_port: This parameter points to the isci_port object @@ -105,21 +106,6 @@ enum isci_status isci_port_get_state( return isci_port->status; } -static void isci_port_change_state( - struct isci_port *isci_port, - enum isci_status status) -{ - unsigned long flags; - - dev_dbg(&isci_port->isci_host->pdev->dev, - "%s: isci_port = %p, state = 0x%x\n", - __func__, isci_port, status); - - spin_lock_irqsave(&isci_port->state_lock, flags); - isci_port->status = status; - spin_unlock_irqrestore(&isci_port->state_lock, flags); -} - void isci_port_bc_change_received(struct isci_host *ihost, struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy) @@ -140,7 +126,7 @@ void isci_port_link_up(struct isci_host *isci_host, unsigned long flags; struct scic_port_properties properties; struct isci_phy *isci_phy = sci_phy_to_iphy(phy); - struct isci_port *isci_port = port->iport; + struct isci_port *isci_port = sci_port_to_iport(port); unsigned long success = true; BUG_ON(isci_phy->isci_port != NULL); @@ -346,8 +332,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor spin_lock_irqsave(&ihost->scic_lock, flags); #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT - status = scic_port_hard_reset(iport->sci_port_handle, - ISCI_PORT_RESET_TIMEOUT); + status = scic_port_hard_reset(&iport->sci, ISCI_PORT_RESET_TIMEOUT); spin_unlock_irqrestore(&ihost->scic_lock, flags); diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index ac1ac86ead6f..355034542e4c 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -53,19 +53,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the isci_port object definition. - * - * port.h - */ - -#if !defined(_ISCI_PORT_H_) +#ifndef _ISCI_PORT_H_ #define _ISCI_PORT_H_ +#include "scic_sds_port.h" struct isci_phy; struct isci_host; -struct scic_sds_phy; - enum isci_status { isci_freed = 0x00, @@ -84,9 +77,6 @@ enum isci_status { * */ struct isci_port { - - struct scic_sds_port *sci_port_handle; - enum isci_status status; struct isci_host *isci_host; struct asd_sas_port sas_port; @@ -96,16 +86,19 @@ struct isci_port { struct completion start_complete; struct completion hard_reset_complete; enum sci_status hard_reset_status; + struct scic_sds_port sci; }; -#define to_isci_port(p) \ - container_of(p, struct isci_port, sas_port); +static inline struct isci_port *sci_port_to_iport(struct scic_sds_port *sci_port) +{ + struct isci_port *iport = container_of(sci_port, typeof(*iport), sci); + + return iport; +} enum isci_status isci_port_get_state( struct isci_port *isci_port); - - void isci_port_formed( struct asd_sas_phy *); diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 734d028448b0..a441c23b6859 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1264,7 +1264,7 @@ static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *s static enum sci_status isci_remote_device_construct(struct isci_port *iport, struct isci_remote_device *idev) { - struct scic_sds_port *sci_port = iport->sci_port_handle; + struct scic_sds_port *sci_port = &iport->sci; struct isci_host *ihost = iport->isci_host; struct domain_device *dev = idev->domain_dev; enum sci_status status; diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index bb07ed31b51c..1806969fc435 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -77,7 +77,7 @@ static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port) { - struct isci_port *iport = sci_port->iport; + struct isci_port *iport = sci_port_to_iport(sci_port); if (!iport || !iport->isci_host) return NULL; -- cgit v1.2.3 From 827a84d4e036b342b31abc2bcc3893505c2c7daa Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 May 2011 15:59:09 -0700 Subject: isci: move stp request info to scic_sds_request In preparation for unifying allocation of all request information make stp data available in all requests. Incidentally collapse indentation. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_request.c | 3 +- drivers/scsi/isci/core/scic_sds_request.h | 19 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 711 +++++++++++--------------- drivers/scsi/isci/core/scic_sds_stp_request.h | 10 - drivers/scsi/isci/task.c | 5 +- 5 files changed, 313 insertions(+), 435 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 52692a16449d..fd7bd334fa4b 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -710,8 +710,7 @@ enum sci_status scic_io_request_construct_basic_sata( struct isci_request *isci_request = sci_req->ireq; struct sas_task *task = isci_request_access_task(isci_request); - stp_req = container_of(sci_req, typeof(*stp_req), parent); - + stp_req = &sci_req->stp.req; sci_req->protocol = SCIC_STP_PROTOCOL; copy = (task->data_dir == DMA_NONE) ? false : true; diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index b83d89362909..c93f3ed8946d 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -56,16 +56,10 @@ #ifndef _SCIC_SDS_IO_REQUEST_H_ #define _SCIC_SDS_IO_REQUEST_H_ -/** - * This file contains the structures, constants and prototypes for the - * SCIC_SDS_IO_REQUEST object. - * - * - */ - #include "scic_io_request.h" #include "sci_base_state_machine.h" #include "scu_task_context.h" +#include "scic_sds_stp_request.h" struct scic_sds_controller; struct scic_sds_remote_device; @@ -233,8 +227,19 @@ struct scic_sds_request { */ u8 device_sequence; + struct { + struct scic_sds_stp_request req; + } stp; }; +static inline struct scic_sds_request *to_sci_req(struct scic_sds_stp_request *stp_req) +{ + struct scic_sds_request *sci_req; + + sci_req = container_of(stp_req, typeof(*sci_req), stp.req); + return sci_req; +} + /** * enum sci_base_request_states - This enumeration depicts all the states for * the common request state machine. diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 8569dba6c68b..7dba40fc2585 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -134,8 +134,7 @@ u32 scic_sds_stp_request_get_object_size(void) void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) { - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; sci_req->command_buffer = scic_sds_stp_request_get_h2d_reg_buffer(stp_req); sci_req->response_buffer = scic_sds_stp_request_get_response_buffer(stp_req); @@ -344,17 +343,18 @@ enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_ * utilizing the raw frame method. none */ static void scu_stp_raw_request_construct_task_context( - struct scic_sds_stp_request *sci_req, + struct scic_sds_stp_request *stp_req, struct scu_task_context *task_context) { - scu_sata_reqeust_construct_task_context(&sci_req->parent, task_context); + struct scic_sds_request *sci_req = to_sci_req(stp_req); + + scu_sata_reqeust_construct_task_context(sci_req, task_context); task_context->control_frame = 0; task_context->priority = SCU_TASK_PRIORITY_NORMAL; task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; task_context->type.stp.fis_type = FIS_REGH2D; - task_context->transfer_length_bytes = - sizeof(struct host_to_dev_fis) - sizeof(u32); + task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32); } void scic_stp_io_request_set_ncq_tag( @@ -376,10 +376,11 @@ void *scic_stp_io_request_get_h2d_reg_address( } -void *scic_stp_io_request_get_d2h_reg_address( - struct scic_sds_request *req) +void *scic_stp_io_request_get_d2h_reg_address(struct scic_sds_request *sci_req) { - return &((struct scic_sds_stp_request *)req)->d2h_reg_fis; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + + return &stp_req->d2h_reg_fis; } /** @@ -395,7 +396,7 @@ void *scic_stp_io_request_get_d2h_reg_address( static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) { struct scu_sgl_element *current_sgl; - struct scic_sds_request *sci_req = &stp_req->parent; + struct scic_sds_request *sci_req = to_sci_req(stp_req); struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current; if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { @@ -489,60 +490,54 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( enum sci_status status; struct dev_to_host_fis *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); - - status = scic_sds_unsolicited_frame_control_get_header( - &stp_req->parent.owning_controller->uf_control, - frame_index, - (void **)&frame_header); - - if (status == SCI_SUCCESS) { - switch (frame_header->fis_type) { - case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer( - &stp_req->parent.owning_controller->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response( - &stp_req->d2h_reg_fis, - (u32 *)frame_header, - frame_buffer); - - /* The command has completed with error */ - scic_sds_request_set_status( - &stp_req->parent, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; - - default: - dev_warn(scic_to_dev(sci_req->owning_controller), - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", - __func__, stp_req, frame_index); - - scic_sds_request_set_status( - &stp_req->parent, - SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); - break; - } + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; - sci_base_state_machine_change_state( - &stp_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame( - stp_req->parent.owning_controller, frame_index); - } else + if (status != SCI_SUCCESS) { dev_err(scic_to_dev(sci_req->owning_controller), "%s: SCIC IO Request 0x%p could not get frame header " "for frame index %d, status %x\n", __func__, stp_req, frame_index, status); + return status; + } + + switch (frame_header->fis_type) { + case FIS_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + frame_header, + frame_buffer); + + /* The command has completed with error */ + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", __func__, stp_req, + frame_index); + + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION); + break; + } + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + return status; } @@ -599,8 +594,7 @@ static const struct sci_base_state scic_sds_stp_request_started_non_data_substat enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req) { - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; scic_sds_stp_non_ncq_request_construct(sci_req); @@ -617,36 +611,28 @@ enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request #define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ -/** - * - * @sci_req: - * @length: - * - * This function will transmit DATA_FIS from (current sgl + offset) for input +/* transmit DATA_FIS from (current sgl + offset) for input * parameter length. current sgl and offset is alreay stored in the IO request - * enum sci_status */ - static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( struct scic_sds_request *sci_req, u32 length) { - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scu_task_context *task_context; struct scu_sgl_element *current_sgl; - /* - * Recycle the TC and reconstruct it for sending out DATA FIS containing - * for the data from current_sgl+offset for the input length */ - struct scu_task_context *task_context = scic_sds_controller_get_task_context_buffer( - sci_req->owning_controller, - sci_req->io_tag - ); + /* Recycle the TC and reconstruct it for sending out DATA FIS containing + * for the data from current_sgl+offset for the input length + */ + task_context = scic_sds_controller_get_task_context_buffer(scic, + sci_req->io_tag); if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) - current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A); + current_sgl = &stp_req->type.pio.request_current.sgl_pair->A; else - current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B); + current_sgl = &stp_req->type.pio.request_current.sgl_pair->B; /* update the TC */ task_context->command_iu_upper = current_sgl->address_upper; @@ -658,23 +644,14 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( return scic_controller_continue_io(sci_req); } -/** - * - * @sci_req: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data( - struct scic_sds_request *sci_req) +static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct scic_sds_request *sci_req) { struct scu_sgl_element *current_sgl; u32 sgl_offset; u32 remaining_bytes_in_current_sgl = 0; enum sci_status status = SCI_SUCCESS; - - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; sgl_offset = stp_req->type.pio.request_current.sgl_offset; @@ -740,7 +717,7 @@ scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *s void *kaddr; int total_len = len; - sci_req = &stp_req->parent; + sci_req = to_sci_req(stp_req); ireq = scic_sds_request_get_user_request(sci_req); task = isci_request_access_task(ireq); src_addr = data_buf; @@ -846,234 +823,184 @@ static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completi return status; } -/** - * - * @sci_req: - * @frame_index: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) +static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) { - enum sci_status status; - struct dev_to_host_fis *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; struct isci_request *ireq = sci_req->ireq; struct sas_task *task = isci_request_access_task(ireq); + struct dev_to_host_fis *frame_header; + enum sci_status status; + u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header( - &(stp_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_header); + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); - if (status == SCI_SUCCESS) { - switch (frame_header->fis_type) { - case FIS_PIO_SETUP: - /* Get from the frame buffer the PIO Setup Data */ - scic_sds_unsolicited_frame_control_get_buffer( - &(stp_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_buffer); - - /* Get the data from the PIO Setup The SCU Hardware - * returns first word in the frame_header and the rest - * of the data is in the frame buffer so we need to back - * up one dword - */ + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + switch (frame_header->fis_type) { + case FIS_PIO_SETUP: + /* Get from the frame buffer the PIO Setup Data */ + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + /* Get the data from the PIO Setup The SCU Hardware returns + * first word in the frame_header and the rest of the data is in + * the frame buffer so we need to back up one dword + */ - /* transfer_count: first 16bits in the 4th dword */ - stp_req->type.pio.pio_transfer_bytes = - frame_buffer[3] & 0xffff; + /* transfer_count: first 16bits in the 4th dword */ + stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff; - /* ending_status: 4th byte in the 3rd dword */ - stp_req->type.pio.ending_status = - (frame_buffer[2] >> 24) & 0xff; + /* ending_status: 4th byte in the 3rd dword */ + stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; - scic_sds_controller_copy_sata_response( - &stp_req->d2h_reg_fis, - (u32 *)frame_header, - frame_buffer); + scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + frame_header, + frame_buffer); - stp_req->d2h_reg_fis.status = - stp_req->type.pio.ending_status; + stp_req->d2h_reg_fis.status = stp_req->type.pio.ending_status; - /* The next state is dependent on whether the - * request was PIO Data-in or Data out + /* The next state is dependent on whether the + * request was PIO Data-in or Data out + */ + if (task->data_dir == DMA_FROM_DEVICE) { + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); + } else if (task->data_dir == DMA_TO_DEVICE) { + /* Transmit data */ + status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); + if (status != SCI_SUCCESS) + break; + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); + } + break; + case FIS_SETDEVBITS: + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + break; + case FIS_REGD2H: + if (frame_header->status & ATA_BUSY) { + /* Now why is the drive sending a D2H Register FIS when + * it is still busy? Do nothing since we are still in + * the right state. */ - if (task->data_dir == DMA_FROM_DEVICE) { - sci_base_state_machine_change_state( - &stp_req->parent.started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); - } else if (task->data_dir == DMA_TO_DEVICE) { - /* Transmit data */ - status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); - if (status == SCI_SUCCESS) { - sci_base_state_machine_change_state( - &stp_req->parent.started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); - } - } + dev_dbg(scic_to_dev(scic), + "%s: SCIC PIO Request 0x%p received " + "D2H Register FIS with BSY status " + "0x%x\n", __func__, stp_req, + frame_header->status); break; + } - case FIS_SETDEVBITS: - sci_base_state_machine_change_state( - &stp_req->parent.started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); - break; + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); - case FIS_REGD2H: - if ((frame_header->status & ATA_BUSY) == 0) { - scic_sds_unsolicited_frame_control_get_buffer( - &(stp_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response( - &stp_req->d2h_reg_fis, - (u32 *)frame_header, - frame_buffer); - - scic_sds_request_set_status( - &stp_req->parent, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - sci_base_state_machine_change_state( - &stp_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - } else { - /* Now why is the drive sending a D2H Register - * FIS when it is still busy? - * Do nothing since we are still in the right - * state. - */ - dev_dbg(scic_to_dev(sci_req->owning_controller), - "%s: SCIC PIO Request 0x%p received " - "D2H Register FIS with BSY status " - "0x%x\n", - __func__, - stp_req, - frame_header->status); - } - break; + scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + frame_header, + frame_buffer); - default: - /* FIXME: what do we do here? */ - break; - } + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame( - stp_req->parent.owning_controller, - frame_index); - } else - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + default: + /* FIXME: what do we do here? */ + break; + } + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); return status; } -/** - * - * @sci_req: - * @frame_index: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) +static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) { enum sci_status status; struct dev_to_host_fis *frame_header; struct sata_fis_data *frame_buffer; - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; - status = scic_sds_unsolicited_frame_control_get_header( - &(stp_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_header); + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); - if (status == SCI_SUCCESS) { - if (frame_header->fis_type == FIS_DATA) { - if (stp_req->type.pio.request_current.sgl_pair == - NULL) { - stp_req->parent.saved_rx_frame_index = - frame_index; - stp_req->type.pio.pio_transfer_bytes = 0; - } else { - status = scic_sds_unsolicited_frame_control_get_buffer( - &(stp_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_buffer); - - status = scic_sds_stp_request_pio_data_in_copy_data( - stp_req, - (u8 *)frame_buffer); - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame( - stp_req->parent.owning_controller, - frame_index); - } + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } - /* - * Check for the end of the transfer, are there more - * bytes remaining for this data transfer - */ - if ((status == SCI_SUCCESS) && - (stp_req->type.pio.pio_transfer_bytes == 0)) { - if ((stp_req->type.pio.ending_status & - ATA_BUSY) == 0) { - scic_sds_request_set_status( - &stp_req->parent, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - sci_base_state_machine_change_state( - &stp_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - } else { - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); - } - } + if (frame_header->fis_type == FIS_DATA) { + if (stp_req->type.pio.request_current.sgl_pair == NULL) { + sci_req->saved_rx_frame_index = frame_index; + stp_req->type.pio.pio_transfer_bytes = 0; } else { - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC PIO Request 0x%p received frame %d " - "with fis type 0x%02x when expecting a data " - "fis.\n", - __func__, - stp_req, - frame_index, - frame_header->fis_type); - - scic_sds_request_set_status( - &stp_req->parent, - SCU_TASK_DONE_GOOD, - SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); - sci_base_state_machine_change_state( - &stp_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + status = scic_sds_stp_request_pio_data_in_copy_data(stp_req, + (u8 *)frame_buffer); /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame( - stp_req->parent.owning_controller, - frame_index); + scic_sds_controller_release_frame(scic, frame_index); } - } else - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); + + /* Check for the end of the transfer, are there more + * bytes remaining for this data transfer + */ + if (status != SCI_SUCCESS || + stp_req->type.pio.pio_transfer_bytes != 0) + return status; + + if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) { + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + } else { + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + } + } else { + dev_err(scic_to_dev(scic), + "%s: SCIC PIO Request 0x%p received frame %d " + "with fis type 0x%02x when expecting a data " + "fis.\n", __func__, stp_req, frame_index, + frame_header->fis_type); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + } return status; } @@ -1093,8 +1020,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_com { enum sci_status status = SCI_SUCCESS; bool all_frames_transferred = false; - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): @@ -1280,8 +1206,7 @@ enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, bool copy_rx_frame) { - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; scic_sds_stp_non_ncq_request_construct(sci_req); @@ -1325,91 +1250,66 @@ static void scic_sds_stp_request_udma_complete_request( SCI_BASE_REQUEST_STATE_COMPLETED); } -/** - * - * @sci_req: - * @frame_index: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_udma_general_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) +static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) { - enum sci_status status; + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; struct dev_to_host_fis *frame_header; + enum sci_status status; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header( - &sci_req->owning_controller->uf_control, - frame_index, - (void **)&frame_header); + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); if ((status == SCI_SUCCESS) && (frame_header->fis_type == FIS_REGD2H)) { - scic_sds_unsolicited_frame_control_get_buffer( - &sci_req->owning_controller->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response( - &((struct scic_sds_stp_request *)sci_req)->d2h_reg_fis, - (u32 *)frame_header, - frame_buffer); + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + frame_header, + frame_buffer); } - scic_sds_controller_release_frame( - sci_req->owning_controller, frame_index); + scic_sds_controller_release_frame(scic, frame_index); return status; } -/** - * This method process TC completions while in the state where we are waiting - * for TC completions. - * @sci_req: - * @completion_code: - * - * enum sci_status - */ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( - struct scic_sds_request *request, + struct scic_sds_request *sci_req, u32 completion_code) { + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; enum sci_status status = SCI_SUCCESS; - struct scic_sds_stp_request *sci_req = (struct scic_sds_stp_request *)request; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_stp_request_udma_complete_request( - &sci_req->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS); break; - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): /* * We must check ther response buffer to see if the D2H Register FIS was * received before we got the TC completion. */ - if (sci_req->d2h_reg_fis.fis_type == FIS_REGD2H) { - scic_sds_remote_device_suspend( - sci_req->parent.target_device, - SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) - ); + if (stp_req->d2h_reg_fis.fis_type == FIS_REGD2H) { + scic_sds_remote_device_suspend(sci_req->target_device, + SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); - scic_sds_stp_request_udma_complete_request( - &sci_req->parent, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); } else { /* * If we have an error completion status for the TC then we can expect a * D2H register FIS from the device so we must change state to wait for it */ - sci_base_state_machine_change_state( - &sci_req->parent.started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE - ); + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE); } break; @@ -1422,18 +1322,14 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): - scic_sds_remote_device_suspend( - sci_req->parent.target_device, - SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) - ); + scic_sds_remote_device_suspend(sci_req->target_device, + SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); /* Fall through to the default case */ default: /* All other completion status cause the IO to be complete. */ - scic_sds_stp_request_udma_complete_request( - &sci_req->parent, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); break; } @@ -1449,13 +1345,12 @@ static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler /* Use the general frame handler to copy the resposne data */ status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); - if (status == SCI_SUCCESS) { - scic_sds_stp_request_udma_complete_request( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID - ); - } + if (status != SCI_SUCCESS) + return status; + + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); return status; } @@ -1636,67 +1531,58 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_c * if the received frame was processed successfully. */ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( - struct scic_sds_request *request, + struct scic_sds_request *sci_req, u32 frame_index) { enum sci_status status; struct dev_to_host_fis *frame_header; u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = - (struct scic_sds_stp_request *)request; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } - status = scic_sds_unsolicited_frame_control_get_header( - &(stp_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_header); + switch (frame_header->fis_type) { + case FIS_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); - if (status == SCI_SUCCESS) { - switch (frame_header->fis_type) { - case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer( - &(stp_req->parent.owning_controller->uf_control), - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response( - &stp_req->d2h_reg_fis, - (u32 *)frame_header, - frame_buffer); - - /* The command has completed with error */ - scic_sds_request_set_status( - &stp_req->parent, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; + scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + frame_header, + frame_buffer); - default: - dev_warn(scic_to_dev(request->owning_controller), - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", - __func__, - stp_req, - frame_index); - - scic_sds_request_set_status( - &stp_req->parent, - SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); - break; - } + /* The command has completed with error */ + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + break; - sci_base_state_machine_change_state( - &stp_req->parent.state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + default: + dev_warn(scic_to_dev(scic), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", __func__, stp_req, + frame_index); - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame( - stp_req->parent.owning_controller, frame_index); - } else - dev_err(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION); + break; + } + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); return status; } @@ -1787,8 +1673,7 @@ static const struct sci_base_state scic_sds_stp_request_started_soft_reset_subst enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req) { - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; scic_sds_stp_non_ncq_request_construct(sci_req); diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index 50cb48ef554e..6d02030b6cd6 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -58,17 +58,8 @@ #include #include -#include "scic_sds_request.h" -/** - * This structure represents the additional information that is required to - * handle SATA PIO requests. - * - * - */ struct scic_sds_stp_request { - struct scic_sds_request parent; - struct dev_to_host_fis d2h_reg_fis; union { @@ -125,7 +116,6 @@ struct scic_sds_stp_request { u32 device_preferred_cdb_length; } packet; } type; - }; /** diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index cabad0b03ee5..12f2df947362 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -64,7 +64,7 @@ #include "request.h" #include "sata.h" #include "task.h" -#include "scic_sds_stp_request.h" +#include "scic_sds_request.h" /** * isci_task_refuse() - complete the request to the upper layer driver in @@ -1435,8 +1435,7 @@ isci_task_request_complete(struct isci_host *ihost, struct isci_tmf *tmf = isci_request_access_tmf(ireq); struct completion *tmf_complete; struct scic_sds_request *sci_req = ireq->sci_request_handle; - struct scic_sds_stp_request *stp_req = - container_of(sci_req, typeof(*stp_req), parent); + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; dev_dbg(&ihost->pdev->dev, "%s: request = %p, status=%d\n", -- cgit v1.2.3 From 0d84366fbef557f92ef82ac9a224c57ffb3318bc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 8 May 2011 01:56:57 -0700 Subject: isci: make sgl explicit/aligned request object member Towards unifying request objects we need all members to be defined in the object and not carved out of anonymous buffer space. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_request.c | 11 ++--------- drivers/scsi/isci/core/scic_sds_request.h | 14 +++++--------- drivers/scsi/isci/core/scic_sds_smp_request.c | 1 - drivers/scsi/isci/core/scic_sds_stp_request.c | 18 +----------------- drivers/scsi/isci/request.c | 14 ++++---------- drivers/scsi/isci/request.h | 13 +++---------- drivers/scsi/isci/task.c | 12 ++++-------- 7 files changed, 19 insertions(+), 64 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index fd7bd334fa4b..189a7999726c 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -212,8 +212,7 @@ static u32 scic_sds_ssp_request_get_object_size(void) return sizeof(struct scic_sds_request) + scic_ssp_io_request_get_object_size() + sizeof(struct scu_task_context) - + SMP_CACHE_BYTES - + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; + + SMP_CACHE_BYTES; } /** @@ -239,7 +238,7 @@ static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( return &task_context->sgl_pair_cd; } - return &sci_req->sgl_element_pair_buffer[sgl_pair_index - 2]; + return &sci_req->sg_table[sgl_pair_index - 2]; } /** @@ -328,11 +327,6 @@ static void scic_sds_ssp_io_request_assign_buffers( scic_sds_ssp_request_get_command_buffer(sci_req); sci_req->response_buffer = scic_sds_ssp_request_get_response_buffer(sci_req); - sci_req->sgl_element_pair_buffer = - scic_sds_ssp_request_get_sgl_element_buffer(sci_req); - sci_req->sgl_element_pair_buffer = - PTR_ALIGN(sci_req->sgl_element_pair_buffer, - sizeof(struct scu_sgl_element_pair)); if (sci_req->was_tag_assigned_by_user == false) { sci_req->task_context_buffer = @@ -535,7 +529,6 @@ static void scic_sds_ssp_task_request_assign_buffers( scic_sds_ssp_task_request_get_command_buffer(sci_req); sci_req->response_buffer = scic_sds_ssp_task_request_get_response_buffer(sci_req); - sci_req->sgl_element_pair_buffer = NULL; if (sci_req->was_tag_assigned_by_user == false) { sci_req->task_context_buffer = diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index c93f3ed8946d..83d737adbc48 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -60,6 +60,7 @@ #include "sci_base_state_machine.h" #include "scu_task_context.h" #include "scic_sds_stp_request.h" +#include "scu_constants.h" struct scic_sds_controller; struct scic_sds_remote_device; @@ -183,7 +184,10 @@ struct scic_sds_request { void *command_buffer; void *response_buffer; struct scu_task_context *task_context_buffer; - struct scu_sgl_element_pair *sgl_element_pair_buffer; + + /* could be larger with sg chaining */ + #define SCU_SGL_SIZE ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) + struct scu_sgl_element_pair sg_table[SCU_SGL_SIZE] __attribute__ ((aligned(32))); /** * This field indicates if this request is a task management request or @@ -327,14 +331,6 @@ struct scic_sds_io_request_state_handler { extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[]; -/** - * - * - * This macro returns the maximum number of SGL element paris that we will - * support in a single IO request. - */ -#define SCU_MAX_SGL_ELEMENT_PAIRS ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) - /** * scic_sds_request_get_controller() - * diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 1f8773d3b793..cb1adef1d559 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -131,7 +131,6 @@ void scic_sds_smp_request_assign_buffers( scic_sds_smp_request_get_command_buffer(sci_req); sci_req->response_buffer = scic_sds_smp_request_get_response_buffer(sci_req); - sci_req->sgl_element_pair_buffer = NULL; if (sci_req->was_tag_assigned_by_user == false) { sci_req->task_context_buffer = diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 7dba40fc2585..013af11df62b 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -105,18 +105,6 @@ + SSP_RESP_IU_MAX_SIZE \ )) -/** - * scic_sds_stp_request_get_sgl_element_buffer() - - * - * This macro returns the address of the sgl elment pairs in the io request - * memory buffer - */ -#define scic_sds_stp_request_get_sgl_element_buffer(memory) \ - ((struct scu_sgl_element_pair *)(\ - ((char *)(scic_sds_stp_request_get_task_context_buffer(memory))) \ - + sizeof(struct scu_task_context) \ - )) - /** * * @@ -128,8 +116,7 @@ u32 scic_sds_stp_request_get_object_size(void) + sizeof(struct host_to_dev_fis) + sizeof(struct dev_to_host_fis) + sizeof(struct scu_task_context) - + SMP_CACHE_BYTES - + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; + + SMP_CACHE_BYTES; } void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) @@ -138,9 +125,6 @@ void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) sci_req->command_buffer = scic_sds_stp_request_get_h2d_reg_buffer(stp_req); sci_req->response_buffer = scic_sds_stp_request_get_response_buffer(stp_req); - sci_req->sgl_element_pair_buffer = scic_sds_stp_request_get_sgl_element_buffer(stp_req); - sci_req->sgl_element_pair_buffer = PTR_ALIGN(sci_req->sgl_element_pair_buffer, - sizeof(struct scu_sgl_element_pair)); if (sci_req->was_tag_assigned_by_user == false) { sci_req->task_context_buffer = diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index e01c2c98f4e9..9dd971a3fbb2 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -200,14 +200,10 @@ static enum sci_status isci_io_request_build( /* build the common request object. For now, * we will let the core allocate the IO tag. */ - status = scic_io_request_construct( - &isci_host->sci, - sci_device, - SCI_CONTROLLER_INVALID_IO_TAG, - request, - request->sci_request_mem_ptr, - (struct scic_sds_request **)&request->sci_request_handle - ); + status = scic_io_request_construct(&isci_host->sci, sci_device, + SCI_CONTROLLER_INVALID_IO_TAG, + request, request->sci_req, + &request->sci_request_handle); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -277,8 +273,6 @@ static int isci_request_alloc_core( /* initialize the request object. */ spin_lock_init(&request->state_lock); - request->sci_request_mem_ptr = ((u8 *)request) + - sizeof(struct isci_request); request->request_daddr = handle; request->isci_host = isci_host; request->isci_device = isci_device; diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 9c97715e54d8..ddfbf71c97e5 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -53,10 +53,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if !defined(_ISCI_REQUEST_H_) +#ifndef _ISCI_REQUEST_H_ #define _ISCI_REQUEST_H_ #include "isci.h" +#include "scic_sds_request.h" /** * struct isci_request_status - This enum defines the possible states of an I/O @@ -80,16 +81,8 @@ enum task_type { tmf_task = 1 }; -/** - * struct isci_request - This class represents the request object used to track - * IO, smp and TMF request internal. It wraps the SCIC request object. - * - * - */ struct isci_request { - struct scic_sds_request *sci_request_handle; - enum isci_request_status status; enum task_type ttype; unsigned short io_tag; @@ -105,7 +98,6 @@ struct isci_request { struct list_head completed_node; /* For use in the reqs_in_process list: */ struct list_head dev_node; - void *sci_request_mem_ptr; spinlock_t state_lock; dma_addr_t request_daddr; dma_addr_t zero_scatter_daddr; @@ -123,6 +115,7 @@ struct isci_request { * TMF was aborting is guaranteed to have completed. */ struct completion *io_request_completion; + struct scic_sds_request sci_req[0] ____cacheline_aligned; }; /** diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 12f2df947362..7d5f79378452 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -298,14 +298,10 @@ static enum sci_status isci_task_request_build( goto out; /* let the core do it's construct. */ - status = scic_task_request_construct( - &isci_host->sci, - sci_device, - SCI_CONTROLLER_INVALID_IO_TAG, - request, - request->sci_request_mem_ptr, - &request->sci_request_handle - ); + status = scic_task_request_construct(&isci_host->sci, sci_device, + SCI_CONTROLLER_INVALID_IO_TAG, + request, &request->sci_req, + &request->sci_request_handle); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, -- cgit v1.2.3 From 26298264a5de6d46d6e872dfd4c5d14c3011666f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 May 2011 19:07:14 -0700 Subject: isci: move task context alignment from run-time to compile time Remove usage of PTR_ALIGN by arranging for the task context to be aligned by the compiler. Another step towards unifying isci_request and scic_sds_request. Once this is complete the task context in the request can likely be removed in favor of building the task directly to tc memory (see: scic_sds_controller_copy_task_context). It's not clear why this needs to be cacheline aligned if we just end up copying before submission... Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_request.c | 64 +++------------------------ drivers/scsi/isci/core/scic_sds_request.h | 1 + drivers/scsi/isci/core/scic_sds_smp_request.c | 37 ++-------------- drivers/scsi/isci/core/scic_sds_stp_request.c | 24 ++-------- 4 files changed, 13 insertions(+), 113 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 189a7999726c..baf69edab699 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -124,31 +124,6 @@ + sizeof(struct ssp_cmd_iu) \ )) -/** - * scic_sds_ssp_request_get_task_context_buffer() - - * - * This macro returns the address of the task context buffer in the io request - * memory - */ -#define scic_sds_ssp_request_get_task_context_buffer(memory) \ - ((struct scu_task_context *)(\ - ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \ - + SSP_RESP_IU_MAX_SIZE \ - )) - -/** - * scic_sds_ssp_request_get_sgl_element_buffer() - - * - * This macro returns the address of the sgl elment pairs in the io request - * memory buffer - */ -#define scic_sds_ssp_request_get_sgl_element_buffer(memory) \ - ((struct scu_sgl_element_pair *)(\ - ((char *)(scic_sds_ssp_request_get_task_context_buffer(memory))) \ - + sizeof(struct scu_task_context) \ - )) - - /** * scic_ssp_task_request_get_object_size() - * @@ -184,24 +159,6 @@ + sizeof(struct ssp_task_iu) \ )) -/** - * scic_sds_ssp_task_request_get_task_context_buffer() - - * - * This macro returs the task context buffer for the SSP task request. - */ -#define scic_sds_ssp_task_request_get_task_context_buffer(memory) \ - ((struct scu_task_context *)(\ - ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \ - + SSP_RESP_IU_MAX_SIZE \ - )) - - - -/* - * **************************************************************************** - * * SCIC SDS IO REQUEST PRIVATE METHODS - * **************************************************************************** */ - /** * * @@ -210,9 +167,7 @@ static u32 scic_sds_ssp_request_get_object_size(void) { return sizeof(struct scic_sds_request) - + scic_ssp_io_request_get_object_size() - + sizeof(struct scu_task_context) - + SMP_CACHE_BYTES; + + scic_ssp_io_request_get_object_size(); } /** @@ -328,13 +283,8 @@ static void scic_sds_ssp_io_request_assign_buffers( sci_req->response_buffer = scic_sds_ssp_request_get_response_buffer(sci_req); - if (sci_req->was_tag_assigned_by_user == false) { - sci_req->task_context_buffer = - scic_sds_ssp_request_get_task_context_buffer(sci_req); - sci_req->task_context_buffer = - PTR_ALIGN(sci_req->task_context_buffer, - SMP_CACHE_BYTES); - } + if (sci_req->was_tag_assigned_by_user == false) + sci_req->task_context_buffer = &sci_req->tc; } static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) @@ -530,12 +480,8 @@ static void scic_sds_ssp_task_request_assign_buffers( sci_req->response_buffer = scic_sds_ssp_task_request_get_response_buffer(sci_req); - if (sci_req->was_tag_assigned_by_user == false) { - sci_req->task_context_buffer = - scic_sds_ssp_task_request_get_task_context_buffer(sci_req); - sci_req->task_context_buffer = - PTR_ALIGN(sci_req->task_context_buffer, SMP_CACHE_BYTES); - } + if (sci_req->was_tag_assigned_by_user == false) + sci_req->task_context_buffer = &sci_req->tc; } /** diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 83d737adbc48..8f65814e79c8 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -184,6 +184,7 @@ struct scic_sds_request { void *command_buffer; void *response_buffer; struct scu_task_context *task_context_buffer; + struct scu_task_context tc ____cacheline_aligned; /* could be larger with sg chaining */ #define SCU_SGL_SIZE ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index cb1adef1d559..53b1260f44bc 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -78,9 +78,7 @@ u32 scic_sds_smp_request_get_object_size(void) { return sizeof(struct scic_sds_request) + sizeof(struct smp_req) - + sizeof(struct smp_resp) - + sizeof(struct scu_task_context) - + SMP_CACHE_BYTES; + + sizeof(struct smp_resp); } /** @@ -102,29 +100,7 @@ u32 scic_sds_smp_request_get_object_size(void) (((char *)(scic_sds_smp_request_get_command_buffer(memory))) \ + sizeof(struct smp_req)) -/** - * scic_sds_smp_request_get_task_context_buffer() - - * - * This macro returs the task context buffer for the SMP request. - */ -#define scic_sds_smp_request_get_task_context_buffer(memory) \ - ((struct scu_task_context *)(\ - ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \ - + sizeof(struct smp_resp) \ - )) - - - -/** - * This method build the remainder of the IO request object. - * @sci_req: This parameter specifies the request object being constructed. - * - * The scic_sds_general_request_construct() must be called before this call is - * valid. none - */ - -void scic_sds_smp_request_assign_buffers( - struct scic_sds_request *sci_req) +void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req) { /* Assign all of the buffer pointers */ sci_req->command_buffer = @@ -132,13 +108,8 @@ void scic_sds_smp_request_assign_buffers( sci_req->response_buffer = scic_sds_smp_request_get_response_buffer(sci_req); - if (sci_req->was_tag_assigned_by_user == false) { - sci_req->task_context_buffer = - scic_sds_smp_request_get_task_context_buffer(sci_req); - sci_req->task_context_buffer = - PTR_ALIGN(sci_req->task_context_buffer, SMP_CACHE_BYTES); - } - + if (sci_req->was_tag_assigned_by_user == false) + sci_req->task_context_buffer = &sci_req->tc; } /* diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 013af11df62b..f21354571ff8 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -93,18 +93,6 @@ + sizeof(struct host_to_dev_fis) \ )) -/** - * scic_sds_stp_request_get_task_context_buffer() - - * - * This macro returns the address of the task context buffer in the io request - * memory - */ -#define scic_sds_stp_request_get_task_context_buffer(memory) \ - ((struct scu_task_context *)(\ - ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \ - + SSP_RESP_IU_MAX_SIZE \ - )) - /** * * @@ -114,9 +102,7 @@ u32 scic_sds_stp_request_get_object_size(void) { return sizeof(struct scic_sds_stp_request) + sizeof(struct host_to_dev_fis) - + sizeof(struct dev_to_host_fis) - + sizeof(struct scu_task_context) - + SMP_CACHE_BYTES; + + sizeof(struct dev_to_host_fis); } void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) @@ -126,12 +112,8 @@ void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) sci_req->command_buffer = scic_sds_stp_request_get_h2d_reg_buffer(stp_req); sci_req->response_buffer = scic_sds_stp_request_get_response_buffer(stp_req); - if (sci_req->was_tag_assigned_by_user == false) { - sci_req->task_context_buffer = - scic_sds_stp_request_get_task_context_buffer(stp_req); - sci_req->task_context_buffer = PTR_ALIGN(sci_req->task_context_buffer, - SMP_CACHE_BYTES); - } + if (sci_req->was_tag_assigned_by_user == false) + sci_req->task_context_buffer = &sci_req->tc; } /** -- cgit v1.2.3 From b7645818cff1536038c0b21407eefb6b9d5755e6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 8 May 2011 02:35:32 -0700 Subject: isci: make command/response iu explicit request object members Final elimination of the anonymous data at the end of the request structure. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_io_request.h | 61 --------- drivers/scsi/isci/core/scic_sds_request.c | 178 +++----------------------- drivers/scsi/isci/core/scic_sds_request.h | 30 ++++- drivers/scsi/isci/core/scic_sds_smp_request.c | 62 ++------- drivers/scsi/isci/core/scic_sds_stp_request.c | 101 +++------------ drivers/scsi/isci/core/scic_sds_stp_request.h | 2 - drivers/scsi/isci/host.c | 2 +- drivers/scsi/isci/request.c | 31 +---- drivers/scsi/isci/sata.c | 55 ++++---- drivers/scsi/isci/task.c | 5 +- 10 files changed, 104 insertions(+), 423 deletions(-) diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h index 6ddf3801daf8..cb3667decb3c 100644 --- a/drivers/scsi/isci/core/scic_io_request.h +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -103,14 +103,6 @@ typedef enum { } SCIC_TRANSPORT_PROTOCOL; -/** - * scic_io_request_get_object_size() - This method simply returns the size - * required to build an SCI based IO request object. - * - * Return the size of the SCI IO request object. - */ -u32 scic_io_request_get_object_size(void); - /** * scic_io_request_construct() - This method is called by the SCI user to * construct all SCI Core IO requests. Memory initialization and @@ -222,32 +214,6 @@ enum sci_status scic_io_request_construct_smp( u32 scic_request_get_controller_status( struct scic_sds_request *io_request); - - -/** - * scic_io_request_get_command_iu_address() - This method will return the - * address to the command information unit. - * @scic_io_request: This parameter specifies the handle to the io request - * object to be built. - * - * The address of the SSP/SMP command information unit. - */ -void *scic_io_request_get_command_iu_address( - struct scic_sds_request *scic_io_request); - -/** - * scic_io_request_get_response_iu_address() - This method will return the - * address to the response information unit. For an SSP request this buffer - * is only valid if the IO request is completed with the status - * SCI_FAILURE_IO_RESPONSE_VALID. - * @scic_io_request: This parameter specifies the handle to the io request - * object to be built. - * - * The address of the SSP/SMP response information unit. - */ -void *scic_io_request_get_response_iu_address( - struct scic_sds_request *scic_io_request); - /** * scic_io_request_get_io_tag() - This method will return the IO tag utilized * by the IO request. @@ -279,33 +245,6 @@ void scic_stp_io_request_set_ncq_tag( struct scic_sds_request *scic_io_request, u16 ncq_tag); -/** - * scic_stp_io_request_get_h2d_reg_address() - This method will return the - * address of the host to device register fis region for the io request - * object. - * @scic_io_request: This parameter specifies the handle to the io request - * object from which to get the host to device register fis buffer. - * - * The address of the host to device register fis buffer in the io request - * object. This function is only valid for SATA requests. - */ -void *scic_stp_io_request_get_h2d_reg_address( - struct scic_sds_request *scic_io_request); - -/** - * scic_stp_io_request_get_d2h_reg_address() - This method will return the - * address of the device to host register fis region for the io request - * object. - * @scic_io_request: This parameter specifies teh handle to the io request - * object from which to get the device to host register fis buffer. - * - * The address fo the device to host register fis ending the io request. This - * function is only valid for SATA requests. - */ -void *scic_stp_io_request_get_d2h_reg_address( - struct scic_sds_request *scic_io_request); - - /** * scic_io_request_get_number_of_bytes_transferred() - This method will return * the number of bytes transferred from the SCU diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index baf69edab699..36c2b310c175 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -83,93 +83,6 @@ #define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0) #define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0) -/* - * **************************************************************************** - * * SCIC SDS IO REQUEST MACROS - * **************************************************************************** */ - -/** - * scic_ssp_io_request_get_object_size() - - * - * This macro returns the sizeof memory required to store the an SSP IO - * request. This does not include the size of the SGL or SCU Task Context - * memory. - */ -#define scic_ssp_io_request_get_object_size() \ - (\ - sizeof(struct ssp_cmd_iu) \ - + SSP_RESP_IU_MAX_SIZE \ - ) - -/** - * scic_sds_ssp_request_get_command_buffer() - - * - * This macro returns the address of the ssp command buffer in the io request - * memory - */ -#define scic_sds_ssp_request_get_command_buffer(memory) \ - ((struct ssp_cmd_iu *)(\ - ((char *)(memory)) + sizeof(struct scic_sds_request) \ - )) - -/** - * scic_sds_ssp_request_get_response_buffer() - - * - * This macro returns the address of the ssp response buffer in the io request - * memory - */ -#define scic_sds_ssp_request_get_response_buffer(memory) \ - ((struct ssp_response_iu *)(\ - ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \ - + sizeof(struct ssp_cmd_iu) \ - )) - -/** - * scic_ssp_task_request_get_object_size() - - * - * This macro returns the sizeof of memory required to store an SSP Task - * request. This does not include the size of the SCU Task Context memory. - */ -#define scic_ssp_task_request_get_object_size() \ - (\ - sizeof(struct ssp_task_iu) \ - + SSP_RESP_IU_MAX_SIZE \ - ) - -/** - * scic_sds_ssp_task_request_get_command_buffer() - - * - * This macro returns the address of the ssp command buffer in the task request - * memory. Yes its the same as the above macro except for the name. - */ -#define scic_sds_ssp_task_request_get_command_buffer(memory) \ - ((struct ssp_task_iu *)(\ - ((char *)(memory)) + sizeof(struct scic_sds_request) \ - )) - -/** - * scic_sds_ssp_task_request_get_response_buffer() - - * - * This macro returns the address of the ssp response buffer in the task - * request memory. - */ -#define scic_sds_ssp_task_request_get_response_buffer(memory) \ - ((struct ssp_response_iu *)(\ - ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \ - + sizeof(struct ssp_task_iu) \ - )) - -/** - * - * - * This method returns the size required to store an SSP IO request object. u32 - */ -static u32 scic_sds_ssp_request_get_object_size(void) -{ - return sizeof(struct scic_sds_request) - + scic_ssp_io_request_get_object_size(); -} - /** * This method returns the sgl element pair for the specificed sgl_pair index. * @sci_req: This parameter specifies the IO request for which to retrieve @@ -268,21 +181,8 @@ void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) } } -/** - * This method build the remainder of the IO request object. - * @sci_req: This parameter specifies the request object being constructed. - * - * The scic_sds_general_request_construct() must be called before this call is - * valid. none - */ -static void scic_sds_ssp_io_request_assign_buffers( - struct scic_sds_request *sci_req) +static void scic_sds_ssp_io_request_assign_buffers(struct scic_sds_request *sci_req) { - sci_req->command_buffer = - scic_sds_ssp_request_get_command_buffer(sci_req); - sci_req->response_buffer = - scic_sds_ssp_request_get_response_buffer(sci_req); - if (sci_req->was_tag_assigned_by_user == false) sci_req->task_context_buffer = &sci_req->tc; } @@ -293,7 +193,7 @@ static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sc struct isci_request *ireq = sci_req->ireq; struct sas_task *task = isci_request_access_task(ireq); - cmd_iu = sci_req->command_buffer; + cmd_iu = &sci_req->ssp.cmd; memcpy(cmd_iu->LUN, task->ssp_task.LUN, 8); cmd_iu->add_cdb_len = 0; @@ -315,7 +215,7 @@ static void scic_sds_task_request_build_ssp_task_iu(struct scic_sds_request *sci struct sas_task *task = isci_request_access_task(ireq); struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - task_iu = sci_req->command_buffer; + task_iu = &sci_req->ssp.tmf; memset(task_iu, 0, sizeof(struct ssp_task_iu)); @@ -411,7 +311,7 @@ static void scu_ssp_reqeust_construct_task_context( * SCU Task Context */ dma_addr = scic_io_request_get_dma_addr(sds_request, - sds_request->command_buffer); + &sds_request->ssp.cmd); task_context->command_iu_upper = upper_32_bits(dma_addr); task_context->command_iu_lower = lower_32_bits(dma_addr); @@ -421,7 +321,7 @@ static void scu_ssp_reqeust_construct_task_context( * SCU Task Context */ dma_addr = scic_io_request_get_dma_addr(sds_request, - sds_request->response_buffer); + &sds_request->ssp.rsp); task_context->response_iu_upper = upper_32_bits(dma_addr); task_context->response_iu_lower = lower_32_bits(dma_addr); @@ -464,22 +364,8 @@ static void scu_ssp_io_request_construct_task_context( scic_sds_request_build_sgl(sci_req); } - -/** - * This method will fill in the remainder of the io request object for SSP Task - * requests. - * @sci_req: - * - */ -static void scic_sds_ssp_task_request_assign_buffers( - struct scic_sds_request *sci_req) +static void scic_sds_ssp_task_request_assign_buffers(struct scic_sds_request *sci_req) { - /* Assign all of the buffer pointers */ - sci_req->command_buffer = - scic_sds_ssp_task_request_get_command_buffer(sci_req); - sci_req->response_buffer = - scic_sds_ssp_task_request_get_response_buffer(sci_req); - if (sci_req->was_tag_assigned_by_user == false) sci_req->task_context_buffer = &sci_req->tc; } @@ -589,19 +475,6 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, return status; } -u32 scic_io_request_get_object_size(void) -{ - u32 ssp_request_size; - u32 stp_request_size; - u32 smp_request_size; - - ssp_request_size = scic_sds_ssp_request_get_object_size(); - stp_request_size = scic_sds_stp_request_get_object_size(); - smp_request_size = scic_sds_smp_request_get_object_size(); - - return max(ssp_request_size, max(stp_request_size, smp_request_size)); -} - enum sci_status scic_io_request_construct_basic_ssp( struct scic_sds_request *sci_req) { @@ -712,21 +585,6 @@ u32 scic_request_get_controller_status( return sci_req->scu_status; } - -void *scic_io_request_get_command_iu_address( - struct scic_sds_request *sci_req) -{ - return sci_req->command_buffer; -} - - -void *scic_io_request_get_response_iu_address( - struct scic_sds_request *sci_req) -{ - return sci_req->response_buffer; -} - - #define SCU_TASK_CONTEXT_SRAM 0x200000 u32 scic_io_request_get_number_of_bytes_transferred( struct scic_sds_request *scic_sds_request) @@ -885,7 +743,7 @@ void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) struct isci_request *ireq = sci_req->ireq; struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - ssp_response = sci_req->response_buffer; + ssp_response = &sci_req->ssp.rsp; resp_buf = &isci_tmf->resp.resp_iu; @@ -1053,11 +911,11 @@ scic_sds_request_started_state_tc_completion_handler( * truly a failed request or a good request that just got * completed early. */ - struct ssp_response_iu *resp = sci_req->response_buffer; + struct ssp_response_iu *resp = &sci_req->ssp.rsp; ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - sci_swab32_cpy(sci_req->response_buffer, - sci_req->response_buffer, + sci_swab32_cpy(&sci_req->ssp.rsp, + &sci_req->ssp.rsp, word_cnt); if (resp->status == 0) { @@ -1078,8 +936,8 @@ scic_sds_request_started_state_tc_completion_handler( { ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - sci_swab32_cpy(sci_req->response_buffer, - sci_req->response_buffer, + sci_swab32_cpy(&sci_req->ssp.rsp, + &sci_req->ssp.rsp, word_cnt); scic_sds_request_set_status(sci_req, @@ -1094,7 +952,7 @@ scic_sds_request_started_state_tc_completion_handler( * guaranteed to be received before this completion status is * posted? */ - resp_iu = sci_req->response_buffer; + resp_iu = &sci_req->ssp.rsp; datapres = resp_iu->datapres; if ((datapres == 0x01) || (datapres == 0x02)) { @@ -1222,10 +1080,10 @@ scic_sds_request_started_state_frame_handler(struct scic_sds_request *sci_req, frame_index, (void **)&resp_iu); - sci_swab32_cpy(sci_req->response_buffer, + sci_swab32_cpy(&sci_req->ssp.rsp, resp_iu, word_cnt); - resp_iu = sci_req->response_buffer; + resp_iu = &sci_req->ssp.rsp; if ((resp_iu->datapres == 0x01) || (resp_iu->datapres == 0x02)) { @@ -1627,12 +1485,10 @@ scic_io_request_construct(struct scic_sds_controller *scic, else if ((dev->dev_type == SATA_DEV) || (dev->tproto & SAS_PROTOCOL_STP)) { scic_sds_stp_request_assign_buffers(sci_req); - memset(sci_req->command_buffer, - 0, - sizeof(struct host_to_dev_fis)); + memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); } else if (dev_is_expander(dev)) { scic_sds_smp_request_assign_buffers(sci_req); - memset(sci_req->command_buffer, 0, sizeof(struct smp_req)); + memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); } else status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 8f65814e79c8..3f551eaf3dfa 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -61,6 +61,7 @@ #include "scu_task_context.h" #include "scic_sds_stp_request.h" #include "scu_constants.h" +#include "sas.h" struct scic_sds_controller; struct scic_sds_remote_device; @@ -181,8 +182,6 @@ struct scic_sds_request { */ u32 post_context; - void *command_buffer; - void *response_buffer; struct scu_task_context *task_context_buffer; struct scu_task_context tc ____cacheline_aligned; @@ -232,9 +231,30 @@ struct scic_sds_request { */ u8 device_sequence; - struct { - struct scic_sds_stp_request req; - } stp; + union { + struct { + union { + struct ssp_cmd_iu cmd; + struct ssp_task_iu tmf; + }; + union { + struct ssp_response_iu rsp; + u8 rsp_buf[SSP_RESP_IU_MAX_SIZE]; + }; + } ssp; + + struct { + struct smp_req cmd; + struct smp_resp rsp; + } smp; + + struct { + struct scic_sds_stp_request req; + struct host_to_dev_fis cmd; + struct dev_to_host_fis rsp; + } stp; + }; + }; static inline struct scic_sds_request *to_sci_req(struct scic_sds_stp_request *stp_req) diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 53b1260f44bc..2b911206e8d2 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -69,45 +69,8 @@ static void scu_smp_request_construct_task_context( struct scic_sds_request *sci_req, struct smp_req *smp_req); -/** - * - * - * This method return the memory space required for STP PIO requests. u32 - */ -u32 scic_sds_smp_request_get_object_size(void) -{ - return sizeof(struct scic_sds_request) - + sizeof(struct smp_req) - + sizeof(struct smp_resp); -} - -/** - * scic_sds_smp_request_get_command_buffer() - - * - * This macro returns the address of the smp command buffer in the smp request - * memory. No need to cast to SMP request type. - */ -#define scic_sds_smp_request_get_command_buffer(memory) \ - (((char *)(memory)) + sizeof(struct scic_sds_request)) - -/** - * scic_sds_smp_request_get_response_buffer() - - * - * This macro returns the address of the smp response buffer in the smp request - * memory. - */ -#define scic_sds_smp_request_get_response_buffer(memory) \ - (((char *)(scic_sds_smp_request_get_command_buffer(memory))) \ - + sizeof(struct smp_req)) - void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req) { - /* Assign all of the buffer pointers */ - sci_req->command_buffer = - scic_sds_smp_request_get_command_buffer(sci_req); - sci_req->response_buffer = - scic_sds_smp_request_get_response_buffer(sci_req); - if (sci_req->was_tag_assigned_by_user == false) sci_req->task_context_buffer = &sci_req->tc; } @@ -135,7 +98,7 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); /* byte swap the smp request. */ - sci_swab32_cpy(sci_req->command_buffer, smp_req, + sci_swab32_cpy(&sci_req->smp.cmd, smp_req, word_cnt); task_context = scic_sds_request_get_task_context(sci_req); @@ -185,9 +148,7 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, * 18h ~ 30h, protocol specific * since commandIU has been build by framework at this point, we just * copy the frist DWord from command IU to this location. */ - memcpy((void *)(&task_context->type.smp), - sci_req->command_buffer, - sizeof(u32)); + memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); /* * 40h @@ -228,8 +189,7 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, * Context command buffer should not contain command header. */ dma_addr = scic_io_request_get_dma_addr(sci_req, - (char *) - (sci_req->command_buffer) + + ((char *) &sci_req->smp.cmd) + sizeof(u32)); task_context->command_iu_upper = upper_32_bits(dma_addr); @@ -255,14 +215,12 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, * indicates successful processing of the TC response. */ static enum sci_status -scic_sds_smp_request_await_response_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) +scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) { enum sci_status status; void *frame_header; - struct smp_resp *rsp_hdr; - u8 *usr_smp_buf = sci_req->response_buffer; + struct smp_resp *rsp_hdr = &sci_req->smp.rsp; ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); status = scic_sds_unsolicited_frame_control_get_header( @@ -271,9 +229,7 @@ scic_sds_smp_request_await_response_frame_handler( &frame_header); /* byte swap the header. */ - sci_swab32_cpy(usr_smp_buf, frame_header, word_cnt); - - rsp_hdr = (struct smp_resp *)usr_smp_buf; + sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); if (rsp_hdr->frame_type == SMP_RESPONSE) { void *smp_resp; @@ -286,7 +242,7 @@ scic_sds_smp_request_await_response_frame_handler( word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / sizeof(u32); - sci_swab32_cpy(usr_smp_buf + SMP_RESP_HDR_SZ, + sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, smp_resp, word_cnt); scic_sds_request_set_status( @@ -532,7 +488,7 @@ enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) ); /* Construct the SMP SCU Task Context */ - memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req)); + memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req)); /* * Look at the SMP requests' header fields; for certain SAS 1.x SMP diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index f21354571ff8..c7a8931a3bcb 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -70,48 +70,8 @@ #include "scu_event_codes.h" #include "scu_task_context.h" -/** - * scic_sds_stp_request_get_h2d_reg_buffer() - - * - * This macro returns the address of the stp h2d reg fis buffer in the io - * request memory - */ -#define scic_sds_stp_request_get_h2d_reg_buffer(memory) \ - ((struct host_to_dev_fis *)(\ - ((char *)(memory)) + sizeof(struct scic_sds_stp_request) \ - )) - -/** - * scic_sds_stp_request_get_response_buffer() - - * - * This macro returns the address of the ssp response iu buffer in the io - * request memory - */ -#define scic_sds_stp_request_get_response_buffer(memory) \ - ((struct dev_to_host_fis *)(\ - ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \ - + sizeof(struct host_to_dev_fis) \ - )) - -/** - * - * - * This method return the memory space required for STP PIO requests. u32 - */ -u32 scic_sds_stp_request_get_object_size(void) -{ - return sizeof(struct scic_sds_stp_request) - + sizeof(struct host_to_dev_fis) - + sizeof(struct dev_to_host_fis); -} - void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) { - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - sci_req->command_buffer = scic_sds_stp_request_get_h2d_reg_buffer(stp_req); - sci_req->response_buffer = scic_sds_stp_request_get_response_buffer(stp_req); - if (sci_req->was_tag_assigned_by_user == false) sci_req->task_context_buffer = &sci_req->tc; } @@ -129,7 +89,7 @@ void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) * determine what is common for SSP/SMP/STP task context structures. */ static void scu_sata_reqeust_construct_task_context( - struct scic_sds_request *sds_request, + struct scic_sds_request *sci_req, struct scu_task_context *task_context) { dma_addr_t dma_addr; @@ -137,9 +97,9 @@ static void scu_sata_reqeust_construct_task_context( struct scic_sds_remote_device *target_device; struct scic_sds_port *target_port; - controller = scic_sds_request_get_controller(sds_request); - target_device = scic_sds_request_get_device(sds_request); - target_port = scic_sds_request_get_port(sds_request); + controller = scic_sds_request_get_controller(sci_req); + target_device = scic_sds_request_get_device(sci_req); + target_port = scic_sds_request_get_port(sci_req); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -155,7 +115,7 @@ static void scu_sata_reqeust_construct_task_context( task_context->context_type = SCU_TASK_CONTEXT_TYPE; task_context->remote_node_index = - scic_sds_remote_device_get_index(sds_request->target_device); + scic_sds_remote_device_get_index(sci_req->target_device); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -172,21 +132,21 @@ static void scu_sata_reqeust_construct_task_context( (sizeof(struct host_to_dev_fis) - sizeof(u32)) / sizeof(u32); /* Set the first word of the H2D REG FIS */ - task_context->type.words[0] = *(u32 *)sds_request->command_buffer; + task_context->type.words[0] = *(u32 *)&sci_req->stp.cmd; - if (sds_request->was_tag_assigned_by_user) { + if (sci_req->was_tag_assigned_by_user) { /* * Build the task context now since we have already read * the data */ - sds_request->post_context = + sci_req->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | (scic_sds_controller_get_protocol_engine_group( controller) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | (scic_sds_port_get_index(target_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sds_request->io_tag)); + scic_sds_io_tag_get_index(sci_req->io_tag)); } else { /* * Build the task context now since we have already read @@ -194,7 +154,7 @@ static void scu_sata_reqeust_construct_task_context( * I/O tag index is not assigned because we have to wait * until we get a TCi. */ - sds_request->post_context = + sci_req->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | (scic_sds_controller_get_protocol_engine_group( controller) << @@ -208,11 +168,9 @@ static void scu_sata_reqeust_construct_task_context( * Context. We must offset the command buffer by 4 bytes because the * first 4 bytes are transfered in the body of the TC. */ - dma_addr = - scic_io_request_get_dma_addr(sds_request, - (char *)sds_request-> - command_buffer + - sizeof(u32)); + dma_addr = scic_io_request_get_dma_addr(sci_req, + ((char *) &sci_req->stp.cmd) + + sizeof(u32)); task_context->command_iu_upper = upper_32_bits(dma_addr); task_context->command_iu_lower = lower_32_bits(dma_addr); @@ -334,21 +292,6 @@ void scic_stp_io_request_set_ncq_tag( req->task_context_buffer->type.stp.ncq_tag = ncq_tag; } - -void *scic_stp_io_request_get_h2d_reg_address( - struct scic_sds_request *req) -{ - return req->command_buffer; -} - - -void *scic_stp_io_request_get_d2h_reg_address(struct scic_sds_request *sci_req) -{ - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - return &stp_req->d2h_reg_fis; -} - /** * * @sci_req: @@ -478,7 +421,7 @@ static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, frame_header, frame_buffer); @@ -830,11 +773,11 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct /* ending_status: 4th byte in the 3rd dword */ stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; - scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, frame_header, frame_buffer); - stp_req->d2h_reg_fis.status = stp_req->type.pio.ending_status; + sci_req->stp.rsp.status = stp_req->type.pio.ending_status; /* The next state is dependent on whether the * request was PIO Data-in or Data out @@ -873,7 +816,7 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + scic_sds_controller_copy_sata_response(&sci_req->stp.req, frame_header, frame_buffer); @@ -1220,7 +1163,6 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct sc u32 frame_index) { struct scic_sds_controller *scic = sci_req->owning_controller; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; struct dev_to_host_fis *frame_header; enum sci_status status; u32 *frame_buffer; @@ -1235,7 +1177,7 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct sc frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, frame_header, frame_buffer); } @@ -1249,7 +1191,6 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi struct scic_sds_request *sci_req, u32 completion_code) { - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; enum sci_status status = SCI_SUCCESS; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { @@ -1263,7 +1204,7 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi /* * We must check ther response buffer to see if the D2H Register FIS was * received before we got the TC completion. */ - if (stp_req->d2h_reg_fis.fis_type == FIS_REGD2H) { + if (sci_req->stp.rsp.fis_type == FIS_REGD2H) { scic_sds_remote_device_suspend(sci_req->target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); @@ -1523,7 +1464,7 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&stp_req->d2h_reg_fis, + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, frame_header, frame_buffer); @@ -1595,7 +1536,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet enum sci_status status; /* Clear the SRST bit */ - h2d_fis = scic_stp_io_request_get_h2d_reg_address(sci_req); + h2d_fis = &sci_req->stp.cmd; h2d_fis->control = 0; /* Clear the TC control bit */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h index 6d02030b6cd6..f5434f12ad06 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h @@ -60,8 +60,6 @@ #include struct scic_sds_stp_request { - struct dev_to_host_fis d2h_reg_fis; - union { u32 ncq; diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index cdd99304c363..4d0ee7bf847b 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -433,7 +433,7 @@ int isci_host_init(struct isci_host *isci_host) * when trying to convert virtual addresses to physical addresses */ isci_host->dma_pool_alloc_size = sizeof(struct isci_request) + - scic_io_request_get_object_size(); + sizeof(struct scic_sds_request); isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev, isci_host->dma_pool_alloc_size, SLAB_HWCACHE_ALIGN, 0); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 9dd971a3fbb2..a5b9b22d3b3a 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -126,7 +126,6 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) enum sci_status status = SCI_FAILURE; struct sas_task *task = isci_request_access_task(ireq); struct scic_sds_request *sci_req = ireq->sci_request_handle; - void *cmd_iu = sci_req->command_buffer; dev_dbg(&ireq->isci_host->pdev->dev, "%s: request = %p\n", __func__, ireq); @@ -138,7 +137,7 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) /* copy the smp_command to the address; */ sg_copy_to_buffer(&task->smp_task.smp_req, 1, - (char *)cmd_iu, + &sci_req->smp.cmd, sizeof(struct smp_req)); status = scic_io_request_construct_smp(sci_req); @@ -998,25 +997,15 @@ void isci_request_io_request_complete( task); if (sas_protocol_ata(task->task_proto)) { - resp_buf - = scic_stp_io_request_get_d2h_reg_address( - request->sci_request_handle - ); + resp_buf = &request->sci_request_handle->stp.rsp; isci_request_process_stp_response(task, - resp_buf - ); - + resp_buf); } else if (SAS_PROTOCOL_SSP == task->task_proto) { /* crack the iu response buffer. */ - resp_iu - = scic_io_request_get_response_iu_address( - request->sci_request_handle - ); - + resp_iu = &request->sci_request_handle->ssp.rsp; isci_request_process_response_iu(task, resp_iu, - &isci_host->pdev->dev - ); + &isci_host->pdev->dev); } else if (SAS_PROTOCOL_SMP == task->task_proto) { @@ -1045,11 +1034,7 @@ void isci_request_io_request_complete( request->complete_in_target = true; if (task->task_proto == SAS_PROTOCOL_SMP) { - - u8 *command_iu_address - = scic_io_request_get_command_iu_address( - request->sci_request_handle - ); + void *rsp = &request->sci_request_handle->smp.rsp; dev_dbg(&isci_host->pdev->dev, "%s: SMP protocol completion\n", @@ -1057,9 +1042,7 @@ void isci_request_io_request_complete( sg_copy_from_buffer( &task->smp_task.smp_resp, 1, - command_iu_address - + sizeof(struct smp_req), - sizeof(struct smp_resp)); + rsp, sizeof(struct smp_resp)); } else if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) { diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index a08fcf511908..578b1c5d40a9 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -71,24 +71,17 @@ */ struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task) { - struct isci_request *request = task->lldd_task; - struct host_to_dev_fis *register_fis = - scic_stp_io_request_get_h2d_reg_address( - request->sci_request_handle - ); - - memcpy( - (u8 *)register_fis, - (u8 *)&task->ata_task.fis, - sizeof(struct host_to_dev_fis) - ); + struct isci_request *ireq = task->lldd_task; + struct host_to_dev_fis *fis = &ireq->sci_request_handle->stp.cmd; + + memcpy(fis, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); if (!task->ata_task.device_control_reg_update) - register_fis->flags |= 0x80; + fis->flags |= 0x80; - register_fis->flags &= 0xF0; + fis->flags &= 0xF0; - return register_fis; + return fis; } /** @@ -161,36 +154,32 @@ void isci_request_process_stp_response(struct sas_task *task, ts->resp = SAS_TASK_COMPLETE; } -enum sci_status isci_sata_management_task_request_build( - struct isci_request *isci_request) +enum sci_status isci_sata_management_task_request_build(struct isci_request *ireq) { + struct scic_sds_request *sci_req = ireq->sci_request_handle; struct isci_tmf *isci_tmf; enum sci_status status; - if (tmf_task != isci_request->ttype) + if (tmf_task != ireq->ttype) return SCI_FAILURE; - isci_tmf = isci_request_access_tmf(isci_request); + isci_tmf = isci_request_access_tmf(ireq); switch (isci_tmf->tmf_code) { case isci_tmf_sata_srst_high: - case isci_tmf_sata_srst_low: - { - struct host_to_dev_fis *register_fis = - scic_stp_io_request_get_h2d_reg_address( - isci_request->sci_request_handle - ); - - memset(register_fis, 0, sizeof(*register_fis)); - - register_fis->fis_type = 0x27; - register_fis->flags &= ~0x80; - register_fis->flags &= 0xF0; + case isci_tmf_sata_srst_low: { + struct host_to_dev_fis *fis = &sci_req->stp.cmd; + + memset(fis, 0, sizeof(*fis)); + + fis->fis_type = 0x27; + fis->flags &= ~0x80; + fis->flags &= 0xF0; if (isci_tmf->tmf_code == isci_tmf_sata_srst_high) - register_fis->control |= ATA_SRST; + fis->control |= ATA_SRST; else - register_fis->control &= ~ATA_SRST; + fis->control &= ~ATA_SRST; break; } /* other management commnd go here... */ @@ -202,7 +191,7 @@ enum sci_status isci_sata_management_task_request_build( * based on the h2d fis. */ status = scic_task_request_construct_sata( - isci_request->sci_request_handle + ireq->sci_request_handle ); return status; diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 7d5f79378452..492faeea8b3a 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1431,7 +1431,6 @@ isci_task_request_complete(struct isci_host *ihost, struct isci_tmf *tmf = isci_request_access_tmf(ireq); struct completion *tmf_complete; struct scic_sds_request *sci_req = ireq->sci_request_handle; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; dev_dbg(&ihost->pdev->dev, "%s: request = %p, status=%d\n", @@ -1444,11 +1443,11 @@ isci_task_request_complete(struct isci_host *ihost, if (tmf->proto == SAS_PROTOCOL_SSP) { memcpy(&tmf->resp.resp_iu, - sci_req->response_buffer, + &sci_req->ssp.rsp, SSP_RESP_IU_MAX_SIZE); } else if (tmf->proto == SAS_PROTOCOL_SATA) { memcpy(&tmf->resp.d2h_fis, - &stp_req->d2h_reg_fis, + &sci_req->stp.rsp, sizeof(struct dev_to_host_fis)); } -- cgit v1.2.3 From 67ea838d17acdad3331aeae848683c768df96aaa Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 8 May 2011 11:47:15 -0700 Subject: isci: unify request data structures Make scic_sds_request a proper member of isci_request. Also let's us get rid of the dma pool object size tracking since we now know that all requests are sizeof(isci_request). While cleaning up the construct routine incidentally replaced SCI_FIELD_OFFSET with offsetof. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_util.c | 9 +- drivers/scsi/isci/core/sci_util.h | 3 - drivers/scsi/isci/core/scic_io_request.h | 33 +---- drivers/scsi/isci/core/scic_sds_controller.c | 2 +- drivers/scsi/isci/core/scic_sds_request.c | 53 +++----- drivers/scsi/isci/core/scic_sds_request.h | 14 --- drivers/scsi/isci/core/scic_sds_stp_request.c | 4 +- drivers/scsi/isci/core/scic_task_request.h | 36 +----- drivers/scsi/isci/host.c | 8 +- drivers/scsi/isci/host.h | 1 - drivers/scsi/isci/remote_device.c | 2 +- drivers/scsi/isci/request.c | 168 ++++++++++++-------------- drivers/scsi/isci/request.h | 12 +- drivers/scsi/isci/sata.c | 10 +- drivers/scsi/isci/task.c | 30 ++--- 15 files changed, 128 insertions(+), 257 deletions(-) diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c index 0c75d14240a1..4e60d55836e9 100644 --- a/drivers/scsi/isci/core/sci_util.c +++ b/drivers/scsi/isci/core/sci_util.c @@ -59,14 +59,14 @@ void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr) { - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); dma_addr_t offset; BUG_ON(phys_addr < ireq->request_daddr); offset = phys_addr - ireq->request_daddr; - BUG_ON(offset >= ireq->request_alloc_size); + BUG_ON(offset >= sizeof(*ireq)); return (char *)ireq + offset; } @@ -74,14 +74,13 @@ void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t ph dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request, void *virt_addr) { - struct isci_request *isci_request = sds_request->ireq; + struct isci_request *isci_request = sci_req_to_ireq(sds_request); char *requested_addr = (char *)virt_addr; char *base_addr = (char *)isci_request; BUG_ON(requested_addr < base_addr); - BUG_ON((requested_addr - base_addr) >= - isci_request->request_alloc_size); + BUG_ON((requested_addr - base_addr) >= sizeof(*isci_request)); return isci_request->request_daddr + (requested_addr - base_addr); } diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h index 4e9c3189cf95..0f9dd0fe1266 100644 --- a/drivers/scsi/isci/core/sci_util.h +++ b/drivers/scsi/isci/core/sci_util.h @@ -66,9 +66,6 @@ | ((char_buffer)[3]) \ ) -#define SCI_FIELD_OFFSET(type, field) ((unsigned long)&(((type *)0)->field)) - - #define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h index cb3667decb3c..f7c6d426f8c0 100644 --- a/drivers/scsi/isci/core/scic_io_request.h +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -102,41 +102,10 @@ typedef enum { } SCIC_TRANSPORT_PROTOCOL; - -/** - * scic_io_request_construct() - This method is called by the SCI user to - * construct all SCI Core IO requests. Memory initialization and - * functionality common to all IO request types is performed in this method. - * @scic_controller: the handle to the core controller object for which to - * build an IO request. - * @scic_remote_device: the handle to the core remote device object for which - * to build an IO request. - * @io_tag: This parameter specifies the IO tag to be associated with this - * request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the - * request is built internally. The request will be copied into the actual - * controller request memory when the IO tag is allocated internally during - * the scic_controller_start_io() method. - * @user_io_request_object: This parameter specifies the user IO request to be - * utilized during IO construction. This IO pointer will become the - * associated object for the core IO request object. - * @scic_io_request_memory: This parameter specifies the memory location to be - * utilized when building the core request. - * @new_scic_io_request_handle: This parameter specifies a pointer to the - * handle the core will expect in further interactions with the core IO - * request object. - * - * The SCI core implementation will create an association between the user IO - * request object and the core IO request object. Indicate if the controller - * successfully built the IO request. SCI_SUCCESS This value is returned if the - * IO request was successfully built. - */ enum sci_status scic_io_request_construct( struct scic_sds_controller *scic_controller, struct scic_sds_remote_device *scic_remote_device, - u16 io_tag, - void *user_io_request_object, - struct scic_sds_request *scic_io_request_memory, - struct scic_sds_request **new_scic_io_request_handle); + u16 io_tag, struct scic_sds_request *sci_req); /** * scic_io_request_construct_basic_ssp() - This method is called by the SCI diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 4179bdf3eda7..852b7d52f84f 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1572,7 +1572,7 @@ void scic_sds_controller_copy_task_context( memcpy(task_context_buffer, sci_req->task_context_buffer, - SCI_FIELD_OFFSET(struct scu_task_context, sgl_snapshot_ac)); + offsetof(struct scu_task_context, sgl_snapshot_ac)); /* * Now that the soft copy of the TC has been copied into the TC diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 36c2b310c175..50dd19bba3db 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -117,7 +117,7 @@ static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( */ void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) { - struct isci_request *isci_request = sds_request->ireq; + struct isci_request *isci_request = sci_req_to_ireq(sds_request); struct isci_host *isci_host = isci_request->isci_host; struct sas_task *task = isci_request_access_task(isci_request); struct scatterlist *sg = NULL; @@ -190,7 +190,7 @@ static void scic_sds_ssp_io_request_assign_buffers(struct scic_sds_request *sci_ static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) { struct ssp_cmd_iu *cmd_iu; - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); cmd_iu = &sci_req->ssp.cmd; @@ -211,7 +211,7 @@ static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sc static void scic_sds_task_request_build_ssp_task_iu(struct scic_sds_request *sci_req) { struct ssp_task_iu *task_iu; - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); @@ -429,7 +429,7 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, bool copy) { enum sci_status status = SCI_SUCCESS; - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); /* check for management protocols */ @@ -478,7 +478,7 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, enum sci_status scic_io_request_construct_basic_ssp( struct scic_sds_request *sci_req) { - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); sci_req->protocol = SCIC_SSP_PROTOCOL; @@ -519,7 +519,7 @@ enum sci_status scic_io_request_construct_basic_sata( enum sci_status status; struct scic_sds_stp_request *stp_req; bool copy = false; - struct isci_request *isci_request = sci_req->ireq; + struct isci_request *isci_request = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(isci_request); stp_req = &sci_req->stp.req; @@ -540,11 +540,10 @@ enum sci_status scic_io_request_construct_basic_sata( } -enum sci_status scic_task_request_construct_sata( - struct scic_sds_request *sci_req) +enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req) { enum sci_status status = SCI_SUCCESS; - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); /* check for management protocols */ if (ireq->ttype == tmf_task) { @@ -740,7 +739,7 @@ void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) void *resp_buf; u32 len; struct ssp_response_iu *ssp_response; - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); ssp_response = &sci_req->ssp.rsp; @@ -1342,7 +1341,7 @@ static void scic_sds_request_completed_state_enter(void *object) struct scic_sds_controller *scic = scic_sds_request_get_controller(sci_req); struct isci_host *ihost = scic_to_ihost(scic); - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); SET_STATE_HANDLER(sci_req, scic_sds_request_state_handler_table, @@ -1424,16 +1423,13 @@ static const struct sci_base_state scic_sds_request_state_table[] = { static void scic_sds_general_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - u16 io_tag, - void *user_io_request_object, - struct scic_sds_request *sci_req) + u16 io_tag, struct scic_sds_request *sci_req) { sci_base_state_machine_construct(&sci_req->state_machine, sci_req, scic_sds_request_state_table, SCI_BASE_REQUEST_STATE_INITIAL); sci_base_state_machine_start(&sci_req->state_machine); sci_req->io_tag = io_tag; - sci_req->user_request = user_io_request_object; sci_req->owning_controller = scic; sci_req->target_device = sci_dev; sci_req->has_started_substate_machine = false; @@ -1461,20 +1457,13 @@ static void scic_sds_general_request_construct(struct scic_sds_controller *scic, enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - u16 io_tag, - void *user_req, - struct scic_sds_request *sci_req, - struct scic_sds_request **new_sci_req) + u16 io_tag, struct scic_sds_request *sci_req) { struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, - sci_dev, - io_tag, - user_req, - sci_req); + scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) @@ -1493,10 +1482,8 @@ scic_io_request_construct(struct scic_sds_controller *scic, status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; if (status == SCI_SUCCESS) { - memset(sci_req->task_context_buffer, - 0, - SCI_FIELD_OFFSET(struct scu_task_context, sgl_pair_ab)); - *new_sci_req = sci_req; + memset(sci_req->task_context_buffer, 0, + offsetof(struct scu_task_context, sgl_pair_ab)); } return status; @@ -1504,18 +1491,13 @@ scic_io_request_construct(struct scic_sds_controller *scic, enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - u16 io_tag, - void *user_io_request_object, - struct scic_sds_request *sci_req, - struct scic_sds_request **new_sci_req) + u16 io_tag, struct scic_sds_request *sci_req) { struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, io_tag, - user_io_request_object, - sci_req); + scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); if (dev->dev_type == SAS_END_DEV) { scic_sds_ssp_task_request_assign_buffers(sci_req); @@ -1537,7 +1519,6 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, if (status == SCI_SUCCESS) { sci_req->is_task_management_request = true; memset(sci_req->task_context_buffer, 0, sizeof(struct scu_task_context)); - *new_sci_req = sci_req; } return status; diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 3f551eaf3dfa..1dd98aabe32d 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -113,26 +113,12 @@ enum scic_sds_smp_request_started_substates { SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, }; -struct isci_request; -/** - * struct scic_sds_request - This structure contains or references all of - * the data necessary to process a task management or normal IO request. - * - * - */ struct scic_sds_request { - /** - * The field specifies that the peer object for the request object. - */ - struct isci_request *ireq; - /** * This field contains the information for the base request state machine. */ struct sci_base_state_machine state_machine; - void *user_request; - /** * This field simply points to the controller to which this IO request * is associated. diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index c7a8931a3bcb..2677393db6f4 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -627,7 +627,7 @@ scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *s int total_len = len; sci_req = to_sci_req(stp_req); - ireq = scic_sds_request_get_user_request(sci_req); + ireq = sci_req_to_ireq(sci_req); task = isci_request_access_task(ireq); src_addr = data_buf; @@ -737,7 +737,7 @@ static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct { struct scic_sds_controller *scic = sci_req->owning_controller; struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); struct dev_to_host_fis *frame_header; enum sci_status status; diff --git a/drivers/scsi/isci/core/scic_task_request.h b/drivers/scsi/isci/core/scic_task_request.h index 7e6d20aa0f02..98cfaa9e6d38 100644 --- a/drivers/scsi/isci/core/scic_task_request.h +++ b/drivers/scsi/isci/core/scic_task_request.h @@ -72,44 +72,10 @@ struct scic_sds_remote_device; struct scic_sds_controller; -/** - * scic_task_request_construct() - This method is called by the SCI user to - * construct all SCI Core task management requests, regardless of protocol. - * Memory initialization and functionality common to all task request types - * is performed in this method. - * @scic_controller: the handle to the core controller object for which to - * build the task managmement request. - * @scic_remote_device: the handle to the core remote device object for which - * to build the task management request. passed, then a copy of the request - * is built internally. The request will be copied into the actual - * controller request memory when the task is allocated internally during - * the scic_controller_start_task() method. - * @io_tag: This parameter specifies the IO tag to be associated with this - * request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the - * request is built internally. The request will be copied into the actual - * controller request memory when the IO tag is allocated internally during - * the scic_controller_start_io() method. - * @user_task_request_object: This parameter specifies the user task request to - * be utilized during construction. This task pointer will become the - * associated object for the core task request object. - * @scic_task_request_memory: This parameter specifies the memory location to - * be utilized when building the core request. - * @new_scic_task_request_handle: This parameter specifies a pointer to the - * handle the core will expect in further interactions with the core task - * request object. - * - * The SCI core implementation will create an association between the user task - * request object and the core task request object. Indicate if the controller - * successfully built the task request. SCI_SUCCESS This value is returned if - * the task request was successfully built. - */ enum sci_status scic_task_request_construct( struct scic_sds_controller *scic_controller, struct scic_sds_remote_device *scic_remote_device, - u16 io_tag, - void *user_task_request_object, - void *scic_task_request_memory, - struct scic_sds_request **new_scic_task_request_handle); + u16 io_tag, struct scic_sds_request *sci_req); /** * scic_task_request_construct_ssp() - This method is called by the SCI user to diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 4d0ee7bf847b..271a7e171e7d 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -428,14 +428,8 @@ int isci_host_init(struct isci_host *isci_host) if (err) return err; - /* - * keep the pool alloc size around, will use it for a bounds checking - * when trying to convert virtual addresses to physical addresses - */ - isci_host->dma_pool_alloc_size = sizeof(struct isci_request) + - sizeof(struct scic_sds_request); isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev, - isci_host->dma_pool_alloc_size, + sizeof(struct isci_request), SLAB_HWCACHE_ALIGN, 0); if (!isci_host->dma_pool) diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 5a414c31a877..afa41e83eaa7 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -82,7 +82,6 @@ struct isci_host { struct list_head timers; void *core_ctrl_memory; struct dma_pool *dma_pool; - unsigned int dma_pool_alloc_size; struct isci_phy phys[SCI_MAX_PHYS]; struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ struct sas_ha_struct sas_ha; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index a441c23b6859..8b1ef19a6732 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -473,7 +473,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic struct sci_base_state_machine *sm = &sci_dev->state_machine; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_port *sci_port = sci_dev->owning_port; - struct isci_request *ireq = sci_req->ireq; + struct isci_request *ireq = sci_req_to_ireq(sci_req); enum sci_status status; switch (state) { diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index a5b9b22d3b3a..4961ee347091 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -73,9 +73,7 @@ static enum sci_status isci_request_ssp_request_construct( "%s: request = %p\n", __func__, request); - status = scic_io_request_construct_basic_ssp( - request->sci_request_handle - ); + status = scic_io_request_construct_basic_ssp(&request->sci); return status; } @@ -96,9 +94,7 @@ static enum sci_status isci_request_stp_request_construct( */ register_fis = isci_sata_task_to_fis_copy(task); - status = scic_io_request_construct_basic_sata( - request->sci_request_handle - ); + status = scic_io_request_construct_basic_sata(&request->sci); /* Set the ncq tag in the fis, from the queue * command in the task. @@ -125,7 +121,7 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) { enum sci_status status = SCI_FAILURE; struct sas_task *task = isci_request_access_task(ireq); - struct scic_sds_request *sci_req = ireq->sci_request_handle; + struct scic_sds_request *sci_req = &ireq->sci; dev_dbg(&ireq->isci_host->pdev->dev, "%s: request = %p\n", __func__, ireq); @@ -201,8 +197,7 @@ static enum sci_status isci_io_request_build( */ status = scic_io_request_construct(&isci_host->sci, sci_device, SCI_CONTROLLER_INVALID_IO_TAG, - request, request->sci_req, - &request->sci_request_handle); + &request->sci); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -211,8 +206,6 @@ static enum sci_status isci_io_request_build( return SCI_FAILURE; } - request->sci_request_handle->ireq = request; - switch (task->task_proto) { case SAS_PROTOCOL_SMP: status = isci_smp_request_build(request); @@ -276,8 +269,8 @@ static int isci_request_alloc_core( request->isci_host = isci_host; request->isci_device = isci_device; request->io_request_completion = NULL; + request->terminated = false; - request->request_alloc_size = isci_host->dma_pool_alloc_size; request->num_sg_entries = 0; request->complete_in_target = false; @@ -381,80 +374,74 @@ int isci_request_execute( goto out; status = isci_io_request_build(isci_host, request, isci_device); - if (status == SCI_SUCCESS) { - - spin_lock_irqsave(&isci_host->scic_lock, flags); - - /* send the request, let the core assign the IO TAG. */ - status = scic_controller_start_io( - &isci_host->sci, - sci_device, - request->sci_request_handle, - SCI_CONTROLLER_INVALID_IO_TAG - ); - - if (status == SCI_SUCCESS || - status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - - /* Either I/O started OK, or the core has signaled that - * the device needs a target reset. - * - * In either case, hold onto the I/O for later. - * - * Update it's status and add it to the list in the - * remote device object. - */ - isci_request_change_state(request, started); - list_add(&request->dev_node, - &isci_device->reqs_in_process); - - if (status == SCI_SUCCESS) { - /* Save the tag for possible task mgmt later. */ - request->io_tag = scic_io_request_get_io_tag( - request->sci_request_handle); - } else { - /* The request did not really start in the - * hardware, so clear the request handle - * here so no terminations will be done. - */ - request->sci_request_handle = NULL; - } + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: request_construct failed - status = 0x%x\n", + __func__, + status); + goto out; + } - } else - dev_warn(&isci_host->pdev->dev, - "%s: failed request start (0x%x)\n", - __func__, status); + spin_lock_irqsave(&isci_host->scic_lock, flags); + /* send the request, let the core assign the IO TAG. */ + status = scic_controller_start_io(&isci_host->sci, sci_device, + &request->sci, + SCI_CONTROLLER_INVALID_IO_TAG); + if (status != SCI_SUCCESS && + status != SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + dev_warn(&isci_host->pdev->dev, + "%s: failed request start (0x%x)\n", + __func__, status); spin_unlock_irqrestore(&isci_host->scic_lock, flags); + goto out; + } - if (status == - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - /* Signal libsas that we need the SCSI error - * handler thread to work on this I/O and that - * we want a device reset. - */ - spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; - spin_unlock_irqrestore(&task->task_state_lock, flags); - - /* Cause this task to be scheduled in the SCSI error - * handler thread. - */ - isci_execpath_callback(isci_host, task, - sas_task_abort); - - /* Change the status, since we are holding - * the I/O until it is managed by the SCSI - * error handler. - */ - status = SCI_SUCCESS; - } + /* Either I/O started OK, or the core has signaled that + * the device needs a target reset. + * + * In either case, hold onto the I/O for later. + * + * Update it's status and add it to the list in the + * remote device object. + */ + isci_request_change_state(request, started); + list_add(&request->dev_node, &isci_device->reqs_in_process); - } else - dev_warn(&isci_host->pdev->dev, - "%s: request_construct failed - status = 0x%x\n", - __func__, - status); + if (status == SCI_SUCCESS) { + /* Save the tag for possible task mgmt later. */ + request->io_tag = scic_io_request_get_io_tag(&request->sci); + } else { + /* The request did not really start in the + * hardware, so clear the request handle + * here so no terminations will be done. + */ + request->terminated = true; + } + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + if (status == + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + /* Signal libsas that we need the SCSI error + * handler thread to work on this I/O and that + * we want a device reset. + */ + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + /* Cause this task to be scheduled in the SCSI error + * handler thread. + */ + isci_execpath_callback(isci_host, task, + sas_task_abort); + + /* Change the status, since we are holding + * the I/O until it is managed by the SCSI + * error handler. + */ + status = SCI_SUCCESS; + } out: if (status != SCI_SUCCESS) { @@ -554,9 +541,7 @@ static void isci_request_handle_controller_specific_errors( { unsigned int cstatus; - cstatus = scic_request_get_controller_status( - request->sci_request_handle - ); + cstatus = scic_request_get_controller_status(&request->sci); dev_dbg(&request->isci_host->pdev->dev, "%s: %p SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR " @@ -997,13 +982,13 @@ void isci_request_io_request_complete( task); if (sas_protocol_ata(task->task_proto)) { - resp_buf = &request->sci_request_handle->stp.rsp; + resp_buf = &request->sci.stp.rsp; isci_request_process_stp_response(task, resp_buf); } else if (SAS_PROTOCOL_SSP == task->task_proto) { /* crack the iu response buffer. */ - resp_iu = &request->sci_request_handle->ssp.rsp; + resp_iu = &request->sci.ssp.rsp; isci_request_process_response_iu(task, resp_iu, &isci_host->pdev->dev); @@ -1034,7 +1019,7 @@ void isci_request_io_request_complete( request->complete_in_target = true; if (task->task_proto == SAS_PROTOCOL_SMP) { - void *rsp = &request->sci_request_handle->smp.rsp; + void *rsp = &request->sci.smp.rsp; dev_dbg(&isci_host->pdev->dev, "%s: SMP protocol completion\n", @@ -1051,8 +1036,7 @@ void isci_request_io_request_complete( * the maximum was transferred. */ u32 transferred_length - = scic_io_request_get_number_of_bytes_transferred( - request->sci_request_handle); + = scic_io_request_get_number_of_bytes_transferred(&request->sci); task->task_status.residual = task->total_xfer_len - transferred_length; @@ -1165,12 +1149,12 @@ void isci_request_io_request_complete( /* complete the io request to the core. */ scic_controller_complete_io(&isci_host->sci, &isci_device->sci, - request->sci_request_handle); - /* NULL the request handle so it cannot be completed or + &request->sci); + /* set terminated handle so it cannot be completed or * terminated again, and to cause any calls into abort * task to recognize the already completed case. */ - request->sci_request_handle = NULL; + request->terminated = true; isci_host_can_dequeue(isci_host, 1); } diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index ddfbf71c97e5..89d8b0a27dfe 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -82,11 +82,11 @@ enum task_type { }; struct isci_request { - struct scic_sds_request *sci_request_handle; enum isci_request_status status; enum task_type ttype; unsigned short io_tag; bool complete_in_target; + bool terminated; union ttype_ptr_union { struct sas_task *io_task_ptr; /* When ttype==io_task */ @@ -103,7 +103,6 @@ struct isci_request { dma_addr_t zero_scatter_daddr; unsigned int num_sg_entries; /* returned by pci_alloc_sg */ - unsigned int request_alloc_size; /* size of block from dma_pool_alloc */ /** Note: "io_request_completion" is completed in two different ways * depending on whether this is a TMF or regular request. @@ -115,9 +114,16 @@ struct isci_request { * TMF was aborting is guaranteed to have completed. */ struct completion *io_request_completion; - struct scic_sds_request sci_req[0] ____cacheline_aligned; + struct scic_sds_request sci; }; +static inline struct isci_request *sci_req_to_ireq(struct scic_sds_request *sci_req) +{ + struct isci_request *ireq = container_of(sci_req, typeof(*ireq), sci); + + return ireq; +} + /** * This function gets the status of the request object. * @request: This parameter points to the isci_request object diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 578b1c5d40a9..08dabf08f7d7 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -72,7 +72,7 @@ struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task) { struct isci_request *ireq = task->lldd_task; - struct host_to_dev_fis *fis = &ireq->sci_request_handle->stp.cmd; + struct host_to_dev_fis *fis = &ireq->sci.stp.cmd; memcpy(fis, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); @@ -118,7 +118,7 @@ void isci_sata_set_ncq_tag( struct isci_request *request = task->lldd_task; register_fis->sector_count = qc->tag << 3; - scic_stp_io_request_set_ncq_tag(request->sci_request_handle, qc->tag); + scic_stp_io_request_set_ncq_tag(&request->sci, qc->tag); } /** @@ -156,7 +156,7 @@ void isci_request_process_stp_response(struct sas_task *task, enum sci_status isci_sata_management_task_request_build(struct isci_request *ireq) { - struct scic_sds_request *sci_req = ireq->sci_request_handle; + struct scic_sds_request *sci_req = &ireq->sci; struct isci_tmf *isci_tmf; enum sci_status status; @@ -190,9 +190,7 @@ enum sci_status isci_sata_management_task_request_build(struct isci_request *ire /* core builds the protocol specific request * based on the h2d fis. */ - status = scic_task_request_construct_sata( - ireq->sci_request_handle - ); + status = scic_task_request_construct_sata(&ireq->sci); return status; } diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 492faeea8b3a..7adaf71c19d1 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -300,8 +300,7 @@ static enum sci_status isci_task_request_build( /* let the core do it's construct. */ status = scic_task_request_construct(&isci_host->sci, sci_device, SCI_CONTROLLER_INVALID_IO_TAG, - request, &request->sci_req, - &request->sci_request_handle); + &request->sci); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -312,14 +311,10 @@ static enum sci_status isci_task_request_build( goto errout; } - request->sci_request_handle->ireq = request; - /* XXX convert to get this from task->tproto like other drivers */ if (dev->dev_type == SAS_END_DEV) { isci_tmf->proto = SAS_PROTOCOL_SSP; - status = scic_task_request_construct_ssp( - request->sci_request_handle - ); + status = scic_task_request_construct_ssp(&request->sci); if (status != SCI_SUCCESS) goto errout; } @@ -376,8 +371,7 @@ static void isci_tmf_timeout_cb(void *tmf_request_arg) status = scic_controller_terminate_request( &request->isci_host->sci, &request->isci_device->sci, - request->sci_request_handle - ); + &request->sci); dev_dbg(&request->isci_host->pdev->dev, "%s: tmf_request = %p; tmf = %p; status = %d\n", @@ -467,9 +461,8 @@ int isci_task_execute_tmf( status = scic_controller_start_task( &isci_host->sci, sci_device, - request->sci_request_handle, - SCI_CONTROLLER_INVALID_IO_TAG - ); + &request->sci, + SCI_CONTROLLER_INVALID_IO_TAG); if (status != SCI_TASK_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -764,13 +757,13 @@ static void isci_terminate_request_core( * device condition (if the request handle is NULL, then the * request completed but needed additional handling here). */ - if (isci_request->sci_request_handle != NULL) { + if (!isci_request->terminated) { was_terminated = true; needs_cleanup_handling = true; status = scic_controller_terminate_request( &isci_host->sci, &isci_device->sci, - isci_request->sci_request_handle); + &isci_request->sci); } spin_unlock_irqrestore(&isci_host->scic_lock, flags); @@ -1430,7 +1423,7 @@ isci_task_request_complete(struct isci_host *ihost, enum isci_request_status old_state; struct isci_tmf *tmf = isci_request_access_tmf(ireq); struct completion *tmf_complete; - struct scic_sds_request *sci_req = ireq->sci_request_handle; + struct scic_sds_request *sci_req = &ireq->sci; dev_dbg(&ihost->pdev->dev, "%s: request = %p, status=%d\n", @@ -1460,12 +1453,11 @@ isci_task_request_complete(struct isci_host *ihost, /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; - scic_controller_complete_io(&ihost->sci, &idev->sci, - ireq->sci_request_handle); - /* NULL the request handle to make sure it cannot be terminated + scic_controller_complete_io(&ihost->sci, &idev->sci, &ireq->sci); + /* set the 'terminated' flag handle to make sure it cannot be terminated * or completed again. */ - ireq->sci_request_handle = NULL; + ireq->terminated = true;; isci_request_change_state(ireq, unallocated); list_del_init(&ireq->dev_node); -- cgit v1.2.3 From ce2b3261b6765c3b80fda95426c73e8d3bb1b035 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 8 May 2011 15:49:15 -0700 Subject: isci: unify constants cross driver constants are spread out over multiple header files, consolidate them into isci.h, and push some includes out to the source files that need them. TODO: remove SCI_MODE_SIZE infrastructure. TODO: task.h is full of inlines that are too large Signed-off-by: Dan Williams --- drivers/scsi/isci/core/sci_controller.h | 69 --- drivers/scsi/isci/core/sci_controller_constants.h | 206 --------- drivers/scsi/isci/core/sci_status.h | 409 ------------------ drivers/scsi/isci/core/sci_util.c | 1 + drivers/scsi/isci/core/scic_config_parameters.h | 11 - drivers/scsi/isci/core/scic_controller.h | 8 - drivers/scsi/isci/core/scic_io_request.h | 8 - drivers/scsi/isci/core/scic_phy.h | 1 - drivers/scsi/isci/core/scic_port.h | 2 +- drivers/scsi/isci/core/scic_sds_controller.c | 2 +- drivers/scsi/isci/core/scic_sds_controller.h | 2 - drivers/scsi/isci/core/scic_sds_phy.c | 1 + drivers/scsi/isci/core/scic_sds_port.c | 1 + drivers/scsi/isci/core/scic_sds_port.h | 10 +- .../isci/core/scic_sds_port_configuration_agent.c | 8 +- drivers/scsi/isci/core/scic_sds_request.c | 3 +- drivers/scsi/isci/core/scic_sds_request.h | 2 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 1 + .../isci/core/scic_sds_unsolicited_frame_control.h | 19 +- drivers/scsi/isci/core/scic_task_request.h | 11 +- drivers/scsi/isci/core/scu_constants.h | 151 ------- drivers/scsi/isci/host.c | 2 + drivers/scsi/isci/host.h | 18 +- drivers/scsi/isci/init.c | 2 +- drivers/scsi/isci/isci.h | 480 ++++++++++++++++++++- drivers/scsi/isci/phy.c | 2 +- drivers/scsi/isci/phy.h | 5 +- drivers/scsi/isci/port.h | 3 + drivers/scsi/isci/probe_roms.c | 1 - drivers/scsi/isci/probe_roms.h | 1 + drivers/scsi/isci/remote_device.h | 1 - drivers/scsi/isci/remote_node_table.h | 9 +- drivers/scsi/isci/request.c | 1 + drivers/scsi/isci/request.h | 1 + drivers/scsi/isci/sci_environment.h | 3 +- drivers/scsi/isci/task.c | 2 + drivers/scsi/isci/task.h | 1 + drivers/scsi/isci/timers.c | 1 + 38 files changed, 497 insertions(+), 962 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_controller.h delete mode 100644 drivers/scsi/isci/core/sci_controller_constants.h delete mode 100644 drivers/scsi/isci/core/sci_status.h delete mode 100644 drivers/scsi/isci/core/scu_constants.h diff --git a/drivers/scsi/isci/core/sci_controller.h b/drivers/scsi/isci/core/sci_controller.h deleted file mode 100644 index 01316b1a8f27..000000000000 --- a/drivers/scsi/isci/core/sci_controller.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_CONTROLLER_H_ -#define _SCI_CONTROLLER_H_ - -/** - * This file contains all of the interface methods that can be called by an SCI - * user on all SCI controller objects. - * - * - */ - -#define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF - -#endif /* _SCI_CONTROLLER_H_ */ - diff --git a/drivers/scsi/isci/core/sci_controller_constants.h b/drivers/scsi/isci/core/sci_controller_constants.h deleted file mode 100644 index 2525c26d7c08..000000000000 --- a/drivers/scsi/isci/core/sci_controller_constants.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_CONTROLLER_CONSTANTS_H_ -#define _SCI_CONTROLLER_CONSTANTS_H_ - -/** - * This file contains constant values that change based on the type of core or - * framework being managed. These constants are exported in order to - * provide the user with information as to the bounds (i.e. how many) of - * specific objects. - * - * - */ - -#ifndef SCI_MAX_PHYS -/** - * - * - * This constant defines the maximum number of phy objects that can be - * supported for the SCU Driver Standard (SDS) library. This is tied directly - * to silicon capabilities. - */ -#define SCI_MAX_PHYS (4) -#endif - -#ifndef SCI_MAX_PORTS -/** - * - * - * This constant defines the maximum number of port objects that can be - * supported for the SCU Driver Standard (SDS) library. This is tied directly - * to silicon capabilities. - */ -#define SCI_MAX_PORTS SCI_MAX_PHYS -#endif - -#ifndef SCI_MIN_SMP_PHYS -/** - * - * - * This constant defines the minimum number of SMP phy objects that can be - * supported for a single expander level. This was determined by using 36 - * physical phys and room for 2 virtual phys. - */ -#define SCI_MIN_SMP_PHYS (38) -#endif - -#ifndef SCI_MAX_SMP_PHYS -/** - * - * - * This constant defines the maximum number of SMP phy objects that can be - * supported for the SCU Driver Standard (SDS) library. This number can be - * increased if required. - */ -#define SCI_MAX_SMP_PHYS (384) -#endif - -#ifndef SCI_MAX_REMOTE_DEVICES -/** - * - * - * This constant defines the maximum number of remote device objects that can - * be supported for the SCU Driver Standard (SDS) library. This is tied - * directly to silicon capabilities. - */ -#define SCI_MAX_REMOTE_DEVICES (256) -#endif - -#ifndef SCI_MIN_REMOTE_DEVICES -/** - * - * - * This constant defines the minimum number of remote device objects that can - * be supported for the SCU Driver Standard (SDS) library. This # can be - * configured for minimum memory environments to any value less than - * SCI_MAX_REMOTE_DEVICES - */ -#define SCI_MIN_REMOTE_DEVICES (16) -#endif - -#ifndef SCI_MAX_IO_REQUESTS -/** - * - * - * This constant defines the maximum number of IO request objects that can be - * supported for the SCU Driver Standard (SDS) library. This is tied directly - * to silicon capabilities. - */ -#define SCI_MAX_IO_REQUESTS (256) -#endif - -#ifndef SCI_MIN_IO_REQUESTS -/** - * - * - * This constant defines the minimum number of IO request objects that can be - * supported for the SCU Driver Standard (SDS) library. This # can be - * configured for minimum memory environments to any value less than - * SCI_MAX_IO_REQUESTS. - */ -#define SCI_MIN_IO_REQUESTS (1) -#endif - -#ifndef SCI_MAX_MSIX_MESSAGES -/** - * - * - * This constant defines the maximum number of MSI-X interrupt vectors/messages - * supported for an SCU hardware controller instance. - */ -#define SCI_MAX_MSIX_MESSAGES (2) -#endif - -#ifndef SCI_MAX_SCATTER_GATHER_ELEMENTS -/** - * - * - * This constant defines the maximum number of Scatter-Gather Elements to be - * used by any SCI component. - */ -#define SCI_MAX_SCATTER_GATHER_ELEMENTS 130 -#endif - -#ifndef SCI_MIN_SCATTER_GATHER_ELEMENTS -/** - * - * - * This constant defines the minimum number of Scatter-Gather Elements to be - * used by any SCI component. - */ -#define SCI_MIN_SCATTER_GATHER_ELEMENTS 1 -#endif - -/** - * - * - * This constant defines the maximum number of controllers that can occur in a - * single silicon package. - */ -#define SCI_MAX_CONTROLLERS 2 - -/** - * - * - * The maximum number of supported domain objects is currently tied to the - * maximum number of support port objects. - */ -#define SCI_MAX_DOMAINS SCI_MAX_PORTS - - -#endif /* _SCI_CONTROLLER_CONSTANTS_H_ */ - diff --git a/drivers/scsi/isci/core/sci_status.h b/drivers/scsi/isci/core/sci_status.h deleted file mode 100644 index 8b66619022cf..000000000000 --- a/drivers/scsi/isci/core/sci_status.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_STATUS_H_ -#define _SCI_STATUS_H_ - -/** - * This file contains all of the return status codes utilized across the - * various sub-components in SCI. - * - * - */ - - -/** - * enum sci_status - This is the general return status enumeration for non-IO, - * non-task management related SCI interface methods. - * - * - */ -enum sci_status { - /** - * This member indicates successful completion. - */ - SCI_SUCCESS = 0, - - /** - * This value indicates that the calling method completed successfully, - * but that the IO may have completed before having it's start method - * invoked. This occurs during SAT translation for requests that do - * not require an IO to the target or for any other requests that may - * be completed without having to submit IO. - */ - SCI_SUCCESS_IO_COMPLETE_BEFORE_START, - - /** - * This Value indicates that the SCU hardware returned an early response - * because the io request specified more data than is returned by the - * target device (mode pages, inquiry data, etc.). The completion routine - * will handle this case to get the actual number of bytes transferred. - */ - SCI_SUCCESS_IO_DONE_EARLY, - - /** - * This member indicates that the object for which a state change is - * being requested is already in said state. - */ - SCI_WARNING_ALREADY_IN_STATE, - - /** - * This member indicates interrupt coalescence timer may cause SAS - * specification compliance issues (i.e. SMP target mode response - * frames must be returned within 1.9 milliseconds). - */ - SCI_WARNING_TIMER_CONFLICT, - - /** - * This field indicates a sequence of action is not completed yet. Mostly, - * this status is used when multiple ATA commands are needed in a SATI translation. - */ - SCI_WARNING_SEQUENCE_INCOMPLETE, - - /** - * This member indicates that there was a general failure. - */ - SCI_FAILURE, - - /** - * This member indicates that the SCI implementation is unable to complete - * an operation due to a critical flaw the prevents any further operation - * (i.e. an invalid pointer). - */ - SCI_FATAL_ERROR, - - /** - * This member indicates the calling function failed, because the state - * of the controller is in a state that prevents successful completion. - */ - SCI_FAILURE_INVALID_STATE, - - /** - * This member indicates the calling function failed, because there is - * insufficient resources/memory to complete the request. - */ - SCI_FAILURE_INSUFFICIENT_RESOURCES, - - /** - * This member indicates the calling function failed, because the - * controller object required for the operation can't be located. - */ - SCI_FAILURE_CONTROLLER_NOT_FOUND, - - /** - * This member indicates the calling function failed, because the - * discovered controller type is not supported by the library. - */ - SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE, - - /** - * This member indicates the calling function failed, because the - * requested initialization data version isn't supported. - */ - SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION, - - /** - * This member indicates the calling function failed, because the - * requested configuration of SAS Phys into SAS Ports is not supported. - */ - SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION, - - /** - * This member indicates the calling function failed, because the - * requested protocol is not supported by the remote device, port, - * or controller. - */ - SCI_FAILURE_UNSUPPORTED_PROTOCOL, - - /** - * This member indicates the calling function failed, because the - * requested information type is not supported by the SCI implementation. - */ - SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE, - - /** - * This member indicates the calling function failed, because the - * device already exists. - */ - SCI_FAILURE_DEVICE_EXISTS, - - /** - * This member indicates the calling function failed, because adding - * a phy to the object is not possible. - */ - SCI_FAILURE_ADDING_PHY_UNSUPPORTED, - - /** - * This member indicates the calling function failed, because the - * requested information type is not supported by the SCI implementation. - */ - SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD, - - /** - * This member indicates the calling function failed, because the SCI - * implementation does not support the supplied time limit. - */ - SCI_FAILURE_UNSUPPORTED_TIME_LIMIT, - - /** - * This member indicates the calling method failed, because the SCI - * implementation does not contain the specified Phy. - */ - SCI_FAILURE_INVALID_PHY, - - /** - * This member indicates the calling method failed, because the SCI - * implementation does not contain the specified Port. - */ - SCI_FAILURE_INVALID_PORT, - - /** - * This member indicates the calling method was partly successful - * The port was reset but not all phys in port are operational - */ - SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS, - - /** - * This member indicates that calling method failed - * The port reset did not complete because none of the phys are operational - */ - SCI_FAILURE_RESET_PORT_FAILURE, - - /** - * This member indicates the calling method failed, because the SCI - * implementation does not contain the specified remote device. - */ - SCI_FAILURE_INVALID_REMOTE_DEVICE, - - /** - * This member indicates the calling method failed, because the remote - * device is in a bad state and requires a reset. - */ - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, - - /** - * This member indicates the calling method failed, because the SCI - * implementation does not contain or support the specified IO tag. - */ - SCI_FAILURE_INVALID_IO_TAG, - - /** - * This member indicates that the operation failed and the user should - * check the response data associated with the IO. - */ - SCI_FAILURE_IO_RESPONSE_VALID, - - /** - * This member indicates that the operation failed, the failure is - * controller implementation specific, and the response data associated - * with the request is not valid. You can query for the controller - * specific error information via scic_controller_get_request_status() - */ - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, - - /** - * This member indicated that the operation failed because the - * user requested this IO to be terminated. - */ - SCI_FAILURE_IO_TERMINATED, - - /** - * This member indicates that the operation failed and the associated - * request requires a SCSI abort task to be sent to the target. - */ - SCI_FAILURE_IO_REQUIRES_SCSI_ABORT, - - /** - * This member indicates that the operation failed because the supplied - * device could not be located. - */ - SCI_FAILURE_DEVICE_NOT_FOUND, - - /** - * This member indicates that the operation failed because the - * objects association is required and is not correctly set. - */ - SCI_FAILURE_INVALID_ASSOCIATION, - - /** - * This member indicates that the operation failed, because a timeout - * occurred. - */ - SCI_FAILURE_TIMEOUT, - - /** - * This member indicates that the operation failed, because the user - * specified a value that is either invalid or not supported. - */ - SCI_FAILURE_INVALID_PARAMETER_VALUE, - - /** - * This value indicates that the operation failed, because the number - * of messages (MSI-X) is not supported. - */ - SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT, - - /** - * This value indicates that the method failed due to a lack of - * available NCQ tags. - */ - SCI_FAILURE_NO_NCQ_TAG_AVAILABLE, - - /** - * This value indicates that a protocol violation has occurred on the - * link. - */ - SCI_FAILURE_PROTOCOL_VIOLATION, - - /** - * This value indicates a failure condition that retry may help to clear. - */ - SCI_FAILURE_RETRY_REQUIRED, - - /** - * This field indicates the retry limit was reached when a retry is attempted - */ - SCI_FAILURE_RETRY_LIMIT_REACHED, - - /** - * This member indicates the calling method was partly successful. - * Mostly, this status is used when a LUN_RESET issued to an expander attached - * STP device in READY NCQ substate needs to have RNC suspended/resumed - * before posting TC. - */ - SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS, - - /** - * This field indicates an illegal phy connection based on the routing attribute - * of both expander phy attached to each other. - */ - SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION, - - /** - * This field indicates a CONFIG ROUTE INFO command has a response with function result - * INDEX DOES NOT EXIST, usually means exceeding max route index. - */ - SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX, - - /** - * This value indicates that an unsupported PCI device ID has been - * specified. This indicates that attempts to invoke - * scic_library_allocate_controller() will fail. - */ - SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID - -}; - -/** - * enum sci_io_status - This enumeration depicts all of the possible IO - * completion status values. Each value in this enumeration maps directly - * to a value in the enum sci_status enumeration. Please refer to that - * enumeration for detailed comments concerning what the status represents. - * - * Add the API to retrieve the SCU status from the core. Check to see that the - * following status are properly handled: - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL - * - SCI_IO_FAILURE_INVALID_IO_TAG - */ -enum sci_io_status { - SCI_IO_SUCCESS = SCI_SUCCESS, - SCI_IO_FAILURE = SCI_FAILURE, - SCI_IO_SUCCESS_COMPLETE_BEFORE_START = SCI_SUCCESS_IO_COMPLETE_BEFORE_START, - SCI_IO_SUCCESS_IO_DONE_EARLY = SCI_SUCCESS_IO_DONE_EARLY, - SCI_IO_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE, - SCI_IO_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES, - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL, - SCI_IO_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID, - SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, - SCI_IO_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED, - SCI_IO_FAILURE_REQUIRES_SCSI_ABORT = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT, - SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE, - SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE, - SCI_IO_FAILURE_PROTOCOL_VIOLATION = SCI_FAILURE_PROTOCOL_VIOLATION, - - SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, - - SCI_IO_FAILURE_RETRY_REQUIRED = SCI_FAILURE_RETRY_REQUIRED, - SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED, - SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE -}; - -/** - * enum sci_task_status - This enumeration depicts all of the possible task - * completion status values. Each value in this enumeration maps directly - * to a value in the enum sci_status enumeration. Please refer to that - * enumeration for detailed comments concerning what the status represents. - * - * Check to see that the following status are properly handled: - */ -enum sci_task_status { - SCI_TASK_SUCCESS = SCI_SUCCESS, - SCI_TASK_FAILURE = SCI_FAILURE, - SCI_TASK_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE, - SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES, - SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL, - SCI_TASK_FAILURE_INVALID_TAG = SCI_FAILURE_INVALID_IO_TAG, - SCI_TASK_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID, - SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, - SCI_TASK_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED, - SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE, - - SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, - SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS - -}; - - -#endif /* _SCI_STATUS_H_ */ - diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c index 4e60d55836e9..0101fec23865 100644 --- a/drivers/scsi/isci/core/sci_util.c +++ b/drivers/scsi/isci/core/sci_util.c @@ -56,6 +56,7 @@ #include #include "sci_util.h" #include "sci_environment.h" +#include "request.h" void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr) { diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index ea09d0bd2d1b..8b8c9259f52f 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -56,17 +56,6 @@ #ifndef _SCIC_SDS_USER_PARAMETERS_H_ #define _SCIC_SDS_USER_PARAMETERS_H_ -/** - * This file contains all of the structure definitions and interface methods - * that can be called by a SCIC user on the SCU Driver Standard - * (struct scic_sds_user_parameters) user parameter block. - * - * - */ - - -#include "sci_status.h" -#include "sci_controller_constants.h" #include "probe_roms.h" struct scic_sds_controller; diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 50ba155a6c7c..bd08f306ed67 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -56,8 +56,6 @@ #ifndef _SCIC_CONTROLLER_H_ #define _SCIC_CONTROLLER_H_ -#include "sci_status.h" -#include "sci_controller.h" #include "scic_config_parameters.h" struct scic_sds_request; @@ -65,12 +63,6 @@ struct scic_sds_phy; struct scic_sds_port; struct scic_sds_remote_device; - -enum sci_controller_mode { - SCI_MODE_SPEED, /* Optimized for performance */ - SCI_MODE_SIZE /* Optimized for memory use */ -}; - enum sci_status scic_controller_construct(struct scic_sds_controller *c, void __iomem *scu_base, void __iomem *smu_base); diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h index f7c6d426f8c0..a4664cc3c576 100644 --- a/drivers/scsi/isci/core/scic_io_request.h +++ b/drivers/scsi/isci/core/scic_io_request.h @@ -56,15 +56,7 @@ #ifndef _SCIC_IO_REQUEST_H_ #define _SCIC_IO_REQUEST_H_ -/** - * This file contains the structures and interface methods that can be - * referenced and used by the SCI user for the SCI IO request object. - * - * Determine the failure situations and return values. - */ - #include -#include "sci_status.h" struct scic_sds_request; struct scic_sds_remote_device; diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h index 1fb49f02162b..f046b4af4b8d 100644 --- a/drivers/scsi/isci/core/scic_phy.h +++ b/drivers/scsi/isci/core/scic_phy.h @@ -66,7 +66,6 @@ #include #include -#include "sci_status.h" struct scic_sds_phy; struct scic_sds_port; diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h index 44a8ea887151..51e7eede5c88 100644 --- a/drivers/scsi/isci/core/scic_port.h +++ b/drivers/scsi/isci/core/scic_port.h @@ -56,8 +56,8 @@ #ifndef _SCIC_PORT_H_ #define _SCIC_PORT_H_ +#include "isci.h" #include "sas.h" -#include "sci_status.h" #include "scic_phy.h" struct scic_sds_port; diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 852b7d52f84f..e77265b9b9ec 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -68,11 +68,11 @@ #include "sci_environment.h" #include "sci_util.h" #include "scu_completion_codes.h" -#include "scu_constants.h" #include "scu_event_codes.h" #include "scu_remote_node_context.h" #include "scu_task_context.h" #include "scu_unsolicited_frame.h" +#include "timers.h" #define SCU_CONTEXT_RAM_INIT_STALL_TIME 200 diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index 0d5047319cbf..5c00f9688c18 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -67,7 +67,6 @@ */ #include "sci_pool.h" -#include "sci_controller_constants.h" #include "sci_base_state.h" #include "sci_base_state_machine.h" #include "scic_config_parameters.h" @@ -76,7 +75,6 @@ #include "remote_node_table.h" #include "remote_device.h" #include "scu_registers.h" -#include "scu_constants.h" #include "scu_task_context.h" #include "scu_unsolicited_frame.h" #include "scic_sds_unsolicited_frame_control.h" diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index f0f4c74e4619..c6df0e2c842e 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -65,6 +65,7 @@ #include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" +#include "timers.h" #define SCIC_SDS_PHY_MIN_TIMER_COUNT (SCI_MAX_PHYS) #define SCIC_SDS_PHY_MAX_TIMER_COUNT (SCI_MAX_PHYS) diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 01288dd44fb6..9302e397e4ca 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -64,6 +64,7 @@ #include "scic_sds_request.h" #include "sci_environment.h" #include "scu_registers.h" +#include "timers.h" #define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) #define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 3633561b686a..3696debcce12 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -58,21 +58,15 @@ #include #include "sas.h" -#include "sci_controller_constants.h" #include "scu_registers.h" - -#define SCIC_SDS_DUMMY_PORT 0xFF +#include "sci_base_state_machine.h" struct scic_sds_controller; struct scic_sds_phy; struct scic_sds_remote_device; struct scic_sds_request; -/** - * This constant defines the value utilized by SCI Components to indicate - * an invalid handle. - */ -#define SCI_INVALID_HANDLE 0x0 +#define SCIC_SDS_DUMMY_PORT 0xFF /** * enum SCIC_SDS_PORT_READY_SUBSTATES - diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index 2d3d067396d3..3fad8c1db6c9 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -53,17 +53,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the implementation for the public and protected methods - * for the port configuration agent. - * - * - */ - #include "sci_environment.h" #include "scic_controller.h" #include "scic_sds_controller.h" #include "scic_sds_port_configuration_agent.h" +#include "timers.h" #define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) #define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 50dd19bba3db..de35885eb1f9 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -67,8 +67,9 @@ #include "sci_environment.h" #include "sci_util.h" #include "scu_completion_codes.h" -#include "scu_constants.h" #include "scu_task_context.h" +#include "request.h" +#include "task.h" /* * **************************************************************************** diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 1dd98aabe32d..5ce7ff2aed9a 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -56,11 +56,11 @@ #ifndef _SCIC_SDS_IO_REQUEST_H_ #define _SCIC_SDS_IO_REQUEST_H_ +#include "isci.h" #include "scic_io_request.h" #include "sci_base_state_machine.h" #include "scu_task_context.h" #include "scic_sds_stp_request.h" -#include "scu_constants.h" #include "sas.h" struct scic_sds_controller; diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 2677393db6f4..c1c316cad522 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -69,6 +69,7 @@ #include "scu_completion_codes.h" #include "scu_event_codes.h" #include "scu_task_context.h" +#include "request.h" void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) { diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h index 4eb244c06cfc..0d8ca8c4770f 100644 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h @@ -53,19 +53,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains all of the unsolicited frame related management for the - * address table, the headers, and actual payload buffers. - * - * - */ - #ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ #define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ +#include "isci.h" #include "scu_unsolicited_frame.h" -#include "scu_constants.h" -#include "sci_status.h" /** * enum unsolicited_frame_state - @@ -144,15 +136,6 @@ struct scic_sds_uf_header_array { }; -/* - * Determine the size of the unsolicited frame array including - * unused buffers. */ -#if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES -#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES -#else -#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES -#endif /* SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES */ - /** * struct scic_sds_uf_buffer_array - * diff --git a/drivers/scsi/isci/core/scic_task_request.h b/drivers/scsi/isci/core/scic_task_request.h index 98cfaa9e6d38..790cee9b4af6 100644 --- a/drivers/scsi/isci/core/scic_task_request.h +++ b/drivers/scsi/isci/core/scic_task_request.h @@ -56,16 +56,7 @@ #ifndef _SCIC_TASK_REQUEST_H_ #define _SCIC_TASK_REQUEST_H_ -/** - * This file contains the structures and interface methods that can be - * referenced and used by the SCI user for to utilize task management - * requests. - * - * - */ - - -#include "sci_status.h" +#include "isci.h" struct scic_sds_request; struct scic_sds_remote_device; diff --git a/drivers/scsi/isci/core/scu_constants.h b/drivers/scsi/isci/core/scu_constants.h deleted file mode 100644 index a99d1103ad3b..000000000000 --- a/drivers/scsi/isci/core/scu_constants.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCU_CONSTANTS_H_ -#define _SCU_CONSTANTS_H_ - -/** - * This file contains the SCU hardware constants. - * - * - */ - -#include "sci_controller_constants.h" - -/** - * - * - * 2 indicates the maximum number of UFs that can occur for a given IO request. - * The hardware handles reception of additional unsolicited frames while all - * UFs are in use, by holding off the transmitting device. This number could - * be theoretically reduced to 1, but 2 provides for more reliable operation. - * During SATA PIO operation, it is possible under some conditions for there to - * be 3 separate FISes received, back to back to back (PIO Setup, Data, D2H - * Register). It is unlikely to have all 3 pending all at once without some of - * them already being processed. - */ -#define SCU_MIN_UNSOLICITED_FRAMES (1) -#define SCU_MIN_CRITICAL_NOTIFICATIONS (24) -#define SCU_MIN_EVENTS (4) -#define SCU_MIN_COMPLETION_QUEUE_SCRATCH (2) -#define SCU_MIN_COMPLETION_QUEUE_ENTRIES (SCU_MIN_CRITICAL_NOTIFICATIONS \ - + SCU_MIN_EVENTS \ - + SCU_MIN_UNSOLICITED_FRAMES \ - + SCI_MIN_IO_REQUESTS \ - + SCU_MIN_COMPLETION_QUEUE_SCRATCH) - -#define SCU_MAX_CRITICAL_NOTIFICATIONS (384) -#define SCU_MAX_EVENTS (128) -#define SCU_MAX_UNSOLICITED_FRAMES (128) -#define SCU_MAX_COMPLETION_QUEUE_SCRATCH (128) -#define SCU_MAX_COMPLETION_QUEUE_ENTRIES (SCU_MAX_CRITICAL_NOTIFICATIONS \ - + SCU_MAX_EVENTS \ - + SCU_MAX_UNSOLICITED_FRAMES \ - + SCI_MAX_IO_REQUESTS \ - + SCU_MAX_COMPLETION_QUEUE_SCRATCH) - -#if !defined(ENABLE_MINIMUM_MEMORY_MODE) -#define SCU_UNSOLICITED_FRAME_COUNT SCU_MAX_UNSOLICITED_FRAMES -#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MAX_CRITICAL_NOTIFICATIONS -#define SCU_EVENT_COUNT SCU_MAX_EVENTS -#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MAX_COMPLETION_QUEUE_SCRATCH -#define SCU_IO_REQUEST_COUNT SCI_MAX_IO_REQUESTS -#define SCU_IO_REQUEST_SGE_COUNT SCI_MAX_SCATTER_GATHER_ELEMENTS -#define SCU_COMPLETION_QUEUE_COUNT SCU_MAX_COMPLETION_QUEUE_ENTRIES -#else -#define SCU_UNSOLICITED_FRAME_COUNT SCU_MIN_UNSOLICITED_FRAMES -#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MIN_CRITICAL_NOTIFICATIONS -#define SCU_EVENT_COUNT SCU_MIN_EVENTS -#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MIN_COMPLETION_QUEUE_SCRATCH -#define SCU_IO_REQUEST_COUNT SCI_MIN_IO_REQUESTS -#define SCU_IO_REQUEST_SGE_COUNT SCI_MIN_SCATTER_GATHER_ELEMENTS -#define SCU_COMPLETION_QUEUE_COUNT SCU_MIN_COMPLETION_QUEUE_ENTRIES -#endif /* !defined(ENABLE_MINIMUM_MEMORY_OPERATION) */ - -/** - * - * - * The SCU_COMPLETION_QUEUE_COUNT constant indicates the size of the completion - * queue into which the hardware DMAs 32-bit quantas (completion entries). - */ - -/** - * - * - * This queue must be programmed to a power of 2 size (e.g. 32, 64, 1024, etc.). - */ -#if (SCU_COMPLETION_QUEUE_COUNT != 16) && \ - (SCU_COMPLETION_QUEUE_COUNT != 32) && \ - (SCU_COMPLETION_QUEUE_COUNT != 64) && \ - (SCU_COMPLETION_QUEUE_COUNT != 128) && \ - (SCU_COMPLETION_QUEUE_COUNT != 256) && \ - (SCU_COMPLETION_QUEUE_COUNT != 512) && \ - (SCU_COMPLETION_QUEUE_COUNT != 1024) -#error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2." -#endif - -#if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES -#error "Invalid configuration of unsolicited frame constants" -#endif /* SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES */ - -#define SCU_MIN_UF_TABLE_ENTRIES (8) -#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096) -#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024) -#define SCU_INVALID_FRAME_INDEX (0xFFFF) - -#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF) -#define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH (0x00FFFFFF) - -#endif /* _SCU_CONSTANTS_H_ */ diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 271a7e171e7d..5847149857a9 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -60,7 +60,9 @@ #include "request.h" #include "host.h" #include "probe_roms.h" +#include "scic_controller.h" #include "scic_sds_controller.h" +#include "timers.h" irqreturn_t isci_msix_isr(int vec, void *data) { diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index afa41e83eaa7..13c1c99ef294 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -53,26 +53,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#if !defined(_SCI_HOST_H_) +#ifndef _SCI_HOST_H_ #define _SCI_HOST_H_ -#include "phy.h" #include "scic_sds_controller.h" -#include "timers.h" #include "remote_device.h" - -#define DRV_NAME "isci" -#define SCI_PCI_BAR_COUNT 2 -#define SCI_NUM_MSI_X_INT 2 -#define SCI_SMU_BAR 0 -#define SCI_SMU_BAR_SIZE (16*1024) -#define SCI_SCU_BAR 1 -#define SCI_SCU_BAR_SIZE (4*1024*1024) -#define SCI_IO_SPACE_BAR0 2 -#define SCI_IO_SPACE_BAR1 3 -#define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */ -#define SCIC_CONTROLLER_STOP_TIMEOUT 5000 +#include "phy.h" struct isci_host { struct scic_sds_controller sci; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 522d39f9e132..df132c07badf 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -61,9 +61,9 @@ #include #include "isci.h" #include "task.h" -#include "sci_controller_constants.h" #include "sci_environment.h" #include "probe_roms.h" +#include "scic_controller.h" static struct scsi_transport_template *isci_transport_template; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 60c84627c13e..800f2332ecd0 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -56,22 +56,470 @@ #ifndef __ISCI_H__ #define __ISCI_H__ -#include -#include -#include -#include #include -#include -#include -#include - -#include "scic_controller.h" -#include "host.h" -#include "timers.h" -#include "sci_status.h" -#include "request.h" -#include "task.h" -#include "sata.h" + +#define DRV_NAME "isci" +#define SCI_PCI_BAR_COUNT 2 +#define SCI_NUM_MSI_X_INT 2 +#define SCI_SMU_BAR 0 +#define SCI_SMU_BAR_SIZE (16*1024) +#define SCI_SCU_BAR 1 +#define SCI_SCU_BAR_SIZE (4*1024*1024) +#define SCI_IO_SPACE_BAR0 2 +#define SCI_IO_SPACE_BAR1 3 +#define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */ +#define SCIC_CONTROLLER_STOP_TIMEOUT 5000 + +#define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF + +enum sci_controller_mode { + SCI_MODE_SPEED, + SCI_MODE_SIZE /* deprecated */ +}; + +#define SCI_MAX_PHYS (4) +#define SCI_MAX_PORTS SCI_MAX_PHYS +#define SCI_MIN_SMP_PHYS (38) +#define SCI_MAX_SMP_PHYS (384) /* not silicon constrained */ +#define SCI_MAX_REMOTE_DEVICES (256) +#define SCI_MIN_REMOTE_DEVICES (16) +#define SCI_MAX_IO_REQUESTS (256) +#define SCI_MIN_IO_REQUESTS (1) +#define SCI_MAX_MSIX_MESSAGES (2) +#define SCI_MAX_SCATTER_GATHER_ELEMENTS 130 /* not silicon constrained */ +#define SCI_MIN_SCATTER_GATHER_ELEMENTS 1 +#define SCI_MAX_CONTROLLERS 2 +#define SCI_MAX_DOMAINS SCI_MAX_PORTS + +/* 2 indicates the maximum number of UFs that can occur for a given IO request. + * The hardware handles reception of additional unsolicited frames while all + * UFs are in use, by holding off the transmitting device. This number could + * be theoretically reduced to 1, but 2 provides for more reliable operation. + * During SATA PIO operation, it is possible under some conditions for there to + * be 3 separate FISes received, back to back to back (PIO Setup, Data, D2H + * Register). It is unlikely to have all 3 pending all at once without some of + * them already being processed. + */ +#define SCU_MIN_UNSOLICITED_FRAMES (1) +#define SCU_MIN_CRITICAL_NOTIFICATIONS (24) +#define SCU_MIN_EVENTS (4) +#define SCU_MIN_COMPLETION_QUEUE_SCRATCH (2) +#define SCU_MIN_COMPLETION_QUEUE_ENTRIES (SCU_MIN_CRITICAL_NOTIFICATIONS \ + + SCU_MIN_EVENTS \ + + SCU_MIN_UNSOLICITED_FRAMES \ + + SCI_MIN_IO_REQUESTS \ + + SCU_MIN_COMPLETION_QUEUE_SCRATCH) + +#define SCU_MAX_CRITICAL_NOTIFICATIONS (384) +#define SCU_MAX_EVENTS (128) +#define SCU_MAX_UNSOLICITED_FRAMES (128) +#define SCU_MAX_COMPLETION_QUEUE_SCRATCH (128) +#define SCU_MAX_COMPLETION_QUEUE_ENTRIES (SCU_MAX_CRITICAL_NOTIFICATIONS \ + + SCU_MAX_EVENTS \ + + SCU_MAX_UNSOLICITED_FRAMES \ + + SCI_MAX_IO_REQUESTS \ + + SCU_MAX_COMPLETION_QUEUE_SCRATCH) + +#if !defined(ENABLE_MINIMUM_MEMORY_MODE) +#define SCU_UNSOLICITED_FRAME_COUNT SCU_MAX_UNSOLICITED_FRAMES +#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MAX_CRITICAL_NOTIFICATIONS +#define SCU_EVENT_COUNT SCU_MAX_EVENTS +#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MAX_COMPLETION_QUEUE_SCRATCH +#define SCU_IO_REQUEST_COUNT SCI_MAX_IO_REQUESTS +#define SCU_IO_REQUEST_SGE_COUNT SCI_MAX_SCATTER_GATHER_ELEMENTS +#define SCU_COMPLETION_QUEUE_COUNT SCU_MAX_COMPLETION_QUEUE_ENTRIES +#else +#define SCU_UNSOLICITED_FRAME_COUNT SCU_MIN_UNSOLICITED_FRAMES +#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MIN_CRITICAL_NOTIFICATIONS +#define SCU_EVENT_COUNT SCU_MIN_EVENTS +#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MIN_COMPLETION_QUEUE_SCRATCH +#define SCU_IO_REQUEST_COUNT SCI_MIN_IO_REQUESTS +#define SCU_IO_REQUEST_SGE_COUNT SCI_MIN_SCATTER_GATHER_ELEMENTS +#define SCU_COMPLETION_QUEUE_COUNT SCU_MIN_COMPLETION_QUEUE_ENTRIES +#endif /* !defined(ENABLE_MINIMUM_MEMORY_OPERATION) */ + +/** + * + * + * The SCU_COMPLETION_QUEUE_COUNT constant indicates the size of the completion + * queue into which the hardware DMAs 32-bit quantas (completion entries). + */ + +/** + * + * + * This queue must be programmed to a power of 2 size (e.g. 32, 64, 1024, etc.). + */ +#if (SCU_COMPLETION_QUEUE_COUNT != 16) && \ + (SCU_COMPLETION_QUEUE_COUNT != 32) && \ + (SCU_COMPLETION_QUEUE_COUNT != 64) && \ + (SCU_COMPLETION_QUEUE_COUNT != 128) && \ + (SCU_COMPLETION_QUEUE_COUNT != 256) && \ + (SCU_COMPLETION_QUEUE_COUNT != 512) && \ + (SCU_COMPLETION_QUEUE_COUNT != 1024) +#error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2." +#endif + +#if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES +#error "Invalid configuration of unsolicited frame constants" +#endif /* SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES */ + +#define SCU_MIN_UF_TABLE_ENTRIES (8) +#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096) +#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024) +#define SCU_INVALID_FRAME_INDEX (0xFFFF) + +#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF) +#define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH (0x00FFFFFF) + +/* + * Determine the size of the unsolicited frame array including + * unused buffers. */ +#if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES +#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES +#else +#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES +#endif /* SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES */ + +/** + * enum sci_status - This is the general return status enumeration for non-IO, + * non-task management related SCI interface methods. + * + * + */ +enum sci_status { + /** + * This member indicates successful completion. + */ + SCI_SUCCESS = 0, + + /** + * This value indicates that the calling method completed successfully, + * but that the IO may have completed before having it's start method + * invoked. This occurs during SAT translation for requests that do + * not require an IO to the target or for any other requests that may + * be completed without having to submit IO. + */ + SCI_SUCCESS_IO_COMPLETE_BEFORE_START, + + /** + * This Value indicates that the SCU hardware returned an early response + * because the io request specified more data than is returned by the + * target device (mode pages, inquiry data, etc.). The completion routine + * will handle this case to get the actual number of bytes transferred. + */ + SCI_SUCCESS_IO_DONE_EARLY, + + /** + * This member indicates that the object for which a state change is + * being requested is already in said state. + */ + SCI_WARNING_ALREADY_IN_STATE, + + /** + * This member indicates interrupt coalescence timer may cause SAS + * specification compliance issues (i.e. SMP target mode response + * frames must be returned within 1.9 milliseconds). + */ + SCI_WARNING_TIMER_CONFLICT, + + /** + * This field indicates a sequence of action is not completed yet. Mostly, + * this status is used when multiple ATA commands are needed in a SATI translation. + */ + SCI_WARNING_SEQUENCE_INCOMPLETE, + + /** + * This member indicates that there was a general failure. + */ + SCI_FAILURE, + + /** + * This member indicates that the SCI implementation is unable to complete + * an operation due to a critical flaw the prevents any further operation + * (i.e. an invalid pointer). + */ + SCI_FATAL_ERROR, + + /** + * This member indicates the calling function failed, because the state + * of the controller is in a state that prevents successful completion. + */ + SCI_FAILURE_INVALID_STATE, + + /** + * This member indicates the calling function failed, because there is + * insufficient resources/memory to complete the request. + */ + SCI_FAILURE_INSUFFICIENT_RESOURCES, + + /** + * This member indicates the calling function failed, because the + * controller object required for the operation can't be located. + */ + SCI_FAILURE_CONTROLLER_NOT_FOUND, + + /** + * This member indicates the calling function failed, because the + * discovered controller type is not supported by the library. + */ + SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE, + + /** + * This member indicates the calling function failed, because the + * requested initialization data version isn't supported. + */ + SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION, + + /** + * This member indicates the calling function failed, because the + * requested configuration of SAS Phys into SAS Ports is not supported. + */ + SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION, + + /** + * This member indicates the calling function failed, because the + * requested protocol is not supported by the remote device, port, + * or controller. + */ + SCI_FAILURE_UNSUPPORTED_PROTOCOL, + + /** + * This member indicates the calling function failed, because the + * requested information type is not supported by the SCI implementation. + */ + SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE, + + /** + * This member indicates the calling function failed, because the + * device already exists. + */ + SCI_FAILURE_DEVICE_EXISTS, + + /** + * This member indicates the calling function failed, because adding + * a phy to the object is not possible. + */ + SCI_FAILURE_ADDING_PHY_UNSUPPORTED, + + /** + * This member indicates the calling function failed, because the + * requested information type is not supported by the SCI implementation. + */ + SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD, + + /** + * This member indicates the calling function failed, because the SCI + * implementation does not support the supplied time limit. + */ + SCI_FAILURE_UNSUPPORTED_TIME_LIMIT, + + /** + * This member indicates the calling method failed, because the SCI + * implementation does not contain the specified Phy. + */ + SCI_FAILURE_INVALID_PHY, + + /** + * This member indicates the calling method failed, because the SCI + * implementation does not contain the specified Port. + */ + SCI_FAILURE_INVALID_PORT, + + /** + * This member indicates the calling method was partly successful + * The port was reset but not all phys in port are operational + */ + SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS, + + /** + * This member indicates that calling method failed + * The port reset did not complete because none of the phys are operational + */ + SCI_FAILURE_RESET_PORT_FAILURE, + + /** + * This member indicates the calling method failed, because the SCI + * implementation does not contain the specified remote device. + */ + SCI_FAILURE_INVALID_REMOTE_DEVICE, + + /** + * This member indicates the calling method failed, because the remote + * device is in a bad state and requires a reset. + */ + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, + + /** + * This member indicates the calling method failed, because the SCI + * implementation does not contain or support the specified IO tag. + */ + SCI_FAILURE_INVALID_IO_TAG, + + /** + * This member indicates that the operation failed and the user should + * check the response data associated with the IO. + */ + SCI_FAILURE_IO_RESPONSE_VALID, + + /** + * This member indicates that the operation failed, the failure is + * controller implementation specific, and the response data associated + * with the request is not valid. You can query for the controller + * specific error information via scic_controller_get_request_status() + */ + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, + + /** + * This member indicated that the operation failed because the + * user requested this IO to be terminated. + */ + SCI_FAILURE_IO_TERMINATED, + + /** + * This member indicates that the operation failed and the associated + * request requires a SCSI abort task to be sent to the target. + */ + SCI_FAILURE_IO_REQUIRES_SCSI_ABORT, + + /** + * This member indicates that the operation failed because the supplied + * device could not be located. + */ + SCI_FAILURE_DEVICE_NOT_FOUND, + + /** + * This member indicates that the operation failed because the + * objects association is required and is not correctly set. + */ + SCI_FAILURE_INVALID_ASSOCIATION, + + /** + * This member indicates that the operation failed, because a timeout + * occurred. + */ + SCI_FAILURE_TIMEOUT, + + /** + * This member indicates that the operation failed, because the user + * specified a value that is either invalid or not supported. + */ + SCI_FAILURE_INVALID_PARAMETER_VALUE, + + /** + * This value indicates that the operation failed, because the number + * of messages (MSI-X) is not supported. + */ + SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT, + + /** + * This value indicates that the method failed due to a lack of + * available NCQ tags. + */ + SCI_FAILURE_NO_NCQ_TAG_AVAILABLE, + + /** + * This value indicates that a protocol violation has occurred on the + * link. + */ + SCI_FAILURE_PROTOCOL_VIOLATION, + + /** + * This value indicates a failure condition that retry may help to clear. + */ + SCI_FAILURE_RETRY_REQUIRED, + + /** + * This field indicates the retry limit was reached when a retry is attempted + */ + SCI_FAILURE_RETRY_LIMIT_REACHED, + + /** + * This member indicates the calling method was partly successful. + * Mostly, this status is used when a LUN_RESET issued to an expander attached + * STP device in READY NCQ substate needs to have RNC suspended/resumed + * before posting TC. + */ + SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS, + + /** + * This field indicates an illegal phy connection based on the routing attribute + * of both expander phy attached to each other. + */ + SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION, + + /** + * This field indicates a CONFIG ROUTE INFO command has a response with function result + * INDEX DOES NOT EXIST, usually means exceeding max route index. + */ + SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX, + + /** + * This value indicates that an unsupported PCI device ID has been + * specified. This indicates that attempts to invoke + * scic_library_allocate_controller() will fail. + */ + SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID + +}; + +/** + * enum sci_io_status - This enumeration depicts all of the possible IO + * completion status values. Each value in this enumeration maps directly + * to a value in the enum sci_status enumeration. Please refer to that + * enumeration for detailed comments concerning what the status represents. + * + * Add the API to retrieve the SCU status from the core. Check to see that the + * following status are properly handled: - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL + * - SCI_IO_FAILURE_INVALID_IO_TAG + */ +enum sci_io_status { + SCI_IO_SUCCESS = SCI_SUCCESS, + SCI_IO_FAILURE = SCI_FAILURE, + SCI_IO_SUCCESS_COMPLETE_BEFORE_START = SCI_SUCCESS_IO_COMPLETE_BEFORE_START, + SCI_IO_SUCCESS_IO_DONE_EARLY = SCI_SUCCESS_IO_DONE_EARLY, + SCI_IO_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE, + SCI_IO_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES, + SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL, + SCI_IO_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID, + SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, + SCI_IO_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED, + SCI_IO_FAILURE_REQUIRES_SCSI_ABORT = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT, + SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE, + SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE, + SCI_IO_FAILURE_PROTOCOL_VIOLATION = SCI_FAILURE_PROTOCOL_VIOLATION, + + SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, + + SCI_IO_FAILURE_RETRY_REQUIRED = SCI_FAILURE_RETRY_REQUIRED, + SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED, + SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE +}; + +/** + * enum sci_task_status - This enumeration depicts all of the possible task + * completion status values. Each value in this enumeration maps directly + * to a value in the enum sci_status enumeration. Please refer to that + * enumeration for detailed comments concerning what the status represents. + * + * Check to see that the following status are properly handled: + */ +enum sci_task_status { + SCI_TASK_SUCCESS = SCI_SUCCESS, + SCI_TASK_FAILURE = SCI_FAILURE, + SCI_TASK_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE, + SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES, + SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL, + SCI_TASK_FAILURE_INVALID_TAG = SCI_FAILURE_INVALID_IO_TAG, + SCI_TASK_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID, + SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, + SCI_TASK_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED, + SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE, + + SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, + SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS + +}; extern unsigned char no_outbound_task_to; extern u16 ssp_max_occ_to; @@ -85,9 +533,9 @@ irqreturn_t isci_msix_isr(int vec, void *data); irqreturn_t isci_intx_isr(int vec, void *data); irqreturn_t isci_error_isr(int vec, void *data); +struct scic_sds_controller; bool scic_sds_controller_isr(struct scic_sds_controller *scic); void scic_sds_controller_completion_handler(struct scic_sds_controller *scic); bool scic_sds_controller_error_isr(struct scic_sds_controller *scic); void scic_sds_controller_error_handler(struct scic_sds_controller *scic); - #endif /* __ISCI_H__ */ diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 328004918329..1134395c970e 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -54,10 +54,10 @@ */ #include "isci.h" +#include "host.h" #include "phy.h" #include "scic_port.h" #include "scic_config_parameters.h" -#include "core/scic_sds_phy.h" struct scic_sds_phy; extern enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy); diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 93ec2d4a9c30..3a95adbb508c 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -52,16 +52,12 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - - #ifndef _ISCI_PHY_H_ #define _ISCI_PHY_H_ #include #include #include "scic_sds_phy.h" -#include "port.h" -#include "host.h" struct isci_phy { struct scic_sds_phy sci; @@ -89,6 +85,7 @@ static inline struct isci_phy *sci_phy_to_iphy(struct scic_sds_phy *sci_phy) return iphy; } +struct isci_host; void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index); int isci_phy_control(struct asd_sas_phy *phy, enum phy_func func, void *buf); diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 355034542e4c..59505cbf2bb3 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -55,6 +55,9 @@ #ifndef _ISCI_PORT_H_ #define _ISCI_PORT_H_ + +#include +#include "isci.h" #include "scic_sds_port.h" struct isci_phy; diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 933d81109ea4..705517440441 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -32,7 +32,6 @@ #include "isci.h" #include "task.h" -#include "sci_controller_constants.h" #include "sci_environment.h" #include "probe_roms.h" diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 55983363764b..f4ef19ac281c 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -58,6 +58,7 @@ #ifdef __KERNEL__ #include #include +#include "isci.h" struct isci_orom *isci_request_oprom(struct pci_dev *pdev); diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 2e433b7f16b3..a118f5873f64 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -56,7 +56,6 @@ #ifndef _ISCI_REMOTE_DEVICE_H_ #define _ISCI_REMOTE_DEVICE_H_ #include -#include "sci_status.h" #include "scu_remote_node_context.h" #include "remote_node_context.h" #include "port.h" diff --git a/drivers/scsi/isci/remote_node_table.h b/drivers/scsi/isci/remote_node_table.h index 9c02a6ccb2fe..5737d9a30cca 100644 --- a/drivers/scsi/isci/remote_node_table.h +++ b/drivers/scsi/isci/remote_node_table.h @@ -56,14 +56,7 @@ #ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_ #define _SCIC_SDS_REMOTE_NODE_TABLE_H_ -/** - * This file contains the structures, constants and prototypes used for the - * remote node table. - * - * - */ - -#include "sci_controller_constants.h" +#include "isci.h" /** * diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 4961ee347091..a58072807a37 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -62,6 +62,7 @@ #include "sata.h" #include "scu_completion_codes.h" #include "scic_sds_request.h" +#include "scic_controller.h" #include "sas.h" static enum sci_status isci_request_ssp_request_construct( diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 89d8b0a27dfe..06786ece9bb2 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -57,6 +57,7 @@ #define _ISCI_REQUEST_H_ #include "isci.h" +#include "host.h" #include "scic_sds_request.h" /** diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h index 1806969fc435..30addba4d43a 100644 --- a/drivers/scsi/isci/sci_environment.h +++ b/drivers/scsi/isci/sci_environment.h @@ -56,8 +56,7 @@ #ifndef _SCI_ENVIRONMENT_H_ #define _SCI_ENVIRONMENT_H_ -#include "isci.h" -#include "core/scic_sds_controller.h" +#include "host.h" static inline struct device *scic_to_dev(struct scic_sds_controller *scic) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 7adaf71c19d1..597c49020ac8 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -65,6 +65,8 @@ #include "sata.h" #include "task.h" #include "scic_sds_request.h" +#include "scic_controller.h" +#include "timers.h" /** * isci_task_refuse() - complete the request to the upper layer driver in diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index ecc5f1395063..c59dc9620cf9 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -56,6 +56,7 @@ #define _ISCI_TASK_H_ #include +#include "host.h" struct isci_request; diff --git a/drivers/scsi/isci/timers.c b/drivers/scsi/isci/timers.c index f33eff00dc01..007700e3eb6a 100644 --- a/drivers/scsi/isci/timers.c +++ b/drivers/scsi/isci/timers.c @@ -55,6 +55,7 @@ #include "isci.h" #include "timers.h" +#include "host.h" /** * isci_timer_list_construct() - This method contrucst the SCI Timer List -- cgit v1.2.3 From cc9203bf381a465cd115762b9cf7c9a313c874bc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 8 May 2011 17:34:44 -0700 Subject: isci: move core/controller to host Now that the data structures are unified unify the implementation in host.[ch] and cleanup namespace pollution. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 1 - drivers/scsi/isci/core/sci_pool.h | 199 -- drivers/scsi/isci/core/sci_util.c | 1 - drivers/scsi/isci/core/scic_config_parameters.h | 38 - drivers/scsi/isci/core/scic_controller.h | 130 - drivers/scsi/isci/core/scic_sds_controller.c | 2973 -------------------- drivers/scsi/isci/core/scic_sds_controller.h | 576 ---- drivers/scsi/isci/core/scic_sds_phy.c | 3 +- drivers/scsi/isci/core/scic_sds_port.c | 4 +- drivers/scsi/isci/core/scic_sds_port.h | 1 + .../isci/core/scic_sds_port_configuration_agent.c | 4 +- drivers/scsi/isci/core/scic_sds_request.c | 3 - drivers/scsi/isci/core/scic_sds_smp_request.c | 4 +- drivers/scsi/isci/core/scic_sds_ssp_request.c | 4 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 2 - .../isci/core/scic_sds_unsolicited_frame_control.c | 11 +- drivers/scsi/isci/host.c | 2791 +++++++++++++++++- drivers/scsi/isci/host.h | 612 +++- drivers/scsi/isci/init.c | 2 - drivers/scsi/isci/isci.h | 6 - drivers/scsi/isci/pool.h | 199 ++ drivers/scsi/isci/port.c | 8 - drivers/scsi/isci/probe_roms.c | 1 - drivers/scsi/isci/remote_device.c | 3 - drivers/scsi/isci/remote_node_context.c | 3 +- drivers/scsi/isci/remote_node_table.c | 1 - drivers/scsi/isci/request.c | 1 - drivers/scsi/isci/sci_environment.h | 122 - drivers/scsi/isci/task.c | 1 - 29 files changed, 3562 insertions(+), 4142 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_pool.h delete mode 100644 drivers/scsi/isci/core/scic_controller.h delete mode 100644 drivers/scsi/isci/core/scic_sds_controller.c delete mode 100644 drivers/scsi/isci/core/scic_sds_controller.h create mode 100644 drivers/scsi/isci/pool.h delete mode 100644 drivers/scsi/isci/sci_environment.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 78ba0fc3548a..45f8f68caf4a 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -5,7 +5,6 @@ isci-objs := init.o phy.o request.o sata.o \ host.o task.o probe_roms.o \ remote_node_context.o \ remote_node_table.o \ - core/scic_sds_controller.o \ core/scic_sds_request.o \ core/scic_sds_stp_request.o \ core/scic_sds_port.o \ diff --git a/drivers/scsi/isci/core/sci_pool.h b/drivers/scsi/isci/core/sci_pool.h deleted file mode 100644 index 016ec832f74f..000000000000 --- a/drivers/scsi/isci/core/sci_pool.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains the interface to the pool class. This class allows two - * different two different priority tasks to insert and remove items from - * the free pool. The user of the pool is expected to evaluate the pool - * condition empty before a get operation and pool condition full before a - * put operation. Methods Provided: - sci_pool_create() - - * sci_pool_initialize() - sci_pool_empty() - sci_pool_full() - - * sci_pool_get() - sci_pool_put() - * - * - */ - -#ifndef _SCI_POOL_H_ -#define _SCI_POOL_H_ - -/** - * SCI_POOL_INCREMENT() - - * - * Private operation for the pool - */ -#define SCI_POOL_INCREMENT(pool, index) \ - (((index) + 1) == (pool).size ? 0 : (index) + 1) - -/** - * SCI_POOL_CREATE() - - * - * This creates a pool structure of pool_name. The members in the pool are of - * type with number of elements equal to size. - */ -#define SCI_POOL_CREATE(pool_name, type, pool_size) \ - struct \ - { \ - u32 size; \ - u32 get; \ - u32 put; \ - type array[(pool_size) + 1]; \ - } pool_name - - -/** - * sci_pool_empty() - - * - * This macro evaluates the pool and returns true if the pool is empty. If the - * pool is empty the user should not perform any get operation on the pool. - */ -#define sci_pool_empty(pool) \ - ((pool).get == (pool).put) - -/** - * sci_pool_full() - - * - * This macro evaluates the pool and returns true if the pool is full. If the - * pool is full the user should not perform any put operation. - */ -#define sci_pool_full(pool) \ - (SCI_POOL_INCREMENT(pool, (pool).put) == (pool).get) - -/** - * sci_pool_size() - - * - * This macro returns the size of the pool created. The internal size of the - * pool is actually 1 larger then necessary in order to ensure get and put - * pointers can be written simultaneously by different users. As a result, - * this macro subtracts 1 from the internal size - */ -#define sci_pool_size(pool) \ - ((pool).size - 1) - -/** - * sci_pool_count() - - * - * This macro indicates the number of elements currently contained in the pool. - */ -#define sci_pool_count(pool) \ - (\ - sci_pool_empty((pool)) \ - ? 0 \ - : (\ - sci_pool_full((pool)) \ - ? sci_pool_size((pool)) \ - : (\ - (pool).get > (pool).put \ - ? ((pool).size - (pool).get + (pool).put) \ - : ((pool).put - (pool).get) \ - ) \ - ) \ - ) - -/** - * sci_pool_initialize() - - * - * This macro initializes the pool to an empty condition. - */ -#define sci_pool_initialize(pool) \ - { \ - (pool).size = (sizeof((pool).array) / sizeof((pool).array[0])); \ - (pool).get = 0; \ - (pool).put = 0; \ - } - -/** - * sci_pool_get() - - * - * This macro will get the next free element from the pool. This should only be - * called if the pool is not empty. - */ -#define sci_pool_get(pool, my_value) \ - { \ - (my_value) = (pool).array[(pool).get]; \ - (pool).get = SCI_POOL_INCREMENT((pool), (pool).get); \ - } - -/** - * sci_pool_put() - - * - * This macro will put the value into the pool. This should only be called if - * the pool is not full. - */ -#define sci_pool_put(pool, value) \ - { \ - (pool).array[(pool).put] = (value); \ - (pool).put = SCI_POOL_INCREMENT((pool), (pool).put); \ - } - -/** - * sci_pool_erase() - - * - * This macro will search the pool and remove any elements in the pool matching - * the supplied value. This method can only be utilized on pools - */ -#define sci_pool_erase(pool, type, value) \ - { \ - type tmp_value; \ - u32 index; \ - u32 element_count = sci_pool_count((pool)); \ - \ - for (index = 0; index < element_count; index++) { \ - sci_pool_get((pool), tmp_value); \ - if (tmp_value != (value)) \ - sci_pool_put((pool), tmp_value); \ - } \ - } - -#endif /* _SCI_POOL_H_ */ diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c index 0101fec23865..595d8da1abba 100644 --- a/drivers/scsi/isci/core/sci_util.c +++ b/drivers/scsi/isci/core/sci_util.c @@ -55,7 +55,6 @@ #include #include "sci_util.h" -#include "sci_environment.h" #include "request.h" void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr) diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h index 8b8c9259f52f..15e7744dbdcf 100644 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ b/drivers/scsi/isci/core/scic_config_parameters.h @@ -229,44 +229,6 @@ union scic_oem_parameters { struct scic_sds_oem_params sds1; }; -/** - * scic_user_parameters_set() - This method allows the user to attempt to - * change the user parameters utilized by the controller. - * @controller: This parameter specifies the controller on which to set the - * user parameters. - * @user_parameters: This parameter specifies the USER_PARAMETERS object - * containing the potential new values. - * - * Indicate if the update of the user parameters was successful. SCI_SUCCESS - * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE - * This value is returned if the attempt to change the user parameter failed, - * because changing one of the parameters is not currently allowed. - * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user - * supplied an invalid interrupt coalescence time, spin up delay interval, etc. - */ -enum sci_status scic_user_parameters_set( - struct scic_sds_controller *controller, - union scic_user_parameters *user_parameters); - -/** - * scic_oem_parameters_set() - This method allows the user to attempt to change - * the OEM parameters utilized by the controller. - * @controller: This parameter specifies the controller on which to set the - * user parameters. - * @oem_parameters: This parameter specifies the OEM parameters object - * containing the potential new values. - * - * Indicate if the update of the user parameters was successful. SCI_SUCCESS - * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE - * This value is returned if the attempt to change the user parameter failed, - * because changing one of the parameters is not currently allowed. - * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user - * supplied an unsupported value for one of the OEM parameters. - */ -enum sci_status scic_oem_parameters_set( - struct scic_sds_controller *controller, - union scic_oem_parameters *oem_parameters); - int scic_oem_parameters_validate(struct scic_sds_oem_params *oem); /** diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h deleted file mode 100644 index bd08f306ed67..000000000000 --- a/drivers/scsi/isci/core/scic_controller.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_CONTROLLER_H_ -#define _SCIC_CONTROLLER_H_ - -#include "scic_config_parameters.h" - -struct scic_sds_request; -struct scic_sds_phy; -struct scic_sds_port; -struct scic_sds_remote_device; - -enum sci_status scic_controller_construct(struct scic_sds_controller *c, - void __iomem *scu_base, - void __iomem *smu_base); - -void scic_controller_enable_interrupts( - struct scic_sds_controller *controller); - -void scic_controller_disable_interrupts( - struct scic_sds_controller *controller); - -enum sci_status scic_controller_initialize( - struct scic_sds_controller *controller); - -u32 scic_controller_get_suggested_start_timeout( - struct scic_sds_controller *controller); - -enum sci_status scic_controller_start( - struct scic_sds_controller *controller, - u32 timeout); - -enum sci_status scic_controller_stop( - struct scic_sds_controller *controller, - u32 timeout); - -enum sci_status scic_controller_reset( - struct scic_sds_controller *controller); - -enum sci_status scic_controller_start_io( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *io_request, - u16 io_tag); - -enum sci_task_status scic_controller_start_task( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *task_request, - u16 io_tag); - -enum sci_status scic_controller_terminate_request( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *request); - -enum sci_status scic_controller_complete_io( - struct scic_sds_controller *controller, - struct scic_sds_remote_device *remote_device, - struct scic_sds_request *io_request); - -enum sci_status scic_controller_get_phy_handle( - struct scic_sds_controller *controller, - u8 phy_index, - struct scic_sds_phy **phy_handle); - -u16 scic_controller_allocate_io_tag( - struct scic_sds_controller *controller); - -enum sci_status scic_controller_free_io_tag( - struct scic_sds_controller *controller, - u16 io_tag); - -struct device; -struct scic_sds_controller *scic_controller_alloc(struct device *dev); -int scic_controller_mem_init(struct scic_sds_controller *scic); -#endif /* _SCIC_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c deleted file mode 100644 index e77265b9b9ec..000000000000 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ /dev/null @@ -1,2973 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include "scic_controller.h" -#include "scic_phy.h" -#include "scic_port.h" -#include "scic_sds_controller.h" -#include "scu_registers.h" -#include "scic_sds_phy.h" -#include "scic_sds_port_configuration_agent.h" -#include "scic_sds_port.h" -#include "remote_device.h" -#include "scic_sds_request.h" -#include "sci_environment.h" -#include "sci_util.h" -#include "scu_completion_codes.h" -#include "scu_event_codes.h" -#include "scu_remote_node_context.h" -#include "scu_task_context.h" -#include "scu_unsolicited_frame.h" -#include "timers.h" - -#define SCU_CONTEXT_RAM_INIT_STALL_TIME 200 - -/** - * smu_dcc_get_max_ports() - - * - * This macro returns the maximum number of logical ports supported by the - * hardware. The caller passes in the value read from the device context - * capacity register and this macro will mash and shift the value appropriately. - */ -#define smu_dcc_get_max_ports(dcc_value) \ - (\ - (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ - >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \ - ) - -/** - * smu_dcc_get_max_task_context() - - * - * This macro returns the maximum number of task contexts supported by the - * hardware. The caller passes in the value read from the device context - * capacity register and this macro will mash and shift the value appropriately. - */ -#define smu_dcc_get_max_task_context(dcc_value) \ - (\ - (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ - >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \ - ) - -/** - * smu_dcc_get_max_remote_node_context() - - * - * This macro returns the maximum number of remote node contexts supported by - * the hardware. The caller passes in the value read from the device context - * capacity register and this macro will mash and shift the value appropriately. - */ -#define smu_dcc_get_max_remote_node_context(dcc_value) \ - (\ - (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ - >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \ - ) - - -static void scic_sds_controller_power_control_timer_handler( - void *controller); -#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3 -#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3 - -/** - * - * - * The number of milliseconds to wait for a phy to start. - */ -#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100 - -/** - * - * - * The number of milliseconds to wait while a given phy is consuming power - * before allowing another set of phys to consume power. Ultimately, this will - * be specified by OEM parameter. - */ -#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500 - -/** - * COMPLETION_QUEUE_CYCLE_BIT() - - * - * This macro will return the cycle bit of the completion queue entry - */ -#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000) - -/** - * NORMALIZE_GET_POINTER() - - * - * This macro will normalize the completion queue get pointer so its value can - * be used as an index into an array - */ -#define NORMALIZE_GET_POINTER(x) \ - ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK) - -/** - * NORMALIZE_PUT_POINTER() - - * - * This macro will normalize the completion queue put pointer so its value can - * be used as an array inde - */ -#define NORMALIZE_PUT_POINTER(x) \ - ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK) - - -/** - * NORMALIZE_GET_POINTER_CYCLE_BIT() - - * - * This macro will normalize the completion queue cycle pointer so it matches - * the completion queue cycle bit - */ -#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \ - ((SMU_CQGR_CYCLE_BIT & (x)) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT)) - -/** - * NORMALIZE_EVENT_POINTER() - - * - * This macro will normalize the completion queue event entry so its value can - * be used as an index. - */ -#define NORMALIZE_EVENT_POINTER(x) \ - (\ - ((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK) \ - >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \ - ) - -/** - * INCREMENT_COMPLETION_QUEUE_GET() - - * - * This macro will increment the controllers completion queue index value and - * possibly toggle the cycle bit if the completion queue index wraps back to 0. - */ -#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \ - INCREMENT_QUEUE_GET(\ - (index), \ - (cycle), \ - (controller)->completion_queue_entries, \ - SMU_CQGR_CYCLE_BIT \ - ) - -/** - * INCREMENT_EVENT_QUEUE_GET() - - * - * This macro will increment the controllers event queue index value and - * possibly toggle the event cycle bit if the event queue index wraps back to 0. - */ -#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \ - INCREMENT_QUEUE_GET(\ - (index), \ - (cycle), \ - (controller)->completion_event_entries, \ - SMU_CQGR_EVENT_CYCLE_BIT \ - ) - -static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) -{ - struct isci_host *ihost = scic_to_ihost(scic); - scic->power_control.timer = isci_timer_create(ihost, - scic, - scic_sds_controller_power_control_timer_handler); - - memset(scic->power_control.requesters, 0, - sizeof(scic->power_control.requesters)); - - scic->power_control.phys_waiting = 0; - scic->power_control.phys_granted_power = 0; -} - -int scic_controller_mem_init(struct scic_sds_controller *scic) -{ - struct device *dev = scic_to_dev(scic); - dma_addr_t dma_handle; - enum sci_status result; - - scic->completion_queue = dmam_alloc_coherent(dev, - scic->completion_queue_entries * sizeof(u32), - &dma_handle, GFP_KERNEL); - if (!scic->completion_queue) - return -ENOMEM; - - writel(lower_32_bits(dma_handle), - &scic->smu_registers->completion_queue_lower); - writel(upper_32_bits(dma_handle), - &scic->smu_registers->completion_queue_upper); - - scic->remote_node_context_table = dmam_alloc_coherent(dev, - scic->remote_node_entries * - sizeof(union scu_remote_node_context), - &dma_handle, GFP_KERNEL); - if (!scic->remote_node_context_table) - return -ENOMEM; - - writel(lower_32_bits(dma_handle), - &scic->smu_registers->remote_node_context_lower); - writel(upper_32_bits(dma_handle), - &scic->smu_registers->remote_node_context_upper); - - scic->task_context_table = dmam_alloc_coherent(dev, - scic->task_context_entries * - sizeof(struct scu_task_context), - &dma_handle, GFP_KERNEL); - if (!scic->task_context_table) - return -ENOMEM; - - writel(lower_32_bits(dma_handle), - &scic->smu_registers->host_task_table_lower); - writel(upper_32_bits(dma_handle), - &scic->smu_registers->host_task_table_upper); - - result = scic_sds_unsolicited_frame_control_construct(scic); - if (result) - return result; - - /* - * Inform the silicon as to the location of the UF headers and - * address table. - */ - writel(lower_32_bits(scic->uf_control.headers.physical_address), - &scic->scu_registers->sdma.uf_header_base_address_lower); - writel(upper_32_bits(scic->uf_control.headers.physical_address), - &scic->scu_registers->sdma.uf_header_base_address_upper); - - writel(lower_32_bits(scic->uf_control.address_table.physical_address), - &scic->scu_registers->sdma.uf_address_table_lower); - writel(upper_32_bits(scic->uf_control.address_table.physical_address), - &scic->scu_registers->sdma.uf_address_table_upper); - - return 0; -} - -/** - * This method initializes the task context data for the controller. - * @scic: - * - */ -static void -scic_sds_controller_assign_task_entries(struct scic_sds_controller *controller) -{ - u32 task_assignment; - - /* - * Assign all the TCs to function 0 - * TODO: Do we actually need to read this register to write it back? - */ - - task_assignment = - readl(&controller->smu_registers->task_context_assignment[0]); - - task_assignment |= (SMU_TCA_GEN_VAL(STARTING, 0)) | - (SMU_TCA_GEN_VAL(ENDING, controller->task_context_entries - 1)) | - (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE)); - - writel(task_assignment, - &controller->smu_registers->task_context_assignment[0]); - -} - -/** - * This method initializes the hardware completion queue. - * - * - */ -static void scic_sds_controller_initialize_completion_queue( - struct scic_sds_controller *scic) -{ - u32 index; - u32 completion_queue_control_value; - u32 completion_queue_get_value; - u32 completion_queue_put_value; - - scic->completion_queue_get = 0; - - completion_queue_control_value = ( - SMU_CQC_QUEUE_LIMIT_SET(scic->completion_queue_entries - 1) - | SMU_CQC_EVENT_LIMIT_SET(scic->completion_event_entries - 1) - ); - - writel(completion_queue_control_value, - &scic->smu_registers->completion_queue_control); - - - /* Set the completion queue get pointer and enable the queue */ - completion_queue_get_value = ( - (SMU_CQGR_GEN_VAL(POINTER, 0)) - | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0)) - | (SMU_CQGR_GEN_BIT(ENABLE)) - | (SMU_CQGR_GEN_BIT(EVENT_ENABLE)) - ); - - writel(completion_queue_get_value, - &scic->smu_registers->completion_queue_get); - - /* Set the completion queue put pointer */ - completion_queue_put_value = ( - (SMU_CQPR_GEN_VAL(POINTER, 0)) - | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0)) - ); - - writel(completion_queue_put_value, - &scic->smu_registers->completion_queue_put); - - /* Initialize the cycle bit of the completion queue entries */ - for (index = 0; index < scic->completion_queue_entries; index++) { - /* - * If get.cycle_bit != completion_queue.cycle_bit - * its not a valid completion queue entry - * so at system start all entries are invalid */ - scic->completion_queue[index] = 0x80000000; - } -} - -/** - * This method initializes the hardware unsolicited frame queue. - * - * - */ -static void scic_sds_controller_initialize_unsolicited_frame_queue( - struct scic_sds_controller *scic) -{ - u32 frame_queue_control_value; - u32 frame_queue_get_value; - u32 frame_queue_put_value; - - /* Write the queue size */ - frame_queue_control_value = - SCU_UFQC_GEN_VAL(QUEUE_SIZE, - scic->uf_control.address_table.count); - - writel(frame_queue_control_value, - &scic->scu_registers->sdma.unsolicited_frame_queue_control); - - /* Setup the get pointer for the unsolicited frame queue */ - frame_queue_get_value = ( - SCU_UFQGP_GEN_VAL(POINTER, 0) - | SCU_UFQGP_GEN_BIT(ENABLE_BIT) - ); - - writel(frame_queue_get_value, - &scic->scu_registers->sdma.unsolicited_frame_get_pointer); - /* Setup the put pointer for the unsolicited frame queue */ - frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0); - writel(frame_queue_put_value, - &scic->scu_registers->sdma.unsolicited_frame_put_pointer); -} - -/** - * This method enables the hardware port task scheduler. - * - * - */ -static void scic_sds_controller_enable_port_task_scheduler( - struct scic_sds_controller *scic) -{ - u32 port_task_scheduler_value; - - port_task_scheduler_value = - readl(&scic->scu_registers->peg0.ptsg.control); - port_task_scheduler_value |= - (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | - SCU_PTSGCR_GEN_BIT(PTSG_ENABLE)); - writel(port_task_scheduler_value, - &scic->scu_registers->peg0.ptsg.control); -} - -/** - * - * - * This macro is used to delay between writes to the AFE registers during AFE - * initialization. - */ -#define AFE_REGISTER_WRITE_DELAY 10 - -/* Initialize the AFE for this phy index. We need to read the AFE setup from - * the OEM parameters none - */ -static void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) -{ - const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; - u32 afe_status; - u32 phy_id; - - /* Clear DFX Status registers */ - writel(0x0081000f, &scic->scu_registers->afe.afe_dfx_master_control0); - udelay(AFE_REGISTER_WRITE_DELAY); - - if (is_b0()) { - /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement - * Timer, PM Stagger Timer */ - writel(0x0007BFFF, &scic->scu_registers->afe.afe_pmsn_master_control2); - udelay(AFE_REGISTER_WRITE_DELAY); - } - - /* Configure bias currents to normal */ - if (is_a0()) - writel(0x00005500, &scic->scu_registers->afe.afe_bias_control); - else if (is_a2()) - writel(0x00005A00, &scic->scu_registers->afe.afe_bias_control); - else if (is_b0()) - writel(0x00005F00, &scic->scu_registers->afe.afe_bias_control); - - udelay(AFE_REGISTER_WRITE_DELAY); - - /* Enable PLL */ - if (is_b0()) - writel(0x80040A08, &scic->scu_registers->afe.afe_pll_control0); - else - writel(0x80040908, &scic->scu_registers->afe.afe_pll_control0); - - udelay(AFE_REGISTER_WRITE_DELAY); - - /* Wait for the PLL to lock */ - do { - afe_status = readl(&scic->scu_registers->afe.afe_common_block_status); - udelay(AFE_REGISTER_WRITE_DELAY); - } while ((afe_status & 0x00001000) == 0); - - if (is_a0() || is_a2()) { - /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ - writel(0x7bcc96ad, &scic->scu_registers->afe.afe_pmsn_master_control0); - udelay(AFE_REGISTER_WRITE_DELAY); - } - - for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { - const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id]; - - if (is_b0()) { - /* Configure transmitter SSC parameters */ - writel(0x00030000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); - udelay(AFE_REGISTER_WRITE_DELAY); - } else { - /* - * All defaults, except the Receive Word Alignament/Comma Detect - * Enable....(0xe800) */ - writel(0x00004512, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); - udelay(AFE_REGISTER_WRITE_DELAY); - - writel(0x0050100F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1); - udelay(AFE_REGISTER_WRITE_DELAY); - } - - /* - * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) - * & increase TX int & ext bias 20%....(0xe85c) */ - if (is_a0()) - writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); - else if (is_a2()) - writel(0x000003F0, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); - else { - /* Power down TX and RX (PWRDNTX and PWRDNRX) */ - writel(0x000003d7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); - udelay(AFE_REGISTER_WRITE_DELAY); - - /* - * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) - * & increase TX int & ext bias 20%....(0xe85c) */ - writel(0x000003d4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); - } - udelay(AFE_REGISTER_WRITE_DELAY); - - if (is_a0() || is_a2()) { - /* Enable TX equalization (0xe824) */ - writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); - udelay(AFE_REGISTER_WRITE_DELAY); - } - - /* - * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On), - * RDD=0x0(RX Detect Enabled) ....(0xe800) */ - writel(0x00004100, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); - udelay(AFE_REGISTER_WRITE_DELAY); - - /* Leave DFE/FFE on */ - if (is_a0()) - writel(0x3F09983F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); - else if (is_a2()) - writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); - else { - writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); - udelay(AFE_REGISTER_WRITE_DELAY); - /* Enable TX equalization (0xe824) */ - writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); - } - udelay(AFE_REGISTER_WRITE_DELAY); - - writel(oem_phy->afe_tx_amp_control0, - &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0); - udelay(AFE_REGISTER_WRITE_DELAY); - - writel(oem_phy->afe_tx_amp_control1, - &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1); - udelay(AFE_REGISTER_WRITE_DELAY); - - writel(oem_phy->afe_tx_amp_control2, - &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2); - udelay(AFE_REGISTER_WRITE_DELAY); - - writel(oem_phy->afe_tx_amp_control3, - &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3); - udelay(AFE_REGISTER_WRITE_DELAY); - } - - /* Transfer control to the PEs */ - writel(0x00010f00, &scic->scu_registers->afe.afe_dfx_master_control0); - udelay(AFE_REGISTER_WRITE_DELAY); -} - -/* - * ****************************************************************************- - * * SCIC SDS Controller Internal Start/Stop Routines - * ****************************************************************************- */ - - -/** - * This method will attempt to transition into the ready state for the - * controller and indicate that the controller start operation has completed - * if all criteria are met. - * @scic: This parameter indicates the controller object for which - * to transition to ready. - * @status: This parameter indicates the status value to be pass into the call - * to scic_cb_controller_start_complete(). - * - * none. - */ -static void scic_sds_controller_transition_to_ready( - struct scic_sds_controller *scic, - enum sci_status status) -{ - struct isci_host *ihost = scic_to_ihost(scic); - - if (scic->state_machine.current_state_id == - SCI_BASE_CONTROLLER_STATE_STARTING) { - /* - * We move into the ready state, because some of the phys/ports - * may be up and operational. - */ - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_READY); - - isci_host_start_complete(ihost, status); - } -} - -static void scic_sds_controller_timeout_handler(void *_scic) -{ - struct scic_sds_controller *scic = _scic; - struct isci_host *ihost = scic_to_ihost(scic); - struct sci_base_state_machine *sm = &scic->state_machine; - - if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) - scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT); - else if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STOPPING) { - sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_FAILED); - isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); - } else /* / @todo Now what do we want to do in this case? */ - dev_err(scic_to_dev(scic), - "%s: Controller timer fired when controller was not " - "in a state being timed.\n", - __func__); -} - -static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) -{ - u32 index; - enum sci_status port_status; - enum sci_status status = SCI_SUCCESS; - struct isci_host *ihost = scic_to_ihost(scic); - - for (index = 0; index < scic->logical_port_entries; index++) { - struct scic_sds_port *sci_port = &ihost->ports[index].sci; - scic_sds_port_handler_t stop; - - stop = sci_port->state_handlers->stop_handler; - port_status = stop(sci_port); - - if ((port_status != SCI_SUCCESS) && - (port_status != SCI_FAILURE_INVALID_STATE)) { - status = SCI_FAILURE; - - dev_warn(scic_to_dev(scic), - "%s: Controller stop operation failed to " - "stop port %d because of status %d.\n", - __func__, - sci_port->logical_port_index, - port_status); - } - } - - return status; -} - -static inline void scic_sds_controller_phy_timer_start( - struct scic_sds_controller *scic) -{ - isci_timer_start(scic->phy_startup_timer, - SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT); - - scic->phy_startup_timer_pending = true; -} - -static void scic_sds_controller_phy_timer_stop(struct scic_sds_controller *scic) -{ - isci_timer_stop(scic->phy_startup_timer); - - scic->phy_startup_timer_pending = false; -} - -/** - * scic_sds_controller_start_next_phy - start phy - * @scic: controller - * - * If all the phys have been started, then attempt to transition the - * controller to the READY state and inform the user - * (scic_cb_controller_start_complete()). - */ -static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic) -{ - struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; - struct scic_sds_phy *sci_phy; - enum sci_status status; - - status = SCI_SUCCESS; - - if (scic->phy_startup_timer_pending) - return status; - - if (scic->next_phy_to_start >= SCI_MAX_PHYS) { - bool is_controller_start_complete = true; - u32 state; - u8 index; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - sci_phy = &ihost->phys[index].sci; - state = sci_phy->state_machine.current_state_id; - - if (!scic_sds_phy_get_port(sci_phy)) - continue; - - /* The controller start operation is complete iff: - * - all links have been given an opportunity to start - * - have no indication of a connected device - * - have an indication of a connected device and it has - * finished the link training process. - */ - if ((sci_phy->is_in_link_training == false && - state == SCI_BASE_PHY_STATE_INITIAL) || - (sci_phy->is_in_link_training == false && - state == SCI_BASE_PHY_STATE_STOPPED) || - (sci_phy->is_in_link_training == true && - state == SCI_BASE_PHY_STATE_STARTING)) { - is_controller_start_complete = false; - break; - } - } - - /* - * The controller has successfully finished the start process. - * Inform the SCI Core user and transition to the READY state. */ - if (is_controller_start_complete == true) { - scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS); - scic_sds_controller_phy_timer_stop(scic); - } - } else { - sci_phy = &ihost->phys[scic->next_phy_to_start].sci; - - if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { - if (scic_sds_phy_get_port(sci_phy) == NULL) { - scic->next_phy_to_start++; - - /* Caution recursion ahead be forwarned - * - * The PHY was never added to a PORT in MPC mode - * so start the next phy in sequence This phy - * will never go link up and will not draw power - * the OEM parameters either configured the phy - * incorrectly for the PORT or it was never - * assigned to a PORT - */ - return scic_sds_controller_start_next_phy(scic); - } - } - - status = scic_sds_phy_start(sci_phy); - - if (status == SCI_SUCCESS) { - scic_sds_controller_phy_timer_start(scic); - } else { - dev_warn(scic_to_dev(scic), - "%s: Controller stop operation failed " - "to stop phy %d because of status " - "%d.\n", - __func__, - ihost->phys[scic->next_phy_to_start].sci.phy_index, - status); - } - - scic->next_phy_to_start++; - } - - return status; -} - -static void scic_sds_controller_phy_startup_timeout_handler(void *_scic) -{ - struct scic_sds_controller *scic = _scic; - enum sci_status status; - - scic->phy_startup_timer_pending = false; - status = SCI_FAILURE; - while (status != SCI_SUCCESS) - status = scic_sds_controller_start_next_phy(scic); -} - -static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic) -{ - struct isci_host *ihost = scic_to_ihost(scic); - - scic->phy_startup_timer = isci_timer_create(ihost, - scic, - scic_sds_controller_phy_startup_timeout_handler); - - if (scic->phy_startup_timer == NULL) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - else { - scic->next_phy_to_start = 0; - scic->phy_startup_timer_pending = false; - } - - return SCI_SUCCESS; -} - -static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller *scic) -{ - u32 index; - enum sci_status status; - enum sci_status phy_status; - struct isci_host *ihost = scic_to_ihost(scic); - - status = SCI_SUCCESS; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - phy_status = scic_sds_phy_stop(&ihost->phys[index].sci); - - if (phy_status != SCI_SUCCESS && - phy_status != SCI_FAILURE_INVALID_STATE) { - status = SCI_FAILURE; - - dev_warn(scic_to_dev(scic), - "%s: Controller stop operation failed to stop " - "phy %d because of status %d.\n", - __func__, - ihost->phys[index].sci.phy_index, phy_status); - } - } - - return status; -} - -static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controller *scic) -{ - u32 index; - enum sci_status status; - enum sci_status device_status; - - status = SCI_SUCCESS; - - for (index = 0; index < scic->remote_node_entries; index++) { - if (scic->device_table[index] != NULL) { - /* / @todo What timeout value do we want to provide to this request? */ - device_status = scic_remote_device_stop(scic->device_table[index], 0); - - if ((device_status != SCI_SUCCESS) && - (device_status != SCI_FAILURE_INVALID_STATE)) { - dev_warn(scic_to_dev(scic), - "%s: Controller stop operation failed " - "to stop device 0x%p because of " - "status %d.\n", - __func__, - scic->device_table[index], device_status); - } - } - } - - return status; -} - -static void scic_sds_controller_power_control_timer_start(struct scic_sds_controller *scic) -{ - isci_timer_start(scic->power_control.timer, - SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); - - scic->power_control.timer_started = true; -} - -static void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic) -{ - if (scic->power_control.timer_started) { - isci_timer_stop(scic->power_control.timer); - scic->power_control.timer_started = false; - } -} - -static void scic_sds_controller_power_control_timer_restart(struct scic_sds_controller *scic) -{ - scic_sds_controller_power_control_timer_stop(scic); - scic_sds_controller_power_control_timer_start(scic); -} - -static void scic_sds_controller_power_control_timer_handler( - void *controller) -{ - struct scic_sds_controller *scic; - - scic = (struct scic_sds_controller *)controller; - - scic->power_control.phys_granted_power = 0; - - if (scic->power_control.phys_waiting == 0) { - scic->power_control.timer_started = false; - } else { - struct scic_sds_phy *sci_phy = NULL; - u8 i; - - for (i = 0; - (i < SCI_MAX_PHYS) - && (scic->power_control.phys_waiting != 0); - i++) { - if (scic->power_control.requesters[i] != NULL) { - if (scic->power_control.phys_granted_power < - scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { - sci_phy = scic->power_control.requesters[i]; - scic->power_control.requesters[i] = NULL; - scic->power_control.phys_waiting--; - scic->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(sci_phy); - } else { - break; - } - } - } - - /* - * It doesn't matter if the power list is empty, we need to start the - * timer in case another phy becomes ready. - */ - scic_sds_controller_power_control_timer_start(scic); - } -} - -/** - * This method inserts the phy in the stagger spinup control queue. - * @scic: - * - * - */ -void scic_sds_controller_power_control_queue_insert( - struct scic_sds_controller *scic, - struct scic_sds_phy *sci_phy) -{ - BUG_ON(sci_phy == NULL); - - if (scic->power_control.phys_granted_power < - scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { - scic->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(sci_phy); - - /* - * stop and start the power_control timer. When the timer fires, the - * no_of_phys_granted_power will be set to 0 - */ - scic_sds_controller_power_control_timer_restart(scic); - } else { - /* Add the phy in the waiting list */ - scic->power_control.requesters[sci_phy->phy_index] = sci_phy; - scic->power_control.phys_waiting++; - } -} - -/** - * This method removes the phy from the stagger spinup control queue. - * @scic: - * - * - */ -void scic_sds_controller_power_control_queue_remove( - struct scic_sds_controller *scic, - struct scic_sds_phy *sci_phy) -{ - BUG_ON(sci_phy == NULL); - - if (scic->power_control.requesters[sci_phy->phy_index] != NULL) { - scic->power_control.phys_waiting--; - } - - scic->power_control.requesters[sci_phy->phy_index] = NULL; -} - -/* - * ****************************************************************************- - * * SCIC SDS Controller Completion Routines - * ****************************************************************************- */ - -/** - * This method returns a true value if the completion queue has entries that - * can be processed - * @scic: - * - * bool true if the completion queue has entries to process false if the - * completion queue has no entries to process - */ -static bool scic_sds_controller_completion_queue_has_entries( - struct scic_sds_controller *scic) -{ - u32 get_value = scic->completion_queue_get; - u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK; - - if (NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) == - COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index])) - return true; - - return false; -} - -/** - * This method processes a task completion notification. This is called from - * within the controller completion handler. - * @scic: - * @completion_entry: - * - */ -static void scic_sds_controller_task_completion( - struct scic_sds_controller *scic, - u32 completion_entry) -{ - u32 index; - struct scic_sds_request *io_request; - - index = SCU_GET_COMPLETION_INDEX(completion_entry); - io_request = scic->io_request_table[index]; - - /* Make sure that we really want to process this IO request */ - if ( - (io_request != NULL) - && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) - && ( - scic_sds_io_tag_get_sequence(io_request->io_tag) - == scic->io_request_sequence[index] - ) - ) { - /* Yep this is a valid io request pass it along to the io request handler */ - scic_sds_io_request_tc_completion(io_request, completion_entry); - } -} - -/** - * This method processes an SDMA completion event. This is called from within - * the controller completion handler. - * @scic: - * @completion_entry: - * - */ -static void scic_sds_controller_sdma_completion( - struct scic_sds_controller *scic, - u32 completion_entry) -{ - u32 index; - struct scic_sds_request *io_request; - struct scic_sds_remote_device *device; - - index = SCU_GET_COMPLETION_INDEX(completion_entry); - - switch (scu_get_command_request_type(completion_entry)) { - case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: - case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: - io_request = scic->io_request_table[index]; - dev_warn(scic_to_dev(scic), - "%s: SCIC SDS Completion type SDMA %x for io request " - "%p\n", - __func__, - completion_entry, - io_request); - /* @todo For a post TC operation we need to fail the IO - * request - */ - break; - - case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC: - case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC: - case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: - device = scic->device_table[index]; - dev_warn(scic_to_dev(scic), - "%s: SCIC SDS Completion type SDMA %x for remote " - "device %p\n", - __func__, - completion_entry, - device); - /* @todo For a port RNC operation we need to fail the - * device - */ - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: SCIC SDS Completion unknown SDMA completion " - "type %x\n", - __func__, - completion_entry); - break; - - } -} - -static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *scic, - u32 completion_entry) -{ - u32 index; - u32 frame_index; - - struct isci_host *ihost = scic_to_ihost(scic); - struct scu_unsolicited_frame_header *frame_header; - struct scic_sds_phy *phy; - struct scic_sds_remote_device *device; - - enum sci_status result = SCI_FAILURE; - - frame_index = SCU_GET_FRAME_INDEX(completion_entry); - - frame_header = scic->uf_control.buffers.array[frame_index].header; - scic->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE; - - if (SCU_GET_FRAME_ERROR(completion_entry)) { - /* - * / @todo If the IAF frame or SIGNATURE FIS frame has an error will - * / this cause a problem? We expect the phy initialization will - * / fail if there is an error in the frame. */ - scic_sds_controller_release_frame(scic, frame_index); - return; - } - - if (frame_header->is_address_frame) { - index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &ihost->phys[index].sci; - result = scic_sds_phy_frame_handler(phy, frame_index); - } else { - - index = SCU_GET_COMPLETION_INDEX(completion_entry); - - if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - /* - * This is a signature fis or a frame from a direct attached SATA - * device that has not yet been created. In either case forwared - * the frame to the PE and let it take care of the frame data. */ - index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &ihost->phys[index].sci; - result = scic_sds_phy_frame_handler(phy, frame_index); - } else { - if (index < scic->remote_node_entries) - device = scic->device_table[index]; - else - device = NULL; - - if (device != NULL) - result = scic_sds_remote_device_frame_handler(device, frame_index); - else - scic_sds_controller_release_frame(scic, frame_index); - } - } - - if (result != SCI_SUCCESS) { - /* - * / @todo Is there any reason to report some additional error message - * / when we get this failure notifiction? */ - } -} - -static void scic_sds_controller_event_completion(struct scic_sds_controller *scic, - u32 completion_entry) -{ - struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_request *io_request; - struct scic_sds_remote_device *device; - struct scic_sds_phy *phy; - u32 index; - - index = SCU_GET_COMPLETION_INDEX(completion_entry); - - switch (scu_get_event_type(completion_entry)) { - case SCU_EVENT_TYPE_SMU_COMMAND_ERROR: - /* / @todo The driver did something wrong and we need to fix the condtion. */ - dev_err(scic_to_dev(scic), - "%s: SCIC Controller 0x%p received SMU command error " - "0x%x\n", - __func__, - scic, - completion_entry); - break; - - case SCU_EVENT_TYPE_SMU_PCQ_ERROR: - case SCU_EVENT_TYPE_SMU_ERROR: - case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR: - /* - * / @todo This is a hardware failure and its likely that we want to - * / reset the controller. */ - dev_err(scic_to_dev(scic), - "%s: SCIC Controller 0x%p received fatal controller " - "event 0x%x\n", - __func__, - scic, - completion_entry); - break; - - case SCU_EVENT_TYPE_TRANSPORT_ERROR: - io_request = scic->io_request_table[index]; - scic_sds_io_request_event_handler(io_request, completion_entry); - break; - - case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: - switch (scu_get_event_specifier(completion_entry)) { - case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: - case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: - io_request = scic->io_request_table[index]; - if (io_request != NULL) - scic_sds_io_request_event_handler(io_request, completion_entry); - else - dev_warn(scic_to_dev(scic), - "%s: SCIC Controller 0x%p received " - "event 0x%x for io request object " - "that doesnt exist.\n", - __func__, - scic, - completion_entry); - - break; - - case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: - device = scic->device_table[index]; - if (device != NULL) - scic_sds_remote_device_event_handler(device, completion_entry); - else - dev_warn(scic_to_dev(scic), - "%s: SCIC Controller 0x%p received " - "event 0x%x for remote device object " - "that doesnt exist.\n", - __func__, - scic, - completion_entry); - - break; - } - break; - - case SCU_EVENT_TYPE_BROADCAST_CHANGE: - /* - * direct the broadcast change event to the phy first and then let - * the phy redirect the broadcast change to the port object */ - case SCU_EVENT_TYPE_ERR_CNT_EVENT: - /* - * direct error counter event to the phy object since that is where - * we get the event notification. This is a type 4 event. */ - case SCU_EVENT_TYPE_OSSP_EVENT: - index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &ihost->phys[index].sci; - scic_sds_phy_event_handler(phy, completion_entry); - break; - - case SCU_EVENT_TYPE_RNC_SUSPEND_TX: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - case SCU_EVENT_TYPE_RNC_OPS_MISC: - if (index < scic->remote_node_entries) { - device = scic->device_table[index]; - - if (device != NULL) - scic_sds_remote_device_event_handler(device, completion_entry); - } else - dev_err(scic_to_dev(scic), - "%s: SCIC Controller 0x%p received event 0x%x " - "for remote device object 0x%0x that doesnt " - "exist.\n", - __func__, - scic, - completion_entry, - index); - - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: SCIC Controller received unknown event code %x\n", - __func__, - completion_entry); - break; - } -} - -/** - * This method is a private routine for processing the completion queue entries. - * @scic: - * - */ -static void scic_sds_controller_process_completions( - struct scic_sds_controller *scic) -{ - u32 completion_count = 0; - u32 completion_entry; - u32 get_index; - u32 get_cycle; - u32 event_index; - u32 event_cycle; - - dev_dbg(scic_to_dev(scic), - "%s: completion queue begining get:0x%08x\n", - __func__, - scic->completion_queue_get); - - /* Get the component parts of the completion queue */ - get_index = NORMALIZE_GET_POINTER(scic->completion_queue_get); - get_cycle = SMU_CQGR_CYCLE_BIT & scic->completion_queue_get; - - event_index = NORMALIZE_EVENT_POINTER(scic->completion_queue_get); - event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & scic->completion_queue_get; - - while ( - NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) - == COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index]) - ) { - completion_count++; - - completion_entry = scic->completion_queue[get_index]; - INCREMENT_COMPLETION_QUEUE_GET(scic, get_index, get_cycle); - - dev_dbg(scic_to_dev(scic), - "%s: completion queue entry:0x%08x\n", - __func__, - completion_entry); - - switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { - case SCU_COMPLETION_TYPE_TASK: - scic_sds_controller_task_completion(scic, completion_entry); - break; - - case SCU_COMPLETION_TYPE_SDMA: - scic_sds_controller_sdma_completion(scic, completion_entry); - break; - - case SCU_COMPLETION_TYPE_UFI: - scic_sds_controller_unsolicited_frame(scic, completion_entry); - break; - - case SCU_COMPLETION_TYPE_EVENT: - INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle); - scic_sds_controller_event_completion(scic, completion_entry); - break; - - case SCU_COMPLETION_TYPE_NOTIFY: - /* - * Presently we do the same thing with a notify event that we do with the - * other event codes. */ - INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle); - scic_sds_controller_event_completion(scic, completion_entry); - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: SCIC Controller received unknown " - "completion type %x\n", - __func__, - completion_entry); - break; - } - } - - /* Update the get register if we completed one or more entries */ - if (completion_count > 0) { - scic->completion_queue_get = - SMU_CQGR_GEN_BIT(ENABLE) | - SMU_CQGR_GEN_BIT(EVENT_ENABLE) | - event_cycle | - SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) | - get_cycle | - SMU_CQGR_GEN_VAL(POINTER, get_index); - - writel(scic->completion_queue_get, - &scic->smu_registers->completion_queue_get); - - } - - dev_dbg(scic_to_dev(scic), - "%s: completion queue ending get:0x%08x\n", - __func__, - scic->completion_queue_get); - -} - -bool scic_sds_controller_isr(struct scic_sds_controller *scic) -{ - if (scic_sds_controller_completion_queue_has_entries(scic)) { - return true; - } else { - /* - * we have a spurious interrupt it could be that we have already - * emptied the completion queue from a previous interrupt */ - writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); - - /* - * There is a race in the hardware that could cause us not to be notified - * of an interrupt completion if we do not take this step. We will mask - * then unmask the interrupts so if there is another interrupt pending - * the clearing of the interrupt source we get the next interrupt message. */ - writel(0xFF000000, &scic->smu_registers->interrupt_mask); - writel(0, &scic->smu_registers->interrupt_mask); - } - - return false; -} - -void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) -{ - /* Empty out the completion queue */ - if (scic_sds_controller_completion_queue_has_entries(scic)) - scic_sds_controller_process_completions(scic); - - /* Clear the interrupt and enable all interrupts again */ - writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); - /* Could we write the value of SMU_ISR_COMPLETION? */ - writel(0xFF000000, &scic->smu_registers->interrupt_mask); - writel(0, &scic->smu_registers->interrupt_mask); -} - -bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) -{ - u32 interrupt_status; - - interrupt_status = - readl(&scic->smu_registers->interrupt_status); - interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); - - if (interrupt_status != 0) { - /* - * There is an error interrupt pending so let it through and handle - * in the callback */ - return true; - } - - /* - * There is a race in the hardware that could cause us not to be notified - * of an interrupt completion if we do not take this step. We will mask - * then unmask the error interrupts so if there was another interrupt - * pending we will be notified. - * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */ - writel(0xff, &scic->smu_registers->interrupt_mask); - writel(0, &scic->smu_registers->interrupt_mask); - - return false; -} - -void scic_sds_controller_error_handler(struct scic_sds_controller *scic) -{ - u32 interrupt_status; - - interrupt_status = - readl(&scic->smu_registers->interrupt_status); - - if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && - scic_sds_controller_completion_queue_has_entries(scic)) { - - scic_sds_controller_process_completions(scic); - writel(SMU_ISR_QUEUE_SUSPEND, &scic->smu_registers->interrupt_status); - } else { - dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, - interrupt_status); - - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_FAILED); - - return; - } - - /* If we dont process any completions I am not sure that we want to do this. - * We are in the middle of a hardware fault and should probably be reset. - */ - writel(0, &scic->smu_registers->interrupt_mask); -} - - - - -void scic_sds_controller_link_up(struct scic_sds_controller *scic, - struct scic_sds_port *port, struct scic_sds_phy *phy) -{ - switch (scic->state_machine.current_state_id) { - case SCI_BASE_CONTROLLER_STATE_STARTING: - scic_sds_controller_phy_timer_stop(scic); - scic->port_agent.link_up_handler(scic, &scic->port_agent, - port, phy); - scic_sds_controller_start_next_phy(scic); - break; - case SCI_BASE_CONTROLLER_STATE_READY: - scic->port_agent.link_up_handler(scic, &scic->port_agent, - port, phy); - break; - default: - dev_dbg(scic_to_dev(scic), - "%s: SCIC Controller linkup event from phy %d in " - "unexpected state %d\n", __func__, phy->phy_index, - scic->state_machine.current_state_id); - } -} - -void scic_sds_controller_link_down(struct scic_sds_controller *scic, - struct scic_sds_port *port, struct scic_sds_phy *phy) -{ - switch (scic->state_machine.current_state_id) { - case SCI_BASE_CONTROLLER_STATE_STARTING: - case SCI_BASE_CONTROLLER_STATE_READY: - scic->port_agent.link_down_handler(scic, &scic->port_agent, - port, phy); - break; - default: - dev_dbg(scic_to_dev(scic), - "%s: SCIC Controller linkdown event from phy %d in " - "unexpected state %d\n", - __func__, - phy->phy_index, - scic->state_machine.current_state_id); - } -} - -/** - * This is a helper method to determine if any remote devices on this - * controller are still in the stopping state. - * - */ -static bool scic_sds_controller_has_remote_devices_stopping( - struct scic_sds_controller *controller) -{ - u32 index; - - for (index = 0; index < controller->remote_node_entries; index++) { - if ((controller->device_table[index] != NULL) && - (controller->device_table[index]->state_machine.current_state_id - == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING)) - return true; - } - - return false; -} - -/** - * This method is called by the remote device to inform the controller - * object that the remote device has stopped. - */ -void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev) -{ - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_STOPPING) { - dev_dbg(scic_to_dev(scic), - "SCIC Controller 0x%p remote device stopped event " - "from device 0x%p in unexpected state %d\n", - scic, sci_dev, - scic->state_machine.current_state_id); - return; - } - - if (!scic_sds_controller_has_remote_devices_stopping(scic)) { - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_STOPPED); - } -} - -/** - * This method will write to the SCU PCP register the request value. The method - * is used to suspend/resume ports, devices, and phys. - * @scic: - * - * - */ -void scic_sds_controller_post_request( - struct scic_sds_controller *scic, - u32 request) -{ - dev_dbg(scic_to_dev(scic), - "%s: SCIC Controller 0x%p post request 0x%08x\n", - __func__, - scic, - request); - - writel(request, &scic->smu_registers->post_context_port); -} - -/** - * This method will copy the soft copy of the task context into the physical - * memory accessible by the controller. - * @scic: This parameter specifies the controller for which to copy - * the task context. - * @sci_req: This parameter specifies the request for which the task - * context is being copied. - * - * After this call is made the SCIC_SDS_IO_REQUEST object will always point to - * the physical memory version of the task context. Thus, all subsequent - * updates to the task context are performed in the TC table (i.e. DMAable - * memory). none - */ -void scic_sds_controller_copy_task_context( - struct scic_sds_controller *scic, - struct scic_sds_request *sci_req) -{ - struct scu_task_context *task_context_buffer; - - task_context_buffer = scic_sds_controller_get_task_context_buffer( - scic, sci_req->io_tag); - - memcpy(task_context_buffer, - sci_req->task_context_buffer, - offsetof(struct scu_task_context, sgl_snapshot_ac)); - - /* - * Now that the soft copy of the TC has been copied into the TC - * table accessible by the silicon. Thus, any further changes to - * the TC (e.g. TC termination) occur in the appropriate location. */ - sci_req->task_context_buffer = task_context_buffer; -} - -/** - * This method returns the task context buffer for the given io tag. - * @scic: - * @io_tag: - * - * struct scu_task_context* - */ -struct scu_task_context *scic_sds_controller_get_task_context_buffer( - struct scic_sds_controller *scic, - u16 io_tag - ) { - u16 task_index = scic_sds_io_tag_get_index(io_tag); - - if (task_index < scic->task_context_entries) { - return &scic->task_context_table[task_index]; - } - - return NULL; -} - -struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, - u16 io_tag) -{ - u16 task_index; - u16 task_sequence; - - task_index = scic_sds_io_tag_get_index(io_tag); - - if (task_index < scic->task_context_entries) { - if (scic->io_request_table[task_index] != NULL) { - task_sequence = scic_sds_io_tag_get_sequence(io_tag); - - if (task_sequence == scic->io_request_sequence[task_index]) { - return scic->io_request_table[task_index]; - } - } - } - - return NULL; -} - -/** - * This method allocates remote node index and the reserves the remote node - * context space for use. This method can fail if there are no more remote - * node index available. - * @scic: This is the controller object which contains the set of - * free remote node ids - * @sci_dev: This is the device object which is requesting the a remote node - * id - * @node_id: This is the remote node id that is assinged to the device if one - * is available - * - * enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote - * node index available. - */ -enum sci_status scic_sds_controller_allocate_remote_node_context( - struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - u16 *node_id) -{ - u16 node_index; - u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev); - - node_index = scic_sds_remote_node_table_allocate_remote_node( - &scic->available_remote_nodes, remote_node_count - ); - - if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - scic->device_table[node_index] = sci_dev; - - *node_id = node_index; - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INSUFFICIENT_RESOURCES; -} - -/** - * This method frees the remote node index back to the available pool. Once - * this is done the remote node context buffer is no longer valid and can - * not be used. - * @scic: - * @sci_dev: - * @node_id: - * - */ -void scic_sds_controller_free_remote_node_context( - struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - u16 node_id) -{ - u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev); - - if (scic->device_table[node_id] == sci_dev) { - scic->device_table[node_id] = NULL; - - scic_sds_remote_node_table_release_remote_node_index( - &scic->available_remote_nodes, remote_node_count, node_id - ); - } -} - -/** - * This method returns the union scu_remote_node_context for the specified remote - * node id. - * @scic: - * @node_id: - * - * union scu_remote_node_context* - */ -union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( - struct scic_sds_controller *scic, - u16 node_id - ) { - if ( - (node_id < scic->remote_node_entries) - && (scic->device_table[node_id] != NULL) - ) { - return &scic->remote_node_context_table[node_id]; - } - - return NULL; -} - -/** - * - * @resposne_buffer: This is the buffer into which the D2H register FIS will be - * constructed. - * @frame_header: This is the frame header returned by the hardware. - * @frame_buffer: This is the frame buffer returned by the hardware. - * - * This method will combind the frame header and frame buffer to create a SATA - * D2H register FIS none - */ -void scic_sds_controller_copy_sata_response( - void *response_buffer, - void *frame_header, - void *frame_buffer) -{ - memcpy(response_buffer, frame_header, sizeof(u32)); - - memcpy(response_buffer + sizeof(u32), - frame_buffer, - sizeof(struct dev_to_host_fis) - sizeof(u32)); -} - -/** - * This method releases the frame once this is done the frame is available for - * re-use by the hardware. The data contained in the frame header and frame - * buffer is no longer valid. The UF queue get pointer is only updated if UF - * control indicates this is appropriate. - * @scic: - * @frame_index: - * - */ -void scic_sds_controller_release_frame( - struct scic_sds_controller *scic, - u32 frame_index) -{ - if (scic_sds_unsolicited_frame_control_release_frame( - &scic->uf_control, frame_index) == true) - writel(scic->uf_control.get, - &scic->scu_registers->sdma.unsolicited_frame_get_pointer); -} - -/** - * This method sets user parameters and OEM parameters to default values. - * Users can override these values utilizing the scic_user_parameters_set() - * and scic_oem_parameters_set() methods. - * @scic: This parameter specifies the controller for which to set the - * configuration parameters to their default values. - * - */ -static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) -{ - struct isci_host *ihost = scic_to_ihost(scic); - u16 index; - - /* Default to APC mode. */ - scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; - - /* Default to APC mode. */ - scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1; - - /* Default to no SSC operation. */ - scic->oem_parameters.sds1.controller.do_enable_ssc = false; - - /* Initialize all of the port parameter information to narrow ports. */ - for (index = 0; index < SCI_MAX_PORTS; index++) { - scic->oem_parameters.sds1.ports[index].phy_mask = 0; - } - - /* Initialize all of the phy parameter information. */ - for (index = 0; index < SCI_MAX_PHYS; index++) { - /* Default to 6G (i.e. Gen 3) for now. */ - scic->user_parameters.sds1.phys[index].max_speed_generation = 3; - - /* the frequencies cannot be 0 */ - scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f; - scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff; - scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; - - /* - * Previous Vitesse based expanders had a arbitration issue that - * is worked around by having the upper 32-bits of SAS address - * with a value greater then the Vitesse company identifier. - * Hence, usage of 0x5FCFFFFF. */ - scic->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id; - scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF; - } - - scic->user_parameters.sds1.stp_inactivity_timeout = 5; - scic->user_parameters.sds1.ssp_inactivity_timeout = 5; - scic->user_parameters.sds1.stp_max_occupancy_timeout = 5; - scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20; - scic->user_parameters.sds1.no_outbound_task_timeout = 20; -} - -/** - * scic_controller_get_suggested_start_timeout() - This method returns the - * suggested scic_controller_start() timeout amount. The user is free to - * use any timeout value, but this method provides the suggested minimum - * start timeout value. The returned value is based upon empirical - * information determined as a result of interoperability testing. - * @controller: the handle to the controller object for which to return the - * suggested start timeout. - * - * This method returns the number of milliseconds for the suggested start - * operation timeout. - */ -u32 scic_controller_get_suggested_start_timeout( - struct scic_sds_controller *sc) -{ - /* Validate the user supplied parameters. */ - if (sc == NULL) - return 0; - - /* - * The suggested minimum timeout value for a controller start operation: - * - * Signature FIS Timeout - * + Phy Start Timeout - * + Number of Phy Spin Up Intervals - * --------------------------------- - * Number of milliseconds for the controller start operation. - * - * NOTE: The number of phy spin up intervals will be equivalent - * to the number of phys divided by the number phys allowed - * per interval - 1 (once OEM parameters are supported). - * Currently we assume only 1 phy per interval. */ - - return SCIC_SDS_SIGNATURE_FIS_TIMEOUT - + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT - + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); -} - -/** - * scic_controller_stop() - This method will stop an individual controller - * object.This method will invoke the associated user callback upon - * completion. The completion callback is called when the following - * conditions are met: -# the method return status is SCI_SUCCESS. -# the - * controller has been quiesced. This method will ensure that all IO - * requests are quiesced, phys are stopped, and all additional operation by - * the hardware is halted. - * @controller: the handle to the controller object to stop. - * @timeout: This parameter specifies the number of milliseconds in which the - * stop operation should complete. - * - * The controller must be in the STARTED or STOPPED state. Indicate if the - * controller stop method succeeded or failed in some way. SCI_SUCCESS if the - * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the - * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the - * controller is not either in the STARTED or STOPPED states. - */ -enum sci_status scic_controller_stop( - struct scic_sds_controller *scic, - u32 timeout) -{ - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { - dev_warn(scic_to_dev(scic), - "SCIC Controller stop operation requested in " - "invalid state\n"); - return SCI_FAILURE_INVALID_STATE; - } - - isci_timer_start(scic->timeout_timer, timeout); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_STOPPING); - return SCI_SUCCESS; -} - -/** - * scic_controller_reset() - This method will reset the supplied core - * controller regardless of the state of said controller. This operation is - * considered destructive. In other words, all current operations are wiped - * out. No IO completions for outstanding devices occur. Outstanding IO - * requests are not aborted or completed at the actual remote device. - * @controller: the handle to the controller object to reset. - * - * Indicate if the controller reset method succeeded or failed in some way. - * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if - * the controller reset operation is unable to complete. - */ -enum sci_status scic_controller_reset( - struct scic_sds_controller *scic) -{ - switch (scic->state_machine.current_state_id) { - case SCI_BASE_CONTROLLER_STATE_RESET: - case SCI_BASE_CONTROLLER_STATE_READY: - case SCI_BASE_CONTROLLER_STATE_STOPPED: - case SCI_BASE_CONTROLLER_STATE_FAILED: - /* - * The reset operation is not a graceful cleanup, just - * perform the state transition. - */ - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_RESETTING); - return SCI_SUCCESS; - default: - dev_warn(scic_to_dev(scic), - "SCIC Controller reset operation requested in " - "invalid state\n"); - return SCI_FAILURE_INVALID_STATE; - } -} - -/** - * scic_controller_start_io() - This method is called by the SCI user to - * send/start an IO request. If the method invocation is successful, then - * the IO request has been queued to the hardware for processing. - * @controller: the handle to the controller object for which to start an IO - * request. - * @remote_device: the handle to the remote device object for which to start an - * IO request. - * @io_request: the handle to the io request object to start. - * @io_tag: This parameter specifies a previously allocated IO tag that the - * user desires to be utilized for this request. This parameter is optional. - * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value - * for this parameter. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a - * result, it is expected the user will have set the NCQ tag field in the host - * to device register FIS prior to calling this method. There is also a - * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking - * the scic_controller_start_io() method. scic_controller_allocate_tag() for - * more information on allocating a tag. Indicate if the controller - * successfully started the IO request. SCI_SUCCESS if the IO request was - * successfully started. Determine the failure situations and return values. - */ -enum sci_status scic_controller_start_io( - struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, - struct scic_sds_request *req, - u16 io_tag) -{ - enum sci_status status; - - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { - dev_warn(scic_to_dev(scic), "invalid state to start I/O"); - return SCI_FAILURE_INVALID_STATE; - } - - status = scic_sds_remote_device_start_io(scic, rdev, req); - if (status != SCI_SUCCESS) - return status; - - scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; - scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); - return SCI_SUCCESS; -} - -/** - * scic_controller_terminate_request() - This method is called by the SCI Core - * user to terminate an ongoing (i.e. started) core IO request. This does - * not abort the IO request at the target, but rather removes the IO request - * from the host controller. - * @controller: the handle to the controller object for which to terminate a - * request. - * @remote_device: the handle to the remote device object for which to - * terminate a request. - * @request: the handle to the io or task management request object to - * terminate. - * - * Indicate if the controller successfully began the terminate process for the - * IO request. SCI_SUCCESS if the terminate process was successfully started - * for the request. Determine the failure situations and return values. - */ -enum sci_status scic_controller_terminate_request( - struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, - struct scic_sds_request *req) -{ - enum sci_status status; - - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { - dev_warn(scic_to_dev(scic), - "invalid state to terminate request\n"); - return SCI_FAILURE_INVALID_STATE; - } - - status = scic_sds_io_request_terminate(req); - if (status != SCI_SUCCESS) - return status; - - /* - * Utilize the original post context command and or in the POST_TC_ABORT - * request sub-type. - */ - scic_sds_controller_post_request(scic, - scic_sds_request_get_post_context(req) | - SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); - return SCI_SUCCESS; -} - -/** - * scic_controller_complete_io() - This method will perform core specific - * completion operations for an IO request. After this method is invoked, - * the user should consider the IO request as invalid until it is properly - * reused (i.e. re-constructed). - * @controller: The handle to the controller object for which to complete the - * IO request. - * @remote_device: The handle to the remote device object for which to complete - * the IO request. - * @io_request: the handle to the io request object to complete. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI - * Core user, using the scic_controller_allocate_io_tag() method, then it is - * the responsibility of the caller to invoke the scic_controller_free_io_tag() - * method to free the tag (i.e. this method will not free the IO tag). Indicate - * if the controller successfully completed the IO request. SCI_SUCCESS if the - * completion process was successful. - */ -enum sci_status scic_controller_complete_io( - struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, - struct scic_sds_request *request) -{ - enum sci_status status; - u16 index; - - switch (scic->state_machine.current_state_id) { - case SCI_BASE_CONTROLLER_STATE_STOPPING: - /* XXX: Implement this function */ - return SCI_FAILURE; - case SCI_BASE_CONTROLLER_STATE_READY: - status = scic_sds_remote_device_complete_io(scic, rdev, request); - if (status != SCI_SUCCESS) - return status; - - index = scic_sds_io_tag_get_index(request->io_tag); - scic->io_request_table[index] = NULL; - return SCI_SUCCESS; - default: - dev_warn(scic_to_dev(scic), "invalid state to complete I/O"); - return SCI_FAILURE_INVALID_STATE; - } - -} - -enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) -{ - struct scic_sds_controller *scic = sci_req->owning_controller; - - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { - dev_warn(scic_to_dev(scic), "invalid state to continue I/O"); - return SCI_FAILURE_INVALID_STATE; - } - - scic->io_request_table[scic_sds_io_tag_get_index(sci_req->io_tag)] = sci_req; - scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req)); - return SCI_SUCCESS; -} - -/** - * scic_controller_start_task() - This method is called by the SCIC user to - * send/start a framework task management request. - * @controller: the handle to the controller object for which to start the task - * management request. - * @remote_device: the handle to the remote device object for which to start - * the task management request. - * @task_request: the handle to the task request object to start. - * @io_tag: This parameter specifies a previously allocated IO tag that the - * user desires to be utilized for this request. Note this not the io_tag - * of the request being managed. It is to be utilized for the task request - * itself. This parameter is optional. The user is allowed to supply - * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - The user must synchronize this task with completion - * queue processing. If they are not synchronized then it is possible for the - * io requests that are being managed by the task request can complete before - * starting the task request. scic_controller_allocate_tag() for more - * information on allocating a tag. Indicate if the controller successfully - * started the IO request. SCI_TASK_SUCCESS if the task request was - * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is - * returned if there is/are task(s) outstanding that require termination or - * completion before this request can succeed. - */ -enum sci_task_status scic_controller_start_task( - struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, - struct scic_sds_request *req, - u16 task_tag) -{ - enum sci_status status; - - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { - dev_warn(scic_to_dev(scic), - "%s: SCIC Controller starting task from invalid " - "state\n", - __func__); - return SCI_TASK_FAILURE_INVALID_STATE; - } - - status = scic_sds_remote_device_start_task(scic, rdev, req); - switch (status) { - case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: - scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; - - /* - * We will let framework know this task request started successfully, - * although core is still woring on starting the request (to post tc when - * RNC is resumed.) - */ - return SCI_SUCCESS; - case SCI_SUCCESS: - scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; - - scic_sds_controller_post_request(scic, - scic_sds_request_get_post_context(req)); - break; - default: - break; - } - - return status; -} - -/** - * scic_controller_allocate_io_tag() - This method will allocate a tag from the - * pool of free IO tags. Direct allocation of IO tags by the SCI Core user - * is optional. The scic_controller_start_io() method will allocate an IO - * tag if this method is not utilized and the tag is not supplied to the IO - * construct routine. Direct allocation of IO tags may provide additional - * performance improvements in environments capable of supporting this usage - * model. Additionally, direct allocation of IO tags also provides - * additional flexibility to the SCI Core user. Specifically, the user may - * retain IO tags across the lives of multiple IO requests. - * @controller: the handle to the controller object for which to allocate the - * tag. - * - * IO tags are a protected resource. It is incumbent upon the SCI Core user to - * ensure that each of the methods that may allocate or free available IO tags - * are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). An unsigned integer representing an available IO tag. - * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no - * currently available tags to be allocated. All return other values indicate a - * legitimate tag. - */ -u16 scic_controller_allocate_io_tag( - struct scic_sds_controller *scic) -{ - u16 task_context; - u16 sequence_count; - - if (!sci_pool_empty(scic->tci_pool)) { - sci_pool_get(scic->tci_pool, task_context); - - sequence_count = scic->io_request_sequence[task_context]; - - return scic_sds_io_tag_construct(sequence_count, task_context); - } - - return SCI_CONTROLLER_INVALID_IO_TAG; -} - -/** - * scic_controller_free_io_tag() - This method will free an IO tag to the pool - * of free IO tags. This method provides the SCI Core user more flexibility - * with regards to IO tags. The user may desire to keep an IO tag after an - * IO request has completed, because they plan on re-using the tag for a - * subsequent IO request. This method is only legal if the tag was - * allocated via scic_controller_allocate_io_tag(). - * @controller: This parameter specifies the handle to the controller object - * for which to free/return the tag. - * @io_tag: This parameter represents the tag to be freed to the pool of - * available tags. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI - * Core user, using the scic_controller_allocate_io_tag() method, then it is - * the responsibility of the caller to invoke this method to free the tag. This - * method returns an indication of whether the tag was successfully put back - * (freed) to the pool of available tags. SCI_SUCCESS This return value - * indicates the tag was successfully placed into the pool of available IO - * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag - * is not a valid IO tag value. - */ -enum sci_status scic_controller_free_io_tag( - struct scic_sds_controller *scic, - u16 io_tag) -{ - u16 sequence; - u16 index; - - BUG_ON(io_tag == SCI_CONTROLLER_INVALID_IO_TAG); - - sequence = scic_sds_io_tag_get_sequence(io_tag); - index = scic_sds_io_tag_get_index(io_tag); - - if (!sci_pool_full(scic->tci_pool)) { - if (sequence == scic->io_request_sequence[index]) { - scic_sds_io_sequence_increment( - scic->io_request_sequence[index]); - - sci_pool_put(scic->tci_pool, index); - - return SCI_SUCCESS; - } - } - - return SCI_FAILURE_INVALID_IO_TAG; -} - -void scic_controller_enable_interrupts( - struct scic_sds_controller *scic) -{ - BUG_ON(scic->smu_registers == NULL); - writel(0, &scic->smu_registers->interrupt_mask); -} - -void scic_controller_disable_interrupts( - struct scic_sds_controller *scic) -{ - BUG_ON(scic->smu_registers == NULL); - writel(0xffffffff, &scic->smu_registers->interrupt_mask); -} - -static enum sci_status scic_controller_set_mode( - struct scic_sds_controller *scic, - enum sci_controller_mode operating_mode) -{ - enum sci_status status = SCI_SUCCESS; - - if ((scic->state_machine.current_state_id == - SCI_BASE_CONTROLLER_STATE_INITIALIZING) || - (scic->state_machine.current_state_id == - SCI_BASE_CONTROLLER_STATE_INITIALIZED)) { - switch (operating_mode) { - case SCI_MODE_SPEED: - scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; - scic->task_context_entries = SCU_IO_REQUEST_COUNT; - scic->uf_control.buffers.count = - SCU_UNSOLICITED_FRAME_COUNT; - scic->completion_event_entries = SCU_EVENT_COUNT; - scic->completion_queue_entries = - SCU_COMPLETION_QUEUE_COUNT; - break; - - case SCI_MODE_SIZE: - scic->remote_node_entries = SCI_MIN_REMOTE_DEVICES; - scic->task_context_entries = SCI_MIN_IO_REQUESTS; - scic->uf_control.buffers.count = - SCU_MIN_UNSOLICITED_FRAMES; - scic->completion_event_entries = SCU_MIN_EVENTS; - scic->completion_queue_entries = - SCU_MIN_COMPLETION_QUEUE_ENTRIES; - break; - - default: - status = SCI_FAILURE_INVALID_PARAMETER_VALUE; - break; - } - } else - status = SCI_FAILURE_INVALID_STATE; - - return status; -} - -/** - * scic_sds_controller_reset_hardware() - - * - * This method will reset the controller hardware. - */ -static void scic_sds_controller_reset_hardware( - struct scic_sds_controller *scic) -{ - /* Disable interrupts so we dont take any spurious interrupts */ - scic_controller_disable_interrupts(scic); - - /* Reset the SCU */ - writel(0xFFFFFFFF, &scic->smu_registers->soft_reset_control); - - /* Delay for 1ms to before clearing the CQP and UFQPR. */ - udelay(1000); - - /* The write to the CQGR clears the CQP */ - writel(0x00000000, &scic->smu_registers->completion_queue_get); - - /* The write to the UFQGP clears the UFQPR */ - writel(0, &scic->scu_registers->sdma.unsolicited_frame_get_pointer); -} - -enum sci_status scic_user_parameters_set( - struct scic_sds_controller *scic, - union scic_user_parameters *scic_parms) -{ - u32 state = scic->state_machine.current_state_id; - - if (state == SCI_BASE_CONTROLLER_STATE_RESET || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { - u16 index; - - /* - * Validate the user parameters. If they are not legal, then - * return a failure. - */ - for (index = 0; index < SCI_MAX_PHYS; index++) { - struct sci_phy_user_params *user_phy; - - user_phy = &scic_parms->sds1.phys[index]; - - if (!((user_phy->max_speed_generation <= - SCIC_SDS_PARM_MAX_SPEED) && - (user_phy->max_speed_generation > - SCIC_SDS_PARM_NO_SPEED))) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - - if (user_phy->in_connection_align_insertion_frequency < - 3) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - - if ((user_phy->in_connection_align_insertion_frequency < - 3) || - (user_phy->align_insertion_frequency == 0) || - (user_phy-> - notify_enable_spin_up_insertion_frequency == - 0)) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } - - if ((scic_parms->sds1.stp_inactivity_timeout == 0) || - (scic_parms->sds1.ssp_inactivity_timeout == 0) || - (scic_parms->sds1.stp_max_occupancy_timeout == 0) || - (scic_parms->sds1.ssp_max_occupancy_timeout == 0) || - (scic_parms->sds1.no_outbound_task_timeout == 0)) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - - memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms)); - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_STATE; -} - -int scic_oem_parameters_validate(struct scic_sds_oem_params *oem) -{ - int i; - - for (i = 0; i < SCI_MAX_PORTS; i++) - if (oem->ports[i].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) - return -EINVAL; - - for (i = 0; i < SCI_MAX_PHYS; i++) - if (oem->phys[i].sas_address.high == 0 && - oem->phys[i].sas_address.low == 0) - return -EINVAL; - - if (oem->controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) { - for (i = 0; i < SCI_MAX_PHYS; i++) - if (oem->ports[i].phy_mask != 0) - return -EINVAL; - } else if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { - u8 phy_mask = 0; - - for (i = 0; i < SCI_MAX_PHYS; i++) - phy_mask |= oem->ports[i].phy_mask; - - if (phy_mask == 0) - return -EINVAL; - } else - return -EINVAL; - - if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT) - return -EINVAL; - - return 0; -} - -enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic, - union scic_oem_parameters *scic_parms) -{ - u32 state = scic->state_machine.current_state_id; - - if (state == SCI_BASE_CONTROLLER_STATE_RESET || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { - - if (scic_oem_parameters_validate(&scic_parms->sds1)) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - scic->oem_parameters.sds1 = scic_parms->sds1; - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_STATE; -} - -void scic_oem_parameters_get( - struct scic_sds_controller *scic, - union scic_oem_parameters *scic_parms) -{ - memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms)); -} - -#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853 -#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280 -#define INTERRUPT_COALESCE_TIMEOUT_MAX_US 2700000 -#define INTERRUPT_COALESCE_NUMBER_MAX 256 -#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 7 -#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28 - -/** - * scic_controller_set_interrupt_coalescence() - This method allows the user to - * configure the interrupt coalescence. - * @controller: This parameter represents the handle to the controller object - * for which its interrupt coalesce register is overridden. - * @coalesce_number: Used to control the number of entries in the Completion - * Queue before an interrupt is generated. If the number of entries exceed - * this number, an interrupt will be generated. The valid range of the input - * is [0, 256]. A setting of 0 results in coalescing being disabled. - * @coalesce_timeout: Timeout value in microseconds. The valid range of the - * input is [0, 2700000] . A setting of 0 is allowed and results in no - * interrupt coalescing timeout. - * - * Indicate if the user successfully set the interrupt coalesce parameters. - * SCI_SUCCESS The user successfully updated the interrutp coalescence. - * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range. - */ -static enum sci_status scic_controller_set_interrupt_coalescence( - struct scic_sds_controller *scic_controller, - u32 coalesce_number, - u32 coalesce_timeout) -{ - u8 timeout_encode = 0; - u32 min = 0; - u32 max = 0; - - /* Check if the input parameters fall in the range. */ - if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - - /* - * Defined encoding for interrupt coalescing timeout: - * Value Min Max Units - * ----- --- --- ----- - * 0 - - Disabled - * 1 13.3 20.0 ns - * 2 26.7 40.0 - * 3 53.3 80.0 - * 4 106.7 160.0 - * 5 213.3 320.0 - * 6 426.7 640.0 - * 7 853.3 1280.0 - * 8 1.7 2.6 us - * 9 3.4 5.1 - * 10 6.8 10.2 - * 11 13.7 20.5 - * 12 27.3 41.0 - * 13 54.6 81.9 - * 14 109.2 163.8 - * 15 218.5 327.7 - * 16 436.9 655.4 - * 17 873.8 1310.7 - * 18 1.7 2.6 ms - * 19 3.5 5.2 - * 20 7.0 10.5 - * 21 14.0 21.0 - * 22 28.0 41.9 - * 23 55.9 83.9 - * 24 111.8 167.8 - * 25 223.7 335.5 - * 26 447.4 671.1 - * 27 894.8 1342.2 - * 28 1.8 2.7 s - * Others Undefined */ - - /* - * Use the table above to decide the encode of interrupt coalescing timeout - * value for register writing. */ - if (coalesce_timeout == 0) - timeout_encode = 0; - else{ - /* make the timeout value in unit of (10 ns). */ - coalesce_timeout = coalesce_timeout * 100; - min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10; - max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10; - - /* get the encode of timeout for register writing. */ - for (timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN; - timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX; - timeout_encode++) { - if (min <= coalesce_timeout && max > coalesce_timeout) - break; - else if (coalesce_timeout >= max && coalesce_timeout < min * 2 - && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US * 100) { - if ((coalesce_timeout - max) < (2 * min - coalesce_timeout)) - break; - else{ - timeout_encode++; - break; - } - } else { - max = max * 2; - min = min * 2; - } - } - - if (timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX + 1) - /* the value is out of range. */ - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } - - writel(SMU_ICC_GEN_VAL(NUMBER, coalesce_number) | - SMU_ICC_GEN_VAL(TIMER, timeout_encode), - &scic_controller->smu_registers->interrupt_coalesce_control); - - - scic_controller->interrupt_coalesce_number = (u16)coalesce_number; - scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100; - - return SCI_SUCCESS; -} - - - -enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) -{ - struct sci_base_state_machine *sm = &scic->state_machine; - enum sci_status result = SCI_SUCCESS; - struct isci_host *ihost = scic_to_ihost(scic); - u32 index, state; - - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_RESET) { - dev_warn(scic_to_dev(scic), - "SCIC Controller initialize operation requested " - "in invalid state\n"); - return SCI_FAILURE_INVALID_STATE; - } - - sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); - - scic->timeout_timer = isci_timer_create(ihost, - scic, - scic_sds_controller_timeout_handler); - - scic_sds_controller_initialize_phy_startup(scic); - - scic_sds_controller_initialize_power_control(scic); - - /* - * There is nothing to do here for B0 since we do not have to - * program the AFE registers. - * / @todo The AFE settings are supposed to be correct for the B0 but - * / presently they seem to be wrong. */ - scic_sds_controller_afe_initialization(scic); - - if (result == SCI_SUCCESS) { - u32 status; - u32 terminate_loop; - - /* Take the hardware out of reset */ - writel(0, &scic->smu_registers->soft_reset_control); - - /* - * / @todo Provide meaningfull error code for hardware failure - * result = SCI_FAILURE_CONTROLLER_HARDWARE; */ - result = SCI_FAILURE; - terminate_loop = 100; - - while (terminate_loop-- && (result != SCI_SUCCESS)) { - /* Loop until the hardware reports success */ - udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME); - status = readl(&scic->smu_registers->control_status); - - if ((status & SCU_RAM_INIT_COMPLETED) == - SCU_RAM_INIT_COMPLETED) - result = SCI_SUCCESS; - } - } - - if (result == SCI_SUCCESS) { - u32 max_supported_ports; - u32 max_supported_devices; - u32 max_supported_io_requests; - u32 device_context_capacity; - - /* - * Determine what are the actaul device capacities that the - * hardware will support */ - device_context_capacity = - readl(&scic->smu_registers->device_context_capacity); - - - max_supported_ports = smu_dcc_get_max_ports(device_context_capacity); - max_supported_devices = smu_dcc_get_max_remote_node_context(device_context_capacity); - max_supported_io_requests = smu_dcc_get_max_task_context(device_context_capacity); - - /* - * Make all PEs that are unassigned match up with the - * logical ports - */ - for (index = 0; index < max_supported_ports; index++) { - struct scu_port_task_scheduler_group_registers __iomem - *ptsg = &scic->scu_registers->peg0.ptsg; - - writel(index, &ptsg->protocol_engine[index]); - } - - /* Record the smaller of the two capacity values */ - scic->logical_port_entries = - min(max_supported_ports, scic->logical_port_entries); - - scic->task_context_entries = - min(max_supported_io_requests, - scic->task_context_entries); - - scic->remote_node_entries = - min(max_supported_devices, scic->remote_node_entries); - - /* - * Now that we have the correct hardware reported minimum values - * build the MDL for the controller. Default to a performance - * configuration. - */ - scic_controller_set_mode(scic, SCI_MODE_SPEED); - } - - /* Initialize hardware PCI Relaxed ordering in DMA engines */ - if (result == SCI_SUCCESS) { - u32 dma_configuration; - - /* Configure the payload DMA */ - dma_configuration = - readl(&scic->scu_registers->sdma.pdma_configuration); - dma_configuration |= - SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - writel(dma_configuration, - &scic->scu_registers->sdma.pdma_configuration); - - /* Configure the control DMA */ - dma_configuration = - readl(&scic->scu_registers->sdma.cdma_configuration); - dma_configuration |= - SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - writel(dma_configuration, - &scic->scu_registers->sdma.cdma_configuration); - } - - /* - * Initialize the PHYs before the PORTs because the PHY registers - * are accessed during the port initialization. - */ - if (result == SCI_SUCCESS) { - /* Initialize the phys */ - for (index = 0; - (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS); - index++) { - result = scic_sds_phy_initialize( - &ihost->phys[index].sci, - &scic->scu_registers->peg0.pe[index].tl, - &scic->scu_registers->peg0.pe[index].ll); - } - } - - if (result == SCI_SUCCESS) { - /* Initialize the logical ports */ - for (index = 0; - (index < scic->logical_port_entries) && - (result == SCI_SUCCESS); - index++) { - result = scic_sds_port_initialize( - &ihost->ports[index].sci, - &scic->scu_registers->peg0.ptsg.port[index], - &scic->scu_registers->peg0.ptsg.protocol_engine, - &scic->scu_registers->peg0.viit[index]); - } - } - - if (result == SCI_SUCCESS) - result = scic_sds_port_configuration_agent_initialize( - scic, - &scic->port_agent); - - /* Advance the controller state machine */ - if (result == SCI_SUCCESS) - state = SCI_BASE_CONTROLLER_STATE_INITIALIZED; - else - state = SCI_BASE_CONTROLLER_STATE_FAILED; - sci_base_state_machine_change_state(sm, state); - - return result; -} - -enum sci_status scic_controller_start(struct scic_sds_controller *scic, - u32 timeout) -{ - struct isci_host *ihost = scic_to_ihost(scic); - enum sci_status result; - u16 index; - - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_INITIALIZED) { - dev_warn(scic_to_dev(scic), - "SCIC Controller start operation requested in " - "invalid state\n"); - return SCI_FAILURE_INVALID_STATE; - } - - /* Build the TCi free pool */ - sci_pool_initialize(scic->tci_pool); - for (index = 0; index < scic->task_context_entries; index++) - sci_pool_put(scic->tci_pool, index); - - /* Build the RNi free pool */ - scic_sds_remote_node_table_initialize( - &scic->available_remote_nodes, - scic->remote_node_entries); - - /* - * Before anything else lets make sure we will not be - * interrupted by the hardware. - */ - scic_controller_disable_interrupts(scic); - - /* Enable the port task scheduler */ - scic_sds_controller_enable_port_task_scheduler(scic); - - /* Assign all the task entries to scic physical function */ - scic_sds_controller_assign_task_entries(scic); - - /* Now initialize the completion queue */ - scic_sds_controller_initialize_completion_queue(scic); - - /* Initialize the unsolicited frame queue for use */ - scic_sds_controller_initialize_unsolicited_frame_queue(scic); - - /* Start all of the ports on this controller */ - for (index = 0; index < scic->logical_port_entries; index++) { - struct scic_sds_port *sci_port = &ihost->ports[index].sci; - - result = sci_port->state_handlers->start_handler(sci_port); - if (result) - return result; - } - - scic_sds_controller_start_next_phy(scic); - - isci_timer_start(scic->timeout_timer, timeout); - - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_STARTING); - - return SCI_SUCCESS; -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_controller - * object. - * - * This method implements the actions taken by the struct scic_sds_controller on entry - * to the SCI_BASE_CONTROLLER_STATE_INITIAL. - Set the state handlers to the - * controllers initial state. none This function should initialize the - * controller object. - */ -static void scic_sds_controller_initial_state_enter(void *object) -{ - struct scic_sds_controller *scic = object; - - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_RESET); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_controller - * object. - * - * This method implements the actions taken by the struct scic_sds_controller on exit - * from the SCI_BASE_CONTROLLER_STATE_STARTING. - This function stops the - * controller starting timeout timer. none - */ -static inline void scic_sds_controller_starting_state_exit(void *object) -{ - struct scic_sds_controller *scic = object; - - isci_timer_stop(scic->timeout_timer); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_controller - * object. - * - * This method implements the actions taken by the struct scic_sds_controller on entry - * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the - * controllers ready state. none - */ -static void scic_sds_controller_ready_state_enter(void *object) -{ - struct scic_sds_controller *scic = object; - - /* set the default interrupt coalescence number and timeout value. */ - scic_controller_set_interrupt_coalescence( - scic, 0x10, 250); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_controller - * object. - * - * This method implements the actions taken by the struct scic_sds_controller on exit - * from the SCI_BASE_CONTROLLER_STATE_READY. - This function does nothing. none - */ -static void scic_sds_controller_ready_state_exit(void *object) -{ - struct scic_sds_controller *scic = object; - - /* disable interrupt coalescence. */ - scic_controller_set_interrupt_coalescence(scic, 0, 0); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_controller - * object. - * - * This method implements the actions taken by the struct scic_sds_controller on entry - * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the - * controllers ready state. - Stop the phys on this controller - Stop the ports - * on this controller - Stop all of the remote devices on this controller none - */ -static void scic_sds_controller_stopping_state_enter(void *object) -{ - struct scic_sds_controller *scic = object; - - /* Stop all of the components for this controller */ - scic_sds_controller_stop_phys(scic); - scic_sds_controller_stop_ports(scic); - scic_sds_controller_stop_devices(scic); -} - -/** - * - * @object: This is the object which is cast to a struct - * scic_sds_controller object. - * - * This function implements the actions taken by the struct scic_sds_controller - * on exit from the SCI_BASE_CONTROLLER_STATE_STOPPING. - - * This function stops the controller stopping timeout timer. - */ -static inline void scic_sds_controller_stopping_state_exit(void *object) -{ - struct scic_sds_controller *scic = object; - - isci_timer_stop(scic->timeout_timer); -} - -static void scic_sds_controller_resetting_state_enter(void *object) -{ - struct scic_sds_controller *scic = object; - - scic_sds_controller_reset_hardware(scic); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_RESET); -} - -static const struct sci_base_state scic_sds_controller_state_table[] = { - [SCI_BASE_CONTROLLER_STATE_INITIAL] = { - .enter_state = scic_sds_controller_initial_state_enter, - }, - [SCI_BASE_CONTROLLER_STATE_RESET] = {}, - [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {}, - [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {}, - [SCI_BASE_CONTROLLER_STATE_STARTING] = { - .exit_state = scic_sds_controller_starting_state_exit, - }, - [SCI_BASE_CONTROLLER_STATE_READY] = { - .enter_state = scic_sds_controller_ready_state_enter, - .exit_state = scic_sds_controller_ready_state_exit, - }, - [SCI_BASE_CONTROLLER_STATE_RESETTING] = { - .enter_state = scic_sds_controller_resetting_state_enter, - }, - [SCI_BASE_CONTROLLER_STATE_STOPPING] = { - .enter_state = scic_sds_controller_stopping_state_enter, - .exit_state = scic_sds_controller_stopping_state_exit, - }, - [SCI_BASE_CONTROLLER_STATE_STOPPED] = {}, - [SCI_BASE_CONTROLLER_STATE_FAILED] = {} -}; - -/** - * scic_controller_construct() - This method will attempt to construct a - * controller object utilizing the supplied parameter information. - * @c: This parameter specifies the controller to be constructed. - * @scu_base: mapped base address of the scu registers - * @smu_base: mapped base address of the smu registers - * - * Indicate if the controller was successfully constructed or if it failed in - * some way. SCI_SUCCESS This value is returned if the controller was - * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned - * if the interrupt coalescence timer may cause SAS compliance issues for SMP - * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE - * This value is returned if the controller does not support the supplied type. - * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the - * controller does not support the supplied initialization data version. - */ -enum sci_status scic_controller_construct(struct scic_sds_controller *scic, - void __iomem *scu_base, - void __iomem *smu_base) -{ - struct isci_host *ihost = scic_to_ihost(scic); - u8 i; - - sci_base_state_machine_construct(&scic->state_machine, - scic, scic_sds_controller_state_table, - SCI_BASE_CONTROLLER_STATE_INITIAL); - - sci_base_state_machine_start(&scic->state_machine); - - scic->scu_registers = scu_base; - scic->smu_registers = smu_base; - - scic_sds_port_configuration_agent_construct(&scic->port_agent); - - /* Construct the ports for this controller */ - for (i = 0; i < SCI_MAX_PORTS; i++) - scic_sds_port_construct(&ihost->ports[i].sci, i, scic); - scic_sds_port_construct(&ihost->ports[i].sci, SCIC_SDS_DUMMY_PORT, scic); - - /* Construct the phys for this controller */ - for (i = 0; i < SCI_MAX_PHYS; i++) { - /* Add all the PHYs to the dummy port */ - scic_sds_phy_construct(&ihost->phys[i].sci, - &ihost->ports[SCI_MAX_PORTS].sci, i); - } - - scic->invalid_phy_mask = 0; - - /* Set the default maximum values */ - scic->completion_event_entries = SCU_EVENT_COUNT; - scic->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; - scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; - scic->logical_port_entries = SCI_MAX_PORTS; - scic->task_context_entries = SCU_IO_REQUEST_COUNT; - scic->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT; - scic->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT; - - /* Initialize the User and OEM parameters to default values. */ - scic_sds_controller_set_default_config_parameters(scic); - - return scic_controller_reset(scic); -} diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h deleted file mode 100644 index 5c00f9688c18..000000000000 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ /dev/null @@ -1,576 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_CONTROLLER_H_ -#define _SCIC_SDS_CONTROLLER_H_ - -#include -#include - -/** - * This file contains the structures, constants and prototypes used for the - * core controller object. - * - * - */ - -#include "sci_pool.h" -#include "sci_base_state.h" -#include "sci_base_state_machine.h" -#include "scic_config_parameters.h" -#include "scic_sds_port.h" -#include "scic_sds_phy.h" -#include "remote_node_table.h" -#include "remote_device.h" -#include "scu_registers.h" -#include "scu_task_context.h" -#include "scu_unsolicited_frame.h" -#include "scic_sds_unsolicited_frame_control.h" -#include "scic_sds_port_configuration_agent.h" - -struct sci_base_remote_device; -struct scic_sds_remote_device; -struct scic_sds_request; -struct scic_sds_controller; - -/** - * struct scic_power_control - - * - * This structure defines the fields for managing power control for direct - * attached disk devices. - */ -struct scic_power_control { - /** - * This field is set when the power control timer is running and cleared when - * it is not. - */ - bool timer_started; - - /** - * This field is the handle to the driver timer object. This timer is used to - * control when the directed attached disks can consume power. - */ - void *timer; - - /** - * This field is used to keep track of how many phys are put into the - * requesters field. - */ - u8 phys_waiting; - - /** - * This field is used to keep track of how many phys have been granted to consume power - */ - u8 phys_granted_power; - - /** - * This field is an array of phys that we are waiting on. The phys are direct - * mapped into requesters via struct scic_sds_phy.phy_index - */ - struct scic_sds_phy *requesters[SCI_MAX_PHYS]; - -}; - -/** - * struct scic_sds_controller - - * - * This structure represents the SCU controller object. - */ -struct scic_sds_controller { - /** - * This field contains the information for the base controller state - * machine. - */ - struct sci_base_state_machine state_machine; - - /** - * This field is the driver timer object handler used to time the controller - * object start and stop requests. - */ - void *timeout_timer; - - /** - * This field contains the user parameters to be utilized for this - * core controller object. - */ - union scic_user_parameters user_parameters; - - /** - * This field contains the OEM parameters to be utilized for this - * core controller object. - */ - union scic_oem_parameters oem_parameters; - - /** - * This field contains the port configuration agent for this controller. - */ - struct scic_sds_port_configuration_agent port_agent; - - /** - * This field is the array of device objects that are currently constructed - * for this controller object. This table is used as a fast lookup of device - * objects that need to handle device completion notifications from the - * hardware. The table is RNi based. - */ - struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; - - /** - * This field is the array of IO request objects that are currently active for - * this controller object. This table is used as a fast lookup of the io - * request object that need to handle completion queue notifications. The - * table is TCi based. - */ - struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS]; - - /** - * This field is the free RNi data structure - */ - struct scic_remote_node_table available_remote_nodes; - - /** - * This field is the TCi pool used to manage the task context index. - */ - SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS); - - /** - * This filed is the struct scic_power_control data used to controll when direct - * attached devices can consume power. - */ - struct scic_power_control power_control; - - /** - * This field is the array of sequence values for the IO Tag fields. Even - * though only 4 bits of the field is used for the sequence the sequence is 16 - * bits in size so the sequence can be bitwise or'd with the TCi to build the - * IO Tag value. - */ - u16 io_request_sequence[SCI_MAX_IO_REQUESTS]; - - /** - * This field in the array of sequence values for the RNi. These are used - * to control io request build to io request start operations. The sequence - * value is recorded into an io request when it is built and is checked on - * the io request start operation to make sure that there was not a device - * hot plug between the build and start operation. - */ - u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES]; - - /** - * This field is a pointer to the memory allocated by the driver for the task - * context table. This data is shared between the hardware and software. - */ - struct scu_task_context *task_context_table; - - /** - * This field is a pointer to the memory allocated by the driver for the - * remote node context table. This table is shared between the hardware and - * software. - */ - union scu_remote_node_context *remote_node_context_table; - - /** - * This field is a pointer to the completion queue. This memory is - * written to by the hardware and read by the software. - */ - u32 *completion_queue; - - /** - * This field is the software copy of the completion queue get pointer. The - * controller object writes this value to the hardware after processing the - * completion entries. - */ - u32 completion_queue_get; - - /** - * This field is the minimum of the number of hardware supported port entries - * and the software requested port entries. - */ - u32 logical_port_entries; - - /** - * This field is the minimum number of hardware supported completion queue - * entries and the software requested completion queue entries. - */ - u32 completion_queue_entries; - - /** - * This field is the minimum number of hardware supported event entries and - * the software requested event entries. - */ - u32 completion_event_entries; - - /** - * This field is the minimum number of devices supported by the hardware and - * the number of devices requested by the software. - */ - u32 remote_node_entries; - - /** - * This field is the minimum number of IO requests supported by the hardware - * and the number of IO requests requested by the software. - */ - u32 task_context_entries; - - /** - * This object contains all of the unsolicited frame specific - * data utilized by the core controller. - */ - struct scic_sds_unsolicited_frame_control uf_control; - - /* Phy Startup Data */ - /** - * This field is the driver timer handle for controller phy request startup. - * On controller start the controller will start each PHY individually in - * order of phy index. - */ - void *phy_startup_timer; - - /** - * This field is set when the phy_startup_timer is running and is cleared when - * the phy_startup_timer is stopped. - */ - bool phy_startup_timer_pending; - - /** - * This field is the index of the next phy start. It is initialized to 0 and - * increments for each phy index that is started. - */ - u32 next_phy_to_start; - - /** - * This field controlls the invalid link up notifications to the SCI_USER. If - * an invalid_link_up notification is reported a bit for the PHY index is set - * so further notifications are not made. Once the PHY object reports link up - * and is made part of a port then this bit for the PHY index is cleared. - */ - u8 invalid_phy_mask; - - /* - * This field saves the current interrupt coalescing number of the controller. - */ - u16 interrupt_coalesce_number; - - /* - * This field saves the current interrupt coalescing timeout value in microseconds. - */ - u32 interrupt_coalesce_timeout; - - /** - * This field is a pointer to the memory mapped register space for the - * struct smu_registers. - */ - struct smu_registers __iomem *smu_registers; - - /** - * This field is a pointer to the memory mapped register space for the - * struct scu_registers. - */ - struct scu_registers __iomem *scu_registers; - -}; - -/** - * enum scic_sds_controller_states - This enumeration depicts all the states - * for the common controller state machine. - */ -enum scic_sds_controller_states { - /** - * Simply the initial state for the base controller state machine. - */ - SCI_BASE_CONTROLLER_STATE_INITIAL = 0, - - /** - * This state indicates that the controller is reset. The memory for - * the controller is in it's initial state, but the controller requires - * initialization. - * This state is entered from the INITIAL state. - * This state is entered from the RESETTING state. - */ - SCI_BASE_CONTROLLER_STATE_RESET, - - /** - * This state is typically an action state that indicates the controller - * is in the process of initialization. In this state no new IO operations - * are permitted. - * This state is entered from the RESET state. - */ - SCI_BASE_CONTROLLER_STATE_INITIALIZING, - - /** - * This state indicates that the controller has been successfully - * initialized. In this state no new IO operations are permitted. - * This state is entered from the INITIALIZING state. - */ - SCI_BASE_CONTROLLER_STATE_INITIALIZED, - - /** - * This state indicates the the controller is in the process of becoming - * ready (i.e. starting). In this state no new IO operations are permitted. - * This state is entered from the INITIALIZED state. - */ - SCI_BASE_CONTROLLER_STATE_STARTING, - - /** - * This state indicates the controller is now ready. Thus, the user - * is able to perform IO operations on the controller. - * This state is entered from the STARTING state. - */ - SCI_BASE_CONTROLLER_STATE_READY, - - /** - * This state is typically an action state that indicates the controller - * is in the process of resetting. Thus, the user is unable to perform - * IO operations on the controller. A reset is considered destructive in - * most cases. - * This state is entered from the READY state. - * This state is entered from the FAILED state. - * This state is entered from the STOPPED state. - */ - SCI_BASE_CONTROLLER_STATE_RESETTING, - - /** - * This state indicates that the controller is in the process of stopping. - * In this state no new IO operations are permitted, but existing IO - * operations are allowed to complete. - * This state is entered from the READY state. - */ - SCI_BASE_CONTROLLER_STATE_STOPPING, - - /** - * This state indicates that the controller has successfully been stopped. - * In this state no new IO operations are permitted. - * This state is entered from the STOPPING state. - */ - SCI_BASE_CONTROLLER_STATE_STOPPED, - - /** - * This state indicates that the controller could not successfully be - * initialized. In this state no new IO operations are permitted. - * This state is entered from the INITIALIZING state. - * This state is entered from the STARTING state. - * This state is entered from the STOPPING state. - * This state is entered from the RESETTING state. - */ - SCI_BASE_CONTROLLER_STATE_FAILED, - - SCI_BASE_CONTROLLER_MAX_STATES - -}; - -/** - * INCREMENT_QUEUE_GET() - - * - * This macro will increment the specified index to and if the index wraps to 0 - * it will toggel the cycle bit. - */ -#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \ - { \ - if ((index) + 1 == entry_count) { \ - (index) = 0; \ - (cycle) = (cycle) ^ (bit_toggle); \ - } else { \ - index = index + 1; \ - } \ - } - -/** - * scic_sds_controller_get_port_configuration_agent() - - * - * This is a helper macro to get the port configuration agent from the - * controller object. - */ -#define scic_sds_controller_get_port_configuration_agent(controller) \ - (&(controller)->port_agent) - -/** - * scic_sds_controller_get_protocol_engine_group() - - * - * This macro returns the protocol engine group for this controller object. - * Presently we only support protocol engine group 0 so just return that - */ -#define scic_sds_controller_get_protocol_engine_group(controller) 0 - -/** - * scic_sds_io_tag_construct() - - * - * This macro constructs an IO tag from the sequence and index values. - */ -#define scic_sds_io_tag_construct(sequence, task_index) \ - ((sequence) << 12 | (task_index)) - -/** - * scic_sds_io_tag_get_sequence() - - * - * This macro returns the IO sequence from the IO tag value. - */ -#define scic_sds_io_tag_get_sequence(io_tag) \ - (((io_tag) & 0xF000) >> 12) - -/** - * scic_sds_io_tag_get_index() - - * - * This macro returns the TCi from the io tag value - */ -#define scic_sds_io_tag_get_index(io_tag) \ - ((io_tag) & 0x0FFF) - -/** - * scic_sds_io_sequence_increment() - - * - * This is a helper macro to increment the io sequence count. We may find in - * the future that it will be faster to store the sequence count in such a way - * as we dont perform the shift operation to build io tag values so therefore - * need a way to incrment them correctly - */ -#define scic_sds_io_sequence_increment(value) \ - ((value) = (((value) + 1) & 0x000F)) - -/* expander attached sata devices require 3 rnc slots */ -static inline int scic_sds_remote_device_node_count(struct scic_sds_remote_device *sci_dev) -{ - struct domain_device *dev = sci_dev_to_domain(sci_dev); - - if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) && - !sci_dev->is_direct_attached) - return SCU_STP_REMOTE_NODE_COUNT; - return SCU_SSP_REMOTE_NODE_COUNT; -} - -/** - * scic_sds_controller_set_invalid_phy() - - * - * This macro will set the bit in the invalid phy mask for this controller - * object. This is used to control messages reported for invalid link up - * notifications. - */ -#define scic_sds_controller_set_invalid_phy(controller, phy) \ - ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index)) - -/** - * scic_sds_controller_clear_invalid_phy() - - * - * This macro will clear the bit in the invalid phy mask for this controller - * object. This is used to control messages reported for invalid link up - * notifications. - */ -#define scic_sds_controller_clear_invalid_phy(controller, phy) \ - ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) - -void scic_sds_controller_post_request( - struct scic_sds_controller *this_controller, - u32 request); - -void scic_sds_controller_release_frame( - struct scic_sds_controller *this_controller, - u32 frame_index); - -void scic_sds_controller_copy_sata_response( - void *response_buffer, - void *frame_header, - void *frame_buffer); - -enum sci_status scic_sds_controller_allocate_remote_node_context( - struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *sci_dev, - u16 *node_id); - -void scic_sds_controller_free_remote_node_context( - struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *sci_dev, - u16 node_id); - -union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( - struct scic_sds_controller *this_controller, - u16 node_id); - -struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, - u16 io_tag); - -struct scu_task_context *scic_sds_controller_get_task_context_buffer( - struct scic_sds_controller *this_controller, - u16 io_tag); - -void scic_sds_controller_power_control_queue_insert( - struct scic_sds_controller *this_controller, - struct scic_sds_phy *sci_phy); - -void scic_sds_controller_power_control_queue_remove( - struct scic_sds_controller *this_controller, - struct scic_sds_phy *sci_phy); - -void scic_sds_controller_link_up( - struct scic_sds_controller *this_controller, - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -void scic_sds_controller_link_down( - struct scic_sds_controller *this_controller, - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -void scic_sds_controller_remote_device_stopped( - struct scic_sds_controller *this_controller, - struct scic_sds_remote_device *sci_dev); - -void scic_sds_controller_copy_task_context( - struct scic_sds_controller *this_controller, - struct scic_sds_request *this_request); - -void scic_sds_controller_register_setup( - struct scic_sds_controller *this_controller); - -enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req); - -#endif /* _SCIC_SDS_CONTROLLER_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index c6df0e2c842e..c82ccb93fd9b 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -55,14 +55,13 @@ #include #include "sas.h" +#include "host.h" #include "sci_base_state.h" #include "sci_base_state_machine.h" #include "scic_phy.h" -#include "scic_sds_controller.h" #include "scic_sds_phy.h" #include "scic_sds_port.h" #include "remote_node_context.h" -#include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" #include "timers.h" diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 9302e397e4ca..652d823d5fa3 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -53,16 +53,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "scic_controller.h" +#include "host.h" #include "scic_phy.h" #include "scic_port.h" -#include "scic_sds_controller.h" #include "scic_sds_phy.h" #include "scic_sds_port.h" #include "remote_device.h" #include "remote_node_context.h" #include "scic_sds_request.h" -#include "sci_environment.h" #include "scu_registers.h" #include "timers.h" diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 3696debcce12..bd612d576093 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -57,6 +57,7 @@ #define _SCIC_SDS_PORT_H_ #include +#include "isci.h" #include "sas.h" #include "scu_registers.h" #include "sci_base_state_machine.h" diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c index 3fad8c1db6c9..a5871fddc09a 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c @@ -53,9 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "sci_environment.h" -#include "scic_controller.h" -#include "scic_sds_controller.h" +#include "host.h" #include "scic_sds_port_configuration_agent.h" #include "timers.h" diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index de35885eb1f9..1405aa703c3a 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -54,9 +54,7 @@ */ #include -#include "scic_controller.h" #include "scic_io_request.h" -#include "scic_sds_controller.h" #include "scu_registers.h" #include "scic_sds_port.h" #include "remote_device.h" @@ -64,7 +62,6 @@ #include "scic_sds_smp_request.h" #include "scic_sds_stp_request.h" #include "scic_sds_unsolicited_frame_control.h" -#include "sci_environment.h" #include "sci_util.h" #include "scu_completion_codes.h" #include "scu_task_context.h" diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 2b911206e8d2..7f338948ae0d 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -55,15 +55,13 @@ #include #include "sci_base_state_machine.h" -#include "scic_controller.h" -#include "scic_sds_controller.h" #include "remote_device.h" #include "scic_sds_request.h" #include "scic_sds_smp_request.h" -#include "sci_environment.h" #include "sci_util.h" #include "scu_completion_codes.h" #include "scu_task_context.h" +#include "host.h" static void scu_smp_request_construct_task_context( struct scic_sds_request *sci_req, diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index 18bf3874d6ac..137f6ddac82c 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -53,11 +53,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "host.h" #include "sci_base_state_machine.h" -#include "scic_controller.h" -#include "scic_sds_controller.h" #include "scic_sds_request.h" -#include "sci_environment.h" #include "scu_completion_codes.h" #include "scu_task_context.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index c1c316cad522..2f5095130cad 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -58,13 +58,11 @@ #include "sci_base_state.h" #include "sci_base_state_machine.h" #include "scic_io_request.h" -#include "scic_sds_controller.h" #include "remote_device.h" #include "scic_sds_request.h" #include "scic_sds_stp_pio_request.h" #include "scic_sds_stp_request.h" #include "scic_sds_unsolicited_frame_control.h" -#include "sci_environment.h" #include "sci_util.h" #include "scu_completion_codes.h" #include "scu_event_codes.h" diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c index 9e393e5df8ec..d0e03731377e 100644 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c @@ -53,19 +53,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the implementation of the - * struct scic_sds_unsolicited_frame_control object and it's public, protected, and - * private methods. - * - * - */ - +#include "host.h" #include "scic_sds_unsolicited_frame_control.h" #include "scu_registers.h" -#include "scic_sds_controller.h" #include "sci_util.h" -#include "sci_environment.h" /** * This method will program the unsolicited frames (UFs) into the UF address diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 5847149857a9..43a5d7a8b291 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -52,18 +52,198 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#include +#include +#include "host.h" #include "isci.h" -#include "scic_io_request.h" -#include "scic_port.h" #include "port.h" -#include "request.h" #include "host.h" #include "probe_roms.h" -#include "scic_controller.h" -#include "scic_sds_controller.h" +#include "remote_device.h" +#include "request.h" +#include "scic_io_request.h" +#include "scic_sds_port_configuration_agent.h" +#include "sci_util.h" +#include "scu_completion_codes.h" +#include "scu_event_codes.h" +#include "scu_registers.h" +#include "scu_remote_node_context.h" +#include "scu_task_context.h" +#include "scu_unsolicited_frame.h" #include "timers.h" +#define SCU_CONTEXT_RAM_INIT_STALL_TIME 200 + +/** + * smu_dcc_get_max_ports() - + * + * This macro returns the maximum number of logical ports supported by the + * hardware. The caller passes in the value read from the device context + * capacity register and this macro will mash and shift the value appropriately. + */ +#define smu_dcc_get_max_ports(dcc_value) \ + (\ + (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \ + ) + +/** + * smu_dcc_get_max_task_context() - + * + * This macro returns the maximum number of task contexts supported by the + * hardware. The caller passes in the value read from the device context + * capacity register and this macro will mash and shift the value appropriately. + */ +#define smu_dcc_get_max_task_context(dcc_value) \ + (\ + (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \ + ) + +/** + * smu_dcc_get_max_remote_node_context() - + * + * This macro returns the maximum number of remote node contexts supported by + * the hardware. The caller passes in the value read from the device context + * capacity register and this macro will mash and shift the value appropriately. + */ +#define smu_dcc_get_max_remote_node_context(dcc_value) \ + (\ + (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \ + ) + + +#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3 +#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3 + +/** + * + * + * The number of milliseconds to wait for a phy to start. + */ +#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100 + +/** + * + * + * The number of milliseconds to wait while a given phy is consuming power + * before allowing another set of phys to consume power. Ultimately, this will + * be specified by OEM parameter. + */ +#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500 + +/** + * NORMALIZE_PUT_POINTER() - + * + * This macro will normalize the completion queue put pointer so its value can + * be used as an array inde + */ +#define NORMALIZE_PUT_POINTER(x) \ + ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK) + + +/** + * NORMALIZE_EVENT_POINTER() - + * + * This macro will normalize the completion queue event entry so its value can + * be used as an index. + */ +#define NORMALIZE_EVENT_POINTER(x) \ + (\ + ((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK) \ + >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \ + ) + +/** + * INCREMENT_COMPLETION_QUEUE_GET() - + * + * This macro will increment the controllers completion queue index value and + * possibly toggle the cycle bit if the completion queue index wraps back to 0. + */ +#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \ + INCREMENT_QUEUE_GET(\ + (index), \ + (cycle), \ + (controller)->completion_queue_entries, \ + SMU_CQGR_CYCLE_BIT \ + ) + +/** + * INCREMENT_EVENT_QUEUE_GET() - + * + * This macro will increment the controllers event queue index value and + * possibly toggle the event cycle bit if the event queue index wraps back to 0. + */ +#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \ + INCREMENT_QUEUE_GET(\ + (index), \ + (cycle), \ + (controller)->completion_event_entries, \ + SMU_CQGR_EVENT_CYCLE_BIT \ + ) + + +/** + * NORMALIZE_GET_POINTER() - + * + * This macro will normalize the completion queue get pointer so its value can + * be used as an index into an array + */ +#define NORMALIZE_GET_POINTER(x) \ + ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK) + +/** + * NORMALIZE_GET_POINTER_CYCLE_BIT() - + * + * This macro will normalize the completion queue cycle pointer so it matches + * the completion queue cycle bit + */ +#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \ + ((SMU_CQGR_CYCLE_BIT & (x)) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT)) + +/** + * COMPLETION_QUEUE_CYCLE_BIT() - + * + * This macro will return the cycle bit of the completion queue entry + */ +#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000) + +static bool scic_sds_controller_completion_queue_has_entries( + struct scic_sds_controller *scic) +{ + u32 get_value = scic->completion_queue_get; + u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK; + + if (NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) == + COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index])) + return true; + + return false; +} + +static bool scic_sds_controller_isr(struct scic_sds_controller *scic) +{ + if (scic_sds_controller_completion_queue_has_entries(scic)) { + return true; + } else { + /* + * we have a spurious interrupt it could be that we have already + * emptied the completion queue from a previous interrupt */ + writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); + + /* + * There is a race in the hardware that could cause us not to be notified + * of an interrupt completion if we do not take this step. We will mask + * then unmask the interrupts so if there is another interrupt pending + * the clearing of the interrupt source we get the next interrupt message. */ + writel(0xFF000000, &scic->smu_registers->interrupt_mask); + writel(0, &scic->smu_registers->interrupt_mask); + } + + return false; +} + irqreturn_t isci_msix_isr(int vec, void *data) { struct isci_host *ihost = data; @@ -74,6 +254,411 @@ irqreturn_t isci_msix_isr(int vec, void *data) return IRQ_HANDLED; } +static bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) +{ + u32 interrupt_status; + + interrupt_status = + readl(&scic->smu_registers->interrupt_status); + interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); + + if (interrupt_status != 0) { + /* + * There is an error interrupt pending so let it through and handle + * in the callback */ + return true; + } + + /* + * There is a race in the hardware that could cause us not to be notified + * of an interrupt completion if we do not take this step. We will mask + * then unmask the error interrupts so if there was another interrupt + * pending we will be notified. + * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */ + writel(0xff, &scic->smu_registers->interrupt_mask); + writel(0, &scic->smu_registers->interrupt_mask); + + return false; +} + +static void scic_sds_controller_task_completion(struct scic_sds_controller *scic, + u32 completion_entry) +{ + u32 index; + struct scic_sds_request *io_request; + + index = SCU_GET_COMPLETION_INDEX(completion_entry); + io_request = scic->io_request_table[index]; + + /* Make sure that we really want to process this IO request */ + if ( + (io_request != NULL) + && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) + && ( + scic_sds_io_tag_get_sequence(io_request->io_tag) + == scic->io_request_sequence[index] + ) + ) { + /* Yep this is a valid io request pass it along to the io request handler */ + scic_sds_io_request_tc_completion(io_request, completion_entry); + } +} + +static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic, + u32 completion_entry) +{ + u32 index; + struct scic_sds_request *io_request; + struct scic_sds_remote_device *device; + + index = SCU_GET_COMPLETION_INDEX(completion_entry); + + switch (scu_get_command_request_type(completion_entry)) { + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: + io_request = scic->io_request_table[index]; + dev_warn(scic_to_dev(scic), + "%s: SCIC SDS Completion type SDMA %x for io request " + "%p\n", + __func__, + completion_entry, + io_request); + /* @todo For a post TC operation we need to fail the IO + * request + */ + break; + + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC: + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC: + case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: + device = scic->device_table[index]; + dev_warn(scic_to_dev(scic), + "%s: SCIC SDS Completion type SDMA %x for remote " + "device %p\n", + __func__, + completion_entry, + device); + /* @todo For a port RNC operation we need to fail the + * device + */ + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: SCIC SDS Completion unknown SDMA completion " + "type %x\n", + __func__, + completion_entry); + break; + + } +} + +static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *scic, + u32 completion_entry) +{ + u32 index; + u32 frame_index; + + struct isci_host *ihost = scic_to_ihost(scic); + struct scu_unsolicited_frame_header *frame_header; + struct scic_sds_phy *phy; + struct scic_sds_remote_device *device; + + enum sci_status result = SCI_FAILURE; + + frame_index = SCU_GET_FRAME_INDEX(completion_entry); + + frame_header = scic->uf_control.buffers.array[frame_index].header; + scic->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE; + + if (SCU_GET_FRAME_ERROR(completion_entry)) { + /* + * / @todo If the IAF frame or SIGNATURE FIS frame has an error will + * / this cause a problem? We expect the phy initialization will + * / fail if there is an error in the frame. */ + scic_sds_controller_release_frame(scic, frame_index); + return; + } + + if (frame_header->is_address_frame) { + index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + phy = &ihost->phys[index].sci; + result = scic_sds_phy_frame_handler(phy, frame_index); + } else { + + index = SCU_GET_COMPLETION_INDEX(completion_entry); + + if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + /* + * This is a signature fis or a frame from a direct attached SATA + * device that has not yet been created. In either case forwared + * the frame to the PE and let it take care of the frame data. */ + index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + phy = &ihost->phys[index].sci; + result = scic_sds_phy_frame_handler(phy, frame_index); + } else { + if (index < scic->remote_node_entries) + device = scic->device_table[index]; + else + device = NULL; + + if (device != NULL) + result = scic_sds_remote_device_frame_handler(device, frame_index); + else + scic_sds_controller_release_frame(scic, frame_index); + } + } + + if (result != SCI_SUCCESS) { + /* + * / @todo Is there any reason to report some additional error message + * / when we get this failure notifiction? */ + } +} + +static void scic_sds_controller_event_completion(struct scic_sds_controller *scic, + u32 completion_entry) +{ + struct isci_host *ihost = scic_to_ihost(scic); + struct scic_sds_request *io_request; + struct scic_sds_remote_device *device; + struct scic_sds_phy *phy; + u32 index; + + index = SCU_GET_COMPLETION_INDEX(completion_entry); + + switch (scu_get_event_type(completion_entry)) { + case SCU_EVENT_TYPE_SMU_COMMAND_ERROR: + /* / @todo The driver did something wrong and we need to fix the condtion. */ + dev_err(scic_to_dev(scic), + "%s: SCIC Controller 0x%p received SMU command error " + "0x%x\n", + __func__, + scic, + completion_entry); + break; + + case SCU_EVENT_TYPE_SMU_PCQ_ERROR: + case SCU_EVENT_TYPE_SMU_ERROR: + case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR: + /* + * / @todo This is a hardware failure and its likely that we want to + * / reset the controller. */ + dev_err(scic_to_dev(scic), + "%s: SCIC Controller 0x%p received fatal controller " + "event 0x%x\n", + __func__, + scic, + completion_entry); + break; + + case SCU_EVENT_TYPE_TRANSPORT_ERROR: + io_request = scic->io_request_table[index]; + scic_sds_io_request_event_handler(io_request, completion_entry); + break; + + case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: + switch (scu_get_event_specifier(completion_entry)) { + case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: + case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: + io_request = scic->io_request_table[index]; + if (io_request != NULL) + scic_sds_io_request_event_handler(io_request, completion_entry); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller 0x%p received " + "event 0x%x for io request object " + "that doesnt exist.\n", + __func__, + scic, + completion_entry); + + break; + + case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: + device = scic->device_table[index]; + if (device != NULL) + scic_sds_remote_device_event_handler(device, completion_entry); + else + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller 0x%p received " + "event 0x%x for remote device object " + "that doesnt exist.\n", + __func__, + scic, + completion_entry); + + break; + } + break; + + case SCU_EVENT_TYPE_BROADCAST_CHANGE: + /* + * direct the broadcast change event to the phy first and then let + * the phy redirect the broadcast change to the port object */ + case SCU_EVENT_TYPE_ERR_CNT_EVENT: + /* + * direct error counter event to the phy object since that is where + * we get the event notification. This is a type 4 event. */ + case SCU_EVENT_TYPE_OSSP_EVENT: + index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + phy = &ihost->phys[index].sci; + scic_sds_phy_event_handler(phy, completion_entry); + break; + + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + case SCU_EVENT_TYPE_RNC_OPS_MISC: + if (index < scic->remote_node_entries) { + device = scic->device_table[index]; + + if (device != NULL) + scic_sds_remote_device_event_handler(device, completion_entry); + } else + dev_err(scic_to_dev(scic), + "%s: SCIC Controller 0x%p received event 0x%x " + "for remote device object 0x%0x that doesnt " + "exist.\n", + __func__, + scic, + completion_entry, + index); + + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller received unknown event code %x\n", + __func__, + completion_entry); + break; + } +} + + + +static void scic_sds_controller_process_completions(struct scic_sds_controller *scic) +{ + u32 completion_count = 0; + u32 completion_entry; + u32 get_index; + u32 get_cycle; + u32 event_index; + u32 event_cycle; + + dev_dbg(scic_to_dev(scic), + "%s: completion queue begining get:0x%08x\n", + __func__, + scic->completion_queue_get); + + /* Get the component parts of the completion queue */ + get_index = NORMALIZE_GET_POINTER(scic->completion_queue_get); + get_cycle = SMU_CQGR_CYCLE_BIT & scic->completion_queue_get; + + event_index = NORMALIZE_EVENT_POINTER(scic->completion_queue_get); + event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & scic->completion_queue_get; + + while ( + NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) + == COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index]) + ) { + completion_count++; + + completion_entry = scic->completion_queue[get_index]; + INCREMENT_COMPLETION_QUEUE_GET(scic, get_index, get_cycle); + + dev_dbg(scic_to_dev(scic), + "%s: completion queue entry:0x%08x\n", + __func__, + completion_entry); + + switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { + case SCU_COMPLETION_TYPE_TASK: + scic_sds_controller_task_completion(scic, completion_entry); + break; + + case SCU_COMPLETION_TYPE_SDMA: + scic_sds_controller_sdma_completion(scic, completion_entry); + break; + + case SCU_COMPLETION_TYPE_UFI: + scic_sds_controller_unsolicited_frame(scic, completion_entry); + break; + + case SCU_COMPLETION_TYPE_EVENT: + INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle); + scic_sds_controller_event_completion(scic, completion_entry); + break; + + case SCU_COMPLETION_TYPE_NOTIFY: + /* + * Presently we do the same thing with a notify event that we do with the + * other event codes. */ + INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle); + scic_sds_controller_event_completion(scic, completion_entry); + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller received unknown " + "completion type %x\n", + __func__, + completion_entry); + break; + } + } + + /* Update the get register if we completed one or more entries */ + if (completion_count > 0) { + scic->completion_queue_get = + SMU_CQGR_GEN_BIT(ENABLE) | + SMU_CQGR_GEN_BIT(EVENT_ENABLE) | + event_cycle | + SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) | + get_cycle | + SMU_CQGR_GEN_VAL(POINTER, get_index); + + writel(scic->completion_queue_get, + &scic->smu_registers->completion_queue_get); + + } + + dev_dbg(scic_to_dev(scic), + "%s: completion queue ending get:0x%08x\n", + __func__, + scic->completion_queue_get); + +} + +static void scic_sds_controller_error_handler(struct scic_sds_controller *scic) +{ + u32 interrupt_status; + + interrupt_status = + readl(&scic->smu_registers->interrupt_status); + + if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && + scic_sds_controller_completion_queue_has_entries(scic)) { + + scic_sds_controller_process_completions(scic); + writel(SMU_ISR_QUEUE_SUSPEND, &scic->smu_registers->interrupt_status); + } else { + dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, + interrupt_status); + + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_FAILED); + + return; + } + + /* If we dont process any completions I am not sure that we want to do this. + * We are in the middle of a hardware fault and should probably be reset. + */ + writel(0, &scic->smu_registers->interrupt_mask); +} + irqreturn_t isci_intx_isr(int vec, void *data) { irqreturn_t ret = IRQ_NONE; @@ -112,7 +697,7 @@ irqreturn_t isci_error_isr(int vec, void *data) * core library. * */ -void isci_host_start_complete(struct isci_host *ihost, enum sci_status completion_status) +static void isci_host_start_complete(struct isci_host *ihost, enum sci_status completion_status) { if (completion_status != SCI_SUCCESS) dev_info(&ihost->pdev->dev, @@ -142,6 +727,383 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) } +/** + * scic_controller_get_suggested_start_timeout() - This method returns the + * suggested scic_controller_start() timeout amount. The user is free to + * use any timeout value, but this method provides the suggested minimum + * start timeout value. The returned value is based upon empirical + * information determined as a result of interoperability testing. + * @controller: the handle to the controller object for which to return the + * suggested start timeout. + * + * This method returns the number of milliseconds for the suggested start + * operation timeout. + */ +static u32 scic_controller_get_suggested_start_timeout( + struct scic_sds_controller *sc) +{ + /* Validate the user supplied parameters. */ + if (sc == NULL) + return 0; + + /* + * The suggested minimum timeout value for a controller start operation: + * + * Signature FIS Timeout + * + Phy Start Timeout + * + Number of Phy Spin Up Intervals + * --------------------------------- + * Number of milliseconds for the controller start operation. + * + * NOTE: The number of phy spin up intervals will be equivalent + * to the number of phys divided by the number phys allowed + * per interval - 1 (once OEM parameters are supported). + * Currently we assume only 1 phy per interval. */ + + return SCIC_SDS_SIGNATURE_FIS_TIMEOUT + + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT + + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); +} + +static void scic_controller_enable_interrupts( + struct scic_sds_controller *scic) +{ + BUG_ON(scic->smu_registers == NULL); + writel(0, &scic->smu_registers->interrupt_mask); +} + +void scic_controller_disable_interrupts( + struct scic_sds_controller *scic) +{ + BUG_ON(scic->smu_registers == NULL); + writel(0xffffffff, &scic->smu_registers->interrupt_mask); +} + +static void scic_sds_controller_enable_port_task_scheduler( + struct scic_sds_controller *scic) +{ + u32 port_task_scheduler_value; + + port_task_scheduler_value = + readl(&scic->scu_registers->peg0.ptsg.control); + port_task_scheduler_value |= + (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | + SCU_PTSGCR_GEN_BIT(PTSG_ENABLE)); + writel(port_task_scheduler_value, + &scic->scu_registers->peg0.ptsg.control); +} + +static void scic_sds_controller_assign_task_entries(struct scic_sds_controller *scic) +{ + u32 task_assignment; + + /* + * Assign all the TCs to function 0 + * TODO: Do we actually need to read this register to write it back? + */ + + task_assignment = + readl(&scic->smu_registers->task_context_assignment[0]); + + task_assignment |= (SMU_TCA_GEN_VAL(STARTING, 0)) | + (SMU_TCA_GEN_VAL(ENDING, scic->task_context_entries - 1)) | + (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE)); + + writel(task_assignment, + &scic->smu_registers->task_context_assignment[0]); + +} + +static void scic_sds_controller_initialize_completion_queue(struct scic_sds_controller *scic) +{ + u32 index; + u32 completion_queue_control_value; + u32 completion_queue_get_value; + u32 completion_queue_put_value; + + scic->completion_queue_get = 0; + + completion_queue_control_value = ( + SMU_CQC_QUEUE_LIMIT_SET(scic->completion_queue_entries - 1) + | SMU_CQC_EVENT_LIMIT_SET(scic->completion_event_entries - 1) + ); + + writel(completion_queue_control_value, + &scic->smu_registers->completion_queue_control); + + + /* Set the completion queue get pointer and enable the queue */ + completion_queue_get_value = ( + (SMU_CQGR_GEN_VAL(POINTER, 0)) + | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0)) + | (SMU_CQGR_GEN_BIT(ENABLE)) + | (SMU_CQGR_GEN_BIT(EVENT_ENABLE)) + ); + + writel(completion_queue_get_value, + &scic->smu_registers->completion_queue_get); + + /* Set the completion queue put pointer */ + completion_queue_put_value = ( + (SMU_CQPR_GEN_VAL(POINTER, 0)) + | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0)) + ); + + writel(completion_queue_put_value, + &scic->smu_registers->completion_queue_put); + + /* Initialize the cycle bit of the completion queue entries */ + for (index = 0; index < scic->completion_queue_entries; index++) { + /* + * If get.cycle_bit != completion_queue.cycle_bit + * its not a valid completion queue entry + * so at system start all entries are invalid */ + scic->completion_queue[index] = 0x80000000; + } +} + +static void scic_sds_controller_initialize_unsolicited_frame_queue(struct scic_sds_controller *scic) +{ + u32 frame_queue_control_value; + u32 frame_queue_get_value; + u32 frame_queue_put_value; + + /* Write the queue size */ + frame_queue_control_value = + SCU_UFQC_GEN_VAL(QUEUE_SIZE, + scic->uf_control.address_table.count); + + writel(frame_queue_control_value, + &scic->scu_registers->sdma.unsolicited_frame_queue_control); + + /* Setup the get pointer for the unsolicited frame queue */ + frame_queue_get_value = ( + SCU_UFQGP_GEN_VAL(POINTER, 0) + | SCU_UFQGP_GEN_BIT(ENABLE_BIT) + ); + + writel(frame_queue_get_value, + &scic->scu_registers->sdma.unsolicited_frame_get_pointer); + /* Setup the put pointer for the unsolicited frame queue */ + frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0); + writel(frame_queue_put_value, + &scic->scu_registers->sdma.unsolicited_frame_put_pointer); +} + +/** + * This method will attempt to transition into the ready state for the + * controller and indicate that the controller start operation has completed + * if all criteria are met. + * @scic: This parameter indicates the controller object for which + * to transition to ready. + * @status: This parameter indicates the status value to be pass into the call + * to scic_cb_controller_start_complete(). + * + * none. + */ +static void scic_sds_controller_transition_to_ready( + struct scic_sds_controller *scic, + enum sci_status status) +{ + struct isci_host *ihost = scic_to_ihost(scic); + + if (scic->state_machine.current_state_id == + SCI_BASE_CONTROLLER_STATE_STARTING) { + /* + * We move into the ready state, because some of the phys/ports + * may be up and operational. + */ + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_READY); + + isci_host_start_complete(ihost, status); + } +} + +static void scic_sds_controller_phy_timer_stop(struct scic_sds_controller *scic) +{ + isci_timer_stop(scic->phy_startup_timer); + + scic->phy_startup_timer_pending = false; +} + +static void scic_sds_controller_phy_timer_start(struct scic_sds_controller *scic) +{ + isci_timer_start(scic->phy_startup_timer, + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT); + + scic->phy_startup_timer_pending = true; +} + +/** + * scic_sds_controller_start_next_phy - start phy + * @scic: controller + * + * If all the phys have been started, then attempt to transition the + * controller to the READY state and inform the user + * (scic_cb_controller_start_complete()). + */ +static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic) +{ + struct isci_host *ihost = scic_to_ihost(scic); + struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; + struct scic_sds_phy *sci_phy; + enum sci_status status; + + status = SCI_SUCCESS; + + if (scic->phy_startup_timer_pending) + return status; + + if (scic->next_phy_to_start >= SCI_MAX_PHYS) { + bool is_controller_start_complete = true; + u32 state; + u8 index; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + sci_phy = &ihost->phys[index].sci; + state = sci_phy->state_machine.current_state_id; + + if (!scic_sds_phy_get_port(sci_phy)) + continue; + + /* The controller start operation is complete iff: + * - all links have been given an opportunity to start + * - have no indication of a connected device + * - have an indication of a connected device and it has + * finished the link training process. + */ + if ((sci_phy->is_in_link_training == false && + state == SCI_BASE_PHY_STATE_INITIAL) || + (sci_phy->is_in_link_training == false && + state == SCI_BASE_PHY_STATE_STOPPED) || + (sci_phy->is_in_link_training == true && + state == SCI_BASE_PHY_STATE_STARTING)) { + is_controller_start_complete = false; + break; + } + } + + /* + * The controller has successfully finished the start process. + * Inform the SCI Core user and transition to the READY state. */ + if (is_controller_start_complete == true) { + scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS); + scic_sds_controller_phy_timer_stop(scic); + } + } else { + sci_phy = &ihost->phys[scic->next_phy_to_start].sci; + + if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { + if (scic_sds_phy_get_port(sci_phy) == NULL) { + scic->next_phy_to_start++; + + /* Caution recursion ahead be forwarned + * + * The PHY was never added to a PORT in MPC mode + * so start the next phy in sequence This phy + * will never go link up and will not draw power + * the OEM parameters either configured the phy + * incorrectly for the PORT or it was never + * assigned to a PORT + */ + return scic_sds_controller_start_next_phy(scic); + } + } + + status = scic_sds_phy_start(sci_phy); + + if (status == SCI_SUCCESS) { + scic_sds_controller_phy_timer_start(scic); + } else { + dev_warn(scic_to_dev(scic), + "%s: Controller stop operation failed " + "to stop phy %d because of status " + "%d.\n", + __func__, + ihost->phys[scic->next_phy_to_start].sci.phy_index, + status); + } + + scic->next_phy_to_start++; + } + + return status; +} + +static void scic_sds_controller_phy_startup_timeout_handler(void *_scic) +{ + struct scic_sds_controller *scic = _scic; + enum sci_status status; + + scic->phy_startup_timer_pending = false; + status = SCI_FAILURE; + while (status != SCI_SUCCESS) + status = scic_sds_controller_start_next_phy(scic); +} + +static enum sci_status scic_controller_start(struct scic_sds_controller *scic, + u32 timeout) +{ + struct isci_host *ihost = scic_to_ihost(scic); + enum sci_status result; + u16 index; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_INITIALIZED) { + dev_warn(scic_to_dev(scic), + "SCIC Controller start operation requested in " + "invalid state\n"); + return SCI_FAILURE_INVALID_STATE; + } + + /* Build the TCi free pool */ + sci_pool_initialize(scic->tci_pool); + for (index = 0; index < scic->task_context_entries; index++) + sci_pool_put(scic->tci_pool, index); + + /* Build the RNi free pool */ + scic_sds_remote_node_table_initialize( + &scic->available_remote_nodes, + scic->remote_node_entries); + + /* + * Before anything else lets make sure we will not be + * interrupted by the hardware. + */ + scic_controller_disable_interrupts(scic); + + /* Enable the port task scheduler */ + scic_sds_controller_enable_port_task_scheduler(scic); + + /* Assign all the task entries to scic physical function */ + scic_sds_controller_assign_task_entries(scic); + + /* Now initialize the completion queue */ + scic_sds_controller_initialize_completion_queue(scic); + + /* Initialize the unsolicited frame queue for use */ + scic_sds_controller_initialize_unsolicited_frame_queue(scic); + + /* Start all of the ports on this controller */ + for (index = 0; index < scic->logical_port_entries; index++) { + struct scic_sds_port *sci_port = &ihost->ports[index].sci; + + result = sci_port->state_handlers->start_handler(sci_port); + if (result) + return result; + } + + scic_sds_controller_start_next_phy(scic); + + isci_timer_start(scic->timeout_timer, timeout); + + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_STARTING); + + return SCI_SUCCESS; +} + void isci_host_scan_start(struct Scsi_Host *shost) { struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha; @@ -155,7 +1117,7 @@ void isci_host_scan_start(struct Scsi_Host *shost) spin_unlock_irq(&ihost->scic_lock); } -void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) +static void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) { isci_host_change_state(ihost, isci_stopped); scic_controller_disable_interrupts(&ihost->sci); @@ -163,6 +1125,19 @@ void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion wake_up(&ihost->eventq); } +static void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) +{ + /* Empty out the completion queue */ + if (scic_sds_controller_completion_queue_has_entries(scic)) + scic_sds_controller_process_completions(scic); + + /* Clear the interrupt and enable all interrupts again */ + writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); + /* Could we write the value of SMU_ISR_COMPLETION? */ + writel(0xFF000000, &scic->smu_registers->interrupt_mask); + writel(0, &scic->smu_registers->interrupt_mask); +} + /** * isci_host_completion_routine() - This function is the delayed service * routine that calls the sci core library's completion handler. It's @@ -273,11 +1248,80 @@ static void isci_host_completion_routine(unsigned long data) } -void isci_host_deinit(struct isci_host *ihost) +/** + * scic_controller_stop() - This method will stop an individual controller + * object.This method will invoke the associated user callback upon + * completion. The completion callback is called when the following + * conditions are met: -# the method return status is SCI_SUCCESS. -# the + * controller has been quiesced. This method will ensure that all IO + * requests are quiesced, phys are stopped, and all additional operation by + * the hardware is halted. + * @controller: the handle to the controller object to stop. + * @timeout: This parameter specifies the number of milliseconds in which the + * stop operation should complete. + * + * The controller must be in the STARTED or STOPPED state. Indicate if the + * controller stop method succeeded or failed in some way. SCI_SUCCESS if the + * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the + * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the + * controller is not either in the STARTED or STOPPED states. + */ +static enum sci_status scic_controller_stop(struct scic_sds_controller *scic, + u32 timeout) { - int i; + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { + dev_warn(scic_to_dev(scic), + "SCIC Controller stop operation requested in " + "invalid state\n"); + return SCI_FAILURE_INVALID_STATE; + } - isci_host_change_state(ihost, isci_stopping); + isci_timer_start(scic->timeout_timer, timeout); + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_STOPPING); + return SCI_SUCCESS; +} + +/** + * scic_controller_reset() - This method will reset the supplied core + * controller regardless of the state of said controller. This operation is + * considered destructive. In other words, all current operations are wiped + * out. No IO completions for outstanding devices occur. Outstanding IO + * requests are not aborted or completed at the actual remote device. + * @controller: the handle to the controller object to reset. + * + * Indicate if the controller reset method succeeded or failed in some way. + * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if + * the controller reset operation is unable to complete. + */ +static enum sci_status scic_controller_reset(struct scic_sds_controller *scic) +{ + switch (scic->state_machine.current_state_id) { + case SCI_BASE_CONTROLLER_STATE_RESET: + case SCI_BASE_CONTROLLER_STATE_READY: + case SCI_BASE_CONTROLLER_STATE_STOPPED: + case SCI_BASE_CONTROLLER_STATE_FAILED: + /* + * The reset operation is not a graceful cleanup, just + * perform the state transition. + */ + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_RESETTING); + return SCI_SUCCESS; + default: + dev_warn(scic_to_dev(scic), + "SCIC Controller reset operation requested in " + "invalid state\n"); + return SCI_FAILURE_INVALID_STATE; + } +} + +void isci_host_deinit(struct isci_host *ihost) +{ + int i; + + isci_host_change_state(ihost, isci_stopping); for (i = 0; i < SCI_MAX_PORTS; i++) { struct isci_port *iport = &ihost->ports[i]; struct isci_remote_device *idev, *d; @@ -341,6 +1385,1109 @@ static void isci_user_parameters_get( u->max_number_concurrent_device_spin_up = max_concurr_spinup; } +static void scic_sds_controller_initial_state_enter(void *object) +{ + struct scic_sds_controller *scic = object; + + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_RESET); +} + +static inline void scic_sds_controller_starting_state_exit(void *object) +{ + struct scic_sds_controller *scic = object; + + isci_timer_stop(scic->timeout_timer); +} + +#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853 +#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280 +#define INTERRUPT_COALESCE_TIMEOUT_MAX_US 2700000 +#define INTERRUPT_COALESCE_NUMBER_MAX 256 +#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 7 +#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28 + +/** + * scic_controller_set_interrupt_coalescence() - This method allows the user to + * configure the interrupt coalescence. + * @controller: This parameter represents the handle to the controller object + * for which its interrupt coalesce register is overridden. + * @coalesce_number: Used to control the number of entries in the Completion + * Queue before an interrupt is generated. If the number of entries exceed + * this number, an interrupt will be generated. The valid range of the input + * is [0, 256]. A setting of 0 results in coalescing being disabled. + * @coalesce_timeout: Timeout value in microseconds. The valid range of the + * input is [0, 2700000] . A setting of 0 is allowed and results in no + * interrupt coalescing timeout. + * + * Indicate if the user successfully set the interrupt coalesce parameters. + * SCI_SUCCESS The user successfully updated the interrutp coalescence. + * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range. + */ +static enum sci_status scic_controller_set_interrupt_coalescence( + struct scic_sds_controller *scic_controller, + u32 coalesce_number, + u32 coalesce_timeout) +{ + u8 timeout_encode = 0; + u32 min = 0; + u32 max = 0; + + /* Check if the input parameters fall in the range. */ + if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + + /* + * Defined encoding for interrupt coalescing timeout: + * Value Min Max Units + * ----- --- --- ----- + * 0 - - Disabled + * 1 13.3 20.0 ns + * 2 26.7 40.0 + * 3 53.3 80.0 + * 4 106.7 160.0 + * 5 213.3 320.0 + * 6 426.7 640.0 + * 7 853.3 1280.0 + * 8 1.7 2.6 us + * 9 3.4 5.1 + * 10 6.8 10.2 + * 11 13.7 20.5 + * 12 27.3 41.0 + * 13 54.6 81.9 + * 14 109.2 163.8 + * 15 218.5 327.7 + * 16 436.9 655.4 + * 17 873.8 1310.7 + * 18 1.7 2.6 ms + * 19 3.5 5.2 + * 20 7.0 10.5 + * 21 14.0 21.0 + * 22 28.0 41.9 + * 23 55.9 83.9 + * 24 111.8 167.8 + * 25 223.7 335.5 + * 26 447.4 671.1 + * 27 894.8 1342.2 + * 28 1.8 2.7 s + * Others Undefined */ + + /* + * Use the table above to decide the encode of interrupt coalescing timeout + * value for register writing. */ + if (coalesce_timeout == 0) + timeout_encode = 0; + else{ + /* make the timeout value in unit of (10 ns). */ + coalesce_timeout = coalesce_timeout * 100; + min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10; + max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10; + + /* get the encode of timeout for register writing. */ + for (timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN; + timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX; + timeout_encode++) { + if (min <= coalesce_timeout && max > coalesce_timeout) + break; + else if (coalesce_timeout >= max && coalesce_timeout < min * 2 + && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US * 100) { + if ((coalesce_timeout - max) < (2 * min - coalesce_timeout)) + break; + else{ + timeout_encode++; + break; + } + } else { + max = max * 2; + min = min * 2; + } + } + + if (timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX + 1) + /* the value is out of range. */ + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } + + writel(SMU_ICC_GEN_VAL(NUMBER, coalesce_number) | + SMU_ICC_GEN_VAL(TIMER, timeout_encode), + &scic_controller->smu_registers->interrupt_coalesce_control); + + + scic_controller->interrupt_coalesce_number = (u16)coalesce_number; + scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100; + + return SCI_SUCCESS; +} + + +static void scic_sds_controller_ready_state_enter(void *object) +{ + struct scic_sds_controller *scic = object; + + /* set the default interrupt coalescence number and timeout value. */ + scic_controller_set_interrupt_coalescence(scic, 0x10, 250); +} + +static void scic_sds_controller_ready_state_exit(void *object) +{ + struct scic_sds_controller *scic = object; + + /* disable interrupt coalescence. */ + scic_controller_set_interrupt_coalescence(scic, 0, 0); +} + +static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller *scic) +{ + u32 index; + enum sci_status status; + enum sci_status phy_status; + struct isci_host *ihost = scic_to_ihost(scic); + + status = SCI_SUCCESS; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + phy_status = scic_sds_phy_stop(&ihost->phys[index].sci); + + if (phy_status != SCI_SUCCESS && + phy_status != SCI_FAILURE_INVALID_STATE) { + status = SCI_FAILURE; + + dev_warn(scic_to_dev(scic), + "%s: Controller stop operation failed to stop " + "phy %d because of status %d.\n", + __func__, + ihost->phys[index].sci.phy_index, phy_status); + } + } + + return status; +} + +static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) +{ + u32 index; + enum sci_status port_status; + enum sci_status status = SCI_SUCCESS; + struct isci_host *ihost = scic_to_ihost(scic); + + for (index = 0; index < scic->logical_port_entries; index++) { + struct scic_sds_port *sci_port = &ihost->ports[index].sci; + scic_sds_port_handler_t stop; + + stop = sci_port->state_handlers->stop_handler; + port_status = stop(sci_port); + + if ((port_status != SCI_SUCCESS) && + (port_status != SCI_FAILURE_INVALID_STATE)) { + status = SCI_FAILURE; + + dev_warn(scic_to_dev(scic), + "%s: Controller stop operation failed to " + "stop port %d because of status %d.\n", + __func__, + sci_port->logical_port_index, + port_status); + } + } + + return status; +} + +static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controller *scic) +{ + u32 index; + enum sci_status status; + enum sci_status device_status; + + status = SCI_SUCCESS; + + for (index = 0; index < scic->remote_node_entries; index++) { + if (scic->device_table[index] != NULL) { + /* / @todo What timeout value do we want to provide to this request? */ + device_status = scic_remote_device_stop(scic->device_table[index], 0); + + if ((device_status != SCI_SUCCESS) && + (device_status != SCI_FAILURE_INVALID_STATE)) { + dev_warn(scic_to_dev(scic), + "%s: Controller stop operation failed " + "to stop device 0x%p because of " + "status %d.\n", + __func__, + scic->device_table[index], device_status); + } + } + } + + return status; +} + +static void scic_sds_controller_stopping_state_enter(void *object) +{ + struct scic_sds_controller *scic = object; + + /* Stop all of the components for this controller */ + scic_sds_controller_stop_phys(scic); + scic_sds_controller_stop_ports(scic); + scic_sds_controller_stop_devices(scic); +} + +static void scic_sds_controller_stopping_state_exit(void *object) +{ + struct scic_sds_controller *scic = object; + + isci_timer_stop(scic->timeout_timer); +} + + +/** + * scic_sds_controller_reset_hardware() - + * + * This method will reset the controller hardware. + */ +static void scic_sds_controller_reset_hardware(struct scic_sds_controller *scic) +{ + /* Disable interrupts so we dont take any spurious interrupts */ + scic_controller_disable_interrupts(scic); + + /* Reset the SCU */ + writel(0xFFFFFFFF, &scic->smu_registers->soft_reset_control); + + /* Delay for 1ms to before clearing the CQP and UFQPR. */ + udelay(1000); + + /* The write to the CQGR clears the CQP */ + writel(0x00000000, &scic->smu_registers->completion_queue_get); + + /* The write to the UFQGP clears the UFQPR */ + writel(0, &scic->scu_registers->sdma.unsolicited_frame_get_pointer); +} + +static void scic_sds_controller_resetting_state_enter(void *object) +{ + struct scic_sds_controller *scic = object; + + scic_sds_controller_reset_hardware(scic); + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_RESET); +} + +static const struct sci_base_state scic_sds_controller_state_table[] = { + [SCI_BASE_CONTROLLER_STATE_INITIAL] = { + .enter_state = scic_sds_controller_initial_state_enter, + }, + [SCI_BASE_CONTROLLER_STATE_RESET] = {}, + [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {}, + [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {}, + [SCI_BASE_CONTROLLER_STATE_STARTING] = { + .exit_state = scic_sds_controller_starting_state_exit, + }, + [SCI_BASE_CONTROLLER_STATE_READY] = { + .enter_state = scic_sds_controller_ready_state_enter, + .exit_state = scic_sds_controller_ready_state_exit, + }, + [SCI_BASE_CONTROLLER_STATE_RESETTING] = { + .enter_state = scic_sds_controller_resetting_state_enter, + }, + [SCI_BASE_CONTROLLER_STATE_STOPPING] = { + .enter_state = scic_sds_controller_stopping_state_enter, + .exit_state = scic_sds_controller_stopping_state_exit, + }, + [SCI_BASE_CONTROLLER_STATE_STOPPED] = {}, + [SCI_BASE_CONTROLLER_STATE_FAILED] = {} +}; + +static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) +{ + /* these defaults are overridden by the platform / firmware */ + struct isci_host *ihost = scic_to_ihost(scic); + u16 index; + + /* Default to APC mode. */ + scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; + + /* Default to APC mode. */ + scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1; + + /* Default to no SSC operation. */ + scic->oem_parameters.sds1.controller.do_enable_ssc = false; + + /* Initialize all of the port parameter information to narrow ports. */ + for (index = 0; index < SCI_MAX_PORTS; index++) { + scic->oem_parameters.sds1.ports[index].phy_mask = 0; + } + + /* Initialize all of the phy parameter information. */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + /* Default to 6G (i.e. Gen 3) for now. */ + scic->user_parameters.sds1.phys[index].max_speed_generation = 3; + + /* the frequencies cannot be 0 */ + scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f; + scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff; + scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; + + /* + * Previous Vitesse based expanders had a arbitration issue that + * is worked around by having the upper 32-bits of SAS address + * with a value greater then the Vitesse company identifier. + * Hence, usage of 0x5FCFFFFF. */ + scic->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id; + scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF; + } + + scic->user_parameters.sds1.stp_inactivity_timeout = 5; + scic->user_parameters.sds1.ssp_inactivity_timeout = 5; + scic->user_parameters.sds1.stp_max_occupancy_timeout = 5; + scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20; + scic->user_parameters.sds1.no_outbound_task_timeout = 20; +} + + + +/** + * scic_controller_construct() - This method will attempt to construct a + * controller object utilizing the supplied parameter information. + * @c: This parameter specifies the controller to be constructed. + * @scu_base: mapped base address of the scu registers + * @smu_base: mapped base address of the smu registers + * + * Indicate if the controller was successfully constructed or if it failed in + * some way. SCI_SUCCESS This value is returned if the controller was + * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned + * if the interrupt coalescence timer may cause SAS compliance issues for SMP + * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE + * This value is returned if the controller does not support the supplied type. + * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the + * controller does not support the supplied initialization data version. + */ +static enum sci_status scic_controller_construct(struct scic_sds_controller *scic, + void __iomem *scu_base, + void __iomem *smu_base) +{ + struct isci_host *ihost = scic_to_ihost(scic); + u8 i; + + sci_base_state_machine_construct(&scic->state_machine, + scic, scic_sds_controller_state_table, + SCI_BASE_CONTROLLER_STATE_INITIAL); + + sci_base_state_machine_start(&scic->state_machine); + + scic->scu_registers = scu_base; + scic->smu_registers = smu_base; + + scic_sds_port_configuration_agent_construct(&scic->port_agent); + + /* Construct the ports for this controller */ + for (i = 0; i < SCI_MAX_PORTS; i++) + scic_sds_port_construct(&ihost->ports[i].sci, i, scic); + scic_sds_port_construct(&ihost->ports[i].sci, SCIC_SDS_DUMMY_PORT, scic); + + /* Construct the phys for this controller */ + for (i = 0; i < SCI_MAX_PHYS; i++) { + /* Add all the PHYs to the dummy port */ + scic_sds_phy_construct(&ihost->phys[i].sci, + &ihost->ports[SCI_MAX_PORTS].sci, i); + } + + scic->invalid_phy_mask = 0; + + /* Set the default maximum values */ + scic->completion_event_entries = SCU_EVENT_COUNT; + scic->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; + scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; + scic->logical_port_entries = SCI_MAX_PORTS; + scic->task_context_entries = SCU_IO_REQUEST_COUNT; + scic->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT; + scic->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT; + + /* Initialize the User and OEM parameters to default values. */ + scic_sds_controller_set_default_config_parameters(scic); + + return scic_controller_reset(scic); +} + +int scic_oem_parameters_validate(struct scic_sds_oem_params *oem) +{ + int i; + + for (i = 0; i < SCI_MAX_PORTS; i++) + if (oem->ports[i].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) + return -EINVAL; + + for (i = 0; i < SCI_MAX_PHYS; i++) + if (oem->phys[i].sas_address.high == 0 && + oem->phys[i].sas_address.low == 0) + return -EINVAL; + + if (oem->controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) { + for (i = 0; i < SCI_MAX_PHYS; i++) + if (oem->ports[i].phy_mask != 0) + return -EINVAL; + } else if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { + u8 phy_mask = 0; + + for (i = 0; i < SCI_MAX_PHYS; i++) + phy_mask |= oem->ports[i].phy_mask; + + if (phy_mask == 0) + return -EINVAL; + } else + return -EINVAL; + + if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT) + return -EINVAL; + + return 0; +} + +static enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic, + union scic_oem_parameters *scic_parms) +{ + u32 state = scic->state_machine.current_state_id; + + if (state == SCI_BASE_CONTROLLER_STATE_RESET || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { + + if (scic_oem_parameters_validate(&scic_parms->sds1)) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + scic->oem_parameters.sds1 = scic_parms->sds1; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_STATE; +} + +void scic_oem_parameters_get( + struct scic_sds_controller *scic, + union scic_oem_parameters *scic_parms) +{ + memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms)); +} + +static void scic_sds_controller_timeout_handler(void *_scic) +{ + struct scic_sds_controller *scic = _scic; + struct isci_host *ihost = scic_to_ihost(scic); + struct sci_base_state_machine *sm = &scic->state_machine; + + if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) + scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT); + else if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STOPPING) { + sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_FAILED); + isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); + } else /* / @todo Now what do we want to do in this case? */ + dev_err(scic_to_dev(scic), + "%s: Controller timer fired when controller was not " + "in a state being timed.\n", + __func__); +} + +static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic) +{ + struct isci_host *ihost = scic_to_ihost(scic); + + scic->phy_startup_timer = isci_timer_create(ihost, + scic, + scic_sds_controller_phy_startup_timeout_handler); + + if (scic->phy_startup_timer == NULL) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + else { + scic->next_phy_to_start = 0; + scic->phy_startup_timer_pending = false; + } + + return SCI_SUCCESS; +} + +static void scic_sds_controller_power_control_timer_start(struct scic_sds_controller *scic) +{ + isci_timer_start(scic->power_control.timer, + SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); + + scic->power_control.timer_started = true; +} + +static void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic) +{ + if (scic->power_control.timer_started) { + isci_timer_stop(scic->power_control.timer); + scic->power_control.timer_started = false; + } +} + +static void scic_sds_controller_power_control_timer_restart(struct scic_sds_controller *scic) +{ + scic_sds_controller_power_control_timer_stop(scic); + scic_sds_controller_power_control_timer_start(scic); +} + +static void scic_sds_controller_power_control_timer_handler( + void *controller) +{ + struct scic_sds_controller *scic; + + scic = (struct scic_sds_controller *)controller; + + scic->power_control.phys_granted_power = 0; + + if (scic->power_control.phys_waiting == 0) { + scic->power_control.timer_started = false; + } else { + struct scic_sds_phy *sci_phy = NULL; + u8 i; + + for (i = 0; + (i < SCI_MAX_PHYS) + && (scic->power_control.phys_waiting != 0); + i++) { + if (scic->power_control.requesters[i] != NULL) { + if (scic->power_control.phys_granted_power < + scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { + sci_phy = scic->power_control.requesters[i]; + scic->power_control.requesters[i] = NULL; + scic->power_control.phys_waiting--; + scic->power_control.phys_granted_power++; + scic_sds_phy_consume_power_handler(sci_phy); + } else { + break; + } + } + } + + /* + * It doesn't matter if the power list is empty, we need to start the + * timer in case another phy becomes ready. + */ + scic_sds_controller_power_control_timer_start(scic); + } +} + +/** + * This method inserts the phy in the stagger spinup control queue. + * @scic: + * + * + */ +void scic_sds_controller_power_control_queue_insert( + struct scic_sds_controller *scic, + struct scic_sds_phy *sci_phy) +{ + BUG_ON(sci_phy == NULL); + + if (scic->power_control.phys_granted_power < + scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { + scic->power_control.phys_granted_power++; + scic_sds_phy_consume_power_handler(sci_phy); + + /* + * stop and start the power_control timer. When the timer fires, the + * no_of_phys_granted_power will be set to 0 + */ + scic_sds_controller_power_control_timer_restart(scic); + } else { + /* Add the phy in the waiting list */ + scic->power_control.requesters[sci_phy->phy_index] = sci_phy; + scic->power_control.phys_waiting++; + } +} + +/** + * This method removes the phy from the stagger spinup control queue. + * @scic: + * + * + */ +void scic_sds_controller_power_control_queue_remove( + struct scic_sds_controller *scic, + struct scic_sds_phy *sci_phy) +{ + BUG_ON(sci_phy == NULL); + + if (scic->power_control.requesters[sci_phy->phy_index] != NULL) { + scic->power_control.phys_waiting--; + } + + scic->power_control.requesters[sci_phy->phy_index] = NULL; +} + +#define AFE_REGISTER_WRITE_DELAY 10 + +/* Initialize the AFE for this phy index. We need to read the AFE setup from + * the OEM parameters + */ +static void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) +{ + const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; + u32 afe_status; + u32 phy_id; + + /* Clear DFX Status registers */ + writel(0x0081000f, &scic->scu_registers->afe.afe_dfx_master_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + + if (is_b0()) { + /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement + * Timer, PM Stagger Timer */ + writel(0x0007BFFF, &scic->scu_registers->afe.afe_pmsn_master_control2); + udelay(AFE_REGISTER_WRITE_DELAY); + } + + /* Configure bias currents to normal */ + if (is_a0()) + writel(0x00005500, &scic->scu_registers->afe.afe_bias_control); + else if (is_a2()) + writel(0x00005A00, &scic->scu_registers->afe.afe_bias_control); + else if (is_b0()) + writel(0x00005F00, &scic->scu_registers->afe.afe_bias_control); + + udelay(AFE_REGISTER_WRITE_DELAY); + + /* Enable PLL */ + if (is_b0()) + writel(0x80040A08, &scic->scu_registers->afe.afe_pll_control0); + else + writel(0x80040908, &scic->scu_registers->afe.afe_pll_control0); + + udelay(AFE_REGISTER_WRITE_DELAY); + + /* Wait for the PLL to lock */ + do { + afe_status = readl(&scic->scu_registers->afe.afe_common_block_status); + udelay(AFE_REGISTER_WRITE_DELAY); + } while ((afe_status & 0x00001000) == 0); + + if (is_a0() || is_a2()) { + /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ + writel(0x7bcc96ad, &scic->scu_registers->afe.afe_pmsn_master_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + } + + for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { + const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id]; + + if (is_b0()) { + /* Configure transmitter SSC parameters */ + writel(0x00030000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); + udelay(AFE_REGISTER_WRITE_DELAY); + } else { + /* + * All defaults, except the Receive Word Alignament/Comma Detect + * Enable....(0xe800) */ + writel(0x00004512, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(0x0050100F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1); + udelay(AFE_REGISTER_WRITE_DELAY); + } + + /* + * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) + * & increase TX int & ext bias 20%....(0xe85c) */ + if (is_a0()) + writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + else if (is_a2()) + writel(0x000003F0, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + else { + /* Power down TX and RX (PWRDNTX and PWRDNRX) */ + writel(0x000003d7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + udelay(AFE_REGISTER_WRITE_DELAY); + + /* + * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) + * & increase TX int & ext bias 20%....(0xe85c) */ + writel(0x000003d4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + } + udelay(AFE_REGISTER_WRITE_DELAY); + + if (is_a0() || is_a2()) { + /* Enable TX equalization (0xe824) */ + writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + udelay(AFE_REGISTER_WRITE_DELAY); + } + + /* + * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On), + * RDD=0x0(RX Detect Enabled) ....(0xe800) */ + writel(0x00004100, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + + /* Leave DFE/FFE on */ + if (is_a0()) + writel(0x3F09983F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + else if (is_a2()) + writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + else { + writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + /* Enable TX equalization (0xe824) */ + writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + } + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(oem_phy->afe_tx_amp_control0, + &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(oem_phy->afe_tx_amp_control1, + &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1); + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(oem_phy->afe_tx_amp_control2, + &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2); + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(oem_phy->afe_tx_amp_control3, + &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3); + udelay(AFE_REGISTER_WRITE_DELAY); + } + + /* Transfer control to the PEs */ + writel(0x00010f00, &scic->scu_registers->afe.afe_dfx_master_control0); + udelay(AFE_REGISTER_WRITE_DELAY); +} + +static enum sci_status scic_controller_set_mode(struct scic_sds_controller *scic, + enum sci_controller_mode operating_mode) +{ + enum sci_status status = SCI_SUCCESS; + + if ((scic->state_machine.current_state_id == + SCI_BASE_CONTROLLER_STATE_INITIALIZING) || + (scic->state_machine.current_state_id == + SCI_BASE_CONTROLLER_STATE_INITIALIZED)) { + switch (operating_mode) { + case SCI_MODE_SPEED: + scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; + scic->task_context_entries = SCU_IO_REQUEST_COUNT; + scic->uf_control.buffers.count = + SCU_UNSOLICITED_FRAME_COUNT; + scic->completion_event_entries = SCU_EVENT_COUNT; + scic->completion_queue_entries = + SCU_COMPLETION_QUEUE_COUNT; + break; + + case SCI_MODE_SIZE: + scic->remote_node_entries = SCI_MIN_REMOTE_DEVICES; + scic->task_context_entries = SCI_MIN_IO_REQUESTS; + scic->uf_control.buffers.count = + SCU_MIN_UNSOLICITED_FRAMES; + scic->completion_event_entries = SCU_MIN_EVENTS; + scic->completion_queue_entries = + SCU_MIN_COMPLETION_QUEUE_ENTRIES; + break; + + default: + status = SCI_FAILURE_INVALID_PARAMETER_VALUE; + break; + } + } else + status = SCI_FAILURE_INVALID_STATE; + + return status; +} + +static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) +{ + struct isci_host *ihost = scic_to_ihost(scic); + scic->power_control.timer = isci_timer_create(ihost, + scic, + scic_sds_controller_power_control_timer_handler); + + memset(scic->power_control.requesters, 0, + sizeof(scic->power_control.requesters)); + + scic->power_control.phys_waiting = 0; + scic->power_control.phys_granted_power = 0; +} + +static enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) +{ + struct sci_base_state_machine *sm = &scic->state_machine; + enum sci_status result = SCI_SUCCESS; + struct isci_host *ihost = scic_to_ihost(scic); + u32 index, state; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_RESET) { + dev_warn(scic_to_dev(scic), + "SCIC Controller initialize operation requested " + "in invalid state\n"); + return SCI_FAILURE_INVALID_STATE; + } + + sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); + + scic->timeout_timer = isci_timer_create(ihost, scic, + scic_sds_controller_timeout_handler); + + scic_sds_controller_initialize_phy_startup(scic); + + scic_sds_controller_initialize_power_control(scic); + + /* + * There is nothing to do here for B0 since we do not have to + * program the AFE registers. + * / @todo The AFE settings are supposed to be correct for the B0 but + * / presently they seem to be wrong. */ + scic_sds_controller_afe_initialization(scic); + + if (result == SCI_SUCCESS) { + u32 status; + u32 terminate_loop; + + /* Take the hardware out of reset */ + writel(0, &scic->smu_registers->soft_reset_control); + + /* + * / @todo Provide meaningfull error code for hardware failure + * result = SCI_FAILURE_CONTROLLER_HARDWARE; */ + result = SCI_FAILURE; + terminate_loop = 100; + + while (terminate_loop-- && (result != SCI_SUCCESS)) { + /* Loop until the hardware reports success */ + udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME); + status = readl(&scic->smu_registers->control_status); + + if ((status & SCU_RAM_INIT_COMPLETED) == + SCU_RAM_INIT_COMPLETED) + result = SCI_SUCCESS; + } + } + + if (result == SCI_SUCCESS) { + u32 max_supported_ports; + u32 max_supported_devices; + u32 max_supported_io_requests; + u32 device_context_capacity; + + /* + * Determine what are the actaul device capacities that the + * hardware will support */ + device_context_capacity = + readl(&scic->smu_registers->device_context_capacity); + + + max_supported_ports = smu_dcc_get_max_ports(device_context_capacity); + max_supported_devices = smu_dcc_get_max_remote_node_context(device_context_capacity); + max_supported_io_requests = smu_dcc_get_max_task_context(device_context_capacity); + + /* + * Make all PEs that are unassigned match up with the + * logical ports + */ + for (index = 0; index < max_supported_ports; index++) { + struct scu_port_task_scheduler_group_registers __iomem + *ptsg = &scic->scu_registers->peg0.ptsg; + + writel(index, &ptsg->protocol_engine[index]); + } + + /* Record the smaller of the two capacity values */ + scic->logical_port_entries = + min(max_supported_ports, scic->logical_port_entries); + + scic->task_context_entries = + min(max_supported_io_requests, + scic->task_context_entries); + + scic->remote_node_entries = + min(max_supported_devices, scic->remote_node_entries); + + /* + * Now that we have the correct hardware reported minimum values + * build the MDL for the controller. Default to a performance + * configuration. + */ + scic_controller_set_mode(scic, SCI_MODE_SPEED); + } + + /* Initialize hardware PCI Relaxed ordering in DMA engines */ + if (result == SCI_SUCCESS) { + u32 dma_configuration; + + /* Configure the payload DMA */ + dma_configuration = + readl(&scic->scu_registers->sdma.pdma_configuration); + dma_configuration |= + SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); + writel(dma_configuration, + &scic->scu_registers->sdma.pdma_configuration); + + /* Configure the control DMA */ + dma_configuration = + readl(&scic->scu_registers->sdma.cdma_configuration); + dma_configuration |= + SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); + writel(dma_configuration, + &scic->scu_registers->sdma.cdma_configuration); + } + + /* + * Initialize the PHYs before the PORTs because the PHY registers + * are accessed during the port initialization. + */ + if (result == SCI_SUCCESS) { + /* Initialize the phys */ + for (index = 0; + (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS); + index++) { + result = scic_sds_phy_initialize( + &ihost->phys[index].sci, + &scic->scu_registers->peg0.pe[index].tl, + &scic->scu_registers->peg0.pe[index].ll); + } + } + + if (result == SCI_SUCCESS) { + /* Initialize the logical ports */ + for (index = 0; + (index < scic->logical_port_entries) && + (result == SCI_SUCCESS); + index++) { + result = scic_sds_port_initialize( + &ihost->ports[index].sci, + &scic->scu_registers->peg0.ptsg.port[index], + &scic->scu_registers->peg0.ptsg.protocol_engine, + &scic->scu_registers->peg0.viit[index]); + } + } + + if (result == SCI_SUCCESS) + result = scic_sds_port_configuration_agent_initialize( + scic, + &scic->port_agent); + + /* Advance the controller state machine */ + if (result == SCI_SUCCESS) + state = SCI_BASE_CONTROLLER_STATE_INITIALIZED; + else + state = SCI_BASE_CONTROLLER_STATE_FAILED; + sci_base_state_machine_change_state(sm, state); + + return result; +} + +static enum sci_status scic_user_parameters_set( + struct scic_sds_controller *scic, + union scic_user_parameters *scic_parms) +{ + u32 state = scic->state_machine.current_state_id; + + if (state == SCI_BASE_CONTROLLER_STATE_RESET || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || + state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { + u16 index; + + /* + * Validate the user parameters. If they are not legal, then + * return a failure. + */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + struct sci_phy_user_params *user_phy; + + user_phy = &scic_parms->sds1.phys[index]; + + if (!((user_phy->max_speed_generation <= + SCIC_SDS_PARM_MAX_SPEED) && + (user_phy->max_speed_generation > + SCIC_SDS_PARM_NO_SPEED))) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + + if (user_phy->in_connection_align_insertion_frequency < + 3) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + + if ((user_phy->in_connection_align_insertion_frequency < + 3) || + (user_phy->align_insertion_frequency == 0) || + (user_phy-> + notify_enable_spin_up_insertion_frequency == + 0)) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + } + + if ((scic_parms->sds1.stp_inactivity_timeout == 0) || + (scic_parms->sds1.ssp_inactivity_timeout == 0) || + (scic_parms->sds1.stp_max_occupancy_timeout == 0) || + (scic_parms->sds1.ssp_max_occupancy_timeout == 0) || + (scic_parms->sds1.no_outbound_task_timeout == 0)) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + + memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms)); + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_STATE; +} + +static int scic_controller_mem_init(struct scic_sds_controller *scic) +{ + struct device *dev = scic_to_dev(scic); + dma_addr_t dma_handle; + enum sci_status result; + + scic->completion_queue = dmam_alloc_coherent(dev, + scic->completion_queue_entries * sizeof(u32), + &dma_handle, GFP_KERNEL); + if (!scic->completion_queue) + return -ENOMEM; + + writel(lower_32_bits(dma_handle), + &scic->smu_registers->completion_queue_lower); + writel(upper_32_bits(dma_handle), + &scic->smu_registers->completion_queue_upper); + + scic->remote_node_context_table = dmam_alloc_coherent(dev, + scic->remote_node_entries * + sizeof(union scu_remote_node_context), + &dma_handle, GFP_KERNEL); + if (!scic->remote_node_context_table) + return -ENOMEM; + + writel(lower_32_bits(dma_handle), + &scic->smu_registers->remote_node_context_lower); + writel(upper_32_bits(dma_handle), + &scic->smu_registers->remote_node_context_upper); + + scic->task_context_table = dmam_alloc_coherent(dev, + scic->task_context_entries * + sizeof(struct scu_task_context), + &dma_handle, GFP_KERNEL); + if (!scic->task_context_table) + return -ENOMEM; + + writel(lower_32_bits(dma_handle), + &scic->smu_registers->host_task_table_lower); + writel(upper_32_bits(dma_handle), + &scic->smu_registers->host_task_table_upper); + + result = scic_sds_unsolicited_frame_control_construct(scic); + if (result) + return result; + + /* + * Inform the silicon as to the location of the UF headers and + * address table. + */ + writel(lower_32_bits(scic->uf_control.headers.physical_address), + &scic->scu_registers->sdma.uf_header_base_address_lower); + writel(upper_32_bits(scic->uf_control.headers.physical_address), + &scic->scu_registers->sdma.uf_header_base_address_upper); + + writel(lower_32_bits(scic->uf_control.address_table.physical_address), + &scic->scu_registers->sdma.uf_address_table_lower); + writel(upper_32_bits(scic->uf_control.address_table.physical_address), + &scic->scu_registers->sdma.uf_address_table_upper); + + return 0; +} + int isci_host_init(struct isci_host *isci_host) { int err = 0, i; @@ -453,3 +2600,625 @@ int isci_host_init(struct isci_host *isci_host) return 0; } + +void scic_sds_controller_link_up(struct scic_sds_controller *scic, + struct scic_sds_port *port, struct scic_sds_phy *phy) +{ + switch (scic->state_machine.current_state_id) { + case SCI_BASE_CONTROLLER_STATE_STARTING: + scic_sds_controller_phy_timer_stop(scic); + scic->port_agent.link_up_handler(scic, &scic->port_agent, + port, phy); + scic_sds_controller_start_next_phy(scic); + break; + case SCI_BASE_CONTROLLER_STATE_READY: + scic->port_agent.link_up_handler(scic, &scic->port_agent, + port, phy); + break; + default: + dev_dbg(scic_to_dev(scic), + "%s: SCIC Controller linkup event from phy %d in " + "unexpected state %d\n", __func__, phy->phy_index, + scic->state_machine.current_state_id); + } +} + +void scic_sds_controller_link_down(struct scic_sds_controller *scic, + struct scic_sds_port *port, struct scic_sds_phy *phy) +{ + switch (scic->state_machine.current_state_id) { + case SCI_BASE_CONTROLLER_STATE_STARTING: + case SCI_BASE_CONTROLLER_STATE_READY: + scic->port_agent.link_down_handler(scic, &scic->port_agent, + port, phy); + break; + default: + dev_dbg(scic_to_dev(scic), + "%s: SCIC Controller linkdown event from phy %d in " + "unexpected state %d\n", + __func__, + phy->phy_index, + scic->state_machine.current_state_id); + } +} + +/** + * This is a helper method to determine if any remote devices on this + * controller are still in the stopping state. + * + */ +static bool scic_sds_controller_has_remote_devices_stopping( + struct scic_sds_controller *controller) +{ + u32 index; + + for (index = 0; index < controller->remote_node_entries; index++) { + if ((controller->device_table[index] != NULL) && + (controller->device_table[index]->state_machine.current_state_id + == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING)) + return true; + } + + return false; +} + +/** + * This method is called by the remote device to inform the controller + * object that the remote device has stopped. + */ +void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev) +{ + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_STOPPING) { + dev_dbg(scic_to_dev(scic), + "SCIC Controller 0x%p remote device stopped event " + "from device 0x%p in unexpected state %d\n", + scic, sci_dev, + scic->state_machine.current_state_id); + return; + } + + if (!scic_sds_controller_has_remote_devices_stopping(scic)) { + sci_base_state_machine_change_state(&scic->state_machine, + SCI_BASE_CONTROLLER_STATE_STOPPED); + } +} + +/** + * This method will write to the SCU PCP register the request value. The method + * is used to suspend/resume ports, devices, and phys. + * @scic: + * + * + */ +void scic_sds_controller_post_request( + struct scic_sds_controller *scic, + u32 request) +{ + dev_dbg(scic_to_dev(scic), + "%s: SCIC Controller 0x%p post request 0x%08x\n", + __func__, + scic, + request); + + writel(request, &scic->smu_registers->post_context_port); +} + +/** + * This method will copy the soft copy of the task context into the physical + * memory accessible by the controller. + * @scic: This parameter specifies the controller for which to copy + * the task context. + * @sci_req: This parameter specifies the request for which the task + * context is being copied. + * + * After this call is made the SCIC_SDS_IO_REQUEST object will always point to + * the physical memory version of the task context. Thus, all subsequent + * updates to the task context are performed in the TC table (i.e. DMAable + * memory). none + */ +void scic_sds_controller_copy_task_context( + struct scic_sds_controller *scic, + struct scic_sds_request *sci_req) +{ + struct scu_task_context *task_context_buffer; + + task_context_buffer = scic_sds_controller_get_task_context_buffer( + scic, sci_req->io_tag); + + memcpy(task_context_buffer, + sci_req->task_context_buffer, + offsetof(struct scu_task_context, sgl_snapshot_ac)); + + /* + * Now that the soft copy of the TC has been copied into the TC + * table accessible by the silicon. Thus, any further changes to + * the TC (e.g. TC termination) occur in the appropriate location. */ + sci_req->task_context_buffer = task_context_buffer; +} + +/** + * This method returns the task context buffer for the given io tag. + * @scic: + * @io_tag: + * + * struct scu_task_context* + */ +struct scu_task_context *scic_sds_controller_get_task_context_buffer( + struct scic_sds_controller *scic, + u16 io_tag + ) { + u16 task_index = scic_sds_io_tag_get_index(io_tag); + + if (task_index < scic->task_context_entries) { + return &scic->task_context_table[task_index]; + } + + return NULL; +} + +struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, + u16 io_tag) +{ + u16 task_index; + u16 task_sequence; + + task_index = scic_sds_io_tag_get_index(io_tag); + + if (task_index < scic->task_context_entries) { + if (scic->io_request_table[task_index] != NULL) { + task_sequence = scic_sds_io_tag_get_sequence(io_tag); + + if (task_sequence == scic->io_request_sequence[task_index]) { + return scic->io_request_table[task_index]; + } + } + } + + return NULL; +} + +/** + * This method allocates remote node index and the reserves the remote node + * context space for use. This method can fail if there are no more remote + * node index available. + * @scic: This is the controller object which contains the set of + * free remote node ids + * @sci_dev: This is the device object which is requesting the a remote node + * id + * @node_id: This is the remote node id that is assinged to the device if one + * is available + * + * enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote + * node index available. + */ +enum sci_status scic_sds_controller_allocate_remote_node_context( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 *node_id) +{ + u16 node_index; + u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev); + + node_index = scic_sds_remote_node_table_allocate_remote_node( + &scic->available_remote_nodes, remote_node_count + ); + + if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { + scic->device_table[node_index] = sci_dev; + + *node_id = node_index; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INSUFFICIENT_RESOURCES; +} + +/** + * This method frees the remote node index back to the available pool. Once + * this is done the remote node context buffer is no longer valid and can + * not be used. + * @scic: + * @sci_dev: + * @node_id: + * + */ +void scic_sds_controller_free_remote_node_context( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 node_id) +{ + u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev); + + if (scic->device_table[node_id] == sci_dev) { + scic->device_table[node_id] = NULL; + + scic_sds_remote_node_table_release_remote_node_index( + &scic->available_remote_nodes, remote_node_count, node_id + ); + } +} + +/** + * This method returns the union scu_remote_node_context for the specified remote + * node id. + * @scic: + * @node_id: + * + * union scu_remote_node_context* + */ +union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( + struct scic_sds_controller *scic, + u16 node_id + ) { + if ( + (node_id < scic->remote_node_entries) + && (scic->device_table[node_id] != NULL) + ) { + return &scic->remote_node_context_table[node_id]; + } + + return NULL; +} + +/** + * + * @resposne_buffer: This is the buffer into which the D2H register FIS will be + * constructed. + * @frame_header: This is the frame header returned by the hardware. + * @frame_buffer: This is the frame buffer returned by the hardware. + * + * This method will combind the frame header and frame buffer to create a SATA + * D2H register FIS none + */ +void scic_sds_controller_copy_sata_response( + void *response_buffer, + void *frame_header, + void *frame_buffer) +{ + memcpy(response_buffer, frame_header, sizeof(u32)); + + memcpy(response_buffer + sizeof(u32), + frame_buffer, + sizeof(struct dev_to_host_fis) - sizeof(u32)); +} + +/** + * This method releases the frame once this is done the frame is available for + * re-use by the hardware. The data contained in the frame header and frame + * buffer is no longer valid. The UF queue get pointer is only updated if UF + * control indicates this is appropriate. + * @scic: + * @frame_index: + * + */ +void scic_sds_controller_release_frame( + struct scic_sds_controller *scic, + u32 frame_index) +{ + if (scic_sds_unsolicited_frame_control_release_frame( + &scic->uf_control, frame_index) == true) + writel(scic->uf_control.get, + &scic->scu_registers->sdma.unsolicited_frame_get_pointer); +} + +/** + * scic_controller_start_io() - This method is called by the SCI user to + * send/start an IO request. If the method invocation is successful, then + * the IO request has been queued to the hardware for processing. + * @controller: the handle to the controller object for which to start an IO + * request. + * @remote_device: the handle to the remote device object for which to start an + * IO request. + * @io_request: the handle to the io request object to start. + * @io_tag: This parameter specifies a previously allocated IO tag that the + * user desires to be utilized for this request. This parameter is optional. + * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value + * for this parameter. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a + * result, it is expected the user will have set the NCQ tag field in the host + * to device register FIS prior to calling this method. There is also a + * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking + * the scic_controller_start_io() method. scic_controller_allocate_tag() for + * more information on allocating a tag. Indicate if the controller + * successfully started the IO request. SCI_SUCCESS if the IO request was + * successfully started. Determine the failure situations and return values. + */ +enum sci_status scic_controller_start_io( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *rdev, + struct scic_sds_request *req, + u16 io_tag) +{ + enum sci_status status; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { + dev_warn(scic_to_dev(scic), "invalid state to start I/O"); + return SCI_FAILURE_INVALID_STATE; + } + + status = scic_sds_remote_device_start_io(scic, rdev, req); + if (status != SCI_SUCCESS) + return status; + + scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; + scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); + return SCI_SUCCESS; +} + +/** + * scic_controller_terminate_request() - This method is called by the SCI Core + * user to terminate an ongoing (i.e. started) core IO request. This does + * not abort the IO request at the target, but rather removes the IO request + * from the host controller. + * @controller: the handle to the controller object for which to terminate a + * request. + * @remote_device: the handle to the remote device object for which to + * terminate a request. + * @request: the handle to the io or task management request object to + * terminate. + * + * Indicate if the controller successfully began the terminate process for the + * IO request. SCI_SUCCESS if the terminate process was successfully started + * for the request. Determine the failure situations and return values. + */ +enum sci_status scic_controller_terminate_request( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *rdev, + struct scic_sds_request *req) +{ + enum sci_status status; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { + dev_warn(scic_to_dev(scic), + "invalid state to terminate request\n"); + return SCI_FAILURE_INVALID_STATE; + } + + status = scic_sds_io_request_terminate(req); + if (status != SCI_SUCCESS) + return status; + + /* + * Utilize the original post context command and or in the POST_TC_ABORT + * request sub-type. + */ + scic_sds_controller_post_request(scic, + scic_sds_request_get_post_context(req) | + SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); + return SCI_SUCCESS; +} + +/** + * scic_controller_complete_io() - This method will perform core specific + * completion operations for an IO request. After this method is invoked, + * the user should consider the IO request as invalid until it is properly + * reused (i.e. re-constructed). + * @controller: The handle to the controller object for which to complete the + * IO request. + * @remote_device: The handle to the remote device object for which to complete + * the IO request. + * @io_request: the handle to the io request object to complete. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI + * Core user, using the scic_controller_allocate_io_tag() method, then it is + * the responsibility of the caller to invoke the scic_controller_free_io_tag() + * method to free the tag (i.e. this method will not free the IO tag). Indicate + * if the controller successfully completed the IO request. SCI_SUCCESS if the + * completion process was successful. + */ +enum sci_status scic_controller_complete_io( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *rdev, + struct scic_sds_request *request) +{ + enum sci_status status; + u16 index; + + switch (scic->state_machine.current_state_id) { + case SCI_BASE_CONTROLLER_STATE_STOPPING: + /* XXX: Implement this function */ + return SCI_FAILURE; + case SCI_BASE_CONTROLLER_STATE_READY: + status = scic_sds_remote_device_complete_io(scic, rdev, request); + if (status != SCI_SUCCESS) + return status; + + index = scic_sds_io_tag_get_index(request->io_tag); + scic->io_request_table[index] = NULL; + return SCI_SUCCESS; + default: + dev_warn(scic_to_dev(scic), "invalid state to complete I/O"); + return SCI_FAILURE_INVALID_STATE; + } + +} + +enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { + dev_warn(scic_to_dev(scic), "invalid state to continue I/O"); + return SCI_FAILURE_INVALID_STATE; + } + + scic->io_request_table[scic_sds_io_tag_get_index(sci_req->io_tag)] = sci_req; + scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req)); + return SCI_SUCCESS; +} + +/** + * scic_controller_start_task() - This method is called by the SCIC user to + * send/start a framework task management request. + * @controller: the handle to the controller object for which to start the task + * management request. + * @remote_device: the handle to the remote device object for which to start + * the task management request. + * @task_request: the handle to the task request object to start. + * @io_tag: This parameter specifies a previously allocated IO tag that the + * user desires to be utilized for this request. Note this not the io_tag + * of the request being managed. It is to be utilized for the task request + * itself. This parameter is optional. The user is allowed to supply + * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - The user must synchronize this task with completion + * queue processing. If they are not synchronized then it is possible for the + * io requests that are being managed by the task request can complete before + * starting the task request. scic_controller_allocate_tag() for more + * information on allocating a tag. Indicate if the controller successfully + * started the IO request. SCI_TASK_SUCCESS if the task request was + * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is + * returned if there is/are task(s) outstanding that require termination or + * completion before this request can succeed. + */ +enum sci_task_status scic_controller_start_task( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *rdev, + struct scic_sds_request *req, + u16 task_tag) +{ + enum sci_status status; + + if (scic->state_machine.current_state_id != + SCI_BASE_CONTROLLER_STATE_READY) { + dev_warn(scic_to_dev(scic), + "%s: SCIC Controller starting task from invalid " + "state\n", + __func__); + return SCI_TASK_FAILURE_INVALID_STATE; + } + + status = scic_sds_remote_device_start_task(scic, rdev, req); + switch (status) { + case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: + scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; + + /* + * We will let framework know this task request started successfully, + * although core is still woring on starting the request (to post tc when + * RNC is resumed.) + */ + return SCI_SUCCESS; + case SCI_SUCCESS: + scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; + + scic_sds_controller_post_request(scic, + scic_sds_request_get_post_context(req)); + break; + default: + break; + } + + return status; +} + +/** + * scic_controller_allocate_io_tag() - This method will allocate a tag from the + * pool of free IO tags. Direct allocation of IO tags by the SCI Core user + * is optional. The scic_controller_start_io() method will allocate an IO + * tag if this method is not utilized and the tag is not supplied to the IO + * construct routine. Direct allocation of IO tags may provide additional + * performance improvements in environments capable of supporting this usage + * model. Additionally, direct allocation of IO tags also provides + * additional flexibility to the SCI Core user. Specifically, the user may + * retain IO tags across the lives of multiple IO requests. + * @controller: the handle to the controller object for which to allocate the + * tag. + * + * IO tags are a protected resource. It is incumbent upon the SCI Core user to + * ensure that each of the methods that may allocate or free available IO tags + * are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). An unsigned integer representing an available IO tag. + * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no + * currently available tags to be allocated. All return other values indicate a + * legitimate tag. + */ +u16 scic_controller_allocate_io_tag( + struct scic_sds_controller *scic) +{ + u16 task_context; + u16 sequence_count; + + if (!sci_pool_empty(scic->tci_pool)) { + sci_pool_get(scic->tci_pool, task_context); + + sequence_count = scic->io_request_sequence[task_context]; + + return scic_sds_io_tag_construct(sequence_count, task_context); + } + + return SCI_CONTROLLER_INVALID_IO_TAG; +} + +/** + * scic_controller_free_io_tag() - This method will free an IO tag to the pool + * of free IO tags. This method provides the SCI Core user more flexibility + * with regards to IO tags. The user may desire to keep an IO tag after an + * IO request has completed, because they plan on re-using the tag for a + * subsequent IO request. This method is only legal if the tag was + * allocated via scic_controller_allocate_io_tag(). + * @controller: This parameter specifies the handle to the controller object + * for which to free/return the tag. + * @io_tag: This parameter represents the tag to be freed to the pool of + * available tags. + * + * - IO tags are a protected resource. It is incumbent upon the SCI Core user + * to ensure that each of the methods that may allocate or free available IO + * tags are handled in a mutually exclusive manner. This method is one of said + * methods requiring proper critical code section protection (e.g. semaphore, + * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI + * Core user, using the scic_controller_allocate_io_tag() method, then it is + * the responsibility of the caller to invoke this method to free the tag. This + * method returns an indication of whether the tag was successfully put back + * (freed) to the pool of available tags. SCI_SUCCESS This return value + * indicates the tag was successfully placed into the pool of available IO + * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag + * is not a valid IO tag value. + */ +enum sci_status scic_controller_free_io_tag( + struct scic_sds_controller *scic, + u16 io_tag) +{ + u16 sequence; + u16 index; + + BUG_ON(io_tag == SCI_CONTROLLER_INVALID_IO_TAG); + + sequence = scic_sds_io_tag_get_sequence(io_tag); + index = scic_sds_io_tag_get_index(io_tag); + + if (!sci_pool_full(scic->tci_pool)) { + if (sequence == scic->io_request_sequence[index]) { + scic_sds_io_sequence_increment( + scic->io_request_sequence[index]); + + sci_pool_put(scic->tci_pool, index); + + return SCI_SUCCESS; + } + } + + return SCI_FAILURE_INVALID_IO_TAG; +} + + diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 13c1c99ef294..1f542c47fb3a 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -52,13 +52,258 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #ifndef _SCI_HOST_H_ #define _SCI_HOST_H_ -#include "scic_sds_controller.h" +#include "scic_config_parameters.h" #include "remote_device.h" #include "phy.h" +#include "pool.h" +#include "sci_base_state_machine.h" +#include "remote_node_table.h" +#include "scu_registers.h" +#include "scu_unsolicited_frame.h" +#include "scic_sds_unsolicited_frame_control.h" +#include "scic_sds_port_configuration_agent.h" + +struct scic_sds_request; +struct scu_task_context; + +/** + * struct scic_power_control - + * + * This structure defines the fields for managing power control for direct + * attached disk devices. + */ +struct scic_power_control { + /** + * This field is set when the power control timer is running and cleared when + * it is not. + */ + bool timer_started; + + /** + * This field is the handle to the driver timer object. This timer is used to + * control when the directed attached disks can consume power. + */ + void *timer; + + /** + * This field is used to keep track of how many phys are put into the + * requesters field. + */ + u8 phys_waiting; + + /** + * This field is used to keep track of how many phys have been granted to consume power + */ + u8 phys_granted_power; + + /** + * This field is an array of phys that we are waiting on. The phys are direct + * mapped into requesters via struct scic_sds_phy.phy_index + */ + struct scic_sds_phy *requesters[SCI_MAX_PHYS]; + +}; + +/** + * struct scic_sds_controller - + * + * This structure represents the SCU controller object. + */ +struct scic_sds_controller { + /** + * This field contains the information for the base controller state + * machine. + */ + struct sci_base_state_machine state_machine; + + /** + * This field is the driver timer object handler used to time the controller + * object start and stop requests. + */ + void *timeout_timer; + + /** + * This field contains the user parameters to be utilized for this + * core controller object. + */ + union scic_user_parameters user_parameters; + + /** + * This field contains the OEM parameters to be utilized for this + * core controller object. + */ + union scic_oem_parameters oem_parameters; + + /** + * This field contains the port configuration agent for this controller. + */ + struct scic_sds_port_configuration_agent port_agent; + + /** + * This field is the array of device objects that are currently constructed + * for this controller object. This table is used as a fast lookup of device + * objects that need to handle device completion notifications from the + * hardware. The table is RNi based. + */ + struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; + + /** + * This field is the array of IO request objects that are currently active for + * this controller object. This table is used as a fast lookup of the io + * request object that need to handle completion queue notifications. The + * table is TCi based. + */ + struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS]; + + /** + * This field is the free RNi data structure + */ + struct scic_remote_node_table available_remote_nodes; + + /** + * This field is the TCi pool used to manage the task context index. + */ + SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS); + + /** + * This filed is the struct scic_power_control data used to controll when direct + * attached devices can consume power. + */ + struct scic_power_control power_control; + + /** + * This field is the array of sequence values for the IO Tag fields. Even + * though only 4 bits of the field is used for the sequence the sequence is 16 + * bits in size so the sequence can be bitwise or'd with the TCi to build the + * IO Tag value. + */ + u16 io_request_sequence[SCI_MAX_IO_REQUESTS]; + + /** + * This field in the array of sequence values for the RNi. These are used + * to control io request build to io request start operations. The sequence + * value is recorded into an io request when it is built and is checked on + * the io request start operation to make sure that there was not a device + * hot plug between the build and start operation. + */ + u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES]; + + /** + * This field is a pointer to the memory allocated by the driver for the task + * context table. This data is shared between the hardware and software. + */ + struct scu_task_context *task_context_table; + + /** + * This field is a pointer to the memory allocated by the driver for the + * remote node context table. This table is shared between the hardware and + * software. + */ + union scu_remote_node_context *remote_node_context_table; + + /** + * This field is a pointer to the completion queue. This memory is + * written to by the hardware and read by the software. + */ + u32 *completion_queue; + + /** + * This field is the software copy of the completion queue get pointer. The + * controller object writes this value to the hardware after processing the + * completion entries. + */ + u32 completion_queue_get; + + /** + * This field is the minimum of the number of hardware supported port entries + * and the software requested port entries. + */ + u32 logical_port_entries; + + /** + * This field is the minimum number of hardware supported completion queue + * entries and the software requested completion queue entries. + */ + u32 completion_queue_entries; + + /** + * This field is the minimum number of hardware supported event entries and + * the software requested event entries. + */ + u32 completion_event_entries; + + /** + * This field is the minimum number of devices supported by the hardware and + * the number of devices requested by the software. + */ + u32 remote_node_entries; + + /** + * This field is the minimum number of IO requests supported by the hardware + * and the number of IO requests requested by the software. + */ + u32 task_context_entries; + + /** + * This object contains all of the unsolicited frame specific + * data utilized by the core controller. + */ + struct scic_sds_unsolicited_frame_control uf_control; + + /* Phy Startup Data */ + /** + * This field is the driver timer handle for controller phy request startup. + * On controller start the controller will start each PHY individually in + * order of phy index. + */ + void *phy_startup_timer; + + /** + * This field is set when the phy_startup_timer is running and is cleared when + * the phy_startup_timer is stopped. + */ + bool phy_startup_timer_pending; + + /** + * This field is the index of the next phy start. It is initialized to 0 and + * increments for each phy index that is started. + */ + u32 next_phy_to_start; + + /** + * This field controlls the invalid link up notifications to the SCI_USER. If + * an invalid_link_up notification is reported a bit for the PHY index is set + * so further notifications are not made. Once the PHY object reports link up + * and is made part of a port then this bit for the PHY index is cleared. + */ + u8 invalid_phy_mask; + + /* + * This field saves the current interrupt coalescing number of the controller. + */ + u16 interrupt_coalesce_number; + + /* + * This field saves the current interrupt coalescing timeout value in microseconds. + */ + u32 interrupt_coalesce_timeout; + + /** + * This field is a pointer to the memory mapped register space for the + * struct smu_registers. + */ + struct smu_registers __iomem *smu_registers; + + /** + * This field is a pointer to the memory mapped register space for the + * struct scu_registers. + */ + struct scu_registers __iomem *scu_registers; + +}; struct isci_host { struct scic_sds_controller sci; @@ -92,6 +337,96 @@ struct isci_host { struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES]; }; +/** + * enum scic_sds_controller_states - This enumeration depicts all the states + * for the common controller state machine. + */ +enum scic_sds_controller_states { + /** + * Simply the initial state for the base controller state machine. + */ + SCI_BASE_CONTROLLER_STATE_INITIAL = 0, + + /** + * This state indicates that the controller is reset. The memory for + * the controller is in it's initial state, but the controller requires + * initialization. + * This state is entered from the INITIAL state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_CONTROLLER_STATE_RESET, + + /** + * This state is typically an action state that indicates the controller + * is in the process of initialization. In this state no new IO operations + * are permitted. + * This state is entered from the RESET state. + */ + SCI_BASE_CONTROLLER_STATE_INITIALIZING, + + /** + * This state indicates that the controller has been successfully + * initialized. In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + */ + SCI_BASE_CONTROLLER_STATE_INITIALIZED, + + /** + * This state indicates the the controller is in the process of becoming + * ready (i.e. starting). In this state no new IO operations are permitted. + * This state is entered from the INITIALIZED state. + */ + SCI_BASE_CONTROLLER_STATE_STARTING, + + /** + * This state indicates the controller is now ready. Thus, the user + * is able to perform IO operations on the controller. + * This state is entered from the STARTING state. + */ + SCI_BASE_CONTROLLER_STATE_READY, + + /** + * This state is typically an action state that indicates the controller + * is in the process of resetting. Thus, the user is unable to perform + * IO operations on the controller. A reset is considered destructive in + * most cases. + * This state is entered from the READY state. + * This state is entered from the FAILED state. + * This state is entered from the STOPPED state. + */ + SCI_BASE_CONTROLLER_STATE_RESETTING, + + /** + * This state indicates that the controller is in the process of stopping. + * In this state no new IO operations are permitted, but existing IO + * operations are allowed to complete. + * This state is entered from the READY state. + */ + SCI_BASE_CONTROLLER_STATE_STOPPING, + + /** + * This state indicates that the controller has successfully been stopped. + * In this state no new IO operations are permitted. + * This state is entered from the STOPPING state. + */ + SCI_BASE_CONTROLLER_STATE_STOPPED, + + /** + * This state indicates that the controller could not successfully be + * initialized. In this state no new IO operations are permitted. + * This state is entered from the INITIALIZING state. + * This state is entered from the STARTING state. + * This state is entered from the STOPPING state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_CONTROLLER_STATE_FAILED, + + SCI_BASE_CONTROLLER_MAX_STATES + +}; + + + /** * struct isci_pci_info - This class represents the pci function containing the * controllers. Depending on PCI SKU, there could be up to 2 controllers in @@ -115,17 +450,13 @@ static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev) id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \ ihost = to_pci_info(pdev)->hosts[++id]) -static inline -enum isci_status isci_host_get_state( - struct isci_host *isci_host) +static inline enum isci_status isci_host_get_state(struct isci_host *isci_host) { return isci_host->status; } - -static inline void isci_host_change_state( - struct isci_host *isci_host, - enum isci_status status) +static inline void isci_host_change_state(struct isci_host *isci_host, + enum isci_status status) { unsigned long flags; @@ -140,9 +471,7 @@ static inline void isci_host_change_state( } -static inline int isci_host_can_queue( - struct isci_host *isci_host, - int num) +static inline int isci_host_can_queue(struct isci_host *isci_host, int num) { int ret = 0; unsigned long flags; @@ -163,9 +492,7 @@ static inline int isci_host_can_queue( return ret; } -static inline void isci_host_can_dequeue( - struct isci_host *isci_host, - int num) +static inline void isci_host_can_dequeue(struct isci_host *isci_host, int num) { unsigned long flags; @@ -208,39 +535,219 @@ static inline struct isci_host *scic_to_ihost(struct scic_sds_controller *scic) } /** - * isci_host_scan_finished() - + * INCREMENT_QUEUE_GET() - * - * This function is one of the SCSI Host Template functions. The SCSI midlayer - * calls this function during a target scan, approx. once every 10 millisecs. + * This macro will increment the specified index to and if the index wraps to 0 + * it will toggel the cycle bit. */ -int isci_host_scan_finished( - struct Scsi_Host *, - unsigned long); +#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \ + { \ + if ((index) + 1 == entry_count) { \ + (index) = 0; \ + (cycle) = (cycle) ^ (bit_toggle); \ + } else { \ + index = index + 1; \ + } \ + } +/** + * scic_sds_controller_get_port_configuration_agent() - + * + * This is a helper macro to get the port configuration agent from the + * controller object. + */ +#define scic_sds_controller_get_port_configuration_agent(controller) \ + (&(controller)->port_agent) /** - * isci_host_scan_start() - + * scic_sds_controller_get_protocol_engine_group() - * - * This function is one of the SCSI Host Template function, called by the SCSI - * mid layer berfore a target scan begins. The core library controller start - * routine is called from here. + * This macro returns the protocol engine group for this controller object. + * Presently we only support protocol engine group 0 so just return that */ -void isci_host_scan_start( - struct Scsi_Host *); +#define scic_sds_controller_get_protocol_engine_group(controller) 0 /** - * isci_host_start_complete() - + * scic_sds_io_tag_construct() - * - * This function is called by the core library, through the ISCI Module, to - * indicate controller start status. + * This macro constructs an IO tag from the sequence and index values. */ -void isci_host_start_complete( - struct isci_host *, - enum sci_status); +#define scic_sds_io_tag_construct(sequence, task_index) \ + ((sequence) << 12 | (task_index)) -void isci_host_stop_complete( - struct isci_host *isci_host, - enum sci_status completion_status); +/** + * scic_sds_io_tag_get_sequence() - + * + * This macro returns the IO sequence from the IO tag value. + */ +#define scic_sds_io_tag_get_sequence(io_tag) \ + (((io_tag) & 0xF000) >> 12) + +/** + * scic_sds_io_tag_get_index() - + * + * This macro returns the TCi from the io tag value + */ +#define scic_sds_io_tag_get_index(io_tag) \ + ((io_tag) & 0x0FFF) + +/** + * scic_sds_io_sequence_increment() - + * + * This is a helper macro to increment the io sequence count. We may find in + * the future that it will be faster to store the sequence count in such a way + * as we dont perform the shift operation to build io tag values so therefore + * need a way to incrment them correctly + */ +#define scic_sds_io_sequence_increment(value) \ + ((value) = (((value) + 1) & 0x000F)) + +/* expander attached sata devices require 3 rnc slots */ +static inline int scic_sds_remote_device_node_count(struct scic_sds_remote_device *sci_dev) +{ + struct domain_device *dev = sci_dev_to_domain(sci_dev); + + if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) && + !sci_dev->is_direct_attached) + return SCU_STP_REMOTE_NODE_COUNT; + return SCU_SSP_REMOTE_NODE_COUNT; +} + +/** + * scic_sds_controller_set_invalid_phy() - + * + * This macro will set the bit in the invalid phy mask for this controller + * object. This is used to control messages reported for invalid link up + * notifications. + */ +#define scic_sds_controller_set_invalid_phy(controller, phy) \ + ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index)) + +/** + * scic_sds_controller_clear_invalid_phy() - + * + * This macro will clear the bit in the invalid phy mask for this controller + * object. This is used to control messages reported for invalid link up + * notifications. + */ +#define scic_sds_controller_clear_invalid_phy(controller, phy) \ + ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) + +static inline struct device *scic_to_dev(struct scic_sds_controller *scic) +{ + return &scic_to_ihost(scic)->pdev->dev; +} + +static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) +{ + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host) + return NULL; + + return &iphy->isci_port->isci_host->pdev->dev; +} + +static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port) +{ + struct isci_port *iport = sci_port_to_iport(sci_port); + + if (!iport || !iport->isci_host) + return NULL; + + return &iport->isci_host->pdev->dev; +} + +static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev) +{ + struct isci_remote_device *idev = + container_of(sci_dev, typeof(*idev), sci); + + if (!idev || !idev->isci_port || !idev->isci_port->isci_host) + return NULL; + + return &idev->isci_port->isci_host->pdev->dev; +} + +enum { + ISCI_SI_REVA0, + ISCI_SI_REVA2, + ISCI_SI_REVB0, +}; + +extern int isci_si_rev; + +static inline bool is_a0(void) +{ + return isci_si_rev == ISCI_SI_REVA0; +} + +static inline bool is_a2(void) +{ + return isci_si_rev == ISCI_SI_REVA2; +} + +static inline bool is_b0(void) +{ + return isci_si_rev > ISCI_SI_REVA2; +} + +void scic_sds_controller_post_request(struct scic_sds_controller *scic, + u32 request); +void scic_sds_controller_release_frame(struct scic_sds_controller *scic, + u32 frame_index); +void scic_sds_controller_copy_sata_response(void *response_buffer, + void *frame_header, + void *frame_buffer); +enum sci_status scic_sds_controller_allocate_remote_node_context(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 *node_id); +void scic_sds_controller_free_remote_node_context( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 node_id); +union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( + struct scic_sds_controller *scic, + u16 node_id); + +struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, + u16 io_tag); + +struct scu_task_context *scic_sds_controller_get_task_context_buffer( + struct scic_sds_controller *scic, + u16 io_tag); + +void scic_sds_controller_power_control_queue_insert( + struct scic_sds_controller *scic, + struct scic_sds_phy *sci_phy); + +void scic_sds_controller_power_control_queue_remove( + struct scic_sds_controller *scic, + struct scic_sds_phy *sci_phy); + +void scic_sds_controller_link_up( + struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +void scic_sds_controller_link_down( + struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +void scic_sds_controller_remote_device_stopped( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev); + +void scic_sds_controller_copy_task_context( + struct scic_sds_controller *scic, + struct scic_sds_request *this_request); + +void scic_sds_controller_register_setup(struct scic_sds_controller *scic); + +enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req); +int isci_host_scan_finished(struct Scsi_Host *, unsigned long); +void isci_host_scan_start(struct Scsi_Host *); int isci_host_init(struct isci_host *); @@ -262,4 +769,35 @@ void isci_host_remote_device_start_complete( struct isci_remote_device *, enum sci_status); -#endif /* !defined(_SCI_HOST_H_) */ +void scic_controller_disable_interrupts( + struct scic_sds_controller *scic); + +enum sci_status scic_controller_start_io( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *io_request, + u16 io_tag); + +enum sci_task_status scic_controller_start_task( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *task_request, + u16 io_tag); + +enum sci_status scic_controller_terminate_request( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *request); + +enum sci_status scic_controller_complete_io( + struct scic_sds_controller *scic, + struct scic_sds_remote_device *remote_device, + struct scic_sds_request *io_request); + +u16 scic_controller_allocate_io_tag( + struct scic_sds_controller *scic); + +enum sci_status scic_controller_free_io_tag( + struct scic_sds_controller *scic, + u16 io_tag); +#endif diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index df132c07badf..bda701655b25 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -61,9 +61,7 @@ #include #include "isci.h" #include "task.h" -#include "sci_environment.h" #include "probe_roms.h" -#include "scic_controller.h" static struct scsi_transport_template *isci_transport_template; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 800f2332ecd0..d288897b85fb 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -532,10 +532,4 @@ extern unsigned char max_concurr_spinup; irqreturn_t isci_msix_isr(int vec, void *data); irqreturn_t isci_intx_isr(int vec, void *data); irqreturn_t isci_error_isr(int vec, void *data); - -struct scic_sds_controller; -bool scic_sds_controller_isr(struct scic_sds_controller *scic); -void scic_sds_controller_completion_handler(struct scic_sds_controller *scic); -bool scic_sds_controller_error_isr(struct scic_sds_controller *scic); -void scic_sds_controller_error_handler(struct scic_sds_controller *scic); #endif /* __ISCI_H__ */ diff --git a/drivers/scsi/isci/pool.h b/drivers/scsi/isci/pool.h new file mode 100644 index 000000000000..016ec832f74f --- /dev/null +++ b/drivers/scsi/isci/pool.h @@ -0,0 +1,199 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains the interface to the pool class. This class allows two + * different two different priority tasks to insert and remove items from + * the free pool. The user of the pool is expected to evaluate the pool + * condition empty before a get operation and pool condition full before a + * put operation. Methods Provided: - sci_pool_create() - + * sci_pool_initialize() - sci_pool_empty() - sci_pool_full() - + * sci_pool_get() - sci_pool_put() + * + * + */ + +#ifndef _SCI_POOL_H_ +#define _SCI_POOL_H_ + +/** + * SCI_POOL_INCREMENT() - + * + * Private operation for the pool + */ +#define SCI_POOL_INCREMENT(pool, index) \ + (((index) + 1) == (pool).size ? 0 : (index) + 1) + +/** + * SCI_POOL_CREATE() - + * + * This creates a pool structure of pool_name. The members in the pool are of + * type with number of elements equal to size. + */ +#define SCI_POOL_CREATE(pool_name, type, pool_size) \ + struct \ + { \ + u32 size; \ + u32 get; \ + u32 put; \ + type array[(pool_size) + 1]; \ + } pool_name + + +/** + * sci_pool_empty() - + * + * This macro evaluates the pool and returns true if the pool is empty. If the + * pool is empty the user should not perform any get operation on the pool. + */ +#define sci_pool_empty(pool) \ + ((pool).get == (pool).put) + +/** + * sci_pool_full() - + * + * This macro evaluates the pool and returns true if the pool is full. If the + * pool is full the user should not perform any put operation. + */ +#define sci_pool_full(pool) \ + (SCI_POOL_INCREMENT(pool, (pool).put) == (pool).get) + +/** + * sci_pool_size() - + * + * This macro returns the size of the pool created. The internal size of the + * pool is actually 1 larger then necessary in order to ensure get and put + * pointers can be written simultaneously by different users. As a result, + * this macro subtracts 1 from the internal size + */ +#define sci_pool_size(pool) \ + ((pool).size - 1) + +/** + * sci_pool_count() - + * + * This macro indicates the number of elements currently contained in the pool. + */ +#define sci_pool_count(pool) \ + (\ + sci_pool_empty((pool)) \ + ? 0 \ + : (\ + sci_pool_full((pool)) \ + ? sci_pool_size((pool)) \ + : (\ + (pool).get > (pool).put \ + ? ((pool).size - (pool).get + (pool).put) \ + : ((pool).put - (pool).get) \ + ) \ + ) \ + ) + +/** + * sci_pool_initialize() - + * + * This macro initializes the pool to an empty condition. + */ +#define sci_pool_initialize(pool) \ + { \ + (pool).size = (sizeof((pool).array) / sizeof((pool).array[0])); \ + (pool).get = 0; \ + (pool).put = 0; \ + } + +/** + * sci_pool_get() - + * + * This macro will get the next free element from the pool. This should only be + * called if the pool is not empty. + */ +#define sci_pool_get(pool, my_value) \ + { \ + (my_value) = (pool).array[(pool).get]; \ + (pool).get = SCI_POOL_INCREMENT((pool), (pool).get); \ + } + +/** + * sci_pool_put() - + * + * This macro will put the value into the pool. This should only be called if + * the pool is not full. + */ +#define sci_pool_put(pool, value) \ + { \ + (pool).array[(pool).put] = (value); \ + (pool).put = SCI_POOL_INCREMENT((pool), (pool).put); \ + } + +/** + * sci_pool_erase() - + * + * This macro will search the pool and remove any elements in the pool matching + * the supplied value. This method can only be utilized on pools + */ +#define sci_pool_erase(pool, type, value) \ + { \ + type tmp_value; \ + u32 index; \ + u32 element_count = sci_pool_count((pool)); \ + \ + for (index = 0; index < element_count; index++) { \ + sci_pool_get((pool), tmp_value); \ + if (tmp_value != (value)) \ + sci_pool_put((pool), tmp_value); \ + } \ + } + +#endif /* _SCI_POOL_H_ */ diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 35e2e517f671..f44fa20cad96 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -53,13 +53,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This file contains the isci port implementation. - * - * - */ - - #include #include "isci.h" #include "scic_io_request.h" @@ -68,7 +61,6 @@ #include "scic_port.h" #include "port.h" #include "request.h" -#include "core/scic_sds_controller.h" static void isci_port_change_state(struct isci_port *iport, enum isci_status status) { diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 705517440441..9bc173fa49e1 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -32,7 +32,6 @@ #include "isci.h" #include "task.h" -#include "sci_environment.h" #include "probe_roms.h" struct efi_variable { diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 8b1ef19a6732..00334b9ccd80 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -57,16 +57,13 @@ #include "port.h" #include "remote_device.h" #include "request.h" -#include "scic_controller.h" #include "scic_io_request.h" #include "scic_phy.h" #include "scic_port.h" -#include "scic_sds_controller.h" #include "scic_sds_phy.h" #include "scic_sds_port.h" #include "remote_node_context.h" #include "scic_sds_request.h" -#include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" #include "task.h" diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 5e85a18a06de..af4759383db4 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -53,12 +53,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "host.h" #include "sci_base_state_machine.h" -#include "scic_sds_controller.h" #include "scic_sds_port.h" #include "remote_device.h" #include "remote_node_context.h" -#include "sci_environment.h" #include "sci_util.h" #include "scu_event_codes.h" #include "scu_task_context.h" diff --git a/drivers/scsi/isci/remote_node_table.c b/drivers/scsi/isci/remote_node_table.c index 8886146d9db2..80f44c25f45f 100644 --- a/drivers/scsi/isci/remote_node_table.c +++ b/drivers/scsi/isci/remote_node_table.c @@ -60,7 +60,6 @@ * */ #include "sci_util.h" -#include "sci_environment.h" #include "remote_node_table.h" #include "remote_node_context.h" diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index a58072807a37..4961ee347091 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -62,7 +62,6 @@ #include "sata.h" #include "scu_completion_codes.h" #include "scic_sds_request.h" -#include "scic_controller.h" #include "sas.h" static enum sci_status isci_request_ssp_request_construct( diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h deleted file mode 100644 index 30addba4d43a..000000000000 --- a/drivers/scsi/isci/sci_environment.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_ENVIRONMENT_H_ -#define _SCI_ENVIRONMENT_H_ - -#include "host.h" - - -static inline struct device *scic_to_dev(struct scic_sds_controller *scic) -{ - return &scic_to_ihost(scic)->pdev->dev; -} - -static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) -{ - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host) - return NULL; - - return &iphy->isci_port->isci_host->pdev->dev; -} - -static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port) -{ - struct isci_port *iport = sci_port_to_iport(sci_port); - - if (!iport || !iport->isci_host) - return NULL; - - return &iport->isci_host->pdev->dev; -} - -static inline struct device *scirdev_to_dev( - struct scic_sds_remote_device *sci_dev) -{ - struct isci_remote_device *idev = - container_of(sci_dev, typeof(*idev), sci); - - if (!idev || !idev->isci_port || !idev->isci_port->isci_host) - return NULL; - - return &idev->isci_port->isci_host->pdev->dev; -} - -enum { - ISCI_SI_REVA0, - ISCI_SI_REVA2, - ISCI_SI_REVB0, -}; - -extern int isci_si_rev; - -static inline bool is_a0(void) -{ - return isci_si_rev == ISCI_SI_REVA0; -} - -static inline bool is_a2(void) -{ - return isci_si_rev == ISCI_SI_REVA2; -} - -static inline bool is_b0(void) -{ - return isci_si_rev > ISCI_SI_REVA2; -} - -#endif diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 597c49020ac8..2a8603881929 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -65,7 +65,6 @@ #include "sata.h" #include "task.h" #include "scic_sds_request.h" -#include "scic_controller.h" #include "timers.h" /** -- cgit v1.2.3 From 63a3a15fb00ef49e50e98ff675094afcd92f113a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 8 May 2011 21:36:46 -0700 Subject: isci: uplevel register hardware data structures and unsolicited frame handling Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 2 +- drivers/scsi/isci/core/scic_sds_phy.h | 2 +- drivers/scsi/isci/core/scic_sds_port.c | 2 +- drivers/scsi/isci/core/scic_sds_port.h | 2 +- drivers/scsi/isci/core/scic_sds_port_registers.h | 66 - drivers/scsi/isci/core/scic_sds_request.c | 4 +- drivers/scsi/isci/core/scic_sds_stp_request.c | 2 +- .../isci/core/scic_sds_unsolicited_frame_control.c | 357 ---- .../isci/core/scic_sds_unsolicited_frame_control.h | 251 --- drivers/scsi/isci/core/scu_completion_codes.h | 283 --- drivers/scsi/isci/core/scu_event_codes.h | 336 ---- drivers/scsi/isci/core/scu_registers.h | 1826 ------------------ drivers/scsi/isci/core/scu_task_context.h | 942 ---------- drivers/scsi/isci/core/scu_unsolicited_frame.h | 117 -- drivers/scsi/isci/core/scu_viit_data.h | 178 -- drivers/scsi/isci/host.c | 2 +- drivers/scsi/isci/host.h | 4 +- drivers/scsi/isci/registers.h | 1934 ++++++++++++++++++++ drivers/scsi/isci/scu_completion_codes.h | 283 +++ drivers/scsi/isci/scu_event_codes.h | 336 ++++ drivers/scsi/isci/scu_task_context.h | 942 ++++++++++ drivers/scsi/isci/scu_unsolicited_frame.h | 117 ++ drivers/scsi/isci/unsolicited_frame_control.c | 357 ++++ drivers/scsi/isci/unsolicited_frame_control.h | 251 +++ 24 files changed, 4230 insertions(+), 4366 deletions(-) delete mode 100644 drivers/scsi/isci/core/scic_sds_port_registers.h delete mode 100644 drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c delete mode 100644 drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h delete mode 100644 drivers/scsi/isci/core/scu_completion_codes.h delete mode 100644 drivers/scsi/isci/core/scu_event_codes.h delete mode 100644 drivers/scsi/isci/core/scu_registers.h delete mode 100644 drivers/scsi/isci/core/scu_task_context.h delete mode 100644 drivers/scsi/isci/core/scu_unsolicited_frame.h delete mode 100644 drivers/scsi/isci/core/scu_viit_data.h create mode 100644 drivers/scsi/isci/registers.h create mode 100644 drivers/scsi/isci/scu_completion_codes.h create mode 100644 drivers/scsi/isci/scu_event_codes.h create mode 100644 drivers/scsi/isci/scu_task_context.h create mode 100644 drivers/scsi/isci/scu_unsolicited_frame.h create mode 100644 drivers/scsi/isci/unsolicited_frame_control.c create mode 100644 drivers/scsi/isci/unsolicited_frame_control.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 45f8f68caf4a..0153b0fe13b8 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -5,6 +5,7 @@ isci-objs := init.o phy.o request.o sata.o \ host.o task.o probe_roms.o \ remote_node_context.o \ remote_node_table.o \ + unsolicited_frame_control.o \ core/scic_sds_request.o \ core/scic_sds_stp_request.o \ core/scic_sds_port.o \ @@ -12,6 +13,5 @@ isci-objs := init.o phy.o request.o sata.o \ core/scic_sds_phy.o \ core/scic_sds_ssp_request.o \ core/scic_sds_smp_request.o \ - core/scic_sds_unsolicited_frame_control.o \ core/sci_base_state_machine.o \ core/sci_util.o diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index c40c09b0c726..472718d2f444 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -58,7 +58,7 @@ #include "sas.h" #include "scic_phy.h" -#include "scu_registers.h" +#include "registers.h" #include "sci_base_state_machine.h" #include diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 652d823d5fa3..652917eeead4 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -61,7 +61,7 @@ #include "remote_device.h" #include "remote_node_context.h" #include "scic_sds_request.h" -#include "scu_registers.h" +#include "registers.h" #include "timers.h" #define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index bd612d576093..4b28c5acd758 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -59,7 +59,7 @@ #include #include "isci.h" #include "sas.h" -#include "scu_registers.h" +#include "registers.h" #include "sci_base_state_machine.h" struct scic_sds_controller; diff --git a/drivers/scsi/isci/core/scic_sds_port_registers.h b/drivers/scsi/isci/core/scic_sds_port_registers.h deleted file mode 100644 index 01e24e52990c..000000000000 --- a/drivers/scsi/isci/core/scic_sds_port_registers.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_PORT_REGISTERS_H_ -#define _SCIC_SDS_PORT_REGISTERS_H_ - -/** - * This file contains a set of macros that assist in reading the SCU hardware - * registers. - * - * - */ - -#endif /* _SCIC_SDS_PORT_REGISTERS_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c index 1405aa703c3a..cd279601de01 100644 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ b/drivers/scsi/isci/core/scic_sds_request.c @@ -55,13 +55,13 @@ #include #include "scic_io_request.h" -#include "scu_registers.h" +#include "registers.h" #include "scic_sds_port.h" #include "remote_device.h" #include "scic_sds_request.h" #include "scic_sds_smp_request.h" #include "scic_sds_stp_request.h" -#include "scic_sds_unsolicited_frame_control.h" +#include "unsolicited_frame_control.h" #include "sci_util.h" #include "scu_completion_codes.h" #include "scu_task_context.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 2f5095130cad..9a787e25b48b 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -62,7 +62,7 @@ #include "scic_sds_request.h" #include "scic_sds_stp_pio_request.h" #include "scic_sds_stp_request.h" -#include "scic_sds_unsolicited_frame_control.h" +#include "unsolicited_frame_control.h" #include "sci_util.h" #include "scu_completion_codes.h" #include "scu_event_codes.h" diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c deleted file mode 100644 index d0e03731377e..000000000000 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "host.h" -#include "scic_sds_unsolicited_frame_control.h" -#include "scu_registers.h" -#include "sci_util.h" - -/** - * This method will program the unsolicited frames (UFs) into the UF address - * table and construct the UF frame structure being modeled in the core. It - * will handle the case where some of the UFs are not being used and thus - * should have entries programmed to zero in the address table. - * @uf_control: This parameter specifies the unsolicted frame control object - * for which to construct the unsolicited frames objects. - * @uf_buffer_phys_address: This parameter specifies the physical address for - * the first unsolicited frame buffer. - * @uf_buffer_virt_address: This parameter specifies the virtual address for - * the first unsolicited frame buffer. - * @unused_uf_header_entries: This parameter specifies the number of unused UF - * headers. This value can be non-zero when there are a non-power of 2 - * number of unsolicited frames being supported. - * @used_uf_header_entries: This parameter specifies the number of actually - * utilized UF headers. - * - */ -static void scic_sds_unsolicited_frame_control_construct_frames( - struct scic_sds_unsolicited_frame_control *uf_control, - dma_addr_t uf_buffer_phys_address, - void *uf_buffer_virt_address, - u32 unused_uf_header_entries, - u32 used_uf_header_entries) -{ - u32 index; - struct scic_sds_unsolicited_frame *uf; - - /* - * Program the unused buffers into the UF address table and the - * controller's array of UFs. - */ - for (index = 0; index < unused_uf_header_entries; index++) { - uf = &uf_control->buffers.array[index]; - - sci_cb_make_physical_address( - uf_control->address_table.array[index], 0, 0 - ); - uf->buffer = NULL; - uf->header = &uf_control->headers.array[index]; - uf->state = UNSOLICITED_FRAME_EMPTY; - } - - /* - * Program the actual used UF buffers into the UF address table and - * the controller's array of UFs. - */ - for (index = unused_uf_header_entries; - index < unused_uf_header_entries + used_uf_header_entries; - index++) { - uf = &uf_control->buffers.array[index]; - - uf_control->address_table.array[index] = uf_buffer_phys_address; - - uf->buffer = uf_buffer_virt_address; - uf->header = &uf_control->headers.array[index]; - uf->state = UNSOLICITED_FRAME_EMPTY; - - /* - * Increment the address of the physical and virtual memory - * pointers. Everything is aligned on 1k boundary with an - * increment of 1k. - */ - uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; - uf_buffer_phys_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; - } -} - -int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic) -{ - struct scic_sds_unsolicited_frame_control *uf_control = &scic->uf_control; - u32 unused_uf_header_entries; - u32 used_uf_header_entries; - u32 used_uf_buffer_bytes; - u32 unused_uf_header_bytes; - u32 used_uf_header_bytes; - dma_addr_t uf_buffer_phys_address; - void *uf_buffer_virt_address; - size_t size; - - /* - * The UF buffer address table size must be programmed to a power - * of 2. Find the first power of 2 that is equal to or greater then - * the number of unsolicited frame buffers to be utilized. - */ - uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES; - while (uf_control->address_table.count < uf_control->buffers.count && - uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES) - uf_control->address_table.count <<= 1; - - /* - * Prepare all of the memory sizes for the UF headers, UF address - * table, and UF buffers themselves. - */ - used_uf_buffer_bytes = uf_control->buffers.count - * SCU_UNSOLICITED_FRAME_BUFFER_SIZE; - unused_uf_header_entries = uf_control->address_table.count - - uf_control->buffers.count; - used_uf_header_entries = uf_control->buffers.count; - unused_uf_header_bytes = unused_uf_header_entries - * sizeof(struct scu_unsolicited_frame_header); - used_uf_header_bytes = used_uf_header_entries - * sizeof(struct scu_unsolicited_frame_header); - - size = used_uf_buffer_bytes + used_uf_header_bytes + - uf_control->address_table.count * sizeof(dma_addr_t); - - - /* - * The Unsolicited Frame buffers are set at the start of the UF - * memory descriptor entry. The headers and address table will be - * placed after the buffers. - */ - uf_buffer_virt_address = dmam_alloc_coherent(scic_to_dev(scic), size, - &uf_buffer_phys_address, GFP_KERNEL); - if (!uf_buffer_virt_address) - return -ENOMEM; - - /* - * Program the location of the UF header table into the SCU. - * Notes: - * - The address must align on a 64-byte boundary. Guaranteed to be - * on 64-byte boundary already 1KB boundary for unsolicited frames. - * - Program unused header entries to overlap with the last - * unsolicited frame. The silicon will never DMA to these unused - * headers, since we program the UF address table pointers to - * NULL. - */ - uf_control->headers.physical_address = - uf_buffer_phys_address + - used_uf_buffer_bytes - - unused_uf_header_bytes; - - uf_control->headers.array = - uf_buffer_virt_address + - used_uf_buffer_bytes - - unused_uf_header_bytes; - - /* - * Program the location of the UF address table into the SCU. - * Notes: - * - The address must align on a 64-bit boundary. Guaranteed to be on 64 - * byte boundary already due to above programming headers being on a - * 64-bit boundary and headers are on a 64-bytes in size. - */ - uf_control->address_table.physical_address = - uf_buffer_phys_address + - used_uf_buffer_bytes + - used_uf_header_bytes; - - uf_control->address_table.array = - uf_buffer_virt_address + - used_uf_buffer_bytes + - used_uf_header_bytes; - - uf_control->get = 0; - - /* - * UF buffer requirements are: - * - The last entry in the UF queue is not NULL. - * - There is a power of 2 number of entries (NULL or not-NULL) - * programmed into the queue. - * - Aligned on a 1KB boundary. */ - - /* - * If the user provided less then the maximum amount of memory, - * then be sure that we programm the first entries in the UF - * address table to NULL. */ - scic_sds_unsolicited_frame_control_construct_frames( - uf_control, - uf_buffer_phys_address, - uf_buffer_virt_address, - unused_uf_header_entries, - used_uf_header_entries - ); - - return 0; -} - -/** - * This method returns the frame header for the specified frame index. - * @uf_control: - * @frame_index: - * @frame_header: - * - * enum sci_status - */ -enum sci_status scic_sds_unsolicited_frame_control_get_header( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index, - void **frame_header) -{ - if (frame_index < uf_control->address_table.count) { - /* - * Skip the first word in the frame since this is a controll word used - * by the hardware. */ - *frame_header = &uf_control->buffers.array[frame_index].header->data; - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_PARAMETER_VALUE; -} - -/** - * This method returns the frame buffer for the specified frame index. - * @uf_control: - * @frame_index: - * @frame_buffer: - * - * enum sci_status - */ -enum sci_status scic_sds_unsolicited_frame_control_get_buffer( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index, - void **frame_buffer) -{ - if (frame_index < uf_control->address_table.count) { - *frame_buffer = uf_control->buffers.array[frame_index].buffer; - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_PARAMETER_VALUE; -} - -/** - * This method releases the frame once this is done the frame is available for - * re-use by the hardware. The data contained in the frame header and frame - * buffer is no longer valid. - * @uf_control: This parameter specifies the UF control object - * @frame_index: This parameter specifies the frame index to attempt to release. - * - * This method returns an indication to the caller as to whether the - * unsolicited frame get pointer should be updated. - */ -bool scic_sds_unsolicited_frame_control_release_frame( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index) -{ - u32 frame_get; - u32 frame_cycle; - - frame_get = uf_control->get & (uf_control->address_table.count - 1); - frame_cycle = uf_control->get & uf_control->address_table.count; - - /* - * In the event there are NULL entries in the UF table, we need to - * advance the get pointer in order to find out if this frame should - * be released (i.e. update the get pointer). */ - while (((lower_32_bits(uf_control->address_table.array[frame_get]) - == 0) && - (upper_32_bits(uf_control->address_table.array[frame_get]) - == 0)) && - (frame_get < uf_control->address_table.count)) - frame_get++; - - /* - * The table has a NULL entry as it's last element. This is - * illegal. */ - BUG_ON(frame_get >= uf_control->address_table.count); - - if (frame_index < uf_control->address_table.count) { - uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED; - - /* - * The frame index is equal to the current get pointer so we - * can now free up all of the frame entries that */ - if (frame_get == frame_index) { - while ( - uf_control->buffers.array[frame_get].state - == UNSOLICITED_FRAME_RELEASED - ) { - uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY; - - INCREMENT_QUEUE_GET( - frame_get, - frame_cycle, - uf_control->address_table.count - 1, - uf_control->address_table.count - ); - } - - uf_control->get = - (SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get); - - return true; - } else { - /* - * Frames remain in use until we advance the get pointer - * so there is nothing we can do here */ - } - } - - return false; -} - diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h deleted file mode 100644 index 0d8ca8c4770f..000000000000 --- a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ -#define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ - -#include "isci.h" -#include "scu_unsolicited_frame.h" - -/** - * enum unsolicited_frame_state - - * - * This enumeration represents the current unsolicited frame state. The - * controller object can not updtate the hardware unsolicited frame put pointer - * unless it has already processed the priror unsolicited frames. - */ -enum unsolicited_frame_state { - /** - * This state is when the frame is empty and not in use. It is - * different from the released state in that the hardware could DMA - * data to this frame buffer. - */ - UNSOLICITED_FRAME_EMPTY, - - /** - * This state is set when the frame buffer is in use by by some - * object in the system. - */ - UNSOLICITED_FRAME_IN_USE, - - /** - * This state is set when the frame is returned to the free pool - * but one or more frames prior to this one are still in use. - * Once all of the frame before this one are freed it will go to - * the empty state. - */ - UNSOLICITED_FRAME_RELEASED, - - UNSOLICITED_FRAME_MAX_STATES -}; - -/** - * struct scic_sds_unsolicited_frame - - * - * This is the unsolicited frame data structure it acts as the container for - * the current frame state, frame header and frame buffer. - */ -struct scic_sds_unsolicited_frame { - /** - * This field contains the current frame state - */ - enum unsolicited_frame_state state; - - /** - * This field points to the frame header data. - */ - struct scu_unsolicited_frame_header *header; - - /** - * This field points to the frame buffer data. - */ - void *buffer; - -}; - -/** - * struct scic_sds_uf_header_array - - * - * This structure contains all of the unsolicited frame header information. - */ -struct scic_sds_uf_header_array { - /** - * This field is represents a virtual pointer to the start - * address of the UF address table. The table contains - * 64-bit pointers as required by the hardware. - */ - struct scu_unsolicited_frame_header *array; - - /** - * This field specifies the physical address location for the UF - * buffer array. - */ - dma_addr_t physical_address; - -}; - -/** - * struct scic_sds_uf_buffer_array - - * - * This structure contains all of the unsolicited frame buffer (actual payload) - * information. - */ -struct scic_sds_uf_buffer_array { - /** - * This field is the minimum number of unsolicited frames supported by the - * hardware and the number of unsolicited frames requested by the software. - */ - u32 count; - - /** - * This field is the SCIC_UNSOLICITED_FRAME data its used to manage - * the data for the unsolicited frame requests. It also represents - * the virtual address location that corresponds to the - * physical_address field. - */ - struct scic_sds_unsolicited_frame array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE]; - - /** - * This field specifies the physical address location for the UF - * buffer array. - */ - dma_addr_t physical_address; - -}; - -/** - * struct scic_sds_uf_address_table_array - - * - * This object maintains all of the unsolicited frame address table specific - * data. The address table is a collection of 64-bit pointers that point to - * 1KB buffers into which the silicon will DMA unsolicited frames. - */ -struct scic_sds_uf_address_table_array { - /** - * This field specifies the actual programmed size of the - * unsolicited frame buffer address table. The size of the table - * can be larger than the actual number of UF buffers, but it must - * be a power of 2 and the last entry in the table is not allowed - * to be NULL. - */ - u32 count; - - /** - * This field represents a virtual pointer that refers to the - * starting address of the UF address table. - * 64-bit pointers are required by the hardware. - */ - dma_addr_t *array; - - /** - * This field specifies the physical address location for the UF - * address table. - */ - dma_addr_t physical_address; - -}; - -/** - * struct scic_sds_unsolicited_frame_control - - * - * This object contains all of the data necessary to handle unsolicited frames. - */ -struct scic_sds_unsolicited_frame_control { - /** - * This field is the software copy of the unsolicited frame queue - * get pointer. The controller object writes this value to the - * hardware to let the hardware put more unsolicited frame entries. - */ - u32 get; - - /** - * This field contains all of the unsolicited frame header - * specific fields. - */ - struct scic_sds_uf_header_array headers; - - /** - * This field contains all of the unsolicited frame buffer - * specific fields. - */ - struct scic_sds_uf_buffer_array buffers; - - /** - * This field contains all of the unsolicited frame address table - * specific fields. - */ - struct scic_sds_uf_address_table_array address_table; - -}; - -struct scic_sds_controller; - -int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic); - -enum sci_status scic_sds_unsolicited_frame_control_get_header( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index, - void **frame_header); - -enum sci_status scic_sds_unsolicited_frame_control_get_buffer( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index, - void **frame_buffer); - -bool scic_sds_unsolicited_frame_control_release_frame( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index); - -#endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */ diff --git a/drivers/scsi/isci/core/scu_completion_codes.h b/drivers/scsi/isci/core/scu_completion_codes.h deleted file mode 100644 index c8b329c695f9..000000000000 --- a/drivers/scsi/isci/core/scu_completion_codes.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCU_COMPLETION_CODES_HEADER_ -#define _SCU_COMPLETION_CODES_HEADER_ - -/** - * This file contains the constants and macros for the SCU hardware completion - * codes. - * - * - */ - -#define SCU_COMPLETION_TYPE_SHIFT 28 -#define SCU_COMPLETION_TYPE_MASK 0x70000000 - -/** - * SCU_COMPLETION_TYPE() - - * - * This macro constructs an SCU completion type - */ -#define SCU_COMPLETION_TYPE(type) \ - ((u32)(type) << SCU_COMPLETION_TYPE_SHIFT) - -/** - * SCU_COMPLETION_TYPE() - - * - * These macros contain the SCU completion types SCU_COMPLETION_TYPE - */ -#define SCU_COMPLETION_TYPE_TASK SCU_COMPLETION_TYPE(0) -#define SCU_COMPLETION_TYPE_SDMA SCU_COMPLETION_TYPE(1) -#define SCU_COMPLETION_TYPE_UFI SCU_COMPLETION_TYPE(2) -#define SCU_COMPLETION_TYPE_EVENT SCU_COMPLETION_TYPE(3) -#define SCU_COMPLETION_TYPE_NOTIFY SCU_COMPLETION_TYPE(4) - -/** - * - * - * These constants provide the shift and mask values for the various parts of - * an SCU completion code. - */ -#define SCU_COMPLETION_STATUS_MASK 0x0FFC0000 -#define SCU_COMPLETION_TL_STATUS_MASK 0x0FC00000 -#define SCU_COMPLETION_TL_STATUS_SHIFT 22 -#define SCU_COMPLETION_SDMA_STATUS_MASK 0x003C0000 -#define SCU_COMPLETION_PEG_MASK 0x00010000 -#define SCU_COMPLETION_PORT_MASK 0x00007000 -#define SCU_COMPLETION_PE_MASK SCU_COMPLETION_PORT_MASK -#define SCU_COMPLETION_PE_SHIFT 12 -#define SCU_COMPLETION_INDEX_MASK 0x00000FFF - -/** - * SCU_GET_COMPLETION_TYPE() - - * - * This macro returns the SCU completion type. - */ -#define SCU_GET_COMPLETION_TYPE(completion_code) \ - ((completion_code) & SCU_COMPLETION_TYPE_MASK) - -/** - * SCU_GET_COMPLETION_STATUS() - - * - * This macro returns the SCU completion status. - */ -#define SCU_GET_COMPLETION_STATUS(completion_code) \ - ((completion_code) & SCU_COMPLETION_STATUS_MASK) - -/** - * SCU_GET_COMPLETION_TL_STATUS() - - * - * This macro returns the transport layer completion status. - */ -#define SCU_GET_COMPLETION_TL_STATUS(completion_code) \ - ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) - -/** - * SCU_MAKE_COMPLETION_STATUS() - - * - * This macro takes a completion code and performs the shift and mask - * operations to turn it into a completion code that can be compared to a - * SCU_GET_COMPLETION_TL_STATUS. - */ -#define SCU_MAKE_COMPLETION_STATUS(completion_code) \ - ((u32)(completion_code) << SCU_COMPLETION_TL_STATUS_SHIFT) - -/** - * SCU_NORMALIZE_COMPLETION_STATUS() - - * - * This macro takes a SCU_GET_COMPLETION_TL_STATUS and normalizes it for a - * return code. - */ -#define SCU_NORMALIZE_COMPLETION_STATUS(completion_code) \ - (\ - ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) \ - >> SCU_COMPLETION_TL_STATUS_SHIFT \ - ) - -/** - * SCU_GET_COMPLETION_SDMA_STATUS() - - * - * This macro returns the SDMA completion status. - */ -#define SCU_GET_COMPLETION_SDMA_STATUS(completion_code) \ - ((completion_code) & SCU_COMPLETION_SDMA_STATUS_MASK) - -/** - * SCU_GET_COMPLETION_PEG() - - * - * This macro returns the Protocol Engine Group from the completion code. - */ -#define SCU_GET_COMPLETION_PEG(completion_code) \ - ((completion_code) & SCU_COMPLETION_PEG_MASK) - -/** - * SCU_GET_COMPLETION_PORT() - - * - * This macro reuturns the logical port index from the completion code. - */ -#define SCU_GET_COMPLETION_PORT(completion_code) \ - ((completion_code) & SCU_COMPLETION_PORT_MASK) - -/** - * SCU_GET_PROTOCOL_ENGINE_INDEX() - - * - * This macro returns the PE index from the completion code. - */ -#define SCU_GET_PROTOCOL_ENGINE_INDEX(completion_code) \ - (((completion_code) & SCU_COMPLETION_PE_MASK) >> SCU_COMPLETION_PE_SHIFT) - -/** - * SCU_GET_COMPLETION_INDEX() - - * - * This macro returns the index of the completion which is either a TCi or an - * RNi depending on the completion type. - */ -#define SCU_GET_COMPLETION_INDEX(completion_code) \ - ((completion_code) & SCU_COMPLETION_INDEX_MASK) - -#define SCU_UNSOLICITED_FRAME_MASK 0x0FFF0000 -#define SCU_UNSOLICITED_FRAME_SHIFT 16 - -/** - * SCU_GET_FRAME_INDEX() - - * - * This macro returns a normalized frame index from an unsolicited frame - * completion. - */ -#define SCU_GET_FRAME_INDEX(completion_code) \ - (\ - ((completion_code) & SCU_UNSOLICITED_FRAME_MASK) \ - >> SCU_UNSOLICITED_FRAME_SHIFT \ - ) - -#define SCU_UNSOLICITED_FRAME_ERROR_MASK 0x00008000 - -/** - * SCU_GET_FRAME_ERROR() - - * - * This macro returns a zero (0) value if there is no frame error otherwise it - * returns non-zero (!0). - */ -#define SCU_GET_FRAME_ERROR(completion_code) \ - ((completion_code) & SCU_UNSOLICITED_FRAME_ERROR_MASK) - -/** - * - * - * These constants represent normalized completion codes which must be shifted - * 18 bits to match it with the hardware completion code. In a 16-bit compiler, - * immediate constants are 16-bit values (the size of an int). If we shift - * those by 18 bits, we completely lose the value. To ensure the value is a - * 32-bit value like we want, each immediate value must be cast to a u32. - */ -#define SCU_TASK_DONE_GOOD ((u32)0x00) -#define SCU_TASK_DONE_CRC_ERR ((u32)0x14) -#define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14) -#define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15) -#define SCU_TASK_DONE_NAK_CMD_ERR ((u32)0x16) -#define SCU_TASK_DONE_CMD_LL_R_ERR ((u32)0x16) -#define SCU_TASK_DONE_LL_R_ERR ((u32)0x17) -#define SCU_TASK_DONE_ACK_NAK_TO ((u32)0x17) -#define SCU_TASK_DONE_LL_PERR ((u32)0x18) -#define SCU_TASK_DONE_LL_SY_TERM ((u32)0x19) -#define SCU_TASK_DONE_NAK_ERR ((u32)0x19) -#define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A) -#define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A) -#define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B) -#define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B) -#define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C) -#define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C) -#define SCU_TASK_DONE_INV_FIS_TYPE ((u32)0x1D) -#define SCU_TASK_DONE_XR_IU_LEN_ERR ((u32)0x1D) -#define SCU_TASK_DONE_INV_FIS_LEN ((u32)0x1E) -#define SCU_TASK_DONE_XR_WD_LEN ((u32)0x1E) -#define SCU_TASK_DONE_SDMA_ERR ((u32)0x1F) -#define SCU_TASK_DONE_OFFSET_ERR ((u32)0x20) -#define SCU_TASK_DONE_MAX_PLD_ERR ((u32)0x21) -#define SCU_TASK_DONE_EXCESS_DATA ((u32)0x22) -#define SCU_TASK_DONE_LF_ERR ((u32)0x23) -#define SCU_TASK_DONE_UNEXP_FIS ((u32)0x24) -#define SCU_TASK_DONE_UNEXP_RESP ((u32)0x24) -#define SCU_TASK_DONE_EARLY_RESP ((u32)0x25) -#define SCU_TASK_DONE_SMP_RESP_TO_ERR ((u32)0x26) -#define SCU_TASK_DONE_DMASETUP_DIRERR ((u32)0x27) -#define SCU_TASK_DONE_SMP_UFI_ERR ((u32)0x27) -#define SCU_TASK_DONE_XFERCNT_ERR ((u32)0x28) -#define SCU_TASK_DONE_SMP_FRM_TYPE_ERR ((u32)0x28) -#define SCU_TASK_DONE_SMP_LL_RX_ERR ((u32)0x29) -#define SCU_TASK_DONE_RESP_LEN_ERR ((u32)0x2A) -#define SCU_TASK_DONE_UNEXP_DATA ((u32)0x2B) -#define SCU_TASK_DONE_OPEN_FAIL ((u32)0x2C) -#define SCU_TASK_DONE_UNEXP_SDBFIS ((u32)0x2D) -#define SCU_TASK_DONE_REG_ERR ((u32)0x2E) -#define SCU_TASK_DONE_SDB_ERR ((u32)0x2F) -#define SCU_TASK_DONE_TASK_ABORT ((u32)0x30) -#define SCU_TASK_DONE_CMD_SDMA_ERR ((U32)0x32) -#define SCU_TASK_DONE_CMD_LL_ABORT_ERR ((U32)0x33) -#define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION ((u32)0x34) -#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1 ((u32)0x35) -#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2 ((u32)0x36) -#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3 ((u32)0x37) -#define SCU_TASK_OPEN_REJECT_BAD_DESTINATION ((u32)0x38) -#define SCU_TASK_OPEN_REJECT_ZONE_VIOLATION ((u32)0x39) -#define SCU_TASK_DONE_VIIT_ENTRY_NV ((u32)0x3A) -#define SCU_TASK_DONE_IIT_ENTRY_NV ((u32)0x3B) -#define SCU_TASK_DONE_RNCNV_OUTBOUND ((u32)0x3C) -#define SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY ((u32)0x3D) -#define SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED ((u32)0x3E) -#define SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED ((u32)0x3F) - -#endif /* _SCU_COMPLETION_CODES_HEADER_ */ diff --git a/drivers/scsi/isci/core/scu_event_codes.h b/drivers/scsi/isci/core/scu_event_codes.h deleted file mode 100644 index 36a945ad5722..000000000000 --- a/drivers/scsi/isci/core/scu_event_codes.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SCU_EVENT_CODES_HEADER__ -#define __SCU_EVENT_CODES_HEADER__ - -/** - * This file contains the constants and macros for the SCU event codes. - * - * - */ - -#define SCU_EVENT_TYPE_CODE_SHIFT 24 -#define SCU_EVENT_TYPE_CODE_MASK 0x0F000000 - -#define SCU_EVENT_SPECIFIC_CODE_SHIFT 18 -#define SCU_EVENT_SPECIFIC_CODE_MASK 0x00FC0000 - -#define SCU_EVENT_CODE_MASK \ - (SCU_EVENT_TYPE_CODE_MASK | SCU_EVENT_SPECIFIC_CODE_MASK) - -/** - * SCU_EVENT_TYPE() - - * - * This macro constructs an SCU event type from the type value. - */ -#define SCU_EVENT_TYPE(type) \ - ((u32)(type) << SCU_EVENT_TYPE_CODE_SHIFT) - -/** - * SCU_EVENT_SPECIFIC() - - * - * This macro constructs an SCU event specifier from the code value. - */ -#define SCU_EVENT_SPECIFIC(code) \ - ((u32)(code) << SCU_EVENT_SPECIFIC_CODE_SHIFT) - -/** - * SCU_EVENT_MESSAGE() - - * - * This macro constructs a combines an SCU event type and SCU event specifier - * from the type and code values. - */ -#define SCU_EVENT_MESSAGE(type, code) \ - ((type) | SCU_EVENT_SPECIFIC(code)) - -/** - * SCU_EVENT_TYPE() - - * - * SCU_EVENT_TYPES - */ -#define SCU_EVENT_TYPE_SMU_COMMAND_ERROR SCU_EVENT_TYPE(0x08) -#define SCU_EVENT_TYPE_SMU_PCQ_ERROR SCU_EVENT_TYPE(0x09) -#define SCU_EVENT_TYPE_SMU_ERROR SCU_EVENT_TYPE(0x00) -#define SCU_EVENT_TYPE_TRANSPORT_ERROR SCU_EVENT_TYPE(0x01) -#define SCU_EVENT_TYPE_BROADCAST_CHANGE SCU_EVENT_TYPE(0x02) -#define SCU_EVENT_TYPE_OSSP_EVENT SCU_EVENT_TYPE(0x03) -#define SCU_EVENT_TYPE_FATAL_MEMORY_ERROR SCU_EVENT_TYPE(0x0F) -#define SCU_EVENT_TYPE_RNC_SUSPEND_TX SCU_EVENT_TYPE(0x04) -#define SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX SCU_EVENT_TYPE(0x05) -#define SCU_EVENT_TYPE_RNC_OPS_MISC SCU_EVENT_TYPE(0x06) -#define SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT SCU_EVENT_TYPE(0x07) -#define SCU_EVENT_TYPE_ERR_CNT_EVENT SCU_EVENT_TYPE(0x0A) - -/** - * - * - * SCU_EVENT_SPECIFIERS - */ -#define SCU_EVENT_SPECIFIER_DRIVER_SUSPEND 0x20 -#define SCU_EVENT_SPECIFIER_RNC_RELEASE 0x00 - -/** - * - * - * SMU_COMMAND_EVENTS - */ -#define SCU_EVENT_INVALID_CONTEXT_COMMAND \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_COMMAND_ERROR, 0x00) - -/** - * - * - * SMU_PCQ_EVENTS - */ -#define SCU_EVENT_UNCORRECTABLE_PCQ_ERROR \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_PCQ_ERROR, 0x00) - -/** - * - * - * SMU_EVENTS - */ -#define SCU_EVENT_UNCORRECTABLE_REGISTER_WRITE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x02) -#define SCU_EVENT_UNCORRECTABLE_REGISTER_READ \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x03) -#define SCU_EVENT_PCIE_INTERFACE_ERROR \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x04) -#define SCU_EVENT_FUNCTION_LEVEL_RESET \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x05) - -/** - * - * - * TRANSPORT_LEVEL_ERRORS - */ -#define SCU_EVENT_ACK_NAK_TIMEOUT_ERROR \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_TRANSPORT_ERROR, 0x00) - -/** - * - * - * BROADCAST_CHANGE_EVENTS - */ -#define SCU_EVENT_BROADCAST_CHANGE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x01) -#define SCU_EVENT_BROADCAST_RESERVED0 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x02) -#define SCU_EVENT_BROADCAST_RESERVED1 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x03) -#define SCU_EVENT_BROADCAST_SES \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x04) -#define SCU_EVENT_BROADCAST_EXPANDER \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x05) -#define SCU_EVENT_BROADCAST_AEN \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x06) -#define SCU_EVENT_BROADCAST_RESERVED3 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x07) -#define SCU_EVENT_BROADCAST_RESERVED4 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x08) -#define SCU_EVENT_PE_SUSPENDED \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x09) - -/** - * - * - * OSSP_EVENTS - */ -#define SCU_EVENT_PORT_SELECTOR_DETECTED \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x10) -#define SCU_EVENT_SENT_PORT_SELECTION \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x11) -#define SCU_EVENT_HARD_RESET_TRANSMITTED \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x12) -#define SCU_EVENT_HARD_RESET_RECEIVED \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x13) -#define SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x15) -#define SCU_EVENT_LINK_FAILURE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x16) -#define SCU_EVENT_SATA_SPINUP_HOLD \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x17) -#define SCU_EVENT_SAS_15_SSC \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x18) -#define SCU_EVENT_SAS_15 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x19) -#define SCU_EVENT_SAS_30_SSC \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1A) -#define SCU_EVENT_SAS_30 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1B) -#define SCU_EVENT_SAS_60_SSC \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1C) -#define SCU_EVENT_SAS_60 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1D) -#define SCU_EVENT_SATA_15_SSC \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1E) -#define SCU_EVENT_SATA_15 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1F) -#define SCU_EVENT_SATA_30_SSC \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x20) -#define SCU_EVENT_SATA_30 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x21) -#define SCU_EVENT_SATA_60_SSC \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x22) -#define SCU_EVENT_SATA_60 \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x23) -#define SCU_EVENT_SAS_PHY_DETECTED \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x24) -#define SCU_EVENT_SATA_PHY_DETECTED \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x25) - -/** - * - * - * FATAL_INTERNAL_MEMORY_ERROR_EVENTS - */ -#define SCU_EVENT_TSC_RNSC_UNCORRECTABLE_ERROR \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x00) -#define SCU_EVENT_TC_RNC_UNCORRECTABLE_ERROR \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x01) -#define SCU_EVENT_ZPT_UNCORRECTABLE_ERROR \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x02) - -/** - * - * - * REMOTE_NODE_SUSPEND_EVENTS - */ -#define SCU_EVENT_TL_RNC_SUSPEND_TX \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x00) -#define SCU_EVENT_TL_RNC_SUSPEND_TX_RX \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x00) -#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20) -#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX_RX \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x20) - -/** - * - * - * REMOTE_NODE_MISC_EVENTS - */ -#define SCU_EVENT_POST_RCN_RELEASE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, SCU_EVENT_SPECIFIER_RNC_RELEASE) -#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_ENABLE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x01) -#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_DISABLE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x02) -#define SCU_EVENT_POST_RNC_COMPLETE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x03) -#define SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x04) - -/** - * - * - * ERROR_COUNT_EVENT - */ -#define SCU_EVENT_RX_CREDIT_BLOCKED_RECEIVED \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x00) -#define SCU_EVENT_TX_DONE_CREDIT_TIMEOUT \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x01) -#define SCU_EVENT_RX_DONE_CREDIT_TIMEOUT \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x02) - -/** - * scu_get_event_type() - - * - * This macro returns the SCU event type from the event code. - */ -#define scu_get_event_type(event_code) \ - ((event_code) & SCU_EVENT_TYPE_CODE_MASK) - -/** - * scu_get_event_specifier() - - * - * This macro returns the SCU event specifier from the event code. - */ -#define scu_get_event_specifier(event_code) \ - ((event_code) & SCU_EVENT_SPECIFIC_CODE_MASK) - -/** - * scu_get_event_code() - - * - * This macro returns the combined SCU event type and SCU event specifier from - * the event code. - */ -#define scu_get_event_code(event_code) \ - ((event_code) & SCU_EVENT_CODE_MASK) - - -/** - * - * - * PTS_SCHEDULE_EVENT - */ -#define SCU_EVENT_SMP_RESPONSE_NO_PE \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x00) -#define SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE \ - scu_get_event_specifier(SCU_EVENT_SMP_RESPONSE_NO_PE) - -#define SCU_EVENT_TASK_TIMEOUT \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x01) -#define SCU_EVENT_SPECIFIC_TASK_TIMEOUT \ - scu_get_event_specifier(SCU_EVENT_TASK_TIMEOUT) - -#define SCU_EVENT_IT_NEXUS_TIMEOUT \ - SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x02) -#define SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT \ - scu_get_event_specifier(SCU_EVENT_IT_NEXUS_TIMEOUT) - - -#endif /* __SCU_EVENT_CODES_HEADER__ */ diff --git a/drivers/scsi/isci/core/scu_registers.h b/drivers/scsi/isci/core/scu_registers.h deleted file mode 100644 index 12f2bacc9c09..000000000000 --- a/drivers/scsi/isci/core/scu_registers.h +++ /dev/null @@ -1,1826 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCU_REGISTERS_H_ -#define _SCU_REGISTERS_H_ - -/** - * This file contains the constants and structures for the SCU memory mapped - * registers. - * - * - */ - -#include "scu_viit_data.h" - - -/* Generate a value for an SCU register */ -#define SCU_GEN_VALUE(name, value) \ - (((value) << name ## _SHIFT) & (name ## _MASK)) - -/* - * Generate a bit value for an SCU register - * Make sure that the register MASK is just a single bit */ -#define SCU_GEN_BIT(name) \ - SCU_GEN_VALUE(name, ((u32)1)) - -#define SCU_SET_BIT(name, reg_value) \ - ((reg_value) | SCU_GEN_BIT(name)) - -#define SCU_CLEAR_BIT(name, reg_value) \ - ((reg_value)$ ~(SCU_GEN_BIT(name))) - -/* - * ***************************************************************************** - * Unions for bitfield definitions of SCU Registers - * SMU Post Context Port - * ***************************************************************************** */ -#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_SHIFT (0) -#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_MASK (0x00000FFF) -#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_SHIFT (12) -#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_MASK (0x0000F000) -#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_SHIFT (16) -#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_MASK (0x00030000) -#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_SHIFT (18) -#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_MASK (0x00FC0000) -#define SMU_POST_CONTEXT_PORT_RESERVED_MASK (0xFF000000) - -#define SMU_PCP_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SMU_POST_CONTEXT_PORT_ ## name, value) - -/* ***************************************************************************** */ -#define SMU_INTERRUPT_STATUS_COMPLETION_SHIFT (31) -#define SMU_INTERRUPT_STATUS_COMPLETION_MASK (0x80000000) -#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_SHIFT (1) -#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_MASK (0x00000002) -#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_SHIFT (0) -#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_MASK (0x00000001) -#define SMU_INTERRUPT_STATUS_RESERVED_MASK (0x7FFFFFFC) - -#define SMU_ISR_GEN_BIT(name) \ - SCU_GEN_BIT(SMU_INTERRUPT_STATUS_ ## name) - -#define SMU_ISR_QUEUE_ERROR SMU_ISR_GEN_BIT(QUEUE_ERROR) -#define SMU_ISR_QUEUE_SUSPEND SMU_ISR_GEN_BIT(QUEUE_SUSPEND) -#define SMU_ISR_COMPLETION SMU_ISR_GEN_BIT(COMPLETION) - -/* ***************************************************************************** */ -#define SMU_INTERRUPT_MASK_COMPLETION_SHIFT (31) -#define SMU_INTERRUPT_MASK_COMPLETION_MASK (0x80000000) -#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_SHIFT (1) -#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_MASK (0x00000002) -#define SMU_INTERRUPT_MASK_QUEUE_ERROR_SHIFT (0) -#define SMU_INTERRUPT_MASK_QUEUE_ERROR_MASK (0x00000001) -#define SMU_INTERRUPT_MASK_RESERVED_MASK (0x7FFFFFFC) - -#define SMU_IMR_GEN_BIT(name) \ - SCU_GEN_BIT(SMU_INTERRUPT_MASK_ ## name) - -#define SMU_IMR_QUEUE_ERROR SMU_IMR_GEN_BIT(QUEUE_ERROR) -#define SMU_IMR_QUEUE_SUSPEND SMU_IMR_GEN_BIT(QUEUE_SUSPEND) -#define SMU_IMR_COMPLETION SMU_IMR_GEN_BIT(COMPLETION) - -/* ***************************************************************************** */ -#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_SHIFT (0) -#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_MASK (0x0000001F) -#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_SHIFT (8) -#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_MASK (0x0000FF00) -#define SMU_INTERRUPT_COALESCING_CONTROL_RESERVED_MASK (0xFFFF00E0) - -#define SMU_ICC_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SMU_INTERRUPT_COALESCING_CONTROL_ ## name, value) - -/* ***************************************************************************** */ -#define SMU_TASK_CONTEXT_RANGE_START_SHIFT (0) -#define SMU_TASK_CONTEXT_RANGE_START_MASK (0x00000FFF) -#define SMU_TASK_CONTEXT_RANGE_ENDING_SHIFT (16) -#define SMU_TASK_CONTEXT_RANGE_ENDING_MASK (0x0FFF0000) -#define SMU_TASK_CONTEXT_RANGE_ENABLE_SHIFT (31) -#define SMU_TASK_CONTEXT_RANGE_ENABLE_MASK (0x80000000) -#define SMU_TASK_CONTEXT_RANGE_RESERVED_MASK (0x7000F000) - -#define SMU_TCR_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SMU_TASK_CONTEXT_RANGE_ ## name, value) - -#define SMU_TCR_GEN_BIT(name, value) \ - SCU_GEN_BIT(SMU_TASK_CONTEXT_RANGE_ ## name) - -/* ***************************************************************************** */ - -#define SMU_COMPLETION_QUEUE_PUT_POINTER_SHIFT (0) -#define SMU_COMPLETION_QUEUE_PUT_POINTER_MASK (0x00003FFF) -#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_SHIFT (15) -#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_MASK (0x00008000) -#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_SHIFT (16) -#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_MASK (0x03FF0000) -#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_SHIFT (26) -#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_MASK (0x04000000) -#define SMU_COMPLETION_QUEUE_PUT_RESERVED_MASK (0xF8004000) - -#define SMU_CQPR_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_PUT_ ## name, value) - -#define SMU_CQPR_GEN_BIT(name) \ - SCU_GEN_BIT(SMU_COMPLETION_QUEUE_PUT_ ## name) - -/* ***************************************************************************** */ - -#define SMU_COMPLETION_QUEUE_GET_POINTER_SHIFT (0) -#define SMU_COMPLETION_QUEUE_GET_POINTER_MASK (0x00003FFF) -#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT (15) -#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_MASK (0x00008000) -#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT (16) -#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK (0x03FF0000) -#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT (26) -#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_MASK (0x04000000) -#define SMU_COMPLETION_QUEUE_GET_ENABLE_SHIFT (30) -#define SMU_COMPLETION_QUEUE_GET_ENABLE_MASK (0x40000000) -#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_SHIFT (31) -#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_MASK (0x80000000) -#define SMU_COMPLETION_QUEUE_GET_RESERVED_MASK (0x38004000) - -#define SMU_CQGR_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_GET_ ## name, value) - -#define SMU_CQGR_GEN_BIT(name) \ - SCU_GEN_BIT(SMU_COMPLETION_QUEUE_GET_ ## name) - -#define SMU_CQGR_CYCLE_BIT \ - SMU_CQGR_GEN_BIT(CYCLE_BIT) - -#define SMU_CQGR_EVENT_CYCLE_BIT \ - SMU_CQGR_GEN_BIT(EVENT_CYCLE_BIT) - -#define SMU_CQGR_GET_POINTER_SET(value) \ - SMU_CQGR_GEN_VAL(POINTER, value) - - -/* ***************************************************************************** */ -#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_SHIFT (0) -#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_MASK (0x00003FFF) -#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_SHIFT (16) -#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_MASK (0x03FF0000) -#define SMU_COMPLETION_QUEUE_CONTROL_RESERVED_MASK (0xFC00C000) - -#define SMU_CQC_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_CONTROL_ ## name, value) - -#define SMU_CQC_QUEUE_LIMIT_SET(value) \ - SMU_CQC_GEN_VAL(QUEUE_LIMIT, value) - -#define SMU_CQC_EVENT_LIMIT_SET(value) \ - SMU_CQC_GEN_VAL(EVENT_LIMIT, value) - - -/* ***************************************************************************** */ -#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT (0) -#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK (0x00000FFF) -#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT (12) -#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK (0x00007000) -#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT (15) -#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK (0x07FF8000) -#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_SHIFT (27) -#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK (0x08000000) -#define SMU_DEVICE_CONTEXT_CAPACITY_RESERVED_MASK (0xF0000000) - -#define SMU_DCC_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SMU_DEVICE_CONTEXT_CAPACITY_ ## name, value) - -#define SMU_DCC_GET_MAX_PEG(value) \ - (\ - ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK) \ - >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \ - ) - -#define SMU_DCC_GET_MAX_LP(value) \ - (\ - ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ - >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \ - ) - -#define SMU_DCC_GET_MAX_TC(value) \ - (\ - ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ - >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT \ - ) - -#define SMU_DCC_GET_MAX_RNC(value) \ - (\ - ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ - >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT \ - ) - -/* -------------------------------------------------------------------------- */ - -#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_SHIFT (0) -#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_MASK (0x00000001) -#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_SHIFT (1) -#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_MASK (0x00000002) -#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_SHIFT (16) -#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_MASK (0x00010000) -#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_SHIFT (17) -#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_MASK (0x00020000) -#define SMU_CONTROL_STATUS_RESERVED_MASK (0xFFFCFFFC) - -#define SMU_SMUCSR_GEN_BIT(name) \ - SCU_GEN_BIT(SMU_CONTROL_STATUS_ ## name) - -#define SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \ - (SMU_SMUCSR_GEN_BIT(SCHEDULER_RAM_INIT_COMPLETED)) - -#define SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \ - (SMU_SMUCSR_GEN_BIT(CONTEXT_RAM_INIT_COMPLETED)) - -#define SCU_RAM_INIT_COMPLETED \ - (\ - SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \ - | SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \ - ) - -/* -------------------------------------------------------------------------- */ - -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_SHIFT (0) -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_MASK (0x00000001) -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_SHIFT (1) -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_MASK (0x00000002) -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_SHIFT (2) -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_MASK (0x00000004) -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_SHIFT (3) -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_MASK (0x00000008) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_SHIFT (8) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_MASK (0x00000100) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_SHIFT (9) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_MASK (0x00000200) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_SHIFT (10) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_MASK (0x00000400) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_SHIFT (11) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_MASK (0x00000800) - -#define SMU_RESET_PROTOCOL_ENGINE(peg, pe) \ - ((1 << (pe)) << ((peg) * 8)) - -#define SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \ - (\ - SMU_RESET_PROTOCOL_ENGINE(peg, 0) \ - | SMU_RESET_PROTOCOL_ENGINE(peg, 1) \ - | SMU_RESET_PROTOCOL_ENGINE(peg, 2) \ - | SMU_RESET_PROTOCOL_ENGINE(peg, 3) \ - ) - -#define SMU_RESET_ALL_PROTOCOL_ENGINES() \ - (\ - SMU_RESET_PEG_PROTOCOL_ENGINES(0) \ - | SMU_RESET_PEG_PROTOCOL_ENGINES(1) \ - ) - -#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_SHIFT (16) -#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_MASK (0x00010000) -#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_SHIFT (17) -#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_MASK (0x00020000) -#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_SHIFT (18) -#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_MASK (0x00040000) -#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_SHIFT (19) -#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_MASK (0x00080000) - -#define SMU_RESET_WIDE_PORT_QUEUE(peg, wide_port) \ - ((1 << ((wide_port) / 2)) << ((peg) * 2) << 16) - -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_SHIFT (20) -#define SMU_SOFTRESET_CONTROL_RESET_PEG0_MASK (0x00100000) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_SHIFT (21) -#define SMU_SOFTRESET_CONTROL_RESET_PEG1_MASK (0x00200000) -#define SMU_SOFTRESET_CONTROL_RESET_SCU_SHIFT (22) -#define SMU_SOFTRESET_CONTROL_RESET_SCU_MASK (0x00400000) - -/* - * It seems to make sense that if you are going to reset the protocol - * engine group that you would also reset all of the protocol engines */ -#define SMU_RESET_PROTOCOL_ENGINE_GROUP(peg) \ - (\ - (1 << ((peg) + 20)) \ - | SMU_RESET_WIDE_PORT_QUEUE(peg, 0) \ - | SMU_RESET_WIDE_PORT_QUEUE(peg, 1) \ - | SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \ - ) - -#define SMU_RESET_ALL_PROTOCOL_ENGINE_GROUPS() \ - (\ - SMU_RESET_PROTOCOL_ENGINE_GROUP(0) \ - | SMU_RESET_PROTOCOL_ENGINE_GROUP(1) \ - ) - -#define SMU_RESET_SCU() (0xFFFFFFFF) - - - -/* ***************************************************************************** */ -#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_SHIFT (0) -#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_MASK (0x00000FFF) -#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_SHIFT (16) -#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_MASK (0x0FFF0000) -#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_SHIFT (31) -#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_MASK (0x80000000) -#define SMU_TASK_CONTEXT_ASSIGNMENT_RESERVED_MASK (0x7000F000) - -#define SMU_TCA_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name, value) - -#define SMU_TCA_GEN_BIT(name) \ - SCU_GEN_BIT(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name) - -/* ***************************************************************************** */ -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_SHIFT (0) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_MASK (0x00000FFF) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_RESERVED_MASK (0xFFFFF000) - -#define SCU_UFQC_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_ ## name, value) - -#define SCU_UFQC_QUEUE_SIZE_SET(value) \ - SCU_UFQC_GEN_VAL(QUEUE_SIZE, value) - -/* ***************************************************************************** */ -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_SHIFT (0) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_MASK (0x00000FFF) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_SHIFT (12) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_MASK (0x00001000) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_RESERVED_MASK (0xFFFFE000) - -#define SCU_UFQPP_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name, value) - -#define SCU_UFQPP_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name) - -/* - * ***************************************************************************** - * * SDMA Registers - * ***************************************************************************** */ -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_SHIFT (0) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_MASK (0x00000FFF) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_SHIFT (12) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_MASK (12) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_SHIFT (31) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_MASK (0x80000000) -#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_RESERVED_MASK (0x7FFFE000) - -#define SCU_UFQGP_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name, value) - -#define SCU_UFQGP_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name) - -#define SCU_UFQGP_CYCLE_BIT(value) \ - SCU_UFQGP_GEN_BIT(CYCLE_BIT, value) - -#define SCU_UFQGP_GET_POINTER(value) \ - SCU_UFQGP_GEN_VALUE(POINTER, value) - -#define SCU_UFQGP_ENABLE(value) \ - (SCU_UFQGP_GEN_BIT(ENABLE) | value) - -#define SCU_UFQGP_DISABLE(value) \ - (~SCU_UFQGP_GEN_BIT(ENABLE) & value) - -#define SCU_UFQGP_VALUE(bit, value) \ - (SCU_UFQGP_CYCLE_BIT(bit) | SCU_UFQGP_GET_POINTER(value)) - -/* ***************************************************************************** */ -#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SHIFT (0) -#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_MASK (0x0000FFFF) -#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT (16) -#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK (0x00010000) -#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_SHIFT (17) -#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_MASK (0x00020000) -#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_SHIFT (18) -#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_MASK (0x00040000) -#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_SHIFT (19) -#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_MASK (0x00080000) -#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_SHIFT (20) -#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_MASK (0x00100000) -#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_SHIFT (21) -#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_MASK (0x00200000) -#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_SHIFT (22) -#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_MASK (0x00400000) -#define SCU_PDMA_CONFIGURATION_RESERVED_MASK (0xFF800000) - -#define SCU_PDMACR_GEN_VALUE(name, value) \ - SCU_GEN_VALUE(SCU_PDMA_CONFIGURATION_ ## name, value) - -#define SCU_PDMACR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_PDMA_CONFIGURATION_ ## name) - -#define SCU_PDMACR_BE_GEN_BIT(name) \ - SCU_PCMACR_GEN_BIT(BIG_ENDIAN_CONTROL_ ## name) - -/* ***************************************************************************** */ -#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT (8) -#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK (0x00000100) - -#define SCU_CDMACR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_CDMA_CONFIGURATION_ ## name) - -/* - * ***************************************************************************** - * * SCU Link Layer Registers - * ***************************************************************************** */ -#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_SHIFT (0) -#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_MASK (0x000000FF) -#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_SHIFT (8) -#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_MASK (0x0000FF00) -#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_SHIFT (16) -#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_MASK (0x00FF0000) -#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_SHIFT (24) -#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_MASK (0xFF000000) -#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_REQUIRED_MASK (0x00000000) -#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_DEFAULT_MASK (0x7D00676F) -#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_RESERVED_MASK (0x00FF0000) - -#define SCU_SAS_SPDTOV_GEN_VALUE(name, value) \ - SCU_GEN_VALUE(SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_ ## name, value) - - -#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_SHIFT (2) -#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_MASK (0x00000004) -#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_SHIFT (4) -#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_MASK (0x00000010) -#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_SHIFT (5) -#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_MASK (0x00000020) -#define SCU_LINK_STATUS_RESERVED_MASK (0xFFFFFFCD) - -#define SCU_SAS_LLSTA_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_LINK_STATUS_ ## name) - - -/* TODO: Where is the SATA_PSELTOV register? */ - -/* - * ***************************************************************************** - * * SCU SAS Maximum Arbitration Wait Time Timeout Register - * ***************************************************************************** */ -#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_SHIFT (0) -#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_MASK (0x00007FFF) -#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_SHIFT (15) -#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_MASK (0x00008000) - -#define SCU_SAS_MAWTTOV_GEN_VALUE(name, value) \ - SCU_GEN_VALUE(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name, value) - -#define SCU_SAS_MAWTTOV_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name) - - -/* - * TODO: Where is the SAS_LNKTOV regsiter? - * TODO: Where is the SAS_PHYTOV register? */ - -#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_SHIFT (1) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_MASK (0x00000002) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_SHIFT (2) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_MASK (0x00000004) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_SHIFT (3) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_MASK (0x00000008) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_SHIFT (8) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_MASK (0x00000100) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_SHIFT (9) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_MASK (0x00000200) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_SHIFT (10) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_MASK (0x00000400) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_SHIFT (11) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_MASK (0x00000800) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_SHIFT (16) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_MASK (0x000F0000) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_SHIFT (24) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_MASK (0x0F000000) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_SHIFT (28) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_MASK (0x70000000) -#define SCU_SAS_TRANSMIT_IDENTIFICATION_RESERVED_MASK (0x80F0F1F1) - -#define SCU_SAS_TIID_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name, value) - -#define SCU_SAS_TIID_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name) - -/* SAS Identify Frame PHY Identifier Register */ -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_SHIFT (16) -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_MASK (0x00010000) -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_SHIFT (17) -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_MASK (0x00020000) -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_SHIFT (18) -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_MASK (0x00040000) -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_SHIFT (24) -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_MASK (0xFF000000) -#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_RESERVED_MASK (0x00F800FF) - -#define SCU_SAS_TIPID_GEN_VALUE(name, value) \ - SCU_GEN_VALUE(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name, value) - -#define SCU_SAS_TIPID_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name) - - -#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_SHIFT (4) -#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_MASK (0x00000010) -#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_SHIFT (6) -#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_MASK (0x00000040) -#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_SHIFT (7) -#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_MASK (0x00000080) -#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_SHIFT (8) -#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_MASK (0x00000100) -#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_SHIFT (9) -#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_MASK (0x00000200) -#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_SHIFT (11) -#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_MASK (0x00000800) -#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_SHIFT (12) -#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_MASK (0x00001000) -#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_SHIFT (13) -#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_MASK (0x00002000) -#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_SHIFT (14) -#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_MASK (0x00004000) -#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_SHIFT (15) -#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_MASK (0x00008000) -#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_SHIFT (23) -#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_MASK (0x00800000) -#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_SHIFT (27) -#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_MASK (0x08000000) -#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_SHIFT (28) -#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_MASK (0x10000000) -#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_SHIFT (29) -#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_MASK (0x20000000) -#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_SHIFT (30) -#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_MASK (0x40000000) -#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_SHIFT (31) -#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_MASK (0x80000000) -#define SCU_SAS_PHY_CONFIGURATION_REQUIRED_MASK (0x0100000F) -#define SCU_SAS_PHY_CONFIGURATION_DEFAULT_MASK (0x4180100F) -#define SCU_SAS_PHY_CONFIGURATION_RESERVED_MASK (0x00000000) - -#define SCU_SAS_PCFG_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_SAS_PHY_CONFIGURATION_ ## name) - -#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_SHIFT (0) -#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_MASK (0x000007FF) -#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_SHIFT (16) -#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_MASK (0x00ff0000) - -#define SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_##name, value) - -#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_SHIFT (0) -#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_MASK (0x0003FFFF) -#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_SHIFT (31) -#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_MASK (0x80000000) -#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_RESERVED_MASK (0x7FFC0000) - -#define SCU_ENSPINUP_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name, value) - -#define SCU_ENSPINUP_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name) - - -#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_SHIFT (1) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_MASK (0x00000002) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_SHIFT (4) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_MASK (0x000000F0) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_SHIFT (8) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_MASK (0x00000100) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_SHIFT (9) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_MASK (0x00000201) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_SHIFT (10) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_MASK (0x00000401) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_SHIFT (11) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_MASK (0x00000801) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_SHIFT (12) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_MASK (0x00001001) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_SHIFT (13) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_MASK (0x00002001) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_SHIFT (31) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_MASK (0x80000000) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_DEFAULT_MASK (0x00003F01) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_REQUIRED_MASK (0x00000001) -#define SCU_LINK_LAYER_PHY_CAPABILITIES_RESERVED_MASK (0x7FFFC00D) - -#define SCU_SAS_PHYCAP_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name, value) - -#define SCU_SAS_PHYCAP_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name) - - -#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_SHIFT (0) -#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_MASK (0x000000FF) -#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_SHIFT (31) -#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_MASK (0x80000000) -#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_RESERVED_MASK (0x7FFFFF00) - -#define SCU_PSZGCR_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name, value) - -#define SCU_PSZGCR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name) - -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_SHIFT (1) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_MASK (0x00000002) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_SHIFT (2) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_MASK (0x00000004) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_SHIFT (4) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_MASK (0x00000010) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_SHIFT (5) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_MASK (0x00000020) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_SHIFT (16) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_MASK (0x00030000) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_SHIFT (19) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_MASK (0x00080000) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_SHIFT (20) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_MASK (0x00300000) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_SHIFT (23) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_MASK (0x00800000) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_SHIFT (24) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_MASK (0x03000000) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_SHIFT (27) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_MASK (0x08000000) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_SHIFT (28) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_MASK (0x30000000) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_SHIFT (31) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_MASK (0x80000000) -#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_RESERVED_MASK (0x4444FFC9) - -#define SCU_PEG_SCUVZECR_GEN_VAL(name, val) \ - SCU_GEN_VALUE(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name, val) - -#define SCU_PEG_SCUVZECR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name) - - -/* - * ***************************************************************************** - * * Port Task Scheduler registers shift and mask values - * ***************************************************************************** */ -#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_SHIFT (0) -#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_MASK (0x0000FFFF) -#define SCU_PTSG_CONTROL_TASK_TIMEOUT_SHIFT (16) -#define SCU_PTSG_CONTROL_TASK_TIMEOUT_MASK (0x00FF0000) -#define SCU_PTSG_CONTROL_PTSG_ENABLE_SHIFT (24) -#define SCU_PTSG_CONTROL_PTSG_ENABLE_MASK (0x01000000) -#define SCU_PTSG_CONTROL_ETM_ENABLE_SHIFT (25) -#define SCU_PTSG_CONTROL_ETM_ENABLE_MASK (0x02000000) -#define SCU_PTSG_CONTROL_DEFAULT_MASK (0x00020002) -#define SCU_PTSG_CONTROL_REQUIRED_MASK (0x00000000) -#define SCU_PTSG_CONTROL_RESERVED_MASK (0xFC000000) - -#define SCU_PTSGCR_GEN_VAL(name, val) \ - SCU_GEN_VALUE(SCU_PTSG_CONTROL_ ## name, val) - -#define SCU_PTSGCR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_PTSG_CONTROL_ ## name) - - -/* ***************************************************************************** */ -#define SCU_PTSG_REAL_TIME_CLOCK_SHIFT (0) -#define SCU_PTSG_REAL_TIME_CLOCK_MASK (0x0000FFFF) -#define SCU_PTSG_REAL_TIME_CLOCK_RESERVED_MASK (0xFFFF0000) - -#define SCU_RTCR_GEN_VAL(name, val) \ - SCU_GEN_VALUE(SCU_PTSG_ ## name, val) - - -#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_SHIFT (0) -#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_MASK (0x00FFFFFF) -#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_RESERVED_MASK (0xFF000000) - -#define SCU_RTCCR_GEN_VAL(name, val) \ - SCU_GEN_VALUE(SCU_PTSG_REAL_TIME_CLOCK_CONTROL_ ## name, val) - - -#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_SHIFT (0) -#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_MASK (0x00000001) -#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_SHIFT (1) -#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_MASK (0x00000002) -#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_RESERVED_MASK (0xFFFFFFFC) - -#define SCU_PTSxCR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ ## name) - - -#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_SHIFT (0) -#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_MASK (0x00000001) -#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_SHIFT (1) -#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_MASK (0x00000002) -#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_SHIFT (2) -#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_MASK (0x00000004) -#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_RESERVED_MASK (0xFFFFFFF8) - -#define SCU_PTSxSR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ ## name) - - -/* - * ***************************************************************************** - * * SGPIO Register shift and mask values - * ***************************************************************************** */ -#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_SHIFT (0) -#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_MASK (0x00000001) -#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_SHIFT (1) -#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_MASK (0x00000002) -#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_SHIFT (2) -#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_MASK (0x00000004) -#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_SHIFT (15) -#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_MASK (0x00008000) -#define SCU_SGPIO_CONTROL_SGPIO_RESERVED_MASK (0xFFFF7FF8) - -#define SCU_SGICRx_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_SGPIO_CONTROL_SGPIO_ ## name) - -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_SHIFT (0) -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_MASK (0x0000000F) -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_SHIFT (4) -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_MASK (0x000000F0) -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_SHIFT (8) -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_MASK (0x00000F00) -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_SHIFT (12) -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_MASK (0x0000F000) -#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_RESERVED_MASK (0xFFFF0000) - -#define SCU_SGPBRx_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_ ## name, value) - -#define SCU_SGPIO_START_DRIVE_LOWER_R0_SHIFT (0) -#define SCU_SGPIO_START_DRIVE_LOWER_R0_MASK (0x00000003) -#define SCU_SGPIO_START_DRIVE_LOWER_R1_SHIFT (4) -#define SCU_SGPIO_START_DRIVE_LOWER_R1_MASK (0x00000030) -#define SCU_SGPIO_START_DRIVE_LOWER_R2_SHIFT (8) -#define SCU_SGPIO_START_DRIVE_LOWER_R2_MASK (0x00000300) -#define SCU_SGPIO_START_DRIVE_LOWER_R3_SHIFT (12) -#define SCU_SGPIO_START_DRIVE_LOWER_R3_MASK (0x00003000) -#define SCU_SGPIO_START_DRIVE_LOWER_RESERVED_MASK (0xFFFF8888) - -#define SCU_SGSDLRx_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value) - -#define SCU_SGPIO_START_DRIVE_UPPER_R0_SHIFT (0) -#define SCU_SGPIO_START_DRIVE_UPPER_R0_MASK (0x00000003) -#define SCU_SGPIO_START_DRIVE_UPPER_R1_SHIFT (4) -#define SCU_SGPIO_START_DRIVE_UPPER_R1_MASK (0x00000030) -#define SCU_SGPIO_START_DRIVE_UPPER_R2_SHIFT (8) -#define SCU_SGPIO_START_DRIVE_UPPER_R2_MASK (0x00000300) -#define SCU_SGPIO_START_DRIVE_UPPER_R3_SHIFT (12) -#define SCU_SGPIO_START_DRIVE_UPPER_R3_MASK (0x00003000) -#define SCU_SGPIO_START_DRIVE_UPPER_RESERVED_MASK (0xFFFF8888) - -#define SCU_SGSDURx_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value) - -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_SHIFT (0) -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_MASK (0x00000003) -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_SHIFT (4) -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_MASK (0x00000030) -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_SHIFT (8) -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_MASK (0x00000300) -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_SHIFT (12) -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_MASK (0x00003000) -#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_RESERVED_MASK (0xFFFF8888) - -#define SCU_SGSIDLRx_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value) - -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_SHIFT (0) -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_MASK (0x00000003) -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_SHIFT (4) -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_MASK (0x00000030) -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_SHIFT (8) -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_MASK (0x00000300) -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_SHIFT (12) -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_MASK (0x00003000) -#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_RESERVED_MASK (0xFFFF8888) - -#define SCU_SGSIDURx_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value) - -#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_SHIFT (0) -#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_MASK (0x0000000F) -#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_RESERVED_MASK (0xFFFFFFF0) - -#define SCU_SGVSCR_GEN_VAL(value) \ - SCU_GEN_VALUE(SCU_SGPIO_VENDOR_SPECIFIC_CODE ## name, value) - -#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_SHIFT (0) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_MASK (0x00000003) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_SHIFT (2) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_MASK (0x00000004) -#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_SHIFT (3) -#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_MASK (0x00000008) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_SHIFT (4) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_MASK (0x00000030) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_SHIFT (6) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_MASK (0x00000040) -#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_SHIFT (7) -#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_MASK (0x00000080) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_SHIFT (8) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_MASK (0x00000300) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_SHIFT (10) -#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_MASK (0x00000400) -#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_SHIFT (11) -#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_MASK (0x00000800) -#define SCU_SGPIO_OUPUT_DATA_SELECT_RESERVED_MASK (0xFFFFF000) - -#define SCU_SGODSR_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name, value) - -#define SCU_SGODSR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name) - -/* - * ***************************************************************************** - * * SMU Registers - * ***************************************************************************** */ - -/* - * ---------------------------------------------------------------------------- - * SMU Registers - * These registers are based off of BAR0 - * - * To calculate the offset for other functions use - * BAR0 + FN# * SystemPageSize * 2 - * - * The TCA is only accessable from FN#0 (Physical Function) and each - * is programmed by (BAR0 + SCU_SMU_TCA_OFFSET + (FN# * 0x04)) or - * TCA0 for FN#0 is at BAR0 + 0x0400 - * TCA1 for FN#1 is at BAR0 + 0x0404 - * etc. - * ---------------------------------------------------------------------------- - * Accessable to all FN#s */ -#define SCU_SMU_PCP_OFFSET 0x0000 -#define SCU_SMU_AMR_OFFSET 0x0004 -#define SCU_SMU_ISR_OFFSET 0x0010 -#define SCU_SMU_IMR_OFFSET 0x0014 -#define SCU_SMU_ICC_OFFSET 0x0018 -#define SCU_SMU_HTTLBAR_OFFSET 0x0020 -#define SCU_SMU_HTTUBAR_OFFSET 0x0024 -#define SCU_SMU_TCR_OFFSET 0x0028 -#define SCU_SMU_CQLBAR_OFFSET 0x0030 -#define SCU_SMU_CQUBAR_OFFSET 0x0034 -#define SCU_SMU_CQPR_OFFSET 0x0040 -#define SCU_SMU_CQGR_OFFSET 0x0044 -#define SCU_SMU_CQC_OFFSET 0x0048 -/* Accessable to FN#0 only */ -#define SCU_SMU_RNCLBAR_OFFSET 0x0080 -#define SCU_SMU_RNCUBAR_OFFSET 0x0084 -#define SCU_SMU_DCC_OFFSET 0x0090 -#define SCU_SMU_DFC_OFFSET 0x0094 -#define SCU_SMU_SMUCSR_OFFSET 0x0098 -#define SCU_SMU_SCUSRCR_OFFSET 0x009C -#define SCU_SMU_SMAW_OFFSET 0x00A0 -#define SCU_SMU_SMDW_OFFSET 0x00A4 -/* Accessable to FN#0 only */ -#define SCU_SMU_TCA_OFFSET 0x0400 -/* Accessable to all FN#s */ -#define SCU_SMU_MT_MLAR0_OFFSET 0x2000 -#define SCU_SMU_MT_MUAR0_OFFSET 0x2004 -#define SCU_SMU_MT_MDR0_OFFSET 0x2008 -#define SCU_SMU_MT_VCR0_OFFSET 0x200C -#define SCU_SMU_MT_MLAR1_OFFSET 0x2010 -#define SCU_SMU_MT_MUAR1_OFFSET 0x2014 -#define SCU_SMU_MT_MDR1_OFFSET 0x2018 -#define SCU_SMU_MT_VCR1_OFFSET 0x201C -#define SCU_SMU_MPBA_OFFSET 0x3000 - -/** - * struct smu_registers - These are the SMU registers - * - * - */ -struct smu_registers { -/* 0x0000 PCP */ - u32 post_context_port; -/* 0x0004 AMR */ - u32 address_modifier; - u32 reserved_08; - u32 reserved_0C; -/* 0x0010 ISR */ - u32 interrupt_status; -/* 0x0014 IMR */ - u32 interrupt_mask; -/* 0x0018 ICC */ - u32 interrupt_coalesce_control; - u32 reserved_1C; -/* 0x0020 HTTLBAR */ - u32 host_task_table_lower; -/* 0x0024 HTTUBAR */ - u32 host_task_table_upper; -/* 0x0028 TCR */ - u32 task_context_range; - u32 reserved_2C; -/* 0x0030 CQLBAR */ - u32 completion_queue_lower; -/* 0x0034 CQUBAR */ - u32 completion_queue_upper; - u32 reserved_38; - u32 reserved_3C; -/* 0x0040 CQPR */ - u32 completion_queue_put; -/* 0x0044 CQGR */ - u32 completion_queue_get; -/* 0x0048 CQC */ - u32 completion_queue_control; - u32 reserved_4C; - u32 reserved_5x[4]; - u32 reserved_6x[4]; - u32 reserved_7x[4]; -/* - * Accessable to FN#0 only - * 0x0080 RNCLBAR */ - u32 remote_node_context_lower; -/* 0x0084 RNCUBAR */ - u32 remote_node_context_upper; - u32 reserved_88; - u32 reserved_8C; -/* 0x0090 DCC */ - u32 device_context_capacity; -/* 0x0094 DFC */ - u32 device_function_capacity; -/* 0x0098 SMUCSR */ - u32 control_status; -/* 0x009C SCUSRCR */ - u32 soft_reset_control; -/* 0x00A0 SMAW */ - u32 mmr_address_window; -/* 0x00A4 SMDW */ - u32 mmr_data_window; - u32 reserved_A8; - u32 reserved_AC; -/* A whole bunch of reserved space */ - u32 reserved_Bx[4]; - u32 reserved_Cx[4]; - u32 reserved_Dx[4]; - u32 reserved_Ex[4]; - u32 reserved_Fx[4]; - u32 reserved_1xx[64]; - u32 reserved_2xx[64]; - u32 reserved_3xx[64]; -/* - * Accessable to FN#0 only - * 0x0400 TCA */ - u32 task_context_assignment[256]; -/* MSI-X registers not included */ -}; - -/* - * ***************************************************************************** - * SDMA Registers - * ***************************************************************************** */ -#define SCU_SDMA_BASE 0x6000 -#define SCU_SDMA_PUFATLHAR_OFFSET 0x0000 -#define SCU_SDMA_PUFATUHAR_OFFSET 0x0004 -#define SCU_SDMA_UFLHBAR_OFFSET 0x0008 -#define SCU_SDMA_UFUHBAR_OFFSET 0x000C -#define SCU_SDMA_UFQC_OFFSET 0x0010 -#define SCU_SDMA_UFQPP_OFFSET 0x0014 -#define SCU_SDMA_UFQGP_OFFSET 0x0018 -#define SCU_SDMA_PDMACR_OFFSET 0x001C -#define SCU_SDMA_CDMACR_OFFSET 0x0080 - -/** - * struct scu_sdma_registers - These are the SCU SDMA Registers - * - * - */ -struct scu_sdma_registers { -/* 0x0000 PUFATLHAR */ - u32 uf_address_table_lower; -/* 0x0004 PUFATUHAR */ - u32 uf_address_table_upper; -/* 0x0008 UFLHBAR */ - u32 uf_header_base_address_lower; -/* 0x000C UFUHBAR */ - u32 uf_header_base_address_upper; -/* 0x0010 UFQC */ - u32 unsolicited_frame_queue_control; -/* 0x0014 UFQPP */ - u32 unsolicited_frame_put_pointer; -/* 0x0018 UFQGP */ - u32 unsolicited_frame_get_pointer; -/* 0x001C PDMACR */ - u32 pdma_configuration; -/* Reserved until offset 0x80 */ - u32 reserved_0020_007C[0x18]; -/* 0x0080 CDMACR */ - u32 cdma_configuration; -/* Remainder SDMA register space */ - u32 reserved_0084_0400[0xDF]; - -}; - -/* - * ***************************************************************************** - * * SCU Link Registers - * ***************************************************************************** */ -#define SCU_PEG0_OFFSET 0x0000 -#define SCU_PEG1_OFFSET 0x8000 - -#define SCU_TL0_OFFSET 0x0000 -#define SCU_TL1_OFFSET 0x0400 -#define SCU_TL2_OFFSET 0x0800 -#define SCU_TL3_OFFSET 0x0C00 - -#define SCU_LL_OFFSET 0x0080 -#define SCU_LL0_OFFSET (SCU_TL0_OFFSET + SCU_LL_OFFSET) -#define SCU_LL1_OFFSET (SCU_TL1_OFFSET + SCU_LL_OFFSET) -#define SCU_LL2_OFFSET (SCU_TL2_OFFSET + SCU_LL_OFFSET) -#define SCU_LL3_OFFSET (SCU_TL3_OFFSET + SCU_LL_OFFSET) - -/* Transport Layer Offsets (PEG + TL) */ -#define SCU_TLCR_OFFSET 0x0000 -#define SCU_TLADTR_OFFSET 0x0004 -#define SCU_TLTTMR_OFFSET 0x0008 -#define SCU_TLEECR0_OFFSET 0x000C -#define SCU_STPTLDARNI_OFFSET 0x0010 - - -#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_SHIFT (0) -#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_MASK (0x00000001) -#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_SHIFT (1) -#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_MASK (0x00000002) -#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_SHIFT (3) -#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_MASK (0x00000008) -#define SCU_TLCR_CMD_NAK_STATUS_CODE_SHIFT (4) -#define SCU_TLCR_CMD_NAK_STATUS_CODE_MASK (0x00000010) -#define SCU_TLCR_RESERVED_MASK (0xFFFFFFEB) - -#define SCU_TLCR_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_TLCR_ ## name) - -/** - * struct scu_transport_layer_registers - These are the SCU Transport Layer - * registers - * - * - */ -struct scu_transport_layer_registers { - /* 0x0000 TLCR */ - u32 control; - /* 0x0004 TLADTR */ - u32 arbitration_delay_timer; - /* 0x0008 TLTTMR */ - u32 timer_test_mode; - /* 0x000C reserved */ - u32 reserved_0C; - /* 0x0010 STPTLDARNI */ - u32 stp_rni; - /* 0x0014 TLFEWPORCTRL */ - u32 tlfe_wpo_read_control; - /* 0x0018 TLFEWPORDATA */ - u32 tlfe_wpo_read_data; - /* 0x001C RXTLSSCSR1 */ - u32 rxtl_single_step_control_status_1; - /* 0x0020 RXTLSSCSR2 */ - u32 rxtl_single_step_control_status_2; - /* 0x0024 AWTRDDCR */ - u32 tlfe_awt_retry_delay_debug_control; - /* Remainder of TL memory space */ - u32 reserved_0028_007F[0x16]; - -}; - -/* Protocol Engine Group Registers */ -#define SCU_SCUVZECRx_OFFSET 0x1080 - -/* Link Layer Offsets (PEG + TL + LL) */ -#define SCU_SAS_SPDTOV_OFFSET 0x0000 -#define SCU_SAS_LLSTA_OFFSET 0x0004 -#define SCU_SATA_PSELTOV_OFFSET 0x0008 -#define SCU_SAS_TIMETOV_OFFSET 0x0010 -#define SCU_SAS_LOSTOT_OFFSET 0x0014 -#define SCU_SAS_LNKTOV_OFFSET 0x0018 -#define SCU_SAS_PHYTOV_OFFSET 0x001C -#define SCU_SAS_AFERCNT_OFFSET 0x0020 -#define SCU_SAS_WERCNT_OFFSET 0x0024 -#define SCU_SAS_TIID_OFFSET 0x0028 -#define SCU_SAS_TIDNH_OFFSET 0x002C -#define SCU_SAS_TIDNL_OFFSET 0x0030 -#define SCU_SAS_TISSAH_OFFSET 0x0034 -#define SCU_SAS_TISSAL_OFFSET 0x0038 -#define SCU_SAS_TIPID_OFFSET 0x003C -#define SCU_SAS_TIRES2_OFFSET 0x0040 -#define SCU_SAS_ADRSTA_OFFSET 0x0044 -#define SCU_SAS_MAWTTOV_OFFSET 0x0048 -#define SCU_SAS_FRPLDFIL_OFFSET 0x0054 -#define SCU_SAS_RFCNT_OFFSET 0x0060 -#define SCU_SAS_TFCNT_OFFSET 0x0064 -#define SCU_SAS_RFDCNT_OFFSET 0x0068 -#define SCU_SAS_TFDCNT_OFFSET 0x006C -#define SCU_SAS_LERCNT_OFFSET 0x0070 -#define SCU_SAS_RDISERRCNT_OFFSET 0x0074 -#define SCU_SAS_CRERCNT_OFFSET 0x0078 -#define SCU_STPCTL_OFFSET 0x007C -#define SCU_SAS_PCFG_OFFSET 0x0080 -#define SCU_SAS_CLKSM_OFFSET 0x0084 -#define SCU_SAS_TXCOMWAKE_OFFSET 0x0088 -#define SCU_SAS_TXCOMINIT_OFFSET 0x008C -#define SCU_SAS_TXCOMSAS_OFFSET 0x0090 -#define SCU_SAS_COMINIT_OFFSET 0x0094 -#define SCU_SAS_COMWAKE_OFFSET 0x0098 -#define SCU_SAS_COMSAS_OFFSET 0x009C -#define SCU_SAS_SFERCNT_OFFSET 0x00A0 -#define SCU_SAS_CDFERCNT_OFFSET 0x00A4 -#define SCU_SAS_DNFERCNT_OFFSET 0x00A8 -#define SCU_SAS_PRSTERCNT_OFFSET 0x00AC -#define SCU_SAS_CNTCTL_OFFSET 0x00B0 -#define SCU_SAS_SSPTOV_OFFSET 0x00B4 -#define SCU_FTCTL_OFFSET 0x00B8 -#define SCU_FRCTL_OFFSET 0x00BC -#define SCU_FTWMRK_OFFSET 0x00C0 -#define SCU_ENSPINUP_OFFSET 0x00C4 -#define SCU_SAS_TRNTOV_OFFSET 0x00C8 -#define SCU_SAS_PHYCAP_OFFSET 0x00CC -#define SCU_SAS_PHYCTL_OFFSET 0x00D0 -#define SCU_SAS_LLCTL_OFFSET 0x00D8 -#define SCU_AFE_XCVRCR_OFFSET 0x00DC -#define SCU_AFE_LUTCR_OFFSET 0x00E0 - -#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_SHIFT (0) -#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_MASK (0x00000003) -#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 (0) -#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 (1) -#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3 (2) -#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_SHIFT (2) -#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_MASK (0x000003FC) -#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_SHIFT (16) -#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_MASK (0x00010000) -#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_SHIFT (17) -#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_MASK (0x00020000) -#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_SHIFT (24) -#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_MASK (0xFF000000) -#define SCU_SAS_LINK_LAYER_CONTROL_RESERVED (0x00FCFC00) - -#define SCU_SAS_LLCTL_GEN_VAL(name, value) \ - SCU_GEN_VALUE(SCU_SAS_LINK_LAYER_CONTROL_ ## name, value) - -#define SCU_SAS_LLCTL_GEN_BIT(name) \ - SCU_GEN_BIT(SCU_SAS_LINK_LAYER_CONTROL_ ## name) - - -/* #define SCU_FRXHECR_DCNT_OFFSET 0x00B0 */ -#define SCU_PSZGCR_OFFSET 0x00E4 -#define SCU_SAS_RECPHYCAP_OFFSET 0x00E8 -/* #define SCU_TX_LUTSEL_OFFSET 0x00B8 */ - -#define SCU_SAS_PTxC_OFFSET 0x00D4 /* Same offset as SAS_TCTSTM */ - -/** - * struct scu_link_layer_registers - SCU Link Layer Registers - * - * - */ -struct scu_link_layer_registers { -/* 0x0000 SAS_SPDTOV */ - u32 speed_negotiation_timers; -/* 0x0004 SAS_LLSTA */ - u32 link_layer_status; -/* 0x0008 SATA_PSELTOV */ - u32 port_selector_timeout; - u32 reserved0C; -/* 0x0010 SAS_TIMETOV */ - u32 timeout_unit_value; -/* 0x0014 SAS_RCDTOV */ - u32 rcd_timeout; -/* 0x0018 SAS_LNKTOV */ - u32 link_timer_timeouts; -/* 0x001C SAS_PHYTOV */ - u32 sas_phy_timeouts; -/* 0x0020 SAS_AFERCNT */ - u32 received_address_frame_error_counter; -/* 0x0024 SAS_WERCNT */ - u32 invalid_dword_counter; -/* 0x0028 SAS_TIID */ - u32 transmit_identification; -/* 0x002C SAS_TIDNH */ - u32 sas_device_name_high; -/* 0x0030 SAS_TIDNL */ - u32 sas_device_name_low; -/* 0x0034 SAS_TISSAH */ - u32 source_sas_address_high; -/* 0x0038 SAS_TISSAL */ - u32 source_sas_address_low; -/* 0x003C SAS_TIPID */ - u32 identify_frame_phy_id; -/* 0x0040 SAS_TIRES2 */ - u32 identify_frame_reserved; -/* 0x0044 SAS_ADRSTA */ - u32 received_address_frame; -/* 0x0048 SAS_MAWTTOV */ - u32 maximum_arbitration_wait_timer_timeout; -/* 0x004C SAS_PTxC */ - u32 transmit_primitive; -/* 0x0050 SAS_RORES */ - u32 error_counter_event_notification_control; -/* 0x0054 SAS_FRPLDFIL */ - u32 frxq_payload_fill_threshold; -/* 0x0058 SAS_LLHANG_TOT */ - u32 link_layer_hang_detection_timeout; - u32 reserved_5C; -/* 0x0060 SAS_RFCNT */ - u32 received_frame_count; -/* 0x0064 SAS_TFCNT */ - u32 transmit_frame_count; -/* 0x0068 SAS_RFDCNT */ - u32 received_dword_count; -/* 0x006C SAS_TFDCNT */ - u32 transmit_dword_count; -/* 0x0070 SAS_LERCNT */ - u32 loss_of_sync_error_count; -/* 0x0074 SAS_RDISERRCNT */ - u32 running_disparity_error_count; -/* 0x0078 SAS_CRERCNT */ - u32 received_frame_crc_error_count; -/* 0x007C STPCTL */ - u32 stp_control; -/* 0x0080 SAS_PCFG */ - u32 phy_configuration; -/* 0x0084 SAS_CLKSM */ - u32 clock_skew_management; -/* 0x0088 SAS_TXCOMWAKE */ - u32 transmit_comwake_signal; -/* 0x008C SAS_TXCOMINIT */ - u32 transmit_cominit_signal; -/* 0x0090 SAS_TXCOMSAS */ - u32 transmit_comsas_signal; -/* 0x0094 SAS_COMINIT */ - u32 cominit_control; -/* 0x0098 SAS_COMWAKE */ - u32 comwake_control; -/* 0x009C SAS_COMSAS */ - u32 comsas_control; -/* 0x00A0 SAS_SFERCNT */ - u32 received_short_frame_count; -/* 0x00A4 SAS_CDFERCNT */ - u32 received_frame_without_credit_count; -/* 0x00A8 SAS_DNFERCNT */ - u32 received_frame_after_done_count; -/* 0x00AC SAS_PRSTERCNT */ - u32 phy_reset_problem_count; -/* 0x00B0 SAS_CNTCTL */ - u32 counter_control; -/* 0x00B4 SAS_SSPTOV */ - u32 ssp_timer_timeout_values; -/* 0x00B8 FTCTL */ - u32 ftx_control; -/* 0x00BC FRCTL */ - u32 frx_control; -/* 0x00C0 FTWMRK */ - u32 ftx_watermark; -/* 0x00C4 ENSPINUP */ - u32 notify_enable_spinup_control; -/* 0x00C8 SAS_TRNTOV */ - u32 sas_training_sequence_timer_values; -/* 0x00CC SAS_PHYCAP */ - u32 phy_capabilities; -/* 0x00D0 SAS_PHYCTL */ - u32 phy_control; - u32 reserved_d4; -/* 0x00D8 LLCTL */ - u32 link_layer_control; -/* 0x00DC AFE_XCVRCR */ - u32 afe_xcvr_control; -/* 0x00E0 AFE_LUTCR */ - u32 afe_lookup_table_control; -/* 0x00E4 PSZGCR */ - u32 phy_source_zone_group_control; -/* 0x00E8 SAS_RECPHYCAP */ - u32 receive_phycap; - u32 reserved_ec; -/* 0x00F0 SNAFERXRSTCTL */ - u32 speed_negotiation_afe_rx_reset_control; -/* 0x00F4 SAS_SSIPMCTL */ - u32 power_management_control; -/* 0x00F8 SAS_PSPREQ_PRIM */ - u32 sas_pm_partial_request_primitive; -/* 0x00FC SAS_PSSREQ_PRIM */ - u32 sas_pm_slumber_request_primitive; -/* 0x0100 SAS_PPSACK_PRIM */ - u32 sas_pm_ack_primitive_register; -/* 0x0104 SAS_PSNAK_PRIM */ - u32 sas_pm_nak_primitive_register; -/* 0x0108 SAS_SSIPMTOV */ - u32 sas_primitive_timeout; - u32 reserved_10c; -/* 0x0110 - 0x011C PLAPRDCTRLxREG */ - u32 pla_product_control[4]; -/* 0x0120 PLAPRDSUMREG */ - u32 pla_product_sum; -/* 0x0124 PLACONTROLREG */ - u32 pla_control; -/* Remainder of memory space 896 bytes */ - u32 reserved_0128_037f[0x96]; - -}; - -/* - * 0x00D4 // Same offset as SAS_TCTSTM SAS_PTxC - * u32 primitive_transmit_control; */ - -/* - * ---------------------------------------------------------------------------- - * SGPIO - * ---------------------------------------------------------------------------- */ -#define SCU_SGPIO_OFFSET 0x1400 - -/* #define SCU_SGPIO_OFFSET 0x6000 // later moves to 0x1400 see HSD 652625 */ -#define SCU_SGPIO_SGICR_OFFSET 0x0000 -#define SCU_SGPIO_SGPBR_OFFSET 0x0004 -#define SCU_SGPIO_SGSDLR_OFFSET 0x0008 -#define SCU_SGPIO_SGSDUR_OFFSET 0x000C -#define SCU_SGPIO_SGSIDLR_OFFSET 0x0010 -#define SCU_SGPIO_SGSIDUR_OFFSET 0x0014 -#define SCU_SGPIO_SGVSCR_OFFSET 0x0018 -/* Address from 0x0820 to 0x083C */ -#define SCU_SGPIO_SGODSR_OFFSET 0x0020 - -/** - * struct scu_sgpio_registers - SCU SGPIO Registers - * - * - */ -struct scu_sgpio_registers { -/* 0x0000 SGPIO_SGICR */ - u32 interface_control; -/* 0x0004 SGPIO_SGPBR */ - u32 blink_rate; -/* 0x0008 SGPIO_SGSDLR */ - u32 start_drive_lower; -/* 0x000C SGPIO_SGSDUR */ - u32 start_drive_upper; -/* 0x0010 SGPIO_SGSIDLR */ - u32 serial_input_lower; -/* 0x0014 SGPIO_SGSIDUR */ - u32 serial_input_upper; -/* 0x0018 SGPIO_SGVSCR */ - u32 vendor_specific_code; -/* 0x0020 SGPIO_SGODSR */ - u32 ouput_data_select[8]; -/* Remainder of memory space 256 bytes */ - u32 reserved_1444_14ff[0x31]; - -}; - -/* - * ***************************************************************************** - * * Defines for VIIT entry offsets - * * Access additional entries by SCU_VIIT_BASE + index * 0x10 - * ***************************************************************************** */ -#define SCU_VIIT_BASE 0x1c00 - -struct scu_viit_registers { - u32 registers[256]; -}; - -/* - * ***************************************************************************** - * * SCU PORT TASK SCHEDULER REGISTERS - * ***************************************************************************** */ - -#define SCU_PTSG_BASE 0x1000 - -#define SCU_PTSG_PTSGCR_OFFSET 0x0000 -#define SCU_PTSG_RTCR_OFFSET 0x0004 -#define SCU_PTSG_RTCCR_OFFSET 0x0008 -#define SCU_PTSG_PTS0CR_OFFSET 0x0010 -#define SCU_PTSG_PTS0SR_OFFSET 0x0014 -#define SCU_PTSG_PTS1CR_OFFSET 0x0018 -#define SCU_PTSG_PTS1SR_OFFSET 0x001C -#define SCU_PTSG_PTS2CR_OFFSET 0x0020 -#define SCU_PTSG_PTS2SR_OFFSET 0x0024 -#define SCU_PTSG_PTS3CR_OFFSET 0x0028 -#define SCU_PTSG_PTS3SR_OFFSET 0x002C -#define SCU_PTSG_PCSPE0CR_OFFSET 0x0030 -#define SCU_PTSG_PCSPE1CR_OFFSET 0x0034 -#define SCU_PTSG_PCSPE2CR_OFFSET 0x0038 -#define SCU_PTSG_PCSPE3CR_OFFSET 0x003C -#define SCU_PTSG_ETMTSCCR_OFFSET 0x0040 -#define SCU_PTSG_ETMRNSCCR_OFFSET 0x0044 - -/** - * struct scu_port_task_scheduler_registers - These are the control/stats pairs - * for each Port Task Scheduler. - * - * - */ -struct scu_port_task_scheduler_registers { - u32 control; - u32 status; -}; - -/** - * struct scu_port_task_scheduler_group_registers - These are the PORT Task - * Scheduler registers - * - * - */ -struct scu_port_task_scheduler_group_registers { -/* 0x0000 PTSGCR */ - u32 control; -/* 0x0004 RTCR */ - u32 real_time_clock; -/* 0x0008 RTCCR */ - u32 real_time_clock_control; -/* 0x000C */ - u32 reserved_0C; -/* - * 0x0010 PTS0CR - * 0x0014 PTS0SR - * 0x0018 PTS1CR - * 0x001C PTS1SR - * 0x0020 PTS2CR - * 0x0024 PTS2SR - * 0x0028 PTS3CR - * 0x002C PTS3SR */ - struct scu_port_task_scheduler_registers port[4]; -/* - * 0x0030 PCSPE0CR - * 0x0034 PCSPE1CR - * 0x0038 PCSPE2CR - * 0x003C PCSPE3CR */ - u32 protocol_engine[4]; -/* 0x0040 ETMTSCCR */ - u32 tc_scanning_interval_control; -/* 0x0044 ETMRNSCCR */ - u32 rnc_scanning_interval_control; -/* Remainder of memory space 128 bytes */ - u32 reserved_1048_107f[0x0E]; - -}; - -#define SCU_PTSG_SCUVZECR_OFFSET 0x003C - -/* - * ***************************************************************************** - * * AFE REGISTERS - * ***************************************************************************** */ -#define SCU_AFE_MMR_BASE 0xE000 - -/* - * AFE 0 is at offset 0x0800 - * AFE 1 is at offset 0x0900 - * AFE 2 is at offset 0x0a00 - * AFE 3 is at offset 0x0b00 */ -struct scu_afe_transceiver { - /* 0x0000 AFE_XCVR_CTRL0 */ - u32 afe_xcvr_control0; - /* 0x0004 AFE_XCVR_CTRL1 */ - u32 afe_xcvr_control1; - /* 0x0008 */ - u32 reserved_0008; - /* 0x000c afe_dfx_rx_control0 */ - u32 afe_dfx_rx_control0; - /* 0x0010 AFE_DFX_RX_CTRL1 */ - u32 afe_dfx_rx_control1; - /* 0x0014 */ - u32 reserved_0014; - /* 0x0018 AFE_DFX_RX_STS0 */ - u32 afe_dfx_rx_status0; - /* 0x001c AFE_DFX_RX_STS1 */ - u32 afe_dfx_rx_status1; - /* 0x0020 */ - u32 reserved_0020; - /* 0x0024 AFE_TX_CTRL */ - u32 afe_tx_control; - /* 0x0028 AFE_TX_AMP_CTRL0 */ - u32 afe_tx_amp_control0; - /* 0x002c AFE_TX_AMP_CTRL1 */ - u32 afe_tx_amp_control1; - /* 0x0030 AFE_TX_AMP_CTRL2 */ - u32 afe_tx_amp_control2; - /* 0x0034 AFE_TX_AMP_CTRL3 */ - u32 afe_tx_amp_control3; - /* 0x0038 afe_tx_ssc_control */ - u32 afe_tx_ssc_control; - /* 0x003c */ - u32 reserved_003c; - /* 0x0040 AFE_RX_SSC_CTRL0 */ - u32 afe_rx_ssc_control0; - /* 0x0044 AFE_RX_SSC_CTRL1 */ - u32 afe_rx_ssc_control1; - /* 0x0048 AFE_RX_SSC_CTRL2 */ - u32 afe_rx_ssc_control2; - /* 0x004c AFE_RX_EQ_STS0 */ - u32 afe_rx_eq_status0; - /* 0x0050 AFE_RX_EQ_STS1 */ - u32 afe_rx_eq_status1; - /* 0x0054 AFE_RX_CDR_STS */ - u32 afe_rx_cdr_status; - /* 0x0058 */ - u32 reserved_0058; - /* 0x005c AFE_CHAN_CTRL */ - u32 afe_channel_control; - /* 0x0060-0x006c */ - u32 reserved_0060_006c[0x04]; - /* 0x0070 AFE_XCVR_EC_STS0 */ - u32 afe_xcvr_error_capture_status0; - /* 0x0074 AFE_XCVR_EC_STS1 */ - u32 afe_xcvr_error_capture_status1; - /* 0x0078 AFE_XCVR_EC_STS2 */ - u32 afe_xcvr_error_capture_status2; - /* 0x007c afe_xcvr_ec_status3 */ - u32 afe_xcvr_error_capture_status3; - /* 0x0080 AFE_XCVR_EC_STS4 */ - u32 afe_xcvr_error_capture_status4; - /* 0x0084 AFE_XCVR_EC_STS5 */ - u32 afe_xcvr_error_capture_status5; - /* 0x0088-0x00fc */ - u32 reserved_008c_00fc[0x1e]; -}; - -/** - * struct scu_afe_registers - AFE Regsiters - * - * - */ -/* Uaoa AFE registers */ -struct scu_afe_registers { - /* 0Xe000 AFE_BIAS_CTRL */ - u32 afe_bias_control; - u32 reserved_0004; - /* 0x0008 AFE_PLL_CTRL0 */ - u32 afe_pll_control0; - /* 0x000c AFE_PLL_CTRL1 */ - u32 afe_pll_control1; - /* 0x0010 AFE_PLL_CTRL2 */ - u32 afe_pll_control2; - /* 0x0014 AFE_CB_STS */ - u32 afe_common_block_status; - /* 0x0018-0x007c */ - u32 reserved_18_7c[0x1a]; - /* 0x0080 AFE_PMSN_MCTRL0 */ - u32 afe_pmsn_master_control0; - /* 0x0084 AFE_PMSN_MCTRL1 */ - u32 afe_pmsn_master_control1; - /* 0x0088 AFE_PMSN_MCTRL2 */ - u32 afe_pmsn_master_control2; - /* 0x008C-0x00fc */ - u32 reserved_008c_00fc[0x1D]; - /* 0x0100 AFE_DFX_MST_CTRL0 */ - u32 afe_dfx_master_control0; - /* 0x0104 AFE_DFX_MST_CTRL1 */ - u32 afe_dfx_master_control1; - /* 0x0108 AFE_DFX_DCL_CTRL */ - u32 afe_dfx_dcl_control; - /* 0x010c AFE_DFX_DMON_CTRL */ - u32 afe_dfx_digital_monitor_control; - /* 0x0110 AFE_DFX_AMONP_CTRL */ - u32 afe_dfx_analog_p_monitor_control; - /* 0x0114 AFE_DFX_AMONN_CTRL */ - u32 afe_dfx_analog_n_monitor_control; - /* 0x0118 AFE_DFX_NTL_STS */ - u32 afe_dfx_ntl_status; - /* 0x011c AFE_DFX_FIFO_STS0 */ - u32 afe_dfx_fifo_status0; - /* 0x0120 AFE_DFX_FIFO_STS1 */ - u32 afe_dfx_fifo_status1; - /* 0x0124 AFE_DFX_MPAT_CTRL */ - u32 afe_dfx_master_pattern_control; - /* 0x0128 AFE_DFX_P0_CTRL */ - u32 afe_dfx_p0_control; - /* 0x012c-0x01a8 AFE_DFX_P0_DRx */ - u32 afe_dfx_p0_data[32]; - /* 0x01ac */ - u32 reserved_01ac; - /* 0x01b0-0x020c AFE_DFX_P0_IRx */ - u32 afe_dfx_p0_instruction[24]; - /* 0x0210 */ - u32 reserved_0210; - /* 0x0214 AFE_DFX_P1_CTRL */ - u32 afe_dfx_p1_control; - /* 0x0218-0x245 AFE_DFX_P1_DRx */ - u32 afe_dfx_p1_data[16]; - /* 0x0258-0x029c */ - u32 reserved_0258_029c[0x12]; - /* 0x02a0-0x02bc AFE_DFX_P1_IRx */ - u32 afe_dfx_p1_instruction[8]; - /* 0x02c0-0x2fc */ - u32 reserved_02c0_02fc[0x10]; - /* 0x0300 AFE_DFX_TX_PMSN_CTRL */ - u32 afe_dfx_tx_pmsn_control; - /* 0x0304 AFE_DFX_RX_PMSN_CTRL */ - u32 afe_dfx_rx_pmsn_control; - u32 reserved_0308; - /* 0x030c AFE_DFX_NOA_CTRL0 */ - u32 afe_dfx_noa_control0; - /* 0x0310 AFE_DFX_NOA_CTRL1 */ - u32 afe_dfx_noa_control1; - /* 0x0314 AFE_DFX_NOA_CTRL2 */ - u32 afe_dfx_noa_control2; - /* 0x0318 AFE_DFX_NOA_CTRL3 */ - u32 afe_dfx_noa_control3; - /* 0x031c AFE_DFX_NOA_CTRL4 */ - u32 afe_dfx_noa_control4; - /* 0x0320 AFE_DFX_NOA_CTRL5 */ - u32 afe_dfx_noa_control5; - /* 0x0324 AFE_DFX_NOA_CTRL6 */ - u32 afe_dfx_noa_control6; - /* 0x0328 AFE_DFX_NOA_CTRL7 */ - u32 afe_dfx_noa_control7; - /* 0x032c-0x07fc */ - u32 reserved_032c_07fc[0x135]; - - /* 0x0800-0x0bfc */ - struct scu_afe_transceiver scu_afe_xcvr[4]; - - /* 0x0c00-0x0ffc */ - u32 reserved_0c00_0ffc[0x0100]; -}; - -struct scu_protocol_engine_group_registers { - u32 table[0xE0]; -}; - - -struct scu_viit_iit { - u32 table[256]; -}; - -/** - * Placeholder for the ZONE Partition Table information ZONING will not be - * included in the 1.1 release. - * - * - */ -struct scu_zone_partition_table { - u32 table[2048]; -}; - -/** - * Placeholder for the CRAM register since I am not sure if we need to - * read/write to these registers as yet. - * - * - */ -struct scu_completion_ram { - u32 ram[128]; -}; - -/** - * Placeholder for the FBRAM registers since I am not sure if we need to - * read/write to these registers as yet. - * - * - */ -struct scu_frame_buffer_ram { - u32 ram[128]; -}; - -#define scu_scratch_ram_SIZE_IN_DWORDS 256 - -/** - * Placeholder for the scratch RAM registers. - * - * - */ -struct scu_scratch_ram { - u32 ram[scu_scratch_ram_SIZE_IN_DWORDS]; -}; - -/** - * Placeholder since I am not yet sure what these registers are here for. - * - * - */ -struct noa_protocol_engine_partition { - u32 reserved[64]; -}; - -/** - * Placeholder since I am not yet sure what these registers are here for. - * - * - */ -struct noa_hub_partition { - u32 reserved[64]; -}; - -/** - * Placeholder since I am not yet sure what these registers are here for. - * - * - */ -struct noa_host_interface_partition { - u32 reserved[64]; -}; - -/** - * struct transport_link_layer_pair - The SCU Hardware pairs up the TL - * registers with the LL registers so we must place them adjcent to make the - * array of registers in the PEG. - * - * - */ -struct transport_link_layer_pair { - struct scu_transport_layer_registers tl; - struct scu_link_layer_registers ll; -}; - -/** - * struct scu_peg_registers - SCU Protocol Engine Memory mapped register space. - * These registers are unique to each protocol engine group. There can be - * at most two PEG for a single SCU part. - * - * - */ -struct scu_peg_registers { - struct transport_link_layer_pair pe[4]; - struct scu_port_task_scheduler_group_registers ptsg; - struct scu_protocol_engine_group_registers peg; - struct scu_sgpio_registers sgpio; - u32 reserved_01500_1BFF[0x1C0]; - struct scu_viit_entry viit[64]; - struct scu_zone_partition_table zpt0; - struct scu_zone_partition_table zpt1; -}; - -/** - * struct scu_registers - SCU regsiters including both PEG registers if we turn - * on that compile option. All of these registers are in the memory mapped - * space returned from BAR1. - * - * - */ -struct scu_registers { - /* 0x0000 - PEG 0 */ - struct scu_peg_registers peg0; - - /* 0x6000 - SDMA and Miscellaneous */ - struct scu_sdma_registers sdma; - struct scu_completion_ram cram; - struct scu_frame_buffer_ram fbram; - u32 reserved_6800_69FF[0x80]; - struct noa_protocol_engine_partition noa_pe; - struct noa_hub_partition noa_hub; - struct noa_host_interface_partition noa_if; - u32 reserved_6d00_7fff[0x4c0]; - - /* 0x8000 - PEG 1 */ - struct scu_peg_registers peg1; - - /* 0xE000 - AFE Registers */ - struct scu_afe_registers afe; - - /* 0xF000 - reserved */ - u32 reserved_f000_211fff[0x80c00]; - - /* 0x212000 - scratch RAM */ - struct scu_scratch_ram scratch_ram; -}; - -#endif /* _SCU_REGISTERS_HEADER_ */ diff --git a/drivers/scsi/isci/core/scu_task_context.h b/drivers/scsi/isci/core/scu_task_context.h deleted file mode 100644 index 7df87d923285..000000000000 --- a/drivers/scsi/isci/core/scu_task_context.h +++ /dev/null @@ -1,942 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCU_TASK_CONTEXT_H_ -#define _SCU_TASK_CONTEXT_H_ - -/** - * This file contains the structures and constants for the SCU hardware task - * context. - * - * - */ - - -/** - * enum scu_ssp_task_type - This enumberation defines the various SSP task - * types the SCU hardware will accept. The definition for the various task - * types the SCU hardware will accept can be found in the DS specification. - * - * - */ -typedef enum { - SCU_TASK_TYPE_IOREAD, /* /< IO READ direction or no direction */ - SCU_TASK_TYPE_IOWRITE, /* /< IO Write direction */ - SCU_TASK_TYPE_SMP_REQUEST, /* /< SMP Request type */ - SCU_TASK_TYPE_RESPONSE, /* /< Driver generated response frame (targt mode) */ - SCU_TASK_TYPE_RAW_FRAME, /* /< Raw frame request type */ - SCU_TASK_TYPE_PRIMITIVE /* /< Request for a primitive to be transmitted */ -} scu_ssp_task_type; - -/** - * enum scu_sata_task_type - This enumeration defines the various SATA task - * types the SCU hardware will accept. The definition for the various task - * types the SCU hardware will accept can be found in the DS specification. - * - * - */ -typedef enum { - SCU_TASK_TYPE_DMA_IN, /* /< Read request */ - SCU_TASK_TYPE_FPDMAQ_READ, /* /< NCQ read request */ - SCU_TASK_TYPE_PACKET_DMA_IN, /* /< Packet read request */ - SCU_TASK_TYPE_SATA_RAW_FRAME, /* /< Raw frame request */ - RESERVED_4, - RESERVED_5, - RESERVED_6, - RESERVED_7, - SCU_TASK_TYPE_DMA_OUT, /* /< Write request */ - SCU_TASK_TYPE_FPDMAQ_WRITE, /* /< NCQ write Request */ - SCU_TASK_TYPE_PACKET_DMA_OUT /* /< Packet write request */ -} scu_sata_task_type; - - -/** - * - * - * SCU_CONTEXT_TYPE - */ -#define SCU_TASK_CONTEXT_TYPE 0 -#define SCU_RNC_CONTEXT_TYPE 1 - -/** - * - * - * SCU_TASK_CONTEXT_VALIDITY - */ -#define SCU_TASK_CONTEXT_INVALID 0 -#define SCU_TASK_CONTEXT_VALID 1 - -/** - * - * - * SCU_COMMAND_CODE - */ -#define SCU_COMMAND_CODE_INITIATOR_NEW_TASK 0 -#define SCU_COMMAND_CODE_ACTIVE_TASK 1 -#define SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK 2 -#define SCU_COMMAND_CODE_TARGET_RAW_FRAMES 3 - -/** - * - * - * SCU_TASK_PRIORITY - */ -/** - * - * - * This priority is used when there is no priority request for this request. - */ -#define SCU_TASK_PRIORITY_NORMAL 0 - -/** - * - * - * This priority indicates that the task should be scheduled to the head of the - * queue. The task will NOT be executed if the TX is suspended for the remote - * node. - */ -#define SCU_TASK_PRIORITY_HEAD_OF_Q 1 - -/** - * - * - * This priority indicates that the task will be executed before all - * SCU_TASK_PRIORITY_NORMAL and SCU_TASK_PRIORITY_HEAD_OF_Q tasks. The task - * WILL be executed if the TX is suspended for the remote node. - */ -#define SCU_TASK_PRIORITY_HIGH 2 - -/** - * - * - * This task priority is reserved and should not be used. - */ -#define SCU_TASK_PRIORITY_RESERVED 3 - -#define SCU_TASK_INITIATOR_MODE 1 -#define SCU_TASK_TARGET_MODE 0 - -#define SCU_TASK_REGULAR 0 -#define SCU_TASK_ABORTED 1 - -/* direction bit defintion */ -/** - * - * - * SATA_DIRECTION - */ -#define SCU_SATA_WRITE_DATA_DIRECTION 0 -#define SCU_SATA_READ_DATA_DIRECTION 1 - -/** - * - * - * SCU_COMMAND_CONTEXT_MACROS These macros provide the mask and shift - * operations to construct the various SCU commands - */ -#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT 21 -#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK 0x00E00000 -#define scu_get_command_request_type(x) \ - ((x) & SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK) - -#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT 18 -#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK 0x001C0000 -#define scu_get_command_request_subtype(x) \ - ((x) & SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK) - -#define SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK \ - (\ - SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK \ - | SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK \ - ) -#define scu_get_command_request_full_type(x) \ - ((x) & SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK) - -#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 16 -#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK 0x00010000 -#define scu_get_command_protocl_engine_group(x) \ - ((x) & SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK) - -#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 12 -#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK 0x00007000 -#define scu_get_command_reqeust_logical_port(x) \ - ((x) & SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK) - - -#define MAKE_SCU_CONTEXT_COMMAND_TYPE(type) \ - ((u32)(type) << SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT) - -/** - * MAKE_SCU_CONTEXT_COMMAND_TYPE() - - * - * SCU_COMMAND_TYPES These constants provide the grouping of the different SCU - * command types. - */ -#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(0) -#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(1) -#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(2) -#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(3) -#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(6) - -#define MAKE_SCU_CONTEXT_COMMAND_REQUEST(type, command) \ - ((type) | ((command) << SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT)) - -/** - * - * - * SCU_REQUEST_TYPES These constants are the various request types that can be - * posted to the SCU hardware. - */ -#define SCU_CONTEXT_COMMAND_REQUST_POST_TC \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 0)) - -#define SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 1)) - -#define SCU_CONTEXT_COMMAND_REQUST_DUMP_TC \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC, 0)) - -#define SCU_CONTEXT_COMMAND_POST_RNC_32 \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 0)) - -#define SCU_CONTEXT_COMMAND_POST_RNC_96 \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 1)) - -#define SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 2)) - -#define SCU_CONTEXT_COMMAND_DUMP_RNC_32 \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 0)) - -#define SCU_CONTEXT_COMMAND_DUMP_RNC_96 \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 1)) - -#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 0)) - -#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 1)) - -#define SCU_CONTEXT_COMMAND_POST_RNC_RESUME \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 2)) - -#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_ENABLE \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 3)) - -#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_DISABLE \ - (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 4)) - -/** - * - * - * SCU_TASK_CONTEXT_PROTOCOL SCU Task context protocol types this is uesd to - * program the SCU Task context protocol field in word 0x00. - */ -#define SCU_TASK_CONTEXT_PROTOCOL_SMP 0x00 -#define SCU_TASK_CONTEXT_PROTOCOL_SSP 0x01 -#define SCU_TASK_CONTEXT_PROTOCOL_STP 0x02 -#define SCU_TASK_CONTEXT_PROTOCOL_NONE 0x07 - -/** - * struct ssp_task_context - This is the SCU hardware definition for an SSP - * request. - * - * - */ -struct ssp_task_context { - /* OFFSET 0x18 */ - u32 reserved00:24; - u32 frame_type:8; - - /* OFFSET 0x1C */ - u32 reserved01; - - /* OFFSET 0x20 */ - u32 fill_bytes:2; - u32 reserved02:6; - u32 changing_data_pointer:1; - u32 retransmit:1; - u32 retry_data_frame:1; - u32 tlr_control:2; - u32 reserved03:19; - - /* OFFSET 0x24 */ - u32 uiRsvd4; - - /* OFFSET 0x28 */ - u32 target_port_transfer_tag:16; - u32 tag:16; - - /* OFFSET 0x2C */ - u32 data_offset; -}; - -/** - * struct stp_task_context - This is the SCU hardware definition for an STP - * request. - * - * - */ -struct stp_task_context { - /* OFFSET 0x18 */ - u32 fis_type:8; - u32 pm_port:4; - u32 reserved0:3; - u32 control:1; - u32 command:8; - u32 features:8; - - /* OFFSET 0x1C */ - u32 reserved1; - - /* OFFSET 0x20 */ - u32 reserved2; - - /* OFFSET 0x24 */ - u32 reserved3; - - /* OFFSET 0x28 */ - u32 ncq_tag:5; - u32 reserved4:27; - - /* OFFSET 0x2C */ - u32 data_offset; /* TODO: What is this used for? */ -}; - -/** - * struct smp_task_context - This is the SCU hardware definition for an SMP - * request. - * - * - */ -struct smp_task_context { - /* OFFSET 0x18 */ - u32 response_length:8; - u32 function_result:8; - u32 function:8; - u32 frame_type:8; - - /* OFFSET 0x1C */ - u32 smp_response_ufi:12; - u32 reserved1:20; - - /* OFFSET 0x20 */ - u32 reserved2; - - /* OFFSET 0x24 */ - u32 reserved3; - - /* OFFSET 0x28 */ - u32 reserved4; - - /* OFFSET 0x2C */ - u32 reserved5; -}; - -/** - * struct primitive_task_context - This is the SCU hardware definition used - * when the driver wants to send a primitive on the link. - * - * - */ -struct primitive_task_context { - /* OFFSET 0x18 */ - /** - * This field is the control word and it must be 0. - */ - u32 control; /* /< must be set to 0 */ - - /* OFFSET 0x1C */ - /** - * This field specifies the primitive that is to be transmitted. - */ - u32 sequence; - - /* OFFSET 0x20 */ - u32 reserved0; - - /* OFFSET 0x24 */ - u32 reserved1; - - /* OFFSET 0x28 */ - u32 reserved2; - - /* OFFSET 0x2C */ - u32 reserved3; -}; - -/** - * The union of the protocols that can be selected in the SCU task context - * field. - * - * protocol_context - */ -union protocol_context { - struct ssp_task_context ssp; - struct stp_task_context stp; - struct smp_task_context smp; - struct primitive_task_context primitive; - u32 words[6]; -}; - -/** - * struct scu_sgl_element - This structure represents a single SCU defined SGL - * element. SCU SGLs contain a 64 bit address with the maximum data transfer - * being 24 bits in size. The SGL can not cross a 4GB boundary. - * - * struct scu_sgl_element - */ -struct scu_sgl_element { - /** - * This field is the upper 32 bits of the 64 bit physical address. - */ - u32 address_upper; - - /** - * This field is the lower 32 bits of the 64 bit physical address. - */ - u32 address_lower; - - /** - * This field is the number of bytes to transfer. - */ - u32 length:24; - - /** - * This field is the address modifier to be used when a virtual function is - * requesting a data transfer. - */ - u32 address_modifier:8; - -}; - -#define SCU_SGL_ELEMENT_PAIR_A 0 -#define SCU_SGL_ELEMENT_PAIR_B 1 - -/** - * struct scu_sgl_element_pair - This structure is the SCU hardware definition - * of a pair of SGL elements. The SCU hardware always works on SGL pairs. - * They are refered to in the DS specification as SGL A and SGL B. Each SGL - * pair is followed by the address of the next pair. - * - * - */ -struct scu_sgl_element_pair { - /* OFFSET 0x60-0x68 */ - /** - * This field is the SGL element A of the SGL pair. - */ - struct scu_sgl_element A; - - /* OFFSET 0x6C-0x74 */ - /** - * This field is the SGL element B of the SGL pair. - */ - struct scu_sgl_element B; - - /* OFFSET 0x78-0x7C */ - /** - * This field is the upper 32 bits of the 64 bit address to the next SGL - * element pair. - */ - u32 next_pair_upper; - - /** - * This field is the lower 32 bits of the 64 bit address to the next SGL - * element pair. - */ - u32 next_pair_lower; - -}; - -/** - * struct transport_snapshot - This structure is the SCU hardware scratch area - * for the task context. This is set to 0 by the driver but can be read by - * issuing a dump TC request to the SCU. - * - * - */ -struct transport_snapshot { - /* OFFSET 0x48 */ - u32 xfer_rdy_write_data_length; - - /* OFFSET 0x4C */ - u32 data_offset; - - /* OFFSET 0x50 */ - u32 data_transfer_size:24; - u32 reserved_50_0:8; - - /* OFFSET 0x54 */ - u32 next_initiator_write_data_offset; - - /* OFFSET 0x58 */ - u32 next_initiator_write_data_xfer_size:24; - u32 reserved_58_0:8; -}; - -/** - * struct scu_task_context - This structure defines the contents of the SCU - * silicon task context. It lays out all of the fields according to the - * expected order and location for the Storage Controller unit. - * - * - */ -struct scu_task_context { - /* OFFSET 0x00 ------ */ - /** - * This field must be encoded to one of the valid SCU task priority values - * - SCU_TASK_PRIORITY_NORMAL - * - SCU_TASK_PRIORITY_HEAD_OF_Q - * - SCU_TASK_PRIORITY_HIGH - */ - u32 priority:2; - - /** - * This field must be set to true if this is an initiator generated request. - * Until target mode is supported all task requests are initiator requests. - */ - u32 initiator_request:1; - - /** - * This field must be set to one of the valid connection rates valid values - * are 0x8, 0x9, and 0xA. - */ - u32 connection_rate:4; - - /** - * This field muse be programed when generating an SMP response since the SMP - * connection remains open until the SMP response is generated. - */ - u32 protocol_engine_index:3; - - /** - * This field must contain the logical port for the task request. - */ - u32 logical_port_index:3; - - /** - * This field must be set to one of the SCU_TASK_CONTEXT_PROTOCOL values - * - SCU_TASK_CONTEXT_PROTOCOL_SMP - * - SCU_TASK_CONTEXT_PROTOCOL_SSP - * - SCU_TASK_CONTEXT_PROTOCOL_STP - * - SCU_TASK_CONTEXT_PROTOCOL_NONE - */ - u32 protocol_type:3; - - /** - * This filed must be set to the TCi allocated for this task - */ - u32 task_index:12; - - /** - * This field is reserved and must be set to 0x00 - */ - u32 reserved_00_0:1; - - /** - * For a normal task request this must be set to 0. If this is an abort of - * this task request it must be set to 1. - */ - u32 abort:1; - - /** - * This field must be set to true for the SCU hardware to process the task. - */ - u32 valid:1; - - /** - * This field must be set to SCU_TASK_CONTEXT_TYPE - */ - u32 context_type:1; - - /* OFFSET 0x04 */ - /** - * This field contains the RNi that is the target of this request. - */ - u32 remote_node_index:12; - - /** - * This field is programmed if this is a mirrored request, which we are not - * using, in which case it is the RNi for the mirrored target. - */ - u32 mirrored_node_index:12; - - /** - * This field is programmed with the direction of the SATA reqeust - * - SCU_SATA_WRITE_DATA_DIRECTION - * - SCU_SATA_READ_DATA_DIRECTION - */ - u32 sata_direction:1; - - /** - * This field is programmsed with one of the following SCU_COMMAND_CODE - * - SCU_COMMAND_CODE_INITIATOR_NEW_TASK - * - SCU_COMMAND_CODE_ACTIVE_TASK - * - SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK - * - SCU_COMMAND_CODE_TARGET_RAW_FRAMES - */ - u32 command_code:2; - - /** - * This field is set to true if the remote node should be suspended. - * This bit is only valid for SSP & SMP target devices. - */ - u32 suspend_node:1; - - /** - * This field is programmed with one of the following command type codes - * - * For SAS requests use the scu_ssp_task_type - * - SCU_TASK_TYPE_IOREAD - * - SCU_TASK_TYPE_IOWRITE - * - SCU_TASK_TYPE_SMP_REQUEST - * - SCU_TASK_TYPE_RESPONSE - * - SCU_TASK_TYPE_RAW_FRAME - * - SCU_TASK_TYPE_PRIMITIVE - * - * For SATA requests use the scu_sata_task_type - * - SCU_TASK_TYPE_DMA_IN - * - SCU_TASK_TYPE_FPDMAQ_READ - * - SCU_TASK_TYPE_PACKET_DMA_IN - * - SCU_TASK_TYPE_SATA_RAW_FRAME - * - SCU_TASK_TYPE_DMA_OUT - * - SCU_TASK_TYPE_FPDMAQ_WRITE - * - SCU_TASK_TYPE_PACKET_DMA_OUT - */ - u32 task_type:4; - - /* OFFSET 0x08 */ - /** - * This field is reserved and the must be set to 0x00 - */ - u32 link_layer_control:8; /* presently all reserved */ - - /** - * This field is set to true when TLR is to be enabled - */ - u32 ssp_tlr_enable:1; - - /** - * This is field specifies if the SCU DMAs a response frame to host - * memory for good response frames when operating in target mode. - */ - u32 dma_ssp_target_good_response:1; - - /** - * This field indicates if the SCU should DMA the response frame to - * host memory. - */ - u32 do_not_dma_ssp_good_response:1; - - /** - * This field is set to true when strict ordering is to be enabled - */ - u32 strict_ordering:1; - - /** - * This field indicates the type of endianess to be utilized for the - * frame. command, task, and response frames utilized control_frame - * set to 1. - */ - u32 control_frame:1; - - /** - * This field is reserved and the driver should set to 0x00 - */ - u32 tl_control_reserved:3; - - /** - * This field is set to true when the SCU hardware task timeout control is to - * be enabled - */ - u32 timeout_enable:1; - - /** - * This field is reserved and the driver should set it to 0x00 - */ - u32 pts_control_reserved:7; - - /** - * This field should be set to true when block guard is to be enabled - */ - u32 block_guard_enable:1; - - /** - * This field is reserved and the driver should set to 0x00 - */ - u32 sdma_control_reserved:7; - - /* OFFSET 0x0C */ - /** - * This field is the address modifier for this io request it should be - * programmed with the virtual function that is making the request. - */ - u32 address_modifier:16; - - /** - * @todo What we support mirrored SMP response frame? - */ - u32 mirrored_protocol_engine:3; /* mirrored protocol Engine Index */ - - /** - * If this is a mirrored request the logical port index for the mirrored RNi - * must be programmed. - */ - u32 mirrored_logical_port:4; /* mirrored local port index */ - - /** - * This field is reserved and the driver must set it to 0x00 - */ - u32 reserved_0C_0:8; - - /** - * This field must be set to true if the mirrored request processing is to be - * enabled. - */ - u32 mirror_request_enable:1; /* Mirrored request Enable */ - - /* OFFSET 0x10 */ - /** - * This field is the command iu length in dwords - */ - u32 ssp_command_iu_length:8; - - /** - * This is the target TLR enable bit it must be set to 0 when creatning the - * task context. - */ - u32 xfer_ready_tlr_enable:1; - - /** - * This field is reserved and the driver must set it to 0x00 - */ - u32 reserved_10_0:7; - - /** - * This is the maximum burst size that the SCU hardware will send in one - * connection its value is (N x 512) and N must be a multiple of 2. If the - * value is 0x00 then maximum burst size is disabled. - */ - u32 ssp_max_burst_size:16; - - /* OFFSET 0x14 */ - /** - * This filed is set to the number of bytes to be transfered in the request. - */ - u32 transfer_length_bytes:24; /* In terms of bytes */ - - /** - * This field is reserved and the driver should set it to 0x00 - */ - u32 reserved_14_0:8; - - /* OFFSET 0x18-0x2C */ - /** - * This union provides for the protocol specif part of the SCU Task Context. - */ - union protocol_context type; - - /* OFFSET 0x30-0x34 */ - /** - * This field is the upper 32 bits of the 64 bit physical address of the - * command iu buffer - */ - u32 command_iu_upper; - - /** - * This field is the lower 32 bits of the 64 bit physical address of the - * command iu buffer - */ - u32 command_iu_lower; - - /* OFFSET 0x38-0x3C */ - /** - * This field is the upper 32 bits of the 64 bit physical address of the - * response iu buffer - */ - u32 response_iu_upper; - - /** - * This field is the lower 32 bits of the 64 bit physical address of the - * response iu buffer - */ - u32 response_iu_lower; - - /* OFFSET 0x40 */ - /** - * This field is set to the task phase of the SCU hardware. The driver must - * set this to 0x01 - */ - u32 task_phase:8; - - /** - * This field is set to the transport layer task status. The driver must set - * this to 0x00 - */ - u32 task_status:8; - - /** - * This field is used during initiator write TLR - */ - u32 previous_extended_tag:4; - - /** - * This field is set the maximum number of retries for a STP non-data FIS - */ - u32 stp_retry_count:2; - - /** - * This field is reserved and the driver must set it to 0x00 - */ - u32 reserved_40_1:2; - - /** - * This field is used by the SCU TL to determine when to take a snapshot when - * tranmitting read data frames. - * - 0x00 The entire IO - * - 0x01 32k - * - 0x02 64k - * - 0x04 128k - * - 0x08 256k - */ - u32 ssp_tlr_threshold:4; - - /** - * This field is reserved and the driver must set it to 0x00 - */ - u32 reserved_40_2:4; - - /* OFFSET 0x44 */ - u32 write_data_length; /* read only set to 0 */ - - /* OFFSET 0x48-0x58 */ - struct transport_snapshot snapshot; /* read only set to 0 */ - - /* OFFSET 0x5C */ - u32 block_protection_enable:1; - u32 block_size:2; - u32 block_protection_function:2; - u32 reserved_5C_0:9; - u32 active_sgl_element:2; /* read only set to 0 */ - u32 sgl_exhausted:1; /* read only set to 0 */ - u32 payload_data_transfer_error:4; /* read only set to 0 */ - u32 frame_buffer_offset:11; /* read only set to 0 */ - - /* OFFSET 0x60-0x7C */ - /** - * This field is the first SGL element pair found in the TC data structure. - */ - struct scu_sgl_element_pair sgl_pair_ab; - /* OFFSET 0x80-0x9C */ - /** - * This field is the second SGL element pair found in the TC data structure. - */ - struct scu_sgl_element_pair sgl_pair_cd; - - /* OFFSET 0xA0-BC */ - struct scu_sgl_element_pair sgl_snapshot_ac; - - /* OFFSET 0xC0 */ - u32 active_sgl_element_pair; /* read only set to 0 */ - - /* OFFSET 0xC4-0xCC */ - u32 reserved_C4_CC[3]; - - /* OFFSET 0xD0 */ - u32 intermediate_crc_value:16; - u32 initial_crc_seed:16; - - /* OFFSET 0xD4 */ - u32 application_tag_for_verify:16; - u32 application_tag_for_generate:16; - - /* OFFSET 0xD8 */ - u32 reference_tag_seed_for_verify_function; - - /* OFFSET 0xDC */ - u32 reserved_DC; - - /* OFFSET 0xE0 */ - u32 reserved_E0_0:16; - u32 application_tag_mask_for_generate:16; - - /* OFFSET 0xE4 */ - u32 block_protection_control:16; - u32 application_tag_mask_for_verify:16; - - /* OFFSET 0xE8 */ - u32 block_protection_error:8; - u32 reserved_E8_0:24; - - /* OFFSET 0xEC */ - u32 reference_tag_seed_for_verify; - - /* OFFSET 0xF0 */ - u32 intermediate_crc_valid_snapshot:16; - u32 reserved_F0_0:16; - - /* OFFSET 0xF4 */ - u32 reference_tag_seed_for_verify_function_snapshot; - - /* OFFSET 0xF8 */ - u32 snapshot_of_reserved_dword_DC_of_tc; - - /* OFFSET 0xFC */ - u32 reference_tag_seed_for_generate_function_snapshot; - -}; - -#endif /* _SCU_TASK_CONTEXT_H_ */ diff --git a/drivers/scsi/isci/core/scu_unsolicited_frame.h b/drivers/scsi/isci/core/scu_unsolicited_frame.h deleted file mode 100644 index 187c4f03f596..000000000000 --- a/drivers/scsi/isci/core/scu_unsolicited_frame.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This field defines the SCU format of an unsolicited frame (UF). A UF is a - * frame received by the SCU for which there is no known corresponding task - * context (TC). - * - * - */ - -#ifndef _SCU_UNSOLICITED_FRAME_H_ -#define _SCU_UNSOLICITED_FRAME_H_ - -#include - -/** - * - * - * This constant defines the number of DWORDS found the unsolicited frame - * header data member. - */ -#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15 - -/** - * struct scu_unsolicited_frame_header - - * - * This structure delineates the format of an unsolicited frame header. The - * first DWORD are UF attributes defined by the silicon architecture. The data - * depicts actual header information received on the link. - */ -struct scu_unsolicited_frame_header { - /** - * This field indicates if there is an Initiator Index Table entry with - * which this header is associated. - */ - u32 iit_exists:1; - - /** - * This field simply indicates the protocol type (i.e. SSP, STP, SMP). - */ - u32 protocol_type:3; - - /** - * This field indicates if the frame is an address frame (IAF or OAF) - * or if it is a information unit frame. - */ - u32 is_address_frame:1; - - /** - * This field simply indicates the connection rate at which the frame - * was received. - */ - u32 connection_rate:4; - - u32 reserved:23; - - /** - * This field represents the actual header data received on the link. - */ - u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS]; - -}; - -#endif /* _SCU_UNSOLICITED_FRAME_H_ */ diff --git a/drivers/scsi/isci/core/scu_viit_data.h b/drivers/scsi/isci/core/scu_viit_data.h deleted file mode 100644 index c959d9158225..000000000000 --- a/drivers/scsi/isci/core/scu_viit_data.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCU_VIIT_DATA_HEADER_ -#define _SCU_VIIT_DATA_HEADER_ - -/** - * This file contains the constants and structures for the SCU hardware VIIT - * table entries. - * - * - */ - - -#define SCU_VIIT_ENTRY_ID_MASK (0xC0000000) -#define SCU_VIIT_ENTRY_ID_SHIFT (30) - -#define SCU_VIIT_ENTRY_FUNCTION_MASK (0x0FF00000) -#define SCU_VIIT_ENTRY_FUNCTION_SHIFT (20) - -#define SCU_VIIT_ENTRY_IPPTMODE_MASK (0x0001F800) -#define SCU_VIIT_ENTRY_IPPTMODE_SHIFT (12) - -#define SCU_VIIT_ENTRY_LPVIE_MASK (0x00000F00) -#define SCU_VIIT_ENTRY_LPVIE_SHIFT (8) - -#define SCU_VIIT_ENTRY_STATUS_MASK (0x000000FF) -#define SCU_VIIT_ENTRY_STATUS_SHIFT (0) - -#define SCU_VIIT_ENTRY_ID_INVALID (0 << SCU_VIIT_ENTRY_ID_SHIFT) -#define SCU_VIIT_ENTRY_ID_VIIT (1 << SCU_VIIT_ENTRY_ID_SHIFT) -#define SCU_VIIT_ENTRY_ID_IIT (2 << SCU_VIIT_ENTRY_ID_SHIFT) -#define SCU_VIIT_ENTRY_ID_VIRT_EXP (3 << SCU_VIIT_ENTRY_ID_SHIFT) - -#define SCU_VIIT_IPPT_SSP_INITIATOR (0x01 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) -#define SCU_VIIT_IPPT_SMP_INITIATOR (0x02 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) -#define SCU_VIIT_IPPT_STP_INITIATOR (0x04 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) -#define SCU_VIIT_IPPT_INITIATOR \ - (\ - SCU_VIIT_IPPT_SSP_INITIATOR \ - | SCU_VIIT_IPPT_SMP_INITIATOR \ - | SCU_VIIT_IPPT_STP_INITIATOR \ - ) - -#define SCU_VIIT_STATUS_RNC_VALID (0x01 << SCU_VIIT_ENTRY_STATUS_SHIFT) -#define SCU_VIIT_STATUS_ADDRESS_VALID (0x02 << SCU_VIIT_ENTRY_STATUS_SHIFT) -#define SCU_VIIT_STATUS_RNI_VALID (0x04 << SCU_VIIT_ENTRY_STATUS_SHIFT) -#define SCU_VIIT_STATUS_ALL_VALID \ - (\ - SCU_VIIT_STATUS_RNC_VALID \ - | SCU_VIIT_STATUS_ADDRESS_VALID \ - | SCU_VIIT_STATUS_RNI_VALID \ - ) - -#define SCU_VIIT_IPPT_SMP_TARGET (0x10 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) - -/** - * struct scu_viit_entry - This is the SCU Virtual Initiator Table Entry - * - * - */ -struct scu_viit_entry { - /** - * This must be encoded as to the type of initiator that is being constructed - * for this port. - */ - u32 status; - - /** - * Virtual initiator high SAS Address - */ - u32 initiator_sas_address_hi; - - /** - * Virtual initiator low SAS Address - */ - u32 initiator_sas_address_lo; - - /** - * This must be 0 - */ - u32 reserved; - -}; - - -/* IIT Status Defines */ -#define SCU_IIT_ENTRY_ID_MASK (0xC0000000) -#define SCU_IIT_ENTRY_ID_SHIFT (30) - -#define SCU_IIT_ENTRY_STATUS_UPDATE_MASK (0x20000000) -#define SCU_IIT_ENTRY_STATUS_UPDATE_SHIFT (29) - -#define SCU_IIT_ENTRY_LPI_MASK (0x00000F00) -#define SCU_IIT_ENTRY_LPI_SHIFT (8) - -#define SCU_IIT_ENTRY_STATUS_MASK (0x000000FF) -#define SCU_IIT_ENTRY_STATUS_SHIFT (0) - -/* IIT Remote Initiator Defines */ -#define SCU_IIT_ENTRY_REMOTE_TAG_MASK (0x0000FFFF) -#define SCU_IIT_ENTRY_REMOTE_TAG_SHIFT (0) - -#define SCU_IIT_ENTRY_REMOTE_RNC_MASK (0x0FFF0000) -#define SCU_IIT_ENTRY_REMOTE_RNC_SHIFT (16) - -#define SCU_IIT_ENTRY_ID_INVALID (0 << SCU_IIT_ENTRY_ID_SHIFT) -#define SCU_IIT_ENTRY_ID_VIIT (1 << SCU_IIT_ENTRY_ID_SHIFT) -#define SCU_IIT_ENTRY_ID_IIT (2 << SCU_IIT_ENTRY_ID_SHIFT) -#define SCU_IIT_ENTRY_ID_VIRT_EXP (3 << SCU_IIT_ENTRY_ID_SHIFT) - -/** - * struct scu_iit_entry - This will be implemented later when we support - * virtual functions - * - * - */ -struct scu_iit_entry { - u32 status; - u32 remote_initiator_sas_address_hi; - u32 remote_initiator_sas_address_lo; - u32 remote_initiator; - -}; - -#endif /* _SCU_VIIT_DATA_HEADER_ */ diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 43a5d7a8b291..71a0466d1c8e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -66,7 +66,7 @@ #include "sci_util.h" #include "scu_completion_codes.h" #include "scu_event_codes.h" -#include "scu_registers.h" +#include "registers.h" #include "scu_remote_node_context.h" #include "scu_task_context.h" #include "scu_unsolicited_frame.h" diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 1f542c47fb3a..64edac8ccce1 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -61,9 +61,9 @@ #include "pool.h" #include "sci_base_state_machine.h" #include "remote_node_table.h" -#include "scu_registers.h" +#include "registers.h" #include "scu_unsolicited_frame.h" -#include "scic_sds_unsolicited_frame_control.h" +#include "unsolicited_frame_control.h" #include "scic_sds_port_configuration_agent.h" struct scic_sds_request; diff --git a/drivers/scsi/isci/registers.h b/drivers/scsi/isci/registers.h new file mode 100644 index 000000000000..9b266c7428e8 --- /dev/null +++ b/drivers/scsi/isci/registers.h @@ -0,0 +1,1934 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCU_REGISTERS_H_ +#define _SCU_REGISTERS_H_ + +/** + * This file contains the constants and structures for the SCU memory mapped + * registers. + * + * + */ + +#define SCU_VIIT_ENTRY_ID_MASK (0xC0000000) +#define SCU_VIIT_ENTRY_ID_SHIFT (30) + +#define SCU_VIIT_ENTRY_FUNCTION_MASK (0x0FF00000) +#define SCU_VIIT_ENTRY_FUNCTION_SHIFT (20) + +#define SCU_VIIT_ENTRY_IPPTMODE_MASK (0x0001F800) +#define SCU_VIIT_ENTRY_IPPTMODE_SHIFT (12) + +#define SCU_VIIT_ENTRY_LPVIE_MASK (0x00000F00) +#define SCU_VIIT_ENTRY_LPVIE_SHIFT (8) + +#define SCU_VIIT_ENTRY_STATUS_MASK (0x000000FF) +#define SCU_VIIT_ENTRY_STATUS_SHIFT (0) + +#define SCU_VIIT_ENTRY_ID_INVALID (0 << SCU_VIIT_ENTRY_ID_SHIFT) +#define SCU_VIIT_ENTRY_ID_VIIT (1 << SCU_VIIT_ENTRY_ID_SHIFT) +#define SCU_VIIT_ENTRY_ID_IIT (2 << SCU_VIIT_ENTRY_ID_SHIFT) +#define SCU_VIIT_ENTRY_ID_VIRT_EXP (3 << SCU_VIIT_ENTRY_ID_SHIFT) + +#define SCU_VIIT_IPPT_SSP_INITIATOR (0x01 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) +#define SCU_VIIT_IPPT_SMP_INITIATOR (0x02 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) +#define SCU_VIIT_IPPT_STP_INITIATOR (0x04 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) +#define SCU_VIIT_IPPT_INITIATOR \ + (\ + SCU_VIIT_IPPT_SSP_INITIATOR \ + | SCU_VIIT_IPPT_SMP_INITIATOR \ + | SCU_VIIT_IPPT_STP_INITIATOR \ + ) + +#define SCU_VIIT_STATUS_RNC_VALID (0x01 << SCU_VIIT_ENTRY_STATUS_SHIFT) +#define SCU_VIIT_STATUS_ADDRESS_VALID (0x02 << SCU_VIIT_ENTRY_STATUS_SHIFT) +#define SCU_VIIT_STATUS_RNI_VALID (0x04 << SCU_VIIT_ENTRY_STATUS_SHIFT) +#define SCU_VIIT_STATUS_ALL_VALID \ + (\ + SCU_VIIT_STATUS_RNC_VALID \ + | SCU_VIIT_STATUS_ADDRESS_VALID \ + | SCU_VIIT_STATUS_RNI_VALID \ + ) + +#define SCU_VIIT_IPPT_SMP_TARGET (0x10 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) + +/** + * struct scu_viit_entry - This is the SCU Virtual Initiator Table Entry + * + * + */ +struct scu_viit_entry { + /** + * This must be encoded as to the type of initiator that is being constructed + * for this port. + */ + u32 status; + + /** + * Virtual initiator high SAS Address + */ + u32 initiator_sas_address_hi; + + /** + * Virtual initiator low SAS Address + */ + u32 initiator_sas_address_lo; + + /** + * This must be 0 + */ + u32 reserved; + +}; + + +/* IIT Status Defines */ +#define SCU_IIT_ENTRY_ID_MASK (0xC0000000) +#define SCU_IIT_ENTRY_ID_SHIFT (30) + +#define SCU_IIT_ENTRY_STATUS_UPDATE_MASK (0x20000000) +#define SCU_IIT_ENTRY_STATUS_UPDATE_SHIFT (29) + +#define SCU_IIT_ENTRY_LPI_MASK (0x00000F00) +#define SCU_IIT_ENTRY_LPI_SHIFT (8) + +#define SCU_IIT_ENTRY_STATUS_MASK (0x000000FF) +#define SCU_IIT_ENTRY_STATUS_SHIFT (0) + +/* IIT Remote Initiator Defines */ +#define SCU_IIT_ENTRY_REMOTE_TAG_MASK (0x0000FFFF) +#define SCU_IIT_ENTRY_REMOTE_TAG_SHIFT (0) + +#define SCU_IIT_ENTRY_REMOTE_RNC_MASK (0x0FFF0000) +#define SCU_IIT_ENTRY_REMOTE_RNC_SHIFT (16) + +#define SCU_IIT_ENTRY_ID_INVALID (0 << SCU_IIT_ENTRY_ID_SHIFT) +#define SCU_IIT_ENTRY_ID_VIIT (1 << SCU_IIT_ENTRY_ID_SHIFT) +#define SCU_IIT_ENTRY_ID_IIT (2 << SCU_IIT_ENTRY_ID_SHIFT) +#define SCU_IIT_ENTRY_ID_VIRT_EXP (3 << SCU_IIT_ENTRY_ID_SHIFT) + +/** + * struct scu_iit_entry - This will be implemented later when we support + * virtual functions + * + * + */ +struct scu_iit_entry { + u32 status; + u32 remote_initiator_sas_address_hi; + u32 remote_initiator_sas_address_lo; + u32 remote_initiator; + +}; + +/* Generate a value for an SCU register */ +#define SCU_GEN_VALUE(name, value) \ + (((value) << name ## _SHIFT) & (name ## _MASK)) + +/* + * Generate a bit value for an SCU register + * Make sure that the register MASK is just a single bit */ +#define SCU_GEN_BIT(name) \ + SCU_GEN_VALUE(name, ((u32)1)) + +#define SCU_SET_BIT(name, reg_value) \ + ((reg_value) | SCU_GEN_BIT(name)) + +#define SCU_CLEAR_BIT(name, reg_value) \ + ((reg_value)$ ~(SCU_GEN_BIT(name))) + +/* + * ***************************************************************************** + * Unions for bitfield definitions of SCU Registers + * SMU Post Context Port + * ***************************************************************************** */ +#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_SHIFT (0) +#define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_MASK (0x00000FFF) +#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_SHIFT (12) +#define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_MASK (0x0000F000) +#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_SHIFT (16) +#define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_MASK (0x00030000) +#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_SHIFT (18) +#define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_MASK (0x00FC0000) +#define SMU_POST_CONTEXT_PORT_RESERVED_MASK (0xFF000000) + +#define SMU_PCP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_POST_CONTEXT_PORT_ ## name, value) + +/* ***************************************************************************** */ +#define SMU_INTERRUPT_STATUS_COMPLETION_SHIFT (31) +#define SMU_INTERRUPT_STATUS_COMPLETION_MASK (0x80000000) +#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_SHIFT (1) +#define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_MASK (0x00000002) +#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_SHIFT (0) +#define SMU_INTERRUPT_STATUS_QUEUE_ERROR_MASK (0x00000001) +#define SMU_INTERRUPT_STATUS_RESERVED_MASK (0x7FFFFFFC) + +#define SMU_ISR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_INTERRUPT_STATUS_ ## name) + +#define SMU_ISR_QUEUE_ERROR SMU_ISR_GEN_BIT(QUEUE_ERROR) +#define SMU_ISR_QUEUE_SUSPEND SMU_ISR_GEN_BIT(QUEUE_SUSPEND) +#define SMU_ISR_COMPLETION SMU_ISR_GEN_BIT(COMPLETION) + +/* ***************************************************************************** */ +#define SMU_INTERRUPT_MASK_COMPLETION_SHIFT (31) +#define SMU_INTERRUPT_MASK_COMPLETION_MASK (0x80000000) +#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_SHIFT (1) +#define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_MASK (0x00000002) +#define SMU_INTERRUPT_MASK_QUEUE_ERROR_SHIFT (0) +#define SMU_INTERRUPT_MASK_QUEUE_ERROR_MASK (0x00000001) +#define SMU_INTERRUPT_MASK_RESERVED_MASK (0x7FFFFFFC) + +#define SMU_IMR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_INTERRUPT_MASK_ ## name) + +#define SMU_IMR_QUEUE_ERROR SMU_IMR_GEN_BIT(QUEUE_ERROR) +#define SMU_IMR_QUEUE_SUSPEND SMU_IMR_GEN_BIT(QUEUE_SUSPEND) +#define SMU_IMR_COMPLETION SMU_IMR_GEN_BIT(COMPLETION) + +/* ***************************************************************************** */ +#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_SHIFT (0) +#define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_MASK (0x0000001F) +#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_SHIFT (8) +#define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_MASK (0x0000FF00) +#define SMU_INTERRUPT_COALESCING_CONTROL_RESERVED_MASK (0xFFFF00E0) + +#define SMU_ICC_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_INTERRUPT_COALESCING_CONTROL_ ## name, value) + +/* ***************************************************************************** */ +#define SMU_TASK_CONTEXT_RANGE_START_SHIFT (0) +#define SMU_TASK_CONTEXT_RANGE_START_MASK (0x00000FFF) +#define SMU_TASK_CONTEXT_RANGE_ENDING_SHIFT (16) +#define SMU_TASK_CONTEXT_RANGE_ENDING_MASK (0x0FFF0000) +#define SMU_TASK_CONTEXT_RANGE_ENABLE_SHIFT (31) +#define SMU_TASK_CONTEXT_RANGE_ENABLE_MASK (0x80000000) +#define SMU_TASK_CONTEXT_RANGE_RESERVED_MASK (0x7000F000) + +#define SMU_TCR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_TASK_CONTEXT_RANGE_ ## name, value) + +#define SMU_TCR_GEN_BIT(name, value) \ + SCU_GEN_BIT(SMU_TASK_CONTEXT_RANGE_ ## name) + +/* ***************************************************************************** */ + +#define SMU_COMPLETION_QUEUE_PUT_POINTER_SHIFT (0) +#define SMU_COMPLETION_QUEUE_PUT_POINTER_MASK (0x00003FFF) +#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_SHIFT (15) +#define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_MASK (0x00008000) +#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_SHIFT (16) +#define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_MASK (0x03FF0000) +#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_SHIFT (26) +#define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_MASK (0x04000000) +#define SMU_COMPLETION_QUEUE_PUT_RESERVED_MASK (0xF8004000) + +#define SMU_CQPR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_PUT_ ## name, value) + +#define SMU_CQPR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_COMPLETION_QUEUE_PUT_ ## name) + +/* ***************************************************************************** */ + +#define SMU_COMPLETION_QUEUE_GET_POINTER_SHIFT (0) +#define SMU_COMPLETION_QUEUE_GET_POINTER_MASK (0x00003FFF) +#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT (15) +#define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_MASK (0x00008000) +#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT (16) +#define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK (0x03FF0000) +#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT (26) +#define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_MASK (0x04000000) +#define SMU_COMPLETION_QUEUE_GET_ENABLE_SHIFT (30) +#define SMU_COMPLETION_QUEUE_GET_ENABLE_MASK (0x40000000) +#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_SHIFT (31) +#define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_MASK (0x80000000) +#define SMU_COMPLETION_QUEUE_GET_RESERVED_MASK (0x38004000) + +#define SMU_CQGR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_GET_ ## name, value) + +#define SMU_CQGR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_COMPLETION_QUEUE_GET_ ## name) + +#define SMU_CQGR_CYCLE_BIT \ + SMU_CQGR_GEN_BIT(CYCLE_BIT) + +#define SMU_CQGR_EVENT_CYCLE_BIT \ + SMU_CQGR_GEN_BIT(EVENT_CYCLE_BIT) + +#define SMU_CQGR_GET_POINTER_SET(value) \ + SMU_CQGR_GEN_VAL(POINTER, value) + + +/* ***************************************************************************** */ +#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_SHIFT (0) +#define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_MASK (0x00003FFF) +#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_SHIFT (16) +#define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_MASK (0x03FF0000) +#define SMU_COMPLETION_QUEUE_CONTROL_RESERVED_MASK (0xFC00C000) + +#define SMU_CQC_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_CONTROL_ ## name, value) + +#define SMU_CQC_QUEUE_LIMIT_SET(value) \ + SMU_CQC_GEN_VAL(QUEUE_LIMIT, value) + +#define SMU_CQC_EVENT_LIMIT_SET(value) \ + SMU_CQC_GEN_VAL(EVENT_LIMIT, value) + + +/* ***************************************************************************** */ +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT (0) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK (0x00000FFF) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT (12) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK (0x00007000) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT (15) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK (0x07FF8000) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_SHIFT (27) +#define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK (0x08000000) +#define SMU_DEVICE_CONTEXT_CAPACITY_RESERVED_MASK (0xF0000000) + +#define SMU_DCC_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_DEVICE_CONTEXT_CAPACITY_ ## name, value) + +#define SMU_DCC_GET_MAX_PEG(value) \ + (\ + ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \ + ) + +#define SMU_DCC_GET_MAX_LP(value) \ + (\ + ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \ + ) + +#define SMU_DCC_GET_MAX_TC(value) \ + (\ + ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT \ + ) + +#define SMU_DCC_GET_MAX_RNC(value) \ + (\ + ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ + >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT \ + ) + +/* -------------------------------------------------------------------------- */ + +#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_SHIFT (0) +#define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_MASK (0x00000001) +#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_SHIFT (1) +#define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_MASK (0x00000002) +#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_SHIFT (16) +#define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_MASK (0x00010000) +#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_SHIFT (17) +#define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_MASK (0x00020000) +#define SMU_CONTROL_STATUS_RESERVED_MASK (0xFFFCFFFC) + +#define SMU_SMUCSR_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_CONTROL_STATUS_ ## name) + +#define SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \ + (SMU_SMUCSR_GEN_BIT(SCHEDULER_RAM_INIT_COMPLETED)) + +#define SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \ + (SMU_SMUCSR_GEN_BIT(CONTEXT_RAM_INIT_COMPLETED)) + +#define SCU_RAM_INIT_COMPLETED \ + (\ + SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \ + | SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \ + ) + +/* -------------------------------------------------------------------------- */ + +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_SHIFT (0) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_MASK (0x00000001) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_SHIFT (1) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_MASK (0x00000002) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_SHIFT (2) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_MASK (0x00000004) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_SHIFT (3) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_MASK (0x00000008) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_SHIFT (8) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_MASK (0x00000100) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_SHIFT (9) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_MASK (0x00000200) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_SHIFT (10) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_MASK (0x00000400) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_SHIFT (11) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_MASK (0x00000800) + +#define SMU_RESET_PROTOCOL_ENGINE(peg, pe) \ + ((1 << (pe)) << ((peg) * 8)) + +#define SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \ + (\ + SMU_RESET_PROTOCOL_ENGINE(peg, 0) \ + | SMU_RESET_PROTOCOL_ENGINE(peg, 1) \ + | SMU_RESET_PROTOCOL_ENGINE(peg, 2) \ + | SMU_RESET_PROTOCOL_ENGINE(peg, 3) \ + ) + +#define SMU_RESET_ALL_PROTOCOL_ENGINES() \ + (\ + SMU_RESET_PEG_PROTOCOL_ENGINES(0) \ + | SMU_RESET_PEG_PROTOCOL_ENGINES(1) \ + ) + +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_SHIFT (16) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_MASK (0x00010000) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_SHIFT (17) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_MASK (0x00020000) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_SHIFT (18) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_MASK (0x00040000) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_SHIFT (19) +#define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_MASK (0x00080000) + +#define SMU_RESET_WIDE_PORT_QUEUE(peg, wide_port) \ + ((1 << ((wide_port) / 2)) << ((peg) * 2) << 16) + +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_SHIFT (20) +#define SMU_SOFTRESET_CONTROL_RESET_PEG0_MASK (0x00100000) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_SHIFT (21) +#define SMU_SOFTRESET_CONTROL_RESET_PEG1_MASK (0x00200000) +#define SMU_SOFTRESET_CONTROL_RESET_SCU_SHIFT (22) +#define SMU_SOFTRESET_CONTROL_RESET_SCU_MASK (0x00400000) + +/* + * It seems to make sense that if you are going to reset the protocol + * engine group that you would also reset all of the protocol engines */ +#define SMU_RESET_PROTOCOL_ENGINE_GROUP(peg) \ + (\ + (1 << ((peg) + 20)) \ + | SMU_RESET_WIDE_PORT_QUEUE(peg, 0) \ + | SMU_RESET_WIDE_PORT_QUEUE(peg, 1) \ + | SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \ + ) + +#define SMU_RESET_ALL_PROTOCOL_ENGINE_GROUPS() \ + (\ + SMU_RESET_PROTOCOL_ENGINE_GROUP(0) \ + | SMU_RESET_PROTOCOL_ENGINE_GROUP(1) \ + ) + +#define SMU_RESET_SCU() (0xFFFFFFFF) + + + +/* ***************************************************************************** */ +#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_SHIFT (0) +#define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_MASK (0x00000FFF) +#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_SHIFT (16) +#define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_MASK (0x0FFF0000) +#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_SHIFT (31) +#define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_MASK (0x80000000) +#define SMU_TASK_CONTEXT_ASSIGNMENT_RESERVED_MASK (0x7000F000) + +#define SMU_TCA_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name, value) + +#define SMU_TCA_GEN_BIT(name) \ + SCU_GEN_BIT(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name) + +/* ***************************************************************************** */ +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_SHIFT (0) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_MASK (0x00000FFF) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_RESERVED_MASK (0xFFFFF000) + +#define SCU_UFQC_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_ ## name, value) + +#define SCU_UFQC_QUEUE_SIZE_SET(value) \ + SCU_UFQC_GEN_VAL(QUEUE_SIZE, value) + +/* ***************************************************************************** */ +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_SHIFT (0) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_MASK (0x00000FFF) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_SHIFT (12) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_MASK (0x00001000) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_RESERVED_MASK (0xFFFFE000) + +#define SCU_UFQPP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name, value) + +#define SCU_UFQPP_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name) + +/* + * ***************************************************************************** + * * SDMA Registers + * ***************************************************************************** */ +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_SHIFT (0) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_MASK (0x00000FFF) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_SHIFT (12) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_MASK (12) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_SHIFT (31) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_MASK (0x80000000) +#define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_RESERVED_MASK (0x7FFFE000) + +#define SCU_UFQGP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name, value) + +#define SCU_UFQGP_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name) + +#define SCU_UFQGP_CYCLE_BIT(value) \ + SCU_UFQGP_GEN_BIT(CYCLE_BIT, value) + +#define SCU_UFQGP_GET_POINTER(value) \ + SCU_UFQGP_GEN_VALUE(POINTER, value) + +#define SCU_UFQGP_ENABLE(value) \ + (SCU_UFQGP_GEN_BIT(ENABLE) | value) + +#define SCU_UFQGP_DISABLE(value) \ + (~SCU_UFQGP_GEN_BIT(ENABLE) & value) + +#define SCU_UFQGP_VALUE(bit, value) \ + (SCU_UFQGP_CYCLE_BIT(bit) | SCU_UFQGP_GET_POINTER(value)) + +/* ***************************************************************************** */ +#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SHIFT (0) +#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_MASK (0x0000FFFF) +#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT (16) +#define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK (0x00010000) +#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_SHIFT (17) +#define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_MASK (0x00020000) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_SHIFT (18) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_MASK (0x00040000) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_SHIFT (19) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_MASK (0x00080000) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_SHIFT (20) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_MASK (0x00100000) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_SHIFT (21) +#define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_MASK (0x00200000) +#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_SHIFT (22) +#define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_MASK (0x00400000) +#define SCU_PDMA_CONFIGURATION_RESERVED_MASK (0xFF800000) + +#define SCU_PDMACR_GEN_VALUE(name, value) \ + SCU_GEN_VALUE(SCU_PDMA_CONFIGURATION_ ## name, value) + +#define SCU_PDMACR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PDMA_CONFIGURATION_ ## name) + +#define SCU_PDMACR_BE_GEN_BIT(name) \ + SCU_PCMACR_GEN_BIT(BIG_ENDIAN_CONTROL_ ## name) + +/* ***************************************************************************** */ +#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT (8) +#define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK (0x00000100) + +#define SCU_CDMACR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_CDMA_CONFIGURATION_ ## name) + +/* + * ***************************************************************************** + * * SCU Link Layer Registers + * ***************************************************************************** */ +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_SHIFT (0) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_MASK (0x000000FF) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_SHIFT (8) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_MASK (0x0000FF00) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_SHIFT (16) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_MASK (0x00FF0000) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_SHIFT (24) +#define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_MASK (0xFF000000) +#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_REQUIRED_MASK (0x00000000) +#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_DEFAULT_MASK (0x7D00676F) +#define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_RESERVED_MASK (0x00FF0000) + +#define SCU_SAS_SPDTOV_GEN_VALUE(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_ ## name, value) + + +#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_SHIFT (2) +#define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_MASK (0x00000004) +#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_SHIFT (4) +#define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_MASK (0x00000010) +#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_SHIFT (5) +#define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_MASK (0x00000020) +#define SCU_LINK_STATUS_RESERVED_MASK (0xFFFFFFCD) + +#define SCU_SAS_LLSTA_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_STATUS_ ## name) + + +/* TODO: Where is the SATA_PSELTOV register? */ + +/* + * ***************************************************************************** + * * SCU SAS Maximum Arbitration Wait Time Timeout Register + * ***************************************************************************** */ +#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_SHIFT (0) +#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_MASK (0x00007FFF) +#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_SHIFT (15) +#define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_MASK (0x00008000) + +#define SCU_SAS_MAWTTOV_GEN_VALUE(name, value) \ + SCU_GEN_VALUE(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name, value) + +#define SCU_SAS_MAWTTOV_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name) + + +/* + * TODO: Where is the SAS_LNKTOV regsiter? + * TODO: Where is the SAS_PHYTOV register? */ + +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_SHIFT (1) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_MASK (0x00000002) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_SHIFT (2) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_MASK (0x00000004) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_SHIFT (3) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_MASK (0x00000008) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_SHIFT (8) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_MASK (0x00000100) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_SHIFT (9) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_MASK (0x00000200) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_SHIFT (10) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_MASK (0x00000400) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_SHIFT (11) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_MASK (0x00000800) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_SHIFT (16) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_MASK (0x000F0000) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_SHIFT (24) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_MASK (0x0F000000) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_SHIFT (28) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_MASK (0x70000000) +#define SCU_SAS_TRANSMIT_IDENTIFICATION_RESERVED_MASK (0x80F0F1F1) + +#define SCU_SAS_TIID_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name, value) + +#define SCU_SAS_TIID_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name) + +/* SAS Identify Frame PHY Identifier Register */ +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_SHIFT (16) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_MASK (0x00010000) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_SHIFT (17) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_MASK (0x00020000) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_SHIFT (18) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_MASK (0x00040000) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_SHIFT (24) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_MASK (0xFF000000) +#define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_RESERVED_MASK (0x00F800FF) + +#define SCU_SAS_TIPID_GEN_VALUE(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name, value) + +#define SCU_SAS_TIPID_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name) + + +#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_SHIFT (4) +#define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_MASK (0x00000010) +#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_SHIFT (6) +#define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_MASK (0x00000040) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_SHIFT (7) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_MASK (0x00000080) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_SHIFT (8) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_MASK (0x00000100) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_SHIFT (9) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_MASK (0x00000200) +#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_SHIFT (11) +#define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_MASK (0x00000800) +#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_SHIFT (12) +#define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_MASK (0x00001000) +#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_SHIFT (13) +#define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_MASK (0x00002000) +#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_SHIFT (14) +#define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_MASK (0x00004000) +#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_SHIFT (15) +#define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_MASK (0x00008000) +#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_SHIFT (23) +#define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_MASK (0x00800000) +#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_SHIFT (27) +#define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_MASK (0x08000000) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_SHIFT (28) +#define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_MASK (0x10000000) +#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_SHIFT (29) +#define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_MASK (0x20000000) +#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_SHIFT (30) +#define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_MASK (0x40000000) +#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_SHIFT (31) +#define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_MASK (0x80000000) +#define SCU_SAS_PHY_CONFIGURATION_REQUIRED_MASK (0x0100000F) +#define SCU_SAS_PHY_CONFIGURATION_DEFAULT_MASK (0x4180100F) +#define SCU_SAS_PHY_CONFIGURATION_RESERVED_MASK (0x00000000) + +#define SCU_SAS_PCFG_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SAS_PHY_CONFIGURATION_ ## name) + +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_SHIFT (0) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_MASK (0x000007FF) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_SHIFT (16) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_MASK (0x00ff0000) + +#define SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_##name, value) + +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_SHIFT (0) +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_MASK (0x0003FFFF) +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_SHIFT (31) +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_MASK (0x80000000) +#define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_RESERVED_MASK (0x7FFC0000) + +#define SCU_ENSPINUP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name, value) + +#define SCU_ENSPINUP_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name) + + +#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_SHIFT (1) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_MASK (0x00000002) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_SHIFT (4) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_MASK (0x000000F0) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_SHIFT (8) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_MASK (0x00000100) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_SHIFT (9) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_MASK (0x00000201) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_SHIFT (10) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_MASK (0x00000401) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_SHIFT (11) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_MASK (0x00000801) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_SHIFT (12) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_MASK (0x00001001) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_SHIFT (13) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_MASK (0x00002001) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_SHIFT (31) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_MASK (0x80000000) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_DEFAULT_MASK (0x00003F01) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_REQUIRED_MASK (0x00000001) +#define SCU_LINK_LAYER_PHY_CAPABILITIES_RESERVED_MASK (0x7FFFC00D) + +#define SCU_SAS_PHYCAP_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name, value) + +#define SCU_SAS_PHYCAP_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name) + + +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_SHIFT (0) +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_MASK (0x000000FF) +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_SHIFT (31) +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_MASK (0x80000000) +#define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_RESERVED_MASK (0x7FFFFF00) + +#define SCU_PSZGCR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name, value) + +#define SCU_PSZGCR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name) + +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_SHIFT (1) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_MASK (0x00000002) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_SHIFT (2) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_MASK (0x00000004) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_SHIFT (4) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_MASK (0x00000010) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_SHIFT (5) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_MASK (0x00000020) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_SHIFT (16) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_MASK (0x00030000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_SHIFT (19) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_MASK (0x00080000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_SHIFT (20) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_MASK (0x00300000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_SHIFT (23) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_MASK (0x00800000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_SHIFT (24) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_MASK (0x03000000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_SHIFT (27) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_MASK (0x08000000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_SHIFT (28) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_MASK (0x30000000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_SHIFT (31) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_MASK (0x80000000) +#define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_RESERVED_MASK (0x4444FFC9) + +#define SCU_PEG_SCUVZECR_GEN_VAL(name, val) \ + SCU_GEN_VALUE(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name, val) + +#define SCU_PEG_SCUVZECR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name) + + +/* + * ***************************************************************************** + * * Port Task Scheduler registers shift and mask values + * ***************************************************************************** */ +#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_SHIFT (0) +#define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_MASK (0x0000FFFF) +#define SCU_PTSG_CONTROL_TASK_TIMEOUT_SHIFT (16) +#define SCU_PTSG_CONTROL_TASK_TIMEOUT_MASK (0x00FF0000) +#define SCU_PTSG_CONTROL_PTSG_ENABLE_SHIFT (24) +#define SCU_PTSG_CONTROL_PTSG_ENABLE_MASK (0x01000000) +#define SCU_PTSG_CONTROL_ETM_ENABLE_SHIFT (25) +#define SCU_PTSG_CONTROL_ETM_ENABLE_MASK (0x02000000) +#define SCU_PTSG_CONTROL_DEFAULT_MASK (0x00020002) +#define SCU_PTSG_CONTROL_REQUIRED_MASK (0x00000000) +#define SCU_PTSG_CONTROL_RESERVED_MASK (0xFC000000) + +#define SCU_PTSGCR_GEN_VAL(name, val) \ + SCU_GEN_VALUE(SCU_PTSG_CONTROL_ ## name, val) + +#define SCU_PTSGCR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PTSG_CONTROL_ ## name) + + +/* ***************************************************************************** */ +#define SCU_PTSG_REAL_TIME_CLOCK_SHIFT (0) +#define SCU_PTSG_REAL_TIME_CLOCK_MASK (0x0000FFFF) +#define SCU_PTSG_REAL_TIME_CLOCK_RESERVED_MASK (0xFFFF0000) + +#define SCU_RTCR_GEN_VAL(name, val) \ + SCU_GEN_VALUE(SCU_PTSG_ ## name, val) + + +#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_SHIFT (0) +#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_MASK (0x00FFFFFF) +#define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_RESERVED_MASK (0xFF000000) + +#define SCU_RTCCR_GEN_VAL(name, val) \ + SCU_GEN_VALUE(SCU_PTSG_REAL_TIME_CLOCK_CONTROL_ ## name, val) + + +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_SHIFT (0) +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_MASK (0x00000001) +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_SHIFT (1) +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_MASK (0x00000002) +#define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_RESERVED_MASK (0xFFFFFFFC) + +#define SCU_PTSxCR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ ## name) + + +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_SHIFT (0) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_MASK (0x00000001) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_SHIFT (1) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_MASK (0x00000002) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_SHIFT (2) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_MASK (0x00000004) +#define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_RESERVED_MASK (0xFFFFFFF8) + +#define SCU_PTSxSR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ ## name) + + +/* + * ***************************************************************************** + * * SGPIO Register shift and mask values + * ***************************************************************************** */ +#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_SHIFT (0) +#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_MASK (0x00000001) +#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_SHIFT (1) +#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_MASK (0x00000002) +#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_SHIFT (2) +#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_MASK (0x00000004) +#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_SHIFT (15) +#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_MASK (0x00008000) +#define SCU_SGPIO_CONTROL_SGPIO_RESERVED_MASK (0xFFFF7FF8) + +#define SCU_SGICRx_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SGPIO_CONTROL_SGPIO_ ## name) + +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_SHIFT (0) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_MASK (0x0000000F) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_SHIFT (4) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_MASK (0x000000F0) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_SHIFT (8) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_MASK (0x00000F00) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_SHIFT (12) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_MASK (0x0000F000) +#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_RESERVED_MASK (0xFFFF0000) + +#define SCU_SGPBRx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_ ## name, value) + +#define SCU_SGPIO_START_DRIVE_LOWER_R0_SHIFT (0) +#define SCU_SGPIO_START_DRIVE_LOWER_R0_MASK (0x00000003) +#define SCU_SGPIO_START_DRIVE_LOWER_R1_SHIFT (4) +#define SCU_SGPIO_START_DRIVE_LOWER_R1_MASK (0x00000030) +#define SCU_SGPIO_START_DRIVE_LOWER_R2_SHIFT (8) +#define SCU_SGPIO_START_DRIVE_LOWER_R2_MASK (0x00000300) +#define SCU_SGPIO_START_DRIVE_LOWER_R3_SHIFT (12) +#define SCU_SGPIO_START_DRIVE_LOWER_R3_MASK (0x00003000) +#define SCU_SGPIO_START_DRIVE_LOWER_RESERVED_MASK (0xFFFF8888) + +#define SCU_SGSDLRx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value) + +#define SCU_SGPIO_START_DRIVE_UPPER_R0_SHIFT (0) +#define SCU_SGPIO_START_DRIVE_UPPER_R0_MASK (0x00000003) +#define SCU_SGPIO_START_DRIVE_UPPER_R1_SHIFT (4) +#define SCU_SGPIO_START_DRIVE_UPPER_R1_MASK (0x00000030) +#define SCU_SGPIO_START_DRIVE_UPPER_R2_SHIFT (8) +#define SCU_SGPIO_START_DRIVE_UPPER_R2_MASK (0x00000300) +#define SCU_SGPIO_START_DRIVE_UPPER_R3_SHIFT (12) +#define SCU_SGPIO_START_DRIVE_UPPER_R3_MASK (0x00003000) +#define SCU_SGPIO_START_DRIVE_UPPER_RESERVED_MASK (0xFFFF8888) + +#define SCU_SGSDURx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value) + +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_SHIFT (0) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_MASK (0x00000003) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_SHIFT (4) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_MASK (0x00000030) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_SHIFT (8) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_MASK (0x00000300) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_SHIFT (12) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_MASK (0x00003000) +#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_RESERVED_MASK (0xFFFF8888) + +#define SCU_SGSIDLRx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value) + +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_SHIFT (0) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_MASK (0x00000003) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_SHIFT (4) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_MASK (0x00000030) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_SHIFT (8) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_MASK (0x00000300) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_SHIFT (12) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_MASK (0x00003000) +#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_RESERVED_MASK (0xFFFF8888) + +#define SCU_SGSIDURx_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value) + +#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_SHIFT (0) +#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_MASK (0x0000000F) +#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_RESERVED_MASK (0xFFFFFFF0) + +#define SCU_SGVSCR_GEN_VAL(value) \ + SCU_GEN_VALUE(SCU_SGPIO_VENDOR_SPECIFIC_CODE ## name, value) + +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_SHIFT (0) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_MASK (0x00000003) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_SHIFT (2) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_MASK (0x00000004) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_SHIFT (3) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_MASK (0x00000008) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_SHIFT (4) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_MASK (0x00000030) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_SHIFT (6) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_MASK (0x00000040) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_SHIFT (7) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_MASK (0x00000080) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_SHIFT (8) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_MASK (0x00000300) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_SHIFT (10) +#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_MASK (0x00000400) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_SHIFT (11) +#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_MASK (0x00000800) +#define SCU_SGPIO_OUPUT_DATA_SELECT_RESERVED_MASK (0xFFFFF000) + +#define SCU_SGODSR_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name, value) + +#define SCU_SGODSR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name) + +/* + * ***************************************************************************** + * * SMU Registers + * ***************************************************************************** */ + +/* + * ---------------------------------------------------------------------------- + * SMU Registers + * These registers are based off of BAR0 + * + * To calculate the offset for other functions use + * BAR0 + FN# * SystemPageSize * 2 + * + * The TCA is only accessable from FN#0 (Physical Function) and each + * is programmed by (BAR0 + SCU_SMU_TCA_OFFSET + (FN# * 0x04)) or + * TCA0 for FN#0 is at BAR0 + 0x0400 + * TCA1 for FN#1 is at BAR0 + 0x0404 + * etc. + * ---------------------------------------------------------------------------- + * Accessable to all FN#s */ +#define SCU_SMU_PCP_OFFSET 0x0000 +#define SCU_SMU_AMR_OFFSET 0x0004 +#define SCU_SMU_ISR_OFFSET 0x0010 +#define SCU_SMU_IMR_OFFSET 0x0014 +#define SCU_SMU_ICC_OFFSET 0x0018 +#define SCU_SMU_HTTLBAR_OFFSET 0x0020 +#define SCU_SMU_HTTUBAR_OFFSET 0x0024 +#define SCU_SMU_TCR_OFFSET 0x0028 +#define SCU_SMU_CQLBAR_OFFSET 0x0030 +#define SCU_SMU_CQUBAR_OFFSET 0x0034 +#define SCU_SMU_CQPR_OFFSET 0x0040 +#define SCU_SMU_CQGR_OFFSET 0x0044 +#define SCU_SMU_CQC_OFFSET 0x0048 +/* Accessable to FN#0 only */ +#define SCU_SMU_RNCLBAR_OFFSET 0x0080 +#define SCU_SMU_RNCUBAR_OFFSET 0x0084 +#define SCU_SMU_DCC_OFFSET 0x0090 +#define SCU_SMU_DFC_OFFSET 0x0094 +#define SCU_SMU_SMUCSR_OFFSET 0x0098 +#define SCU_SMU_SCUSRCR_OFFSET 0x009C +#define SCU_SMU_SMAW_OFFSET 0x00A0 +#define SCU_SMU_SMDW_OFFSET 0x00A4 +/* Accessable to FN#0 only */ +#define SCU_SMU_TCA_OFFSET 0x0400 +/* Accessable to all FN#s */ +#define SCU_SMU_MT_MLAR0_OFFSET 0x2000 +#define SCU_SMU_MT_MUAR0_OFFSET 0x2004 +#define SCU_SMU_MT_MDR0_OFFSET 0x2008 +#define SCU_SMU_MT_VCR0_OFFSET 0x200C +#define SCU_SMU_MT_MLAR1_OFFSET 0x2010 +#define SCU_SMU_MT_MUAR1_OFFSET 0x2014 +#define SCU_SMU_MT_MDR1_OFFSET 0x2018 +#define SCU_SMU_MT_VCR1_OFFSET 0x201C +#define SCU_SMU_MPBA_OFFSET 0x3000 + +/** + * struct smu_registers - These are the SMU registers + * + * + */ +struct smu_registers { +/* 0x0000 PCP */ + u32 post_context_port; +/* 0x0004 AMR */ + u32 address_modifier; + u32 reserved_08; + u32 reserved_0C; +/* 0x0010 ISR */ + u32 interrupt_status; +/* 0x0014 IMR */ + u32 interrupt_mask; +/* 0x0018 ICC */ + u32 interrupt_coalesce_control; + u32 reserved_1C; +/* 0x0020 HTTLBAR */ + u32 host_task_table_lower; +/* 0x0024 HTTUBAR */ + u32 host_task_table_upper; +/* 0x0028 TCR */ + u32 task_context_range; + u32 reserved_2C; +/* 0x0030 CQLBAR */ + u32 completion_queue_lower; +/* 0x0034 CQUBAR */ + u32 completion_queue_upper; + u32 reserved_38; + u32 reserved_3C; +/* 0x0040 CQPR */ + u32 completion_queue_put; +/* 0x0044 CQGR */ + u32 completion_queue_get; +/* 0x0048 CQC */ + u32 completion_queue_control; + u32 reserved_4C; + u32 reserved_5x[4]; + u32 reserved_6x[4]; + u32 reserved_7x[4]; +/* + * Accessable to FN#0 only + * 0x0080 RNCLBAR */ + u32 remote_node_context_lower; +/* 0x0084 RNCUBAR */ + u32 remote_node_context_upper; + u32 reserved_88; + u32 reserved_8C; +/* 0x0090 DCC */ + u32 device_context_capacity; +/* 0x0094 DFC */ + u32 device_function_capacity; +/* 0x0098 SMUCSR */ + u32 control_status; +/* 0x009C SCUSRCR */ + u32 soft_reset_control; +/* 0x00A0 SMAW */ + u32 mmr_address_window; +/* 0x00A4 SMDW */ + u32 mmr_data_window; + u32 reserved_A8; + u32 reserved_AC; +/* A whole bunch of reserved space */ + u32 reserved_Bx[4]; + u32 reserved_Cx[4]; + u32 reserved_Dx[4]; + u32 reserved_Ex[4]; + u32 reserved_Fx[4]; + u32 reserved_1xx[64]; + u32 reserved_2xx[64]; + u32 reserved_3xx[64]; +/* + * Accessable to FN#0 only + * 0x0400 TCA */ + u32 task_context_assignment[256]; +/* MSI-X registers not included */ +}; + +/* + * ***************************************************************************** + * SDMA Registers + * ***************************************************************************** */ +#define SCU_SDMA_BASE 0x6000 +#define SCU_SDMA_PUFATLHAR_OFFSET 0x0000 +#define SCU_SDMA_PUFATUHAR_OFFSET 0x0004 +#define SCU_SDMA_UFLHBAR_OFFSET 0x0008 +#define SCU_SDMA_UFUHBAR_OFFSET 0x000C +#define SCU_SDMA_UFQC_OFFSET 0x0010 +#define SCU_SDMA_UFQPP_OFFSET 0x0014 +#define SCU_SDMA_UFQGP_OFFSET 0x0018 +#define SCU_SDMA_PDMACR_OFFSET 0x001C +#define SCU_SDMA_CDMACR_OFFSET 0x0080 + +/** + * struct scu_sdma_registers - These are the SCU SDMA Registers + * + * + */ +struct scu_sdma_registers { +/* 0x0000 PUFATLHAR */ + u32 uf_address_table_lower; +/* 0x0004 PUFATUHAR */ + u32 uf_address_table_upper; +/* 0x0008 UFLHBAR */ + u32 uf_header_base_address_lower; +/* 0x000C UFUHBAR */ + u32 uf_header_base_address_upper; +/* 0x0010 UFQC */ + u32 unsolicited_frame_queue_control; +/* 0x0014 UFQPP */ + u32 unsolicited_frame_put_pointer; +/* 0x0018 UFQGP */ + u32 unsolicited_frame_get_pointer; +/* 0x001C PDMACR */ + u32 pdma_configuration; +/* Reserved until offset 0x80 */ + u32 reserved_0020_007C[0x18]; +/* 0x0080 CDMACR */ + u32 cdma_configuration; +/* Remainder SDMA register space */ + u32 reserved_0084_0400[0xDF]; + +}; + +/* + * ***************************************************************************** + * * SCU Link Registers + * ***************************************************************************** */ +#define SCU_PEG0_OFFSET 0x0000 +#define SCU_PEG1_OFFSET 0x8000 + +#define SCU_TL0_OFFSET 0x0000 +#define SCU_TL1_OFFSET 0x0400 +#define SCU_TL2_OFFSET 0x0800 +#define SCU_TL3_OFFSET 0x0C00 + +#define SCU_LL_OFFSET 0x0080 +#define SCU_LL0_OFFSET (SCU_TL0_OFFSET + SCU_LL_OFFSET) +#define SCU_LL1_OFFSET (SCU_TL1_OFFSET + SCU_LL_OFFSET) +#define SCU_LL2_OFFSET (SCU_TL2_OFFSET + SCU_LL_OFFSET) +#define SCU_LL3_OFFSET (SCU_TL3_OFFSET + SCU_LL_OFFSET) + +/* Transport Layer Offsets (PEG + TL) */ +#define SCU_TLCR_OFFSET 0x0000 +#define SCU_TLADTR_OFFSET 0x0004 +#define SCU_TLTTMR_OFFSET 0x0008 +#define SCU_TLEECR0_OFFSET 0x000C +#define SCU_STPTLDARNI_OFFSET 0x0010 + + +#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_SHIFT (0) +#define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_MASK (0x00000001) +#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_SHIFT (1) +#define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_MASK (0x00000002) +#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_SHIFT (3) +#define SCU_TLCR_STP_WRITE_DATA_PREFETCH_MASK (0x00000008) +#define SCU_TLCR_CMD_NAK_STATUS_CODE_SHIFT (4) +#define SCU_TLCR_CMD_NAK_STATUS_CODE_MASK (0x00000010) +#define SCU_TLCR_RESERVED_MASK (0xFFFFFFEB) + +#define SCU_TLCR_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_TLCR_ ## name) + +/** + * struct scu_transport_layer_registers - These are the SCU Transport Layer + * registers + * + * + */ +struct scu_transport_layer_registers { + /* 0x0000 TLCR */ + u32 control; + /* 0x0004 TLADTR */ + u32 arbitration_delay_timer; + /* 0x0008 TLTTMR */ + u32 timer_test_mode; + /* 0x000C reserved */ + u32 reserved_0C; + /* 0x0010 STPTLDARNI */ + u32 stp_rni; + /* 0x0014 TLFEWPORCTRL */ + u32 tlfe_wpo_read_control; + /* 0x0018 TLFEWPORDATA */ + u32 tlfe_wpo_read_data; + /* 0x001C RXTLSSCSR1 */ + u32 rxtl_single_step_control_status_1; + /* 0x0020 RXTLSSCSR2 */ + u32 rxtl_single_step_control_status_2; + /* 0x0024 AWTRDDCR */ + u32 tlfe_awt_retry_delay_debug_control; + /* Remainder of TL memory space */ + u32 reserved_0028_007F[0x16]; + +}; + +/* Protocol Engine Group Registers */ +#define SCU_SCUVZECRx_OFFSET 0x1080 + +/* Link Layer Offsets (PEG + TL + LL) */ +#define SCU_SAS_SPDTOV_OFFSET 0x0000 +#define SCU_SAS_LLSTA_OFFSET 0x0004 +#define SCU_SATA_PSELTOV_OFFSET 0x0008 +#define SCU_SAS_TIMETOV_OFFSET 0x0010 +#define SCU_SAS_LOSTOT_OFFSET 0x0014 +#define SCU_SAS_LNKTOV_OFFSET 0x0018 +#define SCU_SAS_PHYTOV_OFFSET 0x001C +#define SCU_SAS_AFERCNT_OFFSET 0x0020 +#define SCU_SAS_WERCNT_OFFSET 0x0024 +#define SCU_SAS_TIID_OFFSET 0x0028 +#define SCU_SAS_TIDNH_OFFSET 0x002C +#define SCU_SAS_TIDNL_OFFSET 0x0030 +#define SCU_SAS_TISSAH_OFFSET 0x0034 +#define SCU_SAS_TISSAL_OFFSET 0x0038 +#define SCU_SAS_TIPID_OFFSET 0x003C +#define SCU_SAS_TIRES2_OFFSET 0x0040 +#define SCU_SAS_ADRSTA_OFFSET 0x0044 +#define SCU_SAS_MAWTTOV_OFFSET 0x0048 +#define SCU_SAS_FRPLDFIL_OFFSET 0x0054 +#define SCU_SAS_RFCNT_OFFSET 0x0060 +#define SCU_SAS_TFCNT_OFFSET 0x0064 +#define SCU_SAS_RFDCNT_OFFSET 0x0068 +#define SCU_SAS_TFDCNT_OFFSET 0x006C +#define SCU_SAS_LERCNT_OFFSET 0x0070 +#define SCU_SAS_RDISERRCNT_OFFSET 0x0074 +#define SCU_SAS_CRERCNT_OFFSET 0x0078 +#define SCU_STPCTL_OFFSET 0x007C +#define SCU_SAS_PCFG_OFFSET 0x0080 +#define SCU_SAS_CLKSM_OFFSET 0x0084 +#define SCU_SAS_TXCOMWAKE_OFFSET 0x0088 +#define SCU_SAS_TXCOMINIT_OFFSET 0x008C +#define SCU_SAS_TXCOMSAS_OFFSET 0x0090 +#define SCU_SAS_COMINIT_OFFSET 0x0094 +#define SCU_SAS_COMWAKE_OFFSET 0x0098 +#define SCU_SAS_COMSAS_OFFSET 0x009C +#define SCU_SAS_SFERCNT_OFFSET 0x00A0 +#define SCU_SAS_CDFERCNT_OFFSET 0x00A4 +#define SCU_SAS_DNFERCNT_OFFSET 0x00A8 +#define SCU_SAS_PRSTERCNT_OFFSET 0x00AC +#define SCU_SAS_CNTCTL_OFFSET 0x00B0 +#define SCU_SAS_SSPTOV_OFFSET 0x00B4 +#define SCU_FTCTL_OFFSET 0x00B8 +#define SCU_FRCTL_OFFSET 0x00BC +#define SCU_FTWMRK_OFFSET 0x00C0 +#define SCU_ENSPINUP_OFFSET 0x00C4 +#define SCU_SAS_TRNTOV_OFFSET 0x00C8 +#define SCU_SAS_PHYCAP_OFFSET 0x00CC +#define SCU_SAS_PHYCTL_OFFSET 0x00D0 +#define SCU_SAS_LLCTL_OFFSET 0x00D8 +#define SCU_AFE_XCVRCR_OFFSET 0x00DC +#define SCU_AFE_LUTCR_OFFSET 0x00E0 + +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_SHIFT (0) +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_MASK (0x00000003) +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 (0) +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 (1) +#define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3 (2) +#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_SHIFT (2) +#define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_MASK (0x000003FC) +#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_SHIFT (16) +#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_MASK (0x00010000) +#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_SHIFT (17) +#define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_MASK (0x00020000) +#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_SHIFT (24) +#define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_MASK (0xFF000000) +#define SCU_SAS_LINK_LAYER_CONTROL_RESERVED (0x00FCFC00) + +#define SCU_SAS_LLCTL_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_SAS_LINK_LAYER_CONTROL_ ## name, value) + +#define SCU_SAS_LLCTL_GEN_BIT(name) \ + SCU_GEN_BIT(SCU_SAS_LINK_LAYER_CONTROL_ ## name) + + +/* #define SCU_FRXHECR_DCNT_OFFSET 0x00B0 */ +#define SCU_PSZGCR_OFFSET 0x00E4 +#define SCU_SAS_RECPHYCAP_OFFSET 0x00E8 +/* #define SCU_TX_LUTSEL_OFFSET 0x00B8 */ + +#define SCU_SAS_PTxC_OFFSET 0x00D4 /* Same offset as SAS_TCTSTM */ + +/** + * struct scu_link_layer_registers - SCU Link Layer Registers + * + * + */ +struct scu_link_layer_registers { +/* 0x0000 SAS_SPDTOV */ + u32 speed_negotiation_timers; +/* 0x0004 SAS_LLSTA */ + u32 link_layer_status; +/* 0x0008 SATA_PSELTOV */ + u32 port_selector_timeout; + u32 reserved0C; +/* 0x0010 SAS_TIMETOV */ + u32 timeout_unit_value; +/* 0x0014 SAS_RCDTOV */ + u32 rcd_timeout; +/* 0x0018 SAS_LNKTOV */ + u32 link_timer_timeouts; +/* 0x001C SAS_PHYTOV */ + u32 sas_phy_timeouts; +/* 0x0020 SAS_AFERCNT */ + u32 received_address_frame_error_counter; +/* 0x0024 SAS_WERCNT */ + u32 invalid_dword_counter; +/* 0x0028 SAS_TIID */ + u32 transmit_identification; +/* 0x002C SAS_TIDNH */ + u32 sas_device_name_high; +/* 0x0030 SAS_TIDNL */ + u32 sas_device_name_low; +/* 0x0034 SAS_TISSAH */ + u32 source_sas_address_high; +/* 0x0038 SAS_TISSAL */ + u32 source_sas_address_low; +/* 0x003C SAS_TIPID */ + u32 identify_frame_phy_id; +/* 0x0040 SAS_TIRES2 */ + u32 identify_frame_reserved; +/* 0x0044 SAS_ADRSTA */ + u32 received_address_frame; +/* 0x0048 SAS_MAWTTOV */ + u32 maximum_arbitration_wait_timer_timeout; +/* 0x004C SAS_PTxC */ + u32 transmit_primitive; +/* 0x0050 SAS_RORES */ + u32 error_counter_event_notification_control; +/* 0x0054 SAS_FRPLDFIL */ + u32 frxq_payload_fill_threshold; +/* 0x0058 SAS_LLHANG_TOT */ + u32 link_layer_hang_detection_timeout; + u32 reserved_5C; +/* 0x0060 SAS_RFCNT */ + u32 received_frame_count; +/* 0x0064 SAS_TFCNT */ + u32 transmit_frame_count; +/* 0x0068 SAS_RFDCNT */ + u32 received_dword_count; +/* 0x006C SAS_TFDCNT */ + u32 transmit_dword_count; +/* 0x0070 SAS_LERCNT */ + u32 loss_of_sync_error_count; +/* 0x0074 SAS_RDISERRCNT */ + u32 running_disparity_error_count; +/* 0x0078 SAS_CRERCNT */ + u32 received_frame_crc_error_count; +/* 0x007C STPCTL */ + u32 stp_control; +/* 0x0080 SAS_PCFG */ + u32 phy_configuration; +/* 0x0084 SAS_CLKSM */ + u32 clock_skew_management; +/* 0x0088 SAS_TXCOMWAKE */ + u32 transmit_comwake_signal; +/* 0x008C SAS_TXCOMINIT */ + u32 transmit_cominit_signal; +/* 0x0090 SAS_TXCOMSAS */ + u32 transmit_comsas_signal; +/* 0x0094 SAS_COMINIT */ + u32 cominit_control; +/* 0x0098 SAS_COMWAKE */ + u32 comwake_control; +/* 0x009C SAS_COMSAS */ + u32 comsas_control; +/* 0x00A0 SAS_SFERCNT */ + u32 received_short_frame_count; +/* 0x00A4 SAS_CDFERCNT */ + u32 received_frame_without_credit_count; +/* 0x00A8 SAS_DNFERCNT */ + u32 received_frame_after_done_count; +/* 0x00AC SAS_PRSTERCNT */ + u32 phy_reset_problem_count; +/* 0x00B0 SAS_CNTCTL */ + u32 counter_control; +/* 0x00B4 SAS_SSPTOV */ + u32 ssp_timer_timeout_values; +/* 0x00B8 FTCTL */ + u32 ftx_control; +/* 0x00BC FRCTL */ + u32 frx_control; +/* 0x00C0 FTWMRK */ + u32 ftx_watermark; +/* 0x00C4 ENSPINUP */ + u32 notify_enable_spinup_control; +/* 0x00C8 SAS_TRNTOV */ + u32 sas_training_sequence_timer_values; +/* 0x00CC SAS_PHYCAP */ + u32 phy_capabilities; +/* 0x00D0 SAS_PHYCTL */ + u32 phy_control; + u32 reserved_d4; +/* 0x00D8 LLCTL */ + u32 link_layer_control; +/* 0x00DC AFE_XCVRCR */ + u32 afe_xcvr_control; +/* 0x00E0 AFE_LUTCR */ + u32 afe_lookup_table_control; +/* 0x00E4 PSZGCR */ + u32 phy_source_zone_group_control; +/* 0x00E8 SAS_RECPHYCAP */ + u32 receive_phycap; + u32 reserved_ec; +/* 0x00F0 SNAFERXRSTCTL */ + u32 speed_negotiation_afe_rx_reset_control; +/* 0x00F4 SAS_SSIPMCTL */ + u32 power_management_control; +/* 0x00F8 SAS_PSPREQ_PRIM */ + u32 sas_pm_partial_request_primitive; +/* 0x00FC SAS_PSSREQ_PRIM */ + u32 sas_pm_slumber_request_primitive; +/* 0x0100 SAS_PPSACK_PRIM */ + u32 sas_pm_ack_primitive_register; +/* 0x0104 SAS_PSNAK_PRIM */ + u32 sas_pm_nak_primitive_register; +/* 0x0108 SAS_SSIPMTOV */ + u32 sas_primitive_timeout; + u32 reserved_10c; +/* 0x0110 - 0x011C PLAPRDCTRLxREG */ + u32 pla_product_control[4]; +/* 0x0120 PLAPRDSUMREG */ + u32 pla_product_sum; +/* 0x0124 PLACONTROLREG */ + u32 pla_control; +/* Remainder of memory space 896 bytes */ + u32 reserved_0128_037f[0x96]; + +}; + +/* + * 0x00D4 // Same offset as SAS_TCTSTM SAS_PTxC + * u32 primitive_transmit_control; */ + +/* + * ---------------------------------------------------------------------------- + * SGPIO + * ---------------------------------------------------------------------------- */ +#define SCU_SGPIO_OFFSET 0x1400 + +/* #define SCU_SGPIO_OFFSET 0x6000 // later moves to 0x1400 see HSD 652625 */ +#define SCU_SGPIO_SGICR_OFFSET 0x0000 +#define SCU_SGPIO_SGPBR_OFFSET 0x0004 +#define SCU_SGPIO_SGSDLR_OFFSET 0x0008 +#define SCU_SGPIO_SGSDUR_OFFSET 0x000C +#define SCU_SGPIO_SGSIDLR_OFFSET 0x0010 +#define SCU_SGPIO_SGSIDUR_OFFSET 0x0014 +#define SCU_SGPIO_SGVSCR_OFFSET 0x0018 +/* Address from 0x0820 to 0x083C */ +#define SCU_SGPIO_SGODSR_OFFSET 0x0020 + +/** + * struct scu_sgpio_registers - SCU SGPIO Registers + * + * + */ +struct scu_sgpio_registers { +/* 0x0000 SGPIO_SGICR */ + u32 interface_control; +/* 0x0004 SGPIO_SGPBR */ + u32 blink_rate; +/* 0x0008 SGPIO_SGSDLR */ + u32 start_drive_lower; +/* 0x000C SGPIO_SGSDUR */ + u32 start_drive_upper; +/* 0x0010 SGPIO_SGSIDLR */ + u32 serial_input_lower; +/* 0x0014 SGPIO_SGSIDUR */ + u32 serial_input_upper; +/* 0x0018 SGPIO_SGVSCR */ + u32 vendor_specific_code; +/* 0x0020 SGPIO_SGODSR */ + u32 ouput_data_select[8]; +/* Remainder of memory space 256 bytes */ + u32 reserved_1444_14ff[0x31]; + +}; + +/* + * ***************************************************************************** + * * Defines for VIIT entry offsets + * * Access additional entries by SCU_VIIT_BASE + index * 0x10 + * ***************************************************************************** */ +#define SCU_VIIT_BASE 0x1c00 + +struct scu_viit_registers { + u32 registers[256]; +}; + +/* + * ***************************************************************************** + * * SCU PORT TASK SCHEDULER REGISTERS + * ***************************************************************************** */ + +#define SCU_PTSG_BASE 0x1000 + +#define SCU_PTSG_PTSGCR_OFFSET 0x0000 +#define SCU_PTSG_RTCR_OFFSET 0x0004 +#define SCU_PTSG_RTCCR_OFFSET 0x0008 +#define SCU_PTSG_PTS0CR_OFFSET 0x0010 +#define SCU_PTSG_PTS0SR_OFFSET 0x0014 +#define SCU_PTSG_PTS1CR_OFFSET 0x0018 +#define SCU_PTSG_PTS1SR_OFFSET 0x001C +#define SCU_PTSG_PTS2CR_OFFSET 0x0020 +#define SCU_PTSG_PTS2SR_OFFSET 0x0024 +#define SCU_PTSG_PTS3CR_OFFSET 0x0028 +#define SCU_PTSG_PTS3SR_OFFSET 0x002C +#define SCU_PTSG_PCSPE0CR_OFFSET 0x0030 +#define SCU_PTSG_PCSPE1CR_OFFSET 0x0034 +#define SCU_PTSG_PCSPE2CR_OFFSET 0x0038 +#define SCU_PTSG_PCSPE3CR_OFFSET 0x003C +#define SCU_PTSG_ETMTSCCR_OFFSET 0x0040 +#define SCU_PTSG_ETMRNSCCR_OFFSET 0x0044 + +/** + * struct scu_port_task_scheduler_registers - These are the control/stats pairs + * for each Port Task Scheduler. + * + * + */ +struct scu_port_task_scheduler_registers { + u32 control; + u32 status; +}; + +/** + * struct scu_port_task_scheduler_group_registers - These are the PORT Task + * Scheduler registers + * + * + */ +struct scu_port_task_scheduler_group_registers { +/* 0x0000 PTSGCR */ + u32 control; +/* 0x0004 RTCR */ + u32 real_time_clock; +/* 0x0008 RTCCR */ + u32 real_time_clock_control; +/* 0x000C */ + u32 reserved_0C; +/* + * 0x0010 PTS0CR + * 0x0014 PTS0SR + * 0x0018 PTS1CR + * 0x001C PTS1SR + * 0x0020 PTS2CR + * 0x0024 PTS2SR + * 0x0028 PTS3CR + * 0x002C PTS3SR */ + struct scu_port_task_scheduler_registers port[4]; +/* + * 0x0030 PCSPE0CR + * 0x0034 PCSPE1CR + * 0x0038 PCSPE2CR + * 0x003C PCSPE3CR */ + u32 protocol_engine[4]; +/* 0x0040 ETMTSCCR */ + u32 tc_scanning_interval_control; +/* 0x0044 ETMRNSCCR */ + u32 rnc_scanning_interval_control; +/* Remainder of memory space 128 bytes */ + u32 reserved_1048_107f[0x0E]; + +}; + +#define SCU_PTSG_SCUVZECR_OFFSET 0x003C + +/* + * ***************************************************************************** + * * AFE REGISTERS + * ***************************************************************************** */ +#define SCU_AFE_MMR_BASE 0xE000 + +/* + * AFE 0 is at offset 0x0800 + * AFE 1 is at offset 0x0900 + * AFE 2 is at offset 0x0a00 + * AFE 3 is at offset 0x0b00 */ +struct scu_afe_transceiver { + /* 0x0000 AFE_XCVR_CTRL0 */ + u32 afe_xcvr_control0; + /* 0x0004 AFE_XCVR_CTRL1 */ + u32 afe_xcvr_control1; + /* 0x0008 */ + u32 reserved_0008; + /* 0x000c afe_dfx_rx_control0 */ + u32 afe_dfx_rx_control0; + /* 0x0010 AFE_DFX_RX_CTRL1 */ + u32 afe_dfx_rx_control1; + /* 0x0014 */ + u32 reserved_0014; + /* 0x0018 AFE_DFX_RX_STS0 */ + u32 afe_dfx_rx_status0; + /* 0x001c AFE_DFX_RX_STS1 */ + u32 afe_dfx_rx_status1; + /* 0x0020 */ + u32 reserved_0020; + /* 0x0024 AFE_TX_CTRL */ + u32 afe_tx_control; + /* 0x0028 AFE_TX_AMP_CTRL0 */ + u32 afe_tx_amp_control0; + /* 0x002c AFE_TX_AMP_CTRL1 */ + u32 afe_tx_amp_control1; + /* 0x0030 AFE_TX_AMP_CTRL2 */ + u32 afe_tx_amp_control2; + /* 0x0034 AFE_TX_AMP_CTRL3 */ + u32 afe_tx_amp_control3; + /* 0x0038 afe_tx_ssc_control */ + u32 afe_tx_ssc_control; + /* 0x003c */ + u32 reserved_003c; + /* 0x0040 AFE_RX_SSC_CTRL0 */ + u32 afe_rx_ssc_control0; + /* 0x0044 AFE_RX_SSC_CTRL1 */ + u32 afe_rx_ssc_control1; + /* 0x0048 AFE_RX_SSC_CTRL2 */ + u32 afe_rx_ssc_control2; + /* 0x004c AFE_RX_EQ_STS0 */ + u32 afe_rx_eq_status0; + /* 0x0050 AFE_RX_EQ_STS1 */ + u32 afe_rx_eq_status1; + /* 0x0054 AFE_RX_CDR_STS */ + u32 afe_rx_cdr_status; + /* 0x0058 */ + u32 reserved_0058; + /* 0x005c AFE_CHAN_CTRL */ + u32 afe_channel_control; + /* 0x0060-0x006c */ + u32 reserved_0060_006c[0x04]; + /* 0x0070 AFE_XCVR_EC_STS0 */ + u32 afe_xcvr_error_capture_status0; + /* 0x0074 AFE_XCVR_EC_STS1 */ + u32 afe_xcvr_error_capture_status1; + /* 0x0078 AFE_XCVR_EC_STS2 */ + u32 afe_xcvr_error_capture_status2; + /* 0x007c afe_xcvr_ec_status3 */ + u32 afe_xcvr_error_capture_status3; + /* 0x0080 AFE_XCVR_EC_STS4 */ + u32 afe_xcvr_error_capture_status4; + /* 0x0084 AFE_XCVR_EC_STS5 */ + u32 afe_xcvr_error_capture_status5; + /* 0x0088-0x00fc */ + u32 reserved_008c_00fc[0x1e]; +}; + +/** + * struct scu_afe_registers - AFE Regsiters + * + * + */ +/* Uaoa AFE registers */ +struct scu_afe_registers { + /* 0Xe000 AFE_BIAS_CTRL */ + u32 afe_bias_control; + u32 reserved_0004; + /* 0x0008 AFE_PLL_CTRL0 */ + u32 afe_pll_control0; + /* 0x000c AFE_PLL_CTRL1 */ + u32 afe_pll_control1; + /* 0x0010 AFE_PLL_CTRL2 */ + u32 afe_pll_control2; + /* 0x0014 AFE_CB_STS */ + u32 afe_common_block_status; + /* 0x0018-0x007c */ + u32 reserved_18_7c[0x1a]; + /* 0x0080 AFE_PMSN_MCTRL0 */ + u32 afe_pmsn_master_control0; + /* 0x0084 AFE_PMSN_MCTRL1 */ + u32 afe_pmsn_master_control1; + /* 0x0088 AFE_PMSN_MCTRL2 */ + u32 afe_pmsn_master_control2; + /* 0x008C-0x00fc */ + u32 reserved_008c_00fc[0x1D]; + /* 0x0100 AFE_DFX_MST_CTRL0 */ + u32 afe_dfx_master_control0; + /* 0x0104 AFE_DFX_MST_CTRL1 */ + u32 afe_dfx_master_control1; + /* 0x0108 AFE_DFX_DCL_CTRL */ + u32 afe_dfx_dcl_control; + /* 0x010c AFE_DFX_DMON_CTRL */ + u32 afe_dfx_digital_monitor_control; + /* 0x0110 AFE_DFX_AMONP_CTRL */ + u32 afe_dfx_analog_p_monitor_control; + /* 0x0114 AFE_DFX_AMONN_CTRL */ + u32 afe_dfx_analog_n_monitor_control; + /* 0x0118 AFE_DFX_NTL_STS */ + u32 afe_dfx_ntl_status; + /* 0x011c AFE_DFX_FIFO_STS0 */ + u32 afe_dfx_fifo_status0; + /* 0x0120 AFE_DFX_FIFO_STS1 */ + u32 afe_dfx_fifo_status1; + /* 0x0124 AFE_DFX_MPAT_CTRL */ + u32 afe_dfx_master_pattern_control; + /* 0x0128 AFE_DFX_P0_CTRL */ + u32 afe_dfx_p0_control; + /* 0x012c-0x01a8 AFE_DFX_P0_DRx */ + u32 afe_dfx_p0_data[32]; + /* 0x01ac */ + u32 reserved_01ac; + /* 0x01b0-0x020c AFE_DFX_P0_IRx */ + u32 afe_dfx_p0_instruction[24]; + /* 0x0210 */ + u32 reserved_0210; + /* 0x0214 AFE_DFX_P1_CTRL */ + u32 afe_dfx_p1_control; + /* 0x0218-0x245 AFE_DFX_P1_DRx */ + u32 afe_dfx_p1_data[16]; + /* 0x0258-0x029c */ + u32 reserved_0258_029c[0x12]; + /* 0x02a0-0x02bc AFE_DFX_P1_IRx */ + u32 afe_dfx_p1_instruction[8]; + /* 0x02c0-0x2fc */ + u32 reserved_02c0_02fc[0x10]; + /* 0x0300 AFE_DFX_TX_PMSN_CTRL */ + u32 afe_dfx_tx_pmsn_control; + /* 0x0304 AFE_DFX_RX_PMSN_CTRL */ + u32 afe_dfx_rx_pmsn_control; + u32 reserved_0308; + /* 0x030c AFE_DFX_NOA_CTRL0 */ + u32 afe_dfx_noa_control0; + /* 0x0310 AFE_DFX_NOA_CTRL1 */ + u32 afe_dfx_noa_control1; + /* 0x0314 AFE_DFX_NOA_CTRL2 */ + u32 afe_dfx_noa_control2; + /* 0x0318 AFE_DFX_NOA_CTRL3 */ + u32 afe_dfx_noa_control3; + /* 0x031c AFE_DFX_NOA_CTRL4 */ + u32 afe_dfx_noa_control4; + /* 0x0320 AFE_DFX_NOA_CTRL5 */ + u32 afe_dfx_noa_control5; + /* 0x0324 AFE_DFX_NOA_CTRL6 */ + u32 afe_dfx_noa_control6; + /* 0x0328 AFE_DFX_NOA_CTRL7 */ + u32 afe_dfx_noa_control7; + /* 0x032c-0x07fc */ + u32 reserved_032c_07fc[0x135]; + + /* 0x0800-0x0bfc */ + struct scu_afe_transceiver scu_afe_xcvr[4]; + + /* 0x0c00-0x0ffc */ + u32 reserved_0c00_0ffc[0x0100]; +}; + +struct scu_protocol_engine_group_registers { + u32 table[0xE0]; +}; + + +struct scu_viit_iit { + u32 table[256]; +}; + +/** + * Placeholder for the ZONE Partition Table information ZONING will not be + * included in the 1.1 release. + * + * + */ +struct scu_zone_partition_table { + u32 table[2048]; +}; + +/** + * Placeholder for the CRAM register since I am not sure if we need to + * read/write to these registers as yet. + * + * + */ +struct scu_completion_ram { + u32 ram[128]; +}; + +/** + * Placeholder for the FBRAM registers since I am not sure if we need to + * read/write to these registers as yet. + * + * + */ +struct scu_frame_buffer_ram { + u32 ram[128]; +}; + +#define scu_scratch_ram_SIZE_IN_DWORDS 256 + +/** + * Placeholder for the scratch RAM registers. + * + * + */ +struct scu_scratch_ram { + u32 ram[scu_scratch_ram_SIZE_IN_DWORDS]; +}; + +/** + * Placeholder since I am not yet sure what these registers are here for. + * + * + */ +struct noa_protocol_engine_partition { + u32 reserved[64]; +}; + +/** + * Placeholder since I am not yet sure what these registers are here for. + * + * + */ +struct noa_hub_partition { + u32 reserved[64]; +}; + +/** + * Placeholder since I am not yet sure what these registers are here for. + * + * + */ +struct noa_host_interface_partition { + u32 reserved[64]; +}; + +/** + * struct transport_link_layer_pair - The SCU Hardware pairs up the TL + * registers with the LL registers so we must place them adjcent to make the + * array of registers in the PEG. + * + * + */ +struct transport_link_layer_pair { + struct scu_transport_layer_registers tl; + struct scu_link_layer_registers ll; +}; + +/** + * struct scu_peg_registers - SCU Protocol Engine Memory mapped register space. + * These registers are unique to each protocol engine group. There can be + * at most two PEG for a single SCU part. + * + * + */ +struct scu_peg_registers { + struct transport_link_layer_pair pe[4]; + struct scu_port_task_scheduler_group_registers ptsg; + struct scu_protocol_engine_group_registers peg; + struct scu_sgpio_registers sgpio; + u32 reserved_01500_1BFF[0x1C0]; + struct scu_viit_entry viit[64]; + struct scu_zone_partition_table zpt0; + struct scu_zone_partition_table zpt1; +}; + +/** + * struct scu_registers - SCU regsiters including both PEG registers if we turn + * on that compile option. All of these registers are in the memory mapped + * space returned from BAR1. + * + * + */ +struct scu_registers { + /* 0x0000 - PEG 0 */ + struct scu_peg_registers peg0; + + /* 0x6000 - SDMA and Miscellaneous */ + struct scu_sdma_registers sdma; + struct scu_completion_ram cram; + struct scu_frame_buffer_ram fbram; + u32 reserved_6800_69FF[0x80]; + struct noa_protocol_engine_partition noa_pe; + struct noa_hub_partition noa_hub; + struct noa_host_interface_partition noa_if; + u32 reserved_6d00_7fff[0x4c0]; + + /* 0x8000 - PEG 1 */ + struct scu_peg_registers peg1; + + /* 0xE000 - AFE Registers */ + struct scu_afe_registers afe; + + /* 0xF000 - reserved */ + u32 reserved_f000_211fff[0x80c00]; + + /* 0x212000 - scratch RAM */ + struct scu_scratch_ram scratch_ram; +}; + +#endif /* _SCU_REGISTERS_HEADER_ */ diff --git a/drivers/scsi/isci/scu_completion_codes.h b/drivers/scsi/isci/scu_completion_codes.h new file mode 100644 index 000000000000..c8b329c695f9 --- /dev/null +++ b/drivers/scsi/isci/scu_completion_codes.h @@ -0,0 +1,283 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCU_COMPLETION_CODES_HEADER_ +#define _SCU_COMPLETION_CODES_HEADER_ + +/** + * This file contains the constants and macros for the SCU hardware completion + * codes. + * + * + */ + +#define SCU_COMPLETION_TYPE_SHIFT 28 +#define SCU_COMPLETION_TYPE_MASK 0x70000000 + +/** + * SCU_COMPLETION_TYPE() - + * + * This macro constructs an SCU completion type + */ +#define SCU_COMPLETION_TYPE(type) \ + ((u32)(type) << SCU_COMPLETION_TYPE_SHIFT) + +/** + * SCU_COMPLETION_TYPE() - + * + * These macros contain the SCU completion types SCU_COMPLETION_TYPE + */ +#define SCU_COMPLETION_TYPE_TASK SCU_COMPLETION_TYPE(0) +#define SCU_COMPLETION_TYPE_SDMA SCU_COMPLETION_TYPE(1) +#define SCU_COMPLETION_TYPE_UFI SCU_COMPLETION_TYPE(2) +#define SCU_COMPLETION_TYPE_EVENT SCU_COMPLETION_TYPE(3) +#define SCU_COMPLETION_TYPE_NOTIFY SCU_COMPLETION_TYPE(4) + +/** + * + * + * These constants provide the shift and mask values for the various parts of + * an SCU completion code. + */ +#define SCU_COMPLETION_STATUS_MASK 0x0FFC0000 +#define SCU_COMPLETION_TL_STATUS_MASK 0x0FC00000 +#define SCU_COMPLETION_TL_STATUS_SHIFT 22 +#define SCU_COMPLETION_SDMA_STATUS_MASK 0x003C0000 +#define SCU_COMPLETION_PEG_MASK 0x00010000 +#define SCU_COMPLETION_PORT_MASK 0x00007000 +#define SCU_COMPLETION_PE_MASK SCU_COMPLETION_PORT_MASK +#define SCU_COMPLETION_PE_SHIFT 12 +#define SCU_COMPLETION_INDEX_MASK 0x00000FFF + +/** + * SCU_GET_COMPLETION_TYPE() - + * + * This macro returns the SCU completion type. + */ +#define SCU_GET_COMPLETION_TYPE(completion_code) \ + ((completion_code) & SCU_COMPLETION_TYPE_MASK) + +/** + * SCU_GET_COMPLETION_STATUS() - + * + * This macro returns the SCU completion status. + */ +#define SCU_GET_COMPLETION_STATUS(completion_code) \ + ((completion_code) & SCU_COMPLETION_STATUS_MASK) + +/** + * SCU_GET_COMPLETION_TL_STATUS() - + * + * This macro returns the transport layer completion status. + */ +#define SCU_GET_COMPLETION_TL_STATUS(completion_code) \ + ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) + +/** + * SCU_MAKE_COMPLETION_STATUS() - + * + * This macro takes a completion code and performs the shift and mask + * operations to turn it into a completion code that can be compared to a + * SCU_GET_COMPLETION_TL_STATUS. + */ +#define SCU_MAKE_COMPLETION_STATUS(completion_code) \ + ((u32)(completion_code) << SCU_COMPLETION_TL_STATUS_SHIFT) + +/** + * SCU_NORMALIZE_COMPLETION_STATUS() - + * + * This macro takes a SCU_GET_COMPLETION_TL_STATUS and normalizes it for a + * return code. + */ +#define SCU_NORMALIZE_COMPLETION_STATUS(completion_code) \ + (\ + ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) \ + >> SCU_COMPLETION_TL_STATUS_SHIFT \ + ) + +/** + * SCU_GET_COMPLETION_SDMA_STATUS() - + * + * This macro returns the SDMA completion status. + */ +#define SCU_GET_COMPLETION_SDMA_STATUS(completion_code) \ + ((completion_code) & SCU_COMPLETION_SDMA_STATUS_MASK) + +/** + * SCU_GET_COMPLETION_PEG() - + * + * This macro returns the Protocol Engine Group from the completion code. + */ +#define SCU_GET_COMPLETION_PEG(completion_code) \ + ((completion_code) & SCU_COMPLETION_PEG_MASK) + +/** + * SCU_GET_COMPLETION_PORT() - + * + * This macro reuturns the logical port index from the completion code. + */ +#define SCU_GET_COMPLETION_PORT(completion_code) \ + ((completion_code) & SCU_COMPLETION_PORT_MASK) + +/** + * SCU_GET_PROTOCOL_ENGINE_INDEX() - + * + * This macro returns the PE index from the completion code. + */ +#define SCU_GET_PROTOCOL_ENGINE_INDEX(completion_code) \ + (((completion_code) & SCU_COMPLETION_PE_MASK) >> SCU_COMPLETION_PE_SHIFT) + +/** + * SCU_GET_COMPLETION_INDEX() - + * + * This macro returns the index of the completion which is either a TCi or an + * RNi depending on the completion type. + */ +#define SCU_GET_COMPLETION_INDEX(completion_code) \ + ((completion_code) & SCU_COMPLETION_INDEX_MASK) + +#define SCU_UNSOLICITED_FRAME_MASK 0x0FFF0000 +#define SCU_UNSOLICITED_FRAME_SHIFT 16 + +/** + * SCU_GET_FRAME_INDEX() - + * + * This macro returns a normalized frame index from an unsolicited frame + * completion. + */ +#define SCU_GET_FRAME_INDEX(completion_code) \ + (\ + ((completion_code) & SCU_UNSOLICITED_FRAME_MASK) \ + >> SCU_UNSOLICITED_FRAME_SHIFT \ + ) + +#define SCU_UNSOLICITED_FRAME_ERROR_MASK 0x00008000 + +/** + * SCU_GET_FRAME_ERROR() - + * + * This macro returns a zero (0) value if there is no frame error otherwise it + * returns non-zero (!0). + */ +#define SCU_GET_FRAME_ERROR(completion_code) \ + ((completion_code) & SCU_UNSOLICITED_FRAME_ERROR_MASK) + +/** + * + * + * These constants represent normalized completion codes which must be shifted + * 18 bits to match it with the hardware completion code. In a 16-bit compiler, + * immediate constants are 16-bit values (the size of an int). If we shift + * those by 18 bits, we completely lose the value. To ensure the value is a + * 32-bit value like we want, each immediate value must be cast to a u32. + */ +#define SCU_TASK_DONE_GOOD ((u32)0x00) +#define SCU_TASK_DONE_CRC_ERR ((u32)0x14) +#define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14) +#define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15) +#define SCU_TASK_DONE_NAK_CMD_ERR ((u32)0x16) +#define SCU_TASK_DONE_CMD_LL_R_ERR ((u32)0x16) +#define SCU_TASK_DONE_LL_R_ERR ((u32)0x17) +#define SCU_TASK_DONE_ACK_NAK_TO ((u32)0x17) +#define SCU_TASK_DONE_LL_PERR ((u32)0x18) +#define SCU_TASK_DONE_LL_SY_TERM ((u32)0x19) +#define SCU_TASK_DONE_NAK_ERR ((u32)0x19) +#define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A) +#define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A) +#define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B) +#define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B) +#define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C) +#define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C) +#define SCU_TASK_DONE_INV_FIS_TYPE ((u32)0x1D) +#define SCU_TASK_DONE_XR_IU_LEN_ERR ((u32)0x1D) +#define SCU_TASK_DONE_INV_FIS_LEN ((u32)0x1E) +#define SCU_TASK_DONE_XR_WD_LEN ((u32)0x1E) +#define SCU_TASK_DONE_SDMA_ERR ((u32)0x1F) +#define SCU_TASK_DONE_OFFSET_ERR ((u32)0x20) +#define SCU_TASK_DONE_MAX_PLD_ERR ((u32)0x21) +#define SCU_TASK_DONE_EXCESS_DATA ((u32)0x22) +#define SCU_TASK_DONE_LF_ERR ((u32)0x23) +#define SCU_TASK_DONE_UNEXP_FIS ((u32)0x24) +#define SCU_TASK_DONE_UNEXP_RESP ((u32)0x24) +#define SCU_TASK_DONE_EARLY_RESP ((u32)0x25) +#define SCU_TASK_DONE_SMP_RESP_TO_ERR ((u32)0x26) +#define SCU_TASK_DONE_DMASETUP_DIRERR ((u32)0x27) +#define SCU_TASK_DONE_SMP_UFI_ERR ((u32)0x27) +#define SCU_TASK_DONE_XFERCNT_ERR ((u32)0x28) +#define SCU_TASK_DONE_SMP_FRM_TYPE_ERR ((u32)0x28) +#define SCU_TASK_DONE_SMP_LL_RX_ERR ((u32)0x29) +#define SCU_TASK_DONE_RESP_LEN_ERR ((u32)0x2A) +#define SCU_TASK_DONE_UNEXP_DATA ((u32)0x2B) +#define SCU_TASK_DONE_OPEN_FAIL ((u32)0x2C) +#define SCU_TASK_DONE_UNEXP_SDBFIS ((u32)0x2D) +#define SCU_TASK_DONE_REG_ERR ((u32)0x2E) +#define SCU_TASK_DONE_SDB_ERR ((u32)0x2F) +#define SCU_TASK_DONE_TASK_ABORT ((u32)0x30) +#define SCU_TASK_DONE_CMD_SDMA_ERR ((U32)0x32) +#define SCU_TASK_DONE_CMD_LL_ABORT_ERR ((U32)0x33) +#define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION ((u32)0x34) +#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1 ((u32)0x35) +#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2 ((u32)0x36) +#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3 ((u32)0x37) +#define SCU_TASK_OPEN_REJECT_BAD_DESTINATION ((u32)0x38) +#define SCU_TASK_OPEN_REJECT_ZONE_VIOLATION ((u32)0x39) +#define SCU_TASK_DONE_VIIT_ENTRY_NV ((u32)0x3A) +#define SCU_TASK_DONE_IIT_ENTRY_NV ((u32)0x3B) +#define SCU_TASK_DONE_RNCNV_OUTBOUND ((u32)0x3C) +#define SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY ((u32)0x3D) +#define SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED ((u32)0x3E) +#define SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED ((u32)0x3F) + +#endif /* _SCU_COMPLETION_CODES_HEADER_ */ diff --git a/drivers/scsi/isci/scu_event_codes.h b/drivers/scsi/isci/scu_event_codes.h new file mode 100644 index 000000000000..36a945ad5722 --- /dev/null +++ b/drivers/scsi/isci/scu_event_codes.h @@ -0,0 +1,336 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCU_EVENT_CODES_HEADER__ +#define __SCU_EVENT_CODES_HEADER__ + +/** + * This file contains the constants and macros for the SCU event codes. + * + * + */ + +#define SCU_EVENT_TYPE_CODE_SHIFT 24 +#define SCU_EVENT_TYPE_CODE_MASK 0x0F000000 + +#define SCU_EVENT_SPECIFIC_CODE_SHIFT 18 +#define SCU_EVENT_SPECIFIC_CODE_MASK 0x00FC0000 + +#define SCU_EVENT_CODE_MASK \ + (SCU_EVENT_TYPE_CODE_MASK | SCU_EVENT_SPECIFIC_CODE_MASK) + +/** + * SCU_EVENT_TYPE() - + * + * This macro constructs an SCU event type from the type value. + */ +#define SCU_EVENT_TYPE(type) \ + ((u32)(type) << SCU_EVENT_TYPE_CODE_SHIFT) + +/** + * SCU_EVENT_SPECIFIC() - + * + * This macro constructs an SCU event specifier from the code value. + */ +#define SCU_EVENT_SPECIFIC(code) \ + ((u32)(code) << SCU_EVENT_SPECIFIC_CODE_SHIFT) + +/** + * SCU_EVENT_MESSAGE() - + * + * This macro constructs a combines an SCU event type and SCU event specifier + * from the type and code values. + */ +#define SCU_EVENT_MESSAGE(type, code) \ + ((type) | SCU_EVENT_SPECIFIC(code)) + +/** + * SCU_EVENT_TYPE() - + * + * SCU_EVENT_TYPES + */ +#define SCU_EVENT_TYPE_SMU_COMMAND_ERROR SCU_EVENT_TYPE(0x08) +#define SCU_EVENT_TYPE_SMU_PCQ_ERROR SCU_EVENT_TYPE(0x09) +#define SCU_EVENT_TYPE_SMU_ERROR SCU_EVENT_TYPE(0x00) +#define SCU_EVENT_TYPE_TRANSPORT_ERROR SCU_EVENT_TYPE(0x01) +#define SCU_EVENT_TYPE_BROADCAST_CHANGE SCU_EVENT_TYPE(0x02) +#define SCU_EVENT_TYPE_OSSP_EVENT SCU_EVENT_TYPE(0x03) +#define SCU_EVENT_TYPE_FATAL_MEMORY_ERROR SCU_EVENT_TYPE(0x0F) +#define SCU_EVENT_TYPE_RNC_SUSPEND_TX SCU_EVENT_TYPE(0x04) +#define SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX SCU_EVENT_TYPE(0x05) +#define SCU_EVENT_TYPE_RNC_OPS_MISC SCU_EVENT_TYPE(0x06) +#define SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT SCU_EVENT_TYPE(0x07) +#define SCU_EVENT_TYPE_ERR_CNT_EVENT SCU_EVENT_TYPE(0x0A) + +/** + * + * + * SCU_EVENT_SPECIFIERS + */ +#define SCU_EVENT_SPECIFIER_DRIVER_SUSPEND 0x20 +#define SCU_EVENT_SPECIFIER_RNC_RELEASE 0x00 + +/** + * + * + * SMU_COMMAND_EVENTS + */ +#define SCU_EVENT_INVALID_CONTEXT_COMMAND \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_COMMAND_ERROR, 0x00) + +/** + * + * + * SMU_PCQ_EVENTS + */ +#define SCU_EVENT_UNCORRECTABLE_PCQ_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_PCQ_ERROR, 0x00) + +/** + * + * + * SMU_EVENTS + */ +#define SCU_EVENT_UNCORRECTABLE_REGISTER_WRITE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x02) +#define SCU_EVENT_UNCORRECTABLE_REGISTER_READ \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x03) +#define SCU_EVENT_PCIE_INTERFACE_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x04) +#define SCU_EVENT_FUNCTION_LEVEL_RESET \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x05) + +/** + * + * + * TRANSPORT_LEVEL_ERRORS + */ +#define SCU_EVENT_ACK_NAK_TIMEOUT_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_TRANSPORT_ERROR, 0x00) + +/** + * + * + * BROADCAST_CHANGE_EVENTS + */ +#define SCU_EVENT_BROADCAST_CHANGE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x01) +#define SCU_EVENT_BROADCAST_RESERVED0 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x02) +#define SCU_EVENT_BROADCAST_RESERVED1 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x03) +#define SCU_EVENT_BROADCAST_SES \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x04) +#define SCU_EVENT_BROADCAST_EXPANDER \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x05) +#define SCU_EVENT_BROADCAST_AEN \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x06) +#define SCU_EVENT_BROADCAST_RESERVED3 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x07) +#define SCU_EVENT_BROADCAST_RESERVED4 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x08) +#define SCU_EVENT_PE_SUSPENDED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x09) + +/** + * + * + * OSSP_EVENTS + */ +#define SCU_EVENT_PORT_SELECTOR_DETECTED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x10) +#define SCU_EVENT_SENT_PORT_SELECTION \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x11) +#define SCU_EVENT_HARD_RESET_TRANSMITTED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x12) +#define SCU_EVENT_HARD_RESET_RECEIVED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x13) +#define SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x15) +#define SCU_EVENT_LINK_FAILURE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x16) +#define SCU_EVENT_SATA_SPINUP_HOLD \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x17) +#define SCU_EVENT_SAS_15_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x18) +#define SCU_EVENT_SAS_15 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x19) +#define SCU_EVENT_SAS_30_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1A) +#define SCU_EVENT_SAS_30 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1B) +#define SCU_EVENT_SAS_60_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1C) +#define SCU_EVENT_SAS_60 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1D) +#define SCU_EVENT_SATA_15_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1E) +#define SCU_EVENT_SATA_15 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1F) +#define SCU_EVENT_SATA_30_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x20) +#define SCU_EVENT_SATA_30 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x21) +#define SCU_EVENT_SATA_60_SSC \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x22) +#define SCU_EVENT_SATA_60 \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x23) +#define SCU_EVENT_SAS_PHY_DETECTED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x24) +#define SCU_EVENT_SATA_PHY_DETECTED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x25) + +/** + * + * + * FATAL_INTERNAL_MEMORY_ERROR_EVENTS + */ +#define SCU_EVENT_TSC_RNSC_UNCORRECTABLE_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x00) +#define SCU_EVENT_TC_RNC_UNCORRECTABLE_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x01) +#define SCU_EVENT_ZPT_UNCORRECTABLE_ERROR \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x02) + +/** + * + * + * REMOTE_NODE_SUSPEND_EVENTS + */ +#define SCU_EVENT_TL_RNC_SUSPEND_TX \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x00) +#define SCU_EVENT_TL_RNC_SUSPEND_TX_RX \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x00) +#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20) +#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX_RX \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x20) + +/** + * + * + * REMOTE_NODE_MISC_EVENTS + */ +#define SCU_EVENT_POST_RCN_RELEASE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, SCU_EVENT_SPECIFIER_RNC_RELEASE) +#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_ENABLE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x01) +#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_DISABLE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x02) +#define SCU_EVENT_POST_RNC_COMPLETE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x03) +#define SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x04) + +/** + * + * + * ERROR_COUNT_EVENT + */ +#define SCU_EVENT_RX_CREDIT_BLOCKED_RECEIVED \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x00) +#define SCU_EVENT_TX_DONE_CREDIT_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x01) +#define SCU_EVENT_RX_DONE_CREDIT_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x02) + +/** + * scu_get_event_type() - + * + * This macro returns the SCU event type from the event code. + */ +#define scu_get_event_type(event_code) \ + ((event_code) & SCU_EVENT_TYPE_CODE_MASK) + +/** + * scu_get_event_specifier() - + * + * This macro returns the SCU event specifier from the event code. + */ +#define scu_get_event_specifier(event_code) \ + ((event_code) & SCU_EVENT_SPECIFIC_CODE_MASK) + +/** + * scu_get_event_code() - + * + * This macro returns the combined SCU event type and SCU event specifier from + * the event code. + */ +#define scu_get_event_code(event_code) \ + ((event_code) & SCU_EVENT_CODE_MASK) + + +/** + * + * + * PTS_SCHEDULE_EVENT + */ +#define SCU_EVENT_SMP_RESPONSE_NO_PE \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x00) +#define SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE \ + scu_get_event_specifier(SCU_EVENT_SMP_RESPONSE_NO_PE) + +#define SCU_EVENT_TASK_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x01) +#define SCU_EVENT_SPECIFIC_TASK_TIMEOUT \ + scu_get_event_specifier(SCU_EVENT_TASK_TIMEOUT) + +#define SCU_EVENT_IT_NEXUS_TIMEOUT \ + SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x02) +#define SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT \ + scu_get_event_specifier(SCU_EVENT_IT_NEXUS_TIMEOUT) + + +#endif /* __SCU_EVENT_CODES_HEADER__ */ diff --git a/drivers/scsi/isci/scu_task_context.h b/drivers/scsi/isci/scu_task_context.h new file mode 100644 index 000000000000..7df87d923285 --- /dev/null +++ b/drivers/scsi/isci/scu_task_context.h @@ -0,0 +1,942 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCU_TASK_CONTEXT_H_ +#define _SCU_TASK_CONTEXT_H_ + +/** + * This file contains the structures and constants for the SCU hardware task + * context. + * + * + */ + + +/** + * enum scu_ssp_task_type - This enumberation defines the various SSP task + * types the SCU hardware will accept. The definition for the various task + * types the SCU hardware will accept can be found in the DS specification. + * + * + */ +typedef enum { + SCU_TASK_TYPE_IOREAD, /* /< IO READ direction or no direction */ + SCU_TASK_TYPE_IOWRITE, /* /< IO Write direction */ + SCU_TASK_TYPE_SMP_REQUEST, /* /< SMP Request type */ + SCU_TASK_TYPE_RESPONSE, /* /< Driver generated response frame (targt mode) */ + SCU_TASK_TYPE_RAW_FRAME, /* /< Raw frame request type */ + SCU_TASK_TYPE_PRIMITIVE /* /< Request for a primitive to be transmitted */ +} scu_ssp_task_type; + +/** + * enum scu_sata_task_type - This enumeration defines the various SATA task + * types the SCU hardware will accept. The definition for the various task + * types the SCU hardware will accept can be found in the DS specification. + * + * + */ +typedef enum { + SCU_TASK_TYPE_DMA_IN, /* /< Read request */ + SCU_TASK_TYPE_FPDMAQ_READ, /* /< NCQ read request */ + SCU_TASK_TYPE_PACKET_DMA_IN, /* /< Packet read request */ + SCU_TASK_TYPE_SATA_RAW_FRAME, /* /< Raw frame request */ + RESERVED_4, + RESERVED_5, + RESERVED_6, + RESERVED_7, + SCU_TASK_TYPE_DMA_OUT, /* /< Write request */ + SCU_TASK_TYPE_FPDMAQ_WRITE, /* /< NCQ write Request */ + SCU_TASK_TYPE_PACKET_DMA_OUT /* /< Packet write request */ +} scu_sata_task_type; + + +/** + * + * + * SCU_CONTEXT_TYPE + */ +#define SCU_TASK_CONTEXT_TYPE 0 +#define SCU_RNC_CONTEXT_TYPE 1 + +/** + * + * + * SCU_TASK_CONTEXT_VALIDITY + */ +#define SCU_TASK_CONTEXT_INVALID 0 +#define SCU_TASK_CONTEXT_VALID 1 + +/** + * + * + * SCU_COMMAND_CODE + */ +#define SCU_COMMAND_CODE_INITIATOR_NEW_TASK 0 +#define SCU_COMMAND_CODE_ACTIVE_TASK 1 +#define SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK 2 +#define SCU_COMMAND_CODE_TARGET_RAW_FRAMES 3 + +/** + * + * + * SCU_TASK_PRIORITY + */ +/** + * + * + * This priority is used when there is no priority request for this request. + */ +#define SCU_TASK_PRIORITY_NORMAL 0 + +/** + * + * + * This priority indicates that the task should be scheduled to the head of the + * queue. The task will NOT be executed if the TX is suspended for the remote + * node. + */ +#define SCU_TASK_PRIORITY_HEAD_OF_Q 1 + +/** + * + * + * This priority indicates that the task will be executed before all + * SCU_TASK_PRIORITY_NORMAL and SCU_TASK_PRIORITY_HEAD_OF_Q tasks. The task + * WILL be executed if the TX is suspended for the remote node. + */ +#define SCU_TASK_PRIORITY_HIGH 2 + +/** + * + * + * This task priority is reserved and should not be used. + */ +#define SCU_TASK_PRIORITY_RESERVED 3 + +#define SCU_TASK_INITIATOR_MODE 1 +#define SCU_TASK_TARGET_MODE 0 + +#define SCU_TASK_REGULAR 0 +#define SCU_TASK_ABORTED 1 + +/* direction bit defintion */ +/** + * + * + * SATA_DIRECTION + */ +#define SCU_SATA_WRITE_DATA_DIRECTION 0 +#define SCU_SATA_READ_DATA_DIRECTION 1 + +/** + * + * + * SCU_COMMAND_CONTEXT_MACROS These macros provide the mask and shift + * operations to construct the various SCU commands + */ +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT 21 +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK 0x00E00000 +#define scu_get_command_request_type(x) \ + ((x) & SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK) + +#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT 18 +#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK 0x001C0000 +#define scu_get_command_request_subtype(x) \ + ((x) & SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK) + +#define SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK \ + (\ + SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK \ + | SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK \ + ) +#define scu_get_command_request_full_type(x) \ + ((x) & SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK) + +#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 16 +#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK 0x00010000 +#define scu_get_command_protocl_engine_group(x) \ + ((x) & SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK) + +#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 12 +#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK 0x00007000 +#define scu_get_command_reqeust_logical_port(x) \ + ((x) & SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK) + + +#define MAKE_SCU_CONTEXT_COMMAND_TYPE(type) \ + ((u32)(type) << SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT) + +/** + * MAKE_SCU_CONTEXT_COMMAND_TYPE() - + * + * SCU_COMMAND_TYPES These constants provide the grouping of the different SCU + * command types. + */ +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(0) +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(1) +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(2) +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(3) +#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(6) + +#define MAKE_SCU_CONTEXT_COMMAND_REQUEST(type, command) \ + ((type) | ((command) << SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT)) + +/** + * + * + * SCU_REQUEST_TYPES These constants are the various request types that can be + * posted to the SCU hardware. + */ +#define SCU_CONTEXT_COMMAND_REQUST_POST_TC \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 0)) + +#define SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 1)) + +#define SCU_CONTEXT_COMMAND_REQUST_DUMP_TC \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC, 0)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_32 \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 0)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_96 \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 1)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 2)) + +#define SCU_CONTEXT_COMMAND_DUMP_RNC_32 \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 0)) + +#define SCU_CONTEXT_COMMAND_DUMP_RNC_96 \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 1)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 0)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 1)) + +#define SCU_CONTEXT_COMMAND_POST_RNC_RESUME \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 2)) + +#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_ENABLE \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 3)) + +#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_DISABLE \ + (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 4)) + +/** + * + * + * SCU_TASK_CONTEXT_PROTOCOL SCU Task context protocol types this is uesd to + * program the SCU Task context protocol field in word 0x00. + */ +#define SCU_TASK_CONTEXT_PROTOCOL_SMP 0x00 +#define SCU_TASK_CONTEXT_PROTOCOL_SSP 0x01 +#define SCU_TASK_CONTEXT_PROTOCOL_STP 0x02 +#define SCU_TASK_CONTEXT_PROTOCOL_NONE 0x07 + +/** + * struct ssp_task_context - This is the SCU hardware definition for an SSP + * request. + * + * + */ +struct ssp_task_context { + /* OFFSET 0x18 */ + u32 reserved00:24; + u32 frame_type:8; + + /* OFFSET 0x1C */ + u32 reserved01; + + /* OFFSET 0x20 */ + u32 fill_bytes:2; + u32 reserved02:6; + u32 changing_data_pointer:1; + u32 retransmit:1; + u32 retry_data_frame:1; + u32 tlr_control:2; + u32 reserved03:19; + + /* OFFSET 0x24 */ + u32 uiRsvd4; + + /* OFFSET 0x28 */ + u32 target_port_transfer_tag:16; + u32 tag:16; + + /* OFFSET 0x2C */ + u32 data_offset; +}; + +/** + * struct stp_task_context - This is the SCU hardware definition for an STP + * request. + * + * + */ +struct stp_task_context { + /* OFFSET 0x18 */ + u32 fis_type:8; + u32 pm_port:4; + u32 reserved0:3; + u32 control:1; + u32 command:8; + u32 features:8; + + /* OFFSET 0x1C */ + u32 reserved1; + + /* OFFSET 0x20 */ + u32 reserved2; + + /* OFFSET 0x24 */ + u32 reserved3; + + /* OFFSET 0x28 */ + u32 ncq_tag:5; + u32 reserved4:27; + + /* OFFSET 0x2C */ + u32 data_offset; /* TODO: What is this used for? */ +}; + +/** + * struct smp_task_context - This is the SCU hardware definition for an SMP + * request. + * + * + */ +struct smp_task_context { + /* OFFSET 0x18 */ + u32 response_length:8; + u32 function_result:8; + u32 function:8; + u32 frame_type:8; + + /* OFFSET 0x1C */ + u32 smp_response_ufi:12; + u32 reserved1:20; + + /* OFFSET 0x20 */ + u32 reserved2; + + /* OFFSET 0x24 */ + u32 reserved3; + + /* OFFSET 0x28 */ + u32 reserved4; + + /* OFFSET 0x2C */ + u32 reserved5; +}; + +/** + * struct primitive_task_context - This is the SCU hardware definition used + * when the driver wants to send a primitive on the link. + * + * + */ +struct primitive_task_context { + /* OFFSET 0x18 */ + /** + * This field is the control word and it must be 0. + */ + u32 control; /* /< must be set to 0 */ + + /* OFFSET 0x1C */ + /** + * This field specifies the primitive that is to be transmitted. + */ + u32 sequence; + + /* OFFSET 0x20 */ + u32 reserved0; + + /* OFFSET 0x24 */ + u32 reserved1; + + /* OFFSET 0x28 */ + u32 reserved2; + + /* OFFSET 0x2C */ + u32 reserved3; +}; + +/** + * The union of the protocols that can be selected in the SCU task context + * field. + * + * protocol_context + */ +union protocol_context { + struct ssp_task_context ssp; + struct stp_task_context stp; + struct smp_task_context smp; + struct primitive_task_context primitive; + u32 words[6]; +}; + +/** + * struct scu_sgl_element - This structure represents a single SCU defined SGL + * element. SCU SGLs contain a 64 bit address with the maximum data transfer + * being 24 bits in size. The SGL can not cross a 4GB boundary. + * + * struct scu_sgl_element + */ +struct scu_sgl_element { + /** + * This field is the upper 32 bits of the 64 bit physical address. + */ + u32 address_upper; + + /** + * This field is the lower 32 bits of the 64 bit physical address. + */ + u32 address_lower; + + /** + * This field is the number of bytes to transfer. + */ + u32 length:24; + + /** + * This field is the address modifier to be used when a virtual function is + * requesting a data transfer. + */ + u32 address_modifier:8; + +}; + +#define SCU_SGL_ELEMENT_PAIR_A 0 +#define SCU_SGL_ELEMENT_PAIR_B 1 + +/** + * struct scu_sgl_element_pair - This structure is the SCU hardware definition + * of a pair of SGL elements. The SCU hardware always works on SGL pairs. + * They are refered to in the DS specification as SGL A and SGL B. Each SGL + * pair is followed by the address of the next pair. + * + * + */ +struct scu_sgl_element_pair { + /* OFFSET 0x60-0x68 */ + /** + * This field is the SGL element A of the SGL pair. + */ + struct scu_sgl_element A; + + /* OFFSET 0x6C-0x74 */ + /** + * This field is the SGL element B of the SGL pair. + */ + struct scu_sgl_element B; + + /* OFFSET 0x78-0x7C */ + /** + * This field is the upper 32 bits of the 64 bit address to the next SGL + * element pair. + */ + u32 next_pair_upper; + + /** + * This field is the lower 32 bits of the 64 bit address to the next SGL + * element pair. + */ + u32 next_pair_lower; + +}; + +/** + * struct transport_snapshot - This structure is the SCU hardware scratch area + * for the task context. This is set to 0 by the driver but can be read by + * issuing a dump TC request to the SCU. + * + * + */ +struct transport_snapshot { + /* OFFSET 0x48 */ + u32 xfer_rdy_write_data_length; + + /* OFFSET 0x4C */ + u32 data_offset; + + /* OFFSET 0x50 */ + u32 data_transfer_size:24; + u32 reserved_50_0:8; + + /* OFFSET 0x54 */ + u32 next_initiator_write_data_offset; + + /* OFFSET 0x58 */ + u32 next_initiator_write_data_xfer_size:24; + u32 reserved_58_0:8; +}; + +/** + * struct scu_task_context - This structure defines the contents of the SCU + * silicon task context. It lays out all of the fields according to the + * expected order and location for the Storage Controller unit. + * + * + */ +struct scu_task_context { + /* OFFSET 0x00 ------ */ + /** + * This field must be encoded to one of the valid SCU task priority values + * - SCU_TASK_PRIORITY_NORMAL + * - SCU_TASK_PRIORITY_HEAD_OF_Q + * - SCU_TASK_PRIORITY_HIGH + */ + u32 priority:2; + + /** + * This field must be set to true if this is an initiator generated request. + * Until target mode is supported all task requests are initiator requests. + */ + u32 initiator_request:1; + + /** + * This field must be set to one of the valid connection rates valid values + * are 0x8, 0x9, and 0xA. + */ + u32 connection_rate:4; + + /** + * This field muse be programed when generating an SMP response since the SMP + * connection remains open until the SMP response is generated. + */ + u32 protocol_engine_index:3; + + /** + * This field must contain the logical port for the task request. + */ + u32 logical_port_index:3; + + /** + * This field must be set to one of the SCU_TASK_CONTEXT_PROTOCOL values + * - SCU_TASK_CONTEXT_PROTOCOL_SMP + * - SCU_TASK_CONTEXT_PROTOCOL_SSP + * - SCU_TASK_CONTEXT_PROTOCOL_STP + * - SCU_TASK_CONTEXT_PROTOCOL_NONE + */ + u32 protocol_type:3; + + /** + * This filed must be set to the TCi allocated for this task + */ + u32 task_index:12; + + /** + * This field is reserved and must be set to 0x00 + */ + u32 reserved_00_0:1; + + /** + * For a normal task request this must be set to 0. If this is an abort of + * this task request it must be set to 1. + */ + u32 abort:1; + + /** + * This field must be set to true for the SCU hardware to process the task. + */ + u32 valid:1; + + /** + * This field must be set to SCU_TASK_CONTEXT_TYPE + */ + u32 context_type:1; + + /* OFFSET 0x04 */ + /** + * This field contains the RNi that is the target of this request. + */ + u32 remote_node_index:12; + + /** + * This field is programmed if this is a mirrored request, which we are not + * using, in which case it is the RNi for the mirrored target. + */ + u32 mirrored_node_index:12; + + /** + * This field is programmed with the direction of the SATA reqeust + * - SCU_SATA_WRITE_DATA_DIRECTION + * - SCU_SATA_READ_DATA_DIRECTION + */ + u32 sata_direction:1; + + /** + * This field is programmsed with one of the following SCU_COMMAND_CODE + * - SCU_COMMAND_CODE_INITIATOR_NEW_TASK + * - SCU_COMMAND_CODE_ACTIVE_TASK + * - SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK + * - SCU_COMMAND_CODE_TARGET_RAW_FRAMES + */ + u32 command_code:2; + + /** + * This field is set to true if the remote node should be suspended. + * This bit is only valid for SSP & SMP target devices. + */ + u32 suspend_node:1; + + /** + * This field is programmed with one of the following command type codes + * + * For SAS requests use the scu_ssp_task_type + * - SCU_TASK_TYPE_IOREAD + * - SCU_TASK_TYPE_IOWRITE + * - SCU_TASK_TYPE_SMP_REQUEST + * - SCU_TASK_TYPE_RESPONSE + * - SCU_TASK_TYPE_RAW_FRAME + * - SCU_TASK_TYPE_PRIMITIVE + * + * For SATA requests use the scu_sata_task_type + * - SCU_TASK_TYPE_DMA_IN + * - SCU_TASK_TYPE_FPDMAQ_READ + * - SCU_TASK_TYPE_PACKET_DMA_IN + * - SCU_TASK_TYPE_SATA_RAW_FRAME + * - SCU_TASK_TYPE_DMA_OUT + * - SCU_TASK_TYPE_FPDMAQ_WRITE + * - SCU_TASK_TYPE_PACKET_DMA_OUT + */ + u32 task_type:4; + + /* OFFSET 0x08 */ + /** + * This field is reserved and the must be set to 0x00 + */ + u32 link_layer_control:8; /* presently all reserved */ + + /** + * This field is set to true when TLR is to be enabled + */ + u32 ssp_tlr_enable:1; + + /** + * This is field specifies if the SCU DMAs a response frame to host + * memory for good response frames when operating in target mode. + */ + u32 dma_ssp_target_good_response:1; + + /** + * This field indicates if the SCU should DMA the response frame to + * host memory. + */ + u32 do_not_dma_ssp_good_response:1; + + /** + * This field is set to true when strict ordering is to be enabled + */ + u32 strict_ordering:1; + + /** + * This field indicates the type of endianess to be utilized for the + * frame. command, task, and response frames utilized control_frame + * set to 1. + */ + u32 control_frame:1; + + /** + * This field is reserved and the driver should set to 0x00 + */ + u32 tl_control_reserved:3; + + /** + * This field is set to true when the SCU hardware task timeout control is to + * be enabled + */ + u32 timeout_enable:1; + + /** + * This field is reserved and the driver should set it to 0x00 + */ + u32 pts_control_reserved:7; + + /** + * This field should be set to true when block guard is to be enabled + */ + u32 block_guard_enable:1; + + /** + * This field is reserved and the driver should set to 0x00 + */ + u32 sdma_control_reserved:7; + + /* OFFSET 0x0C */ + /** + * This field is the address modifier for this io request it should be + * programmed with the virtual function that is making the request. + */ + u32 address_modifier:16; + + /** + * @todo What we support mirrored SMP response frame? + */ + u32 mirrored_protocol_engine:3; /* mirrored protocol Engine Index */ + + /** + * If this is a mirrored request the logical port index for the mirrored RNi + * must be programmed. + */ + u32 mirrored_logical_port:4; /* mirrored local port index */ + + /** + * This field is reserved and the driver must set it to 0x00 + */ + u32 reserved_0C_0:8; + + /** + * This field must be set to true if the mirrored request processing is to be + * enabled. + */ + u32 mirror_request_enable:1; /* Mirrored request Enable */ + + /* OFFSET 0x10 */ + /** + * This field is the command iu length in dwords + */ + u32 ssp_command_iu_length:8; + + /** + * This is the target TLR enable bit it must be set to 0 when creatning the + * task context. + */ + u32 xfer_ready_tlr_enable:1; + + /** + * This field is reserved and the driver must set it to 0x00 + */ + u32 reserved_10_0:7; + + /** + * This is the maximum burst size that the SCU hardware will send in one + * connection its value is (N x 512) and N must be a multiple of 2. If the + * value is 0x00 then maximum burst size is disabled. + */ + u32 ssp_max_burst_size:16; + + /* OFFSET 0x14 */ + /** + * This filed is set to the number of bytes to be transfered in the request. + */ + u32 transfer_length_bytes:24; /* In terms of bytes */ + + /** + * This field is reserved and the driver should set it to 0x00 + */ + u32 reserved_14_0:8; + + /* OFFSET 0x18-0x2C */ + /** + * This union provides for the protocol specif part of the SCU Task Context. + */ + union protocol_context type; + + /* OFFSET 0x30-0x34 */ + /** + * This field is the upper 32 bits of the 64 bit physical address of the + * command iu buffer + */ + u32 command_iu_upper; + + /** + * This field is the lower 32 bits of the 64 bit physical address of the + * command iu buffer + */ + u32 command_iu_lower; + + /* OFFSET 0x38-0x3C */ + /** + * This field is the upper 32 bits of the 64 bit physical address of the + * response iu buffer + */ + u32 response_iu_upper; + + /** + * This field is the lower 32 bits of the 64 bit physical address of the + * response iu buffer + */ + u32 response_iu_lower; + + /* OFFSET 0x40 */ + /** + * This field is set to the task phase of the SCU hardware. The driver must + * set this to 0x01 + */ + u32 task_phase:8; + + /** + * This field is set to the transport layer task status. The driver must set + * this to 0x00 + */ + u32 task_status:8; + + /** + * This field is used during initiator write TLR + */ + u32 previous_extended_tag:4; + + /** + * This field is set the maximum number of retries for a STP non-data FIS + */ + u32 stp_retry_count:2; + + /** + * This field is reserved and the driver must set it to 0x00 + */ + u32 reserved_40_1:2; + + /** + * This field is used by the SCU TL to determine when to take a snapshot when + * tranmitting read data frames. + * - 0x00 The entire IO + * - 0x01 32k + * - 0x02 64k + * - 0x04 128k + * - 0x08 256k + */ + u32 ssp_tlr_threshold:4; + + /** + * This field is reserved and the driver must set it to 0x00 + */ + u32 reserved_40_2:4; + + /* OFFSET 0x44 */ + u32 write_data_length; /* read only set to 0 */ + + /* OFFSET 0x48-0x58 */ + struct transport_snapshot snapshot; /* read only set to 0 */ + + /* OFFSET 0x5C */ + u32 block_protection_enable:1; + u32 block_size:2; + u32 block_protection_function:2; + u32 reserved_5C_0:9; + u32 active_sgl_element:2; /* read only set to 0 */ + u32 sgl_exhausted:1; /* read only set to 0 */ + u32 payload_data_transfer_error:4; /* read only set to 0 */ + u32 frame_buffer_offset:11; /* read only set to 0 */ + + /* OFFSET 0x60-0x7C */ + /** + * This field is the first SGL element pair found in the TC data structure. + */ + struct scu_sgl_element_pair sgl_pair_ab; + /* OFFSET 0x80-0x9C */ + /** + * This field is the second SGL element pair found in the TC data structure. + */ + struct scu_sgl_element_pair sgl_pair_cd; + + /* OFFSET 0xA0-BC */ + struct scu_sgl_element_pair sgl_snapshot_ac; + + /* OFFSET 0xC0 */ + u32 active_sgl_element_pair; /* read only set to 0 */ + + /* OFFSET 0xC4-0xCC */ + u32 reserved_C4_CC[3]; + + /* OFFSET 0xD0 */ + u32 intermediate_crc_value:16; + u32 initial_crc_seed:16; + + /* OFFSET 0xD4 */ + u32 application_tag_for_verify:16; + u32 application_tag_for_generate:16; + + /* OFFSET 0xD8 */ + u32 reference_tag_seed_for_verify_function; + + /* OFFSET 0xDC */ + u32 reserved_DC; + + /* OFFSET 0xE0 */ + u32 reserved_E0_0:16; + u32 application_tag_mask_for_generate:16; + + /* OFFSET 0xE4 */ + u32 block_protection_control:16; + u32 application_tag_mask_for_verify:16; + + /* OFFSET 0xE8 */ + u32 block_protection_error:8; + u32 reserved_E8_0:24; + + /* OFFSET 0xEC */ + u32 reference_tag_seed_for_verify; + + /* OFFSET 0xF0 */ + u32 intermediate_crc_valid_snapshot:16; + u32 reserved_F0_0:16; + + /* OFFSET 0xF4 */ + u32 reference_tag_seed_for_verify_function_snapshot; + + /* OFFSET 0xF8 */ + u32 snapshot_of_reserved_dword_DC_of_tc; + + /* OFFSET 0xFC */ + u32 reference_tag_seed_for_generate_function_snapshot; + +}; + +#endif /* _SCU_TASK_CONTEXT_H_ */ diff --git a/drivers/scsi/isci/scu_unsolicited_frame.h b/drivers/scsi/isci/scu_unsolicited_frame.h new file mode 100644 index 000000000000..187c4f03f596 --- /dev/null +++ b/drivers/scsi/isci/scu_unsolicited_frame.h @@ -0,0 +1,117 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This field defines the SCU format of an unsolicited frame (UF). A UF is a + * frame received by the SCU for which there is no known corresponding task + * context (TC). + * + * + */ + +#ifndef _SCU_UNSOLICITED_FRAME_H_ +#define _SCU_UNSOLICITED_FRAME_H_ + +#include + +/** + * + * + * This constant defines the number of DWORDS found the unsolicited frame + * header data member. + */ +#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15 + +/** + * struct scu_unsolicited_frame_header - + * + * This structure delineates the format of an unsolicited frame header. The + * first DWORD are UF attributes defined by the silicon architecture. The data + * depicts actual header information received on the link. + */ +struct scu_unsolicited_frame_header { + /** + * This field indicates if there is an Initiator Index Table entry with + * which this header is associated. + */ + u32 iit_exists:1; + + /** + * This field simply indicates the protocol type (i.e. SSP, STP, SMP). + */ + u32 protocol_type:3; + + /** + * This field indicates if the frame is an address frame (IAF or OAF) + * or if it is a information unit frame. + */ + u32 is_address_frame:1; + + /** + * This field simply indicates the connection rate at which the frame + * was received. + */ + u32 connection_rate:4; + + u32 reserved:23; + + /** + * This field represents the actual header data received on the link. + */ + u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS]; + +}; + +#endif /* _SCU_UNSOLICITED_FRAME_H_ */ diff --git a/drivers/scsi/isci/unsolicited_frame_control.c b/drivers/scsi/isci/unsolicited_frame_control.c new file mode 100644 index 000000000000..8d68dcc52bc1 --- /dev/null +++ b/drivers/scsi/isci/unsolicited_frame_control.c @@ -0,0 +1,357 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "host.h" +#include "unsolicited_frame_control.h" +#include "registers.h" +#include "sci_util.h" + +/** + * This method will program the unsolicited frames (UFs) into the UF address + * table and construct the UF frame structure being modeled in the core. It + * will handle the case where some of the UFs are not being used and thus + * should have entries programmed to zero in the address table. + * @uf_control: This parameter specifies the unsolicted frame control object + * for which to construct the unsolicited frames objects. + * @uf_buffer_phys_address: This parameter specifies the physical address for + * the first unsolicited frame buffer. + * @uf_buffer_virt_address: This parameter specifies the virtual address for + * the first unsolicited frame buffer. + * @unused_uf_header_entries: This parameter specifies the number of unused UF + * headers. This value can be non-zero when there are a non-power of 2 + * number of unsolicited frames being supported. + * @used_uf_header_entries: This parameter specifies the number of actually + * utilized UF headers. + * + */ +static void scic_sds_unsolicited_frame_control_construct_frames( + struct scic_sds_unsolicited_frame_control *uf_control, + dma_addr_t uf_buffer_phys_address, + void *uf_buffer_virt_address, + u32 unused_uf_header_entries, + u32 used_uf_header_entries) +{ + u32 index; + struct scic_sds_unsolicited_frame *uf; + + /* + * Program the unused buffers into the UF address table and the + * controller's array of UFs. + */ + for (index = 0; index < unused_uf_header_entries; index++) { + uf = &uf_control->buffers.array[index]; + + sci_cb_make_physical_address( + uf_control->address_table.array[index], 0, 0 + ); + uf->buffer = NULL; + uf->header = &uf_control->headers.array[index]; + uf->state = UNSOLICITED_FRAME_EMPTY; + } + + /* + * Program the actual used UF buffers into the UF address table and + * the controller's array of UFs. + */ + for (index = unused_uf_header_entries; + index < unused_uf_header_entries + used_uf_header_entries; + index++) { + uf = &uf_control->buffers.array[index]; + + uf_control->address_table.array[index] = uf_buffer_phys_address; + + uf->buffer = uf_buffer_virt_address; + uf->header = &uf_control->headers.array[index]; + uf->state = UNSOLICITED_FRAME_EMPTY; + + /* + * Increment the address of the physical and virtual memory + * pointers. Everything is aligned on 1k boundary with an + * increment of 1k. + */ + uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; + uf_buffer_phys_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; + } +} + +int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic) +{ + struct scic_sds_unsolicited_frame_control *uf_control = &scic->uf_control; + u32 unused_uf_header_entries; + u32 used_uf_header_entries; + u32 used_uf_buffer_bytes; + u32 unused_uf_header_bytes; + u32 used_uf_header_bytes; + dma_addr_t uf_buffer_phys_address; + void *uf_buffer_virt_address; + size_t size; + + /* + * The UF buffer address table size must be programmed to a power + * of 2. Find the first power of 2 that is equal to or greater then + * the number of unsolicited frame buffers to be utilized. + */ + uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES; + while (uf_control->address_table.count < uf_control->buffers.count && + uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES) + uf_control->address_table.count <<= 1; + + /* + * Prepare all of the memory sizes for the UF headers, UF address + * table, and UF buffers themselves. + */ + used_uf_buffer_bytes = uf_control->buffers.count + * SCU_UNSOLICITED_FRAME_BUFFER_SIZE; + unused_uf_header_entries = uf_control->address_table.count + - uf_control->buffers.count; + used_uf_header_entries = uf_control->buffers.count; + unused_uf_header_bytes = unused_uf_header_entries + * sizeof(struct scu_unsolicited_frame_header); + used_uf_header_bytes = used_uf_header_entries + * sizeof(struct scu_unsolicited_frame_header); + + size = used_uf_buffer_bytes + used_uf_header_bytes + + uf_control->address_table.count * sizeof(dma_addr_t); + + + /* + * The Unsolicited Frame buffers are set at the start of the UF + * memory descriptor entry. The headers and address table will be + * placed after the buffers. + */ + uf_buffer_virt_address = dmam_alloc_coherent(scic_to_dev(scic), size, + &uf_buffer_phys_address, GFP_KERNEL); + if (!uf_buffer_virt_address) + return -ENOMEM; + + /* + * Program the location of the UF header table into the SCU. + * Notes: + * - The address must align on a 64-byte boundary. Guaranteed to be + * on 64-byte boundary already 1KB boundary for unsolicited frames. + * - Program unused header entries to overlap with the last + * unsolicited frame. The silicon will never DMA to these unused + * headers, since we program the UF address table pointers to + * NULL. + */ + uf_control->headers.physical_address = + uf_buffer_phys_address + + used_uf_buffer_bytes - + unused_uf_header_bytes; + + uf_control->headers.array = + uf_buffer_virt_address + + used_uf_buffer_bytes - + unused_uf_header_bytes; + + /* + * Program the location of the UF address table into the SCU. + * Notes: + * - The address must align on a 64-bit boundary. Guaranteed to be on 64 + * byte boundary already due to above programming headers being on a + * 64-bit boundary and headers are on a 64-bytes in size. + */ + uf_control->address_table.physical_address = + uf_buffer_phys_address + + used_uf_buffer_bytes + + used_uf_header_bytes; + + uf_control->address_table.array = + uf_buffer_virt_address + + used_uf_buffer_bytes + + used_uf_header_bytes; + + uf_control->get = 0; + + /* + * UF buffer requirements are: + * - The last entry in the UF queue is not NULL. + * - There is a power of 2 number of entries (NULL or not-NULL) + * programmed into the queue. + * - Aligned on a 1KB boundary. */ + + /* + * If the user provided less then the maximum amount of memory, + * then be sure that we programm the first entries in the UF + * address table to NULL. */ + scic_sds_unsolicited_frame_control_construct_frames( + uf_control, + uf_buffer_phys_address, + uf_buffer_virt_address, + unused_uf_header_entries, + used_uf_header_entries + ); + + return 0; +} + +/** + * This method returns the frame header for the specified frame index. + * @uf_control: + * @frame_index: + * @frame_header: + * + * enum sci_status + */ +enum sci_status scic_sds_unsolicited_frame_control_get_header( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_header) +{ + if (frame_index < uf_control->address_table.count) { + /* + * Skip the first word in the frame since this is a controll word used + * by the hardware. */ + *frame_header = &uf_control->buffers.array[frame_index].header->data; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_PARAMETER_VALUE; +} + +/** + * This method returns the frame buffer for the specified frame index. + * @uf_control: + * @frame_index: + * @frame_buffer: + * + * enum sci_status + */ +enum sci_status scic_sds_unsolicited_frame_control_get_buffer( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_buffer) +{ + if (frame_index < uf_control->address_table.count) { + *frame_buffer = uf_control->buffers.array[frame_index].buffer; + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INVALID_PARAMETER_VALUE; +} + +/** + * This method releases the frame once this is done the frame is available for + * re-use by the hardware. The data contained in the frame header and frame + * buffer is no longer valid. + * @uf_control: This parameter specifies the UF control object + * @frame_index: This parameter specifies the frame index to attempt to release. + * + * This method returns an indication to the caller as to whether the + * unsolicited frame get pointer should be updated. + */ +bool scic_sds_unsolicited_frame_control_release_frame( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index) +{ + u32 frame_get; + u32 frame_cycle; + + frame_get = uf_control->get & (uf_control->address_table.count - 1); + frame_cycle = uf_control->get & uf_control->address_table.count; + + /* + * In the event there are NULL entries in the UF table, we need to + * advance the get pointer in order to find out if this frame should + * be released (i.e. update the get pointer). */ + while (((lower_32_bits(uf_control->address_table.array[frame_get]) + == 0) && + (upper_32_bits(uf_control->address_table.array[frame_get]) + == 0)) && + (frame_get < uf_control->address_table.count)) + frame_get++; + + /* + * The table has a NULL entry as it's last element. This is + * illegal. */ + BUG_ON(frame_get >= uf_control->address_table.count); + + if (frame_index < uf_control->address_table.count) { + uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED; + + /* + * The frame index is equal to the current get pointer so we + * can now free up all of the frame entries that */ + if (frame_get == frame_index) { + while ( + uf_control->buffers.array[frame_get].state + == UNSOLICITED_FRAME_RELEASED + ) { + uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY; + + INCREMENT_QUEUE_GET( + frame_get, + frame_cycle, + uf_control->address_table.count - 1, + uf_control->address_table.count + ); + } + + uf_control->get = + (SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get); + + return true; + } else { + /* + * Frames remain in use until we advance the get pointer + * so there is nothing we can do here */ + } + } + + return false; +} + diff --git a/drivers/scsi/isci/unsolicited_frame_control.h b/drivers/scsi/isci/unsolicited_frame_control.h new file mode 100644 index 000000000000..0d8ca8c4770f --- /dev/null +++ b/drivers/scsi/isci/unsolicited_frame_control.h @@ -0,0 +1,251 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ +#define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ + +#include "isci.h" +#include "scu_unsolicited_frame.h" + +/** + * enum unsolicited_frame_state - + * + * This enumeration represents the current unsolicited frame state. The + * controller object can not updtate the hardware unsolicited frame put pointer + * unless it has already processed the priror unsolicited frames. + */ +enum unsolicited_frame_state { + /** + * This state is when the frame is empty and not in use. It is + * different from the released state in that the hardware could DMA + * data to this frame buffer. + */ + UNSOLICITED_FRAME_EMPTY, + + /** + * This state is set when the frame buffer is in use by by some + * object in the system. + */ + UNSOLICITED_FRAME_IN_USE, + + /** + * This state is set when the frame is returned to the free pool + * but one or more frames prior to this one are still in use. + * Once all of the frame before this one are freed it will go to + * the empty state. + */ + UNSOLICITED_FRAME_RELEASED, + + UNSOLICITED_FRAME_MAX_STATES +}; + +/** + * struct scic_sds_unsolicited_frame - + * + * This is the unsolicited frame data structure it acts as the container for + * the current frame state, frame header and frame buffer. + */ +struct scic_sds_unsolicited_frame { + /** + * This field contains the current frame state + */ + enum unsolicited_frame_state state; + + /** + * This field points to the frame header data. + */ + struct scu_unsolicited_frame_header *header; + + /** + * This field points to the frame buffer data. + */ + void *buffer; + +}; + +/** + * struct scic_sds_uf_header_array - + * + * This structure contains all of the unsolicited frame header information. + */ +struct scic_sds_uf_header_array { + /** + * This field is represents a virtual pointer to the start + * address of the UF address table. The table contains + * 64-bit pointers as required by the hardware. + */ + struct scu_unsolicited_frame_header *array; + + /** + * This field specifies the physical address location for the UF + * buffer array. + */ + dma_addr_t physical_address; + +}; + +/** + * struct scic_sds_uf_buffer_array - + * + * This structure contains all of the unsolicited frame buffer (actual payload) + * information. + */ +struct scic_sds_uf_buffer_array { + /** + * This field is the minimum number of unsolicited frames supported by the + * hardware and the number of unsolicited frames requested by the software. + */ + u32 count; + + /** + * This field is the SCIC_UNSOLICITED_FRAME data its used to manage + * the data for the unsolicited frame requests. It also represents + * the virtual address location that corresponds to the + * physical_address field. + */ + struct scic_sds_unsolicited_frame array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE]; + + /** + * This field specifies the physical address location for the UF + * buffer array. + */ + dma_addr_t physical_address; + +}; + +/** + * struct scic_sds_uf_address_table_array - + * + * This object maintains all of the unsolicited frame address table specific + * data. The address table is a collection of 64-bit pointers that point to + * 1KB buffers into which the silicon will DMA unsolicited frames. + */ +struct scic_sds_uf_address_table_array { + /** + * This field specifies the actual programmed size of the + * unsolicited frame buffer address table. The size of the table + * can be larger than the actual number of UF buffers, but it must + * be a power of 2 and the last entry in the table is not allowed + * to be NULL. + */ + u32 count; + + /** + * This field represents a virtual pointer that refers to the + * starting address of the UF address table. + * 64-bit pointers are required by the hardware. + */ + dma_addr_t *array; + + /** + * This field specifies the physical address location for the UF + * address table. + */ + dma_addr_t physical_address; + +}; + +/** + * struct scic_sds_unsolicited_frame_control - + * + * This object contains all of the data necessary to handle unsolicited frames. + */ +struct scic_sds_unsolicited_frame_control { + /** + * This field is the software copy of the unsolicited frame queue + * get pointer. The controller object writes this value to the + * hardware to let the hardware put more unsolicited frame entries. + */ + u32 get; + + /** + * This field contains all of the unsolicited frame header + * specific fields. + */ + struct scic_sds_uf_header_array headers; + + /** + * This field contains all of the unsolicited frame buffer + * specific fields. + */ + struct scic_sds_uf_buffer_array buffers; + + /** + * This field contains all of the unsolicited frame address table + * specific fields. + */ + struct scic_sds_uf_address_table_array address_table; + +}; + +struct scic_sds_controller; + +int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic); + +enum sci_status scic_sds_unsolicited_frame_control_get_header( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_header); + +enum sci_status scic_sds_unsolicited_frame_control_get_buffer( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_buffer); + +bool scic_sds_unsolicited_frame_control_release_frame( + struct scic_sds_unsolicited_frame_control *uf_control, + u32 frame_index); + +#endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */ -- cgit v1.2.3 From 3bff9d54ecba84e538da822349a9a6fd6e534539 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 8 May 2011 22:15:10 -0700 Subject: isci: uplevel state machine unify core/sci_base_state.h and core/sci_base_state_machine.[ch] into state_machine.[ch] Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 2 +- drivers/scsi/isci/core/sci_base_state.h | 84 ---------- drivers/scsi/isci/core/sci_base_state_machine.c | 182 ---------------------- drivers/scsi/isci/core/sci_base_state_machine.h | 141 ----------------- drivers/scsi/isci/core/scic_sds_phy.c | 3 +- drivers/scsi/isci/core/scic_sds_phy.h | 2 +- drivers/scsi/isci/core/scic_sds_port.h | 2 +- drivers/scsi/isci/core/scic_sds_request.h | 2 +- drivers/scsi/isci/core/scic_sds_smp_request.c | 2 +- drivers/scsi/isci/core/scic_sds_ssp_request.c | 2 +- drivers/scsi/isci/core/scic_sds_stp_pio_request.h | 1 - drivers/scsi/isci/core/scic_sds_stp_request.c | 3 +- drivers/scsi/isci/host.h | 2 +- drivers/scsi/isci/remote_node_context.c | 2 +- drivers/scsi/isci/remote_node_context.h | 3 +- drivers/scsi/isci/state_machine.c | 171 ++++++++++++++++++++ drivers/scsi/isci/state_machine.h | 155 ++++++++++++++++++ 17 files changed, 337 insertions(+), 422 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_base_state.h delete mode 100644 drivers/scsi/isci/core/sci_base_state_machine.c delete mode 100644 drivers/scsi/isci/core/sci_base_state_machine.h create mode 100644 drivers/scsi/isci/state_machine.c create mode 100644 drivers/scsi/isci/state_machine.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 0153b0fe13b8..cfc640f9dc3f 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ remote_device.o port.o timers.o \ host.o task.o probe_roms.o \ + state_machine.o \ remote_node_context.o \ remote_node_table.o \ unsolicited_frame_control.o \ @@ -13,5 +14,4 @@ isci-objs := init.o phy.o request.o sata.o \ core/scic_sds_phy.o \ core/scic_sds_ssp_request.o \ core/scic_sds_smp_request.o \ - core/sci_base_state_machine.o \ core/sci_util.o diff --git a/drivers/scsi/isci/core/sci_base_state.h b/drivers/scsi/isci/core/sci_base_state.h deleted file mode 100644 index d64efac1f090..000000000000 --- a/drivers/scsi/isci/core/sci_base_state.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_STATE_H_ -#define _SCI_BASE_STATE_H_ - -typedef void (*sci_base_state_handler_t)(void); - -typedef void (*sci_state_transition_t)(void *base_object); - -/** - * struct sci_base_state - The base state object abstracts the fields common to - * all state objects defined in SCI. - * - * - */ -struct sci_base_state { - /** - * This field is a function pointer that defines the method to be - * invoked when the state is entered. - */ - sci_state_transition_t enter_state; - - /** - * This field is a function pointer that defines the method to be - * invoked when the state is exited. - */ - sci_state_transition_t exit_state; - -}; - -#endif /* _SCI_BASE_STATE_H_ */ diff --git a/drivers/scsi/isci/core/sci_base_state_machine.c b/drivers/scsi/isci/core/sci_base_state_machine.c deleted file mode 100644 index a704709eed87..000000000000 --- a/drivers/scsi/isci/core/sci_base_state_machine.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains all of the functionality common to all state machine - * object implementations. - * - * - */ - -#include "sci_base_state_machine.h" - -static void sci_state_machine_exit_state(struct sci_base_state_machine *sm) -{ - u32 state = sm->current_state_id; - sci_state_transition_t exit = sm->state_table[state].exit_state; - - if (exit) - exit(sm->state_machine_owner); -} - -static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) -{ - u32 state = sm->current_state_id; - sci_state_transition_t enter = sm->state_table[state].enter_state; - - if (enter) - enter(sm->state_machine_owner); -} - -/* - * ****************************************************************************** - * * P R O T E C T E D M E T H O D S - * ****************************************************************************** */ - -/** - * This method will set the initial state and state table for the state - * machine. The caller should follow this request with the initialize - * request to cause the state machine to start. - * @sm: This parameter provides the state machine object to be - * constructed. - * @state_machine_owner: This parameter indicates the object that is owns the - * state machine being constructed. - * @state_table: This parameter specifies the table of state objects that is - * managed by this state machine. - * @initial_state: This parameter specifies the value of the initial state for - * this state machine. - * - */ -void sci_base_state_machine_construct(struct sci_base_state_machine *sm, - void *owner, - const struct sci_base_state *state_table, - u32 initial_state) -{ - sm->state_machine_owner = owner; - sm->initial_state_id = initial_state; - sm->previous_state_id = initial_state; - sm->current_state_id = initial_state; - sm->state_table = state_table; -} - -/** - * This method will cause the state machine to enter the initial state. - * @sm: This parameter specifies the state machine that is to - * be started. - * - * sci_base_state_machine_construct() for how to set the initial state none - */ -void sci_base_state_machine_start(struct sci_base_state_machine *sm) -{ - sm->current_state_id = sm->initial_state_id; -#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) - sci_base_subject_notify(&sm->parent); -#endif - sci_state_machine_enter_state(sm); -} - -/** - * This method will cause the state machine to exit it's current state only. - * @sm: This parameter specifies the state machine that is to - * be stopped. - * - */ -void sci_base_state_machine_stop( - struct sci_base_state_machine *sm) -{ - sci_state_machine_exit_state(sm); -#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) - sci_base_subject_notify(&sm->parent); -#endif -} - -/** - * This method performs an update to the current state of the state machine. - * @sm: This parameter specifies the state machine for which - * the caller wishes to perform a state change. - * @next_state: This parameter specifies the new state for the state machine. - * - */ -void sci_base_state_machine_change_state( - struct sci_base_state_machine *sm, - u32 next_state) -{ - sci_state_machine_exit_state(sm); - - sm->previous_state_id = sm->current_state_id; - sm->current_state_id = next_state; - -#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) - /* Notify of the state change prior to entering the state. */ - sci_base_subject_notify(&sm->parent); -#endif - - sci_state_machine_enter_state(sm); -} - -/** - * This method simply returns the current state of the state machine to the - * caller. - * @sm: This parameter specifies the state machine for which to - * retrieve the current state. - * - * This method returns a u32 value indicating the current state for the - * supplied state machine. - */ -u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm) -{ - return sm->current_state_id; -} - diff --git a/drivers/scsi/isci/core/sci_base_state_machine.h b/drivers/scsi/isci/core/sci_base_state_machine.h deleted file mode 100644 index c0cf33bbecc8..000000000000 --- a/drivers/scsi/isci/core/sci_base_state_machine.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_STATE_MACHINE_H_ -#define _SCI_BASE_STATE_MACHINE_H_ - -#include - -/** - * This file contains all structures, constants, or method declarations common - * to all state machines defined in SCI. - * - * - */ - - -#include "sci_base_state.h" - - -/** - * SET_STATE_HANDLER() - - * - * This macro simply provides simplified retrieval of an objects state handler. - */ -#define SET_STATE_HANDLER(object, table, state) \ - (object)->state_handlers = &(table)[(state)] - -/** - * struct sci_base_state_machine - This structure defines the fields common to - * all state machines. - * - * - */ -struct sci_base_state_machine { - /** - * This field points to the start of the state machine's state table. - */ - const struct sci_base_state *state_table; - - /** - * This field points to the object to which this state machine is - * associated. It serves as a cookie to be provided to the state - * enter/exit methods. - */ - void *state_machine_owner; - - /** - * This field simply indicates the state value for the state machine's - * initial state. - */ - u32 initial_state_id; - - /** - * This field indicates the current state of the state machine. - */ - u32 current_state_id; - - /** - * This field indicates the previous state of the state machine. - */ - u32 previous_state_id; - -}; - -/* - * ****************************************************************************** - * * P R O T E C T E D M E T H O D S - * ****************************************************************************** */ - -void sci_base_state_machine_construct( - struct sci_base_state_machine *this_state_machine, - void *state_machine_owner, - const struct sci_base_state *state_table, - u32 initial_state); - -void sci_base_state_machine_start( - struct sci_base_state_machine *this_state_machine); - -void sci_base_state_machine_stop( - struct sci_base_state_machine *this_state_machine); - -void sci_base_state_machine_change_state( - struct sci_base_state_machine *this_state_machine, - u32 next_state); - -u32 sci_base_state_machine_get_state( - struct sci_base_state_machine *this_state_machine); - -#endif /* _SCI_BASE_STATE_MACHINE_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index c82ccb93fd9b..6b49d94bc9cc 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -56,8 +56,7 @@ #include #include "sas.h" #include "host.h" -#include "sci_base_state.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" #include "scic_phy.h" #include "scic_sds_phy.h" #include "scic_sds_port.h" diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h index 472718d2f444..0d7bab3fc93b 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ b/drivers/scsi/isci/core/scic_sds_phy.h @@ -59,7 +59,7 @@ #include "sas.h" #include "scic_phy.h" #include "registers.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" #include struct scic_sds_port; diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h index 4b28c5acd758..a351525b1c49 100644 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ b/drivers/scsi/isci/core/scic_sds_port.h @@ -60,7 +60,7 @@ #include "isci.h" #include "sas.h" #include "registers.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" struct scic_sds_controller; struct scic_sds_phy; diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h index 5ce7ff2aed9a..a8d74a15a86b 100644 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ b/drivers/scsi/isci/core/scic_sds_request.h @@ -58,7 +58,7 @@ #include "isci.h" #include "scic_io_request.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" #include "scu_task_context.h" #include "scic_sds_stp_request.h" #include "sas.h" diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c index 7f338948ae0d..6a2b65b9cf0f 100644 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c @@ -54,7 +54,7 @@ */ #include -#include "sci_base_state_machine.h" +#include "state_machine.h" #include "remote_device.h" #include "scic_sds_request.h" #include "scic_sds_smp_request.h" diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c index 137f6ddac82c..3fdf68be7a4d 100644 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c @@ -54,7 +54,7 @@ */ #include "host.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" #include "scic_sds_request.h" #include "scu_completion_codes.h" #include "scu_task_context.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h index d0ae5909aee2..e015a1114760 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h +++ b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h @@ -56,7 +56,6 @@ #ifndef _SCIC_SDS_SATA_PIO_REQUEST_H_ #define _SCIC_SDS_SATA_PIO_REQUEST_H_ -#include "sci_base_state.h" #include "scic_sds_request.h" #include "scu_task_context.h" diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c index 9a787e25b48b..308f486514e9 100644 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c @@ -55,8 +55,7 @@ #include #include "sas.h" -#include "sci_base_state.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" #include "scic_io_request.h" #include "remote_device.h" #include "scic_sds_request.h" diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 64edac8ccce1..9c5d121ce791 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -59,7 +59,7 @@ #include "remote_device.h" #include "phy.h" #include "pool.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" #include "remote_node_table.h" #include "registers.h" #include "scu_unsolicited_frame.h" diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index af4759383db4..5891f3d50177 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -54,7 +54,7 @@ */ #include "host.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" #include "scic_sds_port.h" #include "remote_device.h" #include "remote_node_context.h" diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index 540a49a9c94d..a763468fa74f 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -64,8 +64,7 @@ * */ -#include "sci_base_state.h" -#include "sci_base_state_machine.h" +#include "state_machine.h" /** * diff --git a/drivers/scsi/isci/state_machine.c b/drivers/scsi/isci/state_machine.c new file mode 100644 index 000000000000..6057782af8c2 --- /dev/null +++ b/drivers/scsi/isci/state_machine.c @@ -0,0 +1,171 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This file contains all of the functionality common to all state machine + * object implementations. + * + * + */ + +#include "state_machine.h" + +static void sci_state_machine_exit_state(struct sci_base_state_machine *sm) +{ + u32 state = sm->current_state_id; + sci_state_transition_t exit = sm->state_table[state].exit_state; + + if (exit) + exit(sm->state_machine_owner); +} + +static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) +{ + u32 state = sm->current_state_id; + sci_state_transition_t enter = sm->state_table[state].enter_state; + + if (enter) + enter(sm->state_machine_owner); +} + +/* + * ****************************************************************************** + * * P R O T E C T E D M E T H O D S + * ****************************************************************************** */ + +/** + * This method will set the initial state and state table for the state + * machine. The caller should follow this request with the initialize + * request to cause the state machine to start. + * @sm: This parameter provides the state machine object to be + * constructed. + * @state_machine_owner: This parameter indicates the object that is owns the + * state machine being constructed. + * @state_table: This parameter specifies the table of state objects that is + * managed by this state machine. + * @initial_state: This parameter specifies the value of the initial state for + * this state machine. + * + */ +void sci_base_state_machine_construct(struct sci_base_state_machine *sm, + void *owner, + const struct sci_base_state *state_table, + u32 initial_state) +{ + sm->state_machine_owner = owner; + sm->initial_state_id = initial_state; + sm->previous_state_id = initial_state; + sm->current_state_id = initial_state; + sm->state_table = state_table; +} + +/** + * This method will cause the state machine to enter the initial state. + * @sm: This parameter specifies the state machine that is to + * be started. + * + * sci_base_state_machine_construct() for how to set the initial state none + */ +void sci_base_state_machine_start(struct sci_base_state_machine *sm) +{ + sm->current_state_id = sm->initial_state_id; + sci_state_machine_enter_state(sm); +} + +/** + * This method will cause the state machine to exit it's current state only. + * @sm: This parameter specifies the state machine that is to + * be stopped. + * + */ +void sci_base_state_machine_stop( + struct sci_base_state_machine *sm) +{ + sci_state_machine_exit_state(sm); +} + +/** + * This method performs an update to the current state of the state machine. + * @sm: This parameter specifies the state machine for which + * the caller wishes to perform a state change. + * @next_state: This parameter specifies the new state for the state machine. + * + */ +void sci_base_state_machine_change_state( + struct sci_base_state_machine *sm, + u32 next_state) +{ + sci_state_machine_exit_state(sm); + + sm->previous_state_id = sm->current_state_id; + sm->current_state_id = next_state; + + sci_state_machine_enter_state(sm); +} + +/** + * This method simply returns the current state of the state machine to the + * caller. + * @sm: This parameter specifies the state machine for which to + * retrieve the current state. + * + * This method returns a u32 value indicating the current state for the + * supplied state machine. + */ +u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm) +{ + return sm->current_state_id; +} + diff --git a/drivers/scsi/isci/state_machine.h b/drivers/scsi/isci/state_machine.h new file mode 100644 index 000000000000..c29eb4271d05 --- /dev/null +++ b/drivers/scsi/isci/state_machine.h @@ -0,0 +1,155 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCI_BASE_STATE_MACHINE_H_ +#define _SCI_BASE_STATE_MACHINE_H_ + +#include + +typedef void (*sci_base_state_handler_t)(void); + +typedef void (*sci_state_transition_t)(void *base_object); + +/** + * struct sci_base_state - The base state object abstracts the fields common to + * all state objects defined in SCI. + * + * + */ +struct sci_base_state { + /** + * This field is a function pointer that defines the method to be + * invoked when the state is entered. + */ + sci_state_transition_t enter_state; + + /** + * This field is a function pointer that defines the method to be + * invoked when the state is exited. + */ + sci_state_transition_t exit_state; + +}; + +/** + * SET_STATE_HANDLER() - + * + * This macro simply provides simplified retrieval of an objects state handler. + */ +#define SET_STATE_HANDLER(object, table, state) \ + (object)->state_handlers = &(table)[(state)] + +/** + * struct sci_base_state_machine - This structure defines the fields common to + * all state machines. + * + * + */ +struct sci_base_state_machine { + /** + * This field points to the start of the state machine's state table. + */ + const struct sci_base_state *state_table; + + /** + * This field points to the object to which this state machine is + * associated. It serves as a cookie to be provided to the state + * enter/exit methods. + */ + void *state_machine_owner; + + /** + * This field simply indicates the state value for the state machine's + * initial state. + */ + u32 initial_state_id; + + /** + * This field indicates the current state of the state machine. + */ + u32 current_state_id; + + /** + * This field indicates the previous state of the state machine. + */ + u32 previous_state_id; + +}; + +/* + * ****************************************************************************** + * * P R O T E C T E D M E T H O D S + * ****************************************************************************** */ + +void sci_base_state_machine_construct( + struct sci_base_state_machine *this_state_machine, + void *state_machine_owner, + const struct sci_base_state *state_table, + u32 initial_state); + +void sci_base_state_machine_start( + struct sci_base_state_machine *this_state_machine); + +void sci_base_state_machine_stop( + struct sci_base_state_machine *this_state_machine); + +void sci_base_state_machine_change_state( + struct sci_base_state_machine *this_state_machine, + u32 next_state); + +u32 sci_base_state_machine_get_state( + struct sci_base_state_machine *this_state_machine); + +#endif /* _SCI_BASE_STATE_MACHINE_H_ */ -- cgit v1.2.3 From f1f52e75939b56c40b3d153ae99faf2720250242 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 May 2011 02:28:45 -0700 Subject: isci: uplevel request infrastructure * Consolidate tiny header files * Move files out of core/ (drop core/scic_sds_ prefix) * Merge core/scic_sds_request.[ch] into request.[ch] * Cleanup request.c namespace (clean forward declarations and global namespace pollution) Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 8 +- drivers/scsi/isci/core/sci_util.c | 86 - drivers/scsi/isci/core/sci_util.h | 97 - drivers/scsi/isci/core/scic_io_request.h | 226 -- drivers/scsi/isci/core/scic_sds_phy.c | 1 - drivers/scsi/isci/core/scic_sds_port.c | 2 +- drivers/scsi/isci/core/scic_sds_request.c | 1523 ---------- drivers/scsi/isci/core/scic_sds_request.h | 491 --- drivers/scsi/isci/core/scic_sds_smp_request.c | 520 ---- drivers/scsi/isci/core/scic_sds_smp_request.h | 67 - drivers/scsi/isci/core/scic_sds_ssp_request.c | 240 -- .../scsi/isci/core/scic_sds_stp_packet_request.h | 113 - drivers/scsi/isci/core/scic_sds_stp_pio_request.h | 104 - drivers/scsi/isci/core/scic_sds_stp_request.c | 1594 ---------- drivers/scsi/isci/core/scic_sds_stp_request.h | 178 -- drivers/scsi/isci/core/scic_task_request.h | 104 - drivers/scsi/isci/host.c | 2 - drivers/scsi/isci/isci.h | 19 + drivers/scsi/isci/port.c | 1 - drivers/scsi/isci/remote_device.c | 3 - drivers/scsi/isci/remote_node_context.c | 1 - drivers/scsi/isci/remote_node_table.c | 1 - drivers/scsi/isci/request.c | 3124 ++++++++++++++------ drivers/scsi/isci/request.h | 442 ++- drivers/scsi/isci/sata.c | 2 - drivers/scsi/isci/smp_request.c | 518 ++++ drivers/scsi/isci/ssp_request.c | 240 ++ drivers/scsi/isci/stp_request.c | 1590 ++++++++++ drivers/scsi/isci/stp_request.h | 195 ++ drivers/scsi/isci/task.c | 3 - drivers/scsi/isci/unsolicited_frame_control.c | 5 +- 31 files changed, 5248 insertions(+), 6252 deletions(-) delete mode 100644 drivers/scsi/isci/core/sci_util.c delete mode 100644 drivers/scsi/isci/core/sci_util.h delete mode 100644 drivers/scsi/isci/core/scic_io_request.h delete mode 100644 drivers/scsi/isci/core/scic_sds_request.c delete mode 100644 drivers/scsi/isci/core/scic_sds_request.h delete mode 100644 drivers/scsi/isci/core/scic_sds_smp_request.c delete mode 100644 drivers/scsi/isci/core/scic_sds_smp_request.h delete mode 100644 drivers/scsi/isci/core/scic_sds_ssp_request.c delete mode 100644 drivers/scsi/isci/core/scic_sds_stp_packet_request.h delete mode 100644 drivers/scsi/isci/core/scic_sds_stp_pio_request.h delete mode 100644 drivers/scsi/isci/core/scic_sds_stp_request.c delete mode 100644 drivers/scsi/isci/core/scic_sds_stp_request.h delete mode 100644 drivers/scsi/isci/core/scic_task_request.h create mode 100644 drivers/scsi/isci/smp_request.c create mode 100644 drivers/scsi/isci/ssp_request.c create mode 100644 drivers/scsi/isci/stp_request.c create mode 100644 drivers/scsi/isci/stp_request.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index cfc640f9dc3f..a7d1eb33eca2 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -7,11 +7,9 @@ isci-objs := init.o phy.o request.o sata.o \ remote_node_context.o \ remote_node_table.o \ unsolicited_frame_control.o \ - core/scic_sds_request.o \ - core/scic_sds_stp_request.o \ + stp_request.o \ + ssp_request.o \ + smp_request.o \ core/scic_sds_port.o \ core/scic_sds_port_configuration_agent.o \ core/scic_sds_phy.o \ - core/scic_sds_ssp_request.o \ - core/scic_sds_smp_request.o \ - core/sci_util.o diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c deleted file mode 100644 index 595d8da1abba..000000000000 --- a/drivers/scsi/isci/core/sci_util.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "sci_util.h" -#include "request.h" - -void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr) -{ - struct isci_request *ireq = sci_req_to_ireq(sci_req); - dma_addr_t offset; - - BUG_ON(phys_addr < ireq->request_daddr); - - offset = phys_addr - ireq->request_daddr; - - BUG_ON(offset >= sizeof(*ireq)); - - return (char *)ireq + offset; -} - -dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request, - void *virt_addr) -{ - struct isci_request *isci_request = sci_req_to_ireq(sds_request); - - char *requested_addr = (char *)virt_addr; - char *base_addr = (char *)isci_request; - - BUG_ON(requested_addr < base_addr); - BUG_ON((requested_addr - base_addr) >= sizeof(*isci_request)); - - return isci_request->request_daddr + (requested_addr - base_addr); -} diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h deleted file mode 100644 index 0f9dd0fe1266..000000000000 --- a/drivers/scsi/isci/core/sci_util.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_UTIL_H_ -#define _SCI_UTIL_H_ - -#include "scic_sds_request.h" - -#define SCIC_BUILD_DWORD(char_buffer) \ - (\ - ((char_buffer)[0] << 24) \ - | ((char_buffer)[1] << 16) \ - | ((char_buffer)[2] << 8) \ - | ((char_buffer)[3]) \ - ) - -#define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ - ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) - -/** - * sci_swab32_cpy - convert between scsi and scu-hardware byte format - * @dest: receive the 4-byte endian swapped version of src - * @src: word aligned source buffer - * - * scu hardware handles SSP/SMP control, response, and unidentified - * frames in "big endian dword" order. Regardless of host endian this - * is always a swab32()-per-dword conversion of the standard definition, - * i.e. single byte fields swapped and multi-byte fields in little- - * endian - */ -static inline void sci_swab32_cpy(void *_dest, void *_src, ssize_t word_cnt) -{ - u32 *dest = _dest, *src = _src; - - while (--word_cnt >= 0) - dest[word_cnt] = swab32(src[word_cnt]); -} - -void *scic_request_get_virt_addr(struct scic_sds_request *sds_request, - dma_addr_t phys_addr); - -dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sds_request, - void *virt_addr); - -#endif /* _SCI_UTIL_H_ */ diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h deleted file mode 100644 index a4664cc3c576..000000000000 --- a/drivers/scsi/isci/core/scic_io_request.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_IO_REQUEST_H_ -#define _SCIC_IO_REQUEST_H_ - -#include - -struct scic_sds_request; -struct scic_sds_remote_device; -struct scic_sds_controller; - -/** - * This enumeration specifies the transport protocol utilized for the request. - * - * - */ -typedef enum { - /** - * This enumeration constant indicates that no protocol has yet been - * set. - */ - SCIC_NO_PROTOCOL, - - /** - * This enumeration constant indicates that the protocol utilized - * is the Serial Management Protocol. - */ - SCIC_SMP_PROTOCOL, - - /** - * This enumeration constant indicates that the protocol utilized - * is the Serial SCSI Protocol. - */ - SCIC_SSP_PROTOCOL, - - /** - * This enumeration constant indicates that the protocol utilized - * is the Serial-ATA Tunneling Protocol. - */ - SCIC_STP_PROTOCOL - -} SCIC_TRANSPORT_PROTOCOL; - -enum sci_status scic_io_request_construct( - struct scic_sds_controller *scic_controller, - struct scic_sds_remote_device *scic_remote_device, - u16 io_tag, struct scic_sds_request *sci_req); - -/** - * scic_io_request_construct_basic_ssp() - This method is called by the SCI - * user to build an SSP IO request. - * @scic_io_request: This parameter specifies the handle to the io request - * object to be built. - * - * - The user must have previously called scic_io_request_construct() on the - * supplied IO request. Indicate if the controller successfully built the IO - * request. SCI_SUCCESS This value is returned if the IO request was - * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned - * if the remote_device does not support the SSP protocol. - * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not - * properly set the association between the SCIC IO request and the user's IO - * request. - */ -enum sci_status scic_io_request_construct_basic_ssp( - struct scic_sds_request *scic_io_request); - - - - - -/** - * scic_io_request_construct_basic_sata() - This method is called by the SCI - * Core user to build an STP IO request. - * @scic_io_request: This parameter specifies the handle to the io request - * object to be built. - * - * - The user must have previously called scic_io_request_construct() on the - * supplied IO request. Indicate if the controller successfully built the IO - * request. SCI_SUCCESS This value is returned if the IO request was - * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned - * if the remote_device does not support the STP protocol. - * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not - * properly set the association between the SCIC IO request and the user's IO - * request. - */ -enum sci_status scic_io_request_construct_basic_sata( - struct scic_sds_request *scic_io_request); - - - - -/** - * scic_io_request_construct_smp() - This method is called by the SCI user to - * build an SMP IO request. - * @scic_io_request: This parameter specifies the handle to the io request - * object to be built. - * - * - The user must have previously called scic_io_request_construct() on the - * supplied IO request. Indicate if the controller successfully built the IO - * request. SCI_SUCCESS This value is returned if the IO request was - * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned - * if the remote_device does not support the SMP protocol. - * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not - * properly set the association between the SCIC IO request and the user's IO - * request. - */ -enum sci_status scic_io_request_construct_smp( - struct scic_sds_request *scic_io_request); - - - -/** - * scic_request_get_controller_status() - This method returns the controller - * specific IO/Task request status. These status values are unique to the - * specific controller being managed by the SCIC. - * @io_request: the handle to the IO or task management request object for - * which to retrieve the status. - * - * This method returns a value indicating the controller specific request - * status. - */ -u32 scic_request_get_controller_status( - struct scic_sds_request *io_request); - -/** - * scic_io_request_get_io_tag() - This method will return the IO tag utilized - * by the IO request. - * @scic_io_request: This parameter specifies the handle to the io request - * object for which to return the IO tag. - * - * An unsigned integer representing the IO tag being utilized. - * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if the IO does not - * currently have an IO tag allocated to it. All return other values indicate a - * legitimate tag. - */ -u16 scic_io_request_get_io_tag( - struct scic_sds_request *scic_io_request); - - -/** - * scic_stp_io_request_set_ncq_tag() - This method will assign an NCQ tag to - * the io request object. The caller of this function must make sure that - * only valid NCQ tags are assigned to the io request object. - * @scic_io_request: This parameter specifies the handle to the io request - * object to which to assign the ncq tag. - * @ncq_tag: This parameter specifies the NCQ tag to be utilized for the - * supplied core IO request. It is up to the user to make sure that this is - * a valid NCQ tag. - * - * none This function is only valid for SATA NCQ requests. - */ -void scic_stp_io_request_set_ncq_tag( - struct scic_sds_request *scic_io_request, - u16 ncq_tag); - -/** - * scic_io_request_get_number_of_bytes_transferred() - This method will return - * the number of bytes transferred from the SCU - * @scic_io_request: This parameter specifies the handle to the io request - * whose data length was not eqaul to the data length specified in the - * request. When the driver gets an early io completion status from the - * hardware, this routine should be called to get the actual number of bytes - * transferred - * - * The return is the number of bytes transferred when the data legth is not - * equal to the specified length in the io request - */ -u32 scic_io_request_get_number_of_bytes_transferred( - struct scic_sds_request *scic_io_request); - - -#endif /* _SCIC_IO_REQUEST_H_ */ - diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index 6b49d94bc9cc..150509b0c69e 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -61,7 +61,6 @@ #include "scic_sds_phy.h" #include "scic_sds_port.h" #include "remote_node_context.h" -#include "sci_util.h" #include "scu_event_codes.h" #include "timers.h" diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index 652917eeead4..a9f3ce111b86 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -60,9 +60,9 @@ #include "scic_sds_port.h" #include "remote_device.h" #include "remote_node_context.h" -#include "scic_sds_request.h" #include "registers.h" #include "timers.h" +#include "scu_task_context.h" #define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) #define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c deleted file mode 100644 index cd279601de01..000000000000 --- a/drivers/scsi/isci/core/scic_sds_request.c +++ /dev/null @@ -1,1523 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "scic_io_request.h" -#include "registers.h" -#include "scic_sds_port.h" -#include "remote_device.h" -#include "scic_sds_request.h" -#include "scic_sds_smp_request.h" -#include "scic_sds_stp_request.h" -#include "unsolicited_frame_control.h" -#include "sci_util.h" -#include "scu_completion_codes.h" -#include "scu_task_context.h" -#include "request.h" -#include "task.h" - -/* - * **************************************************************************** - * * SCIC SDS IO REQUEST CONSTANTS - * **************************************************************************** */ - -/** - * - * - * We have no timer requirements for IO requests right now - */ -#define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0) -#define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0) - -/** - * This method returns the sgl element pair for the specificed sgl_pair index. - * @sci_req: This parameter specifies the IO request for which to retrieve - * the Scatter-Gather List element pair. - * @sgl_pair_index: This parameter specifies the index into the SGL element - * pair to be retrieved. - * - * This method returns a pointer to an struct scu_sgl_element_pair. - */ -static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( - struct scic_sds_request *sci_req, - u32 sgl_pair_index - ) { - struct scu_task_context *task_context; - - task_context = (struct scu_task_context *)sci_req->task_context_buffer; - - if (sgl_pair_index == 0) { - return &task_context->sgl_pair_ab; - } else if (sgl_pair_index == 1) { - return &task_context->sgl_pair_cd; - } - - return &sci_req->sg_table[sgl_pair_index - 2]; -} - -/** - * This function will build the SGL list for an IO request. - * @sci_req: This parameter specifies the IO request for which to build - * the Scatter-Gather List. - * - */ -void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) -{ - struct isci_request *isci_request = sci_req_to_ireq(sds_request); - struct isci_host *isci_host = isci_request->isci_host; - struct sas_task *task = isci_request_access_task(isci_request); - struct scatterlist *sg = NULL; - dma_addr_t dma_addr; - u32 sg_idx = 0; - struct scu_sgl_element_pair *scu_sg = NULL; - struct scu_sgl_element_pair *prev_sg = NULL; - - if (task->num_scatter > 0) { - sg = task->scatter; - - while (sg) { - scu_sg = scic_sds_request_get_sgl_element_pair( - sds_request, - sg_idx); - - SCU_SGL_COPY(scu_sg->A, sg); - - sg = sg_next(sg); - - if (sg) { - SCU_SGL_COPY(scu_sg->B, sg); - sg = sg_next(sg); - } else - SCU_SGL_ZERO(scu_sg->B); - - if (prev_sg) { - dma_addr = - scic_io_request_get_dma_addr( - sds_request, - scu_sg); - - prev_sg->next_pair_upper = - upper_32_bits(dma_addr); - prev_sg->next_pair_lower = - lower_32_bits(dma_addr); - } - - prev_sg = scu_sg; - sg_idx++; - } - } else { /* handle when no sg */ - scu_sg = scic_sds_request_get_sgl_element_pair(sds_request, - sg_idx); - - dma_addr = dma_map_single(&isci_host->pdev->dev, - task->scatter, - task->total_xfer_len, - task->data_dir); - - isci_request->zero_scatter_daddr = dma_addr; - - scu_sg->A.length = task->total_xfer_len; - scu_sg->A.address_upper = upper_32_bits(dma_addr); - scu_sg->A.address_lower = lower_32_bits(dma_addr); - } - - if (scu_sg) { - scu_sg->next_pair_upper = 0; - scu_sg->next_pair_lower = 0; - } -} - -static void scic_sds_ssp_io_request_assign_buffers(struct scic_sds_request *sci_req) -{ - if (sci_req->was_tag_assigned_by_user == false) - sci_req->task_context_buffer = &sci_req->tc; -} - -static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) -{ - struct ssp_cmd_iu *cmd_iu; - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(ireq); - - cmd_iu = &sci_req->ssp.cmd; - - memcpy(cmd_iu->LUN, task->ssp_task.LUN, 8); - cmd_iu->add_cdb_len = 0; - cmd_iu->_r_a = 0; - cmd_iu->_r_b = 0; - cmd_iu->en_fburst = 0; /* unsupported */ - cmd_iu->task_prio = task->ssp_task.task_prio; - cmd_iu->task_attr = task->ssp_task.task_attr; - cmd_iu->_r_c = 0; - - sci_swab32_cpy(&cmd_iu->cdb, task->ssp_task.cdb, - sizeof(task->ssp_task.cdb) / sizeof(u32)); -} - -static void scic_sds_task_request_build_ssp_task_iu(struct scic_sds_request *sci_req) -{ - struct ssp_task_iu *task_iu; - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(ireq); - struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - - task_iu = &sci_req->ssp.tmf; - - memset(task_iu, 0, sizeof(struct ssp_task_iu)); - - memcpy(task_iu->LUN, task->ssp_task.LUN, 8); - - task_iu->task_func = isci_tmf->tmf_code; - task_iu->task_tag = - (ireq->ttype == tmf_task) ? - isci_tmf->io_tag : - SCI_CONTROLLER_INVALID_IO_TAG; -} - -/** - * This method is will fill in the SCU Task Context for any type of SSP request. - * @sci_req: - * @task_context: - * - */ -static void scu_ssp_reqeust_construct_task_context( - struct scic_sds_request *sds_request, - struct scu_task_context *task_context) -{ - dma_addr_t dma_addr; - struct scic_sds_controller *controller; - struct scic_sds_remote_device *target_device; - struct scic_sds_port *target_port; - - controller = scic_sds_request_get_controller(sds_request); - target_device = scic_sds_request_get_device(sds_request); - target_port = scic_sds_request_get_port(sds_request); - - /* Fill in the TC with the its required data */ - task_context->abort = 0; - task_context->priority = 0; - task_context->initiator_request = 1; - task_context->connection_rate = target_device->connection_rate; - task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(controller); - task_context->logical_port_index = - scic_sds_port_get_index(target_port); - task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; - task_context->valid = SCU_TASK_CONTEXT_VALID; - task_context->context_type = SCU_TASK_CONTEXT_TYPE; - - task_context->remote_node_index = - scic_sds_remote_device_get_index(sds_request->target_device); - task_context->command_code = 0; - - task_context->link_layer_control = 0; - task_context->do_not_dma_ssp_good_response = 1; - task_context->strict_ordering = 0; - task_context->control_frame = 0; - task_context->timeout_enable = 0; - task_context->block_guard_enable = 0; - - task_context->address_modifier = 0; - - /* task_context->type.ssp.tag = sci_req->io_tag; */ - task_context->task_phase = 0x01; - - if (sds_request->was_tag_assigned_by_user) { - /* - * Build the task context now since we have already read - * the data - */ - sds_request->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sds_request->io_tag)); - } else { - /* - * Build the task context now since we have already read - * the data - * - * I/O tag index is not assigned because we have to wait - * until we get a TCi - */ - sds_request->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - owning_controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); - } - - /* - * Copy the physical address for the command buffer to the - * SCU Task Context - */ - dma_addr = scic_io_request_get_dma_addr(sds_request, - &sds_request->ssp.cmd); - - task_context->command_iu_upper = upper_32_bits(dma_addr); - task_context->command_iu_lower = lower_32_bits(dma_addr); - - /* - * Copy the physical address for the response buffer to the - * SCU Task Context - */ - dma_addr = scic_io_request_get_dma_addr(sds_request, - &sds_request->ssp.rsp); - - task_context->response_iu_upper = upper_32_bits(dma_addr); - task_context->response_iu_lower = lower_32_bits(dma_addr); -} - -/** - * This method is will fill in the SCU Task Context for a SSP IO request. - * @sci_req: - * - */ -static void scu_ssp_io_request_construct_task_context( - struct scic_sds_request *sci_req, - enum dma_data_direction dir, - u32 len) -{ - struct scu_task_context *task_context; - - task_context = scic_sds_request_get_task_context(sci_req); - - scu_ssp_reqeust_construct_task_context(sci_req, task_context); - - task_context->ssp_command_iu_length = - sizeof(struct ssp_cmd_iu) / sizeof(u32); - task_context->type.ssp.frame_type = SSP_COMMAND; - - switch (dir) { - case DMA_FROM_DEVICE: - case DMA_NONE: - default: - task_context->task_type = SCU_TASK_TYPE_IOREAD; - break; - case DMA_TO_DEVICE: - task_context->task_type = SCU_TASK_TYPE_IOWRITE; - break; - } - - task_context->transfer_length_bytes = len; - - if (task_context->transfer_length_bytes > 0) - scic_sds_request_build_sgl(sci_req); -} - -static void scic_sds_ssp_task_request_assign_buffers(struct scic_sds_request *sci_req) -{ - if (sci_req->was_tag_assigned_by_user == false) - sci_req->task_context_buffer = &sci_req->tc; -} - -/** - * This method will fill in the SCU Task Context for a SSP Task request. The - * following important settings are utilized: -# priority == - * SCU_TASK_PRIORITY_HIGH. This ensures that the task request is issued - * ahead of other task destined for the same Remote Node. -# task_type == - * SCU_TASK_TYPE_IOREAD. This simply indicates that a normal request type - * (i.e. non-raw frame) is being utilized to perform task management. -# - * control_frame == 1. This ensures that the proper endianess is set so - * that the bytes are transmitted in the right order for a task frame. - * @sci_req: This parameter specifies the task request object being - * constructed. - * - */ -static void scu_ssp_task_request_construct_task_context( - struct scic_sds_request *sci_req) -{ - struct scu_task_context *task_context; - - task_context = scic_sds_request_get_task_context(sci_req); - - scu_ssp_reqeust_construct_task_context(sci_req, task_context); - - task_context->control_frame = 1; - task_context->priority = SCU_TASK_PRIORITY_HIGH; - task_context->task_type = SCU_TASK_TYPE_RAW_FRAME; - task_context->transfer_length_bytes = 0; - task_context->type.ssp.frame_type = SSP_TASK; - task_context->ssp_command_iu_length = - sizeof(struct ssp_task_iu) / sizeof(u32); -} - - -/** - * This method constructs the SSP Command IU data for this ssp passthrough - * comand request object. - * @sci_req: This parameter specifies the request object for which the SSP - * command information unit is being built. - * - * enum sci_status, returns invalid parameter is cdb > 16 - */ - - -/** - * This method constructs the SATA request object. - * @sci_req: - * @sat_protocol: - * @transfer_length: - * @data_direction: - * @copy_rx_frame: - * - * enum sci_status - */ -static enum sci_status -scic_io_request_construct_sata(struct scic_sds_request *sci_req, - u32 len, - enum dma_data_direction dir, - bool copy) -{ - enum sci_status status = SCI_SUCCESS; - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(ireq); - - /* check for management protocols */ - if (ireq->ttype == tmf_task) { - struct isci_tmf *tmf = isci_request_access_tmf(ireq); - - if (tmf->tmf_code == isci_tmf_sata_srst_high || - tmf->tmf_code == isci_tmf_sata_srst_low) - return scic_sds_stp_soft_reset_request_construct(sci_req); - else { - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: Request 0x%p received un-handled SAT " - "management protocol 0x%x.\n", - __func__, sci_req, tmf->tmf_code); - - return SCI_FAILURE; - } - } - - if (!sas_protocol_ata(task->task_proto)) { - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: Non-ATA protocol in SATA path: 0x%x\n", - __func__, - task->task_proto); - return SCI_FAILURE; - - } - - /* non data */ - if (task->data_dir == DMA_NONE) - return scic_sds_stp_non_data_request_construct(sci_req); - - /* NCQ */ - if (task->ata_task.use_ncq) - return scic_sds_stp_ncq_request_construct(sci_req, len, dir); - - /* DMA */ - if (task->ata_task.dma_xfer) - return scic_sds_stp_udma_request_construct(sci_req, len, dir); - else /* PIO */ - return scic_sds_stp_pio_request_construct(sci_req, copy); - - return status; -} - -enum sci_status scic_io_request_construct_basic_ssp( - struct scic_sds_request *sci_req) -{ - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(ireq); - - sci_req->protocol = SCIC_SSP_PROTOCOL; - - scu_ssp_io_request_construct_task_context(sci_req, - task->data_dir, - task->total_xfer_len); - - scic_sds_io_request_build_ssp_command_iu(sci_req); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); - - return SCI_SUCCESS; -} - - -enum sci_status scic_task_request_construct_ssp( - struct scic_sds_request *sci_req) -{ - /* Construct the SSP Task SCU Task Context */ - scu_ssp_task_request_construct_task_context(sci_req); - - /* Fill in the SSP Task IU */ - scic_sds_task_request_build_ssp_task_iu(sci_req); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); - - return SCI_SUCCESS; -} - - -enum sci_status scic_io_request_construct_basic_sata( - struct scic_sds_request *sci_req) -{ - enum sci_status status; - struct scic_sds_stp_request *stp_req; - bool copy = false; - struct isci_request *isci_request = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(isci_request); - - stp_req = &sci_req->stp.req; - sci_req->protocol = SCIC_STP_PROTOCOL; - - copy = (task->data_dir == DMA_NONE) ? false : true; - - status = scic_io_request_construct_sata(sci_req, - task->total_xfer_len, - task->data_dir, - copy); - - if (status == SCI_SUCCESS) - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); - - return status; -} - - -enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req) -{ - enum sci_status status = SCI_SUCCESS; - struct isci_request *ireq = sci_req_to_ireq(sci_req); - - /* check for management protocols */ - if (ireq->ttype == tmf_task) { - struct isci_tmf *tmf = isci_request_access_tmf(ireq); - - if (tmf->tmf_code == isci_tmf_sata_srst_high || - tmf->tmf_code == isci_tmf_sata_srst_low) { - status = scic_sds_stp_soft_reset_request_construct(sci_req); - } else { - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: Request 0x%p received un-handled SAT " - "Protocol 0x%x.\n", - __func__, sci_req, tmf->tmf_code); - - return SCI_FAILURE; - } - } - - if (status == SCI_SUCCESS) - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); - - return status; -} - - -u16 scic_io_request_get_io_tag( - struct scic_sds_request *sci_req) -{ - return sci_req->io_tag; -} - - -u32 scic_request_get_controller_status( - struct scic_sds_request *sci_req) -{ - return sci_req->scu_status; -} - -#define SCU_TASK_CONTEXT_SRAM 0x200000 -u32 scic_io_request_get_number_of_bytes_transferred( - struct scic_sds_request *scic_sds_request) -{ - struct scic_sds_controller *scic = scic_sds_request->owning_controller; - u32 ret_val = 0; - - if (readl(&scic->smu_registers->address_modifier) == 0) { - void __iomem *scu_reg_base = scic->scu_registers; - /* - * get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where - * BAR1 is the scu_registers - * 0x20002C = 0x200000 + 0x2c - * = start of task context SRAM + offset of (type.ssp.data_offset) - * TCi is the io_tag of struct scic_sds_request */ - ret_val = readl(scu_reg_base + - (SCU_TASK_CONTEXT_SRAM + offsetof(struct scu_task_context, type.ssp.data_offset)) + - ((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(scic_sds_request->io_tag))); - } - - return ret_val; -} - - -/* - * **************************************************************************** - * * SCIC SDS Interface Implementation - * **************************************************************************** */ - -enum sci_status -scic_sds_request_start(struct scic_sds_request *request) -{ - if (request->device_sequence != - scic_sds_remote_device_get_sequence(request->target_device)) - return SCI_FAILURE; - - if (request->state_handlers->start_handler) - return request->state_handlers->start_handler(request); - - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to start while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -enum sci_status -scic_sds_io_request_terminate(struct scic_sds_request *request) -{ - if (request->state_handlers->abort_handler) - return request->state_handlers->abort_handler(request); - - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to abort while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -enum sci_status -scic_sds_io_request_complete(struct scic_sds_request *request) -{ - if (request->state_handlers->complete_handler) - return request->state_handlers->complete_handler(request); - - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to complete while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -enum sci_status scic_sds_io_request_event_handler( - struct scic_sds_request *request, - u32 event_code) -{ - if (request->state_handlers->event_handler) - return request->state_handlers->event_handler(request, event_code); - - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given event code notification %x while " - "in wrong state %d\n", - __func__, - event_code, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -enum sci_status -scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code) -{ - if (request->state_machine.current_state_id == SCI_BASE_REQUEST_STATE_STARTED && - request->has_started_substate_machine == false) - return scic_sds_request_started_state_tc_completion_handler(request, completion_code); - else if (request->state_handlers->tc_completion_handler) - return request->state_handlers->tc_completion_handler(request, completion_code); - - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given task completion notification %x " - "while in wrong state %d\n", - __func__, - completion_code, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; - -} - - -/** - * - * @sci_req: The SCIC_SDS_IO_REQUEST_T object for which the start - * operation is to be executed. - * @frame_index: The frame index returned by the hardware for the reqeust - * object. - * - * This method invokes the core state frame handler for the - * SCIC_SDS_IO_REQUEST_T object. enum sci_status - */ -enum sci_status scic_sds_io_request_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - if (request->state_handlers->frame_handler) - return request->state_handlers->frame_handler(request, frame_index); - - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given unexpected frame %x while in " - "state %d\n", - __func__, - frame_index, - sci_base_state_machine_get_state(&request->state_machine)); - - scic_sds_controller_release_frame(request->owning_controller, frame_index); - return SCI_FAILURE_INVALID_STATE; -} - -/* - * This function copies response data for requests returning response data - * instead of sense data. - * @sci_req: This parameter specifies the request object for which to copy - * the response data. - */ -void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) -{ - void *resp_buf; - u32 len; - struct ssp_response_iu *ssp_response; - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - - ssp_response = &sci_req->ssp.rsp; - - resp_buf = &isci_tmf->resp.resp_iu; - - len = min_t(u32, - SSP_RESP_IU_MAX_SIZE, - be32_to_cpu(ssp_response->response_data_len)); - - memcpy(resp_buf, ssp_response->resp_data, len); -} - -/* - * ***************************************************************************** - * * CONSTRUCTED STATE HANDLERS - * ***************************************************************************** */ - -/* - * This method implements the action taken when a constructed - * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request. - * This method will, if necessary, allocate a TCi for the io request object and - * then will, if necessary, copy the constructed TC data into the actual TC - * buffer. If everything is successful the post context field is updated with - * the TCi so the controller can post the request to the hardware. enum sci_status - * SCI_SUCCESS SCI_FAILURE_INSUFFICIENT_RESOURCES - */ -static enum sci_status scic_sds_request_constructed_state_start_handler( - struct scic_sds_request *request) -{ - struct scu_task_context *task_context; - - if (request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { - request->io_tag = - scic_controller_allocate_io_tag(request->owning_controller); - } - - /* Record the IO Tag in the request */ - if (request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { - task_context = request->task_context_buffer; - - task_context->task_index = scic_sds_io_tag_get_index(request->io_tag); - - switch (task_context->protocol_type) { - case SCU_TASK_CONTEXT_PROTOCOL_SMP: - case SCU_TASK_CONTEXT_PROTOCOL_SSP: - /* SSP/SMP Frame */ - task_context->type.ssp.tag = request->io_tag; - task_context->type.ssp.target_port_transfer_tag = 0xFFFF; - break; - - case SCU_TASK_CONTEXT_PROTOCOL_STP: - /* - * STP/SATA Frame - * task_context->type.stp.ncq_tag = request->ncq_tag; */ - break; - - case SCU_TASK_CONTEXT_PROTOCOL_NONE: - /* / @todo When do we set no protocol type? */ - break; - - default: - /* This should never happen since we build the IO requests */ - break; - } - - /* - * Check to see if we need to copy the task context buffer - * or have been building into the task context buffer */ - if (request->was_tag_assigned_by_user == false) { - scic_sds_controller_copy_task_context( - request->owning_controller, request); - } - - /* Add to the post_context the io tag value */ - request->post_context |= scic_sds_io_tag_get_index(request->io_tag); - - /* Everything is good go ahead and change state */ - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_STARTED); - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INSUFFICIENT_RESOURCES; -} - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_terminate() request. Since the request - * has not yet been posted to the hardware the request transitions to the - * completed state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_constructed_state_abort_handler( - struct scic_sds_request *request) -{ - /* - * This request has been terminated by the user make sure that the correct - * status code is returned */ - scic_sds_request_set_status(request, - SCU_TASK_DONE_TASK_ABORT, - SCI_FAILURE_IO_TERMINATED); - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - return SCI_SUCCESS; -} - -/* - * ***************************************************************************** - * * STARTED STATE HANDLERS - * ***************************************************************************** */ - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_terminate() request. Since the request - * has been posted to the hardware the io request state is changed to the - * aborting state. enum sci_status SCI_SUCCESS - */ -enum sci_status scic_sds_request_started_state_abort_handler( - struct scic_sds_request *request) -{ - if (request->has_started_substate_machine) - sci_base_state_machine_stop(&request->started_substate_machine); - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); - return SCI_SUCCESS; -} - -/* - * scic_sds_request_started_state_tc_completion_handler() - This method process - * TC (task context) completions for normal IO request (i.e. Task/Abort - * Completions of type 0). This method will update the - * SCIC_SDS_IO_REQUEST_T::status field. - * @sci_req: This parameter specifies the request for which a completion - * occurred. - * @completion_code: This parameter specifies the completion code received from - * the SCU. - * - */ -enum sci_status -scic_sds_request_started_state_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - u8 datapres; - struct ssp_response_iu *resp_iu; - - /* - * TODO: Any SDMA return code of other than 0 is bad - * decode 0x003C0000 to determine SDMA status - */ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - break; - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): - { - /* - * There are times when the SCU hardware will return an early - * response because the io request specified more data than is - * returned by the target device (mode pages, inquiry data, - * etc.). We must check the response stats to see if this is - * truly a failed request or a good request that just got - * completed early. - */ - struct ssp_response_iu *resp = &sci_req->ssp.rsp; - ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - - sci_swab32_cpy(&sci_req->ssp.rsp, - &sci_req->ssp.rsp, - word_cnt); - - if (resp->status == 0) { - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS_IO_DONE_EARLY); - } else { - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - } - } - break; - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): - { - ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - - sci_swab32_cpy(&sci_req->ssp.rsp, - &sci_req->ssp.rsp, - word_cnt); - - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; - } - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR): - /* - * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame - * guaranteed to be received before this completion status is - * posted? - */ - resp_iu = &sci_req->ssp.rsp; - datapres = resp_iu->datapres; - - if ((datapres == 0x01) || (datapres == 0x02)) { - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - } else - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - break; - - /* only stp device gets suspended. */ - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): - if (sci_req->protocol == SCIC_STP_PROTOCOL) { - scic_sds_request_set_status( - sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); - } else { - scic_sds_request_set_status( - sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - } - break; - - /* both stp/ssp device gets suspended */ - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): - scic_sds_request_set_status( - sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); - break; - - /* neither ssp nor stp gets suspended. */ - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): - default: - scic_sds_request_set_status( - sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - break; - } - - /* - * TODO: This is probably wrong for ACK/NAK timeout conditions - */ - - /* In all cases we will treat this as the completion of the IO req. */ - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - return SCI_SUCCESS; -} - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_frame_handler() request. This method - * first determines the frame type received. If this is a response frame then - * the response data is copied to the io request response buffer for processing - * at completion time. If the frame type is not a response buffer an error is - * logged. enum sci_status SCI_SUCCESS SCI_FAILURE_INVALID_PARAMETER_VALUE - */ -static enum sci_status -scic_sds_request_started_state_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - u32 *frame_header; - struct ssp_frame_hdr ssp_hdr; - ssize_t word_cnt; - - status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - (void **)&frame_header); - - word_cnt = sizeof(struct ssp_frame_hdr) / sizeof(u32); - sci_swab32_cpy(&ssp_hdr, frame_header, word_cnt); - - if (ssp_hdr.frame_type == SSP_RESPONSE) { - struct ssp_response_iu *resp_iu; - ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - - status = scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - (void **)&resp_iu); - - sci_swab32_cpy(&sci_req->ssp.rsp, - resp_iu, word_cnt); - - resp_iu = &sci_req->ssp.rsp; - - if ((resp_iu->datapres == 0x01) || - (resp_iu->datapres == 0x02)) { - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - } else - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - } else { - /* This was not a response frame why did it get forwarded? */ - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p received unexpected " - "frame %d type 0x%02x\n", - __func__, - sci_req, - frame_index, - ssp_hdr.frame_type); - } - - /* - * In any case we are done with this frame buffer return it to the - * controller - */ - scic_sds_controller_release_frame( - sci_req->owning_controller, frame_index); - - return SCI_SUCCESS; -} - -/* - * ***************************************************************************** - * * COMPLETED STATE HANDLERS - * ***************************************************************************** */ - - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_complete() request. This method frees up - * any io request resources that have been allocated and transitions the - * request to its final state. Consider stopping the state machine instead of - * transitioning to the final state? enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_completed_state_complete_handler( - struct scic_sds_request *request) -{ - if (request->was_tag_assigned_by_user != true) { - scic_controller_free_io_tag( - request->owning_controller, request->io_tag); - } - - if (request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) { - scic_sds_controller_release_frame( - request->owning_controller, request->saved_rx_frame_index); - } - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_FINAL); - return SCI_SUCCESS; -} - -/* - * ***************************************************************************** - * * ABORTING STATE HANDLERS - * ***************************************************************************** */ - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_terminate() request. This method is the - * io request aborting state abort handlers. On receipt of a multiple - * terminate requests the io request will transition to the completed state. - * This should not happen in normal operation. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_aborting_state_abort_handler( - struct scic_sds_request *request) -{ - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - return SCI_SUCCESS; -} - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_task_completion() request. This method - * decodes the completion type waiting for the abort task complete - * notification. When the abort task complete is received the io request - * transitions to the completed state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): - case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED - ); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - - default: - /* - * Unless we get some strange error wait for the task abort to complete - * TODO: Should there be a state change for this completion? */ - break; - } - - return SCI_SUCCESS; -} - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_frame_handler() request. This method - * discards the unsolicited frame since we are waiting for the abort task - * completion. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_aborting_state_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - /* TODO: Is it even possible to get an unsolicited frame in the aborting state? */ - - scic_sds_controller_release_frame( - sci_req->owning_controller, frame_index); - - return SCI_SUCCESS; -} - -static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { - [SCI_BASE_REQUEST_STATE_INITIAL] = { - }, - [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { - .start_handler = scic_sds_request_constructed_state_start_handler, - .abort_handler = scic_sds_request_constructed_state_abort_handler, - }, - [SCI_BASE_REQUEST_STATE_STARTED] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, - .frame_handler = scic_sds_request_started_state_frame_handler, - }, - [SCI_BASE_REQUEST_STATE_COMPLETED] = { - .complete_handler = scic_sds_request_completed_state_complete_handler, - }, - [SCI_BASE_REQUEST_STATE_ABORTING] = { - .abort_handler = scic_sds_request_aborting_state_abort_handler, - .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, - .frame_handler = scic_sds_request_aborting_state_frame_handler, - }, - [SCI_BASE_REQUEST_STATE_FINAL] = { - }, -}; - -/** - * scic_sds_request_initial_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the initial - * base request is constructed. Entry into the initial state sets all handlers - * for the io request object to their default handlers. none - */ -static void scic_sds_request_initial_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_INITIAL - ); -} - -/** - * scic_sds_request_constructed_state_enter() - - * @object: The io request object that is to enter the constructed state. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_CONSTRUCTED state. The method sets the state handlers - * for the the constructed state. none - */ -static void scic_sds_request_constructed_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_CONSTRUCTED - ); -} - -/** - * scic_sds_request_started_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This is cast into a SCIC_SDS_IO_REQUEST object. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a - * SCSI Task request we must enter the started substate machine. none - */ -static void scic_sds_request_started_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_STARTED - ); - - /* - * Most of the request state machines have a started substate machine so - * start its execution on the entry to the started state. */ - if (sci_req->has_started_substate_machine == true) - sci_base_state_machine_start(&sci_req->started_substate_machine); -} - -/** - * scic_sds_request_started_state_exit() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST - * object. - * - * This method implements the actions taken when exiting the - * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be - * to stop the started substate machine. none - */ -static void scic_sds_request_started_state_exit(void *object) -{ - struct scic_sds_request *sci_req = object; - - if (sci_req->has_started_substate_machine == true) - sci_base_state_machine_stop(&sci_req->started_substate_machine); -} - -/** - * scic_sds_request_completed_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST - * object. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_COMPLETED state. This state is entered when the - * SCIC_SDS_IO_REQUEST has completed. The method will decode the request - * completion status and convert it to an enum sci_status to return in the - * completion callback function. none - */ -static void scic_sds_request_completed_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - struct scic_sds_controller *scic = - scic_sds_request_get_controller(sci_req); - struct isci_host *ihost = scic_to_ihost(scic); - struct isci_request *ireq = sci_req_to_ireq(sci_req); - - SET_STATE_HANDLER(sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Tell the SCI_USER that the IO request is complete */ - if (sci_req->is_task_management_request == false) - isci_request_io_request_complete(ihost, - ireq, - sci_req->sci_status); - else - isci_task_request_complete(ihost, ireq, sci_req->sci_status); -} - -/** - * scic_sds_request_aborting_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST - * object. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_ABORTING state. none - */ -static void scic_sds_request_aborting_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - /* Setting the abort bit in the Task Context is required by the silicon. */ - sci_req->task_context_buffer->abort = 1; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_ABORTING - ); -} - -/** - * scic_sds_request_final_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This is cast into a SCIC_SDS_IO_REQUEST object. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the - * state handlers in place. none - */ -static void scic_sds_request_final_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_FINAL - ); -} - -static const struct sci_base_state scic_sds_request_state_table[] = { - [SCI_BASE_REQUEST_STATE_INITIAL] = { - .enter_state = scic_sds_request_initial_state_enter, - }, - [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { - .enter_state = scic_sds_request_constructed_state_enter, - }, - [SCI_BASE_REQUEST_STATE_STARTED] = { - .enter_state = scic_sds_request_started_state_enter, - .exit_state = scic_sds_request_started_state_exit - }, - [SCI_BASE_REQUEST_STATE_COMPLETED] = { - .enter_state = scic_sds_request_completed_state_enter, - }, - [SCI_BASE_REQUEST_STATE_ABORTING] = { - .enter_state = scic_sds_request_aborting_state_enter, - }, - [SCI_BASE_REQUEST_STATE_FINAL] = { - .enter_state = scic_sds_request_final_state_enter, - }, -}; - -static void scic_sds_general_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - u16 io_tag, struct scic_sds_request *sci_req) -{ - sci_base_state_machine_construct(&sci_req->state_machine, sci_req, - scic_sds_request_state_table, SCI_BASE_REQUEST_STATE_INITIAL); - sci_base_state_machine_start(&sci_req->state_machine); - - sci_req->io_tag = io_tag; - sci_req->owning_controller = scic; - sci_req->target_device = sci_dev; - sci_req->has_started_substate_machine = false; - sci_req->protocol = SCIC_NO_PROTOCOL; - sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; - sci_req->device_sequence = scic_sds_remote_device_get_sequence(sci_dev); - - sci_req->sci_status = SCI_SUCCESS; - sci_req->scu_status = 0; - sci_req->post_context = 0xFFFFFFFF; - - sci_req->is_task_management_request = false; - - if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { - sci_req->was_tag_assigned_by_user = false; - sci_req->task_context_buffer = NULL; - } else { - sci_req->was_tag_assigned_by_user = true; - - sci_req->task_context_buffer = - scic_sds_controller_get_task_context_buffer(scic, io_tag); - } -} - -enum sci_status -scic_io_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - u16 io_tag, struct scic_sds_request *sci_req) -{ - struct domain_device *dev = sci_dev_to_domain(sci_dev); - enum sci_status status = SCI_SUCCESS; - - /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); - - if (sci_dev->rnc.remote_node_index == - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) - return SCI_FAILURE_INVALID_REMOTE_DEVICE; - - if (dev->dev_type == SAS_END_DEV) - scic_sds_ssp_io_request_assign_buffers(sci_req); - else if ((dev->dev_type == SATA_DEV) || - (dev->tproto & SAS_PROTOCOL_STP)) { - scic_sds_stp_request_assign_buffers(sci_req); - memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); - } else if (dev_is_expander(dev)) { - scic_sds_smp_request_assign_buffers(sci_req); - memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); - } else - status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - - if (status == SCI_SUCCESS) { - memset(sci_req->task_context_buffer, 0, - offsetof(struct scu_task_context, sgl_pair_ab)); - } - - return status; -} - -enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - u16 io_tag, struct scic_sds_request *sci_req) -{ - struct domain_device *dev = sci_dev_to_domain(sci_dev); - enum sci_status status = SCI_SUCCESS; - - /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); - - if (dev->dev_type == SAS_END_DEV) { - scic_sds_ssp_task_request_assign_buffers(sci_req); - - sci_req->has_started_substate_machine = true; - - /* Construct the started sub-state machine. */ - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - sci_req, - scic_sds_io_request_started_task_mgmt_substate_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION - ); - } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) - scic_sds_stp_request_assign_buffers(sci_req); - else - status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - - if (status == SCI_SUCCESS) { - sci_req->is_task_management_request = true; - memset(sci_req->task_context_buffer, 0, sizeof(struct scu_task_context)); - } - - return status; -} diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h deleted file mode 100644 index a8d74a15a86b..000000000000 --- a/drivers/scsi/isci/core/scic_sds_request.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_IO_REQUEST_H_ -#define _SCIC_SDS_IO_REQUEST_H_ - -#include "isci.h" -#include "scic_io_request.h" -#include "state_machine.h" -#include "scu_task_context.h" -#include "scic_sds_stp_request.h" -#include "sas.h" - -struct scic_sds_controller; -struct scic_sds_remote_device; -struct scic_sds_io_request_state_handler; - -/** - * enum _scic_sds_io_request_started_task_mgmt_substates - This enumeration - * depicts all of the substates for a task management request to be - * performed in the STARTED super-state. - * - * - */ -enum scic_sds_raw_request_started_task_mgmt_substates { - /** - * The AWAIT_TC_COMPLETION sub-state indicates that the started raw - * task management request is waiting for the transmission of the - * initial frame (i.e. command, task, etc.). - */ - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, - - /** - * This sub-state indicates that the started task management request - * is waiting for the reception of an unsolicited frame - * (i.e. response IU). - */ - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, -}; - - -/** - * enum _scic_sds_smp_request_started_substates - This enumeration depicts all - * of the substates for a SMP request to be performed in the STARTED - * super-state. - * - * - */ -enum scic_sds_smp_request_started_substates { - /** - * This sub-state indicates that the started task management request - * is waiting for the reception of an unsolicited frame - * (i.e. response IU). - */ - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, - - /** - * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is - * waiting for the transmission of the initial frame (i.e. command, task, etc.). - */ - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, -}; - -struct scic_sds_request { - /** - * This field contains the information for the base request state machine. - */ - struct sci_base_state_machine state_machine; - - /** - * This field simply points to the controller to which this IO request - * is associated. - */ - struct scic_sds_controller *owning_controller; - - /** - * This field simply points to the remote device to which this IO request - * is associated. - */ - struct scic_sds_remote_device *target_device; - - /** - * This field is utilized to determine if the SCI user is managing - * the IO tag for this request or if the core is managing it. - */ - bool was_tag_assigned_by_user; - - /** - * This field indicates the IO tag for this request. The IO tag is - * comprised of the task_index and a sequence count. The sequence count - * is utilized to help identify tasks from one life to another. - */ - u16 io_tag; - - /** - * This field specifies the protocol being utilized for this - * IO request. - */ - SCIC_TRANSPORT_PROTOCOL protocol; - - /** - * This field indicates the completion status taken from the SCUs - * completion code. It indicates the completion result for the SCU hardware. - */ - u32 scu_status; - - /** - * This field indicates the completion status returned to the SCI user. It - * indicates the users view of the io request completion. - */ - u32 sci_status; - - /** - * This field contains the value to be utilized when posting (e.g. Post_TC, - * Post_TC_Abort) this request to the silicon. - */ - u32 post_context; - - struct scu_task_context *task_context_buffer; - struct scu_task_context tc ____cacheline_aligned; - - /* could be larger with sg chaining */ - #define SCU_SGL_SIZE ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) - struct scu_sgl_element_pair sg_table[SCU_SGL_SIZE] __attribute__ ((aligned(32))); - - /** - * This field indicates if this request is a task management request or - * normal IO request. - */ - bool is_task_management_request; - - /** - * This field indicates that this request contains an initialized started - * substate machine. - */ - bool has_started_substate_machine; - - /** - * This field is a pointer to the stored rx frame data. It is used in STP - * internal requests and SMP response frames. If this field is non-NULL the - * saved frame must be released on IO request completion. - * - * @todo In the future do we want to keep a list of RX frame buffers? - */ - u32 saved_rx_frame_index; - - /** - * This field specifies the data necessary to manage the sub-state - * machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state. - */ - struct sci_base_state_machine started_substate_machine; - - /** - * This field specifies the current state handlers in place for this - * IO Request object. This field is updated each time the request - * changes state. - */ - const struct scic_sds_io_request_state_handler *state_handlers; - - /** - * This field in the recorded device sequence for the io request. This is - * recorded during the build operation and is compared in the start - * operation. If the sequence is different then there was a change of - * devices from the build to start operations. - */ - u8 device_sequence; - - union { - struct { - union { - struct ssp_cmd_iu cmd; - struct ssp_task_iu tmf; - }; - union { - struct ssp_response_iu rsp; - u8 rsp_buf[SSP_RESP_IU_MAX_SIZE]; - }; - } ssp; - - struct { - struct smp_req cmd; - struct smp_resp rsp; - } smp; - - struct { - struct scic_sds_stp_request req; - struct host_to_dev_fis cmd; - struct dev_to_host_fis rsp; - } stp; - }; - -}; - -static inline struct scic_sds_request *to_sci_req(struct scic_sds_stp_request *stp_req) -{ - struct scic_sds_request *sci_req; - - sci_req = container_of(stp_req, typeof(*sci_req), stp.req); - return sci_req; -} - -/** - * enum sci_base_request_states - This enumeration depicts all the states for - * the common request state machine. - * - * - */ -enum sci_base_request_states { - /** - * Simply the initial state for the base request state machine. - */ - SCI_BASE_REQUEST_STATE_INITIAL, - - /** - * This state indicates that the request has been constructed. This state - * is entered from the INITIAL state. - */ - SCI_BASE_REQUEST_STATE_CONSTRUCTED, - - /** - * This state indicates that the request has been started. This state is - * entered from the CONSTRUCTED state. - */ - SCI_BASE_REQUEST_STATE_STARTED, - - /** - * This state indicates that the request has completed. - * This state is entered from the STARTED state. This state is entered from - * the ABORTING state. - */ - SCI_BASE_REQUEST_STATE_COMPLETED, - - /** - * This state indicates that the request is in the process of being - * terminated/aborted. - * This state is entered from the CONSTRUCTED state. - * This state is entered from the STARTED state. - */ - SCI_BASE_REQUEST_STATE_ABORTING, - - /** - * Simply the final state for the base request state machine. - */ - SCI_BASE_REQUEST_STATE_FINAL, -}; - -typedef enum sci_status (*scic_sds_io_request_handler_t) - (struct scic_sds_request *request); -typedef enum sci_status (*scic_sds_io_request_frame_handler_t) - (struct scic_sds_request *req, u32 frame); -typedef enum sci_status (*scic_sds_io_request_event_handler_t) - (struct scic_sds_request *req, u32 event); -typedef enum sci_status (*scic_sds_io_request_task_completion_handler_t) - (struct scic_sds_request *req, u32 completion_code); - -/** - * struct scic_sds_io_request_state_handler - This is the SDS core definition - * of the state handlers. - * - * - */ -struct scic_sds_io_request_state_handler { - /** - * The start_handler specifies the method invoked when a user attempts to - * start a request. - */ - scic_sds_io_request_handler_t start_handler; - - /** - * The abort_handler specifies the method invoked when a user attempts to - * abort a request. - */ - scic_sds_io_request_handler_t abort_handler; - - /** - * The complete_handler specifies the method invoked when a user attempts to - * complete a request. - */ - scic_sds_io_request_handler_t complete_handler; - - scic_sds_io_request_task_completion_handler_t tc_completion_handler; - scic_sds_io_request_event_handler_t event_handler; - scic_sds_io_request_frame_handler_t frame_handler; - -}; - -extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[]; - -/** - * scic_sds_request_get_controller() - - * - * This macro will return the controller for this io request object - */ -#define scic_sds_request_get_controller(sci_req) \ - ((sci_req)->owning_controller) - -/** - * scic_sds_request_get_device() - - * - * This macro will return the device for this io request object - */ -#define scic_sds_request_get_device(sci_req) \ - ((sci_req)->target_device) - -/** - * scic_sds_request_get_port() - - * - * This macro will return the port for this io request object - */ -#define scic_sds_request_get_port(sci_req) \ - scic_sds_remote_device_get_port(scic_sds_request_get_device(sci_req)) - -/** - * scic_sds_request_get_post_context() - - * - * This macro returns the constructed post context result for the io request. - */ -#define scic_sds_request_get_post_context(sci_req) \ - ((sci_req)->post_context) - -/** - * scic_sds_request_get_task_context() - - * - * This is a helper macro to return the os handle for this request object. - */ -#define scic_sds_request_get_task_context(request) \ - ((request)->task_context_buffer) - -/** - * scic_sds_request_set_status() - - * - * This macro will set the scu hardware status and sci request completion - * status for an io request. - */ -#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \ - { \ - (request)->scu_status = (scu_status_code); \ - (request)->sci_status = (sci_status_code); \ - } - -#define scic_sds_request_complete(a_request) \ - ((a_request)->state_handlers->complete_handler(a_request)) - - -extern enum sci_status -scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code); - -/** - * SCU_SGL_ZERO() - - * - * This macro zeros the hardware SGL element data - */ -#define SCU_SGL_ZERO(scu_sge) \ - { \ - (scu_sge).length = 0; \ - (scu_sge).address_lower = 0; \ - (scu_sge).address_upper = 0; \ - (scu_sge).address_modifier = 0; \ - } - -/** - * SCU_SGL_COPY() - - * - * This macro copys the SGL Element data from the host os to the hardware SGL - * elment data - */ -#define SCU_SGL_COPY(scu_sge, os_sge) \ - { \ - (scu_sge).length = sg_dma_len(sg); \ - (scu_sge).address_upper = \ - upper_32_bits(sg_dma_address(sg)); \ - (scu_sge).address_lower = \ - lower_32_bits(sg_dma_address(sg)); \ - (scu_sge).address_modifier = 0; \ - } - -/** - * scic_sds_request_get_user_request() - - * - * This is a helper macro to return the os handle for this request object. - */ -#define scic_sds_request_get_user_request(request) \ - ((request)->user_request) - -/* - * ***************************************************************************** - * * CORE REQUEST PROTOTYPES - * ***************************************************************************** */ - -void scic_sds_request_build_sgl( - struct scic_sds_request *sci_req); - - - -void scic_sds_stp_request_assign_buffers( - struct scic_sds_request *sci_req); - -void scic_sds_smp_request_assign_buffers( - struct scic_sds_request *sci_req); - -/* --------------------------------------------------------------------------- */ - -enum sci_status scic_sds_request_start( - struct scic_sds_request *sci_req); - -enum sci_status scic_sds_io_request_terminate( - struct scic_sds_request *sci_req); - -enum sci_status scic_sds_io_request_complete( - struct scic_sds_request *sci_req); - -void scic_sds_io_request_copy_response( - struct scic_sds_request *sci_req); - -enum sci_status scic_sds_io_request_event_handler( - struct scic_sds_request *sci_req, - u32 event_code); - -enum sci_status scic_sds_io_request_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index); - - -enum sci_status scic_sds_task_request_terminate( - struct scic_sds_request *sci_req); - -/* - * ***************************************************************************** - * * STARTED STATE HANDLERS - * ***************************************************************************** */ - -enum sci_status scic_sds_request_started_state_abort_handler( - struct scic_sds_request *sci_req); - -enum sci_status scic_sds_request_started_state_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code); - -#endif /* _SCIC_SDS_IO_REQUEST_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c deleted file mode 100644 index 6a2b65b9cf0f..000000000000 --- a/drivers/scsi/isci/core/scic_sds_smp_request.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "state_machine.h" -#include "remote_device.h" -#include "scic_sds_request.h" -#include "scic_sds_smp_request.h" -#include "sci_util.h" -#include "scu_completion_codes.h" -#include "scu_task_context.h" -#include "host.h" - -static void scu_smp_request_construct_task_context( - struct scic_sds_request *sci_req, - struct smp_req *smp_req); - -void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req) -{ - if (sci_req->was_tag_assigned_by_user == false) - sci_req->task_context_buffer = &sci_req->tc; -} - -/* - * This function will fill in the SCU Task Context for a SMP request. The - * following important settings are utilized: -# task_type == - * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type - * (i.e. non-raw frame) is being utilized to perform task management. -# - * control_frame == 1. This ensures that the proper endianess is set so - * that the bytes are transmitted in the right order for a smp request frame. - * @sci_req: This parameter specifies the smp request object being - * constructed. - * - */ -static void -scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, - struct smp_req *smp_req) -{ - dma_addr_t dma_addr; - struct scic_sds_controller *scic; - struct scic_sds_remote_device *sci_dev; - struct scic_sds_port *sci_port; - struct scu_task_context *task_context; - ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); - - /* byte swap the smp request. */ - sci_swab32_cpy(&sci_req->smp.cmd, smp_req, - word_cnt); - - task_context = scic_sds_request_get_task_context(sci_req); - - scic = scic_sds_request_get_controller(sci_req); - sci_dev = scic_sds_request_get_device(sci_req); - sci_port = scic_sds_request_get_port(sci_req); - - /* - * Fill in the TC with the its required data - * 00h - */ - task_context->priority = 0; - task_context->initiator_request = 1; - task_context->connection_rate = sci_dev->connection_rate; - task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(scic); - task_context->logical_port_index = scic_sds_port_get_index(sci_port); - task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; - task_context->abort = 0; - task_context->valid = SCU_TASK_CONTEXT_VALID; - task_context->context_type = SCU_TASK_CONTEXT_TYPE; - - /* 04h */ - task_context->remote_node_index = sci_dev->rnc.remote_node_index; - task_context->command_code = 0; - task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; - - /* 08h */ - task_context->link_layer_control = 0; - task_context->do_not_dma_ssp_good_response = 1; - task_context->strict_ordering = 0; - task_context->control_frame = 1; - task_context->timeout_enable = 0; - task_context->block_guard_enable = 0; - - /* 0ch */ - task_context->address_modifier = 0; - - /* 10h */ - task_context->ssp_command_iu_length = smp_req->req_len; - - /* 14h */ - task_context->transfer_length_bytes = 0; - - /* - * 18h ~ 30h, protocol specific - * since commandIU has been build by framework at this point, we just - * copy the frist DWord from command IU to this location. */ - memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); - - /* - * 40h - * "For SMP you could program it to zero. We would prefer that way - * so that done code will be consistent." - Venki - */ - task_context->task_phase = 0; - - if (sci_req->was_tag_assigned_by_user) { - /* - * Build the task context now since we have already read - * the data - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(scic) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(sci_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sci_req->io_tag)); - } else { - /* - * Build the task context now since we have already read - * the data. - * I/O tag index is not assigned because we have to wait - * until we get a TCi. - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(scic) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(sci_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); - } - - /* - * Copy the physical address for the command buffer to the SCU Task - * Context command buffer should not contain command header. - */ - dma_addr = scic_io_request_get_dma_addr(sci_req, - ((char *) &sci_req->smp.cmd) + - sizeof(u32)); - - task_context->command_iu_upper = upper_32_bits(dma_addr); - task_context->command_iu_lower = lower_32_bits(dma_addr); - - /* SMP response comes as UF, so no need to set response IU address. */ - task_context->response_iu_upper = 0; - task_context->response_iu_lower = 0; -} - -/* - * This function processes an unsolicited frame while the SMP request is waiting - * for a response frame. It will copy the response data, release the - * unsolicited frame, and transition the request to the - * SCI_BASE_REQUEST_STATE_COMPLETED state. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This function returns an indication of whether the response frame was handled - * successfully or not. SCI_SUCCESS Currently this value is always returned and - * indicates successful processing of the TC response. - */ -static enum sci_status -scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - void *frame_header; - struct smp_resp *rsp_hdr = &sci_req->smp.rsp; - ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); - - status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - &frame_header); - - /* byte swap the header. */ - sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); - - if (rsp_hdr->frame_type == SMP_RESPONSE) { - void *smp_resp; - - status = scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - &smp_resp); - - word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / - sizeof(u32); - - sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, - smp_resp, word_cnt); - - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); - } else { - /* This was not a response frame why did it get forwarded? */ - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC SMP Request 0x%p received unexpected frame " - "%d type 0x%02x\n", - __func__, - sci_req, - frame_index, - rsp_hdr->frame_type); - - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_SMP_FRM_TYPE_ERR, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - } - - scic_sds_controller_release_frame(sci_req->owning_controller, - frame_index); - - return SCI_SUCCESS; -} - - -/** - * This method processes an abnormal TC completion while the SMP request is - * waiting for a response frame. It decides what happened to the IO based - * on TC completion status. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - /* - * In the AWAIT RESPONSE state, any TC completion is unexpected. - * but if the TC has success status, we complete the IO anyway. */ - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): - /* - * These status has been seen in a specific LSI expander, which sometimes - * is not able to send smp response within 2 ms. This causes our hardware - * break the connection and set TC completion with one of these SMP_XXX_XX_ERR - * status. For these type of error, we ask scic user to retry the request. */ - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - - -/** - * This method processes the completions transport layer (TL) status to - * determine if the SMP request was sent successfully. If the SMP request - * was sent successfully, then the state for the SMP request transits to - * waiting for a response frame. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - - -static const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, - .frame_handler = scic_sds_smp_request_await_response_frame_handler, - }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, - } -}; - -/** - * This method performs the actions required when entering the - * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This - * includes setting the IO request state handlers for this sub-state. - * @object: This parameter specifies the request object for which the sub-state - * change is occurring. - * - * none. - */ -static void scic_sds_smp_request_started_await_response_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_smp_request_started_substate_handler_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE - ); -} - -/** - * This method performs the actions required when entering the - * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state. - * This includes setting the SMP request state handlers for this sub-state. - * @object: This parameter specifies the request object for which the sub-state - * change is occurring. - * - * none. - */ -static void scic_sds_smp_request_started_await_tc_completion_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_smp_request_started_substate_handler_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION - ); -} - -static const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .enter_state = scic_sds_smp_request_started_await_response_substate_enter, - }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, - }, -}; - -/** - * This method is called by the SCI user to build an SMP IO request. - * - * - The user must have previously called scic_io_request_construct() on the - * supplied IO request. Indicate if the controller successfully built the IO - * request. SCI_SUCCESS This value is returned if the IO request was - * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned - * if the remote_device does not support the SMP protocol. - * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not - * properly set the association between the SCIC IO request and the user's IO - * request. - */ -enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) -{ - struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); - - if (!smp_req) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - - sci_req->protocol = SCIC_SMP_PROTOCOL; - sci_req->has_started_substate_machine = true; - - /* Construct the started sub-state machine. */ - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - sci_req, - scic_sds_smp_request_started_substate_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE - ); - - /* Construct the SMP SCU Task Context */ - memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req)); - - /* - * Look at the SMP requests' header fields; for certain SAS 1.x SMP - * functions under SAS 2.0, a zero request length really indicates - * a non-zero default length. */ - if (smp_req->req_len == 0) { - switch (smp_req->func) { - case SMP_DISCOVER: - case SMP_REPORT_PHY_ERR_LOG: - case SMP_REPORT_PHY_SATA: - case SMP_REPORT_ROUTE_INFO: - smp_req->req_len = 2; - break; - case SMP_CONF_ROUTE_INFO: - case SMP_PHY_CONTROL: - case SMP_PHY_TEST_FUNCTION: - smp_req->req_len = 9; - break; - /* Default - zero is a valid default for 2.0. */ - } - } - - scu_smp_request_construct_task_context(sci_req, smp_req); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); - - kfree(smp_req); - - return SCI_SUCCESS; -} diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.h b/drivers/scsi/isci/core/scic_sds_smp_request.h deleted file mode 100644 index f432b7a182cd..000000000000 --- a/drivers/scsi/isci/core/scic_sds_smp_request.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _SCIC_SDS_SMP_REQUEST_T_ -#define _SCIC_SDS_SMP_REQUEST_T_ - -#include "scic_sds_request.h" - - -u32 scic_sds_smp_request_get_object_size(void); - - -void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); - -#endif /* _SCIC_SDS_SMP_REQUEST_T_ */ - diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c deleted file mode 100644 index 3fdf68be7a4d..000000000000 --- a/drivers/scsi/isci/core/scic_sds_ssp_request.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "host.h" -#include "state_machine.h" -#include "scic_sds_request.h" -#include "scu_completion_codes.h" -#include "scu_task_context.h" - -/** - * This method processes the completions transport layer (TL) status to - * determine if the RAW task management frame was sent successfully. If the - * raw frame was sent successfully, then the state for the task request - * transitions to waiting for a response frame. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE - ); - break; - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): - /* - * Currently, the decision is to simply allow the task request to - * timeout if the task IU wasn't received successfully. - * There is a potential for receiving multiple task responses if we - * decide to send the task IU again. */ - dev_warn(scic_to_dev(sci_req->owning_controller), - "%s: TaskRequest:0x%p CompletionCode:%x - " - "ACK/NAK timeout\n", - __func__, - sci_req, - completion_code); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - -/** - * This method is responsible for processing a terminate/abort request for this - * TC while the request is waiting for the task management response - * unsolicited frame. - * @sci_req: This parameter specifies the request for which the - * termination was requested. - * - * This method returns an indication as to whether the abort request was - * successfully handled. need to update to ensure the received UF doesn't cause - * damage to subsequent requests (i.e. put the extended tag in a holding - * pattern for this particular device). - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( - struct scic_sds_request *request) -{ - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - return SCI_SUCCESS; -} - -/** - * This method processes an unsolicited frame while the task mgmt request is - * waiting for a response frame. It will copy the response data, release - * the unsolicited frame, and transition the request to the - * SCI_BASE_REQUEST_STATE_COMPLETED state. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This method returns an indication of whether the TC response frame was - * handled successfully or not. SCI_SUCCESS Currently this value is always - * returned and indicates successful processing of the TC response. Should - * probably update to check frame type and make sure it is a response frame. - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - scic_sds_io_request_copy_response(request); - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - scic_sds_controller_release_frame(request->owning_controller, - frame_index); - return SCI_SUCCESS; -} - -static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, - }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, - .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, - } -}; - -/** - * This method performs the actions required when entering the - * SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION - * sub-state. This includes setting the IO request state handlers for this - * sub-state. - * @object: This parameter specifies the request object for which the sub-state - * change is occurring. - * - * none. - */ -static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_ssp_task_request_started_substate_handler_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION - ); -} - -/** - * This method performs the actions required when entering the - * SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This - * includes setting the IO request state handlers for this sub-state. - * @object: This parameter specifies the request object for which the sub-state - * change is occurring. - * - * none. - */ -static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_ssp_task_request_started_substate_handler_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE - ); -} - -const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = { - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, - }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, - }, -}; - diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h deleted file mode 100644 index e94d689e5103..000000000000 --- a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _SCIC_SDS_STP_PACKET_REQUEST_H_ -#define _SCIC_SDS_STP_PACKET_REQUEST_H_ - -#include "scic_sds_stp_request.h" - -/** - * This file contains the structures and constants for PACKET protocol requests. - * - * - */ - - -/** - * - * - * This is the enumeration of the SATA PIO DATA IN started substate machine. - */ -enum _scic_sds_stp_packet_request_started_substates { - /** - * While in this state the IO request object is waiting for the TC completion - * notification for the H2D Register FIS - */ - SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE, - - /** - * While in this state the IO request object is waiting for either a PIO Setup. - */ - SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE, - - /** - * While in this state the IO request object is waiting for TC completion for - * the Packet DMA DATA fis or Raw Frame. - */ - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE, - - /** - * The non-data IO transit to this state in this state after receiving TC - * completion. While in this state IO request object is waiting for D2H status - * frame as UF. - */ - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE, - - /** - * The IO transit to this state in this state if the previous TC completion status - * is not success and the atapi device is suspended due to target device failed the IO. - * While in this state IO request object is waiting for device coming out of the - * suspension state then complete the IO. - */ - SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE, -}; - -#define scic_sds_stp_packet_request_construct(request) SCI_FAILURE -#define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc) -#define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc) -#define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE -#define scic_sds_stp_packet_internal_request_sense_build_sgl(request) - -#endif /* _SCIC_SDS_STP_PACKET_REQUEST_H_ */ - diff --git a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h deleted file mode 100644 index e015a1114760..000000000000 --- a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_SATA_PIO_REQUEST_H_ -#define _SCIC_SDS_SATA_PIO_REQUEST_H_ - -#include "scic_sds_request.h" -#include "scu_task_context.h" - -/** - * This file contains the structures and constants for SATA PIO requests. - * - * - */ - - -/** - * - * - * This is the enumeration of the SATA PIO DATA IN started substate machine. - */ -enum _scic_sds_stp_request_started_pio_substates { - /** - * While in this state the IO request object is waiting for the TC completion - * notification for the H2D Register FIS - */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE, - - /** - * While in this state the IO request object is waiting for either a PIO Setup - * FIS or a D2H register FIS. The type of frame received is based on the - * result of the prior frame and line conditions. - */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE, - - /** - * While in this state the IO request object is waiting for a DATA frame from - * the device. - */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE, - - /** - * While in this state the IO request object is waiting to transmit the next data - * frame to the device. - */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, -}; - -struct scic_sds_stp_request; - - -#endif /* _SCIC_SDS_SATA_PIO_REQUEST_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c deleted file mode 100644 index 308f486514e9..000000000000 --- a/drivers/scsi/isci/core/scic_sds_stp_request.c +++ /dev/null @@ -1,1594 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "sas.h" -#include "state_machine.h" -#include "scic_io_request.h" -#include "remote_device.h" -#include "scic_sds_request.h" -#include "scic_sds_stp_pio_request.h" -#include "scic_sds_stp_request.h" -#include "unsolicited_frame_control.h" -#include "sci_util.h" -#include "scu_completion_codes.h" -#include "scu_event_codes.h" -#include "scu_task_context.h" -#include "request.h" - -void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) -{ - if (sci_req->was_tag_assigned_by_user == false) - sci_req->task_context_buffer = &sci_req->tc; -} - -/** - * This method is will fill in the SCU Task Context for any type of SATA - * request. This is called from the various SATA constructors. - * @sci_req: The general IO request object which is to be used in - * constructing the SCU task context. - * @task_context: The buffer pointer for the SCU task context which is being - * constructed. - * - * The general io request construction is complete. The buffer assignment for - * the command buffer is complete. none Revisit task context construction to - * determine what is common for SSP/SMP/STP task context structures. - */ -static void scu_sata_reqeust_construct_task_context( - struct scic_sds_request *sci_req, - struct scu_task_context *task_context) -{ - dma_addr_t dma_addr; - struct scic_sds_controller *controller; - struct scic_sds_remote_device *target_device; - struct scic_sds_port *target_port; - - controller = scic_sds_request_get_controller(sci_req); - target_device = scic_sds_request_get_device(sci_req); - target_port = scic_sds_request_get_port(sci_req); - - /* Fill in the TC with the its required data */ - task_context->abort = 0; - task_context->priority = SCU_TASK_PRIORITY_NORMAL; - task_context->initiator_request = 1; - task_context->connection_rate = target_device->connection_rate; - task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(controller); - task_context->logical_port_index = - scic_sds_port_get_index(target_port); - task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; - task_context->valid = SCU_TASK_CONTEXT_VALID; - task_context->context_type = SCU_TASK_CONTEXT_TYPE; - - task_context->remote_node_index = - scic_sds_remote_device_get_index(sci_req->target_device); - task_context->command_code = 0; - - task_context->link_layer_control = 0; - task_context->do_not_dma_ssp_good_response = 1; - task_context->strict_ordering = 0; - task_context->control_frame = 0; - task_context->timeout_enable = 0; - task_context->block_guard_enable = 0; - - task_context->address_modifier = 0; - task_context->task_phase = 0x01; - - task_context->ssp_command_iu_length = - (sizeof(struct host_to_dev_fis) - sizeof(u32)) / sizeof(u32); - - /* Set the first word of the H2D REG FIS */ - task_context->type.words[0] = *(u32 *)&sci_req->stp.cmd; - - if (sci_req->was_tag_assigned_by_user) { - /* - * Build the task context now since we have already read - * the data - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sci_req->io_tag)); - } else { - /* - * Build the task context now since we have already read - * the data. - * I/O tag index is not assigned because we have to wait - * until we get a TCi. - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); - } - - /* - * Copy the physical address for the command buffer to the SCU Task - * Context. We must offset the command buffer by 4 bytes because the - * first 4 bytes are transfered in the body of the TC. - */ - dma_addr = scic_io_request_get_dma_addr(sci_req, - ((char *) &sci_req->stp.cmd) + - sizeof(u32)); - - task_context->command_iu_upper = upper_32_bits(dma_addr); - task_context->command_iu_lower = lower_32_bits(dma_addr); - - /* SATA Requests do not have a response buffer */ - task_context->response_iu_upper = 0; - task_context->response_iu_lower = 0; -} - -/** - * - * @sci_req: - * - * This method will perform any general sata request construction. What part of - * SATA IO request construction is general? none - */ -static void scic_sds_stp_non_ncq_request_construct( - struct scic_sds_request *sci_req) -{ - sci_req->has_started_substate_machine = true; -} - -/** - * - * @sci_req: This parameter specifies the request to be constructed as an - * optimized request. - * @optimized_task_type: This parameter specifies whether the request is to be - * an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A - * value of 1 indicates NCQ. - * - * This method will perform request construction common to all types of STP - * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method - * returns an indication as to whether the construction was successful. - */ -static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sci_req, - u8 optimized_task_type, - u32 len, - enum dma_data_direction dir) -{ - struct scu_task_context *task_context = sci_req->task_context_buffer; - - /* Build the STP task context structure */ - scu_sata_reqeust_construct_task_context(sci_req, task_context); - - /* Copy over the SGL elements */ - scic_sds_request_build_sgl(sci_req); - - /* Copy over the number of bytes to be transfered */ - task_context->transfer_length_bytes = len; - - if (dir == DMA_TO_DEVICE) { - /* - * The difference between the DMA IN and DMA OUT request task type - * values are consistent with the difference between FPDMA READ - * and FPDMA WRITE values. Add the supplied task type parameter - * to this difference to set the task type properly for this - * DATA OUT (WRITE) case. */ - task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT - - SCU_TASK_TYPE_DMA_IN); - } else { - /* - * For the DATA IN (READ) case, simply save the supplied - * optimized task type. */ - task_context->task_type = optimized_task_type; - } -} - -/** - * - * @sci_req: This parameter specifies the request to be constructed. - * - * This method will construct the STP UDMA request and its associated TC data. - * This method returns an indication as to whether the construction was - * successful. SCI_SUCCESS Currently this method always returns this value. - */ -enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_req, - u32 len, - enum dma_data_direction dir) -{ - scic_sds_stp_optimized_request_construct(sci_req, - SCU_TASK_TYPE_FPDMAQ_READ, - len, dir); - return SCI_SUCCESS; -} - -/** - * scu_stp_raw_request_construct_task_context - - * @sci_req: This parameter specifies the STP request object for which to - * construct a RAW command frame task context. - * @task_context: This parameter specifies the SCU specific task context buffer - * to construct. - * - * This method performs the operations common to all SATA/STP requests - * utilizing the raw frame method. none - */ -static void scu_stp_raw_request_construct_task_context( - struct scic_sds_stp_request *stp_req, - struct scu_task_context *task_context) -{ - struct scic_sds_request *sci_req = to_sci_req(stp_req); - - scu_sata_reqeust_construct_task_context(sci_req, task_context); - - task_context->control_frame = 0; - task_context->priority = SCU_TASK_PRIORITY_NORMAL; - task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; - task_context->type.stp.fis_type = FIS_REGH2D; - task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32); -} - -void scic_stp_io_request_set_ncq_tag( - struct scic_sds_request *req, - u16 ncq_tag) -{ - /** - * @note This could be made to return an error to the user if the user - * attempts to set the NCQ tag in the wrong state. - */ - req->task_context_buffer->type.stp.ncq_tag = ncq_tag; -} - -/** - * - * @sci_req: - * - * Get the next SGL element from the request. - Check on which SGL element pair - * we are working - if working on SLG pair element A - advance to element B - - * else - check to see if there are more SGL element pairs for this IO request - * - if there are more SGL element pairs - advance to the next pair and return - * element A struct scu_sgl_element* - */ -static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) -{ - struct scu_sgl_element *current_sgl; - struct scic_sds_request *sci_req = to_sci_req(stp_req); - struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current; - - if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - if (pio_sgl->sgl_pair->B.address_lower == 0 && - pio_sgl->sgl_pair->B.address_upper == 0) { - current_sgl = NULL; - } else { - pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B; - current_sgl = &pio_sgl->sgl_pair->B; - } - } else { - if (pio_sgl->sgl_pair->next_pair_lower == 0 && - pio_sgl->sgl_pair->next_pair_upper == 0) { - current_sgl = NULL; - } else { - u64 phys_addr; - - phys_addr = pio_sgl->sgl_pair->next_pair_upper; - phys_addr <<= 32; - phys_addr |= pio_sgl->sgl_pair->next_pair_lower; - - pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr); - pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A; - current_sgl = &pio_sgl->sgl_pair->A; - } - } - - return current_sgl; -} - -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - -/** - * - * @request: This parameter specifies the request for which a frame has been - * received. - * @frame_index: This parameter specifies the index of the frame that has been - * received. - * - * This method processes frames received from the target while waiting for a - * device to host register FIS. If a non-register FIS is received during this - * time, it is treated as a protocol violation from an IO perspective. Indicate - * if the received frame was processed successfully. - */ -static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - - return status; - } - - switch (frame_header->fis_type) { - case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - /* The command has completed with error */ - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", __func__, stp_req, - frame_index); - - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); - break; - } - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, - } -}; - -static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_non_data_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req - ); -} - -static void scic_sds_stp_request_started_non_data_await_d2h_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_non_data_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE - ); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter, - }, -}; - -enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req) -{ - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - scic_sds_stp_non_ncq_request_construct(sci_req); - - /* Build the STP task context structure */ - scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); - - sci_base_state_machine_construct(&sci_req->started_substate_machine, - sci_req, - scic_sds_stp_request_started_non_data_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE); - - return SCI_SUCCESS; -} - -#define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ - -/* transmit DATA_FIS from (current sgl + offset) for input - * parameter length. current sgl and offset is alreay stored in the IO request - */ -static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( - struct scic_sds_request *sci_req, - u32 length) -{ - struct scic_sds_controller *scic = sci_req->owning_controller; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scu_task_context *task_context; - struct scu_sgl_element *current_sgl; - - /* Recycle the TC and reconstruct it for sending out DATA FIS containing - * for the data from current_sgl+offset for the input length - */ - task_context = scic_sds_controller_get_task_context_buffer(scic, - sci_req->io_tag); - - if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) - current_sgl = &stp_req->type.pio.request_current.sgl_pair->A; - else - current_sgl = &stp_req->type.pio.request_current.sgl_pair->B; - - /* update the TC */ - task_context->command_iu_upper = current_sgl->address_upper; - task_context->command_iu_lower = current_sgl->address_lower; - task_context->transfer_length_bytes = length; - task_context->type.stp.fis_type = FIS_DATA; - - /* send the new TC out. */ - return scic_controller_continue_io(sci_req); -} - -static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct scic_sds_request *sci_req) -{ - - struct scu_sgl_element *current_sgl; - u32 sgl_offset; - u32 remaining_bytes_in_current_sgl = 0; - enum sci_status status = SCI_SUCCESS; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - sgl_offset = stp_req->type.pio.request_current.sgl_offset; - - if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A); - remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->A.length - sgl_offset; - } else { - current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B); - remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->B.length - sgl_offset; - } - - - if (stp_req->type.pio.pio_transfer_bytes > 0) { - if (stp_req->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { - /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ - status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, remaining_bytes_in_current_sgl); - if (status == SCI_SUCCESS) { - stp_req->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; - - /* update the current sgl, sgl_offset and save for future */ - current_sgl = scic_sds_stp_request_pio_get_next_sgl(stp_req); - sgl_offset = 0; - } - } else if (stp_req->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { - /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */ - scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->type.pio.pio_transfer_bytes); - - if (status == SCI_SUCCESS) { - /* Sgl offset will be adjusted and saved for future */ - sgl_offset += stp_req->type.pio.pio_transfer_bytes; - current_sgl->address_lower += stp_req->type.pio.pio_transfer_bytes; - stp_req->type.pio.pio_transfer_bytes = 0; - } - } - } - - if (status == SCI_SUCCESS) { - stp_req->type.pio.request_current.sgl_offset = sgl_offset; - } - - return status; -} - -/** - * - * @stp_request: The request that is used for the SGL processing. - * @data_buffer: The buffer of data to be copied. - * @length: The length of the data transfer. - * - * Copy the data from the buffer for the length specified to the IO reqeust SGL - * specified data region. enum sci_status - */ -static enum sci_status -scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req, - u8 *data_buf, u32 len) -{ - struct scic_sds_request *sci_req; - struct isci_request *ireq; - u8 *src_addr; - int copy_len; - struct sas_task *task; - struct scatterlist *sg; - void *kaddr; - int total_len = len; - - sci_req = to_sci_req(stp_req); - ireq = sci_req_to_ireq(sci_req); - task = isci_request_access_task(ireq); - src_addr = data_buf; - - if (task->num_scatter > 0) { - sg = task->scatter; - - while (total_len > 0) { - struct page *page = sg_page(sg); - - copy_len = min_t(int, total_len, sg_dma_len(sg)); - kaddr = kmap_atomic(page, KM_IRQ0); - memcpy(kaddr + sg->offset, src_addr, copy_len); - kunmap_atomic(kaddr, KM_IRQ0); - total_len -= copy_len; - src_addr += copy_len; - sg = sg_next(sg); - } - } else { - BUG_ON(task->total_xfer_len < total_len); - memcpy(task->scatter, src_addr, total_len); - } - - return SCI_SUCCESS; -} - -/** - * - * @sci_req: The PIO DATA IN request that is to receive the data. - * @data_buffer: The buffer to copy from. - * - * Copy the data buffer to the io request data region. enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( - struct scic_sds_stp_request *sci_req, - u8 *data_buffer) -{ - enum sci_status status; - - /* - * If there is less than 1K remaining in the transfer request - * copy just the data for the transfer */ - if (sci_req->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { - status = scic_sds_stp_request_pio_data_in_copy_data_buffer( - sci_req, data_buffer, sci_req->type.pio.pio_transfer_bytes); - - if (status == SCI_SUCCESS) - sci_req->type.pio.pio_transfer_bytes = 0; - } else { - /* We are transfering the whole frame so copy */ - status = scic_sds_stp_request_pio_data_in_copy_data_buffer( - sci_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); - - if (status == SCI_SUCCESS) - sci_req->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; - } - - return status; -} - -/** - * - * @sci_req: - * @completion_code: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - break; - } - - return status; -} - -static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - struct scic_sds_controller *scic = sci_req->owning_controller; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(ireq); - struct dev_to_host_fis *frame_header; - enum sci_status status; - u32 *frame_buffer; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - - switch (frame_header->fis_type) { - case FIS_PIO_SETUP: - /* Get from the frame buffer the PIO Setup Data */ - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - /* Get the data from the PIO Setup The SCU Hardware returns - * first word in the frame_header and the rest of the data is in - * the frame buffer so we need to back up one dword - */ - - /* transfer_count: first 16bits in the 4th dword */ - stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff; - - /* ending_status: 4th byte in the 3rd dword */ - stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - sci_req->stp.rsp.status = stp_req->type.pio.ending_status; - - /* The next state is dependent on whether the - * request was PIO Data-in or Data out - */ - if (task->data_dir == DMA_FROM_DEVICE) { - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); - } else if (task->data_dir == DMA_TO_DEVICE) { - /* Transmit data */ - status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); - if (status != SCI_SUCCESS) - break; - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); - } - break; - case FIS_SETDEVBITS: - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); - break; - case FIS_REGD2H: - if (frame_header->status & ATA_BUSY) { - /* Now why is the drive sending a D2H Register FIS when - * it is still busy? Do nothing since we are still in - * the right state. - */ - dev_dbg(scic_to_dev(scic), - "%s: SCIC PIO Request 0x%p received " - "D2H Register FIS with BSY status " - "0x%x\n", __func__, stp_req, - frame_header->status); - break; - } - - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.req, - frame_header, - frame_buffer); - - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - default: - /* FIXME: what do we do here? */ - break; - } - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - struct sata_fis_data *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - - if (frame_header->fis_type == FIS_DATA) { - if (stp_req->type.pio.request_current.sgl_pair == NULL) { - sci_req->saved_rx_frame_index = frame_index; - stp_req->type.pio.pio_transfer_bytes = 0; - } else { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - status = scic_sds_stp_request_pio_data_in_copy_data(stp_req, - (u8 *)frame_buffer); - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - } - - /* Check for the end of the transfer, are there more - * bytes remaining for this data transfer - */ - if (status != SCI_SUCCESS || - stp_req->type.pio.pio_transfer_bytes != 0) - return status; - - if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) { - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - } else { - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); - } - } else { - dev_err(scic_to_dev(scic), - "%s: SCIC PIO Request 0x%p received frame %d " - "with fis type 0x%02x when expecting a data " - "fis.\n", __func__, stp_req, frame_index, - frame_header->fis_type); - - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_GOOD, - SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - } - - return status; -} - - -/** - * - * @sci_req: - * @completion_code: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( - - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - bool all_frames_transferred = false; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - /* Transmit data */ - if (stp_req->type.pio.pio_transfer_bytes != 0) { - status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); - if (status == SCI_SUCCESS) { - if (stp_req->type.pio.pio_transfer_bytes == 0) - all_frames_transferred = true; - } - } else if (stp_req->type.pio.pio_transfer_bytes == 0) { - /* - * this will happen if the all data is written at the - * first time after the pio setup fis is received - */ - all_frames_transferred = true; - } - - /* all data transferred. */ - if (all_frames_transferred) { - /* - * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE - * and wait for PIO_SETUP fis / or D2H REg fis. */ - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); - } - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - break; - } - - return status; -} - -/** - * - * @request: This is the request which is receiving the event. - * @event_code: This is the event code that the request on which the request is - * expected to take action. - * - * This method will handle any link layer events while waiting for the data - * frame. enum sci_status SCI_SUCCESS SCI_FAILURE - */ -static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler( - struct scic_sds_request *request, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_specifier(event_code)) { - case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: - /* - * We are waiting for data and the SCU has R_ERR the data frame. - * Go back to waiting for the D2H Register FIS */ - sci_base_state_machine_change_state( - &request->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); - - status = SCI_SUCCESS; - break; - - default: - dev_err(scic_to_dev(request->owning_controller), - "%s: SCIC PIO Request 0x%p received unexpected " - "event 0x%08x\n", - __func__, request, event_code); - - /* / @todo Should we fail the PIO request when we get an unexpected event? */ - status = SCI_FAILURE; - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, - .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, - } -}; - -static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_pio_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req); -} - -static void scic_sds_stp_request_started_pio_await_frame_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_pio_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); -} - -static void scic_sds_stp_request_started_pio_data_in_await_data_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_pio_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE - ); -} - -static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_pio_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE - ); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_await_frame_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter, - } -}; - -enum sci_status -scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, - bool copy_rx_frame) -{ - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; - - scic_sds_stp_non_ncq_request_construct(sci_req); - - scu_stp_raw_request_construct_task_context(stp_req, - sci_req->task_context_buffer); - - pio->current_transfer_bytes = 0; - pio->ending_error = 0; - pio->ending_status = 0; - - pio->request_current.sgl_offset = 0; - pio->request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; - - if (copy_rx_frame) { - scic_sds_request_build_sgl(sci_req); - /* Since the IO request copy of the TC contains the same data as - * the actual TC this pointer is vaild for either. - */ - pio->request_current.sgl_pair = &sci_req->task_context_buffer->sgl_pair_ab; - } else { - /* The user does not want the data copied to the SGL buffer location */ - pio->request_current.sgl_pair = NULL; - } - - sci_base_state_machine_construct(&sci_req->started_substate_machine, - sci_req, - scic_sds_stp_request_started_pio_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE); - - return SCI_SUCCESS; -} - -static void scic_sds_stp_request_udma_complete_request( - struct scic_sds_request *request, - u32 scu_status, - enum sci_status sci_status) -{ - scic_sds_request_set_status(request, scu_status, sci_status); - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); -} - -static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - struct scic_sds_controller *scic = sci_req->owning_controller; - struct dev_to_host_fis *frame_header; - enum sci_status status; - u32 *frame_buffer; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if ((status == SCI_SUCCESS) && - (frame_header->fis_type == FIS_REGD2H)) { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - } - - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - break; - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): - /* - * We must check ther response buffer to see if the D2H Register FIS was - * received before we got the TC completion. */ - if (sci_req->stp.rsp.fis_type == FIS_REGD2H) { - scic_sds_remote_device_suspend(sci_req->target_device, - SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); - - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - } else { - /* - * If we have an error completion status for the TC then we can expect a - * D2H register FIS from the device so we must change state to wait for it */ - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE); - } - break; - - /* - * / @todo Check to see if any of these completion status need to wait for - * / the device to host register fis. */ - /* / @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 */ - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): - scic_sds_remote_device_suspend(sci_req->target_device, - SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); - /* Fall through to the default case */ - default: - /* All other completion status cause the IO to be complete. */ - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - break; - } - - return status; -} - -static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - - /* Use the general frame handler to copy the resposne data */ - status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); - - if (status != SCI_SUCCESS) - return status; - - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, - .frame_handler = scic_sds_stp_request_udma_general_frame_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, - }, -}; - -static void scic_sds_stp_request_started_udma_await_tc_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_udma_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE - ); -} - -/** - * - * - * This state is entered when there is an TC completion failure. The hardware - * received an unexpected condition while processing the IO request and now - * will UF the D2H register FIS to complete the IO. - */ -static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_udma_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE - ); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter, - }, -}; - -enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, - u32 len, - enum dma_data_direction dir) -{ - scic_sds_stp_non_ncq_request_construct(sci_req); - - scic_sds_stp_optimized_request_construct(sci_req, SCU_TASK_TYPE_DMA_IN, - len, dir); - - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - sci_req, - scic_sds_stp_request_started_udma_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE - ); - - return SCI_SUCCESS; -} - -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - -/** - * - * @request: This parameter specifies the request for which a frame has been - * received. - * @frame_index: This parameter specifies the index of the frame that has been - * received. - * - * This method processes frames received from the target while waiting for a - * device to host register FIS. If a non-register FIS is received during this - * time, it is treated as a protocol violation from an IO perspective. Indicate - * if the received frame was processed successfully. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - - switch (frame_header->fis_type) { - case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - /* The command has completed with error */ - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", __func__, stp_req, - frame_index); - - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); - break; - } - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, - }, -}; - -static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_soft_reset_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req - ); -} - -static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - struct scu_task_context *task_context; - struct host_to_dev_fis *h2d_fis; - enum sci_status status; - - /* Clear the SRST bit */ - h2d_fis = &sci_req->stp.cmd; - h2d_fis->control = 0; - - /* Clear the TC control bit */ - task_context = scic_sds_controller_get_task_context_buffer( - sci_req->owning_controller, sci_req->io_tag); - task_context->control_frame = 0; - - status = scic_controller_continue_io(sci_req); - if (status == SCI_SUCCESS) { - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_soft_reset_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE - ); - } -} - -static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_soft_reset_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE - ); -} - -static const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter, - }, -}; - -enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req) -{ - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - scic_sds_stp_non_ncq_request_construct(sci_req); - - /* Build the STP task context structure */ - scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); - - sci_base_state_machine_construct(&sci_req->started_substate_machine, - sci_req, - scic_sds_stp_request_started_soft_reset_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE); - - return SCI_SUCCESS; -} diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h deleted file mode 100644 index f5434f12ad06..000000000000 --- a/drivers/scsi/isci/core/scic_sds_stp_request.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_STP_REQUEST_T_ -#define _SCIC_SDS_STP_REQUEST_T_ - -#include -#include - -struct scic_sds_stp_request { - union { - u32 ncq; - - u32 udma; - - struct scic_sds_stp_pio_request { - /** - * Total transfer for the entire PIO request recorded at request constuction - * time. - * - * @todo Should we just decrement this value for each byte of data transitted - * or received to elemenate the current_transfer_bytes field? - */ - u32 total_transfer_bytes; - - /** - * Total number of bytes received/transmitted in data frames since the start - * of the IO request. At the end of the IO request this should equal the - * total_transfer_bytes. - */ - u32 current_transfer_bytes; - - /** - * The number of bytes requested in the in the PIO setup. - */ - u32 pio_transfer_bytes; - - /** - * PIO Setup ending status value to tell us if we need to wait for another FIS - * or if the transfer is complete. On the receipt of a D2H FIS this will be - * the status field of that FIS. - */ - u8 ending_status; - - /** - * On receipt of a D2H FIS this will be the ending error field if the - * ending_status has the SATA_STATUS_ERR bit set. - */ - u8 ending_error; - - struct scic_sds_request_pio_sgl { - struct scu_sgl_element_pair *sgl_pair; - u8 sgl_set; - u32 sgl_offset; - } request_current; - } pio; - - struct { - /** - * The number of bytes requested in the PIO setup before CDB data frame. - */ - u32 device_preferred_cdb_length; - } packet; - } type; -}; - -/** - * enum scic_sds_stp_request_started_udma_substates - This enumeration depicts - * the various sub-states associated with a SATA/STP UDMA protocol operation. - * - * - */ -enum scic_sds_stp_request_started_udma_substates { - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, -}; - -/** - * enum scic_sds_stp_request_started_non_data_substates - This enumeration - * depicts the various sub-states associated with a SATA/STP non-data - * protocol operation. - * - * - */ -enum scic_sds_stp_request_started_non_data_substates { - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, -}; - -/** - * enum scic_sds_stp_request_started_soft_reset_substates - THis enumeration - * depicts the various sub-states associated with a SATA/STP soft reset - * operation. - * - * - */ -enum scic_sds_stp_request_started_soft_reset_substates { - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, -}; - -u32 scic_sds_stp_request_get_object_size(void); - -enum sci_status scic_sds_stp_pio_request_construct( - struct scic_sds_request *scic_io_request, - bool copy_rx_frame); - -enum sci_status scic_sds_stp_udma_request_construct( - struct scic_sds_request *sci_req, - u32 transfer_length, - enum dma_data_direction dir); - -enum sci_status scic_sds_stp_non_data_request_construct( - struct scic_sds_request *sci_req); - -enum sci_status scic_sds_stp_soft_reset_request_construct( - struct scic_sds_request *sci_req); - -enum sci_status scic_sds_stp_ncq_request_construct( - struct scic_sds_request *sci_req, - u32 transfer_length, - enum dma_data_direction dir); - - -#endif /* _SCIC_SDS_STP_REQUEST_T_ */ diff --git a/drivers/scsi/isci/core/scic_task_request.h b/drivers/scsi/isci/core/scic_task_request.h deleted file mode 100644 index 790cee9b4af6..000000000000 --- a/drivers/scsi/isci/core/scic_task_request.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_TASK_REQUEST_H_ -#define _SCIC_TASK_REQUEST_H_ - -#include "isci.h" - -struct scic_sds_request; -struct scic_sds_remote_device; -struct scic_sds_controller; - - -enum sci_status scic_task_request_construct( - struct scic_sds_controller *scic_controller, - struct scic_sds_remote_device *scic_remote_device, - u16 io_tag, struct scic_sds_request *sci_req); - -/** - * scic_task_request_construct_ssp() - This method is called by the SCI user to - * construct all SCI Core SSP task management requests. Memory - * initialization and functionality common to all task request types is - * performed in this method. - * @scic_task_request: This parameter specifies the handle to the core task - * request object for which to construct a SATA specific task management - * request. - * - * Indicate if the controller successfully built the task request. SCI_SUCCESS - * This value is returned if the task request was successfully built. - */ -enum sci_status scic_task_request_construct_ssp( - struct scic_sds_request *scic_task_request); - -/** - * scic_task_request_construct_sata() - This method is called by the SCI user - * to construct all SCI Core SATA task management requests. Memory - * initialization and functionality common to all task request types is - * performed in this method. - * @scic_task_request_handle: This parameter specifies the handle to the core - * task request object for which to construct a SATA specific task - * management request. - * - * Indicate if the controller successfully built the task request. SCI_SUCCESS - * This value is returned if the task request was successfully built. - */ -enum sci_status scic_task_request_construct_sata( - struct scic_sds_request *scic_task_request_handle); - - - -#endif /* _SCIC_TASK_REQUEST_H_ */ - diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 71a0466d1c8e..e1930da08d4e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -61,9 +61,7 @@ #include "probe_roms.h" #include "remote_device.h" #include "request.h" -#include "scic_io_request.h" #include "scic_sds_port_configuration_agent.h" -#include "sci_util.h" #include "scu_completion_codes.h" #include "scu_event_codes.h" #include "registers.h" diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index d288897b85fb..69826eac97b5 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -521,6 +521,25 @@ enum sci_task_status { }; +/** + * sci_swab32_cpy - convert between scsi and scu-hardware byte format + * @dest: receive the 4-byte endian swapped version of src + * @src: word aligned source buffer + * + * scu hardware handles SSP/SMP control, response, and unidentified + * frames in "big endian dword" order. Regardless of host endian this + * is always a swab32()-per-dword conversion of the standard definition, + * i.e. single byte fields swapped and multi-byte fields in little- + * endian + */ +static inline void sci_swab32_cpy(void *_dest, void *_src, ssize_t word_cnt) +{ + u32 *dest = _dest, *src = _src; + + while (--word_cnt >= 0) + dest[word_cnt] = swab32(src[word_cnt]); +} + extern unsigned char no_outbound_task_to; extern u16 ssp_max_occ_to; extern u16 stp_max_occ_to; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index f44fa20cad96..d4bf6d2d8c9b 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -55,7 +55,6 @@ #include #include "isci.h" -#include "scic_io_request.h" #include "scic_phy.h" #include "scic_sds_phy.h" #include "scic_port.h" diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 00334b9ccd80..23390102514f 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -57,14 +57,11 @@ #include "port.h" #include "remote_device.h" #include "request.h" -#include "scic_io_request.h" #include "scic_phy.h" #include "scic_port.h" #include "scic_sds_phy.h" #include "scic_sds_port.h" #include "remote_node_context.h" -#include "scic_sds_request.h" -#include "sci_util.h" #include "scu_event_codes.h" #include "task.h" diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 5891f3d50177..35231e7407b1 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -58,7 +58,6 @@ #include "scic_sds_port.h" #include "remote_device.h" #include "remote_node_context.h" -#include "sci_util.h" #include "scu_event_codes.h" #include "scu_task_context.h" diff --git a/drivers/scsi/isci/remote_node_table.c b/drivers/scsi/isci/remote_node_table.c index 80f44c25f45f..6b9465a5a217 100644 --- a/drivers/scsi/isci/remote_node_table.c +++ b/drivers/scsi/isci/remote_node_table.c @@ -59,7 +59,6 @@ * * */ -#include "sci_util.h" #include "remote_node_table.h" #include "remote_node_context.h" diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 4961ee347091..857ad067f11c 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -54,898 +54,1286 @@ */ #include "isci.h" -#include "scic_io_request.h" -#include "scic_task_request.h" #include "scic_port.h" #include "task.h" #include "request.h" #include "sata.h" #include "scu_completion_codes.h" -#include "scic_sds_request.h" #include "sas.h" -static enum sci_status isci_request_ssp_request_construct( - struct isci_request *request) -{ - enum sci_status status; +/** + * This method returns the sgl element pair for the specificed sgl_pair index. + * @sci_req: This parameter specifies the IO request for which to retrieve + * the Scatter-Gather List element pair. + * @sgl_pair_index: This parameter specifies the index into the SGL element + * pair to be retrieved. + * + * This method returns a pointer to an struct scu_sgl_element_pair. + */ +static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( + struct scic_sds_request *sci_req, + u32 sgl_pair_index + ) { + struct scu_task_context *task_context; + + task_context = (struct scu_task_context *)sci_req->task_context_buffer; + + if (sgl_pair_index == 0) { + return &task_context->sgl_pair_ab; + } else if (sgl_pair_index == 1) { + return &task_context->sgl_pair_cd; + } - dev_dbg(&request->isci_host->pdev->dev, - "%s: request = %p\n", - __func__, - request); - status = scic_io_request_construct_basic_ssp(&request->sci); - return status; + return &sci_req->sg_table[sgl_pair_index - 2]; } -static enum sci_status isci_request_stp_request_construct( - struct isci_request *request) +/** + * This function will build the SGL list for an IO request. + * @sci_req: This parameter specifies the IO request for which to build + * the Scatter-Gather List. + * + */ +void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) { - struct sas_task *task = isci_request_access_task(request); - enum sci_status status; - struct host_to_dev_fis *register_fis; - - dev_dbg(&request->isci_host->pdev->dev, - "%s: request = %p\n", - __func__, - request); + struct isci_request *isci_request = sci_req_to_ireq(sds_request); + struct isci_host *isci_host = isci_request->isci_host; + struct sas_task *task = isci_request_access_task(isci_request); + struct scatterlist *sg = NULL; + dma_addr_t dma_addr; + u32 sg_idx = 0; + struct scu_sgl_element_pair *scu_sg = NULL; + struct scu_sgl_element_pair *prev_sg = NULL; + + if (task->num_scatter > 0) { + sg = task->scatter; + + while (sg) { + scu_sg = scic_sds_request_get_sgl_element_pair( + sds_request, + sg_idx); + + SCU_SGL_COPY(scu_sg->A, sg); + + sg = sg_next(sg); + + if (sg) { + SCU_SGL_COPY(scu_sg->B, sg); + sg = sg_next(sg); + } else + SCU_SGL_ZERO(scu_sg->B); + + if (prev_sg) { + dma_addr = + scic_io_request_get_dma_addr( + sds_request, + scu_sg); + + prev_sg->next_pair_upper = + upper_32_bits(dma_addr); + prev_sg->next_pair_lower = + lower_32_bits(dma_addr); + } + + prev_sg = scu_sg; + sg_idx++; + } + } else { /* handle when no sg */ + scu_sg = scic_sds_request_get_sgl_element_pair(sds_request, + sg_idx); - /* Get the host_to_dev_fis from the core and copy - * the fis from the task into it. - */ - register_fis = isci_sata_task_to_fis_copy(task); + dma_addr = dma_map_single(&isci_host->pdev->dev, + task->scatter, + task->total_xfer_len, + task->data_dir); - status = scic_io_request_construct_basic_sata(&request->sci); + isci_request->zero_scatter_daddr = dma_addr; - /* Set the ncq tag in the fis, from the queue - * command in the task. - */ - if (isci_sata_is_task_ncq(task)) { + scu_sg->A.length = task->total_xfer_len; + scu_sg->A.address_upper = upper_32_bits(dma_addr); + scu_sg->A.address_lower = lower_32_bits(dma_addr); + } - isci_sata_set_ncq_tag( - register_fis, - task - ); + if (scu_sg) { + scu_sg->next_pair_upper = 0; + scu_sg->next_pair_lower = 0; } +} - return status; +static void scic_sds_ssp_io_request_assign_buffers(struct scic_sds_request *sci_req) +{ + if (sci_req->was_tag_assigned_by_user == false) + sci_req->task_context_buffer = &sci_req->tc; } -/* - * isci_smp_request_build() - This function builds the smp request. - * @ireq: This parameter points to the isci_request allocated in the - * request construct function. - * - * SCI_SUCCESS on successfull completion, or specific failure code. - */ -static enum sci_status isci_smp_request_build(struct isci_request *ireq) +static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) { - enum sci_status status = SCI_FAILURE; + struct ssp_cmd_iu *cmd_iu; + struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); - struct scic_sds_request *sci_req = &ireq->sci; - dev_dbg(&ireq->isci_host->pdev->dev, - "%s: request = %p\n", __func__, ireq); + cmd_iu = &sci_req->ssp.cmd; - dev_dbg(&ireq->isci_host->pdev->dev, - "%s: smp_req len = %d\n", - __func__, - task->smp_task.smp_req.length); + memcpy(cmd_iu->LUN, task->ssp_task.LUN, 8); + cmd_iu->add_cdb_len = 0; + cmd_iu->_r_a = 0; + cmd_iu->_r_b = 0; + cmd_iu->en_fburst = 0; /* unsupported */ + cmd_iu->task_prio = task->ssp_task.task_prio; + cmd_iu->task_attr = task->ssp_task.task_attr; + cmd_iu->_r_c = 0; - /* copy the smp_command to the address; */ - sg_copy_to_buffer(&task->smp_task.smp_req, 1, - &sci_req->smp.cmd, - sizeof(struct smp_req)); + sci_swab32_cpy(&cmd_iu->cdb, task->ssp_task.cdb, + sizeof(task->ssp_task.cdb) / sizeof(u32)); +} - status = scic_io_request_construct_smp(sci_req); - if (status != SCI_SUCCESS) - dev_warn(&ireq->isci_host->pdev->dev, - "%s: failed with status = %d\n", - __func__, - status); +static void scic_sds_task_request_build_ssp_task_iu(struct scic_sds_request *sci_req) +{ + struct ssp_task_iu *task_iu; + struct isci_request *ireq = sci_req_to_ireq(sci_req); + struct sas_task *task = isci_request_access_task(ireq); + struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - return status; + task_iu = &sci_req->ssp.tmf; + + memset(task_iu, 0, sizeof(struct ssp_task_iu)); + + memcpy(task_iu->LUN, task->ssp_task.LUN, 8); + + task_iu->task_func = isci_tmf->tmf_code; + task_iu->task_tag = + (ireq->ttype == tmf_task) ? + isci_tmf->io_tag : + SCI_CONTROLLER_INVALID_IO_TAG; } /** - * isci_io_request_build() - This function builds the io request object. - * @isci_host: This parameter specifies the ISCI host object - * @request: This parameter points to the isci_request object allocated in the - * request construct function. - * @sci_device: This parameter is the handle for the sci core's remote device - * object that is the destination for this request. + * This method is will fill in the SCU Task Context for any type of SSP request. + * @sci_req: + * @task_context: * - * SCI_SUCCESS on successfull completion, or specific failure code. */ -static enum sci_status isci_io_request_build( - struct isci_host *isci_host, - struct isci_request *request, - struct isci_remote_device *isci_device) +static void scu_ssp_reqeust_construct_task_context( + struct scic_sds_request *sds_request, + struct scu_task_context *task_context) { - enum sci_status status = SCI_SUCCESS; - struct sas_task *task = isci_request_access_task(request); - struct scic_sds_remote_device *sci_device = &isci_device->sci; + dma_addr_t dma_addr; + struct scic_sds_controller *controller; + struct scic_sds_remote_device *target_device; + struct scic_sds_port *target_port; + + controller = scic_sds_request_get_controller(sds_request); + target_device = scic_sds_request_get_device(sds_request); + target_port = scic_sds_request_get_port(sds_request); + + /* Fill in the TC with the its required data */ + task_context->abort = 0; + task_context->priority = 0; + task_context->initiator_request = 1; + task_context->connection_rate = target_device->connection_rate; + task_context->protocol_engine_index = + scic_sds_controller_get_protocol_engine_group(controller); + task_context->logical_port_index = + scic_sds_port_get_index(target_port); + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + task_context->remote_node_index = + scic_sds_remote_device_get_index(sds_request->target_device); + task_context->command_code = 0; + + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 0; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + task_context->address_modifier = 0; + + /* task_context->type.ssp.tag = sci_req->io_tag; */ + task_context->task_phase = 0x01; + + if (sds_request->was_tag_assigned_by_user) { + /* + * Build the task context now since we have already read + * the data + */ + sds_request->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + scic_sds_io_tag_get_index(sds_request->io_tag)); + } else { + /* + * Build the task context now since we have already read + * the data + * + * I/O tag index is not assigned because we have to wait + * until we get a TCi + */ + sds_request->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + owning_controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); + } - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = 0x%p; request = %p, " - "num_scatter = %d\n", - __func__, - isci_device, - request, - task->num_scatter); + /* + * Copy the physical address for the command buffer to the + * SCU Task Context + */ + dma_addr = scic_io_request_get_dma_addr(sds_request, + &sds_request->ssp.cmd); - /* map the sgl addresses, if present. - * libata does the mapping for sata devices - * before we get the request. + task_context->command_iu_upper = upper_32_bits(dma_addr); + task_context->command_iu_lower = lower_32_bits(dma_addr); + + /* + * Copy the physical address for the response buffer to the + * SCU Task Context */ - if (task->num_scatter && - !sas_protocol_ata(task->task_proto) && - !(SAS_PROTOCOL_SMP & task->task_proto)) { + dma_addr = scic_io_request_get_dma_addr(sds_request, + &sds_request->ssp.rsp); - request->num_sg_entries = dma_map_sg( - &isci_host->pdev->dev, - task->scatter, - task->num_scatter, - task->data_dir - ); + task_context->response_iu_upper = upper_32_bits(dma_addr); + task_context->response_iu_lower = lower_32_bits(dma_addr); +} - if (request->num_sg_entries == 0) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - } +/** + * This method is will fill in the SCU Task Context for a SSP IO request. + * @sci_req: + * + */ +static void scu_ssp_io_request_construct_task_context( + struct scic_sds_request *sci_req, + enum dma_data_direction dir, + u32 len) +{ + struct scu_task_context *task_context; - /* build the common request object. For now, - * we will let the core allocate the IO tag. - */ - status = scic_io_request_construct(&isci_host->sci, sci_device, - SCI_CONTROLLER_INVALID_IO_TAG, - &request->sci); + task_context = scic_sds_request_get_task_context(sci_req); - if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, - "%s: failed request construct\n", - __func__); - return SCI_FAILURE; - } + scu_ssp_reqeust_construct_task_context(sci_req, task_context); - switch (task->task_proto) { - case SAS_PROTOCOL_SMP: - status = isci_smp_request_build(request); - break; - case SAS_PROTOCOL_SSP: - status = isci_request_ssp_request_construct(request); + task_context->ssp_command_iu_length = + sizeof(struct ssp_cmd_iu) / sizeof(u32); + task_context->type.ssp.frame_type = SSP_COMMAND; + + switch (dir) { + case DMA_FROM_DEVICE: + case DMA_NONE: + default: + task_context->task_type = SCU_TASK_TYPE_IOREAD; break; - case SAS_PROTOCOL_SATA: - case SAS_PROTOCOL_STP: - case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: - status = isci_request_stp_request_construct(request); + case DMA_TO_DEVICE: + task_context->task_type = SCU_TASK_TYPE_IOWRITE; break; - default: - dev_warn(&isci_host->pdev->dev, - "%s: unknown protocol\n", __func__); - return SCI_FAILURE; } - return SCI_SUCCESS; + task_context->transfer_length_bytes = len; + + if (task_context->transfer_length_bytes > 0) + scic_sds_request_build_sgl(sci_req); } +static void scic_sds_ssp_task_request_assign_buffers(struct scic_sds_request *sci_req) +{ + if (sci_req->was_tag_assigned_by_user == false) + sci_req->task_context_buffer = &sci_req->tc; +} /** - * isci_request_alloc_core() - This function gets the request object from the - * isci_host dma cache. - * @isci_host: This parameter specifies the ISCI host object - * @isci_request: This parameter will contain the pointer to the new - * isci_request object. - * @isci_device: This parameter is the pointer to the isci remote device object - * that is the destination for this request. - * @gfp_flags: This parameter specifies the os allocation flags. + * This method will fill in the SCU Task Context for a SSP Task request. The + * following important settings are utilized: -# priority == + * SCU_TASK_PRIORITY_HIGH. This ensures that the task request is issued + * ahead of other task destined for the same Remote Node. -# task_type == + * SCU_TASK_TYPE_IOREAD. This simply indicates that a normal request type + * (i.e. non-raw frame) is being utilized to perform task management. -# + * control_frame == 1. This ensures that the proper endianess is set so + * that the bytes are transmitted in the right order for a task frame. + * @sci_req: This parameter specifies the task request object being + * constructed. * - * SCI_SUCCESS on successfull completion, or specific failure code. */ -static int isci_request_alloc_core( - struct isci_host *isci_host, - struct isci_request **isci_request, - struct isci_remote_device *isci_device, - gfp_t gfp_flags) +static void scu_ssp_task_request_construct_task_context( + struct scic_sds_request *sci_req) { - int ret = 0; - dma_addr_t handle; - struct isci_request *request; - - - /* get pointer to dma memory. This actually points - * to both the isci_remote_device object and the - * sci object. The isci object is at the beginning - * of the memory allocated here. - */ - request = dma_pool_alloc(isci_host->dma_pool, gfp_flags, &handle); - if (!request) { - dev_warn(&isci_host->pdev->dev, - "%s: dma_pool_alloc returned NULL\n", __func__); - return -ENOMEM; - } - - /* initialize the request object. */ - spin_lock_init(&request->state_lock); - request->request_daddr = handle; - request->isci_host = isci_host; - request->isci_device = isci_device; - request->io_request_completion = NULL; - request->terminated = false; - - request->num_sg_entries = 0; - - request->complete_in_target = false; + struct scu_task_context *task_context; - INIT_LIST_HEAD(&request->completed_node); - INIT_LIST_HEAD(&request->dev_node); + task_context = scic_sds_request_get_task_context(sci_req); - *isci_request = request; - isci_request_change_state(request, allocated); + scu_ssp_reqeust_construct_task_context(sci_req, task_context); - return ret; + task_context->control_frame = 1; + task_context->priority = SCU_TASK_PRIORITY_HIGH; + task_context->task_type = SCU_TASK_TYPE_RAW_FRAME; + task_context->transfer_length_bytes = 0; + task_context->type.ssp.frame_type = SSP_TASK; + task_context->ssp_command_iu_length = + sizeof(struct ssp_task_iu) / sizeof(u32); } -static int isci_request_alloc_io( - struct isci_host *isci_host, - struct sas_task *task, - struct isci_request **isci_request, - struct isci_remote_device *isci_device, - gfp_t gfp_flags) -{ - int retval = isci_request_alloc_core(isci_host, isci_request, - isci_device, gfp_flags); - if (!retval) { - (*isci_request)->ttype_ptr.io_task_ptr = task; - (*isci_request)->ttype = io_task; +/** + * This method constructs the SSP Command IU data for this ssp passthrough + * comand request object. + * @sci_req: This parameter specifies the request object for which the SSP + * command information unit is being built. + * + * enum sci_status, returns invalid parameter is cdb > 16 + */ - task->lldd_task = *isci_request; - } - return retval; -} /** - * isci_request_alloc_tmf() - This function gets the request object from the - * isci_host dma cache and initializes the relevant fields as a sas_task. - * @isci_host: This parameter specifies the ISCI host object - * @sas_task: This parameter is the task struct from the upper layer driver. - * @isci_request: This parameter will contain the pointer to the new - * isci_request object. - * @isci_device: This parameter is the pointer to the isci remote device object - * that is the destination for this request. - * @gfp_flags: This parameter specifies the os allocation flags. + * This method constructs the SATA request object. + * @sci_req: + * @sat_protocol: + * @transfer_length: + * @data_direction: + * @copy_rx_frame: * - * SCI_SUCCESS on successfull completion, or specific failure code. + * enum sci_status */ -int isci_request_alloc_tmf( - struct isci_host *isci_host, - struct isci_tmf *isci_tmf, - struct isci_request **isci_request, - struct isci_remote_device *isci_device, - gfp_t gfp_flags) +static enum sci_status +scic_io_request_construct_sata(struct scic_sds_request *sci_req, + u32 len, + enum dma_data_direction dir, + bool copy) { - int retval = isci_request_alloc_core(isci_host, isci_request, - isci_device, gfp_flags); + enum sci_status status = SCI_SUCCESS; + struct isci_request *ireq = sci_req_to_ireq(sci_req); + struct sas_task *task = isci_request_access_task(ireq); - if (!retval) { + /* check for management protocols */ + if (ireq->ttype == tmf_task) { + struct isci_tmf *tmf = isci_request_access_tmf(ireq); - (*isci_request)->ttype_ptr.tmf_task_ptr = isci_tmf; - (*isci_request)->ttype = tmf_task; + if (tmf->tmf_code == isci_tmf_sata_srst_high || + tmf->tmf_code == isci_tmf_sata_srst_low) + return scic_sds_stp_soft_reset_request_construct(sci_req); + else { + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: Request 0x%p received un-handled SAT " + "management protocol 0x%x.\n", + __func__, sci_req, tmf->tmf_code); + + return SCI_FAILURE; + } } - return retval; -} -/** - * isci_request_execute() - This function allocates the isci_request object, - * all fills in some common fields. - * @isci_host: This parameter specifies the ISCI host object - * @sas_task: This parameter is the task struct from the upper layer driver. - * @isci_request: This parameter will contain the pointer to the new - * isci_request object. - * @gfp_flags: This parameter specifies the os allocation flags. - * - * SCI_SUCCESS on successfull completion, or specific failure code. - */ -int isci_request_execute( - struct isci_host *isci_host, - struct sas_task *task, - struct isci_request **isci_request, - gfp_t gfp_flags) + if (!sas_protocol_ata(task->task_proto)) { + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: Non-ATA protocol in SATA path: 0x%x\n", + __func__, + task->task_proto); + return SCI_FAILURE; + + } + + /* non data */ + if (task->data_dir == DMA_NONE) + return scic_sds_stp_non_data_request_construct(sci_req); + + /* NCQ */ + if (task->ata_task.use_ncq) + return scic_sds_stp_ncq_request_construct(sci_req, len, dir); + + /* DMA */ + if (task->ata_task.dma_xfer) + return scic_sds_stp_udma_request_construct(sci_req, len, dir); + else /* PIO */ + return scic_sds_stp_pio_request_construct(sci_req, copy); + + return status; +} + +static enum sci_status scic_io_request_construct_basic_ssp(struct scic_sds_request *sci_req) { - int ret = 0; - struct scic_sds_remote_device *sci_device; - enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - struct isci_remote_device *isci_device; - struct isci_request *request; - unsigned long flags; + struct isci_request *ireq = sci_req_to_ireq(sci_req); + struct sas_task *task = isci_request_access_task(ireq); - isci_device = task->dev->lldd_dev; - sci_device = &isci_device->sci; + sci_req->protocol = SCIC_SSP_PROTOCOL; - /* do common allocation and init of request object. */ - ret = isci_request_alloc_io( - isci_host, - task, - &request, - isci_device, - gfp_flags - ); + scu_ssp_io_request_construct_task_context(sci_req, + task->data_dir, + task->total_xfer_len); - if (ret) - goto out; + scic_sds_io_request_build_ssp_command_iu(sci_req); - status = isci_io_request_build(isci_host, request, isci_device); - if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, - "%s: request_construct failed - status = 0x%x\n", - __func__, - status); - goto out; - } + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); - spin_lock_irqsave(&isci_host->scic_lock, flags); + return SCI_SUCCESS; +} - /* send the request, let the core assign the IO TAG. */ - status = scic_controller_start_io(&isci_host->sci, sci_device, - &request->sci, - SCI_CONTROLLER_INVALID_IO_TAG); - if (status != SCI_SUCCESS && - status != SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - dev_warn(&isci_host->pdev->dev, - "%s: failed request start (0x%x)\n", - __func__, status); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); - goto out; - } +enum sci_status scic_task_request_construct_ssp( + struct scic_sds_request *sci_req) +{ + /* Construct the SSP Task SCU Task Context */ + scu_ssp_task_request_construct_task_context(sci_req); - /* Either I/O started OK, or the core has signaled that - * the device needs a target reset. - * - * In either case, hold onto the I/O for later. - * - * Update it's status and add it to the list in the - * remote device object. - */ - isci_request_change_state(request, started); - list_add(&request->dev_node, &isci_device->reqs_in_process); + /* Fill in the SSP Task IU */ + scic_sds_task_request_build_ssp_task_iu(sci_req); - if (status == SCI_SUCCESS) { - /* Save the tag for possible task mgmt later. */ - request->io_tag = scic_io_request_get_io_tag(&request->sci); - } else { - /* The request did not really start in the - * hardware, so clear the request handle - * here so no terminations will be done. - */ - request->terminated = true; - } - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); - if (status == - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - /* Signal libsas that we need the SCSI error - * handler thread to work on this I/O and that - * we want a device reset. - */ - spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; - spin_unlock_irqrestore(&task->task_state_lock, flags); + return SCI_SUCCESS; +} - /* Cause this task to be scheduled in the SCSI error - * handler thread. - */ - isci_execpath_callback(isci_host, task, - sas_task_abort); - /* Change the status, since we are holding - * the I/O until it is managed by the SCSI - * error handler. - */ - status = SCI_SUCCESS; - } +static enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_request *sci_req) +{ + enum sci_status status; + struct scic_sds_stp_request *stp_req; + bool copy = false; + struct isci_request *isci_request = sci_req_to_ireq(sci_req); + struct sas_task *task = isci_request_access_task(isci_request); - out: - if (status != SCI_SUCCESS) { - /* release dma memory on failure. */ - isci_request_free(isci_host, request); - request = NULL; - ret = SCI_FAILURE; - } + stp_req = &sci_req->stp.req; + sci_req->protocol = SCIC_STP_PROTOCOL; - *isci_request = request; - return ret; + copy = (task->data_dir == DMA_NONE) ? false : true; + + status = scic_io_request_construct_sata(sci_req, + task->total_xfer_len, + task->data_dir, + copy); + + if (status == SCI_SUCCESS) + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); + + return status; } +enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req) +{ + enum sci_status status = SCI_SUCCESS; + struct isci_request *ireq = sci_req_to_ireq(sci_req); + + /* check for management protocols */ + if (ireq->ttype == tmf_task) { + struct isci_tmf *tmf = isci_request_access_tmf(ireq); + + if (tmf->tmf_code == isci_tmf_sata_srst_high || + tmf->tmf_code == isci_tmf_sata_srst_low) { + status = scic_sds_stp_soft_reset_request_construct(sci_req); + } else { + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: Request 0x%p received un-handled SAT " + "Protocol 0x%x.\n", + __func__, sci_req, tmf->tmf_code); + + return SCI_FAILURE; + } + } + + if (status == SCI_SUCCESS) + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); + + return status; +} + /** - * isci_request_process_response_iu() - This function sets the status and - * response iu, in the task struct, from the request object for the upper - * layer driver. - * @sas_task: This parameter is the task struct from the upper layer driver. - * @resp_iu: This parameter points to the response iu of the completed request. - * @dev: This parameter specifies the linux device struct. - * - * none. + * sci_req_tx_bytes - bytes transferred when reply underruns request + * @sci_req: request that was terminated early */ -static void isci_request_process_response_iu( - struct sas_task *task, - struct ssp_response_iu *resp_iu, - struct device *dev) +#define SCU_TASK_CONTEXT_SRAM 0x200000 +static u32 sci_req_tx_bytes(struct scic_sds_request *sci_req) { - dev_dbg(dev, - "%s: resp_iu = %p " - "resp_iu->status = 0x%x,\nresp_iu->datapres = %d " - "resp_iu->response_data_len = %x, " - "resp_iu->sense_data_len = %x\nrepsonse data: ", + struct scic_sds_controller *scic = sci_req->owning_controller; + u32 ret_val = 0; + + if (readl(&scic->smu_registers->address_modifier) == 0) { + void __iomem *scu_reg_base = scic->scu_registers; + + /* get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where + * BAR1 is the scu_registers + * 0x20002C = 0x200000 + 0x2c + * = start of task context SRAM + offset of (type.ssp.data_offset) + * TCi is the io_tag of struct scic_sds_request + */ + ret_val = readl(scu_reg_base + + (SCU_TASK_CONTEXT_SRAM + offsetof(struct scu_task_context, type.ssp.data_offset)) + + ((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(sci_req->io_tag))); + } + + return ret_val; +} + +enum sci_status +scic_sds_request_start(struct scic_sds_request *request) +{ + if (request->device_sequence != + scic_sds_remote_device_get_sequence(request->target_device)) + return SCI_FAILURE; + + if (request->state_handlers->start_handler) + return request->state_handlers->start_handler(request); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request requested to start while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state(&request->state_machine)); + + return SCI_FAILURE_INVALID_STATE; +} + +enum sci_status +scic_sds_io_request_terminate(struct scic_sds_request *request) +{ + if (request->state_handlers->abort_handler) + return request->state_handlers->abort_handler(request); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request requested to abort while in wrong " + "state %d\n", __func__, - resp_iu, - resp_iu->status, - resp_iu->datapres, - resp_iu->response_data_len, - resp_iu->sense_data_len); + sci_base_state_machine_get_state(&request->state_machine)); - task->task_status.stat = resp_iu->status; + return SCI_FAILURE_INVALID_STATE; +} - /* libsas updates the task status fields based on the response iu. */ - sas_ssp_task_response(dev, task, resp_iu); +enum sci_status scic_sds_io_request_event_handler( + struct scic_sds_request *request, + u32 event_code) +{ + if (request->state_handlers->event_handler) + return request->state_handlers->event_handler(request, event_code); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request given event code notification %x while " + "in wrong state %d\n", + __func__, + event_code, + sci_base_state_machine_get_state(&request->state_machine)); + + return SCI_FAILURE_INVALID_STATE; } /** - * isci_request_set_open_reject_status() - This function prepares the I/O - * completion for OPEN_REJECT conditions. - * @request: This parameter is the completed isci_request object. - * @response_ptr: This parameter specifies the service response for the I/O. - * @status_ptr: This parameter specifies the exec status for the I/O. - * @complete_to_host_ptr: This parameter specifies the action to be taken by - * the LLDD with respect to completing this request or forcing an abort - * condition on the I/O. - * @open_rej_reason: This parameter specifies the encoded reason for the - * abandon-class reject. * - * none. + * @sci_req: The SCIC_SDS_IO_REQUEST_T object for which the start + * operation is to be executed. + * @frame_index: The frame index returned by the hardware for the reqeust + * object. + * + * This method invokes the core state frame handler for the + * SCIC_SDS_IO_REQUEST_T object. enum sci_status */ -static void isci_request_set_open_reject_status( - struct isci_request *request, - struct sas_task *task, - enum service_response *response_ptr, - enum exec_status *status_ptr, - enum isci_completion_selection *complete_to_host_ptr, - enum sas_open_rej_reason open_rej_reason) +enum sci_status scic_sds_io_request_frame_handler( + struct scic_sds_request *request, + u32 frame_index) { - /* Task in the target is done. */ - request->complete_in_target = true; - *response_ptr = SAS_TASK_UNDELIVERED; - *status_ptr = SAS_OPEN_REJECT; - *complete_to_host_ptr = isci_perform_normal_io_completion; - task->task_status.open_rej_reason = open_rej_reason; + if (request->state_handlers->frame_handler) + return request->state_handlers->frame_handler(request, frame_index); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request given unexpected frame %x while in " + "state %d\n", + __func__, + frame_index, + sci_base_state_machine_get_state(&request->state_machine)); + + scic_sds_controller_release_frame(request->owning_controller, frame_index); + return SCI_FAILURE_INVALID_STATE; } -/** - * isci_request_handle_controller_specific_errors() - This function decodes - * controller-specific I/O completion error conditions. - * @request: This parameter is the completed isci_request object. - * @response_ptr: This parameter specifies the service response for the I/O. - * @status_ptr: This parameter specifies the exec status for the I/O. - * @complete_to_host_ptr: This parameter specifies the action to be taken by - * the LLDD with respect to completing this request or forcing an abort - * condition on the I/O. - * - * none. +/* + * This function copies response data for requests returning response data + * instead of sense data. + * @sci_req: This parameter specifies the request object for which to copy + * the response data. */ -static void isci_request_handle_controller_specific_errors( - struct isci_remote_device *isci_device, - struct isci_request *request, - struct sas_task *task, - enum service_response *response_ptr, - enum exec_status *status_ptr, - enum isci_completion_selection *complete_to_host_ptr) +void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) { - unsigned int cstatus; + void *resp_buf; + u32 len; + struct ssp_response_iu *ssp_response; + struct isci_request *ireq = sci_req_to_ireq(sci_req); + struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - cstatus = scic_request_get_controller_status(&request->sci); + ssp_response = &sci_req->ssp.rsp; - dev_dbg(&request->isci_host->pdev->dev, - "%s: %p SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR " - "- controller status = 0x%x\n", - __func__, request, cstatus); + resp_buf = &isci_tmf->resp.resp_iu; - /* Decode the controller-specific errors; most - * important is to recognize those conditions in which - * the target may still have a task outstanding that - * must be aborted. - * - * Note that there are SCU completion codes being - * named in the decode below for which SCIC has already - * done work to handle them in a way other than as - * a controller-specific completion code; these are left - * in the decode below for completeness sake. - */ - switch (cstatus) { - case SCU_TASK_DONE_DMASETUP_DIRERR: - /* Also SCU_TASK_DONE_SMP_FRM_TYPE_ERR: */ - case SCU_TASK_DONE_XFERCNT_ERR: - /* Also SCU_TASK_DONE_SMP_UFI_ERR: */ - if (task->task_proto == SAS_PROTOCOL_SMP) { - /* SCU_TASK_DONE_SMP_UFI_ERR == Task Done. */ - *response_ptr = SAS_TASK_COMPLETE; + len = min_t(u32, + SSP_RESP_IU_MAX_SIZE, + be32_to_cpu(ssp_response->response_data_len)); - /* See if the device has been/is being stopped. Note - * that we ignore the quiesce state, since we are - * concerned about the actual device state. - */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) - *status_ptr = SAS_DEVICE_UNKNOWN; - else - *status_ptr = SAS_ABORTED_TASK; + memcpy(resp_buf, ssp_response->resp_data, len); +} - request->complete_in_target = true; +/* + * This method implements the action taken when a constructed + * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request. + * This method will, if necessary, allocate a TCi for the io request object and + * then will, if necessary, copy the constructed TC data into the actual TC + * buffer. If everything is successful the post context field is updated with + * the TCi so the controller can post the request to the hardware. enum sci_status + * SCI_SUCCESS SCI_FAILURE_INSUFFICIENT_RESOURCES + */ +static enum sci_status scic_sds_request_constructed_state_start_handler( + struct scic_sds_request *request) +{ + struct scu_task_context *task_context; - *complete_to_host_ptr = - isci_perform_normal_io_completion; - } else { - /* Task in the target is not done. */ - *response_ptr = SAS_TASK_UNDELIVERED; + if (request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { + request->io_tag = + scic_controller_allocate_io_tag(request->owning_controller); + } - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) - *status_ptr = SAS_DEVICE_UNKNOWN; - else - *status_ptr = SAM_STAT_TASK_ABORTED; + /* Record the IO Tag in the request */ + if (request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { + task_context = request->task_context_buffer; - request->complete_in_target = false; + task_context->task_index = scic_sds_io_tag_get_index(request->io_tag); - *complete_to_host_ptr = - isci_perform_error_io_completion; - } + switch (task_context->protocol_type) { + case SCU_TASK_CONTEXT_PROTOCOL_SMP: + case SCU_TASK_CONTEXT_PROTOCOL_SSP: + /* SSP/SMP Frame */ + task_context->type.ssp.tag = request->io_tag; + task_context->type.ssp.target_port_transfer_tag = 0xFFFF; + break; - break; + case SCU_TASK_CONTEXT_PROTOCOL_STP: + /* + * STP/SATA Frame + * task_context->type.stp.ncq_tag = request->ncq_tag; */ + break; - case SCU_TASK_DONE_CRC_ERR: - case SCU_TASK_DONE_NAK_CMD_ERR: - case SCU_TASK_DONE_EXCESS_DATA: - case SCU_TASK_DONE_UNEXP_FIS: - /* Also SCU_TASK_DONE_UNEXP_RESP: */ - case SCU_TASK_DONE_VIIT_ENTRY_NV: /* TODO - conditions? */ - case SCU_TASK_DONE_IIT_ENTRY_NV: /* TODO - conditions? */ - case SCU_TASK_DONE_RNCNV_OUTBOUND: /* TODO - conditions? */ - /* These are conditions in which the target - * has completed the task, so that no cleanup - * is necessary. - */ - *response_ptr = SAS_TASK_COMPLETE; + case SCU_TASK_CONTEXT_PROTOCOL_NONE: + /* / @todo When do we set no protocol type? */ + break; - /* See if the device has been/is being stopped. Note - * that we ignore the quiesce state, since we are - * concerned about the actual device state. - */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) - *status_ptr = SAS_DEVICE_UNKNOWN; - else - *status_ptr = SAS_ABORTED_TASK; + default: + /* This should never happen since we build the IO requests */ + break; + } - request->complete_in_target = true; + /* + * Check to see if we need to copy the task context buffer + * or have been building into the task context buffer */ + if (request->was_tag_assigned_by_user == false) { + scic_sds_controller_copy_task_context( + request->owning_controller, request); + } - *complete_to_host_ptr = isci_perform_normal_io_completion; - break; + /* Add to the post_context the io tag value */ + request->post_context |= scic_sds_io_tag_get_index(request->io_tag); + /* Everything is good go ahead and change state */ + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_STARTED); - /* Note that the only open reject completion codes seen here will be - * abandon-class codes; all others are automatically retried in the SCU. - */ - case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION: + return SCI_SUCCESS; + } - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_WRONG_DEST); - break; + return SCI_FAILURE_INSUFFICIENT_RESOURCES; +} - case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION: +/* + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_terminate() request. Since the request + * has not yet been posted to the hardware the request transitions to the + * completed state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_constructed_state_abort_handler( + struct scic_sds_request *request) +{ + /* + * This request has been terminated by the user make sure that the correct + * status code is returned */ + scic_sds_request_set_status(request, + SCU_TASK_DONE_TASK_ABORT, + SCI_FAILURE_IO_TERMINATED); + + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + return SCI_SUCCESS; +} - /* Note - the return of AB0 will change when - * libsas implements detection of zone violations. - */ - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_RESV_AB0); - break; +/* + * ***************************************************************************** + * * STARTED STATE HANDLERS + * ***************************************************************************** */ - case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1: +/* + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_terminate() request. Since the request + * has been posted to the hardware the io request state is changed to the + * aborting state. enum sci_status SCI_SUCCESS + */ +enum sci_status scic_sds_request_started_state_abort_handler( + struct scic_sds_request *request) +{ + if (request->has_started_substate_machine) + sci_base_state_machine_stop(&request->started_substate_machine); - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_RESV_AB1); - break; + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_ABORTING); + return SCI_SUCCESS; +} - case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2: +/* + * scic_sds_request_started_state_tc_completion_handler() - This method process + * TC (task context) completions for normal IO request (i.e. Task/Abort + * Completions of type 0). This method will update the + * SCIC_SDS_IO_REQUEST_T::status field. + * @sci_req: This parameter specifies the request for which a completion + * occurred. + * @completion_code: This parameter specifies the completion code received from + * the SCU. + * + */ +static enum sci_status +scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sci_req, + u32 completion_code) +{ + u8 datapres; + struct ssp_response_iu *resp_iu; - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_RESV_AB2); + /* + * TODO: Any SDMA return code of other than 0 is bad + * decode 0x003C0000 to determine SDMA status + */ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS); break; - case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3: + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): + { + /* + * There are times when the SCU hardware will return an early + * response because the io request specified more data than is + * returned by the target device (mode pages, inquiry data, + * etc.). We must check the response stats to see if this is + * truly a failed request or a good request that just got + * completed early. + */ + struct ssp_response_iu *resp = &sci_req->ssp.rsp; + ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); + + sci_swab32_cpy(&sci_req->ssp.rsp, + &sci_req->ssp.rsp, + word_cnt); + + if (resp->status == 0) { + scic_sds_request_set_status( + sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS_IO_DONE_EARLY); + } else { + scic_sds_request_set_status( + sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + } + } + break; - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_RESV_AB3); - break; + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): + { + ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - case SCU_TASK_OPEN_REJECT_BAD_DESTINATION: + sci_swab32_cpy(&sci_req->ssp.rsp, + &sci_req->ssp.rsp, + word_cnt); - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_BAD_DEST); + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); break; + } - case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY: - - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_STP_NORES); + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR): + /* + * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame + * guaranteed to be received before this completion status is + * posted? + */ + resp_iu = &sci_req->ssp.rsp; + datapres = resp_iu->datapres; + + if ((datapres == 0x01) || (datapres == 0x02)) { + scic_sds_request_set_status( + sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + } else + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; - case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED: - - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_EPROTO); + /* only stp device gets suspended. */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): + if (sci_req->protocol == SCIC_STP_PROTOCOL) { + scic_sds_request_set_status( + sci_req, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); + } else { + scic_sds_request_set_status( + sci_req, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + } break; - case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED: - - isci_request_set_open_reject_status( - request, task, response_ptr, status_ptr, - complete_to_host_ptr, SAS_OREJ_CONN_RATE); + /* both stp/ssp device gets suspended */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): + scic_sds_request_set_status( + sci_req, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); break; - case SCU_TASK_DONE_LL_R_ERR: - /* Also SCU_TASK_DONE_ACK_NAK_TO: */ - case SCU_TASK_DONE_LL_PERR: - case SCU_TASK_DONE_LL_SY_TERM: - /* Also SCU_TASK_DONE_NAK_ERR:*/ - case SCU_TASK_DONE_LL_LF_TERM: - /* Also SCU_TASK_DONE_DATA_LEN_ERR: */ - case SCU_TASK_DONE_LL_ABORT_ERR: - case SCU_TASK_DONE_SEQ_INV_TYPE: - /* Also SCU_TASK_DONE_UNEXP_XR: */ - case SCU_TASK_DONE_XR_IU_LEN_ERR: - case SCU_TASK_DONE_INV_FIS_LEN: - /* Also SCU_TASK_DONE_XR_WD_LEN: */ - case SCU_TASK_DONE_SDMA_ERR: - case SCU_TASK_DONE_OFFSET_ERR: - case SCU_TASK_DONE_MAX_PLD_ERR: - case SCU_TASK_DONE_LF_ERR: - case SCU_TASK_DONE_SMP_RESP_TO_ERR: /* Escalate to dev reset? */ - case SCU_TASK_DONE_SMP_LL_RX_ERR: - case SCU_TASK_DONE_UNEXP_DATA: - case SCU_TASK_DONE_UNEXP_SDBFIS: - case SCU_TASK_DONE_REG_ERR: - case SCU_TASK_DONE_SDB_ERR: - case SCU_TASK_DONE_TASK_ABORT: + /* neither ssp nor stp gets suspended. */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): default: - /* Task in the target is not done. */ - *response_ptr = SAS_TASK_UNDELIVERED; - *status_ptr = SAM_STAT_TASK_ABORTED; - request->complete_in_target = false; - - *complete_to_host_ptr = isci_perform_error_io_completion; + scic_sds_request_set_status( + sci_req, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); break; } + + /* + * TODO: This is probably wrong for ACK/NAK timeout conditions + */ + + /* In all cases we will treat this as the completion of the IO req. */ + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + return SCI_SUCCESS; } -/** - * isci_task_save_for_upper_layer_completion() - This function saves the - * request for later completion to the upper layer driver. - * @host: This parameter is a pointer to the host on which the the request - * should be queued (either as an error or success). - * @request: This parameter is the completed request. - * @response: This parameter is the response code for the completed task. - * @status: This parameter is the status code for the completed task. - * - * none. - */ -static void isci_task_save_for_upper_layer_completion( - struct isci_host *host, - struct isci_request *request, - enum service_response response, - enum exec_status status, - enum isci_completion_selection task_notification_selection) +enum sci_status +scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code) { - struct sas_task *task = isci_request_access_task(request); - - task_notification_selection - = isci_task_set_completion_status(task, response, status, - task_notification_selection); + if (request->state_machine.current_state_id == SCI_BASE_REQUEST_STATE_STARTED && + request->has_started_substate_machine == false) + return scic_sds_request_started_state_tc_completion_handler(request, completion_code); + else if (request->state_handlers->tc_completion_handler) + return request->state_handlers->tc_completion_handler(request, completion_code); + + dev_warn(scic_to_dev(request->owning_controller), + "%s: SCIC IO Request given task completion notification %x " + "while in wrong state %d\n", + __func__, + completion_code, + sci_base_state_machine_get_state(&request->state_machine)); - /* Tasks aborted specifically by a call to the lldd_abort_task - * function should not be completed to the host in the regular path. - */ - switch (task_notification_selection) { + return SCI_FAILURE_INVALID_STATE; - case isci_perform_normal_io_completion: +} - /* Normal notification (task_done) */ - dev_dbg(&host->pdev->dev, - "%s: Normal - task = %p, response=%d (%d), status=%d (%d)\n", +/* + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_frame_handler() request. This method + * first determines the frame type received. If this is a response frame then + * the response data is copied to the io request response buffer for processing + * at completion time. If the frame type is not a response buffer an error is + * logged. enum sci_status SCI_SUCCESS SCI_FAILURE_INVALID_PARAMETER_VALUE + */ +static enum sci_status +scic_sds_request_started_state_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + u32 *frame_header; + struct ssp_frame_hdr ssp_hdr; + ssize_t word_cnt; + + status = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_request_get_controller(sci_req)->uf_control), + frame_index, + (void **)&frame_header); + + word_cnt = sizeof(struct ssp_frame_hdr) / sizeof(u32); + sci_swab32_cpy(&ssp_hdr, frame_header, word_cnt); + + if (ssp_hdr.frame_type == SSP_RESPONSE) { + struct ssp_response_iu *resp_iu; + ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); + + status = scic_sds_unsolicited_frame_control_get_buffer( + &(scic_sds_request_get_controller(sci_req)->uf_control), + frame_index, + (void **)&resp_iu); + + sci_swab32_cpy(&sci_req->ssp.rsp, + resp_iu, word_cnt); + + resp_iu = &sci_req->ssp.rsp; + + if ((resp_iu->datapres == 0x01) || + (resp_iu->datapres == 0x02)) { + scic_sds_request_set_status( + sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + } else + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); + } else { + /* This was not a response frame why did it get forwarded? */ + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: SCIC IO Request 0x%p received unexpected " + "frame %d type 0x%02x\n", __func__, - task, - task->task_status.resp, response, - task->task_status.stat, status); - /* Add to the completed list. */ - list_add(&request->completed_node, - &host->requests_to_complete); + sci_req, + frame_index, + ssp_hdr.frame_type); + } - /* Take the request off the device's pending request list. */ - list_del_init(&request->dev_node); - break; + /* + * In any case we are done with this frame buffer return it to the + * controller + */ + scic_sds_controller_release_frame( + sci_req->owning_controller, frame_index); - case isci_perform_aborted_io_completion: - /* No notification to libsas because this request is - * already in the abort path. - */ - dev_warn(&host->pdev->dev, - "%s: Aborted - task = %p, response=%d (%d), status=%d (%d)\n", - __func__, - task, - task->task_status.resp, response, - task->task_status.stat, status); + return SCI_SUCCESS; +} - /* Wake up whatever process was waiting for this - * request to complete. - */ - WARN_ON(request->io_request_completion == NULL); +/* + * ***************************************************************************** + * * COMPLETED STATE HANDLERS + * ***************************************************************************** */ - if (request->io_request_completion != NULL) { - /* Signal whoever is waiting that this - * request is complete. - */ - complete(request->io_request_completion); - } - break; +/* + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_complete() request. This method frees up + * any io request resources that have been allocated and transitions the + * request to its final state. Consider stopping the state machine instead of + * transitioning to the final state? enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_completed_state_complete_handler( + struct scic_sds_request *request) +{ + if (request->was_tag_assigned_by_user != true) { + scic_controller_free_io_tag( + request->owning_controller, request->io_tag); + } - case isci_perform_error_io_completion: - /* Use sas_task_abort */ - dev_warn(&host->pdev->dev, - "%s: Error - task = %p, response=%d (%d), status=%d (%d)\n", - __func__, - task, - task->task_status.resp, response, - task->task_status.stat, status); - /* Add to the aborted list. */ - list_add(&request->completed_node, - &host->requests_to_errorback); - break; + if (request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) { + scic_sds_controller_release_frame( + request->owning_controller, request->saved_rx_frame_index); + } - default: - dev_warn(&host->pdev->dev, - "%s: Unknown - task = %p, response=%d (%d), status=%d (%d)\n", - __func__, - task, - task->task_status.resp, response, - task->task_status.stat, status); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_FINAL); + return SCI_SUCCESS; +} - /* Add to the error to libsas list. */ - list_add(&request->completed_node, - &host->requests_to_errorback); +/* + * ***************************************************************************** + * * ABORTING STATE HANDLERS + * ***************************************************************************** */ + +/* + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_terminate() request. This method is the + * io request aborting state abort handlers. On receipt of a multiple + * terminate requests the io request will transition to the completed state. + * This should not happen in normal operation. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_aborting_state_abort_handler( + struct scic_sds_request *request) +{ + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + return SCI_SUCCESS; +} + +/* + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_task_completion() request. This method + * decodes the completion type waiting for the abort task complete + * notification. When the abort task complete is received the io request + * transitions to the completed state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): + case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED + ); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + + default: + /* + * Unless we get some strange error wait for the task abort to complete + * TODO: Should there be a state change for this completion? */ break; } + + return SCI_SUCCESS; +} + +/* + * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T + * object receives a scic_sds_request_frame_handler() request. This method + * discards the unsolicited frame since we are waiting for the abort task + * completion. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_request_aborting_state_frame_handler( + struct scic_sds_request *sci_req, + u32 frame_index) +{ + /* TODO: Is it even possible to get an unsolicited frame in the aborting state? */ + + scic_sds_controller_release_frame( + sci_req->owning_controller, frame_index); + + return SCI_SUCCESS; } +static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { + [SCI_BASE_REQUEST_STATE_INITIAL] = { + }, + [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { + .start_handler = scic_sds_request_constructed_state_start_handler, + .abort_handler = scic_sds_request_constructed_state_abort_handler, + }, + [SCI_BASE_REQUEST_STATE_STARTED] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, + .frame_handler = scic_sds_request_started_state_frame_handler, + }, + [SCI_BASE_REQUEST_STATE_COMPLETED] = { + .complete_handler = scic_sds_request_completed_state_complete_handler, + }, + [SCI_BASE_REQUEST_STATE_ABORTING] = { + .abort_handler = scic_sds_request_aborting_state_abort_handler, + .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, + .frame_handler = scic_sds_request_aborting_state_frame_handler, + }, + [SCI_BASE_REQUEST_STATE_FINAL] = { + }, +}; + + /** - * isci_request_io_request_complete() - This function is called by the sci core - * when an io request completes. - * @isci_host: This parameter specifies the ISCI host object - * @request: This parameter is the completed isci_request object. - * @completion_status: This parameter specifies the completion status from the - * sci core. + * isci_request_process_response_iu() - This function sets the status and + * response iu, in the task struct, from the request object for the upper + * layer driver. + * @sas_task: This parameter is the task struct from the upper layer driver. + * @resp_iu: This parameter points to the response iu of the completed request. + * @dev: This parameter specifies the linux device struct. * * none. */ -void isci_request_io_request_complete( - struct isci_host *isci_host, - struct isci_request *request, - enum sci_io_status completion_status) +static void isci_request_process_response_iu( + struct sas_task *task, + struct ssp_response_iu *resp_iu, + struct device *dev) { - struct sas_task *task = isci_request_access_task(request); - struct ssp_response_iu *resp_iu; - void *resp_buf; - unsigned long task_flags; - struct isci_remote_device *isci_device = request->isci_device; - enum service_response response = SAS_TASK_UNDELIVERED; - enum exec_status status = SAS_ABORTED_TASK; - enum isci_request_status request_status; - enum isci_completion_selection complete_to_host - = isci_perform_normal_io_completion; - - dev_dbg(&isci_host->pdev->dev, - "%s: request = %p, task = %p,\n" - "task->data_dir = %d completion_status = 0x%x\n", + dev_dbg(dev, + "%s: resp_iu = %p " + "resp_iu->status = 0x%x,\nresp_iu->datapres = %d " + "resp_iu->response_data_len = %x, " + "resp_iu->sense_data_len = %x\nrepsonse data: ", __func__, - request, - task, - task->data_dir, - completion_status); + resp_iu, + resp_iu->status, + resp_iu->datapres, + resp_iu->response_data_len, + resp_iu->sense_data_len); - spin_lock(&request->state_lock); - request_status = isci_request_get_state(request); + task->task_status.stat = resp_iu->status; - /* Decode the request status. Note that if the request has been - * aborted by a task management function, we don't care - * what the status is. - */ - switch (request_status) { + /* libsas updates the task status fields based on the response iu. */ + sas_ssp_task_response(dev, task, resp_iu); +} - case aborted: - /* "aborted" indicates that the request was aborted by a task - * management function, since once a task management request is - * perfomed by the device, the request only completes because - * of the subsequent driver terminate. - * - * Aborted also means an external thread is explicitly managing - * this request, so that we do not complete it up the stack. - * - * The target is still there (since the TMF was successful). - */ - request->complete_in_target = true; - response = SAS_TASK_COMPLETE; +/** + * isci_request_set_open_reject_status() - This function prepares the I/O + * completion for OPEN_REJECT conditions. + * @request: This parameter is the completed isci_request object. + * @response_ptr: This parameter specifies the service response for the I/O. + * @status_ptr: This parameter specifies the exec status for the I/O. + * @complete_to_host_ptr: This parameter specifies the action to be taken by + * the LLDD with respect to completing this request or forcing an abort + * condition on the I/O. + * @open_rej_reason: This parameter specifies the encoded reason for the + * abandon-class reject. + * + * none. + */ +static void isci_request_set_open_reject_status( + struct isci_request *request, + struct sas_task *task, + enum service_response *response_ptr, + enum exec_status *status_ptr, + enum isci_completion_selection *complete_to_host_ptr, + enum sas_open_rej_reason open_rej_reason) +{ + /* Task in the target is done. */ + request->complete_in_target = true; + *response_ptr = SAS_TASK_UNDELIVERED; + *status_ptr = SAS_OPEN_REJECT; + *complete_to_host_ptr = isci_perform_normal_io_completion; + task->task_status.open_rej_reason = open_rej_reason; +} - /* See if the device has been/is being stopped. Note - * that we ignore the quiesce state, since we are - * concerned about the actual device state. - */ - if ((isci_device->status == isci_stopping) - || (isci_device->status == isci_stopped) - ) - status = SAS_DEVICE_UNKNOWN; - else - status = SAS_ABORTED_TASK; +/** + * isci_request_handle_controller_specific_errors() - This function decodes + * controller-specific I/O completion error conditions. + * @request: This parameter is the completed isci_request object. + * @response_ptr: This parameter specifies the service response for the I/O. + * @status_ptr: This parameter specifies the exec status for the I/O. + * @complete_to_host_ptr: This parameter specifies the action to be taken by + * the LLDD with respect to completing this request or forcing an abort + * condition on the I/O. + * + * none. + */ +static void isci_request_handle_controller_specific_errors( + struct isci_remote_device *isci_device, + struct isci_request *request, + struct sas_task *task, + enum service_response *response_ptr, + enum exec_status *status_ptr, + enum isci_completion_selection *complete_to_host_ptr) +{ + unsigned int cstatus; - complete_to_host = isci_perform_aborted_io_completion; - /* This was an aborted request. */ + cstatus = request->sci.scu_status; - spin_unlock(&request->state_lock); - break; + dev_dbg(&request->isci_host->pdev->dev, + "%s: %p SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR " + "- controller status = 0x%x\n", + __func__, request, cstatus); - case aborting: - /* aborting means that the task management function tried and - * failed to abort the request. We need to note the request - * as SAS_TASK_UNDELIVERED, so that the scsi mid layer marks the - * target as down. - * - * Aborting also means an external thread is explicitly managing - * this request, so that we do not complete it up the stack. - */ - request->complete_in_target = true; - response = SAS_TASK_UNDELIVERED; + /* Decode the controller-specific errors; most + * important is to recognize those conditions in which + * the target may still have a task outstanding that + * must be aborted. + * + * Note that there are SCU completion codes being + * named in the decode below for which SCIC has already + * done work to handle them in a way other than as + * a controller-specific completion code; these are left + * in the decode below for completeness sake. + */ + switch (cstatus) { + case SCU_TASK_DONE_DMASETUP_DIRERR: + /* Also SCU_TASK_DONE_SMP_FRM_TYPE_ERR: */ + case SCU_TASK_DONE_XFERCNT_ERR: + /* Also SCU_TASK_DONE_SMP_UFI_ERR: */ + if (task->task_proto == SAS_PROTOCOL_SMP) { + /* SCU_TASK_DONE_SMP_UFI_ERR == Task Done. */ + *response_ptr = SAS_TASK_COMPLETE; - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) - /* The device has been /is being stopped. Note that - * we ignore the quiesce state, since we are + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are * concerned about the actual device state. */ - status = SAS_DEVICE_UNKNOWN; - else - status = SAS_PHY_DOWN; + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + *status_ptr = SAS_DEVICE_UNKNOWN; + else + *status_ptr = SAS_ABORTED_TASK; - complete_to_host = isci_perform_aborted_io_completion; + request->complete_in_target = true; - /* This was an aborted request. */ + *complete_to_host_ptr = + isci_perform_normal_io_completion; + } else { + /* Task in the target is not done. */ + *response_ptr = SAS_TASK_UNDELIVERED; - spin_unlock(&request->state_lock); - break; + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + *status_ptr = SAS_DEVICE_UNKNOWN; + else + *status_ptr = SAM_STAT_TASK_ABORTED; - case terminating: + request->complete_in_target = false; - /* This was an terminated request. This happens when - * the I/O is being terminated because of an action on - * the device (reset, tear down, etc.), and the I/O needs - * to be completed up the stack. + *complete_to_host_ptr = + isci_perform_error_io_completion; + } + + break; + + case SCU_TASK_DONE_CRC_ERR: + case SCU_TASK_DONE_NAK_CMD_ERR: + case SCU_TASK_DONE_EXCESS_DATA: + case SCU_TASK_DONE_UNEXP_FIS: + /* Also SCU_TASK_DONE_UNEXP_RESP: */ + case SCU_TASK_DONE_VIIT_ENTRY_NV: /* TODO - conditions? */ + case SCU_TASK_DONE_IIT_ENTRY_NV: /* TODO - conditions? */ + case SCU_TASK_DONE_RNCNV_OUTBOUND: /* TODO - conditions? */ + /* These are conditions in which the target + * has completed the task, so that no cleanup + * is necessary. */ - request->complete_in_target = true; - response = SAS_TASK_UNDELIVERED; + *response_ptr = SAS_TASK_COMPLETE; /* See if the device has been/is being stopped. Note * that we ignore the quiesce state, since we are @@ -953,208 +1341,1206 @@ void isci_request_io_request_complete( */ if ((isci_device->status == isci_stopping) || (isci_device->status == isci_stopped)) - status = SAS_DEVICE_UNKNOWN; + *status_ptr = SAS_DEVICE_UNKNOWN; else - status = SAS_ABORTED_TASK; - - complete_to_host = isci_perform_aborted_io_completion; + *status_ptr = SAS_ABORTED_TASK; - /* This was a terminated request. */ + request->complete_in_target = true; - spin_unlock(&request->state_lock); + *complete_to_host_ptr = isci_perform_normal_io_completion; break; - default: - /* The request is done from an SCU HW perspective. */ - request->status = completed; + /* Note that the only open reject completion codes seen here will be + * abandon-class codes; all others are automatically retried in the SCU. + */ + case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION: - spin_unlock(&request->state_lock); + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_WRONG_DEST); + break; - /* This is an active request being completed from the core. */ - switch (completion_status) { + case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION: - case SCI_IO_FAILURE_RESPONSE_VALID: - dev_dbg(&isci_host->pdev->dev, - "%s: SCI_IO_FAILURE_RESPONSE_VALID (%p/%p)\n", - __func__, - request, - task); + /* Note - the return of AB0 will change when + * libsas implements detection of zone violations. + */ + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_RESV_AB0); + break; - if (sas_protocol_ata(task->task_proto)) { - resp_buf = &request->sci.stp.rsp; - isci_request_process_stp_response(task, - resp_buf); - } else if (SAS_PROTOCOL_SSP == task->task_proto) { + case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1: - /* crack the iu response buffer. */ - resp_iu = &request->sci.ssp.rsp; - isci_request_process_response_iu(task, resp_iu, - &isci_host->pdev->dev); + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_RESV_AB1); + break; - } else if (SAS_PROTOCOL_SMP == task->task_proto) { + case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2: - dev_err(&isci_host->pdev->dev, - "%s: SCI_IO_FAILURE_RESPONSE_VALID: " - "SAS_PROTOCOL_SMP protocol\n", - __func__); + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_RESV_AB2); + break; - } else - dev_err(&isci_host->pdev->dev, - "%s: unknown protocol\n", __func__); + case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3: - /* use the task status set in the task struct by the - * isci_request_process_response_iu call. - */ - request->complete_in_target = true; - response = task->task_status.resp; - status = task->task_status.stat; - break; + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_RESV_AB3); + break; - case SCI_IO_SUCCESS: - case SCI_IO_SUCCESS_IO_DONE_EARLY: + case SCU_TASK_OPEN_REJECT_BAD_DESTINATION: - response = SAS_TASK_COMPLETE; - status = SAM_STAT_GOOD; - request->complete_in_target = true; + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_BAD_DEST); + break; - if (task->task_proto == SAS_PROTOCOL_SMP) { - void *rsp = &request->sci.smp.rsp; + case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY: - dev_dbg(&isci_host->pdev->dev, - "%s: SMP protocol completion\n", - __func__); + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_STP_NORES); + break; - sg_copy_from_buffer( - &task->smp_task.smp_resp, 1, - rsp, sizeof(struct smp_resp)); - } else if (completion_status - == SCI_IO_SUCCESS_IO_DONE_EARLY) { + case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED: - /* This was an SSP / STP / SATA transfer. - * There is a possibility that less data than - * the maximum was transferred. - */ - u32 transferred_length - = scic_io_request_get_number_of_bytes_transferred(&request->sci); + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_EPROTO); + break; - task->task_status.residual - = task->total_xfer_len - transferred_length; + case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED: - /* If there were residual bytes, call this an - * underrun. - */ - if (task->task_status.residual != 0) - status = SAS_DATA_UNDERRUN; + isci_request_set_open_reject_status( + request, task, response_ptr, status_ptr, + complete_to_host_ptr, SAS_OREJ_CONN_RATE); + break; - dev_dbg(&isci_host->pdev->dev, - "%s: SCI_IO_SUCCESS_IO_DONE_EARLY %d\n", - __func__, - status); + case SCU_TASK_DONE_LL_R_ERR: + /* Also SCU_TASK_DONE_ACK_NAK_TO: */ + case SCU_TASK_DONE_LL_PERR: + case SCU_TASK_DONE_LL_SY_TERM: + /* Also SCU_TASK_DONE_NAK_ERR:*/ + case SCU_TASK_DONE_LL_LF_TERM: + /* Also SCU_TASK_DONE_DATA_LEN_ERR: */ + case SCU_TASK_DONE_LL_ABORT_ERR: + case SCU_TASK_DONE_SEQ_INV_TYPE: + /* Also SCU_TASK_DONE_UNEXP_XR: */ + case SCU_TASK_DONE_XR_IU_LEN_ERR: + case SCU_TASK_DONE_INV_FIS_LEN: + /* Also SCU_TASK_DONE_XR_WD_LEN: */ + case SCU_TASK_DONE_SDMA_ERR: + case SCU_TASK_DONE_OFFSET_ERR: + case SCU_TASK_DONE_MAX_PLD_ERR: + case SCU_TASK_DONE_LF_ERR: + case SCU_TASK_DONE_SMP_RESP_TO_ERR: /* Escalate to dev reset? */ + case SCU_TASK_DONE_SMP_LL_RX_ERR: + case SCU_TASK_DONE_UNEXP_DATA: + case SCU_TASK_DONE_UNEXP_SDBFIS: + case SCU_TASK_DONE_REG_ERR: + case SCU_TASK_DONE_SDB_ERR: + case SCU_TASK_DONE_TASK_ABORT: + default: + /* Task in the target is not done. */ + *response_ptr = SAS_TASK_UNDELIVERED; + *status_ptr = SAM_STAT_TASK_ABORTED; + request->complete_in_target = false; - } else - dev_dbg(&isci_host->pdev->dev, - "%s: SCI_IO_SUCCESS\n", - __func__); + *complete_to_host_ptr = isci_perform_error_io_completion; + break; + } +} - break; +/** + * isci_task_save_for_upper_layer_completion() - This function saves the + * request for later completion to the upper layer driver. + * @host: This parameter is a pointer to the host on which the the request + * should be queued (either as an error or success). + * @request: This parameter is the completed request. + * @response: This parameter is the response code for the completed task. + * @status: This parameter is the status code for the completed task. + * + * none. + */ +static void isci_task_save_for_upper_layer_completion( + struct isci_host *host, + struct isci_request *request, + enum service_response response, + enum exec_status status, + enum isci_completion_selection task_notification_selection) +{ + struct sas_task *task = isci_request_access_task(request); - case SCI_IO_FAILURE_TERMINATED: - dev_dbg(&isci_host->pdev->dev, - "%s: SCI_IO_FAILURE_TERMINATED (%p/%p)\n", - __func__, - request, - task); + task_notification_selection + = isci_task_set_completion_status(task, response, status, + task_notification_selection); - /* The request was terminated explicitly. No handling - * is needed in the SCSI error handler path. - */ - request->complete_in_target = true; - response = SAS_TASK_UNDELIVERED; + /* Tasks aborted specifically by a call to the lldd_abort_task + * function should not be completed to the host in the regular path. + */ + switch (task_notification_selection) { - /* See if the device has been/is being stopped. Note - * that we ignore the quiesce state, since we are - * concerned about the actual device state. - */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) - status = SAS_DEVICE_UNKNOWN; - else - status = SAS_ABORTED_TASK; + case isci_perform_normal_io_completion: - complete_to_host = isci_perform_normal_io_completion; - break; + /* Normal notification (task_done) */ + dev_dbg(&host->pdev->dev, + "%s: Normal - task = %p, response=%d (%d), status=%d (%d)\n", + __func__, + task, + task->task_status.resp, response, + task->task_status.stat, status); + /* Add to the completed list. */ + list_add(&request->completed_node, + &host->requests_to_complete); - case SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR: + /* Take the request off the device's pending request list. */ + list_del_init(&request->dev_node); + break; - isci_request_handle_controller_specific_errors( - isci_device, request, task, &response, &status, - &complete_to_host); + case isci_perform_aborted_io_completion: + /* No notification to libsas because this request is + * already in the abort path. + */ + dev_warn(&host->pdev->dev, + "%s: Aborted - task = %p, response=%d (%d), status=%d (%d)\n", + __func__, + task, + task->task_status.resp, response, + task->task_status.stat, status); - break; + /* Wake up whatever process was waiting for this + * request to complete. + */ + WARN_ON(request->io_request_completion == NULL); - case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED: - /* This is a special case, in that the I/O completion - * is telling us that the device needs a reset. - * In order for the device reset condition to be - * noticed, the I/O has to be handled in the error - * handler. Set the reset flag and cause the - * SCSI error thread to be scheduled. - */ - spin_lock_irqsave(&task->task_state_lock, task_flags); - task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + if (request->io_request_completion != NULL) { + + /* Signal whoever is waiting that this + * request is complete. + */ + complete(request->io_request_completion); + } + break; + + case isci_perform_error_io_completion: + /* Use sas_task_abort */ + dev_warn(&host->pdev->dev, + "%s: Error - task = %p, response=%d (%d), status=%d (%d)\n", + __func__, + task, + task->task_status.resp, response, + task->task_status.stat, status); + /* Add to the aborted list. */ + list_add(&request->completed_node, + &host->requests_to_errorback); + break; + + default: + dev_warn(&host->pdev->dev, + "%s: Unknown - task = %p, response=%d (%d), status=%d (%d)\n", + __func__, + task, + task->task_status.resp, response, + task->task_status.stat, status); + + /* Add to the error to libsas list. */ + list_add(&request->completed_node, + &host->requests_to_errorback); + break; + } +} + +static void isci_request_io_request_complete(struct isci_host *isci_host, + struct isci_request *request, + enum sci_io_status completion_status) +{ + struct sas_task *task = isci_request_access_task(request); + struct ssp_response_iu *resp_iu; + void *resp_buf; + unsigned long task_flags; + struct isci_remote_device *isci_device = request->isci_device; + enum service_response response = SAS_TASK_UNDELIVERED; + enum exec_status status = SAS_ABORTED_TASK; + enum isci_request_status request_status; + enum isci_completion_selection complete_to_host + = isci_perform_normal_io_completion; + + dev_dbg(&isci_host->pdev->dev, + "%s: request = %p, task = %p,\n" + "task->data_dir = %d completion_status = 0x%x\n", + __func__, + request, + task, + task->data_dir, + completion_status); + + spin_lock(&request->state_lock); + request_status = isci_request_get_state(request); + + /* Decode the request status. Note that if the request has been + * aborted by a task management function, we don't care + * what the status is. + */ + switch (request_status) { + + case aborted: + /* "aborted" indicates that the request was aborted by a task + * management function, since once a task management request is + * perfomed by the device, the request only completes because + * of the subsequent driver terminate. + * + * Aborted also means an external thread is explicitly managing + * this request, so that we do not complete it up the stack. + * + * The target is still there (since the TMF was successful). + */ + request->complete_in_target = true; + response = SAS_TASK_COMPLETE; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) + || (isci_device->status == isci_stopped) + ) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_aborted_io_completion; + /* This was an aborted request. */ + + spin_unlock(&request->state_lock); + break; + + case aborting: + /* aborting means that the task management function tried and + * failed to abort the request. We need to note the request + * as SAS_TASK_UNDELIVERED, so that the scsi mid layer marks the + * target as down. + * + * Aborting also means an external thread is explicitly managing + * this request, so that we do not complete it up the stack. + */ + request->complete_in_target = true; + response = SAS_TASK_UNDELIVERED; + + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + /* The device has been /is being stopped. Note that + * we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_PHY_DOWN; + + complete_to_host = isci_perform_aborted_io_completion; + + /* This was an aborted request. */ + + spin_unlock(&request->state_lock); + break; + + case terminating: + + /* This was an terminated request. This happens when + * the I/O is being terminated because of an action on + * the device (reset, tear down, etc.), and the I/O needs + * to be completed up the stack. + */ + request->complete_in_target = true; + response = SAS_TASK_UNDELIVERED; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_aborted_io_completion; + + /* This was a terminated request. */ + + spin_unlock(&request->state_lock); + break; + + default: + + /* The request is done from an SCU HW perspective. */ + request->status = completed; + + spin_unlock(&request->state_lock); + + /* This is an active request being completed from the core. */ + switch (completion_status) { + + case SCI_IO_FAILURE_RESPONSE_VALID: + dev_dbg(&isci_host->pdev->dev, + "%s: SCI_IO_FAILURE_RESPONSE_VALID (%p/%p)\n", + __func__, + request, + task); + + if (sas_protocol_ata(task->task_proto)) { + resp_buf = &request->sci.stp.rsp; + isci_request_process_stp_response(task, + resp_buf); + } else if (SAS_PROTOCOL_SSP == task->task_proto) { + + /* crack the iu response buffer. */ + resp_iu = &request->sci.ssp.rsp; + isci_request_process_response_iu(task, resp_iu, + &isci_host->pdev->dev); + + } else if (SAS_PROTOCOL_SMP == task->task_proto) { + + dev_err(&isci_host->pdev->dev, + "%s: SCI_IO_FAILURE_RESPONSE_VALID: " + "SAS_PROTOCOL_SMP protocol\n", + __func__); + + } else + dev_err(&isci_host->pdev->dev, + "%s: unknown protocol\n", __func__); + + /* use the task status set in the task struct by the + * isci_request_process_response_iu call. + */ + request->complete_in_target = true; + response = task->task_status.resp; + status = task->task_status.stat; + break; + + case SCI_IO_SUCCESS: + case SCI_IO_SUCCESS_IO_DONE_EARLY: + + response = SAS_TASK_COMPLETE; + status = SAM_STAT_GOOD; + request->complete_in_target = true; + + if (task->task_proto == SAS_PROTOCOL_SMP) { + void *rsp = &request->sci.smp.rsp; + + dev_dbg(&isci_host->pdev->dev, + "%s: SMP protocol completion\n", + __func__); + + sg_copy_from_buffer( + &task->smp_task.smp_resp, 1, + rsp, sizeof(struct smp_resp)); + } else if (completion_status + == SCI_IO_SUCCESS_IO_DONE_EARLY) { + + /* This was an SSP / STP / SATA transfer. + * There is a possibility that less data than + * the maximum was transferred. + */ + u32 transferred_length = sci_req_tx_bytes(&request->sci); + + task->task_status.residual + = task->total_xfer_len - transferred_length; + + /* If there were residual bytes, call this an + * underrun. + */ + if (task->task_status.residual != 0) + status = SAS_DATA_UNDERRUN; + + dev_dbg(&isci_host->pdev->dev, + "%s: SCI_IO_SUCCESS_IO_DONE_EARLY %d\n", + __func__, + status); + + } else + dev_dbg(&isci_host->pdev->dev, + "%s: SCI_IO_SUCCESS\n", + __func__); + + break; + + case SCI_IO_FAILURE_TERMINATED: + dev_dbg(&isci_host->pdev->dev, + "%s: SCI_IO_FAILURE_TERMINATED (%p/%p)\n", + __func__, + request, + task); + + /* The request was terminated explicitly. No handling + * is needed in the SCSI error handler path. + */ + request->complete_in_target = true; + response = SAS_TASK_UNDELIVERED; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_normal_io_completion; + break; + + case SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR: + + isci_request_handle_controller_specific_errors( + isci_device, request, task, &response, &status, + &complete_to_host); + + break; + + case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED: + /* This is a special case, in that the I/O completion + * is telling us that the device needs a reset. + * In order for the device reset condition to be + * noticed, the I/O has to be handled in the error + * handler. Set the reset flag and cause the + * SCSI error thread to be scheduled. + */ + spin_lock_irqsave(&task->task_state_lock, task_flags); + task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; spin_unlock_irqrestore(&task->task_state_lock, task_flags); - /* Fail the I/O. */ - response = SAS_TASK_UNDELIVERED; - status = SAM_STAT_TASK_ABORTED; + /* Fail the I/O. */ + response = SAS_TASK_UNDELIVERED; + status = SAM_STAT_TASK_ABORTED; + + complete_to_host = isci_perform_error_io_completion; + request->complete_in_target = false; + break; + + default: + /* Catch any otherwise unhandled error codes here. */ + dev_warn(&isci_host->pdev->dev, + "%s: invalid completion code: 0x%x - " + "isci_request = %p\n", + __func__, completion_status, request); + + response = SAS_TASK_UNDELIVERED; + + /* See if the device has been/is being stopped. Note + * that we ignore the quiesce state, since we are + * concerned about the actual device state. + */ + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_error_io_completion; + request->complete_in_target = false; + break; + } + break; + } + + isci_request_unmap_sgl(request, isci_host->pdev); + + /* Put the completed request on the correct list */ + isci_task_save_for_upper_layer_completion(isci_host, request, response, + status, complete_to_host + ); + + /* complete the io request to the core. */ + scic_controller_complete_io(&isci_host->sci, + &isci_device->sci, + &request->sci); + /* set terminated handle so it cannot be completed or + * terminated again, and to cause any calls into abort + * task to recognize the already completed case. + */ + request->terminated = true; + + isci_host_can_dequeue(isci_host, 1); +} + +/** + * scic_sds_request_initial_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occurring. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the initial + * base request is constructed. Entry into the initial state sets all handlers + * for the io request object to their default handlers. none + */ +static void scic_sds_request_initial_state_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_INITIAL + ); +} + +/** + * scic_sds_request_constructed_state_enter() - + * @object: The io request object that is to enter the constructed state. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_CONSTRUCTED state. The method sets the state handlers + * for the the constructed state. none + */ +static void scic_sds_request_constructed_state_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_CONSTRUCTED + ); +} + +/** + * scic_sds_request_started_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occurring. This is cast into a SCIC_SDS_IO_REQUEST object. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a + * SCSI Task request we must enter the started substate machine. none + */ +static void scic_sds_request_started_state_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_STARTED + ); + + /* + * Most of the request state machines have a started substate machine so + * start its execution on the entry to the started state. */ + if (sci_req->has_started_substate_machine == true) + sci_base_state_machine_start(&sci_req->started_substate_machine); +} + +/** + * scic_sds_request_started_state_exit() - + * @object: This parameter specifies the base object for which the state + * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST + * object. + * + * This method implements the actions taken when exiting the + * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be + * to stop the started substate machine. none + */ +static void scic_sds_request_started_state_exit(void *object) +{ + struct scic_sds_request *sci_req = object; + + if (sci_req->has_started_substate_machine == true) + sci_base_state_machine_stop(&sci_req->started_substate_machine); +} + +/** + * scic_sds_request_completed_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST + * object. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_COMPLETED state. This state is entered when the + * SCIC_SDS_IO_REQUEST has completed. The method will decode the request + * completion status and convert it to an enum sci_status to return in the + * completion callback function. none + */ +static void scic_sds_request_completed_state_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + struct scic_sds_controller *scic = + scic_sds_request_get_controller(sci_req); + struct isci_host *ihost = scic_to_ihost(scic); + struct isci_request *ireq = sci_req_to_ireq(sci_req); + + SET_STATE_HANDLER(sci_req, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Tell the SCI_USER that the IO request is complete */ + if (sci_req->is_task_management_request == false) + isci_request_io_request_complete(ihost, ireq, + sci_req->sci_status); + else + isci_task_request_complete(ihost, ireq, sci_req->sci_status); +} + +/** + * scic_sds_request_aborting_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST + * object. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_ABORTING state. none + */ +static void scic_sds_request_aborting_state_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + /* Setting the abort bit in the Task Context is required by the silicon. */ + sci_req->task_context_buffer->abort = 1; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_ABORTING + ); +} + +/** + * scic_sds_request_final_state_enter() - + * @object: This parameter specifies the base object for which the state + * transition is occurring. This is cast into a SCIC_SDS_IO_REQUEST object. + * + * This method implements the actions taken when entering the + * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the + * state handlers in place. none + */ +static void scic_sds_request_final_state_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCI_BASE_REQUEST_STATE_FINAL + ); +} + +static const struct sci_base_state scic_sds_request_state_table[] = { + [SCI_BASE_REQUEST_STATE_INITIAL] = { + .enter_state = scic_sds_request_initial_state_enter, + }, + [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { + .enter_state = scic_sds_request_constructed_state_enter, + }, + [SCI_BASE_REQUEST_STATE_STARTED] = { + .enter_state = scic_sds_request_started_state_enter, + .exit_state = scic_sds_request_started_state_exit + }, + [SCI_BASE_REQUEST_STATE_COMPLETED] = { + .enter_state = scic_sds_request_completed_state_enter, + }, + [SCI_BASE_REQUEST_STATE_ABORTING] = { + .enter_state = scic_sds_request_aborting_state_enter, + }, + [SCI_BASE_REQUEST_STATE_FINAL] = { + .enter_state = scic_sds_request_final_state_enter, + }, +}; + +static void scic_sds_general_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, struct scic_sds_request *sci_req) +{ + sci_base_state_machine_construct(&sci_req->state_machine, sci_req, + scic_sds_request_state_table, SCI_BASE_REQUEST_STATE_INITIAL); + sci_base_state_machine_start(&sci_req->state_machine); + + sci_req->io_tag = io_tag; + sci_req->owning_controller = scic; + sci_req->target_device = sci_dev; + sci_req->has_started_substate_machine = false; + sci_req->protocol = SCIC_NO_PROTOCOL; + sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; + sci_req->device_sequence = scic_sds_remote_device_get_sequence(sci_dev); + + sci_req->sci_status = SCI_SUCCESS; + sci_req->scu_status = 0; + sci_req->post_context = 0xFFFFFFFF; + + sci_req->is_task_management_request = false; + + if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { + sci_req->was_tag_assigned_by_user = false; + sci_req->task_context_buffer = NULL; + } else { + sci_req->was_tag_assigned_by_user = true; + + sci_req->task_context_buffer = + scic_sds_controller_get_task_context_buffer(scic, io_tag); + } +} + +static enum sci_status +scic_io_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, struct scic_sds_request *sci_req) +{ + struct domain_device *dev = sci_dev_to_domain(sci_dev); + enum sci_status status = SCI_SUCCESS; + + /* Build the common part of the request */ + scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); + + if (sci_dev->rnc.remote_node_index == + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) + return SCI_FAILURE_INVALID_REMOTE_DEVICE; + + if (dev->dev_type == SAS_END_DEV) + scic_sds_ssp_io_request_assign_buffers(sci_req); + else if ((dev->dev_type == SATA_DEV) || + (dev->tproto & SAS_PROTOCOL_STP)) { + scic_sds_stp_request_assign_buffers(sci_req); + memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); + } else if (dev_is_expander(dev)) { + scic_sds_smp_request_assign_buffers(sci_req); + memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); + } else + status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + + if (status == SCI_SUCCESS) { + memset(sci_req->task_context_buffer, 0, + offsetof(struct scu_task_context, sgl_pair_ab)); + } + + return status; +} + +enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, struct scic_sds_request *sci_req) +{ + struct domain_device *dev = sci_dev_to_domain(sci_dev); + enum sci_status status = SCI_SUCCESS; + + /* Build the common part of the request */ + scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); + + if (dev->dev_type == SAS_END_DEV) { + scic_sds_ssp_task_request_assign_buffers(sci_req); + + sci_req->has_started_substate_machine = true; + + /* Construct the started sub-state machine. */ + sci_base_state_machine_construct( + &sci_req->started_substate_machine, + sci_req, + scic_sds_io_request_started_task_mgmt_substate_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION + ); + } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) + scic_sds_stp_request_assign_buffers(sci_req); + else + status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + + if (status == SCI_SUCCESS) { + sci_req->is_task_management_request = true; + memset(sci_req->task_context_buffer, 0, sizeof(struct scu_task_context)); + } + + return status; +} + +static enum sci_status isci_request_ssp_request_construct( + struct isci_request *request) +{ + enum sci_status status; + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p\n", + __func__, + request); + status = scic_io_request_construct_basic_ssp(&request->sci); + return status; +} + +static enum sci_status isci_request_stp_request_construct( + struct isci_request *request) +{ + struct sas_task *task = isci_request_access_task(request); + enum sci_status status; + struct host_to_dev_fis *register_fis; + + dev_dbg(&request->isci_host->pdev->dev, + "%s: request = %p\n", + __func__, + request); + + /* Get the host_to_dev_fis from the core and copy + * the fis from the task into it. + */ + register_fis = isci_sata_task_to_fis_copy(task); + + status = scic_io_request_construct_basic_sata(&request->sci); + + /* Set the ncq tag in the fis, from the queue + * command in the task. + */ + if (isci_sata_is_task_ncq(task)) { + + isci_sata_set_ncq_tag( + register_fis, + task + ); + } + + return status; +} + +/* + * isci_smp_request_build() - This function builds the smp request. + * @ireq: This parameter points to the isci_request allocated in the + * request construct function. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +static enum sci_status isci_smp_request_build(struct isci_request *ireq) +{ + enum sci_status status = SCI_FAILURE; + struct sas_task *task = isci_request_access_task(ireq); + struct scic_sds_request *sci_req = &ireq->sci; + + dev_dbg(&ireq->isci_host->pdev->dev, + "%s: request = %p\n", __func__, ireq); + + dev_dbg(&ireq->isci_host->pdev->dev, + "%s: smp_req len = %d\n", + __func__, + task->smp_task.smp_req.length); + + /* copy the smp_command to the address; */ + sg_copy_to_buffer(&task->smp_task.smp_req, 1, + &sci_req->smp.cmd, + sizeof(struct smp_req)); + + status = scic_io_request_construct_smp(sci_req); + if (status != SCI_SUCCESS) + dev_warn(&ireq->isci_host->pdev->dev, + "%s: failed with status = %d\n", + __func__, + status); + + return status; +} + +/** + * isci_io_request_build() - This function builds the io request object. + * @isci_host: This parameter specifies the ISCI host object + * @request: This parameter points to the isci_request object allocated in the + * request construct function. + * @sci_device: This parameter is the handle for the sci core's remote device + * object that is the destination for this request. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +static enum sci_status isci_io_request_build( + struct isci_host *isci_host, + struct isci_request *request, + struct isci_remote_device *isci_device) +{ + enum sci_status status = SCI_SUCCESS; + struct sas_task *task = isci_request_access_task(request); + struct scic_sds_remote_device *sci_device = &isci_device->sci; + + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = 0x%p; request = %p, " + "num_scatter = %d\n", + __func__, + isci_device, + request, + task->num_scatter); + + /* map the sgl addresses, if present. + * libata does the mapping for sata devices + * before we get the request. + */ + if (task->num_scatter && + !sas_protocol_ata(task->task_proto) && + !(SAS_PROTOCOL_SMP & task->task_proto)) { + + request->num_sg_entries = dma_map_sg( + &isci_host->pdev->dev, + task->scatter, + task->num_scatter, + task->data_dir + ); + + if (request->num_sg_entries == 0) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + } + + /* build the common request object. For now, + * we will let the core allocate the IO tag. + */ + status = scic_io_request_construct(&isci_host->sci, sci_device, + SCI_CONTROLLER_INVALID_IO_TAG, + &request->sci); + + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: failed request construct\n", + __func__); + return SCI_FAILURE; + } + + switch (task->task_proto) { + case SAS_PROTOCOL_SMP: + status = isci_smp_request_build(request); + break; + case SAS_PROTOCOL_SSP: + status = isci_request_ssp_request_construct(request); + break; + case SAS_PROTOCOL_SATA: + case SAS_PROTOCOL_STP: + case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: + status = isci_request_stp_request_construct(request); + break; + default: + dev_warn(&isci_host->pdev->dev, + "%s: unknown protocol\n", __func__); + return SCI_FAILURE; + } + + return SCI_SUCCESS; +} + +/** + * isci_request_alloc_core() - This function gets the request object from the + * isci_host dma cache. + * @isci_host: This parameter specifies the ISCI host object + * @isci_request: This parameter will contain the pointer to the new + * isci_request object. + * @isci_device: This parameter is the pointer to the isci remote device object + * that is the destination for this request. + * @gfp_flags: This parameter specifies the os allocation flags. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +static int isci_request_alloc_core( + struct isci_host *isci_host, + struct isci_request **isci_request, + struct isci_remote_device *isci_device, + gfp_t gfp_flags) +{ + int ret = 0; + dma_addr_t handle; + struct isci_request *request; + - complete_to_host = isci_perform_error_io_completion; - request->complete_in_target = false; - break; + /* get pointer to dma memory. This actually points + * to both the isci_remote_device object and the + * sci object. The isci object is at the beginning + * of the memory allocated here. + */ + request = dma_pool_alloc(isci_host->dma_pool, gfp_flags, &handle); + if (!request) { + dev_warn(&isci_host->pdev->dev, + "%s: dma_pool_alloc returned NULL\n", __func__); + return -ENOMEM; + } - default: - /* Catch any otherwise unhandled error codes here. */ - dev_warn(&isci_host->pdev->dev, - "%s: invalid completion code: 0x%x - " - "isci_request = %p\n", - __func__, completion_status, request); + /* initialize the request object. */ + spin_lock_init(&request->state_lock); + request->request_daddr = handle; + request->isci_host = isci_host; + request->isci_device = isci_device; + request->io_request_completion = NULL; + request->terminated = false; - response = SAS_TASK_UNDELIVERED; + request->num_sg_entries = 0; - /* See if the device has been/is being stopped. Note - * that we ignore the quiesce state, since we are - * concerned about the actual device state. - */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) - status = SAS_DEVICE_UNKNOWN; - else - status = SAS_ABORTED_TASK; + request->complete_in_target = false; - complete_to_host = isci_perform_error_io_completion; - request->complete_in_target = false; - break; - } - break; + INIT_LIST_HEAD(&request->completed_node); + INIT_LIST_HEAD(&request->dev_node); + + *isci_request = request; + isci_request_change_state(request, allocated); + + return ret; +} + +static int isci_request_alloc_io( + struct isci_host *isci_host, + struct sas_task *task, + struct isci_request **isci_request, + struct isci_remote_device *isci_device, + gfp_t gfp_flags) +{ + int retval = isci_request_alloc_core(isci_host, isci_request, + isci_device, gfp_flags); + + if (!retval) { + (*isci_request)->ttype_ptr.io_task_ptr = task; + (*isci_request)->ttype = io_task; + + task->lldd_task = *isci_request; } + return retval; +} - isci_request_unmap_sgl(request, isci_host->pdev); +/** + * isci_request_alloc_tmf() - This function gets the request object from the + * isci_host dma cache and initializes the relevant fields as a sas_task. + * @isci_host: This parameter specifies the ISCI host object + * @sas_task: This parameter is the task struct from the upper layer driver. + * @isci_request: This parameter will contain the pointer to the new + * isci_request object. + * @isci_device: This parameter is the pointer to the isci remote device object + * that is the destination for this request. + * @gfp_flags: This parameter specifies the os allocation flags. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +int isci_request_alloc_tmf( + struct isci_host *isci_host, + struct isci_tmf *isci_tmf, + struct isci_request **isci_request, + struct isci_remote_device *isci_device, + gfp_t gfp_flags) +{ + int retval = isci_request_alloc_core(isci_host, isci_request, + isci_device, gfp_flags); - /* Put the completed request on the correct list */ - isci_task_save_for_upper_layer_completion(isci_host, request, response, - status, complete_to_host - ); + if (!retval) { - /* complete the io request to the core. */ - scic_controller_complete_io(&isci_host->sci, - &isci_device->sci, - &request->sci); - /* set terminated handle so it cannot be completed or - * terminated again, and to cause any calls into abort - * task to recognize the already completed case. + (*isci_request)->ttype_ptr.tmf_task_ptr = isci_tmf; + (*isci_request)->ttype = tmf_task; + } + return retval; +} + +/** + * isci_request_execute() - This function allocates the isci_request object, + * all fills in some common fields. + * @isci_host: This parameter specifies the ISCI host object + * @sas_task: This parameter is the task struct from the upper layer driver. + * @isci_request: This parameter will contain the pointer to the new + * isci_request object. + * @gfp_flags: This parameter specifies the os allocation flags. + * + * SCI_SUCCESS on successfull completion, or specific failure code. + */ +int isci_request_execute( + struct isci_host *isci_host, + struct sas_task *task, + struct isci_request **isci_request, + gfp_t gfp_flags) +{ + int ret = 0; + struct scic_sds_remote_device *sci_device; + enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + struct isci_remote_device *isci_device; + struct isci_request *request; + unsigned long flags; + + isci_device = task->dev->lldd_dev; + sci_device = &isci_device->sci; + + /* do common allocation and init of request object. */ + ret = isci_request_alloc_io( + isci_host, + task, + &request, + isci_device, + gfp_flags + ); + + if (ret) + goto out; + + status = isci_io_request_build(isci_host, request, isci_device); + if (status != SCI_SUCCESS) { + dev_warn(&isci_host->pdev->dev, + "%s: request_construct failed - status = 0x%x\n", + __func__, + status); + goto out; + } + + spin_lock_irqsave(&isci_host->scic_lock, flags); + + /* send the request, let the core assign the IO TAG. */ + status = scic_controller_start_io(&isci_host->sci, sci_device, + &request->sci, + SCI_CONTROLLER_INVALID_IO_TAG); + if (status != SCI_SUCCESS && + status != SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + dev_warn(&isci_host->pdev->dev, + "%s: failed request start (0x%x)\n", + __func__, status); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + goto out; + } + + /* Either I/O started OK, or the core has signaled that + * the device needs a target reset. + * + * In either case, hold onto the I/O for later. + * + * Update it's status and add it to the list in the + * remote device object. */ - request->terminated = true; + isci_request_change_state(request, started); + list_add(&request->dev_node, &isci_device->reqs_in_process); - isci_host_can_dequeue(isci_host, 1); + if (status == SCI_SUCCESS) { + /* Save the tag for possible task mgmt later. */ + request->io_tag = request->sci.io_tag; + } else { + /* The request did not really start in the + * hardware, so clear the request handle + * here so no terminations will be done. + */ + request->terminated = true; + } + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + if (status == + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + /* Signal libsas that we need the SCSI error + * handler thread to work on this I/O and that + * we want a device reset. + */ + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + /* Cause this task to be scheduled in the SCSI error + * handler thread. + */ + isci_execpath_callback(isci_host, task, + sas_task_abort); + + /* Change the status, since we are holding + * the I/O until it is managed by the SCSI + * error handler. + */ + status = SCI_SUCCESS; + } + + out: + if (status != SCI_SUCCESS) { + /* release dma memory on failure. */ + isci_request_free(isci_host, request); + request = NULL; + ret = SCI_FAILURE; + } + + *isci_request = request; + return ret; } + + + diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 06786ece9bb2..932ea767c8c2 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -58,7 +58,8 @@ #include "isci.h" #include "host.h" -#include "scic_sds_request.h" +#include "scu_task_context.h" +#include "stp_request.h" /** * struct isci_request_status - This enum defines the possible states of an I/O @@ -82,6 +83,151 @@ enum task_type { tmf_task = 1 }; +enum sci_request_protocol { + SCIC_NO_PROTOCOL, + SCIC_SMP_PROTOCOL, + SCIC_SSP_PROTOCOL, + SCIC_STP_PROTOCOL +}; /* XXX remove me, use sas_task.dev instead */; + +struct scic_sds_request { + /** + * This field contains the information for the base request state machine. + */ + struct sci_base_state_machine state_machine; + + /** + * This field simply points to the controller to which this IO request + * is associated. + */ + struct scic_sds_controller *owning_controller; + + /** + * This field simply points to the remote device to which this IO request + * is associated. + */ + struct scic_sds_remote_device *target_device; + + /** + * This field is utilized to determine if the SCI user is managing + * the IO tag for this request or if the core is managing it. + */ + bool was_tag_assigned_by_user; + + /** + * This field indicates the IO tag for this request. The IO tag is + * comprised of the task_index and a sequence count. The sequence count + * is utilized to help identify tasks from one life to another. + */ + u16 io_tag; + + /** + * This field specifies the protocol being utilized for this + * IO request. + */ + enum sci_request_protocol protocol; + + /** + * This field indicates the completion status taken from the SCUs + * completion code. It indicates the completion result for the SCU hardware. + */ + u32 scu_status; + + /** + * This field indicates the completion status returned to the SCI user. It + * indicates the users view of the io request completion. + */ + u32 sci_status; + + /** + * This field contains the value to be utilized when posting (e.g. Post_TC, + * Post_TC_Abort) this request to the silicon. + */ + u32 post_context; + + struct scu_task_context *task_context_buffer; + struct scu_task_context tc ____cacheline_aligned; + + /* could be larger with sg chaining */ + #define SCU_SGL_SIZE ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) + struct scu_sgl_element_pair sg_table[SCU_SGL_SIZE] __attribute__ ((aligned(32))); + + /** + * This field indicates if this request is a task management request or + * normal IO request. + */ + bool is_task_management_request; + + /** + * This field indicates that this request contains an initialized started + * substate machine. + */ + bool has_started_substate_machine; + + /** + * This field is a pointer to the stored rx frame data. It is used in STP + * internal requests and SMP response frames. If this field is non-NULL the + * saved frame must be released on IO request completion. + * + * @todo In the future do we want to keep a list of RX frame buffers? + */ + u32 saved_rx_frame_index; + + /** + * This field specifies the data necessary to manage the sub-state + * machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state. + */ + struct sci_base_state_machine started_substate_machine; + + /** + * This field specifies the current state handlers in place for this + * IO Request object. This field is updated each time the request + * changes state. + */ + const struct scic_sds_io_request_state_handler *state_handlers; + + /** + * This field in the recorded device sequence for the io request. This is + * recorded during the build operation and is compared in the start + * operation. If the sequence is different then there was a change of + * devices from the build to start operations. + */ + u8 device_sequence; + + union { + struct { + union { + struct ssp_cmd_iu cmd; + struct ssp_task_iu tmf; + }; + union { + struct ssp_response_iu rsp; + u8 rsp_buf[SSP_RESP_IU_MAX_SIZE]; + }; + } ssp; + + struct { + struct smp_req cmd; + struct smp_resp rsp; + } smp; + + struct { + struct scic_sds_stp_request req; + struct host_to_dev_fis cmd; + struct dev_to_host_fis rsp; + } stp; + }; + +}; + +static inline struct scic_sds_request *to_sci_req(struct scic_sds_stp_request *stp_req) +{ + struct scic_sds_request *sci_req; + + sci_req = container_of(stp_req, typeof(*sci_req), stp.req); + return sci_req; +} + struct isci_request { enum isci_request_status status; enum task_type ttype; @@ -125,6 +271,273 @@ static inline struct isci_request *sci_req_to_ireq(struct scic_sds_request *sci_ return ireq; } +/** + * enum sci_base_request_states - This enumeration depicts all the states for + * the common request state machine. + * + * + */ +enum sci_base_request_states { + /** + * Simply the initial state for the base request state machine. + */ + SCI_BASE_REQUEST_STATE_INITIAL, + + /** + * This state indicates that the request has been constructed. This state + * is entered from the INITIAL state. + */ + SCI_BASE_REQUEST_STATE_CONSTRUCTED, + + /** + * This state indicates that the request has been started. This state is + * entered from the CONSTRUCTED state. + */ + SCI_BASE_REQUEST_STATE_STARTED, + + /** + * This state indicates that the request has completed. + * This state is entered from the STARTED state. This state is entered from + * the ABORTING state. + */ + SCI_BASE_REQUEST_STATE_COMPLETED, + + /** + * This state indicates that the request is in the process of being + * terminated/aborted. + * This state is entered from the CONSTRUCTED state. + * This state is entered from the STARTED state. + */ + SCI_BASE_REQUEST_STATE_ABORTING, + + /** + * Simply the final state for the base request state machine. + */ + SCI_BASE_REQUEST_STATE_FINAL, +}; + +typedef enum sci_status (*scic_sds_io_request_handler_t) + (struct scic_sds_request *request); +typedef enum sci_status (*scic_sds_io_request_frame_handler_t) + (struct scic_sds_request *req, u32 frame); +typedef enum sci_status (*scic_sds_io_request_event_handler_t) + (struct scic_sds_request *req, u32 event); +typedef enum sci_status (*scic_sds_io_request_task_completion_handler_t) + (struct scic_sds_request *req, u32 completion_code); + +/** + * struct scic_sds_io_request_state_handler - This is the SDS core definition + * of the state handlers. + * + * + */ +struct scic_sds_io_request_state_handler { + /** + * The start_handler specifies the method invoked when a user attempts to + * start a request. + */ + scic_sds_io_request_handler_t start_handler; + + /** + * The abort_handler specifies the method invoked when a user attempts to + * abort a request. + */ + scic_sds_io_request_handler_t abort_handler; + + /** + * The complete_handler specifies the method invoked when a user attempts to + * complete a request. + */ + scic_sds_io_request_handler_t complete_handler; + + scic_sds_io_request_task_completion_handler_t tc_completion_handler; + scic_sds_io_request_event_handler_t event_handler; + scic_sds_io_request_frame_handler_t frame_handler; + +}; + +extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[]; + +/** + * scic_sds_request_get_controller() - + * + * This macro will return the controller for this io request object + */ +#define scic_sds_request_get_controller(sci_req) \ + ((sci_req)->owning_controller) + +/** + * scic_sds_request_get_device() - + * + * This macro will return the device for this io request object + */ +#define scic_sds_request_get_device(sci_req) \ + ((sci_req)->target_device) + +/** + * scic_sds_request_get_port() - + * + * This macro will return the port for this io request object + */ +#define scic_sds_request_get_port(sci_req) \ + scic_sds_remote_device_get_port(scic_sds_request_get_device(sci_req)) + +/** + * scic_sds_request_get_post_context() - + * + * This macro returns the constructed post context result for the io request. + */ +#define scic_sds_request_get_post_context(sci_req) \ + ((sci_req)->post_context) + +/** + * scic_sds_request_get_task_context() - + * + * This is a helper macro to return the os handle for this request object. + */ +#define scic_sds_request_get_task_context(request) \ + ((request)->task_context_buffer) + +/** + * scic_sds_request_set_status() - + * + * This macro will set the scu hardware status and sci request completion + * status for an io request. + */ +#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \ + { \ + (request)->scu_status = (scu_status_code); \ + (request)->sci_status = (sci_status_code); \ + } + +#define scic_sds_request_complete(a_request) \ + ((a_request)->state_handlers->complete_handler(a_request)) + + +extern enum sci_status +scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code); + +/** + * SCU_SGL_ZERO() - + * + * This macro zeros the hardware SGL element data + */ +#define SCU_SGL_ZERO(scu_sge) \ + { \ + (scu_sge).length = 0; \ + (scu_sge).address_lower = 0; \ + (scu_sge).address_upper = 0; \ + (scu_sge).address_modifier = 0; \ + } + +/** + * SCU_SGL_COPY() - + * + * This macro copys the SGL Element data from the host os to the hardware SGL + * elment data + */ +#define SCU_SGL_COPY(scu_sge, os_sge) \ + { \ + (scu_sge).length = sg_dma_len(sg); \ + (scu_sge).address_upper = \ + upper_32_bits(sg_dma_address(sg)); \ + (scu_sge).address_lower = \ + lower_32_bits(sg_dma_address(sg)); \ + (scu_sge).address_modifier = 0; \ + } + +void scic_sds_request_build_sgl(struct scic_sds_request *sci_req); +void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req); +void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req); +enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); +enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); +void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req); +enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, + u32 event_code); +enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index); +enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req); +enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); + +/** + * enum _scic_sds_io_request_started_task_mgmt_substates - This enumeration + * depicts all of the substates for a task management request to be + * performed in the STARTED super-state. + * + * + */ +enum scic_sds_raw_request_started_task_mgmt_substates { + /** + * The AWAIT_TC_COMPLETION sub-state indicates that the started raw + * task management request is waiting for the transmission of the + * initial frame (i.e. command, task, etc.). + */ + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, + + /** + * This sub-state indicates that the started task management request + * is waiting for the reception of an unsolicited frame + * (i.e. response IU). + */ + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, +}; + + +/** + * enum _scic_sds_smp_request_started_substates - This enumeration depicts all + * of the substates for a SMP request to be performed in the STARTED + * super-state. + * + * + */ +enum scic_sds_smp_request_started_substates { + /** + * This sub-state indicates that the started task management request + * is waiting for the reception of an unsolicited frame + * (i.e. response IU). + */ + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, + + /** + * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is + * waiting for the transmission of the initial frame (i.e. command, task, etc.). + */ + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, +}; + + + +/* XXX open code in caller */ +static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, + dma_addr_t phys_addr) +{ + struct isci_request *ireq = sci_req_to_ireq(sci_req); + dma_addr_t offset; + + BUG_ON(phys_addr < ireq->request_daddr); + + offset = phys_addr - ireq->request_daddr; + + BUG_ON(offset >= sizeof(*ireq)); + + return (char *)ireq + offset; +} + +/* XXX open code in caller */ +static inline dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sci_req, + void *virt_addr) +{ + struct isci_request *ireq = sci_req_to_ireq(sci_req); + + char *requested_addr = (char *)virt_addr; + char *base_addr = (char *)ireq; + + BUG_ON(requested_addr < base_addr); + BUG_ON((requested_addr - base_addr) >= sizeof(*ireq)); + + return ireq->request_daddr + (requested_addr - base_addr); +} + /** * This function gets the status of the request object. * @request: This parameter points to the isci_request object @@ -337,12 +750,6 @@ static inline void isci_request_unmap_sgl( } } - -void isci_request_io_request_complete( - struct isci_host *isci_host, - struct isci_request *request, - enum sci_io_status completion_status); - /** * isci_request_io_request_get_next_sge() - This function is called by the sci * core to retrieve the next sge for a given request. @@ -385,13 +792,16 @@ static inline void *isci_request_io_request_get_next_sge( return ret; } - -void isci_terminate_pending_requests( - struct isci_host *isci_host, - struct isci_remote_device *isci_device, - enum isci_request_status new_request_state); - - - - +void isci_terminate_pending_requests(struct isci_host *isci_host, + struct isci_remote_device *isci_device, + enum isci_request_status new_request_state); +enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, + struct scic_sds_request *sci_req); +enum sci_status scic_task_request_construct_ssp(struct scic_sds_request *sci_req); +enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req); +enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req); +void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); +void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); #endif /* !defined(_ISCI_REQUEST_H_) */ diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 08dabf08f7d7..b9b9271d4736 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -56,8 +56,6 @@ #include #include "isci.h" #include "remote_device.h" -#include "scic_io_request.h" -#include "scic_task_request.h" #include "task.h" #include "request.h" #include "sata.h" diff --git a/drivers/scsi/isci/smp_request.c b/drivers/scsi/isci/smp_request.c new file mode 100644 index 000000000000..d4750a761c58 --- /dev/null +++ b/drivers/scsi/isci/smp_request.c @@ -0,0 +1,518 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "state_machine.h" +#include "remote_device.h" +#include "request.h" +#include "scu_completion_codes.h" +#include "scu_task_context.h" +#include "host.h" + +static void scu_smp_request_construct_task_context( + struct scic_sds_request *sci_req, + struct smp_req *smp_req); + +void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req) +{ + if (sci_req->was_tag_assigned_by_user == false) + sci_req->task_context_buffer = &sci_req->tc; +} + +/* + * This function will fill in the SCU Task Context for a SMP request. The + * following important settings are utilized: -# task_type == + * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type + * (i.e. non-raw frame) is being utilized to perform task management. -# + * control_frame == 1. This ensures that the proper endianess is set so + * that the bytes are transmitted in the right order for a smp request frame. + * @sci_req: This parameter specifies the smp request object being + * constructed. + * + */ +static void +scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, + struct smp_req *smp_req) +{ + dma_addr_t dma_addr; + struct scic_sds_controller *scic; + struct scic_sds_remote_device *sci_dev; + struct scic_sds_port *sci_port; + struct scu_task_context *task_context; + ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); + + /* byte swap the smp request. */ + sci_swab32_cpy(&sci_req->smp.cmd, smp_req, + word_cnt); + + task_context = scic_sds_request_get_task_context(sci_req); + + scic = scic_sds_request_get_controller(sci_req); + sci_dev = scic_sds_request_get_device(sci_req); + sci_port = scic_sds_request_get_port(sci_req); + + /* + * Fill in the TC with the its required data + * 00h + */ + task_context->priority = 0; + task_context->initiator_request = 1; + task_context->connection_rate = sci_dev->connection_rate; + task_context->protocol_engine_index = + scic_sds_controller_get_protocol_engine_group(scic); + task_context->logical_port_index = scic_sds_port_get_index(sci_port); + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; + task_context->abort = 0; + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + /* 04h */ + task_context->remote_node_index = sci_dev->rnc.remote_node_index; + task_context->command_code = 0; + task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; + + /* 08h */ + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 1; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + /* 0ch */ + task_context->address_modifier = 0; + + /* 10h */ + task_context->ssp_command_iu_length = smp_req->req_len; + + /* 14h */ + task_context->transfer_length_bytes = 0; + + /* + * 18h ~ 30h, protocol specific + * since commandIU has been build by framework at this point, we just + * copy the frist DWord from command IU to this location. */ + memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); + + /* + * 40h + * "For SMP you could program it to zero. We would prefer that way + * so that done code will be consistent." - Venki + */ + task_context->task_phase = 0; + + if (sci_req->was_tag_assigned_by_user) { + /* + * Build the task context now since we have already read + * the data + */ + sci_req->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group(scic) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(sci_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + scic_sds_io_tag_get_index(sci_req->io_tag)); + } else { + /* + * Build the task context now since we have already read + * the data. + * I/O tag index is not assigned because we have to wait + * until we get a TCi. + */ + sci_req->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group(scic) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(sci_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); + } + + /* + * Copy the physical address for the command buffer to the SCU Task + * Context command buffer should not contain command header. + */ + dma_addr = scic_io_request_get_dma_addr(sci_req, + ((char *) &sci_req->smp.cmd) + + sizeof(u32)); + + task_context->command_iu_upper = upper_32_bits(dma_addr); + task_context->command_iu_lower = lower_32_bits(dma_addr); + + /* SMP response comes as UF, so no need to set response IU address. */ + task_context->response_iu_upper = 0; + task_context->response_iu_lower = 0; +} + +/* + * This function processes an unsolicited frame while the SMP request is waiting + * for a response frame. It will copy the response data, release the + * unsolicited frame, and transition the request to the + * SCI_BASE_REQUEST_STATE_COMPLETED state. + * @sci_req: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This function returns an indication of whether the response frame was handled + * successfully or not. SCI_SUCCESS Currently this value is always returned and + * indicates successful processing of the TC response. + */ +static enum sci_status +scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + void *frame_header; + struct smp_resp *rsp_hdr = &sci_req->smp.rsp; + ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); + + status = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_request_get_controller(sci_req)->uf_control), + frame_index, + &frame_header); + + /* byte swap the header. */ + sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); + + if (rsp_hdr->frame_type == SMP_RESPONSE) { + void *smp_resp; + + status = scic_sds_unsolicited_frame_control_get_buffer( + &(scic_sds_request_get_controller(sci_req)->uf_control), + frame_index, + &smp_resp); + + word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / + sizeof(u32); + + sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, + smp_resp, word_cnt); + + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); + + sci_base_state_machine_change_state( + &sci_req->started_substate_machine, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); + } else { + /* This was not a response frame why did it get forwarded? */ + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: SCIC SMP Request 0x%p received unexpected frame " + "%d type 0x%02x\n", + __func__, + sci_req, + frame_index, + rsp_hdr->frame_type); + + scic_sds_request_set_status( + sci_req, + SCU_TASK_DONE_SMP_FRM_TYPE_ERR, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + } + + scic_sds_controller_release_frame(sci_req->owning_controller, + frame_index); + + return SCI_SUCCESS; +} + + +/** + * This method processes an abnormal TC completion while the SMP request is + * waiting for a response frame. It decides what happened to the IO based + * on TC completion status. + * @sci_req: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + /* + * In the AWAIT RESPONSE state, any TC completion is unexpected. + * but if the TC has success status, we complete the IO anyway. */ + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): + /* + * These status has been seen in a specific LSI expander, which sometimes + * is not able to send smp response within 2 ms. This causes our hardware + * break the connection and set TC completion with one of these SMP_XXX_XX_ERR + * status. For these type of error, we ask scic user to retry the request. */ + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + + +/** + * This method processes the completions transport layer (TL) status to + * determine if the SMP request was sent successfully. If the SMP request + * was sent successfully, then the state for the SMP request transits to + * waiting for a response frame. + * @sci_req: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + + +static const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, + .frame_handler = scic_sds_smp_request_await_response_frame_handler, + }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, + } +}; + +/** + * This method performs the actions required when entering the + * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This + * includes setting the IO request state handlers for this sub-state. + * @object: This parameter specifies the request object for which the sub-state + * change is occurring. + * + * none. + */ +static void scic_sds_smp_request_started_await_response_substate_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_smp_request_started_substate_handler_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE + ); +} + +/** + * This method performs the actions required when entering the + * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state. + * This includes setting the SMP request state handlers for this sub-state. + * @object: This parameter specifies the request object for which the sub-state + * change is occurring. + * + * none. + */ +static void scic_sds_smp_request_started_await_tc_completion_substate_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_smp_request_started_substate_handler_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION + ); +} + +static const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { + .enter_state = scic_sds_smp_request_started_await_response_substate_enter, + }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { + .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, + }, +}; + +/** + * This method is called by the SCI user to build an SMP IO request. + * + * - The user must have previously called scic_io_request_construct() on the + * supplied IO request. Indicate if the controller successfully built the IO + * request. SCI_SUCCESS This value is returned if the IO request was + * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned + * if the remote_device does not support the SMP protocol. + * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not + * properly set the association between the SCIC IO request and the user's IO + * request. + */ +enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) +{ + struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); + + if (!smp_req) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + + sci_req->protocol = SCIC_SMP_PROTOCOL; + sci_req->has_started_substate_machine = true; + + /* Construct the started sub-state machine. */ + sci_base_state_machine_construct( + &sci_req->started_substate_machine, + sci_req, + scic_sds_smp_request_started_substate_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE + ); + + /* Construct the SMP SCU Task Context */ + memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req)); + + /* + * Look at the SMP requests' header fields; for certain SAS 1.x SMP + * functions under SAS 2.0, a zero request length really indicates + * a non-zero default length. */ + if (smp_req->req_len == 0) { + switch (smp_req->func) { + case SMP_DISCOVER: + case SMP_REPORT_PHY_ERR_LOG: + case SMP_REPORT_PHY_SATA: + case SMP_REPORT_ROUTE_INFO: + smp_req->req_len = 2; + break; + case SMP_CONF_ROUTE_INFO: + case SMP_PHY_CONTROL: + case SMP_PHY_TEST_FUNCTION: + smp_req->req_len = 9; + break; + /* Default - zero is a valid default for 2.0. */ + } + } + + scu_smp_request_construct_task_context(sci_req, smp_req); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); + + kfree(smp_req); + + return SCI_SUCCESS; +} diff --git a/drivers/scsi/isci/ssp_request.c b/drivers/scsi/isci/ssp_request.c new file mode 100644 index 000000000000..4b6317aeef7d --- /dev/null +++ b/drivers/scsi/isci/ssp_request.c @@ -0,0 +1,240 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "host.h" +#include "request.h" +#include "state_machine.h" +#include "scu_task_context.h" +#include "scu_completion_codes.h" + +/** + * This method processes the completions transport layer (TL) status to + * determine if the RAW task management frame was sent successfully. If the + * raw frame was sent successfully, then the state for the task request + * transitions to waiting for a response frame. + * @sci_req: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->started_substate_machine, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE + ); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): + /* + * Currently, the decision is to simply allow the task request to + * timeout if the task IU wasn't received successfully. + * There is a potential for receiving multiple task responses if we + * decide to send the task IU again. */ + dev_warn(scic_to_dev(sci_req->owning_controller), + "%s: TaskRequest:0x%p CompletionCode:%x - " + "ACK/NAK timeout\n", + __func__, + sci_req, + completion_code); + + sci_base_state_machine_change_state( + &sci_req->started_substate_machine, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + +/** + * This method is responsible for processing a terminate/abort request for this + * TC while the request is waiting for the task management response + * unsolicited frame. + * @sci_req: This parameter specifies the request for which the + * termination was requested. + * + * This method returns an indication as to whether the abort request was + * successfully handled. need to update to ensure the received UF doesn't cause + * damage to subsequent requests (i.e. put the extended tag in a holding + * pattern for this particular device). + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( + struct scic_sds_request *request) +{ + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_ABORTING); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + return SCI_SUCCESS; +} + +/** + * This method processes an unsolicited frame while the task mgmt request is + * waiting for a response frame. It will copy the response data, release + * the unsolicited frame, and transition the request to the + * SCI_BASE_REQUEST_STATE_COMPLETED state. + * @sci_req: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This method returns an indication of whether the TC response frame was + * handled successfully or not. SCI_SUCCESS Currently this value is always + * returned and indicates successful processing of the TC response. Should + * probably update to check frame type and make sure it is a response frame. + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + scic_sds_io_request_copy_response(request); + + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + scic_sds_controller_release_frame(request->owning_controller, + frame_index); + return SCI_SUCCESS; +} + +static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, + }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { + .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, + .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, + } +}; + +/** + * This method performs the actions required when entering the + * SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION + * sub-state. This includes setting the IO request state handlers for this + * sub-state. + * @object: This parameter specifies the request object for which the sub-state + * change is occurring. + * + * none. + */ +static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_ssp_task_request_started_substate_handler_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION + ); +} + +/** + * This method performs the actions required when entering the + * SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This + * includes setting the IO request state handlers for this sub-state. + * @object: This parameter specifies the request object for which the sub-state + * change is occurring. + * + * none. + */ +static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_ssp_task_request_started_substate_handler_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE + ); +} + +const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = { + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { + .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, + }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { + .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, + }, +}; + diff --git a/drivers/scsi/isci/stp_request.c b/drivers/scsi/isci/stp_request.c new file mode 100644 index 000000000000..298086afa5aa --- /dev/null +++ b/drivers/scsi/isci/stp_request.c @@ -0,0 +1,1590 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "sas.h" +#include "state_machine.h" +#include "remote_device.h" +#include "stp_request.h" +#include "unsolicited_frame_control.h" +#include "scu_completion_codes.h" +#include "scu_event_codes.h" +#include "scu_task_context.h" +#include "request.h" + +void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) +{ + if (sci_req->was_tag_assigned_by_user == false) + sci_req->task_context_buffer = &sci_req->tc; +} + +/** + * This method is will fill in the SCU Task Context for any type of SATA + * request. This is called from the various SATA constructors. + * @sci_req: The general IO request object which is to be used in + * constructing the SCU task context. + * @task_context: The buffer pointer for the SCU task context which is being + * constructed. + * + * The general io request construction is complete. The buffer assignment for + * the command buffer is complete. none Revisit task context construction to + * determine what is common for SSP/SMP/STP task context structures. + */ +static void scu_sata_reqeust_construct_task_context( + struct scic_sds_request *sci_req, + struct scu_task_context *task_context) +{ + dma_addr_t dma_addr; + struct scic_sds_controller *controller; + struct scic_sds_remote_device *target_device; + struct scic_sds_port *target_port; + + controller = scic_sds_request_get_controller(sci_req); + target_device = scic_sds_request_get_device(sci_req); + target_port = scic_sds_request_get_port(sci_req); + + /* Fill in the TC with the its required data */ + task_context->abort = 0; + task_context->priority = SCU_TASK_PRIORITY_NORMAL; + task_context->initiator_request = 1; + task_context->connection_rate = target_device->connection_rate; + task_context->protocol_engine_index = + scic_sds_controller_get_protocol_engine_group(controller); + task_context->logical_port_index = + scic_sds_port_get_index(target_port); + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + task_context->remote_node_index = + scic_sds_remote_device_get_index(sci_req->target_device); + task_context->command_code = 0; + + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 0; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + task_context->address_modifier = 0; + task_context->task_phase = 0x01; + + task_context->ssp_command_iu_length = + (sizeof(struct host_to_dev_fis) - sizeof(u32)) / sizeof(u32); + + /* Set the first word of the H2D REG FIS */ + task_context->type.words[0] = *(u32 *)&sci_req->stp.cmd; + + if (sci_req->was_tag_assigned_by_user) { + /* + * Build the task context now since we have already read + * the data + */ + sci_req->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + scic_sds_io_tag_get_index(sci_req->io_tag)); + } else { + /* + * Build the task context now since we have already read + * the data. + * I/O tag index is not assigned because we have to wait + * until we get a TCi. + */ + sci_req->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); + } + + /* + * Copy the physical address for the command buffer to the SCU Task + * Context. We must offset the command buffer by 4 bytes because the + * first 4 bytes are transfered in the body of the TC. + */ + dma_addr = scic_io_request_get_dma_addr(sci_req, + ((char *) &sci_req->stp.cmd) + + sizeof(u32)); + + task_context->command_iu_upper = upper_32_bits(dma_addr); + task_context->command_iu_lower = lower_32_bits(dma_addr); + + /* SATA Requests do not have a response buffer */ + task_context->response_iu_upper = 0; + task_context->response_iu_lower = 0; +} + +/** + * + * @sci_req: + * + * This method will perform any general sata request construction. What part of + * SATA IO request construction is general? none + */ +static void scic_sds_stp_non_ncq_request_construct( + struct scic_sds_request *sci_req) +{ + sci_req->has_started_substate_machine = true; +} + +/** + * + * @sci_req: This parameter specifies the request to be constructed as an + * optimized request. + * @optimized_task_type: This parameter specifies whether the request is to be + * an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A + * value of 1 indicates NCQ. + * + * This method will perform request construction common to all types of STP + * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method + * returns an indication as to whether the construction was successful. + */ +static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sci_req, + u8 optimized_task_type, + u32 len, + enum dma_data_direction dir) +{ + struct scu_task_context *task_context = sci_req->task_context_buffer; + + /* Build the STP task context structure */ + scu_sata_reqeust_construct_task_context(sci_req, task_context); + + /* Copy over the SGL elements */ + scic_sds_request_build_sgl(sci_req); + + /* Copy over the number of bytes to be transfered */ + task_context->transfer_length_bytes = len; + + if (dir == DMA_TO_DEVICE) { + /* + * The difference between the DMA IN and DMA OUT request task type + * values are consistent with the difference between FPDMA READ + * and FPDMA WRITE values. Add the supplied task type parameter + * to this difference to set the task type properly for this + * DATA OUT (WRITE) case. */ + task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT + - SCU_TASK_TYPE_DMA_IN); + } else { + /* + * For the DATA IN (READ) case, simply save the supplied + * optimized task type. */ + task_context->task_type = optimized_task_type; + } +} + +/** + * + * @sci_req: This parameter specifies the request to be constructed. + * + * This method will construct the STP UDMA request and its associated TC data. + * This method returns an indication as to whether the construction was + * successful. SCI_SUCCESS Currently this method always returns this value. + */ +enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_req, + u32 len, + enum dma_data_direction dir) +{ + scic_sds_stp_optimized_request_construct(sci_req, + SCU_TASK_TYPE_FPDMAQ_READ, + len, dir); + return SCI_SUCCESS; +} + +/** + * scu_stp_raw_request_construct_task_context - + * @sci_req: This parameter specifies the STP request object for which to + * construct a RAW command frame task context. + * @task_context: This parameter specifies the SCU specific task context buffer + * to construct. + * + * This method performs the operations common to all SATA/STP requests + * utilizing the raw frame method. none + */ +static void scu_stp_raw_request_construct_task_context( + struct scic_sds_stp_request *stp_req, + struct scu_task_context *task_context) +{ + struct scic_sds_request *sci_req = to_sci_req(stp_req); + + scu_sata_reqeust_construct_task_context(sci_req, task_context); + + task_context->control_frame = 0; + task_context->priority = SCU_TASK_PRIORITY_NORMAL; + task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; + task_context->type.stp.fis_type = FIS_REGH2D; + task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32); +} + +void scic_stp_io_request_set_ncq_tag( + struct scic_sds_request *req, + u16 ncq_tag) +{ + /** + * @note This could be made to return an error to the user if the user + * attempts to set the NCQ tag in the wrong state. + */ + req->task_context_buffer->type.stp.ncq_tag = ncq_tag; +} + +/** + * + * @sci_req: + * + * Get the next SGL element from the request. - Check on which SGL element pair + * we are working - if working on SLG pair element A - advance to element B - + * else - check to see if there are more SGL element pairs for this IO request + * - if there are more SGL element pairs - advance to the next pair and return + * element A struct scu_sgl_element* + */ +static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) +{ + struct scu_sgl_element *current_sgl; + struct scic_sds_request *sci_req = to_sci_req(stp_req); + struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current; + + if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + if (pio_sgl->sgl_pair->B.address_lower == 0 && + pio_sgl->sgl_pair->B.address_upper == 0) { + current_sgl = NULL; + } else { + pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B; + current_sgl = &pio_sgl->sgl_pair->B; + } + } else { + if (pio_sgl->sgl_pair->next_pair_lower == 0 && + pio_sgl->sgl_pair->next_pair_upper == 0) { + current_sgl = NULL; + } else { + u64 phys_addr; + + phys_addr = pio_sgl->sgl_pair->next_pair_upper; + phys_addr <<= 32; + phys_addr |= pio_sgl->sgl_pair->next_pair_lower; + + pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr); + pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A; + current_sgl = &pio_sgl->sgl_pair->A; + } + } + + return current_sgl; +} + +/** + * + * @sci_req: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. + */ +static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + +/** + * + * @request: This parameter specifies the request for which a frame has been + * received. + * @frame_index: This parameter specifies the index of the frame that has been + * received. + * + * This method processes frames received from the target while waiting for a + * device to host register FIS. If a non-register FIS is received during this + * time, it is treated as a protocol violation from an IO perspective. Indicate + * if the received frame was processed successfully. + */ +static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( + struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + struct dev_to_host_fis *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + + return status; + } + + switch (frame_header->fis_type) { + case FIS_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + /* The command has completed with error */ + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", __func__, stp_req, + frame_index); + + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION); + break; + } + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, + } +}; + +static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_non_data_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + sci_req->target_device, sci_req + ); +} + +static void scic_sds_stp_request_started_non_data_await_d2h_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_non_data_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE + ); +} + +/* --------------------------------------------------------------------------- */ + +static const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter, + }, +}; + +enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req) +{ + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + + scic_sds_stp_non_ncq_request_construct(sci_req); + + /* Build the STP task context structure */ + scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); + + sci_base_state_machine_construct(&sci_req->started_substate_machine, + sci_req, + scic_sds_stp_request_started_non_data_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE); + + return SCI_SUCCESS; +} + +#define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ + +/* transmit DATA_FIS from (current sgl + offset) for input + * parameter length. current sgl and offset is alreay stored in the IO request + */ +static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( + struct scic_sds_request *sci_req, + u32 length) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scu_task_context *task_context; + struct scu_sgl_element *current_sgl; + + /* Recycle the TC and reconstruct it for sending out DATA FIS containing + * for the data from current_sgl+offset for the input length + */ + task_context = scic_sds_controller_get_task_context_buffer(scic, + sci_req->io_tag); + + if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) + current_sgl = &stp_req->type.pio.request_current.sgl_pair->A; + else + current_sgl = &stp_req->type.pio.request_current.sgl_pair->B; + + /* update the TC */ + task_context->command_iu_upper = current_sgl->address_upper; + task_context->command_iu_lower = current_sgl->address_lower; + task_context->transfer_length_bytes = length; + task_context->type.stp.fis_type = FIS_DATA; + + /* send the new TC out. */ + return scic_controller_continue_io(sci_req); +} + +static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct scic_sds_request *sci_req) +{ + + struct scu_sgl_element *current_sgl; + u32 sgl_offset; + u32 remaining_bytes_in_current_sgl = 0; + enum sci_status status = SCI_SUCCESS; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + + sgl_offset = stp_req->type.pio.request_current.sgl_offset; + + if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A); + remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->A.length - sgl_offset; + } else { + current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B); + remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->B.length - sgl_offset; + } + + + if (stp_req->type.pio.pio_transfer_bytes > 0) { + if (stp_req->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { + /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ + status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, remaining_bytes_in_current_sgl); + if (status == SCI_SUCCESS) { + stp_req->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; + + /* update the current sgl, sgl_offset and save for future */ + current_sgl = scic_sds_stp_request_pio_get_next_sgl(stp_req); + sgl_offset = 0; + } + } else if (stp_req->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { + /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */ + scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->type.pio.pio_transfer_bytes); + + if (status == SCI_SUCCESS) { + /* Sgl offset will be adjusted and saved for future */ + sgl_offset += stp_req->type.pio.pio_transfer_bytes; + current_sgl->address_lower += stp_req->type.pio.pio_transfer_bytes; + stp_req->type.pio.pio_transfer_bytes = 0; + } + } + } + + if (status == SCI_SUCCESS) { + stp_req->type.pio.request_current.sgl_offset = sgl_offset; + } + + return status; +} + +/** + * + * @stp_request: The request that is used for the SGL processing. + * @data_buffer: The buffer of data to be copied. + * @length: The length of the data transfer. + * + * Copy the data from the buffer for the length specified to the IO reqeust SGL + * specified data region. enum sci_status + */ +static enum sci_status +scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req, + u8 *data_buf, u32 len) +{ + struct scic_sds_request *sci_req; + struct isci_request *ireq; + u8 *src_addr; + int copy_len; + struct sas_task *task; + struct scatterlist *sg; + void *kaddr; + int total_len = len; + + sci_req = to_sci_req(stp_req); + ireq = sci_req_to_ireq(sci_req); + task = isci_request_access_task(ireq); + src_addr = data_buf; + + if (task->num_scatter > 0) { + sg = task->scatter; + + while (total_len > 0) { + struct page *page = sg_page(sg); + + copy_len = min_t(int, total_len, sg_dma_len(sg)); + kaddr = kmap_atomic(page, KM_IRQ0); + memcpy(kaddr + sg->offset, src_addr, copy_len); + kunmap_atomic(kaddr, KM_IRQ0); + total_len -= copy_len; + src_addr += copy_len; + sg = sg_next(sg); + } + } else { + BUG_ON(task->total_xfer_len < total_len); + memcpy(task->scatter, src_addr, total_len); + } + + return SCI_SUCCESS; +} + +/** + * + * @sci_req: The PIO DATA IN request that is to receive the data. + * @data_buffer: The buffer to copy from. + * + * Copy the data buffer to the io request data region. enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( + struct scic_sds_stp_request *sci_req, + u8 *data_buffer) +{ + enum sci_status status; + + /* + * If there is less than 1K remaining in the transfer request + * copy just the data for the transfer */ + if (sci_req->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { + status = scic_sds_stp_request_pio_data_in_copy_data_buffer( + sci_req, data_buffer, sci_req->type.pio.pio_transfer_bytes); + + if (status == SCI_SUCCESS) + sci_req->type.pio.pio_transfer_bytes = 0; + } else { + /* We are transfering the whole frame so copy */ + status = scic_sds_stp_request_pio_data_in_copy_data_buffer( + sci_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); + + if (status == SCI_SUCCESS) + sci_req->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; + } + + return status; +} + +/** + * + * @sci_req: + * @completion_code: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return status; +} + +static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct isci_request *ireq = sci_req_to_ireq(sci_req); + struct sas_task *task = isci_request_access_task(ireq); + struct dev_to_host_fis *frame_header; + enum sci_status status; + u32 *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + switch (frame_header->fis_type) { + case FIS_PIO_SETUP: + /* Get from the frame buffer the PIO Setup Data */ + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + /* Get the data from the PIO Setup The SCU Hardware returns + * first word in the frame_header and the rest of the data is in + * the frame buffer so we need to back up one dword + */ + + /* transfer_count: first 16bits in the 4th dword */ + stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff; + + /* ending_status: 4th byte in the 3rd dword */ + stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + sci_req->stp.rsp.status = stp_req->type.pio.ending_status; + + /* The next state is dependent on whether the + * request was PIO Data-in or Data out + */ + if (task->data_dir == DMA_FROM_DEVICE) { + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); + } else if (task->data_dir == DMA_TO_DEVICE) { + /* Transmit data */ + status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); + if (status != SCI_SUCCESS) + break; + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); + } + break; + case FIS_SETDEVBITS: + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + break; + case FIS_REGD2H: + if (frame_header->status & ATA_BUSY) { + /* Now why is the drive sending a D2H Register FIS when + * it is still busy? Do nothing since we are still in + * the right state. + */ + dev_dbg(scic_to_dev(scic), + "%s: SCIC PIO Request 0x%p received " + "D2H Register FIS with BSY status " + "0x%x\n", __func__, stp_req, + frame_header->status); + break; + } + + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.req, + frame_header, + frame_buffer); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + default: + /* FIXME: what do we do here? */ + break; + } + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + +static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + struct dev_to_host_fis *frame_header; + struct sata_fis_data *frame_buffer; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + if (frame_header->fis_type == FIS_DATA) { + if (stp_req->type.pio.request_current.sgl_pair == NULL) { + sci_req->saved_rx_frame_index = frame_index; + stp_req->type.pio.pio_transfer_bytes = 0; + } else { + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + status = scic_sds_stp_request_pio_data_in_copy_data(stp_req, + (u8 *)frame_buffer); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + } + + /* Check for the end of the transfer, are there more + * bytes remaining for this data transfer + */ + if (status != SCI_SUCCESS || + stp_req->type.pio.pio_transfer_bytes != 0) + return status; + + if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) { + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + } else { + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + } + } else { + dev_err(scic_to_dev(scic), + "%s: SCIC PIO Request 0x%p received frame %d " + "with fis type 0x%02x when expecting a data " + "fis.\n", __func__, stp_req, frame_index, + frame_header->fis_type); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + } + + return status; +} + + +/** + * + * @sci_req: + * @completion_code: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( + + struct scic_sds_request *sci_req, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + bool all_frames_transferred = false; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + /* Transmit data */ + if (stp_req->type.pio.pio_transfer_bytes != 0) { + status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); + if (status == SCI_SUCCESS) { + if (stp_req->type.pio.pio_transfer_bytes == 0) + all_frames_transferred = true; + } + } else if (stp_req->type.pio.pio_transfer_bytes == 0) { + /* + * this will happen if the all data is written at the + * first time after the pio setup fis is received + */ + all_frames_transferred = true; + } + + /* all data transferred. */ + if (all_frames_transferred) { + /* + * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE + * and wait for PIO_SETUP fis / or D2H REg fis. */ + sci_base_state_machine_change_state( + &sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + } + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return status; +} + +/** + * + * @request: This is the request which is receiving the event. + * @event_code: This is the event code that the request on which the request is + * expected to take action. + * + * This method will handle any link layer events while waiting for the data + * frame. enum sci_status SCI_SUCCESS SCI_FAILURE + */ +static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler( + struct scic_sds_request *request, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_specifier(event_code)) { + case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: + /* + * We are waiting for data and the SCU has R_ERR the data frame. + * Go back to waiting for the D2H Register FIS */ + sci_base_state_machine_change_state( + &request->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + + status = SCI_SUCCESS; + break; + + default: + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC PIO Request 0x%p received unexpected " + "event 0x%08x\n", + __func__, request, event_code); + + /* / @todo Should we fail the PIO request when we get an unexpected event? */ + status = SCI_FAILURE; + break; + } + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, + .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, + } +}; + +static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_pio_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + sci_req->target_device, sci_req); +} + +static void scic_sds_stp_request_started_pio_await_frame_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_pio_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); +} + +static void scic_sds_stp_request_started_pio_data_in_await_data_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_pio_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE + ); +} + +static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_pio_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE + ); +} + +/* --------------------------------------------------------------------------- */ + +static const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_await_frame_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter, + } +}; + +enum sci_status +scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, + bool copy_rx_frame) +{ + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; + + scic_sds_stp_non_ncq_request_construct(sci_req); + + scu_stp_raw_request_construct_task_context(stp_req, + sci_req->task_context_buffer); + + pio->current_transfer_bytes = 0; + pio->ending_error = 0; + pio->ending_status = 0; + + pio->request_current.sgl_offset = 0; + pio->request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; + + if (copy_rx_frame) { + scic_sds_request_build_sgl(sci_req); + /* Since the IO request copy of the TC contains the same data as + * the actual TC this pointer is vaild for either. + */ + pio->request_current.sgl_pair = &sci_req->task_context_buffer->sgl_pair_ab; + } else { + /* The user does not want the data copied to the SGL buffer location */ + pio->request_current.sgl_pair = NULL; + } + + sci_base_state_machine_construct(&sci_req->started_substate_machine, + sci_req, + scic_sds_stp_request_started_pio_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE); + + return SCI_SUCCESS; +} + +static void scic_sds_stp_request_udma_complete_request( + struct scic_sds_request *request, + u32 scu_status, + enum sci_status sci_status) +{ + scic_sds_request_set_status(request, scu_status, sci_status); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); +} + +static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; + struct dev_to_host_fis *frame_header; + enum sci_status status; + u32 *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if ((status == SCI_SUCCESS) && + (frame_header->fis_type == FIS_REGD2H)) { + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + } + + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + +static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS); + break; + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): + /* + * We must check ther response buffer to see if the D2H Register FIS was + * received before we got the TC completion. */ + if (sci_req->stp.rsp.fis_type == FIS_REGD2H) { + scic_sds_remote_device_suspend(sci_req->target_device, + SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); + + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + } else { + /* + * If we have an error completion status for the TC then we can expect a + * D2H register FIS from the device so we must change state to wait for it */ + sci_base_state_machine_change_state(&sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE); + } + break; + + /* + * / @todo Check to see if any of these completion status need to wait for + * / the device to host register fis. */ + /* / @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): + scic_sds_remote_device_suspend(sci_req->target_device, + SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); + /* Fall through to the default case */ + default: + /* All other completion status cause the IO to be complete. */ + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + break; + } + + return status; +} + +static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( + struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + + /* Use the general frame handler to copy the resposne data */ + status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); + + if (status != SCI_SUCCESS) + return status; + + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, + .frame_handler = scic_sds_stp_request_udma_general_frame_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, + }, +}; + +static void scic_sds_stp_request_started_udma_await_tc_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_udma_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE + ); +} + +/** + * + * + * This state is entered when there is an TC completion failure. The hardware + * received an unexpected condition while processing the IO request and now + * will UF the D2H register FIS to complete the IO. + */ +static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_udma_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE + ); +} + +/* --------------------------------------------------------------------------- */ + +static const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter, + }, +}; + +enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, + u32 len, + enum dma_data_direction dir) +{ + scic_sds_stp_non_ncq_request_construct(sci_req); + + scic_sds_stp_optimized_request_construct(sci_req, SCU_TASK_TYPE_DMA_IN, + len, dir); + + sci_base_state_machine_construct( + &sci_req->started_substate_machine, + sci_req, + scic_sds_stp_request_started_udma_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE + ); + + return SCI_SUCCESS; +} + +/** + * + * @sci_req: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. + */ +static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + +/** + * + * @sci_req: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. + */ +static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->started_substate_machine, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + +/** + * + * @request: This parameter specifies the request for which a frame has been + * received. + * @frame_index: This parameter specifies the index of the frame that has been + * received. + * + * This method processes frames received from the target while waiting for a + * device to host register FIS. If a non-register FIS is received during this + * time, it is treated as a protocol violation from an IO perspective. Indicate + * if the received frame was processed successfully. + */ +static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( + struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + struct dev_to_host_fis *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + switch (frame_header->fis_type) { + case FIS_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + /* The command has completed with error */ + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", __func__, stp_req, + frame_index); + + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION); + break; + } + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + +/* --------------------------------------------------------------------------- */ + +static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, + }, +}; + +static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_soft_reset_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + sci_req->target_device, sci_req + ); +} + +static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + struct scu_task_context *task_context; + struct host_to_dev_fis *h2d_fis; + enum sci_status status; + + /* Clear the SRST bit */ + h2d_fis = &sci_req->stp.cmd; + h2d_fis->control = 0; + + /* Clear the TC control bit */ + task_context = scic_sds_controller_get_task_context_buffer( + sci_req->owning_controller, sci_req->io_tag); + task_context->control_frame = 0; + + status = scic_controller_continue_io(sci_req); + if (status == SCI_SUCCESS) { + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_soft_reset_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE + ); + } +} + +static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_stp_request_started_soft_reset_substate_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE + ); +} + +static const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = { + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter, + }, +}; + +enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req) +{ + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + + scic_sds_stp_non_ncq_request_construct(sci_req); + + /* Build the STP task context structure */ + scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); + + sci_base_state_machine_construct(&sci_req->started_substate_machine, + sci_req, + scic_sds_stp_request_started_soft_reset_substate_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE); + + return SCI_SUCCESS; +} diff --git a/drivers/scsi/isci/stp_request.h b/drivers/scsi/isci/stp_request.h new file mode 100644 index 000000000000..eb14874ceda3 --- /dev/null +++ b/drivers/scsi/isci/stp_request.h @@ -0,0 +1,195 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SCIC_SDS_STP_REQUEST_T_ +#define _SCIC_SDS_STP_REQUEST_T_ + +#include +#include + +struct scic_sds_stp_request { + union { + u32 ncq; + + u32 udma; + + struct scic_sds_stp_pio_request { + /** + * Total transfer for the entire PIO request recorded at request constuction + * time. + * + * @todo Should we just decrement this value for each byte of data transitted + * or received to elemenate the current_transfer_bytes field? + */ + u32 total_transfer_bytes; + + /** + * Total number of bytes received/transmitted in data frames since the start + * of the IO request. At the end of the IO request this should equal the + * total_transfer_bytes. + */ + u32 current_transfer_bytes; + + /** + * The number of bytes requested in the in the PIO setup. + */ + u32 pio_transfer_bytes; + + /** + * PIO Setup ending status value to tell us if we need to wait for another FIS + * or if the transfer is complete. On the receipt of a D2H FIS this will be + * the status field of that FIS. + */ + u8 ending_status; + + /** + * On receipt of a D2H FIS this will be the ending error field if the + * ending_status has the SATA_STATUS_ERR bit set. + */ + u8 ending_error; + + struct scic_sds_request_pio_sgl { + struct scu_sgl_element_pair *sgl_pair; + u8 sgl_set; + u32 sgl_offset; + } request_current; + } pio; + + struct { + /** + * The number of bytes requested in the PIO setup before CDB data frame. + */ + u32 device_preferred_cdb_length; + } packet; + } type; +}; + +/** + * enum scic_sds_stp_request_started_udma_substates - This enumeration depicts + * the various sub-states associated with a SATA/STP UDMA protocol operation. + * + * + */ +enum scic_sds_stp_request_started_udma_substates { + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, +}; + +/** + * enum scic_sds_stp_request_started_non_data_substates - This enumeration + * depicts the various sub-states associated with a SATA/STP non-data + * protocol operation. + * + * + */ +enum scic_sds_stp_request_started_non_data_substates { + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, +}; + +/** + * enum scic_sds_stp_request_started_soft_reset_substates - THis enumeration + * depicts the various sub-states associated with a SATA/STP soft reset + * operation. + * + * + */ +enum scic_sds_stp_request_started_soft_reset_substates { + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, +}; + +/* This is the enumeration of the SATA PIO DATA IN started substate machine. */ +enum _scic_sds_stp_request_started_pio_substates { + /** + * While in this state the IO request object is waiting for the TC completion + * notification for the H2D Register FIS + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE, + + /** + * While in this state the IO request object is waiting for either a PIO Setup + * FIS or a D2H register FIS. The type of frame received is based on the + * result of the prior frame and line conditions. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE, + + /** + * While in this state the IO request object is waiting for a DATA frame from + * the device. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE, + + /** + * While in this state the IO request object is waiting to transmit the next data + * frame to the device. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, +}; + +struct scic_sds_request; + +enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, + bool copy_rx_frame); +enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, + u32 transfer_length, + enum dma_data_direction dir); +enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req); +enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req); +enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_req, + u32 transfer_length, + enum dma_data_direction dir); +#endif /* _SCIC_SDS_STP_REQUEST_T_ */ diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 2a8603881929..078e2ee4f4be 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -56,15 +56,12 @@ #include #include #include "sas.h" -#include "scic_task_request.h" -#include "scic_io_request.h" #include "remote_device.h" #include "remote_node_context.h" #include "isci.h" #include "request.h" #include "sata.h" #include "task.h" -#include "scic_sds_request.h" #include "timers.h" /** diff --git a/drivers/scsi/isci/unsolicited_frame_control.c b/drivers/scsi/isci/unsolicited_frame_control.c index 8d68dcc52bc1..12e676346386 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.c +++ b/drivers/scsi/isci/unsolicited_frame_control.c @@ -56,7 +56,6 @@ #include "host.h" #include "unsolicited_frame_control.h" #include "registers.h" -#include "sci_util.h" /** * This method will program the unsolicited frames (UFs) into the UF address @@ -93,10 +92,8 @@ static void scic_sds_unsolicited_frame_control_construct_frames( for (index = 0; index < unused_uf_header_entries; index++) { uf = &uf_control->buffers.array[index]; - sci_cb_make_physical_address( - uf_control->address_table.array[index], 0, 0 - ); uf->buffer = NULL; + uf_control->address_table.array[index] = 0; uf->header = &uf_control->headers.array[index]; uf->state = UNSOLICITED_FRAME_EMPTY; } -- cgit v1.2.3 From d35bc1bd18ab9e986cfb67c5a281a70cfd717f05 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 May 2011 02:28:45 -0700 Subject: isci: uplevel phy infrastructure Merge core/scic_sds_phy.[ch] into phy.[ch] Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 1 - drivers/scsi/isci/core/scic_phy.h | 302 --- drivers/scsi/isci/core/scic_port.h | 2 +- drivers/scsi/isci/core/scic_sds_phy.c | 2277 -------------------- drivers/scsi/isci/core/scic_sds_phy.h | 439 ---- drivers/scsi/isci/core/scic_sds_port.c | 2 - .../isci/core/scic_sds_port_configuration_agent.h | 1 - drivers/scsi/isci/phy.c | 2213 ++++++++++++++++++- drivers/scsi/isci/phy.h | 574 ++++- drivers/scsi/isci/port.c | 2 - drivers/scsi/isci/remote_device.c | 2 - 11 files changed, 2784 insertions(+), 3031 deletions(-) delete mode 100644 drivers/scsi/isci/core/scic_phy.h delete mode 100644 drivers/scsi/isci/core/scic_sds_phy.c delete mode 100644 drivers/scsi/isci/core/scic_sds_phy.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index a7d1eb33eca2..2830a97a822a 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -12,4 +12,3 @@ isci-objs := init.o phy.o request.o sata.o \ smp_request.o \ core/scic_sds_port.o \ core/scic_sds_port_configuration_agent.o \ - core/scic_sds_phy.o \ diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h deleted file mode 100644 index f046b4af4b8d..000000000000 --- a/drivers/scsi/isci/core/scic_phy.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_PHY_H_ -#define _SCIC_PHY_H_ - -/** - * This file contains all of the interface methods that can be called by an - * SCIC user on a phy (SAS or SATA) object. - * - * - */ - - -#include -#include - -struct scic_sds_phy; -struct scic_sds_port; - - -enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy); - -struct scic_phy_cap { - union { - struct { - /* - * The SAS specification indicates the start bit shall - * always be set to - * 1. This implementation will have the start bit set - * to 0 if the PHY CAPABILITIES were either not - * received or speed negotiation failed. - */ - u8 start:1; - u8 tx_ssc_type:1; - u8 res1:2; - u8 req_logical_linkrate:4; - - u32 gen1_no_ssc:1; - u32 gen1_ssc:1; - u32 gen2_no_ssc:1; - u32 gen2_ssc:1; - u32 gen3_no_ssc:1; - u32 gen3_ssc:1; - u32 res2:17; - u32 parity:1; - }; - u32 all; - }; -} __packed; - -/* this data structure reflects the link layer transmit identification reg */ -struct scic_phy_proto { - union { - struct { - u16 _r_a:1; - u16 smp_iport:1; - u16 stp_iport:1; - u16 ssp_iport:1; - u16 _r_b:4; - u16 _r_c:1; - u16 smp_tport:1; - u16 stp_tport:1; - u16 ssp_tport:1; - u16 _r_d:4; - }; - u16 all; - }; -} __packed; - - -/** - * struct scic_phy_properties - This structure defines the properties common to - * all phys that can be retrieved. - * - * - */ -struct scic_phy_properties { - /** - * This field specifies the port that currently contains the - * supplied phy. This field may be set to NULL - * if the phy is not currently contained in a port. - */ - struct scic_sds_port *owning_port; - - /** - * This field specifies the link rate at which the phy is - * currently operating. - */ - enum sas_linkrate negotiated_link_rate; - - /** - * This field specifies the index of the phy in relation to other - * phys within the controller. This index is zero relative. - */ - u8 index; -}; - -/** - * struct scic_sas_phy_properties - This structure defines the properties, - * specific to a SAS phy, that can be retrieved. - * - * - */ -struct scic_sas_phy_properties { - /** - * This field delineates the Identify Address Frame received - * from the remote end point. - */ - struct sas_identify_frame rcvd_iaf; - - /** - * This field delineates the Phy capabilities structure received - * from the remote end point. - */ - struct scic_phy_cap rcvd_cap; - -}; - -/** - * struct scic_sata_phy_properties - This structure defines the properties, - * specific to a SATA phy, that can be retrieved. - * - * - */ -struct scic_sata_phy_properties { - /** - * This field delineates the signature FIS received from the - * attached target. - */ - struct dev_to_host_fis signature_fis; - - /** - * This field specifies to the user if a port selector is connected - * on the specified phy. - */ - bool is_port_selector_present; - -}; - -/** - * enum scic_phy_counter_id - This enumeration depicts the various pieces of - * optional information that can be retrieved for a specific phy. - * - * - */ -enum scic_phy_counter_id { - /** - * This PHY information field tracks the number of frames received. - */ - SCIC_PHY_COUNTER_RECEIVED_FRAME, - - /** - * This PHY information field tracks the number of frames transmitted. - */ - SCIC_PHY_COUNTER_TRANSMITTED_FRAME, - - /** - * This PHY information field tracks the number of DWORDs received. - */ - SCIC_PHY_COUNTER_RECEIVED_FRAME_WORD, - - /** - * This PHY information field tracks the number of DWORDs transmitted. - */ - SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD, - - /** - * This PHY information field tracks the number of times DWORD - * synchronization was lost. - */ - SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR, - - /** - * This PHY information field tracks the number of received DWORDs with - * running disparity errors. - */ - SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR, - - /** - * This PHY information field tracks the number of received frames with a - * CRC error (not including short or truncated frames). - */ - SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR, - - /** - * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT) - * primitives received. - */ - SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT, - - /** - * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT) - * primitives transmitted. - */ - SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT, - - /** - * This PHY information field tracks the number of times the inactivity - * timer for connections on the phy has been utilized. - */ - SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED, - - /** - * This PHY information field tracks the number of DONE (CREDIT TIMEOUT) - * primitives received. - */ - SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT, - - /** - * This PHY information field tracks the number of DONE (CREDIT TIMEOUT) - * primitives transmitted. - */ - SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT, - - /** - * This PHY information field tracks the number of CREDIT BLOCKED - * primitives received. - * @note Depending on remote device implementation, credit blocks - * may occur regularly. - */ - SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED, - - /** - * This PHY information field contains the number of short frames - * received. A short frame is simply a frame smaller then what is - * allowed by either the SAS or SATA specification. - */ - SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME, - - /** - * This PHY information field contains the number of frames received after - * credit has been exhausted. - */ - SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT, - - /** - * This PHY information field contains the number of frames received after - * a DONE has been received. - */ - SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE, - - /** - * This PHY information field contains the number of times the phy - * failed to achieve DWORD synchronization during speed negotiation. - */ - SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR -}; - -#endif /* _SCIC_PHY_H_ */ diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h index 51e7eede5c88..431dbd2093f3 100644 --- a/drivers/scsi/isci/core/scic_port.h +++ b/drivers/scsi/isci/core/scic_port.h @@ -58,7 +58,7 @@ #include "isci.h" #include "sas.h" -#include "scic_phy.h" +#include "phy.h" struct scic_sds_port; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c deleted file mode 100644 index 150509b0c69e..000000000000 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ /dev/null @@ -1,2277 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "sas.h" -#include "host.h" -#include "state_machine.h" -#include "scic_phy.h" -#include "scic_sds_phy.h" -#include "scic_sds_port.h" -#include "remote_node_context.h" -#include "scu_event_codes.h" -#include "timers.h" - -#define SCIC_SDS_PHY_MIN_TIMER_COUNT (SCI_MAX_PHYS) -#define SCIC_SDS_PHY_MAX_TIMER_COUNT (SCI_MAX_PHYS) - -/* Maximum arbitration wait time in micro-seconds */ -#define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) - -enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy) -{ - return sci_phy->max_negotiated_speed; -} - -/* - * ***************************************************************************** - * * SCIC SDS PHY Internal Methods - * ***************************************************************************** */ - -/** - * This method will initialize the phy transport layer registers - * @sci_phy: - * @transport_layer_registers - * - * enum sci_status - */ -static enum sci_status scic_sds_phy_transport_layer_initialization( - struct scic_sds_phy *sci_phy, - struct scu_transport_layer_registers __iomem *transport_layer_registers) -{ - u32 tl_control; - - sci_phy->transport_layer_registers = transport_layer_registers; - - writel(SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX, - &sci_phy->transport_layer_registers->stp_rni); - - /* - * Hardware team recommends that we enable the STP prefetch for all - * transports - */ - tl_control = readl(&sci_phy->transport_layer_registers->control); - tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); - writel(tl_control, &sci_phy->transport_layer_registers->control); - - return SCI_SUCCESS; -} - -/** - * This method will initialize the phy link layer registers - * @sci_phy: - * @link_layer_registers: - * - * enum sci_status - */ -static enum sci_status -scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, - struct scu_link_layer_registers __iomem *link_layer_registers) -{ - struct scic_sds_controller *scic = - sci_phy->owning_port->owning_controller; - int phy_idx = sci_phy->phy_index; - struct sci_phy_user_params *phy_user = - &scic->user_parameters.sds1.phys[phy_idx]; - struct sci_phy_oem_params *phy_oem = - &scic->oem_parameters.sds1.phys[phy_idx]; - u32 phy_configuration; - struct scic_phy_cap phy_cap; - u32 parity_check = 0; - u32 parity_count = 0; - u32 llctl, link_rate; - u32 clksm_value = 0; - - sci_phy->link_layer_registers = link_layer_registers; - - /* Set our IDENTIFY frame data */ - #define SCI_END_DEVICE 0x01 - - writel(SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) | - SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) | - SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) | - SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) | - SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE), - &sci_phy->link_layer_registers->transmit_identification); - - /* Write the device SAS Address */ - writel(0xFEDCBA98, - &sci_phy->link_layer_registers->sas_device_name_high); - writel(phy_idx, &sci_phy->link_layer_registers->sas_device_name_low); - - /* Write the source SAS Address */ - writel(phy_oem->sas_address.high, - &sci_phy->link_layer_registers->source_sas_address_high); - writel(phy_oem->sas_address.low, - &sci_phy->link_layer_registers->source_sas_address_low); - - /* Clear and Set the PHY Identifier */ - writel(0, &sci_phy->link_layer_registers->identify_frame_phy_id); - writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), - &sci_phy->link_layer_registers->identify_frame_phy_id); - - /* Change the initial state of the phy configuration register */ - phy_configuration = - readl(&sci_phy->link_layer_registers->phy_configuration); - - /* Hold OOB state machine in reset */ - phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - writel(phy_configuration, - &sci_phy->link_layer_registers->phy_configuration); - - /* Configure the SNW capabilities */ - phy_cap.all = 0; - phy_cap.start = 1; - phy_cap.gen3_no_ssc = 1; - phy_cap.gen2_no_ssc = 1; - phy_cap.gen1_no_ssc = 1; - if (scic->oem_parameters.sds1.controller.do_enable_ssc == true) { - phy_cap.gen3_ssc = 1; - phy_cap.gen2_ssc = 1; - phy_cap.gen1_ssc = 1; - } - - /* - * The SAS specification indicates that the phy_capabilities that - * are transmitted shall have an even parity. Calculate the parity. */ - parity_check = phy_cap.all; - while (parity_check != 0) { - if (parity_check & 0x1) - parity_count++; - parity_check >>= 1; - } - - /* - * If parity indicates there are an odd number of bits set, then - * set the parity bit to 1 in the phy capabilities. */ - if ((parity_count % 2) != 0) - phy_cap.parity = 1; - - writel(phy_cap.all, &sci_phy->link_layer_registers->phy_capabilities); - - /* Set the enable spinup period but disable the ability to send - * notify enable spinup - */ - writel(SCU_ENSPINUP_GEN_VAL(COUNT, - phy_user->notify_enable_spin_up_insertion_frequency), - &sci_phy->link_layer_registers->notify_enable_spinup_control); - - /* Write the ALIGN Insertion Ferequency for connected phy and - * inpendent of connected state - */ - clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(CONNECTED, - phy_user->in_connection_align_insertion_frequency); - - clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL, - phy_user->align_insertion_frequency); - - writel(clksm_value, &sci_phy->link_layer_registers->clock_skew_management); - - /* @todo Provide a way to write this register correctly */ - writel(0x02108421, - &sci_phy->link_layer_registers->afe_lookup_table_control); - - llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, - (u8)scic->user_parameters.sds1.no_outbound_task_timeout); - - switch(phy_user->max_speed_generation) { - case SCIC_SDS_PARM_GEN3_SPEED: - link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3; - break; - case SCIC_SDS_PARM_GEN2_SPEED: - link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2; - break; - default: - link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1; - break; - } - llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate); - writel(llctl, &sci_phy->link_layer_registers->link_layer_control); - - if (is_a0() || is_a2()) { - /* Program the max ARB time for the PHY to 700us so we inter-operate with - * the PMC expander which shuts down PHYs if the expander PHY generates too - * many breaks. This time value will guarantee that the initiator PHY will - * generate the break. - */ - writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME, - &sci_phy->link_layer_registers->maximum_arbitration_wait_timer_timeout); - } - - /* - * Set the link layer hang detection to 500ms (0x1F4) from its default - * value of 128ms. Max value is 511 ms. - */ - writel(0x1F4, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout); - - /* We can exit the initial state to the stopped state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); - - return SCI_SUCCESS; -} - -/** - * This function will handle the sata SIGNATURE FIS timeout condition. It will - * restart the starting substate machine since we dont know what has actually - * happening. - */ -static void scic_sds_phy_sata_timeout(void *phy) -{ - struct scic_sds_phy *sci_phy = phy; - - dev_dbg(sciphy_to_dev(sci_phy), - "%s: SCIC SDS Phy 0x%p did not receive signature fis before " - "timeout.\n", - __func__, - sci_phy); - - sci_base_state_machine_stop(&sci_phy->starting_substate_machine); - - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); -} - -/** - * This method returns the port currently containing this phy. If the phy is - * currently contained by the dummy port, then the phy is considered to not - * be part of a port. - * @sci_phy: This parameter specifies the phy for which to retrieve the - * containing port. - * - * This method returns a handle to a port that contains the supplied phy. - * NULL This value is returned if the phy is not part of a real - * port (i.e. it's contained in the dummy port). !NULL All other - * values indicate a handle/pointer to the port containing the phy. - */ -struct scic_sds_port *scic_sds_phy_get_port( - struct scic_sds_phy *sci_phy) -{ - if (scic_sds_port_get_index(sci_phy->owning_port) == SCIC_SDS_DUMMY_PORT) - return NULL; - - return sci_phy->owning_port; -} - -/** - * This method will assign a port to the phy object. - * @out]: sci_phy This parameter specifies the phy for which to assign a port - * object. - * - * - */ -void scic_sds_phy_set_port( - struct scic_sds_phy *sci_phy, - struct scic_sds_port *sci_port) -{ - sci_phy->owning_port = sci_port; - - if (sci_phy->bcn_received_while_port_unassigned) { - sci_phy->bcn_received_while_port_unassigned = false; - scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); - } -} - -/** - * This method will initialize the constructed phy - * @sci_phy: - * @link_layer_registers: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_initialize( - struct scic_sds_phy *sci_phy, - struct scu_transport_layer_registers __iomem *transport_layer_registers, - struct scu_link_layer_registers __iomem *link_layer_registers) -{ - struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - struct isci_host *ihost = scic_to_ihost(scic); - - /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = - isci_timer_create( - ihost, - sci_phy, - scic_sds_phy_sata_timeout); - - /* Perfrom the initialization of the TL hardware */ - scic_sds_phy_transport_layer_initialization( - sci_phy, - transport_layer_registers); - - /* Perofrm the initialization of the PE hardware */ - scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers); - - /* - * There is nothing that needs to be done in this state just - * transition to the stopped state. */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); - - return SCI_SUCCESS; -} - -/** - * This method assigns the direct attached device ID for this phy. - * - * @sci_phy The phy for which the direct attached device id is to - * be assigned. - * @device_id The direct attached device ID to assign to the phy. - * This will either be the RNi for the device or an invalid RNi if there - * is no current device assigned to the phy. - */ -void scic_sds_phy_setup_transport( - struct scic_sds_phy *sci_phy, - u32 device_id) -{ - u32 tl_control; - - writel(device_id, &sci_phy->transport_layer_registers->stp_rni); - - /* - * The read should guarantee that the first write gets posted - * before the next write - */ - tl_control = readl(&sci_phy->transport_layer_registers->control); - tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); - writel(tl_control, &sci_phy->transport_layer_registers->control); -} - -/** - * - * @sci_phy: The phy object to be suspended. - * - * This function will perform the register reads/writes to suspend the SCU - * hardware protocol engine. none - */ -static void scic_sds_phy_suspend( - struct scic_sds_phy *sci_phy) -{ - u32 scu_sas_pcfg_value; - - scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); - scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); - writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); - - scic_sds_phy_setup_transport( - sci_phy, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); -} - -void scic_sds_phy_resume(struct scic_sds_phy *sci_phy) -{ - u32 scu_sas_pcfg_value; - - scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); - scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); - writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); -} - -void scic_sds_phy_get_sas_address(struct scic_sds_phy *sci_phy, - struct sci_sas_address *sas_address) -{ - sas_address->high = readl(&sci_phy->link_layer_registers->source_sas_address_high); - sas_address->low = readl(&sci_phy->link_layer_registers->source_sas_address_low); -} - -void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy, - struct sci_sas_address *sas_address) -{ - struct sas_identify_frame *iaf; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - iaf = &iphy->frame_rcvd.iaf; - memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); -} - -void scic_sds_phy_get_protocols(struct scic_sds_phy *sci_phy, - struct scic_phy_proto *protocols) -{ - protocols->all = - (u16)(readl(&sci_phy-> - link_layer_registers->transmit_identification) & - 0x0000FFFF); -} - -/** - * This method will attempt to start the phy object. This request is only valid - * when the phy is in the stopped state - * @sci_phy: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) -{ - return sci_phy->state_handlers->start_handler(sci_phy); -} - -/** - * This method will attempt to stop the phy object. - * @sci_phy: - * - * enum sci_status SCI_SUCCESS if the phy is going to stop SCI_INVALID_STATE - * if the phy is not in a valid state to stop - */ -enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) -{ - return sci_phy->state_handlers->stop_handler(sci_phy); -} - -/** - * This method will attempt to reset the phy. This request is only valid when - * the phy is in an ready state - * @sci_phy: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_reset( - struct scic_sds_phy *sci_phy) -{ - return sci_phy->state_handlers->reset_handler(sci_phy); -} - -/** - * This method will process the event code received. - * @sci_phy: - * @event_code: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - return sci_phy->state_handlers->event_handler(sci_phy, event_code); -} - -/** - * This method will process the frame index received. - * @sci_phy: - * @frame_index: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_frame_handler( - struct scic_sds_phy *sci_phy, - u32 frame_index) -{ - return sci_phy->state_handlers->frame_handler(sci_phy, frame_index); -} - -/** - * This method will give the phy permission to consume power - * @sci_phy: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_consume_power_handler( - struct scic_sds_phy *sci_phy) -{ - return sci_phy->state_handlers->consume_power_handler(sci_phy); -} - -/* - * ***************************************************************************** - * * SCIC SDS PHY HELPER FUNCTIONS - * ***************************************************************************** */ - - -/** - * - * @sci_phy: The phy object that received SAS PHY DETECTED. - * - * This method continues the link training for the phy as if it were a SAS PHY - * instead of a SATA PHY. This is done because the completion queue had a SAS - * PHY DETECTED event when the state machine was expecting a SATA PHY event. - * none - */ -static void scic_sds_phy_start_sas_link_training( - struct scic_sds_phy *sci_phy) -{ - u32 phy_control; - - phy_control = - readl(&sci_phy->link_layer_registers->phy_configuration); - phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); - writel(phy_control, - &sci_phy->link_layer_registers->phy_configuration); - - sci_base_state_machine_change_state( - &sci_phy->starting_substate_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN - ); - - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; -} - -/** - * - * @sci_phy: The phy object that received a SATA SPINUP HOLD event - * - * This method continues the link training for the phy as if it were a SATA PHY - * instead of a SAS PHY. This is done because the completion queue had a SATA - * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none - */ -static void scic_sds_phy_start_sata_link_training( - struct scic_sds_phy *sci_phy) -{ - sci_base_state_machine_change_state( - &sci_phy->starting_substate_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER - ); - - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; -} - -/** - * scic_sds_phy_complete_link_training - perform processing common to - * all protocols upon completion of link training. - * @sci_phy: This parameter specifies the phy object for which link training - * has completed. - * @max_link_rate: This parameter specifies the maximum link rate to be - * associated with this phy. - * @next_state: This parameter specifies the next state for the phy's starting - * sub-state machine. - * - */ -static void scic_sds_phy_complete_link_training( - struct scic_sds_phy *sci_phy, - enum sas_linkrate max_link_rate, - u32 next_state) -{ - sci_phy->max_negotiated_speed = max_link_rate; - - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, - next_state); -} - -static void scic_sds_phy_restart_starting_state( - struct scic_sds_phy *sci_phy) -{ - /* Stop the current substate machine */ - sci_base_state_machine_stop(&sci_phy->starting_substate_machine); - - /* Re-enter the base state machine starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); -} - -/* **************************************************************************** - * SCIC SDS PHY general handlers - ************************************************************************** */ -static enum sci_status scic_sds_phy_starting_substate_general_stop_handler( - struct scic_sds_phy *phy) -{ - sci_base_state_machine_stop(&phy->starting_substate_machine); - - sci_base_state_machine_change_state(&phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); - - return SCI_SUCCESS; -} - -/* - * ***************************************************************************** - * * SCIC SDS PHY EVENT_HANDLERS - * ***************************************************************************** */ - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - - * decode the event - sas phy detected causes a state transition to the wait - * for speed event notification. - any other events log a warning message and - * set a failure status enum sci_status SCI_SUCCESS on any valid event notification - * SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SAS_PHY_DETECTED: - scic_sds_phy_start_sas_link_training(sci_phy); - sci_phy->is_in_link_training = true; - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - scic_sds_phy_start_sata_link_training(sci_phy); - sci_phy->is_in_link_training = true; - break; - - default: - dev_dbg(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - - * decode the event - sas phy detected returns us back to this state. - speed - * event detected causes a state transition to the wait for iaf. - identify - * timeout is an un-expected event and the state machine is restarted. - link - * failure events restart the starting state machine - any other events log a - * warning message and set a failure status enum sci_status SCI_SUCCESS on any valid - * event notification SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SAS_PHY_DETECTED: - /* - * Why is this being reported again by the controller? - * We would re-enter this state so just stay here */ - break; - - case SCU_EVENT_SAS_15: - case SCU_EVENT_SAS_15_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_1_5_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); - break; - - case SCU_EVENT_SAS_30: - case SCU_EVENT_SAS_30_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_3_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); - break; - - case SCU_EVENT_SAS_60: - case SCU_EVENT_SAS_60_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_6_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - /* - * We were doing SAS PHY link training and received a SATA PHY event - * continue OOB/SN as if this were a SATA PHY */ - scic_sds_phy_start_sata_link_training(sci_phy); - break; - - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - - * decode the event - sas phy detected event backs up the state machine to the - * await speed notification. - identify timeout is an un-expected event and the - * state machine is restarted. - link failure events restart the starting state - * machine - any other events log a warning message and set a failure status - * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any - * unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SAS_PHY_DETECTED: - /* Backup the state machine */ - scic_sds_phy_start_sas_link_training(sci_phy); - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - /* - * We were doing SAS PHY link training and received a SATA PHY event - * continue OOB/SN as if this were a SATA PHY */ - scic_sds_phy_start_sata_link_training(sci_phy); - break; - - case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: - case SCU_EVENT_LINK_FAILURE: - case SCU_EVENT_HARD_RESET_RECEIVED: - /* Start the oob/sn state machine over again */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER. - - * decode the event - link failure events restart the starting state machine - - * any other events log a warning message and set a failure status enum sci_status - * SCI_SUCCESS on a link failure event SCI_FAILURE on any unexpected event - * notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received unexpected " - "event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - - * decode the event - link failure events restart the starting state machine - - * sata spinup hold events are ignored since they are expected - any other - * events log a warning message and set a failure status enum sci_status SCI_SUCCESS - * on a link failure event SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - /* These events are received every 10ms and are expected while in this state */ - break; - - case SCU_EVENT_SAS_PHY_DETECTED: - /* - * There has been a change in the phy type before OOB/SN for the - * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * scic_sds_phy_starting_substate_await_sata_phy_event_handler - - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - - * decode the event - link failure events restart the starting state machine - - * sata spinup hold events are ignored since they are expected - sata phy - * detected event change to the wait speed event - any other events log a - * warning message and set a failure status enum sci_status SCI_SUCCESS on a link - * failure event SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handler( - struct scic_sds_phy *sci_phy, u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - /* These events might be received since we dont know how many may be in - * the completion queue while waiting for power - */ - break; - - case SCU_EVENT_SATA_PHY_DETECTED: - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; - - /* We have received the SATA PHY notification change state */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); - break; - - case SCU_EVENT_SAS_PHY_DETECTED: - /* There has been a change in the phy type before OOB/SN for the - * SATA finished start down the SAS link traning path. - */ - scic_sds_phy_start_sas_link_training(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - * - decode the event - sata phy detected returns us back to this state. - - * speed event detected causes a state transition to the wait for signature. - - * link failure events restart the starting state machine - any other events - * log a warning message and set a failure status enum sci_status SCI_SUCCESS on any - * valid event notification SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SATA_PHY_DETECTED: - /* - * The hardware reports multiple SATA PHY detected events - * ignore the extras */ - break; - - case SCU_EVENT_SATA_15: - case SCU_EVENT_SATA_15_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_1_5_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); - break; - - case SCU_EVENT_SATA_30: - case SCU_EVENT_SATA_30_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_3_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); - break; - - case SCU_EVENT_SATA_60: - case SCU_EVENT_SATA_60_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_6_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); - break; - - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - case SCU_EVENT_SAS_PHY_DETECTED: - /* - * There has been a change in the phy type before OOB/SN for the - * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * scic_sds_phy_starting_substate_await_sig_fis_event_handler - - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - - * decode the event - sas phy detected event backs up the state machine to the - * await speed notification. - identify timeout is an un-expected event and the - * state machine is restarted. - link failure events restart the starting state - * machine - any other events log a warning message and set a failure status - * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any - * unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handler( - struct scic_sds_phy *sci_phy, u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SATA_PHY_DETECTED: - /* Backup the state machine */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); - break; - - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - - -/* - * ***************************************************************************** - * * SCIC SDS PHY FRAME_HANDLERS - * ***************************************************************************** */ - -/** - * - * @phy: This is struct scic_sds_phy object which is being requested to decode the - * frame data. - * @frame_index: This is the index of the unsolicited frame which was received - * for this phy. - * - * This method decodes the unsolicited frame when the struct scic_sds_phy is in the - * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Get the UF Header - If the UF - * is an IAF - Copy IAF data to local phy object IAF data buffer. - Change - * starting substate to wait power. - else - log warning message of unexpected - * unsolicted frame - release frame buffer enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler( - struct scic_sds_phy *sci_phy, u32 frame_index) -{ - enum sci_status result; - u32 *frame_words; - struct sas_identify_frame iaf; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(sci_phy)->uf_control), - frame_index, - (void **)&frame_words); - - if (result != SCI_SUCCESS) - return result; - - sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32)); - if (iaf.frame_type == 0) { - u32 state; - - memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf)); - if (iaf.smp_tport) { - /* We got the IAF for an expander PHY go to the final - * state since there are no power requirements for - * expander phys. - */ - state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; - } else { - /* We got the IAF we can now go to the await spinup - * semaphore state - */ - state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; - } - sci_base_state_machine_change_state( - &sci_phy->starting_substate_machine, - state); - result = SCI_SUCCESS; - } else - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected frame id %x\n", - __func__, - frame_index); - - scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), - frame_index); - - return result; -} - -/** - * - * @phy: This is struct scic_sds_phy object which is being requested to decode the - * frame data. - * @frame_index: This is the index of the unsolicited frame which was received - * for this phy. - * - * This method decodes the unsolicited frame when the struct scic_sds_phy is in the - * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Get the UF Header - If - * the UF is an SIGNATURE FIS - Copy IAF data to local phy object SIGNATURE FIS - * data buffer. - else - log warning message of unexpected unsolicted frame - - * release frame buffer enum sci_status SCI_SUCCESS Must decode the SIGNATURE FIS - * data - */ -static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handler( - struct scic_sds_phy *sci_phy, - u32 frame_index) -{ - enum sci_status result; - struct dev_to_host_fis *frame_header; - u32 *fis_frame_data; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(sci_phy)->uf_control), - frame_index, - (void **)&frame_header); - - if (result != SCI_SUCCESS) - return result; - - if ((frame_header->fis_type == FIS_REGD2H) && - !(frame_header->status & ATA_BUSY)) { - scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_phy_get_controller(sci_phy)->uf_control), - frame_index, - (void **)&fis_frame_data); - - scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, - frame_header, - fis_frame_data); - - /* got IAF we can now go to the await spinup semaphore state */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); - - result = SCI_SUCCESS; - } else - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected frame id %x\n", - __func__, - frame_index); - - /* Regardless of the result we are done with this frame with it */ - scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), - frame_index); - - return result; -} - -/* - * ***************************************************************************** - * * SCIC SDS PHY POWER_HANDLERS - * ***************************************************************************** */ - -/* - * This method is called by the struct scic_sds_controller when the phy object is - * granted power. - The notify enable spinups are turned on for this phy object - * - The phy state machine is transitioned to the - * SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_power_handler( - struct scic_sds_phy *sci_phy) -{ - u32 enable_spinup; - - enable_spinup = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); - enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); - writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control); - - /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); - - return SCI_SUCCESS; -} - -/* - * This method is called by the struct scic_sds_controller when the phy object is - * granted power. - The phy state machine is transitioned to the - * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_power_handler( - struct scic_sds_phy *sci_phy) -{ - u32 scu_sas_pcfg_value; - - /* Release the spinup hold state and reset the OOB state machine */ - scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); - scu_sas_pcfg_value &= - ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); - scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); - - /* Now restart the OOB operation */ - scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); - writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); - - /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); - - return SCI_SUCCESS; -} - -static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, - const char *func) -{ - dev_dbg(sciphy_to_dev(sci_phy), - "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&sci_phy->state_machine)); - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status -scic_sds_phy_default_start_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - -static enum sci_status -scic_sds_phy_default_stop_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - -static enum sci_status -scic_sds_phy_default_reset_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - -static enum sci_status -scic_sds_phy_default_destroy_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - -static enum sci_status -scic_sds_phy_default_frame_handler(struct scic_sds_phy *sci_phy, - u32 frame_index) -{ - struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - - default_phy_handler(sci_phy, __func__); - scic_sds_controller_release_frame(scic, frame_index); - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status -scic_sds_phy_default_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) -{ - return default_phy_handler(sci_phy, __func__); -} - -static enum sci_status -scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - - - -static const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = { - [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, - .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, - .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, - .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - } -}; - -/** - * scic_sds_phy_set_starting_substate_handlers() - - * - * This macro sets the starting substate handlers by state_id - */ -#define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \ - scic_sds_phy_set_state_handlers(\ - (phy), \ - &scic_sds_phy_starting_substate_handler_table[(state_id)] \ - ) - -/* - * **************************************************************************** - * * PHY STARTING SUBSTATE METHODS - * **************************************************************************** */ - -/** - * scic_sds_phy_starting_initial_substate_enter - - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL. - The initial state - * handlers are put in place for the struct scic_sds_phy object. - The state is - * changed to the wait phy type event notification. none - */ -static void scic_sds_phy_starting_initial_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); - - /* This is just an temporary state go off to the starting state */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ -static void scic_sds_phy_starting_await_ossp_en_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ -static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( - void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ -static void scic_sds_phy_starting_await_iaf_uf_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Set the - * struct scic_sds_phy object state handlers for this state. - Add this phy object to - * the power control queue none - */ -static void scic_sds_phy_starting_await_sas_power_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER - ); - - scic_sds_controller_power_control_queue_insert( - scic_sds_phy_get_controller(sci_phy), - sci_phy - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Remove the - * struct scic_sds_phy object from the power control queue. none - */ -static void scic_sds_phy_starting_await_sas_power_substate_exit(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_controller_power_control_queue_remove( - scic_sds_phy_get_controller(sci_phy), sci_phy - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Set the - * struct scic_sds_phy object state handlers for this state. - Add this phy object to - * the power control queue none - */ -static void scic_sds_phy_starting_await_sata_power_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER - ); - - scic_sds_controller_power_control_queue_insert( - scic_sds_phy_get_controller(sci_phy), - sci_phy - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Remove the - * struct scic_sds_phy object from the power control queue. none - */ -static void scic_sds_phy_starting_await_sata_power_substate_exit(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_controller_power_control_queue_remove( - scic_sds_phy_get_controller(sci_phy), - sci_phy - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ -static void scic_sds_phy_starting_await_sata_phy_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); - - isci_timer_start(sci_phy->sata_timeout_timer, - SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy - * on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer - * that was started on entry to await sata phy event notification none - */ -static inline void scic_sds_phy_starting_await_sata_phy_substate_exit( - void *object) -{ - struct scic_sds_phy *sci_phy = object; - - isci_timer_stop(sci_phy->sata_timeout_timer); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ -static void scic_sds_phy_starting_await_sata_speed_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); - - isci_timer_start(sci_phy->sata_timeout_timer, - SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the - * struct scic_sds_phy on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer - * that was started on entry to await sata phy event notification none - */ -static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( - void *object) -{ - struct scic_sds_phy *sci_phy = object; - - isci_timer_stop(sci_phy->sata_timeout_timer); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Set the - * struct scic_sds_phy object state handlers for this state. - * - Start the SIGNATURE FIS - * timeout timer none - */ -static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) -{ - bool continue_to_ready_state; - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers( - sci_phy, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); - - continue_to_ready_state = scic_sds_port_link_detected( - sci_phy->owning_port, - sci_phy); - - if (continue_to_ready_state) { - /* - * Clear the PE suspend condition so we can actually - * receive SIG FIS - * The hardware will not respond to the XRDY until the PE - * suspend condition is cleared. - */ - scic_sds_phy_resume(sci_phy); - - isci_timer_start(sci_phy->sata_timeout_timer, - SCIC_SDS_SIGNATURE_FIS_TIMEOUT); - } else - sci_phy->is_in_link_training = false; -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the - * struct scic_sds_phy on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Stop the SIGNATURE - * FIS timeout timer. none - */ -static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( - void *object) -{ - struct scic_sds_phy *sci_phy = object; - - isci_timer_stop(sci_phy->sata_timeout_timer); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. - Set the struct scic_sds_phy - * object state handlers for this state. - Change base state machine to the - * ready state. none - */ -static void scic_sds_phy_starting_final_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_starting_substate_handlers(sci_phy, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); - - /* State machine has run to completion so exit out and change - * the base state machine to the ready state - */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_READY); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_phy_starting_substates[] = { - [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .enter_state = scic_sds_phy_starting_initial_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .enter_state = scic_sds_phy_starting_await_ossp_en_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .enter_state = scic_sds_phy_starting_await_sas_speed_en_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .enter_state = scic_sds_phy_starting_await_iaf_uf_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, - .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter, - .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .enter_state = scic_sds_phy_starting_final_substate_enter, - } -}; - -/* - * This method takes the struct scic_sds_phy from a stopped state and - * attempts to start it. - The phy state machine is transitioned to the - * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS - */ -static enum sci_status -scic_sds_phy_stopped_state_start_handler(struct scic_sds_phy *sci_phy) -{ - struct isci_host *ihost; - struct scic_sds_controller *scic; - - scic = scic_sds_phy_get_controller(sci_phy), - ihost = scic_to_ihost(scic); - - /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, - scic_sds_phy_sata_timeout); - - if (sci_phy->sata_timeout_timer) - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - - return SCI_SUCCESS; -} - -static enum sci_status -scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) -{ - return SCI_SUCCESS; -} - -static enum sci_status -scic_sds_phy_ready_state_stop_handler(struct scic_sds_phy *sci_phy) -{ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); - - return SCI_SUCCESS; -} - -static enum sci_status -scic_sds_phy_ready_state_reset_handler(struct scic_sds_phy *sci_phy) -{ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_RESETTING); - - return SCI_SUCCESS; -} - -/** - * scic_sds_phy_ready_state_event_handler - - * @phy: This is the struct scic_sds_phy object which has received the event. - * - * This method request the struct scic_sds_phy handle the received event. The only - * event that we are interested in while in the ready state is the link failure - * event. - decoded event is a link failure - transition the struct scic_sds_phy back - * to the SCI_BASE_PHY_STATE_STARTING state. - any other event received will - * report a warning message enum sci_status SCI_SUCCESS if the event received is a - * link failure SCI_FAILURE_INVALID_STATE for any other event received. - */ -static enum sci_status scic_sds_phy_ready_state_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) -{ - enum sci_status result = SCI_FAILURE; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - result = SCI_SUCCESS; - break; - - case SCU_EVENT_BROADCAST_CHANGE: - /* Broadcast change received. Notify the port. */ - if (scic_sds_phy_get_port(sci_phy) != NULL) - scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); - else - sci_phy->bcn_received_while_port_unassigned = true; - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%sP SCIC PHY 0x%p ready state machine received " - "unexpected event_code %x\n", - __func__, sci_phy, event_code); - - result = SCI_FAILURE_INVALID_STATE; - break; - } - - return result; -} - -static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) -{ - enum sci_status result = SCI_FAILURE; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_HARD_RESET_TRANSMITTED: - /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - result = SCI_SUCCESS; - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: SCIC PHY 0x%p resetting state machine received " - "unexpected event_code %x\n", - __func__, sci_phy, event_code); - - result = SCI_FAILURE_INVALID_STATE; - break; - } - - return result; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { - [SCI_BASE_PHY_STATE_INITIAL] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_STOPPED] = { - .start_handler = scic_sds_phy_stopped_state_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_STARTING] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_READY] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_ready_state_stop_handler, - .reset_handler = scic_sds_phy_ready_state_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_ready_state_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_RESETTING] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_resetting_state_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_FINAL] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - } -}; - -/* - * **************************************************************************** - * * PHY STATE PRIVATE METHODS - * **************************************************************************** */ - -/** - * - * @sci_phy: This is the struct scic_sds_phy object to stop. - * - * This method will stop the struct scic_sds_phy object. This does not reset the - * protocol engine it just suspends it and places it in a state where it will - * not cause the end device to power up. none - */ -static void scu_link_layer_stop_protocol_engine( - struct scic_sds_phy *sci_phy) -{ - u32 scu_sas_pcfg_value; - u32 enable_spinup_value; - - /* Suspend the protocol engine and place it in a sata spinup hold state */ - scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); - scu_sas_pcfg_value |= - (SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | - SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) | - SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD)); - writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); - - /* Disable the notify enable spinup primitives */ - enable_spinup_value = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); - enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE); - writel(enable_spinup_value, &sci_phy->link_layer_registers->notify_enable_spinup_control); -} - -/** - * - * - * This method will start the OOB/SN state machine for this struct scic_sds_phy object. - */ -static void scu_link_layer_start_oob( - struct scic_sds_phy *sci_phy) -{ - u32 scu_sas_pcfg_value; - - scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); - scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); - scu_sas_pcfg_value &= - ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | - SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); - writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); -} - -/** - * - * - * This method will transmit a hard reset request on the specified phy. The SCU - * hardware requires that we reset the OOB state machine and set the hard reset - * bit in the phy configuration register. We then must start OOB over with the - * hard reset bit set. - */ -static void scu_link_layer_tx_hard_reset( - struct scic_sds_phy *sci_phy) -{ - u32 phy_configuration_value; - - /* - * SAS Phys must wait for the HARD_RESET_TX event notification to transition - * to the starting state. */ - phy_configuration_value = - readl(&sci_phy->link_layer_registers->phy_configuration); - phy_configuration_value |= - (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | - SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); - writel(phy_configuration_value, - &sci_phy->link_layer_registers->phy_configuration); - - /* Now take the OOB state machine out of reset */ - phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); - phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - writel(phy_configuration_value, - &sci_phy->link_layer_registers->phy_configuration); -} - -/* - * **************************************************************************** - * * PHY BASE STATE METHODS - * **************************************************************************** */ - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state - * handlers for the phy object base state machine initial state. none - */ -static void scic_sds_phy_initial_state_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_INITIAL); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state - * handlers for the phy object base state machine initial state. - The SCU - * hardware is requested to stop the protocol engine. none - */ -static void scic_sds_phy_stopped_state_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - struct isci_host *ihost = scic_to_ihost(scic); - - /* - * @todo We need to get to the controller to place this PE in a - * reset state - */ - - scic_sds_phy_set_base_state_handlers(sci_phy, - SCI_BASE_PHY_STATE_STOPPED); - - if (sci_phy->sata_timeout_timer != NULL) { - isci_del_timer(ihost, sci_phy->sata_timeout_timer); - - sci_phy->sata_timeout_timer = NULL; - } - - scu_link_layer_stop_protocol_engine(sci_phy); - - if (sci_phy->state_machine.previous_state_id != - SCI_BASE_PHY_STATE_INITIAL) - scic_sds_controller_link_down( - scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), - sci_phy); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_STARTING. - This function sets the state - * handlers for the phy object base state machine starting state. - The SCU - * hardware is requested to start OOB/SN on this protocl engine. - The phy - * starting substate machine is started. - If the previous state was the ready - * state then the struct scic_sds_controller is informed that the phy has gone link - * down. none - */ -static void scic_sds_phy_starting_state_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STARTING); - - scu_link_layer_stop_protocol_engine(sci_phy); - scu_link_layer_start_oob(sci_phy); - - /* We don't know what kind of phy we are going to be just yet */ - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; - sci_phy->bcn_received_while_port_unassigned = false; - - /* Change over to the starting substate machine to continue */ - sci_base_state_machine_start(&sci_phy->starting_substate_machine); - - if (sci_phy->state_machine.previous_state_id - == SCI_BASE_PHY_STATE_READY) { - scic_sds_controller_link_down( - scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), - sci_phy - ); - } -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_READY. - This function sets the state - * handlers for the phy object base state machine ready state. - The SCU - * hardware protocol engine is resumed. - The struct scic_sds_controller is informed - * that the phy object has gone link up. none - */ -static void scic_sds_phy_ready_state_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_READY); - - scic_sds_controller_link_up( - scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), - sci_phy - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on exiting - * the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU hardware - * protocol engine represented by this struct scic_sds_phy object. none - */ -static void scic_sds_phy_ready_state_exit(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_suspend(sci_phy); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_RESETTING. - This function sets the state - * handlers for the phy object base state machine resetting state. none - */ -static void scic_sds_phy_resetting_state_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_RESETTING); - - /* - * The phy is being reset, therefore deactivate it from the port. - * In the resetting state we don't notify the user regarding - * link up and link down notifications. */ - scic_sds_port_deactivate_phy(sci_phy->owning_port, sci_phy, false); - - if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { - scu_link_layer_tx_hard_reset(sci_phy); - } else { - /* - * The SCU does not need to have a discrete reset state so - * just go back to the starting state. - */ - sci_base_state_machine_change_state( - &sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - } -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_FINAL. - This function sets the state - * handlers for the phy object base state machine final state. none - */ -static void scic_sds_phy_final_state_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_FINAL); - - /* Nothing to do here */ -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_phy_state_table[] = { - [SCI_BASE_PHY_STATE_INITIAL] = { - .enter_state = scic_sds_phy_initial_state_enter, - }, - [SCI_BASE_PHY_STATE_STOPPED] = { - .enter_state = scic_sds_phy_stopped_state_enter, - }, - [SCI_BASE_PHY_STATE_STARTING] = { - .enter_state = scic_sds_phy_starting_state_enter, - }, - [SCI_BASE_PHY_STATE_READY] = { - .enter_state = scic_sds_phy_ready_state_enter, - .exit_state = scic_sds_phy_ready_state_exit, - }, - [SCI_BASE_PHY_STATE_RESETTING] = { - .enter_state = scic_sds_phy_resetting_state_enter, - }, - [SCI_BASE_PHY_STATE_FINAL] = { - .enter_state = scic_sds_phy_final_state_enter, - }, -}; - -void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, - struct scic_sds_port *owning_port, u8 phy_index) -{ - sci_base_state_machine_construct(&sci_phy->state_machine, - sci_phy, - scic_sds_phy_state_table, - SCI_BASE_PHY_STATE_INITIAL); - - sci_base_state_machine_start(&sci_phy->state_machine); - - /* Copy the rest of the input data to our locals */ - sci_phy->owning_port = owning_port; - sci_phy->phy_index = phy_index; - sci_phy->bcn_received_while_port_unassigned = false; - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; - sci_phy->link_layer_registers = NULL; - sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; - sci_phy->sata_timeout_timer = NULL; - - /* Initialize the the substate machines */ - sci_base_state_machine_construct(&sci_phy->starting_substate_machine, - sci_phy, - scic_sds_phy_starting_substates, - SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); -} diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h deleted file mode 100644 index 0d7bab3fc93b..000000000000 --- a/drivers/scsi/isci/core/scic_sds_phy.h +++ /dev/null @@ -1,439 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_PHY_H_ -#define _SCIC_SDS_PHY_H_ - -#include "sas.h" -#include "scic_phy.h" -#include "registers.h" -#include "state_machine.h" -#include - -struct scic_sds_port; -/** - * - * - * This is the timeout value for the SATA phy to wait for a SIGNATURE FIS - * before restarting the starting state machine. Technically, the old parallel - * ATA specification required up to 30 seconds for a device to issue its - * signature FIS as a result of a soft reset. Now we see that devices respond - * generally within 15 seconds, but we'll use 25 for now. - */ -#define SCIC_SDS_SIGNATURE_FIS_TIMEOUT 25000 - -/** - * - * - * This is the timeout for the SATA OOB/SN because the hardware does not - * recognize a hot plug after OOB signal but before the SN signals. We need to - * make sure after a hotplug timeout if we have not received the speed event - * notification from the hardware that we restart the hardware OOB state - * machine. - */ -#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250 - -enum scic_sds_phy_states { - /** - * Simply the initial state for the base domain state machine. - */ - SCI_BASE_PHY_STATE_INITIAL, - - /** - * This state indicates that the phy has successfully been stopped. - * In this state no new IO operations are permitted on this phy. - * This state is entered from the INITIAL state. - * This state is entered from the STARTING state. - * This state is entered from the READY state. - * This state is entered from the RESETTING state. - */ - SCI_BASE_PHY_STATE_STOPPED, - - /** - * This state indicates that the phy is in the process of becomming - * ready. In this state no new IO operations are permitted on this phy. - * This state is entered from the STOPPED state. - * This state is entered from the READY state. - * This state is entered from the RESETTING state. - */ - SCI_BASE_PHY_STATE_STARTING, - - /** - * This state indicates the the phy is now ready. Thus, the user - * is able to perform IO operations utilizing this phy as long as it - * is currently part of a valid port. - * This state is entered from the STARTING state. - */ - SCI_BASE_PHY_STATE_READY, - - /** - * This state indicates that the phy is in the process of being reset. - * In this state no new IO operations are permitted on this phy. - * This state is entered from the READY state. - */ - SCI_BASE_PHY_STATE_RESETTING, - - /** - * Simply the final state for the base phy state machine. - */ - SCI_BASE_PHY_STATE_FINAL, -}; - - -/** - * enum scic_sds_phy_starting_substates - - * - * - */ -enum scic_sds_phy_starting_substates { - /** - * Initial state - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL, - - /** - * Wait state for the hardware OSSP event type notification - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN, - - /** - * Wait state for the PHY speed notification - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN, - - /** - * Wait state for the IAF Unsolicited frame notification - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF, - - /** - * Wait state for the request to consume power - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER, - - /** - * Wait state for request to consume power - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, - - /** - * Wait state for the SATA PHY notification - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, - - /** - * Wait for the SATA PHY speed notification - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, - - /** - * Wait state for the SIGNATURE FIS unsolicited frame notification - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, - - /** - * Exit state for this state machine - */ - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL, -}; - -struct scic_sds_port; -struct scic_sds_controller; - -/** - * This enumeration provides a named phy type for the state machine - * - * - */ -enum scic_sds_phy_protocol { - /** - * This is an unknown phy type since there is either nothing on the other - * end or we have not detected the phy type as yet. - */ - SCIC_SDS_PHY_PROTOCOL_UNKNOWN, - - /** - * This is a SAS PHY - */ - SCIC_SDS_PHY_PROTOCOL_SAS, - - /** - * This is a SATA PHY - */ - SCIC_SDS_PHY_PROTOCOL_SATA, - - SCIC_SDS_MAX_PHY_PROTOCOLS -}; - -/** - * struct scic_sds_phy - This structure contains or references all of the data - * necessary to represent the core phy object and SCU harware protocol - * engine. - * - * - */ -struct scic_sds_phy { - /** - * This field contains the information for the base phy state machine. - */ - struct sci_base_state_machine state_machine; - - /** - * This field specifies the port object that owns/contains this phy. - */ - struct scic_sds_port *owning_port; - - /** - * This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s, - * or 6.0 Gb/s operation. - */ - enum sas_linkrate max_negotiated_speed; - - /** - * This member specifies the protocol being utilized on this phy. This - * field contains a legitamite value once the PHY has link trained with - * a remote phy. - */ - enum scic_sds_phy_protocol protocol; - - /** - * This field specifies the index with which this phy is associated (0-3). - */ - u8 phy_index; - - /** - * This member indicates if this particular PHY has received a BCN while - * it had no port assignement. This BCN will be reported once the phy is - * assigned to a port. - */ - bool bcn_received_while_port_unassigned; - - /** - * This field indicates if this PHY is currently in the process of - * link training (i.e. it has started OOB, but has yet to perform - * IAF exchange/Signature FIS reception). - */ - bool is_in_link_training; - - /** - * This field contains a reference to the timer utilized in detecting - * when a signature FIS timeout has occurred. The signature FIS is the - * first FIS sent by an attached SATA device after OOB/SN. - */ - void *sata_timeout_timer; - - const struct scic_sds_phy_state_handler *state_handlers; - - struct sci_base_state_machine starting_substate_machine; - - /** - * This field is the pointer to the transport layer register for the SCU - * hardware. - */ - struct scu_transport_layer_registers __iomem *transport_layer_registers; - - /** - * This field points to the link layer register set within the SCU. - */ - struct scu_link_layer_registers __iomem *link_layer_registers; - -}; - -typedef enum sci_status (*scic_sds_phy_handler_t)(struct scic_sds_phy *); -typedef enum sci_status (*scic_sds_phy_event_handler_t)(struct scic_sds_phy *, u32); -typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u32); -typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); - -/** - * struct scic_sds_phy_state_handler - - * - * - */ -struct scic_sds_phy_state_handler { - /** - * The start_handler specifies the method invoked when there is an - * attempt to start a phy. - */ - scic_sds_phy_handler_t start_handler; - - /** - * The stop_handler specifies the method invoked when there is an - * attempt to stop a phy. - */ - scic_sds_phy_handler_t stop_handler; - - /** - * The reset_handler specifies the method invoked when there is an - * attempt to reset a phy. - */ - scic_sds_phy_handler_t reset_handler; - - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a phy. - */ - scic_sds_phy_handler_t destruct_handler; - - /** - * The state handler for unsolicited frames received from the SCU hardware. - */ - scic_sds_phy_frame_handler_t frame_handler; - - /** - * The state handler for events received from the SCU hardware. - */ - scic_sds_phy_event_handler_t event_handler; - - /** - * The state handler for staggered spinup. - */ - scic_sds_phy_power_handler_t consume_power_handler; - -}; - -/** - * scic_sds_phy_get_index() - - * - * This macro returns the phy index for the specified phy - */ -#define scic_sds_phy_get_index(phy) \ - ((phy)->phy_index) - -/** - * scic_sds_phy_get_controller() - This macro returns the controller for this - * phy - * - * - */ -#define scic_sds_phy_get_controller(phy) \ - (scic_sds_port_get_controller((phy)->owning_port)) - -/** - * scic_sds_phy_set_state_handlers() - This macro sets the state handlers for - * this phy object - * - * - */ -#define scic_sds_phy_set_state_handlers(phy, handlers) \ - ((phy)->state_handlers = (handlers)) - -/** - * scic_sds_phy_set_base_state_handlers() - - * - * This macro set the base state handlers for the phy object. - */ -#define scic_sds_phy_set_base_state_handlers(phy, state_id) \ - scic_sds_phy_set_state_handlers(\ - (phy), \ - &scic_sds_phy_state_handler_table[(state_id)] \ - ) - -void scic_sds_phy_construct( - struct scic_sds_phy *this_phy, - struct scic_sds_port *owning_port, - u8 phy_index); - -struct scic_sds_port *scic_sds_phy_get_port( - struct scic_sds_phy *this_phy); - -void scic_sds_phy_set_port( - struct scic_sds_phy *this_phy, - struct scic_sds_port *owning_port); - -enum sci_status scic_sds_phy_initialize( - struct scic_sds_phy *this_phy, - struct scu_transport_layer_registers __iomem *transport_layer_registers, - struct scu_link_layer_registers __iomem *link_layer_registers); - -enum sci_status scic_sds_phy_start( - struct scic_sds_phy *this_phy); - -enum sci_status scic_sds_phy_stop( - struct scic_sds_phy *this_phy); - -enum sci_status scic_sds_phy_reset( - struct scic_sds_phy *this_phy); - -void scic_sds_phy_resume( - struct scic_sds_phy *this_phy); - -void scic_sds_phy_setup_transport( - struct scic_sds_phy *this_phy, - u32 device_id); - -enum sci_status scic_sds_phy_event_handler( - struct scic_sds_phy *this_phy, - u32 event_code); - -enum sci_status scic_sds_phy_frame_handler( - struct scic_sds_phy *this_phy, - u32 frame_index); - -enum sci_status scic_sds_phy_consume_power_handler( - struct scic_sds_phy *this_phy); - -void scic_sds_phy_get_sas_address( - struct scic_sds_phy *this_phy, - struct sci_sas_address *sas_address); - -void scic_sds_phy_get_attached_sas_address( - struct scic_sds_phy *this_phy, - struct sci_sas_address *sas_address); - -void scic_sds_phy_get_protocols( - struct scic_sds_phy *sci_phy, - struct scic_phy_proto *protocols); - -#endif /* _SCIC_SDS_PHY_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c index a9f3ce111b86..11b516a9a130 100644 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ b/drivers/scsi/isci/core/scic_sds_port.c @@ -54,9 +54,7 @@ */ #include "host.h" -#include "scic_phy.h" #include "scic_port.h" -#include "scic_sds_phy.h" #include "scic_sds_port.h" #include "remote_device.h" #include "remote_node_context.h" diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h index 56a40a712589..7fd161700475 100644 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h @@ -64,7 +64,6 @@ */ #include "scic_sds_port.h" -#include "scic_sds_phy.h" struct scic_sds_controller; struct scic_sds_port_configuration_agent; diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 1134395c970e..b92d51f25481 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -56,12 +56,2219 @@ #include "isci.h" #include "host.h" #include "phy.h" +#include "scu_event_codes.h" #include "scic_port.h" #include "scic_config_parameters.h" +#include "timers.h" -struct scic_sds_phy; -extern enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy); -extern enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy); +/* Maximum arbitration wait time in micro-seconds */ +#define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) + +enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy) +{ + return sci_phy->max_negotiated_speed; +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY Internal Methods + * ***************************************************************************** */ + +/** + * This method will initialize the phy transport layer registers + * @sci_phy: + * @transport_layer_registers + * + * enum sci_status + */ +static enum sci_status scic_sds_phy_transport_layer_initialization( + struct scic_sds_phy *sci_phy, + struct scu_transport_layer_registers __iomem *transport_layer_registers) +{ + u32 tl_control; + + sci_phy->transport_layer_registers = transport_layer_registers; + + writel(SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX, + &sci_phy->transport_layer_registers->stp_rni); + + /* + * Hardware team recommends that we enable the STP prefetch for all + * transports + */ + tl_control = readl(&sci_phy->transport_layer_registers->control); + tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); + writel(tl_control, &sci_phy->transport_layer_registers->control); + + return SCI_SUCCESS; +} + +/** + * This method will initialize the phy link layer registers + * @sci_phy: + * @link_layer_registers: + * + * enum sci_status + */ +static enum sci_status +scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, + struct scu_link_layer_registers __iomem *link_layer_registers) +{ + struct scic_sds_controller *scic = + sci_phy->owning_port->owning_controller; + int phy_idx = sci_phy->phy_index; + struct sci_phy_user_params *phy_user = + &scic->user_parameters.sds1.phys[phy_idx]; + struct sci_phy_oem_params *phy_oem = + &scic->oem_parameters.sds1.phys[phy_idx]; + u32 phy_configuration; + struct scic_phy_cap phy_cap; + u32 parity_check = 0; + u32 parity_count = 0; + u32 llctl, link_rate; + u32 clksm_value = 0; + + sci_phy->link_layer_registers = link_layer_registers; + + /* Set our IDENTIFY frame data */ + #define SCI_END_DEVICE 0x01 + + writel(SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) | + SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) | + SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE), + &sci_phy->link_layer_registers->transmit_identification); + + /* Write the device SAS Address */ + writel(0xFEDCBA98, + &sci_phy->link_layer_registers->sas_device_name_high); + writel(phy_idx, &sci_phy->link_layer_registers->sas_device_name_low); + + /* Write the source SAS Address */ + writel(phy_oem->sas_address.high, + &sci_phy->link_layer_registers->source_sas_address_high); + writel(phy_oem->sas_address.low, + &sci_phy->link_layer_registers->source_sas_address_low); + + /* Clear and Set the PHY Identifier */ + writel(0, &sci_phy->link_layer_registers->identify_frame_phy_id); + writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), + &sci_phy->link_layer_registers->identify_frame_phy_id); + + /* Change the initial state of the phy configuration register */ + phy_configuration = + readl(&sci_phy->link_layer_registers->phy_configuration); + + /* Hold OOB state machine in reset */ + phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + writel(phy_configuration, + &sci_phy->link_layer_registers->phy_configuration); + + /* Configure the SNW capabilities */ + phy_cap.all = 0; + phy_cap.start = 1; + phy_cap.gen3_no_ssc = 1; + phy_cap.gen2_no_ssc = 1; + phy_cap.gen1_no_ssc = 1; + if (scic->oem_parameters.sds1.controller.do_enable_ssc == true) { + phy_cap.gen3_ssc = 1; + phy_cap.gen2_ssc = 1; + phy_cap.gen1_ssc = 1; + } + + /* + * The SAS specification indicates that the phy_capabilities that + * are transmitted shall have an even parity. Calculate the parity. */ + parity_check = phy_cap.all; + while (parity_check != 0) { + if (parity_check & 0x1) + parity_count++; + parity_check >>= 1; + } + + /* + * If parity indicates there are an odd number of bits set, then + * set the parity bit to 1 in the phy capabilities. */ + if ((parity_count % 2) != 0) + phy_cap.parity = 1; + + writel(phy_cap.all, &sci_phy->link_layer_registers->phy_capabilities); + + /* Set the enable spinup period but disable the ability to send + * notify enable spinup + */ + writel(SCU_ENSPINUP_GEN_VAL(COUNT, + phy_user->notify_enable_spin_up_insertion_frequency), + &sci_phy->link_layer_registers->notify_enable_spinup_control); + + /* Write the ALIGN Insertion Ferequency for connected phy and + * inpendent of connected state + */ + clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(CONNECTED, + phy_user->in_connection_align_insertion_frequency); + + clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL, + phy_user->align_insertion_frequency); + + writel(clksm_value, &sci_phy->link_layer_registers->clock_skew_management); + + /* @todo Provide a way to write this register correctly */ + writel(0x02108421, + &sci_phy->link_layer_registers->afe_lookup_table_control); + + llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, + (u8)scic->user_parameters.sds1.no_outbound_task_timeout); + + switch(phy_user->max_speed_generation) { + case SCIC_SDS_PARM_GEN3_SPEED: + link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3; + break; + case SCIC_SDS_PARM_GEN2_SPEED: + link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2; + break; + default: + link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1; + break; + } + llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate); + writel(llctl, &sci_phy->link_layer_registers->link_layer_control); + + if (is_a0() || is_a2()) { + /* Program the max ARB time for the PHY to 700us so we inter-operate with + * the PMC expander which shuts down PHYs if the expander PHY generates too + * many breaks. This time value will guarantee that the initiator PHY will + * generate the break. + */ + writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME, + &sci_phy->link_layer_registers->maximum_arbitration_wait_timer_timeout); + } + + /* + * Set the link layer hang detection to 500ms (0x1F4) from its default + * value of 128ms. Max value is 511 ms. + */ + writel(0x1F4, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout); + + /* We can exit the initial state to the stopped state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STOPPED); + + return SCI_SUCCESS; +} + +/** + * This function will handle the sata SIGNATURE FIS timeout condition. It will + * restart the starting substate machine since we dont know what has actually + * happening. + */ +static void scic_sds_phy_sata_timeout(void *phy) +{ + struct scic_sds_phy *sci_phy = phy; + + dev_dbg(sciphy_to_dev(sci_phy), + "%s: SCIC SDS Phy 0x%p did not receive signature fis before " + "timeout.\n", + __func__, + sci_phy); + + sci_base_state_machine_stop(&sci_phy->starting_substate_machine); + + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); +} + +/** + * This method returns the port currently containing this phy. If the phy is + * currently contained by the dummy port, then the phy is considered to not + * be part of a port. + * @sci_phy: This parameter specifies the phy for which to retrieve the + * containing port. + * + * This method returns a handle to a port that contains the supplied phy. + * NULL This value is returned if the phy is not part of a real + * port (i.e. it's contained in the dummy port). !NULL All other + * values indicate a handle/pointer to the port containing the phy. + */ +struct scic_sds_port *scic_sds_phy_get_port( + struct scic_sds_phy *sci_phy) +{ + if (scic_sds_port_get_index(sci_phy->owning_port) == SCIC_SDS_DUMMY_PORT) + return NULL; + + return sci_phy->owning_port; +} + +/** + * This method will assign a port to the phy object. + * @out]: sci_phy This parameter specifies the phy for which to assign a port + * object. + * + * + */ +void scic_sds_phy_set_port( + struct scic_sds_phy *sci_phy, + struct scic_sds_port *sci_port) +{ + sci_phy->owning_port = sci_port; + + if (sci_phy->bcn_received_while_port_unassigned) { + sci_phy->bcn_received_while_port_unassigned = false; + scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); + } +} + +/** + * This method will initialize the constructed phy + * @sci_phy: + * @link_layer_registers: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_initialize( + struct scic_sds_phy *sci_phy, + struct scu_transport_layer_registers __iomem *transport_layer_registers, + struct scu_link_layer_registers __iomem *link_layer_registers) +{ + struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); + struct isci_host *ihost = scic_to_ihost(scic); + + /* Create the SIGNATURE FIS Timeout timer for this phy */ + sci_phy->sata_timeout_timer = + isci_timer_create( + ihost, + sci_phy, + scic_sds_phy_sata_timeout); + + /* Perfrom the initialization of the TL hardware */ + scic_sds_phy_transport_layer_initialization( + sci_phy, + transport_layer_registers); + + /* Perofrm the initialization of the PE hardware */ + scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers); + + /* + * There is nothing that needs to be done in this state just + * transition to the stopped state. */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STOPPED); + + return SCI_SUCCESS; +} + +/** + * This method assigns the direct attached device ID for this phy. + * + * @sci_phy The phy for which the direct attached device id is to + * be assigned. + * @device_id The direct attached device ID to assign to the phy. + * This will either be the RNi for the device or an invalid RNi if there + * is no current device assigned to the phy. + */ +void scic_sds_phy_setup_transport( + struct scic_sds_phy *sci_phy, + u32 device_id) +{ + u32 tl_control; + + writel(device_id, &sci_phy->transport_layer_registers->stp_rni); + + /* + * The read should guarantee that the first write gets posted + * before the next write + */ + tl_control = readl(&sci_phy->transport_layer_registers->control); + tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); + writel(tl_control, &sci_phy->transport_layer_registers->control); +} + +/** + * + * @sci_phy: The phy object to be suspended. + * + * This function will perform the register reads/writes to suspend the SCU + * hardware protocol engine. none + */ +static void scic_sds_phy_suspend( + struct scic_sds_phy *sci_phy) +{ + u32 scu_sas_pcfg_value; + + scu_sas_pcfg_value = + readl(&sci_phy->link_layer_registers->phy_configuration); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); + + scic_sds_phy_setup_transport( + sci_phy, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); +} + +void scic_sds_phy_resume(struct scic_sds_phy *sci_phy) +{ + u32 scu_sas_pcfg_value; + + scu_sas_pcfg_value = + readl(&sci_phy->link_layer_registers->phy_configuration); + scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); +} + +void scic_sds_phy_get_sas_address(struct scic_sds_phy *sci_phy, + struct sci_sas_address *sas_address) +{ + sas_address->high = readl(&sci_phy->link_layer_registers->source_sas_address_high); + sas_address->low = readl(&sci_phy->link_layer_registers->source_sas_address_low); +} + +void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy, + struct sci_sas_address *sas_address) +{ + struct sas_identify_frame *iaf; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + iaf = &iphy->frame_rcvd.iaf; + memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); +} + +void scic_sds_phy_get_protocols(struct scic_sds_phy *sci_phy, + struct scic_phy_proto *protocols) +{ + protocols->all = + (u16)(readl(&sci_phy-> + link_layer_registers->transmit_identification) & + 0x0000FFFF); +} + +/** + * This method will attempt to start the phy object. This request is only valid + * when the phy is in the stopped state + * @sci_phy: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) +{ + return sci_phy->state_handlers->start_handler(sci_phy); +} + +/** + * This method will attempt to stop the phy object. + * @sci_phy: + * + * enum sci_status SCI_SUCCESS if the phy is going to stop SCI_INVALID_STATE + * if the phy is not in a valid state to stop + */ +enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) +{ + return sci_phy->state_handlers->stop_handler(sci_phy); +} + +/** + * This method will attempt to reset the phy. This request is only valid when + * the phy is in an ready state + * @sci_phy: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_reset( + struct scic_sds_phy *sci_phy) +{ + return sci_phy->state_handlers->reset_handler(sci_phy); +} + +/** + * This method will process the event code received. + * @sci_phy: + * @event_code: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_event_handler( + struct scic_sds_phy *sci_phy, + u32 event_code) +{ + return sci_phy->state_handlers->event_handler(sci_phy, event_code); +} + +/** + * This method will process the frame index received. + * @sci_phy: + * @frame_index: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_frame_handler( + struct scic_sds_phy *sci_phy, + u32 frame_index) +{ + return sci_phy->state_handlers->frame_handler(sci_phy, frame_index); +} + +/** + * This method will give the phy permission to consume power + * @sci_phy: + * + * enum sci_status + */ +enum sci_status scic_sds_phy_consume_power_handler( + struct scic_sds_phy *sci_phy) +{ + return sci_phy->state_handlers->consume_power_handler(sci_phy); +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY HELPER FUNCTIONS + * ***************************************************************************** */ + + +/** + * + * @sci_phy: The phy object that received SAS PHY DETECTED. + * + * This method continues the link training for the phy as if it were a SAS PHY + * instead of a SATA PHY. This is done because the completion queue had a SAS + * PHY DETECTED event when the state machine was expecting a SATA PHY event. + * none + */ +static void scic_sds_phy_start_sas_link_training( + struct scic_sds_phy *sci_phy) +{ + u32 phy_control; + + phy_control = + readl(&sci_phy->link_layer_registers->phy_configuration); + phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); + writel(phy_control, + &sci_phy->link_layer_registers->phy_configuration); + + sci_base_state_machine_change_state( + &sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN + ); + + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; +} + +/** + * + * @sci_phy: The phy object that received a SATA SPINUP HOLD event + * + * This method continues the link training for the phy as if it were a SATA PHY + * instead of a SAS PHY. This is done because the completion queue had a SATA + * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none + */ +static void scic_sds_phy_start_sata_link_training( + struct scic_sds_phy *sci_phy) +{ + sci_base_state_machine_change_state( + &sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER + ); + + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; +} + +/** + * scic_sds_phy_complete_link_training - perform processing common to + * all protocols upon completion of link training. + * @sci_phy: This parameter specifies the phy object for which link training + * has completed. + * @max_link_rate: This parameter specifies the maximum link rate to be + * associated with this phy. + * @next_state: This parameter specifies the next state for the phy's starting + * sub-state machine. + * + */ +static void scic_sds_phy_complete_link_training( + struct scic_sds_phy *sci_phy, + enum sas_linkrate max_link_rate, + u32 next_state) +{ + sci_phy->max_negotiated_speed = max_link_rate; + + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + next_state); +} + +static void scic_sds_phy_restart_starting_state( + struct scic_sds_phy *sci_phy) +{ + /* Stop the current substate machine */ + sci_base_state_machine_stop(&sci_phy->starting_substate_machine); + + /* Re-enter the base state machine starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); +} + +/* **************************************************************************** + * SCIC SDS PHY general handlers + ************************************************************************** */ +static enum sci_status scic_sds_phy_starting_substate_general_stop_handler( + struct scic_sds_phy *phy) +{ + sci_base_state_machine_stop(&phy->starting_substate_machine); + + sci_base_state_machine_change_state(&phy->state_machine, + SCI_BASE_PHY_STATE_STOPPED); + + return SCI_SUCCESS; +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY EVENT_HANDLERS + * ***************************************************************************** */ + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - + * decode the event - sas phy detected causes a state transition to the wait + * for speed event notification. - any other events log a warning message and + * set a failure status enum sci_status SCI_SUCCESS on any valid event notification + * SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler( + struct scic_sds_phy *sci_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + scic_sds_phy_start_sas_link_training(sci_phy); + sci_phy->is_in_link_training = true; + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + scic_sds_phy_start_sata_link_training(sci_phy); + sci_phy->is_in_link_training = true; + break; + + default: + dev_dbg(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - + * decode the event - sas phy detected returns us back to this state. - speed + * event detected causes a state transition to the wait for iaf. - identify + * timeout is an un-expected event and the state machine is restarted. - link + * failure events restart the starting state machine - any other events log a + * warning message and set a failure status enum sci_status SCI_SUCCESS on any valid + * event notification SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler( + struct scic_sds_phy *sci_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * Why is this being reported again by the controller? + * We would re-enter this state so just stay here */ + break; + + case SCU_EVENT_SAS_15: + case SCU_EVENT_SAS_15_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_1_5_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + break; + + case SCU_EVENT_SAS_30: + case SCU_EVENT_SAS_30_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_3_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + break; + + case SCU_EVENT_SAS_60: + case SCU_EVENT_SAS_60_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_6_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + /* + * We were doing SAS PHY link training and received a SATA PHY event + * continue OOB/SN as if this were a SATA PHY */ + scic_sds_phy_start_sata_link_training(sci_phy); + break; + + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(sci_phy); + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - + * decode the event - sas phy detected event backs up the state machine to the + * await speed notification. - identify timeout is an un-expected event and the + * state machine is restarted. - link failure events restart the starting state + * machine - any other events log a warning message and set a failure status + * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any + * unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler( + struct scic_sds_phy *sci_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + /* Backup the state machine */ + scic_sds_phy_start_sas_link_training(sci_phy); + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + /* + * We were doing SAS PHY link training and received a SATA PHY event + * continue OOB/SN as if this were a SATA PHY */ + scic_sds_phy_start_sata_link_training(sci_phy); + break; + + case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: + case SCU_EVENT_LINK_FAILURE: + case SCU_EVENT_HARD_RESET_RECEIVED: + /* Start the oob/sn state machine over again */ + scic_sds_phy_restart_starting_state(sci_phy); + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER. - + * decode the event - link failure events restart the starting state machine - + * any other events log a warning message and set a failure status enum sci_status + * SCI_SUCCESS on a link failure event SCI_FAILURE on any unexpected event + * notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_handler( + struct scic_sds_phy *sci_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(sci_phy); + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received unexpected " + "event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - + * decode the event - link failure events restart the starting state machine - + * sata spinup hold events are ignored since they are expected - any other + * events log a warning message and set a failure status enum sci_status SCI_SUCCESS + * on a link failure event SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_handler( + struct scic_sds_phy *sci_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(sci_phy); + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + /* These events are received every 10ms and are expected while in this state */ + break; + + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. */ + scic_sds_phy_start_sas_link_training(sci_phy); + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * scic_sds_phy_starting_substate_await_sata_phy_event_handler - + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - + * decode the event - link failure events restart the starting state machine - + * sata spinup hold events are ignored since they are expected - sata phy + * detected event change to the wait speed event - any other events log a + * warning message and set a failure status enum sci_status SCI_SUCCESS on a link + * failure event SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handler( + struct scic_sds_phy *sci_phy, u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(sci_phy); + break; + + case SCU_EVENT_SATA_SPINUP_HOLD: + /* These events might be received since we dont know how many may be in + * the completion queue while waiting for power + */ + break; + + case SCU_EVENT_SATA_PHY_DETECTED: + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; + + /* We have received the SATA PHY notification change state */ + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); + break; + + case SCU_EVENT_SAS_PHY_DETECTED: + /* There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. + */ + scic_sds_phy_start_sas_link_training(sci_phy); + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. + * - decode the event - sata phy detected returns us back to this state. - + * speed event detected causes a state transition to the wait for signature. - + * link failure events restart the starting state machine - any other events + * log a warning message and set a failure status enum sci_status SCI_SUCCESS on any + * valid event notification SCI_FAILURE on any unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_handler( + struct scic_sds_phy *sci_phy, + u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SATA_PHY_DETECTED: + /* + * The hardware reports multiple SATA PHY detected events + * ignore the extras */ + break; + + case SCU_EVENT_SATA_15: + case SCU_EVENT_SATA_15_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_1_5_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + break; + + case SCU_EVENT_SATA_30: + case SCU_EVENT_SATA_30_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_3_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + break; + + case SCU_EVENT_SATA_60: + case SCU_EVENT_SATA_60_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_6_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + break; + + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(sci_phy); + break; + + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. */ + scic_sds_phy_start_sas_link_training(sci_phy); + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + +/** + * scic_sds_phy_starting_substate_await_sig_fis_event_handler - + * @phy: This struct scic_sds_phy object which has received an event. + * @event_code: This is the event code which the phy object is to decode. + * + * This method is called when an event notification is received for the phy + * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - + * decode the event - sas phy detected event backs up the state machine to the + * await speed notification. - identify timeout is an un-expected event and the + * state machine is restarted. - link failure events restart the starting state + * machine - any other events log a warning message and set a failure status + * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any + * unexpected event notifation + */ +static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handler( + struct scic_sds_phy *sci_phy, u32 event_code) +{ + u32 result = SCI_SUCCESS; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SATA_PHY_DETECTED: + /* Backup the state machine */ + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); + break; + + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + scic_sds_phy_restart_starting_state(sci_phy); + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + result = SCI_FAILURE; + break; + } + + return result; +} + + +/* + * ***************************************************************************** + * * SCIC SDS PHY FRAME_HANDLERS + * ***************************************************************************** */ + +/** + * + * @phy: This is struct scic_sds_phy object which is being requested to decode the + * frame data. + * @frame_index: This is the index of the unsolicited frame which was received + * for this phy. + * + * This method decodes the unsolicited frame when the struct scic_sds_phy is in the + * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Get the UF Header - If the UF + * is an IAF - Copy IAF data to local phy object IAF data buffer. - Change + * starting substate to wait power. - else - log warning message of unexpected + * unsolicted frame - release frame buffer enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler( + struct scic_sds_phy *sci_phy, u32 frame_index) +{ + enum sci_status result; + u32 *frame_words; + struct sas_identify_frame iaf; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + result = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_phy_get_controller(sci_phy)->uf_control), + frame_index, + (void **)&frame_words); + + if (result != SCI_SUCCESS) + return result; + + sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32)); + if (iaf.frame_type == 0) { + u32 state; + + memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf)); + if (iaf.smp_tport) { + /* We got the IAF for an expander PHY go to the final + * state since there are no power requirements for + * expander phys. + */ + state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; + } else { + /* We got the IAF we can now go to the await spinup + * semaphore state + */ + state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; + } + sci_base_state_machine_change_state( + &sci_phy->starting_substate_machine, + state); + result = SCI_SUCCESS; + } else + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected frame id %x\n", + __func__, + frame_index); + + scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), + frame_index); + + return result; +} + +/** + * + * @phy: This is struct scic_sds_phy object which is being requested to decode the + * frame data. + * @frame_index: This is the index of the unsolicited frame which was received + * for this phy. + * + * This method decodes the unsolicited frame when the struct scic_sds_phy is in the + * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Get the UF Header - If + * the UF is an SIGNATURE FIS - Copy IAF data to local phy object SIGNATURE FIS + * data buffer. - else - log warning message of unexpected unsolicted frame - + * release frame buffer enum sci_status SCI_SUCCESS Must decode the SIGNATURE FIS + * data + */ +static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handler( + struct scic_sds_phy *sci_phy, + u32 frame_index) +{ + enum sci_status result; + struct dev_to_host_fis *frame_header; + u32 *fis_frame_data; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + result = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_phy_get_controller(sci_phy)->uf_control), + frame_index, + (void **)&frame_header); + + if (result != SCI_SUCCESS) + return result; + + if ((frame_header->fis_type == FIS_REGD2H) && + !(frame_header->status & ATA_BUSY)) { + scic_sds_unsolicited_frame_control_get_buffer( + &(scic_sds_phy_get_controller(sci_phy)->uf_control), + frame_index, + (void **)&fis_frame_data); + + scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, + frame_header, + fis_frame_data); + + /* got IAF we can now go to the await spinup semaphore state */ + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); + + result = SCI_SUCCESS; + } else + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected frame id %x\n", + __func__, + frame_index); + + /* Regardless of the result we are done with this frame with it */ + scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), + frame_index); + + return result; +} + +/* + * ***************************************************************************** + * * SCIC SDS PHY POWER_HANDLERS + * ***************************************************************************** */ + +/* + * This method is called by the struct scic_sds_controller when the phy object is + * granted power. - The notify enable spinups are turned on for this phy object + * - The phy state machine is transitioned to the + * SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_power_handler( + struct scic_sds_phy *sci_phy) +{ + u32 enable_spinup; + + enable_spinup = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); + enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); + writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control); + + /* Change state to the final state this substate machine has run to completion */ + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); + + return SCI_SUCCESS; +} + +/* + * This method is called by the struct scic_sds_controller when the phy object is + * granted power. - The phy state machine is transitioned to the + * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_power_handler( + struct scic_sds_phy *sci_phy) +{ + u32 scu_sas_pcfg_value; + + /* Release the spinup hold state and reset the OOB state machine */ + scu_sas_pcfg_value = + readl(&sci_phy->link_layer_registers->phy_configuration); + scu_sas_pcfg_value &= + ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); + + /* Now restart the OOB operation */ + scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); + + /* Change state to the final state this substate machine has run to completion */ + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); + + return SCI_SUCCESS; +} + +static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, + const char *func) +{ + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", func, + sci_base_state_machine_get_state(&sci_phy->state_machine)); + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status +scic_sds_phy_default_start_handler(struct scic_sds_phy *sci_phy) +{ + return default_phy_handler(sci_phy, __func__); +} + +static enum sci_status +scic_sds_phy_default_stop_handler(struct scic_sds_phy *sci_phy) +{ + return default_phy_handler(sci_phy, __func__); +} + +static enum sci_status +scic_sds_phy_default_reset_handler(struct scic_sds_phy *sci_phy) +{ + return default_phy_handler(sci_phy, __func__); +} + +static enum sci_status +scic_sds_phy_default_destroy_handler(struct scic_sds_phy *sci_phy) +{ + return default_phy_handler(sci_phy, __func__); +} + +static enum sci_status +scic_sds_phy_default_frame_handler(struct scic_sds_phy *sci_phy, + u32 frame_index) +{ + struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); + + default_phy_handler(sci_phy, __func__); + scic_sds_controller_release_frame(scic, frame_index); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status +scic_sds_phy_default_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) +{ + return default_phy_handler(sci_phy, __func__); +} + +static enum sci_status +scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) +{ + return default_phy_handler(sci_phy, __func__); +} + + + +static const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = { + [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, + .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, + .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, + .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + } +}; + +/** + * scic_sds_phy_set_starting_substate_handlers() - + * + * This macro sets the starting substate handlers by state_id + */ +#define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \ + scic_sds_phy_set_state_handlers(\ + (phy), \ + &scic_sds_phy_starting_substate_handler_table[(state_id)] \ + ) + +/* + * **************************************************************************** + * * PHY STARTING SUBSTATE METHODS + * **************************************************************************** */ + +/** + * scic_sds_phy_starting_initial_substate_enter - + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL. - The initial state + * handlers are put in place for the struct scic_sds_phy object. - The state is + * changed to the wait phy type event notification. none + */ +static void scic_sds_phy_starting_initial_substate_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); + + /* This is just an temporary state go off to the starting state */ + sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_ossp_en_substate_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( + void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_iaf_uf_substate_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Set the + * struct scic_sds_phy object state handlers for this state. - Add this phy object to + * the power control queue none + */ +static void scic_sds_phy_starting_await_sas_power_substate_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER + ); + + scic_sds_controller_power_control_queue_insert( + scic_sds_phy_get_controller(sci_phy), + sci_phy + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Remove the + * struct scic_sds_phy object from the power control queue. none + */ +static void scic_sds_phy_starting_await_sas_power_substate_exit(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_controller_power_control_queue_remove( + scic_sds_phy_get_controller(sci_phy), sci_phy + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Set the + * struct scic_sds_phy object state handlers for this state. - Add this phy object to + * the power control queue none + */ +static void scic_sds_phy_starting_await_sata_power_substate_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER + ); + + scic_sds_controller_power_control_queue_insert( + scic_sds_phy_get_controller(sci_phy), + sci_phy + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Remove the + * struct scic_sds_phy object from the power control queue. none + */ +static void scic_sds_phy_starting_await_sata_power_substate_exit(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_controller_power_control_queue_remove( + scic_sds_phy_get_controller(sci_phy), + sci_phy + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This function will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_sata_phy_substate_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); + + isci_timer_start(sci_phy->sata_timeout_timer, + SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy + * on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer + * that was started on entry to await sata phy event notification none + */ +static inline void scic_sds_phy_starting_await_sata_phy_substate_exit( + void *object) +{ + struct scic_sds_phy *sci_phy = object; + + isci_timer_stop(sci_phy->sata_timeout_timer); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - Set the + * struct scic_sds_phy object state handlers for this state. none + */ +static void scic_sds_phy_starting_await_sata_speed_substate_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); + + isci_timer_start(sci_phy->sata_timeout_timer, + SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This function will perform the actions required by the + * struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer + * that was started on entry to await sata phy event notification none + */ +static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( + void *object) +{ + struct scic_sds_phy *sci_phy = object; + + isci_timer_stop(sci_phy->sata_timeout_timer); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This function will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Set the + * struct scic_sds_phy object state handlers for this state. + * - Start the SIGNATURE FIS + * timeout timer none + */ +static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) +{ + bool continue_to_ready_state; + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers( + sci_phy, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + + continue_to_ready_state = scic_sds_port_link_detected( + sci_phy->owning_port, + sci_phy); + + if (continue_to_ready_state) { + /* + * Clear the PE suspend condition so we can actually + * receive SIG FIS + * The hardware will not respond to the XRDY until the PE + * suspend condition is cleared. + */ + scic_sds_phy_resume(sci_phy); + + isci_timer_start(sci_phy->sata_timeout_timer, + SCIC_SDS_SIGNATURE_FIS_TIMEOUT); + } else + sci_phy->is_in_link_training = false; +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This function will perform the actions required by the + * struct scic_sds_phy on exiting + * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Stop the SIGNATURE + * FIS timeout timer. none + */ +static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( + void *object) +{ + struct scic_sds_phy *sci_phy = object; + + isci_timer_stop(sci_phy->sata_timeout_timer); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. - Set the struct scic_sds_phy + * object state handlers for this state. - Change base state machine to the + * ready state. none + */ +static void scic_sds_phy_starting_final_substate_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_starting_substate_handlers(sci_phy, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); + + /* State machine has run to completion so exit out and change + * the base state machine to the ready state + */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_READY); +} + +/* --------------------------------------------------------------------------- */ + +static const struct sci_base_state scic_sds_phy_starting_substates[] = { + [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { + .enter_state = scic_sds_phy_starting_initial_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { + .enter_state = scic_sds_phy_starting_await_ossp_en_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { + .enter_state = scic_sds_phy_starting_await_sas_speed_en_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { + .enter_state = scic_sds_phy_starting_await_iaf_uf_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { + .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, + .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { + .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { + .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { + .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { + .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter, + .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { + .enter_state = scic_sds_phy_starting_final_substate_enter, + } +}; + +/* + * This method takes the struct scic_sds_phy from a stopped state and + * attempts to start it. - The phy state machine is transitioned to the + * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS + */ +static enum sci_status +scic_sds_phy_stopped_state_start_handler(struct scic_sds_phy *sci_phy) +{ + struct isci_host *ihost; + struct scic_sds_controller *scic; + + scic = scic_sds_phy_get_controller(sci_phy), + ihost = scic_to_ihost(scic); + + /* Create the SIGNATURE FIS Timeout timer for this phy */ + sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, + scic_sds_phy_sata_timeout); + + if (sci_phy->sata_timeout_timer) + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + + return SCI_SUCCESS; +} + +static enum sci_status +scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) +{ + return SCI_SUCCESS; +} + +static enum sci_status +scic_sds_phy_ready_state_stop_handler(struct scic_sds_phy *sci_phy) +{ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STOPPED); + + return SCI_SUCCESS; +} + +static enum sci_status +scic_sds_phy_ready_state_reset_handler(struct scic_sds_phy *sci_phy) +{ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_RESETTING); + + return SCI_SUCCESS; +} + +/** + * scic_sds_phy_ready_state_event_handler - + * @phy: This is the struct scic_sds_phy object which has received the event. + * + * This method request the struct scic_sds_phy handle the received event. The only + * event that we are interested in while in the ready state is the link failure + * event. - decoded event is a link failure - transition the struct scic_sds_phy back + * to the SCI_BASE_PHY_STATE_STARTING state. - any other event received will + * report a warning message enum sci_status SCI_SUCCESS if the event received is a + * link failure SCI_FAILURE_INVALID_STATE for any other event received. + */ +static enum sci_status scic_sds_phy_ready_state_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) +{ + enum sci_status result = SCI_FAILURE; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + result = SCI_SUCCESS; + break; + + case SCU_EVENT_BROADCAST_CHANGE: + /* Broadcast change received. Notify the port. */ + if (scic_sds_phy_get_port(sci_phy) != NULL) + scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); + else + sci_phy->bcn_received_while_port_unassigned = true; + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%sP SCIC PHY 0x%p ready state machine received " + "unexpected event_code %x\n", + __func__, sci_phy, event_code); + + result = SCI_FAILURE_INVALID_STATE; + break; + } + + return result; +} + +static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) +{ + enum sci_status result = SCI_FAILURE; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_HARD_RESET_TRANSMITTED: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + result = SCI_SUCCESS; + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: SCIC PHY 0x%p resetting state machine received " + "unexpected event_code %x\n", + __func__, sci_phy, event_code); + + result = SCI_FAILURE_INVALID_STATE; + break; + } + + return result; +} + +/* --------------------------------------------------------------------------- */ + +static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { + [SCI_BASE_PHY_STATE_INITIAL] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_STOPPED] = { + .start_handler = scic_sds_phy_stopped_state_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_STARTING] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_READY] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_ready_state_stop_handler, + .reset_handler = scic_sds_phy_ready_state_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_ready_state_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_RESETTING] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_resetting_state_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_FINAL] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + } +}; + +/* + * **************************************************************************** + * * PHY STATE PRIVATE METHODS + * **************************************************************************** */ + +/** + * + * @sci_phy: This is the struct scic_sds_phy object to stop. + * + * This method will stop the struct scic_sds_phy object. This does not reset the + * protocol engine it just suspends it and places it in a state where it will + * not cause the end device to power up. none + */ +static void scu_link_layer_stop_protocol_engine( + struct scic_sds_phy *sci_phy) +{ + u32 scu_sas_pcfg_value; + u32 enable_spinup_value; + + /* Suspend the protocol engine and place it in a sata spinup hold state */ + scu_sas_pcfg_value = + readl(&sci_phy->link_layer_registers->phy_configuration); + scu_sas_pcfg_value |= + (SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | + SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) | + SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD)); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); + + /* Disable the notify enable spinup primitives */ + enable_spinup_value = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); + enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE); + writel(enable_spinup_value, &sci_phy->link_layer_registers->notify_enable_spinup_control); +} + +/** + * + * + * This method will start the OOB/SN state machine for this struct scic_sds_phy object. + */ +static void scu_link_layer_start_oob( + struct scic_sds_phy *sci_phy) +{ + u32 scu_sas_pcfg_value; + + scu_sas_pcfg_value = + readl(&sci_phy->link_layer_registers->phy_configuration); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); + scu_sas_pcfg_value &= + ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | + SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); +} + +/** + * + * + * This method will transmit a hard reset request on the specified phy. The SCU + * hardware requires that we reset the OOB state machine and set the hard reset + * bit in the phy configuration register. We then must start OOB over with the + * hard reset bit set. + */ +static void scu_link_layer_tx_hard_reset( + struct scic_sds_phy *sci_phy) +{ + u32 phy_configuration_value; + + /* + * SAS Phys must wait for the HARD_RESET_TX event notification to transition + * to the starting state. */ + phy_configuration_value = + readl(&sci_phy->link_layer_registers->phy_configuration); + phy_configuration_value |= + (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | + SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); + writel(phy_configuration_value, + &sci_phy->link_layer_registers->phy_configuration); + + /* Now take the OOB state machine out of reset */ + phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); + phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + writel(phy_configuration_value, + &sci_phy->link_layer_registers->phy_configuration); +} + +/* + * **************************************************************************** + * * PHY BASE STATE METHODS + * **************************************************************************** */ + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state + * handlers for the phy object base state machine initial state. none + */ +static void scic_sds_phy_initial_state_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_INITIAL); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This function will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state + * handlers for the phy object base state machine initial state. - The SCU + * hardware is requested to stop the protocol engine. none + */ +static void scic_sds_phy_stopped_state_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); + struct isci_host *ihost = scic_to_ihost(scic); + + /* + * @todo We need to get to the controller to place this PE in a + * reset state + */ + + scic_sds_phy_set_base_state_handlers(sci_phy, + SCI_BASE_PHY_STATE_STOPPED); + + if (sci_phy->sata_timeout_timer != NULL) { + isci_del_timer(ihost, sci_phy->sata_timeout_timer); + + sci_phy->sata_timeout_timer = NULL; + } + + scu_link_layer_stop_protocol_engine(sci_phy); + + if (sci_phy->state_machine.previous_state_id != + SCI_BASE_PHY_STATE_INITIAL) + scic_sds_controller_link_down( + scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_STARTING. - This function sets the state + * handlers for the phy object base state machine starting state. - The SCU + * hardware is requested to start OOB/SN on this protocl engine. - The phy + * starting substate machine is started. - If the previous state was the ready + * state then the struct scic_sds_controller is informed that the phy has gone link + * down. none + */ +static void scic_sds_phy_starting_state_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STARTING); + + scu_link_layer_stop_protocol_engine(sci_phy); + scu_link_layer_start_oob(sci_phy); + + /* We don't know what kind of phy we are going to be just yet */ + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; + sci_phy->bcn_received_while_port_unassigned = false; + + /* Change over to the starting substate machine to continue */ + sci_base_state_machine_start(&sci_phy->starting_substate_machine); + + if (sci_phy->state_machine.previous_state_id + == SCI_BASE_PHY_STATE_READY) { + scic_sds_controller_link_down( + scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy + ); + } +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_READY. - This function sets the state + * handlers for the phy object base state machine ready state. - The SCU + * hardware protocol engine is resumed. - The struct scic_sds_controller is informed + * that the phy object has gone link up. none + */ +static void scic_sds_phy_ready_state_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_READY); + + scic_sds_controller_link_up( + scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on exiting + * the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU hardware + * protocol engine represented by this struct scic_sds_phy object. none + */ +static void scic_sds_phy_ready_state_exit(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_suspend(sci_phy); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_RESETTING. - This function sets the state + * handlers for the phy object base state machine resetting state. none + */ +static void scic_sds_phy_resetting_state_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_RESETTING); + + /* + * The phy is being reset, therefore deactivate it from the port. + * In the resetting state we don't notify the user regarding + * link up and link down notifications. */ + scic_sds_port_deactivate_phy(sci_phy->owning_port, sci_phy, false); + + if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + scu_link_layer_tx_hard_reset(sci_phy); + } else { + /* + * The SCU does not need to have a discrete reset state so + * just go back to the starting state. + */ + sci_base_state_machine_change_state( + &sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + } +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_phy object. + * + * This method will perform the actions required by the struct scic_sds_phy on + * entering the SCI_BASE_PHY_STATE_FINAL. - This function sets the state + * handlers for the phy object base state machine final state. none + */ +static void scic_sds_phy_final_state_enter(void *object) +{ + struct scic_sds_phy *sci_phy = object; + + scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_FINAL); + + /* Nothing to do here */ +} + +/* --------------------------------------------------------------------------- */ + +static const struct sci_base_state scic_sds_phy_state_table[] = { + [SCI_BASE_PHY_STATE_INITIAL] = { + .enter_state = scic_sds_phy_initial_state_enter, + }, + [SCI_BASE_PHY_STATE_STOPPED] = { + .enter_state = scic_sds_phy_stopped_state_enter, + }, + [SCI_BASE_PHY_STATE_STARTING] = { + .enter_state = scic_sds_phy_starting_state_enter, + }, + [SCI_BASE_PHY_STATE_READY] = { + .enter_state = scic_sds_phy_ready_state_enter, + .exit_state = scic_sds_phy_ready_state_exit, + }, + [SCI_BASE_PHY_STATE_RESETTING] = { + .enter_state = scic_sds_phy_resetting_state_enter, + }, + [SCI_BASE_PHY_STATE_FINAL] = { + .enter_state = scic_sds_phy_final_state_enter, + }, +}; + +void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, + struct scic_sds_port *owning_port, u8 phy_index) +{ + sci_base_state_machine_construct(&sci_phy->state_machine, + sci_phy, + scic_sds_phy_state_table, + SCI_BASE_PHY_STATE_INITIAL); + + sci_base_state_machine_start(&sci_phy->state_machine); + + /* Copy the rest of the input data to our locals */ + sci_phy->owning_port = owning_port; + sci_phy->phy_index = phy_index; + sci_phy->bcn_received_while_port_unassigned = false; + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; + sci_phy->link_layer_registers = NULL; + sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; + sci_phy->sata_timeout_timer = NULL; + + /* Initialize the the substate machines */ + sci_base_state_machine_construct(&sci_phy->starting_substate_machine, + sci_phy, + scic_sds_phy_starting_substates, + SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); +} void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index) { diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 3a95adbb508c..093fd473366c 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -57,7 +57,105 @@ #include #include -#include "scic_sds_phy.h" +#include "state_machine.h" + +/* This is the timeout value for the SATA phy to wait for a SIGNATURE FIS + * before restarting the starting state machine. Technically, the old parallel + * ATA specification required up to 30 seconds for a device to issue its + * signature FIS as a result of a soft reset. Now we see that devices respond + * generally within 15 seconds, but we'll use 25 for now. + */ +#define SCIC_SDS_SIGNATURE_FIS_TIMEOUT 25000 + +/* This is the timeout for the SATA OOB/SN because the hardware does not + * recognize a hot plug after OOB signal but before the SN signals. We need to + * make sure after a hotplug timeout if we have not received the speed event + * notification from the hardware that we restart the hardware OOB state + * machine. + */ +#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250 + +enum scic_sds_phy_protocol { + SCIC_SDS_PHY_PROTOCOL_UNKNOWN, + SCIC_SDS_PHY_PROTOCOL_SAS, + SCIC_SDS_PHY_PROTOCOL_SATA, + SCIC_SDS_MAX_PHY_PROTOCOLS +}; + +/** + * struct scic_sds_phy - This structure contains or references all of the data + * necessary to represent the core phy object and SCU harware protocol + * engine. + * + * + */ +struct scic_sds_phy { + /** + * This field contains the information for the base phy state machine. + */ + struct sci_base_state_machine state_machine; + + /** + * This field specifies the port object that owns/contains this phy. + */ + struct scic_sds_port *owning_port; + + /** + * This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s, + * or 6.0 Gb/s operation. + */ + enum sas_linkrate max_negotiated_speed; + + /** + * This member specifies the protocol being utilized on this phy. This + * field contains a legitamite value once the PHY has link trained with + * a remote phy. + */ + enum scic_sds_phy_protocol protocol; + + /** + * This field specifies the index with which this phy is associated (0-3). + */ + u8 phy_index; + + /** + * This member indicates if this particular PHY has received a BCN while + * it had no port assignement. This BCN will be reported once the phy is + * assigned to a port. + */ + bool bcn_received_while_port_unassigned; + + /** + * This field indicates if this PHY is currently in the process of + * link training (i.e. it has started OOB, but has yet to perform + * IAF exchange/Signature FIS reception). + */ + bool is_in_link_training; + + /** + * This field contains a reference to the timer utilized in detecting + * when a signature FIS timeout has occurred. The signature FIS is the + * first FIS sent by an attached SATA device after OOB/SN. + */ + void *sata_timeout_timer; + + const struct scic_sds_phy_state_handler *state_handlers; + + struct sci_base_state_machine starting_substate_machine; + + /** + * This field is the pointer to the transport layer register for the SCU + * hardware. + */ + struct scu_transport_layer_registers __iomem *transport_layer_registers; + + /** + * This field points to the link layer register set within the SCU. + */ + struct scu_link_layer_registers __iomem *link_layer_registers; + +}; + struct isci_phy { struct scic_sds_phy sci; @@ -85,6 +183,480 @@ static inline struct isci_phy *sci_phy_to_iphy(struct scic_sds_phy *sci_phy) return iphy; } +struct scic_phy_cap { + union { + struct { + /* + * The SAS specification indicates the start bit shall + * always be set to + * 1. This implementation will have the start bit set + * to 0 if the PHY CAPABILITIES were either not + * received or speed negotiation failed. + */ + u8 start:1; + u8 tx_ssc_type:1; + u8 res1:2; + u8 req_logical_linkrate:4; + + u32 gen1_no_ssc:1; + u32 gen1_ssc:1; + u32 gen2_no_ssc:1; + u32 gen2_ssc:1; + u32 gen3_no_ssc:1; + u32 gen3_ssc:1; + u32 res2:17; + u32 parity:1; + }; + u32 all; + }; +} __packed; + +/* this data structure reflects the link layer transmit identification reg */ +struct scic_phy_proto { + union { + struct { + u16 _r_a:1; + u16 smp_iport:1; + u16 stp_iport:1; + u16 ssp_iport:1; + u16 _r_b:4; + u16 _r_c:1; + u16 smp_tport:1; + u16 stp_tport:1; + u16 ssp_tport:1; + u16 _r_d:4; + }; + u16 all; + }; +} __packed; + + +/** + * struct scic_phy_properties - This structure defines the properties common to + * all phys that can be retrieved. + * + * + */ +struct scic_phy_properties { + /** + * This field specifies the port that currently contains the + * supplied phy. This field may be set to NULL + * if the phy is not currently contained in a port. + */ + struct scic_sds_port *owning_port; + + /** + * This field specifies the link rate at which the phy is + * currently operating. + */ + enum sas_linkrate negotiated_link_rate; + + /** + * This field specifies the index of the phy in relation to other + * phys within the controller. This index is zero relative. + */ + u8 index; +}; + +/** + * struct scic_sas_phy_properties - This structure defines the properties, + * specific to a SAS phy, that can be retrieved. + * + * + */ +struct scic_sas_phy_properties { + /** + * This field delineates the Identify Address Frame received + * from the remote end point. + */ + struct sas_identify_frame rcvd_iaf; + + /** + * This field delineates the Phy capabilities structure received + * from the remote end point. + */ + struct scic_phy_cap rcvd_cap; + +}; + +/** + * struct scic_sata_phy_properties - This structure defines the properties, + * specific to a SATA phy, that can be retrieved. + * + * + */ +struct scic_sata_phy_properties { + /** + * This field delineates the signature FIS received from the + * attached target. + */ + struct dev_to_host_fis signature_fis; + + /** + * This field specifies to the user if a port selector is connected + * on the specified phy. + */ + bool is_port_selector_present; + +}; + +/** + * enum scic_phy_counter_id - This enumeration depicts the various pieces of + * optional information that can be retrieved for a specific phy. + * + * + */ +enum scic_phy_counter_id { + /** + * This PHY information field tracks the number of frames received. + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME, + + /** + * This PHY information field tracks the number of frames transmitted. + */ + SCIC_PHY_COUNTER_TRANSMITTED_FRAME, + + /** + * This PHY information field tracks the number of DWORDs received. + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME_WORD, + + /** + * This PHY information field tracks the number of DWORDs transmitted. + */ + SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD, + + /** + * This PHY information field tracks the number of times DWORD + * synchronization was lost. + */ + SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR, + + /** + * This PHY information field tracks the number of received DWORDs with + * running disparity errors. + */ + SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR, + + /** + * This PHY information field tracks the number of received frames with a + * CRC error (not including short or truncated frames). + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR, + + /** + * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT) + * primitives received. + */ + SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT, + + /** + * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT) + * primitives transmitted. + */ + SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT, + + /** + * This PHY information field tracks the number of times the inactivity + * timer for connections on the phy has been utilized. + */ + SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED, + + /** + * This PHY information field tracks the number of DONE (CREDIT TIMEOUT) + * primitives received. + */ + SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT, + + /** + * This PHY information field tracks the number of DONE (CREDIT TIMEOUT) + * primitives transmitted. + */ + SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT, + + /** + * This PHY information field tracks the number of CREDIT BLOCKED + * primitives received. + * @note Depending on remote device implementation, credit blocks + * may occur regularly. + */ + SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED, + + /** + * This PHY information field contains the number of short frames + * received. A short frame is simply a frame smaller then what is + * allowed by either the SAS or SATA specification. + */ + SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME, + + /** + * This PHY information field contains the number of frames received after + * credit has been exhausted. + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT, + + /** + * This PHY information field contains the number of frames received after + * a DONE has been received. + */ + SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE, + + /** + * This PHY information field contains the number of times the phy + * failed to achieve DWORD synchronization during speed negotiation. + */ + SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR +}; + +enum scic_sds_phy_states { + /** + * Simply the initial state for the base domain state machine. + */ + SCI_BASE_PHY_STATE_INITIAL, + + /** + * This state indicates that the phy has successfully been stopped. + * In this state no new IO operations are permitted on this phy. + * This state is entered from the INITIAL state. + * This state is entered from the STARTING state. + * This state is entered from the READY state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PHY_STATE_STOPPED, + + /** + * This state indicates that the phy is in the process of becomming + * ready. In this state no new IO operations are permitted on this phy. + * This state is entered from the STOPPED state. + * This state is entered from the READY state. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PHY_STATE_STARTING, + + /** + * This state indicates the the phy is now ready. Thus, the user + * is able to perform IO operations utilizing this phy as long as it + * is currently part of a valid port. + * This state is entered from the STARTING state. + */ + SCI_BASE_PHY_STATE_READY, + + /** + * This state indicates that the phy is in the process of being reset. + * In this state no new IO operations are permitted on this phy. + * This state is entered from the READY state. + */ + SCI_BASE_PHY_STATE_RESETTING, + + /** + * Simply the final state for the base phy state machine. + */ + SCI_BASE_PHY_STATE_FINAL, +}; + + +/** + * enum scic_sds_phy_starting_substates - + * + * + */ +enum scic_sds_phy_starting_substates { + /** + * Initial state + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL, + + /** + * Wait state for the hardware OSSP event type notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN, + + /** + * Wait state for the PHY speed notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN, + + /** + * Wait state for the IAF Unsolicited frame notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF, + + /** + * Wait state for the request to consume power + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER, + + /** + * Wait state for request to consume power + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, + + /** + * Wait state for the SATA PHY notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, + + /** + * Wait for the SATA PHY speed notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, + + /** + * Wait state for the SIGNATURE FIS unsolicited frame notification + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, + + /** + * Exit state for this state machine + */ + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL, +}; + + + +typedef enum sci_status (*scic_sds_phy_handler_t)(struct scic_sds_phy *); +typedef enum sci_status (*scic_sds_phy_event_handler_t)(struct scic_sds_phy *, u32); +typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u32); +typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); + +struct scic_sds_phy_state_handler { + /** + * The start_handler specifies the method invoked when there is an + * attempt to start a phy. + */ + scic_sds_phy_handler_t start_handler; + + /** + * The stop_handler specifies the method invoked when there is an + * attempt to stop a phy. + */ + scic_sds_phy_handler_t stop_handler; + + /** + * The reset_handler specifies the method invoked when there is an + * attempt to reset a phy. + */ + scic_sds_phy_handler_t reset_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a phy. + */ + scic_sds_phy_handler_t destruct_handler; + + /** + * The state handler for unsolicited frames received from the SCU hardware. + */ + scic_sds_phy_frame_handler_t frame_handler; + + /** + * The state handler for events received from the SCU hardware. + */ + scic_sds_phy_event_handler_t event_handler; + + /** + * The state handler for staggered spinup. + */ + scic_sds_phy_power_handler_t consume_power_handler; + +}; + +/** + * scic_sds_phy_get_index() - + * + * This macro returns the phy index for the specified phy + */ +#define scic_sds_phy_get_index(phy) \ + ((phy)->phy_index) + +/** + * scic_sds_phy_get_controller() - This macro returns the controller for this + * phy + * + * + */ +#define scic_sds_phy_get_controller(phy) \ + (scic_sds_port_get_controller((phy)->owning_port)) + +/** + * scic_sds_phy_set_state_handlers() - This macro sets the state handlers for + * this phy object + * + * + */ +#define scic_sds_phy_set_state_handlers(phy, handlers) \ + ((phy)->state_handlers = (handlers)) + +/** + * scic_sds_phy_set_base_state_handlers() - + * + * This macro set the base state handlers for the phy object. + */ +#define scic_sds_phy_set_base_state_handlers(phy, state_id) \ + scic_sds_phy_set_state_handlers(\ + (phy), \ + &scic_sds_phy_state_handler_table[(state_id)] \ + ) + +void scic_sds_phy_construct( + struct scic_sds_phy *this_phy, + struct scic_sds_port *owning_port, + u8 phy_index); + +struct scic_sds_port *scic_sds_phy_get_port( + struct scic_sds_phy *this_phy); + +void scic_sds_phy_set_port( + struct scic_sds_phy *this_phy, + struct scic_sds_port *owning_port); + +enum sci_status scic_sds_phy_initialize( + struct scic_sds_phy *this_phy, + struct scu_transport_layer_registers __iomem *transport_layer_registers, + struct scu_link_layer_registers __iomem *link_layer_registers); + +enum sci_status scic_sds_phy_start( + struct scic_sds_phy *this_phy); + +enum sci_status scic_sds_phy_stop( + struct scic_sds_phy *this_phy); + +enum sci_status scic_sds_phy_reset( + struct scic_sds_phy *this_phy); + +void scic_sds_phy_resume( + struct scic_sds_phy *this_phy); + +void scic_sds_phy_setup_transport( + struct scic_sds_phy *this_phy, + u32 device_id); + +enum sci_status scic_sds_phy_event_handler( + struct scic_sds_phy *this_phy, + u32 event_code); + +enum sci_status scic_sds_phy_frame_handler( + struct scic_sds_phy *this_phy, + u32 frame_index); + +enum sci_status scic_sds_phy_consume_power_handler( + struct scic_sds_phy *this_phy); + +void scic_sds_phy_get_sas_address( + struct scic_sds_phy *this_phy, + struct sci_sas_address *sas_address); + +void scic_sds_phy_get_attached_sas_address( + struct scic_sds_phy *this_phy, + struct sci_sas_address *sas_address); + +struct scic_phy_proto; +void scic_sds_phy_get_protocols( + struct scic_sds_phy *sci_phy, + struct scic_phy_proto *protocols); +enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy); + struct isci_host; void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index); int isci_phy_control(struct asd_sas_phy *phy, enum phy_func func, void *buf); diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index d4bf6d2d8c9b..321935d9560b 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -55,8 +55,6 @@ #include #include "isci.h" -#include "scic_phy.h" -#include "scic_sds_phy.h" #include "scic_port.h" #include "port.h" #include "request.h" diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 23390102514f..2baa215cb275 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -57,9 +57,7 @@ #include "port.h" #include "remote_device.h" #include "request.h" -#include "scic_phy.h" #include "scic_port.h" -#include "scic_sds_phy.h" #include "scic_sds_port.h" #include "remote_node_context.h" #include "scu_event_codes.h" -- cgit v1.2.3 From e2f8db509fdd354bb7a68c86515e9d2d8909ccc9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 May 2011 02:28:46 -0700 Subject: isci: uplevel port infrastructure * Move port configuration agent implementation * Merge core/scic_sds_port.[ch] into port.[ch] Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 4 +- drivers/scsi/isci/core/scic_config_parameters.h | 249 -- drivers/scsi/isci/core/scic_port.h | 97 - drivers/scsi/isci/core/scic_sds_port.c | 2423 ------------------- drivers/scsi/isci/core/scic_sds_port.h | 435 ---- .../isci/core/scic_sds_port_configuration_agent.c | 827 ------- .../isci/core/scic_sds_port_configuration_agent.h | 107 - drivers/scsi/isci/host.c | 1 - drivers/scsi/isci/host.h | 29 +- drivers/scsi/isci/phy.c | 3 +- drivers/scsi/isci/phy.h | 1 + drivers/scsi/isci/port.c | 2519 +++++++++++++++++++- drivers/scsi/isci/port.h | 425 +++- drivers/scsi/isci/port_config.c | 826 +++++++ drivers/scsi/isci/probe_roms.h | 124 +- drivers/scsi/isci/remote_device.c | 2 - drivers/scsi/isci/remote_node_context.c | 1 - drivers/scsi/isci/request.c | 1 - 18 files changed, 3789 insertions(+), 4285 deletions(-) delete mode 100644 drivers/scsi/isci/core/scic_config_parameters.h delete mode 100644 drivers/scsi/isci/core/scic_port.h delete mode 100644 drivers/scsi/isci/core/scic_sds_port.c delete mode 100644 drivers/scsi/isci/core/scic_sds_port.h delete mode 100644 drivers/scsi/isci/core/scic_sds_port_configuration_agent.c delete mode 100644 drivers/scsi/isci/core/scic_sds_port_configuration_agent.h create mode 100644 drivers/scsi/isci/port_config.c diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 2830a97a822a..48218ca908fe 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -1,4 +1,3 @@ -EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ remote_device.o port.o timers.o \ @@ -10,5 +9,4 @@ isci-objs := init.o phy.o request.o sata.o \ stp_request.o \ ssp_request.o \ smp_request.o \ - core/scic_sds_port.o \ - core/scic_sds_port_configuration_agent.o \ + port_config.o \ diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h deleted file mode 100644 index 15e7744dbdcf..000000000000 --- a/drivers/scsi/isci/core/scic_config_parameters.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_USER_PARAMETERS_H_ -#define _SCIC_SDS_USER_PARAMETERS_H_ - -#include "probe_roms.h" - -struct scic_sds_controller; - -/** - * - * - * SCIC_SDS_PARM_PHY_SPEED These constants define the speeds utilized for a - * phy/port. - */ -#define SCIC_SDS_PARM_NO_SPEED 0 - -/** - * - * - * This value of 1 indicates generation 1 (i.e. 1.5 Gb/s). - */ -#define SCIC_SDS_PARM_GEN1_SPEED 1 - -/** - * - * - * This value of 2 indicates generation 2 (i.e. 3.0 Gb/s). - */ -#define SCIC_SDS_PARM_GEN2_SPEED 2 - -/** - * - * - * This value of 3 indicates generation 3 (i.e. 6.0 Gb/s). - */ -#define SCIC_SDS_PARM_GEN3_SPEED 3 - -/** - * - * - * For range checks, the max speed generation - */ -#define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED - -/** - * struct scic_sds_user_parameters - This structure delineates the various user - * parameters that can be changed by the core user. - * - * - */ -struct scic_sds_user_parameters { - struct sci_phy_user_params { - /** - * This field specifies the NOTIFY (ENABLE SPIN UP) primitive - * insertion frequency for this phy index. - */ - u32 notify_enable_spin_up_insertion_frequency; - - /** - * This method specifies the number of transmitted DWORDs within which - * to transmit a single ALIGN primitive. This value applies regardless - * of what type of device is attached or connection state. A value of - * 0 indicates that no ALIGN primitives will be inserted. - */ - u16 align_insertion_frequency; - - /** - * This method specifies the number of transmitted DWORDs within which - * to transmit 2 ALIGN primitives. This applies for SAS connections - * only. A minimum value of 3 is required for this field. - */ - u16 in_connection_align_insertion_frequency; - - /** - * This field indicates the maximum speed generation to be utilized - * by phys in the supplied port. - * - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s). - * - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s). - * - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s). - */ - u8 max_speed_generation; - - } phys[SCI_MAX_PHYS]; - - /** - * This field specifies the maximum number of direct attached devices - * that can have power supplied to them simultaneously. - */ - u8 max_number_concurrent_device_spin_up; - - /** - * This field specifies the number of seconds to allow a phy to consume - * power before yielding to another phy. - * - */ - u8 phy_spin_up_delay_interval; - - /** - * These timer values specifies how long a link will remain open with no - * activity in increments of a microsecond, it can be in increments of - * 100 microseconds if the upper most bit is set. - * - */ - u16 stp_inactivity_timeout; - u16 ssp_inactivity_timeout; - - /** - * These timer values specifies how long a link will remain open in increments - * of 100 microseconds. - * - */ - u16 stp_max_occupancy_timeout; - u16 ssp_max_occupancy_timeout; - - /** - * This timer value specifies how long a link will remain open with no - * outbound traffic in increments of a microsecond. - * - */ - u8 no_outbound_task_timeout; - -}; - -/** - * This structure/union specifies the various different user parameter sets - * available. Each type is specific to a hardware controller version. - * - * union scic_user_parameters - */ -union scic_user_parameters { - /** - * This field specifies the user parameters specific to the - * Storage Controller Unit (SCU) Driver Standard (SDS) version - * 1. - */ - struct scic_sds_user_parameters sds1; - -}; - - -/** - * - * - * SCIC_SDS_OEM_PHY_MASK These constants define the valid values for phy_mask - */ - -/** - * - * - * This is the min value assignable to a port's phy mask - */ -#define SCIC_SDS_PARM_PHY_MASK_MIN 0x0 - -/** - * - * - * This is the max value assignable to a port's phy mask - */ -#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF - -#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4 - -/** - * This structure/union specifies the various different OEM parameter sets - * available. Each type is specific to a hardware controller version. - * - * union scic_oem_parameters - */ -union scic_oem_parameters { - /** - * This field specifies the OEM parameters specific to the - * Storage Controller Unit (SCU) Driver Standard (SDS) version - * 1. - */ - struct scic_sds_oem_params sds1; -}; - -int scic_oem_parameters_validate(struct scic_sds_oem_params *oem); - -/** - * scic_oem_parameters_get() - This method allows the user to retreive the OEM - * parameters utilized by the controller. - * @controller: This parameter specifies the controller on which to set the - * user parameters. - * @oem_parameters: This parameter specifies the OEM parameters object in which - * to write the core's OEM parameters. - * - */ -void scic_oem_parameters_get( - struct scic_sds_controller *controller, - union scic_oem_parameters *oem_parameters); - - -#endif /* _SCIC_SDS_USER_PARAMETERS_H_ */ - diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h deleted file mode 100644 index 431dbd2093f3..000000000000 --- a/drivers/scsi/isci/core/scic_port.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_PORT_H_ -#define _SCIC_PORT_H_ - -#include "isci.h" -#include "sas.h" -#include "phy.h" - -struct scic_sds_port; - -enum scic_port_not_ready_reason_code { - SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, - SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, - SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, - SCIC_PORT_NOT_READY_RECONFIGURING, - - SCIC_PORT_NOT_READY_REASON_CODE_MAX -}; - -struct scic_port_end_point_properties { - struct sci_sas_address sas_address; - struct scic_phy_proto protocols; -}; - -struct scic_port_properties { - u32 index; - struct scic_port_end_point_properties local; - struct scic_port_end_point_properties remote; - u32 phy_mask; -}; - -enum sci_status scic_port_get_properties( - struct scic_sds_port *port, - struct scic_port_properties *properties); - -enum sci_status scic_port_hard_reset( - struct scic_sds_port *port, - u32 reset_timeout); - -void scic_port_enable_broadcast_change_notification( - struct scic_sds_port *port); - -#endif /* _SCIC_PORT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c deleted file mode 100644 index 11b516a9a130..000000000000 --- a/drivers/scsi/isci/core/scic_sds_port.c +++ /dev/null @@ -1,2423 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "host.h" -#include "scic_port.h" -#include "scic_sds_port.h" -#include "remote_device.h" -#include "remote_node_context.h" -#include "registers.h" -#include "timers.h" -#include "scu_task_context.h" - -#define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) -#define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) - -#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) -#define SCU_DUMMY_INDEX (0xFFFF) - - -/** - * - * @sci_port: This is the port object to which the phy is being assigned. - * @phy_index: This is the phy index that is being assigned to the port. - * - * This method will return a true value if the specified phy can be assigned to - * this port The following is a list of phys for each port that are allowed: - - * Port 0 - 3 2 1 0 - Port 1 - 1 - Port 2 - 3 2 - Port 3 - 3 This method - * doesn't preclude all configurations. It merely ensures that a phy is part - * of the allowable set of phy identifiers for that port. For example, one - * could assign phy 3 to port 0 and no other phys. Please refer to - * scic_sds_port_is_phy_mask_valid() for information regarding whether the - * phy_mask for a port can be supported. bool true if this is a valid phy - * assignment for the port false if this is not a valid phy assignment for the - * port - */ -bool scic_sds_port_is_valid_phy_assignment( - struct scic_sds_port *sci_port, - u32 phy_index) -{ - /* Initialize to invalid value. */ - u32 existing_phy_index = SCI_MAX_PHYS; - u32 index; - - if ((sci_port->physical_port_index == 1) && (phy_index != 1)) { - return false; - } - - if (sci_port->physical_port_index == 3 && phy_index != 3) { - return false; - } - - if ( - (sci_port->physical_port_index == 2) - && ((phy_index == 0) || (phy_index == 1)) - ) { - return false; - } - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if ((sci_port->phy_table[index] != NULL) - && (index != phy_index)) { - existing_phy_index = index; - } - } - - /* - * Ensure that all of the phys in the port are capable of - * operating at the same maximum link rate. */ - if ( - (existing_phy_index < SCI_MAX_PHYS) - && (sci_port->owning_controller->user_parameters.sds1.phys[ - phy_index].max_speed_generation != - sci_port->owning_controller->user_parameters.sds1.phys[ - existing_phy_index].max_speed_generation) - ) - return false; - - return true; -} - -/** - * This method requests a list (mask) of the phys contained in the supplied SAS - * port. - * @sci_port: a handle corresponding to the SAS port for which to return the - * phy mask. - * - * Return a bit mask indicating which phys are a part of this port. Each bit - * corresponds to a phy identifier (e.g. bit 0 = phy id 0). - */ -static u32 scic_sds_port_get_phys(struct scic_sds_port *sci_port) -{ - u32 index; - u32 mask; - - mask = 0; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) { - mask |= (1 << index); - } - } - - return mask; -} - -/** - * - * @sci_port: This is the port object for which to determine if the phy mask - * can be supported. - * - * This method will return a true value if the port's phy mask can be supported - * by the SCU. The following is a list of valid PHY mask configurations for - * each port: - Port 0 - [[3 2] 1] 0 - Port 1 - [1] - Port 2 - [[3] 2] - * - Port 3 - [3] This method returns a boolean indication specifying if the - * phy mask can be supported. true if this is a valid phy assignment for the - * port false if this is not a valid phy assignment for the port - */ -static bool scic_sds_port_is_phy_mask_valid( - struct scic_sds_port *sci_port, - u32 phy_mask) -{ - if (sci_port->physical_port_index == 0) { - if (((phy_mask & 0x0F) == 0x0F) - || ((phy_mask & 0x03) == 0x03) - || ((phy_mask & 0x01) == 0x01) - || (phy_mask == 0)) - return true; - } else if (sci_port->physical_port_index == 1) { - if (((phy_mask & 0x02) == 0x02) - || (phy_mask == 0)) - return true; - } else if (sci_port->physical_port_index == 2) { - if (((phy_mask & 0x0C) == 0x0C) - || ((phy_mask & 0x04) == 0x04) - || (phy_mask == 0)) - return true; - } else if (sci_port->physical_port_index == 3) { - if (((phy_mask & 0x08) == 0x08) - || (phy_mask == 0)) - return true; - } - - return false; -} - -/** - * - * @sci_port: This parameter specifies the port from which to return a - * connected phy. - * - * This method retrieves a currently active (i.e. connected) phy contained in - * the port. Currently, the lowest order phy that is connected is returned. - * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is - * returned if there are no currently active (i.e. connected to a remote end - * point) phys contained in the port. All other values specify a struct scic_sds_phy - * object that is active in the port. - */ -static struct scic_sds_phy *scic_sds_port_get_a_connected_phy( - struct scic_sds_port *sci_port - ) { - u32 index; - struct scic_sds_phy *phy; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - /* - * Ensure that the phy is both part of the port and currently - * connected to the remote end-point. */ - phy = sci_port->phy_table[index]; - if ( - (phy != NULL) - && scic_sds_port_active_phy(sci_port, phy) - ) { - return phy; - } - } - - return NULL; -} - -/** - * scic_sds_port_set_phy() - - * @out]: port The port object to which the phy assignement is being made. - * @out]: phy The phy which is being assigned to the port. - * - * This method attempts to make the assignment of the phy to the port. If - * successful the phy is assigned to the ports phy table. bool true if the phy - * assignment can be made. false if the phy assignement can not be made. This - * is a functional test that only fails if the phy is currently assigned to a - * different port. - */ -static enum sci_status scic_sds_port_set_phy( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - /* - * Check to see if we can add this phy to a port - * that means that the phy is not part of a port and that the port does - * not already have a phy assinged to the phy index. */ - if ( - (port->phy_table[phy->phy_index] == NULL) - && (scic_sds_phy_get_port(phy) == NULL) - && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index) - ) { - /* - * Phy is being added in the stopped state so we are in MPC mode - * make logical port index = physical port index */ - port->logical_port_index = port->physical_port_index; - port->phy_table[phy->phy_index] = phy; - scic_sds_phy_set_port(phy, port); - - return SCI_SUCCESS; - } - - return SCI_FAILURE; -} - -/** - * scic_sds_port_clear_phy() - - * @out]: port The port from which the phy is being cleared. - * @out]: phy The phy being cleared from the port. - * - * This method will clear the phy assigned to this port. This method fails if - * this phy is not currently assinged to this port. bool true if the phy is - * removed from the port. false if this phy is not assined to this port. - */ -static enum sci_status scic_sds_port_clear_phy( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - /* Make sure that this phy is part of this port */ - if (port->phy_table[phy->phy_index] == phy && - scic_sds_phy_get_port(phy) == port) { - struct scic_sds_controller *scic = port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - - /* Yep it is assigned to this port so remove it */ - scic_sds_phy_set_port(phy, &ihost->ports[SCI_MAX_PORTS].sci); - port->phy_table[phy->phy_index] = NULL; - return SCI_SUCCESS; - } - - return SCI_FAILURE; -} - -/** - * scic_sds_port_add_phy() - - * @sci_port: This parameter specifies the port in which the phy will be added. - * @sci_phy: This parameter is the phy which is to be added to the port. - * - * This method will add a PHY to the selected port. This method returns an - * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status - * is failre to add the phy to the port. - */ -enum sci_status scic_sds_port_add_phy( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - return sci_port->state_handlers->add_phy_handler( - sci_port, sci_phy); -} - - -/** - * scic_sds_port_remove_phy() - - * @sci_port: This parameter specifies the port in which the phy will be added. - * @sci_phy: This parameter is the phy which is to be added to the port. - * - * This method will remove the PHY from the selected PORT. This method returns - * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other - * status is failre to add the phy to the port. - */ -enum sci_status scic_sds_port_remove_phy( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - return sci_port->state_handlers->remove_phy_handler( - sci_port, sci_phy); -} - -/** - * This method requests the SAS address for the supplied SAS port from the SCI - * implementation. - * @sci_port: a handle corresponding to the SAS port for which to return the - * SAS address. - * @sas_address: This parameter specifies a pointer to a SAS address structure - * into which the core will copy the SAS address for the port. - * - */ -void scic_sds_port_get_sas_address( - struct scic_sds_port *sci_port, - struct sci_sas_address *sas_address) -{ - u32 index; - - sas_address->high = 0; - sas_address->low = 0; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) { - scic_sds_phy_get_sas_address(sci_port->phy_table[index], sas_address); - } - } -} - -/* - * This function will indicate which protocols are supported by this port. - * @sci_port: a handle corresponding to the SAS port for which to return the - * supported protocols. - * @protocols: This parameter specifies a pointer to a data structure - * which the core will copy the protocol values for the port from the - * transmit_identification register. - */ -static void -scic_sds_port_get_protocols(struct scic_sds_port *sci_port, - struct scic_phy_proto *protocols) -{ - u8 index; - - protocols->all = 0; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) { - scic_sds_phy_get_protocols(sci_port->phy_table[index], - protocols); - } - } -} - -/* - * This function requests the SAS address for the device directly attached to - * this SAS port. - * @sci_port: a handle corresponding to the SAS port for which to return the - * SAS address. - * @sas_address: This parameter specifies a pointer to a SAS address structure - * into which the core will copy the SAS address for the device directly - * attached to the port. - * - */ -void scic_sds_port_get_attached_sas_address( - struct scic_sds_port *sci_port, - struct sci_sas_address *sas_address) -{ - struct scic_sds_phy *sci_phy; - - /* - * Ensure that the phy is both part of the port and currently - * connected to the remote end-point. - */ - sci_phy = scic_sds_port_get_a_connected_phy(sci_port); - if (sci_phy) { - if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) { - scic_sds_phy_get_attached_sas_address(sci_phy, - sas_address); - } else { - scic_sds_phy_get_sas_address(sci_phy, sas_address); - sas_address->low += sci_phy->phy_index; - } - } else { - sas_address->high = 0; - sas_address->low = 0; - } -} - -/** - * scic_sds_port_construct_dummy_rnc() - create dummy rnc for si workaround - * - * @sci_port: logical port on which we need to create the remote node context - * @rni: remote node index for this remote node context. - * - * This routine will construct a dummy remote node context data structure - * This structure will be posted to the hardware to work around a scheduler - * error in the hardware. - */ -static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni) -{ - union scu_remote_node_context *rnc; - - rnc = &sci_port->owning_controller->remote_node_context_table[rni]; - - memset(rnc, 0, sizeof(union scu_remote_node_context)); - - rnc->ssp.remote_sas_address_hi = 0; - rnc->ssp.remote_sas_address_lo = 0; - - rnc->ssp.remote_node_index = rni; - rnc->ssp.remote_node_port_width = 1; - rnc->ssp.logical_port_index = sci_port->physical_port_index; - - rnc->ssp.nexus_loss_timer_enable = false; - rnc->ssp.check_bit = false; - rnc->ssp.is_valid = true; - rnc->ssp.is_remote_node_context = true; - rnc->ssp.function_number = 0; - rnc->ssp.arbitration_wait_time = 0; -} - -/** - * scic_sds_port_construct_dummy_task() - create dummy task for si workaround - * @sci_port The logical port on which we need to create the - * remote node context. - * context. - * @tci The remote node index for this remote node context. - * - * This routine will construct a dummy task context data structure. This - * structure will be posted to the hardwre to work around a scheduler error - * in the hardware. - * - */ -static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci) -{ - struct scu_task_context *task_context; - - task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tci); - - memset(task_context, 0, sizeof(struct scu_task_context)); - - task_context->abort = 0; - task_context->priority = 0; - task_context->initiator_request = 1; - task_context->connection_rate = 1; - task_context->protocol_engine_index = 0; - task_context->logical_port_index = sci_port->physical_port_index; - task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; - task_context->task_index = scic_sds_io_tag_get_index(tci); - task_context->valid = SCU_TASK_CONTEXT_VALID; - task_context->context_type = SCU_TASK_CONTEXT_TYPE; - - task_context->remote_node_index = sci_port->reserved_rni; - task_context->command_code = 0; - - task_context->link_layer_control = 0; - task_context->do_not_dma_ssp_good_response = 1; - task_context->strict_ordering = 0; - task_context->control_frame = 0; - task_context->timeout_enable = 0; - task_context->block_guard_enable = 0; - - task_context->address_modifier = 0; - - task_context->task_phase = 0x01; -} - -static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - - if (sci_port->reserved_tci != SCU_DUMMY_INDEX) - scic_controller_free_io_tag(scic, sci_port->reserved_tci); - - if (sci_port->reserved_rni != SCU_DUMMY_INDEX) - scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes, - 1, sci_port->reserved_rni); - - sci_port->reserved_rni = SCU_DUMMY_INDEX; - sci_port->reserved_tci = SCU_DUMMY_INDEX; -} - -/** - * This method performs initialization of the supplied port. Initialization - * includes: - state machine initialization - member variable initialization - * - configuring the phy_mask - * @sci_port: - * @transport_layer_registers: - * @port_task_scheduler_registers: - * @port_configuration_regsiter: - * - * enum sci_status SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned - * if the phy being added to the port - */ -enum sci_status scic_sds_port_initialize( - struct scic_sds_port *sci_port, - void __iomem *port_task_scheduler_registers, - void __iomem *port_configuration_regsiter, - void __iomem *viit_registers) -{ - sci_port->port_task_scheduler_registers = port_task_scheduler_registers; - sci_port->port_pe_configuration_register = port_configuration_regsiter; - sci_port->viit_registers = viit_registers; - - return SCI_SUCCESS; -} - -/** - * scic_port_get_properties() - This method simply returns the properties - * regarding the port, such as: physical index, protocols, sas address, etc. - * @port: this parameter specifies the port for which to retrieve the physical - * index. - * @properties: This parameter specifies the properties structure into which to - * copy the requested information. - * - * Indicate if the user specified a valid port. SCI_SUCCESS This value is - * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This - * value is returned if the specified port is not valid. When this value is - * returned, no data is copied to the properties output parameter. - */ -enum sci_status scic_port_get_properties( - struct scic_sds_port *port, - struct scic_port_properties *prop) -{ - if ((port == NULL) || - (port->logical_port_index == SCIC_SDS_DUMMY_PORT)) - return SCI_FAILURE_INVALID_PORT; - - prop->index = port->logical_port_index; - prop->phy_mask = scic_sds_port_get_phys(port); - scic_sds_port_get_sas_address(port, &prop->local.sas_address); - scic_sds_port_get_protocols(port, &prop->local.protocols); - scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address); - - return SCI_SUCCESS; -} - -/** - * scic_port_hard_reset() - perform port hard reset - * @port: a handle corresponding to the SAS port to be hard reset. - * @reset_timeout: This parameter specifies the number of milliseconds in which - * the port reset operation should complete. - * - * The SCI User callback in scic_user_callbacks_t will only be called once for - * each phy in the SAS Port at completion of the hard reset sequence. Return a - * status indicating whether the hard reset started successfully. SCI_SUCCESS - * This value is returned if the hard reset operation started successfully. - */ -enum sci_status scic_port_hard_reset( - struct scic_sds_port *port, - u32 reset_timeout) -{ - return port->state_handlers->reset_handler( - port, reset_timeout); -} - -/** - * This method assigns the direct attached device ID for this port. - * - * @param[in] sci_port The port for which the direct attached device id is to - * be assigned. - * @param[in] device_id The direct attached device ID to assign to the port. - * This will be the RNi for the device - */ -void scic_sds_port_setup_transports( - struct scic_sds_port *sci_port, - u32 device_id) -{ - u8 index; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->active_phy_mask & (1 << index)) - scic_sds_phy_setup_transport(sci_port->phy_table[index], device_id); - } -} - -/** - * - * @sci_port: This is the port on which the phy should be enabled. - * @sci_phy: This is the specific phy which to enable. - * @do_notify_user: This parameter specifies whether to inform the user (via - * scic_cb_port_link_up()) as to the fact that a new phy as become ready. - * - * This function will activate the phy in the port. - * Activation includes: - adding - * the phy to the port - enabling the Protocol Engine in the silicon. - - * notifying the user that the link is up. none - */ -static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, - bool do_notify_user) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - - if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) - scic_sds_phy_resume(sci_phy); - - sci_port->active_phy_mask |= 1 << sci_phy->phy_index; - - scic_sds_controller_clear_invalid_phy(scic, sci_phy); - - if (do_notify_user == true) - isci_port_link_up(ihost, sci_port, sci_phy); -} - -void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, - bool do_notify_user) -{ - struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_port *iport = sci_port_to_iport(sci_port); - struct isci_host *ihost = scic_to_ihost(scic); - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); - - sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; - - /* Re-assign the phy back to the LP as if it were a narrow port */ - writel(sci_phy->phy_index, - &sci_port->port_pe_configuration_register[sci_phy->phy_index]); - - if (do_notify_user == true) - isci_port_link_down(ihost, iphy, iport); -} - -/** - * - * @sci_port: This is the port on which the phy should be disabled. - * @sci_phy: This is the specific phy which to disabled. - * - * This function will disable the phy and report that the phy is not valid for - * this port object. None - */ -static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - - /* - * Check to see if we have alreay reported this link as bad and if - * not go ahead and tell the SCI_USER that we have discovered an - * invalid link. - */ - if ((scic->invalid_phy_mask & (1 << sci_phy->phy_index)) == 0) { - scic_sds_controller_set_invalid_phy(scic, sci_phy); - dev_warn(&scic_to_ihost(scic)->pdev->dev, "Invalid link up!\n"); - } -} - -/** - * scic_sds_port_general_link_up_handler - phy can be assigned to port? - * @sci_port: scic_sds_port object for which has a phy that has gone link up. - * @sci_phy: This is the struct scic_sds_phy object that has gone link up. - * @do_notify_user: This parameter specifies whether to inform the user (via - * scic_cb_port_link_up()) as to the fact that a new phy as become ready. - * - * Determine if this phy can be assigned to this - * port . If the phy is not a valid PHY for - * this port then the function will notify the user. A PHY can only be - * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in - * the same port. none - */ -static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, - bool do_notify_user) -{ - struct sci_sas_address port_sas_address; - struct sci_sas_address phy_sas_address; - - scic_sds_port_get_attached_sas_address(sci_port, &port_sas_address); - scic_sds_phy_get_attached_sas_address(sci_phy, &phy_sas_address); - - /* If the SAS address of the new phy matches the SAS address of - * other phys in the port OR this is the first phy in the port, - * then activate the phy and allow it to be used for operations - * in this port. - */ - if ((phy_sas_address.high == port_sas_address.high && - phy_sas_address.low == port_sas_address.low) || - sci_port->active_phy_mask == 0) { - struct sci_base_state_machine *sm = &sci_port->state_machine; - - scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); - if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING) - sci_base_state_machine_change_state(sm, SCI_BASE_PORT_STATE_READY); - } else - scic_sds_port_invalid_link_up(sci_port, sci_phy); -} - - - -/** - * This method returns false if the port only has a single phy object assigned. - * If there are no phys or more than one phy then the method will return - * true. - * @sci_port: The port for which the wide port condition is to be checked. - * - * bool true Is returned if this is a wide ported port. false Is returned if - * this is a narrow port. - */ -static bool scic_sds_port_is_wide(struct scic_sds_port *sci_port) -{ - u32 index; - u32 phy_count = 0; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) { - phy_count++; - } - } - - return phy_count != 1; -} - -/** - * This method is called by the PHY object when the link is detected. if the - * port wants the PHY to continue on to the link up state then the port - * layer must return true. If the port object returns false the phy object - * must halt its attempt to go link up. - * @sci_port: The port associated with the phy object. - * @sci_phy: The phy object that is trying to go link up. - * - * true if the phy object can continue to the link up condition. true Is - * returned if this phy can continue to the ready state. false Is returned if - * can not continue on to the ready state. This notification is in place for - * wide ports and direct attached phys. Since there are no wide ported SATA - * devices this could become an invalid port configuration. - */ -bool scic_sds_port_link_detected( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - if ((sci_port->logical_port_index != SCIC_SDS_DUMMY_PORT) && - (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && - scic_sds_port_is_wide(sci_port)) { - scic_sds_port_invalid_link_up(sci_port, sci_phy); - - return false; - } - - return true; -} - -/** - * This method is the entry point for the phy to inform the port that it is now - * in a ready state - * @sci_port: - * - * - */ -void scic_sds_port_link_up( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - sci_phy->is_in_link_training = false; - - sci_port->state_handlers->link_up_handler(sci_port, sci_phy); -} - -/** - * This method is the entry point for the phy to inform the port that it is no - * longer in a ready state - * @sci_port: - * - * - */ -void scic_sds_port_link_down( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - sci_port->state_handlers->link_down_handler(sci_port, sci_phy); -} - -/** - * This method is called to start an IO request on this port. - * @sci_port: - * @sci_dev: - * @sci_req: - * - * enum sci_status - */ -enum sci_status scic_sds_port_start_io( - struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return sci_port->state_handlers->start_io_handler( - sci_port, sci_dev, sci_req); -} - -/** - * This method is called to complete an IO request to the port. - * @sci_port: - * @sci_dev: - * @sci_req: - * - * enum sci_status - */ -enum sci_status scic_sds_port_complete_io( - struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return sci_port->state_handlers->complete_io_handler( - sci_port, sci_dev, sci_req); -} - -/** - * This method is provided to timeout requests for port operations. Mostly its - * for the port reset operation. - * - * - */ -static void scic_sds_port_timeout_handler(void *port) -{ - struct scic_sds_port *sci_port = port; - u32 current_state; - - current_state = sci_base_state_machine_get_state( - &sci_port->state_machine); - - if (current_state == SCI_BASE_PORT_STATE_RESETTING) { - /* - * if the port is still in the resetting state then the - * timeout fired before the reset completed. - */ - sci_base_state_machine_change_state( - &sci_port->state_machine, - SCI_BASE_PORT_STATE_FAILED); - } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { - /* - * if the port is stopped then the start request failed - * In this case stay in the stopped state. - */ - dev_err(sciport_to_dev(sci_port), - "%s: SCIC Port 0x%p failed to stop before tiemout.\n", - __func__, - sci_port); - } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { - /* - * if the port is still stopping then the stop has not - * completed - */ - isci_port_stop_complete( - scic_sds_port_get_controller(sci_port), - sci_port, - SCI_FAILURE_TIMEOUT); - } else { - /* - * The port is in the ready state and we have a timer - * reporting a timeout this should not happen. - */ - dev_err(sciport_to_dev(sci_port), - "%s: SCIC Port 0x%p is processing a timeout operation " - "in state %d.\n", - __func__, - sci_port, - current_state); - } -} - -/* --------------------------------------------------------------------------- */ - -/** - * This function updates the hardwares VIIT entry for this port. - * - * - */ -static void scic_sds_port_update_viit_entry(struct scic_sds_port *sci_port) -{ - struct sci_sas_address sas_address; - - scic_sds_port_get_sas_address(sci_port, &sas_address); - - writel(sas_address.high, - &sci_port->viit_registers->initiator_sas_address_hi); - writel(sas_address.low, - &sci_port->viit_registers->initiator_sas_address_lo); - - /* This value get cleared just in case its not already cleared */ - writel(0, &sci_port->viit_registers->reserved); - - /* We are required to update the status register last */ - writel(SCU_VIIT_ENTRY_ID_VIIT | - SCU_VIIT_IPPT_INITIATOR | - ((1 << sci_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) | - SCU_VIIT_STATUS_ALL_VALID, - &sci_port->viit_registers->status); -} - -/** - * This method returns the maximum allowed speed for data transfers on this - * port. This maximum allowed speed evaluates to the maximum speed of the - * slowest phy in the port. - * @sci_port: This parameter specifies the port for which to retrieve the - * maximum allowed speed. - * - * This method returns the maximum negotiated speed of the slowest phy in the - * port. - */ -enum sas_linkrate scic_sds_port_get_max_allowed_speed( - struct scic_sds_port *sci_port) -{ - u16 index; - enum sas_linkrate max_allowed_speed = SAS_LINK_RATE_6_0_GBPS; - struct scic_sds_phy *phy = NULL; - - /* - * Loop through all of the phys in this port and find the phy with the - * lowest maximum link rate. */ - for (index = 0; index < SCI_MAX_PHYS; index++) { - phy = sci_port->phy_table[index]; - if ( - (phy != NULL) - && (scic_sds_port_active_phy(sci_port, phy) == true) - && (phy->max_negotiated_speed < max_allowed_speed) - ) - max_allowed_speed = phy->max_negotiated_speed; - } - - return max_allowed_speed; -} - - -/** - * This method passes the event to core user. - * @sci_port: The port that a BCN happens. - * @sci_phy: The phy that receives BCN. - * - */ -void scic_sds_port_broadcast_change_received( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - - /* notify the user. */ - isci_port_bc_change_received(ihost, sci_port, sci_phy); -} - - -/** - * This API methhod enables the broadcast change notification from underneath - * hardware. - * @sci_port: The port that a BCN had been disabled from. - * - */ -void scic_port_enable_broadcast_change_notification( - struct scic_sds_port *port) -{ - struct scic_sds_phy *phy; - u32 register_value; - u8 index; - - /* Loop through all of the phys to enable BCN. */ - for (index = 0; index < SCI_MAX_PHYS; index++) { - phy = port->phy_table[index]; - if (phy != NULL) { - register_value = - readl(&phy->link_layer_registers->link_layer_control); - - /* clear the bit by writing 1. */ - writel(register_value, - &phy->link_layer_registers->link_layer_control); - } - } -} - -/* - * **************************************************************************** - * * READY SUBSTATE HANDLERS - * **************************************************************************** */ - -/* - * This method is the general ready state stop handler for the struct scic_sds_port - * object. This function will transition the ready substate machine to its - * final state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_ready_substate_stop_handler( - struct scic_sds_port *port) -{ - sci_base_state_machine_change_state( - &port->state_machine, - SCI_BASE_PORT_STATE_STOPPING - ); - - return SCI_SUCCESS; -} - -/* - * This method is the general ready substate complete io handler for the - * struct scic_sds_port object. This function decrments the outstanding request count - * for this port object. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_ready_substate_complete_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - scic_sds_port_decrement_request_count(port); - - return SCI_SUCCESS; -} - -static enum sci_status scic_sds_port_ready_substate_add_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - enum sci_status status; - - status = scic_sds_port_set_phy(port, phy); - - if (status == SCI_SUCCESS) { - scic_sds_port_general_link_up_handler(port, phy, true); - - port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; - - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); - } - - return status; -} - - -static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - enum sci_status status; - - status = scic_sds_port_clear_phy(port, phy); - - if (status == SCI_SUCCESS) { - scic_sds_port_deactivate_phy(port, phy, true); - - port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; - - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); - } - - return status; -} - -/* - * **************************************************************************** - * * READY SUBSTATE WAITING HANDLERS - * **************************************************************************** */ - -/** - * - * @sci_port: This is the struct scic_sds_port object that which has a phy that has - * gone link up. - * @sci_phy: This is the struct scic_sds_phy object that has gone link up. - * - * This method is the ready waiting substate link up handler for the - * struct scic_sds_port object. This methos will report the link up condition for - * this port and will transition to the ready operational substate. none - */ -static void scic_sds_port_ready_waiting_substate_link_up_handler( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - /* - * Since this is the first phy going link up for the port we can just enable - * it and continue. */ - scic_sds_port_activate_phy(sci_port, sci_phy, true); - - sci_base_state_machine_change_state( - &sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL - ); -} - -/* - * This method is the ready waiting substate start io handler for the - * struct scic_sds_port object. The port object can not accept new requests so the - * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - return SCI_FAILURE_INVALID_STATE; -} - -/* - * **************************************************************************** - * * READY SUBSTATE OPERATIONAL HANDLERS - * **************************************************************************** */ - -/* - * This method will casue the port to reset. enum sci_status SCI_SUCCESS - */ -static enum -sci_status scic_sds_port_ready_operational_substate_reset_handler( - struct scic_sds_port *port, - u32 timeout) -{ - enum sci_status status = SCI_FAILURE_INVALID_PHY; - u32 phy_index; - struct scic_sds_phy *selected_phy = NULL; - - - /* Select a phy on which we can send the hard reset request. */ - for (phy_index = 0; - (phy_index < SCI_MAX_PHYS) && (selected_phy == NULL); - phy_index++) { - selected_phy = port->phy_table[phy_index]; - - if ((selected_phy != NULL) && - !scic_sds_port_active_phy(port, selected_phy)) { - /* - * We found a phy but it is not ready select - * different phy - */ - selected_phy = NULL; - } - } - - /* If we have a phy then go ahead and start the reset procedure */ - if (selected_phy != NULL) { - status = scic_sds_phy_reset(selected_phy); - - if (status == SCI_SUCCESS) { - isci_timer_start(port->timer_handle, timeout); - port->not_ready_reason = - SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; - - sci_base_state_machine_change_state( - &port->state_machine, - SCI_BASE_PORT_STATE_RESETTING); - } - } - - return status; -} - -/** - * scic_sds_port_ready_operational_substate_link_up_handler() - - * @sci_port: This is the struct scic_sds_port object that which has a phy that has - * gone link up. - * @sci_phy: This is the struct scic_sds_phy object that has gone link up. - * - * This method is the ready operational substate link up handler for the - * struct scic_sds_port object. This function notifies the SCI User that the phy has - * gone link up. none - */ -static void scic_sds_port_ready_operational_substate_link_up_handler( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); -} - -/** - * scic_sds_port_ready_operational_substate_link_down_handler() - - * @sci_port: This is the struct scic_sds_port object that which has a phy that has - * gone link down. - * @sci_phy: This is the struct scic_sds_phy object that has gone link down. - * - * This method is the ready operational substate link down handler for the - * struct scic_sds_port object. This function notifies the SCI User that the phy has - * gone link down and if this is the last phy in the port the port will change - * state to the ready waiting substate. none - */ -static void scic_sds_port_ready_operational_substate_link_down_handler( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - scic_sds_port_deactivate_phy(sci_port, sci_phy, true); - - /* - * If there are no active phys left in the port, then transition - * the port to the WAITING state until such time as a phy goes - * link up. */ - if (sci_port->active_phy_mask == 0) - sci_base_state_machine_change_state(&sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); -} - -/* - * This method is the ready operational substate start io handler for the - * struct scic_sds_port object. This function incremetns the outstanding request - * count for this port object. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - port->started_request_count++; - return SCI_SUCCESS; -} - -/* - * **************************************************************************** - * * READY SUBSTATE OPERATIONAL HANDLERS - * **************************************************************************** */ - -/* - * This is the default method for a port add phy request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - enum sci_status status; - - status = scic_sds_port_set_phy(port, phy); - - if (status == SCI_SUCCESS) { - scic_sds_port_general_link_up_handler(port, phy, true); - - /* - * Re-enter the configuring state since this may be the last phy in - * the port. */ - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); - } - - return status; -} - -/* - * This is the default method for a port remove phy request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - enum sci_status status; - - status = scic_sds_port_clear_phy(port, phy); - - if (status == SCI_SUCCESS) { - scic_sds_port_deactivate_phy(port, phy, true); - - /* - * Re-enter the configuring state since this may be the last phy in - * the port. */ - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); - } - - return status; -} - -/** - * scic_sds_port_ready_configuring_substate_complete_io_handler() - - * @port: This is the port that is being requested to complete the io request. - * @device: This is the device on which the io is completing. - * - * This method will decrement the outstanding request count for this port. If - * the request count goes to 0 then the port can be reprogrammed with its new - * phy data. - */ -static enum sci_status -scic_sds_port_ready_configuring_substate_complete_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - scic_sds_port_decrement_request_count(port); - - if (port->started_request_count == 0) { - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL - ); - } - - return SCI_SUCCESS; -} - -static enum sci_status default_port_handler(struct scic_sds_port *sci_port, - const char *func) -{ - dev_warn(sciport_to_dev(sci_port), - "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&sci_port->state_machine)); - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status -scic_sds_port_default_start_handler(struct scic_sds_port *sci_port) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status -scic_sds_port_default_stop_handler(struct scic_sds_port *sci_port) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status -scic_sds_port_default_destruct_handler(struct scic_sds_port *sci_port) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status -scic_sds_port_default_reset_handler(struct scic_sds_port *sci_port, - u32 timeout) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status -scic_sds_port_default_add_phy_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *base_phy) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status -scic_sds_port_default_remove_phy_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *base_phy) -{ - return default_port_handler(sci_port, __func__); -} - -/* - * This is the default method for a port unsolicited frame request. It will - * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even - * possible to receive an unsolicited frame directed to a port object? It - * seems possible if we implementing virtual functions but until then? - */ -static enum sci_status -scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port, - u32 frame_index) -{ - struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - - default_port_handler(sci_port, __func__); - scic_sds_controller_release_frame(scic, frame_index); - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_port_default_event_handler(struct scic_sds_port *sci_port, - u32 event_code) -{ - return default_port_handler(sci_port, __func__); -} - -static void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - default_port_handler(sci_port, __func__); -} - -static void scic_sds_port_default_link_down_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - default_port_handler(sci_port, __func__); -} - -static enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return default_port_handler(sci_port, __func__); -} - - - -static struct scic_sds_port_state_handler -scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = { - { - /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */ - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_ready_substate_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_ready_waiting_substate_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_ready_waiting_substate_start_io_handler, - scic_sds_port_ready_substate_complete_io_handler, - }, - - { - /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */ - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_ready_operational_substate_reset_handler, - scic_sds_port_ready_substate_add_phy_handler, - scic_sds_port_ready_substate_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_ready_operational_substate_link_up_handler, - scic_sds_port_ready_operational_substate_link_down_handler, - scic_sds_port_ready_operational_substate_start_io_handler, - scic_sds_port_ready_substate_complete_io_handler, - }, - - { - /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */ - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_ready_configuring_substate_add_phy_handler, - scic_sds_port_ready_configuring_substate_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_ready_configuring_substate_complete_io_handler - } -}; - -/** - * scic_sds_port_set_ready_state_handlers() - - * - * This macro sets the port ready substate handlers. - */ -#define scic_sds_port_set_ready_state_handlers(port, state_id) \ - scic_sds_port_set_state_handlers(\ - port, &scic_sds_port_ready_substate_handler_table[(state_id)] \ - ) - -/* - * ****************************************************************************** - * * PORT STATE PRIVATE METHODS - * ****************************************************************************** */ - -/** - * - * @sci_port: This is the struct scic_sds_port object to suspend. - * - * This method will susped the port task scheduler for this port object. none - */ -static void -scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port) -{ - u32 pts_control_value; - - pts_control_value = readl(&port->port_task_scheduler_registers->control); - pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND); - writel(pts_control_value, &port->port_task_scheduler_registers->control); -} - -/** - * scic_sds_port_post_dummy_request() - post dummy/workaround request - * @sci_port: port to post task - * - * Prevent the hardware scheduler from posting new requests to the front - * of the scheduler queue causing a starvation problem for currently - * ongoing requests. - * - */ -static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) -{ - u32 command; - struct scu_task_context *task_context; - struct scic_sds_controller *scic = sci_port->owning_controller; - u16 tci = sci_port->reserved_tci; - - task_context = scic_sds_controller_get_task_context_buffer(scic, tci); - - task_context->abort = 0; - - command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | - tci; - - scic_sds_controller_post_request(scic, command); -} - -/** - * This routine will abort the dummy request. This will alow the hardware to - * power down parts of the silicon to save power. - * - * @sci_port: The port on which the task must be aborted. - * - */ -static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - u16 tci = sci_port->reserved_tci; - struct scu_task_context *tc; - u32 command; - - tc = scic_sds_controller_get_task_context_buffer(scic, tci); - - tc->abort = 1; - - command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT | - sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | - tci; - - scic_sds_controller_post_request(scic, command); -} - -/** - * - * @sci_port: This is the struct scic_sds_port object to resume. - * - * This method will resume the port task scheduler for this port object. none - */ -static void -scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) -{ - u32 pts_control_value; - - pts_control_value = readl(&port->port_task_scheduler_registers->control); - pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND); - writel(pts_control_value, &port->port_task_scheduler_registers->control); -} - -/* - * ****************************************************************************** - * * PORT READY SUBSTATE METHODS - * ****************************************************************************** */ - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the - * port for any ready phys. If there is at least one phy in a ready state then - * the port transitions to the ready operational substate. none - */ -static void scic_sds_port_ready_substate_waiting_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - - scic_sds_port_set_ready_state_handlers( - sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING - ); - - scic_sds_port_suspend_port_task_scheduler(sci_port); - - sci_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; - - if (sci_port->active_phy_mask != 0) { - /* At least one of the phys on the port is ready */ - sci_base_state_machine_change_state( - &sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL - ); - } -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This function will perform the actions required by the struct scic_sds_port - * on entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets - * the state handlers for the port object, notifies the SCI User that the port - * is ready, and resumes port operations. none - */ -static void scic_sds_port_ready_substate_operational_enter(void *object) -{ - u32 index; - struct scic_sds_port *sci_port = object; - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port_to_iport(sci_port); - - scic_sds_port_set_ready_state_handlers( - sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); - - isci_port_ready(ihost, iport); - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index]) { - writel(sci_port->physical_port_index, - &sci_port->port_pe_configuration_register[ - sci_port->phy_table[index]->phy_index]); - } - } - - scic_sds_port_update_viit_entry(sci_port); - - scic_sds_port_resume_port_task_scheduler(sci_port); - - /* - * Post the dummy task for the port so the hardware can schedule - * io correctly - */ - scic_sds_port_post_dummy_request(sci_port); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports - * the port not ready and suspends the port task scheduler. none - */ -static void scic_sds_port_ready_substate_operational_exit(void *object) -{ - struct scic_sds_port *sci_port = object; - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port_to_iport(sci_port); - - /* - * Kill the dummy task for this port if it has not yet posted - * the hardware will treat this as a NOP and just return abort - * complete. - */ - scic_sds_port_abort_dummy_request(sci_port); - - isci_port_not_ready(ihost, iport); -} - -/* - * ****************************************************************************** - * * PORT READY CONFIGURING METHODS - * ****************************************************************************** */ - -/** - * scic_sds_port_ready_substate_configuring_enter() - - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports - * the port not ready and suspends the port task scheduler. none - */ -static void scic_sds_port_ready_substate_configuring_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port_to_iport(sci_port); - - scic_sds_port_set_ready_state_handlers( - sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); - - if (sci_port->active_phy_mask == 0) { - isci_port_not_ready(ihost, iport); - - sci_base_state_machine_change_state( - &sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); - } else if (sci_port->started_request_count == 0) - sci_base_state_machine_change_state( - &sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); -} - -static void scic_sds_port_ready_substate_configuring_exit(void *object) -{ - struct scic_sds_port *sci_port = object; - - scic_sds_port_suspend_port_task_scheduler(sci_port); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_port_ready_substate_table[] = { - [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .enter_state = scic_sds_port_ready_substate_waiting_enter, - }, - [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .enter_state = scic_sds_port_ready_substate_operational_enter, - .exit_state = scic_sds_port_ready_substate_operational_exit - }, - [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .enter_state = scic_sds_port_ready_substate_configuring_enter, - .exit_state = scic_sds_port_ready_substate_configuring_exit - }, -}; - -/** - * - * @port: This is the struct scic_sds_port object on which the io request count will - * be decremented. - * @device: This is the struct scic_sds_remote_device object to which the io request - * is being directed. This parameter is not required to complete this - * operation. - * @io_request: This is the request that is being completed on this port - * object. This parameter is not required to complete this operation. - * - * This is a general complete io request handler for the struct scic_sds_port object. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_general_complete_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - scic_sds_port_decrement_request_count(port); - - return SCI_SUCCESS; -} - -/** - * scic_sds_port_stopped_state_start_handler() - stop a port from "started" - * - * @port: This is the struct scic_sds_port object which is cast into a - * struct scic_sds_port object. - * - * This function takes the struct scic_sds_port from a stopped state and - * attempts to start it. To start a port it must have no assiged devices and - * it must have at least one phy assigned to it. If those conditions are - * met then the port can transition to the ready state. - * enum sci_status - * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION - * This struct scic_sds_port object could not be started because the port - * configuration is not valid. - * SCI_SUCCESS - * the start request is successful and the struct scic_sds_port object - * has transitioned to the SCI_BASE_PORT_STATE_READY. - */ -static enum sci_status -scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - enum sci_status status = SCI_SUCCESS; - u32 phy_mask; - - if (sci_port->assigned_device_count > 0) { - /* - * @todo This is a start failure operation because - * there are still devices assigned to this port. - * There must be no devices assigned to a port on a - * start operation. - */ - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - - sci_port->timer_handle = - isci_timer_create(ihost, - sci_port, - scic_sds_port_timeout_handler); - - if (!sci_port->timer_handle) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - - if (sci_port->reserved_rni == SCU_DUMMY_INDEX) { - u16 rni = scic_sds_remote_node_table_allocate_remote_node( - &scic->available_remote_nodes, 1); - - if (rni != SCU_DUMMY_INDEX) - scic_sds_port_construct_dummy_rnc(sci_port, rni); - else - status = SCI_FAILURE_INSUFFICIENT_RESOURCES; - sci_port->reserved_rni = rni; - } - - if (sci_port->reserved_tci == SCU_DUMMY_INDEX) { - /* Allocate a TCI and remove the sequence nibble */ - u16 tci = scic_controller_allocate_io_tag(scic); - - if (tci != SCU_DUMMY_INDEX) - scic_sds_port_construct_dummy_task(sci_port, tci); - else - status = SCI_FAILURE_INSUFFICIENT_RESOURCES; - sci_port->reserved_tci = tci; - } - - if (status == SCI_SUCCESS) { - phy_mask = scic_sds_port_get_phys(sci_port); - - /* - * There are one or more phys assigned to this port. Make sure - * the port's phy mask is in fact legal and supported by the - * silicon. - */ - if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { - sci_base_state_machine_change_state( - &sci_port->state_machine, - SCI_BASE_PORT_STATE_READY); - - return SCI_SUCCESS; - } else - status = SCI_FAILURE; - } - - if (status != SCI_SUCCESS) - scic_sds_port_destroy_dummy_resources(sci_port); - - return status; -} - -/* - * This method takes the struct scic_sds_port that is in a stopped state and handles a - * stop request. This function takes no action. enum sci_status SCI_SUCCESS the - * stop request is successful as the struct scic_sds_port object is already stopped. - */ -static enum sci_status scic_sds_port_stopped_state_stop_handler( - struct scic_sds_port *port) -{ - /* We are already stopped so there is nothing to do here */ - return SCI_SUCCESS; -} - -/* - * This method takes the struct scic_sds_port that is in a stopped state and handles - * the destruct request. The stopped state is the only state in which the - * struct scic_sds_port can be destroyed. This function causes the port object to - * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_stopped_state_destruct_handler( - struct scic_sds_port *port) -{ - sci_base_state_machine_stop(&port->state_machine); - - return SCI_SUCCESS; -} - -/* - * This method takes the struct scic_sds_port that is in a stopped state and handles - * the add phy request. In MPC mode the only time a phy can be added to a port - * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status - * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not - * be added to the port. SCI_SUCCESS if the phy is added to the port. - */ -static enum sci_status scic_sds_port_stopped_state_add_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - struct sci_sas_address port_sas_address; - - /* Read the port assigned SAS Address if there is one */ - scic_sds_port_get_sas_address(port, &port_sas_address); - - if (port_sas_address.high != 0 && port_sas_address.low != 0) { - struct sci_sas_address phy_sas_address; - - /* - * Make sure that the PHY SAS Address matches the SAS Address - * for this port. */ - scic_sds_phy_get_sas_address(phy, &phy_sas_address); - - if ( - (port_sas_address.high != phy_sas_address.high) - || (port_sas_address.low != phy_sas_address.low) - ) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - } - - return scic_sds_port_set_phy(port, phy); -} - -/* - * This method takes the struct scic_sds_port that is in a stopped state and handles - * the remove phy request. In MPC mode the only time a phy can be removed from - * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status - * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not - * be added to the port. SCI_SUCCESS if the phy is added to the port. - */ -static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - return scic_sds_port_clear_phy(port, phy); -} - -/* - * **************************************************************************** - * * READY STATE HANDLERS - * **************************************************************************** */ - -/* - * **************************************************************************** - * * RESETTING STATE HANDLERS - * **************************************************************************** */ - -/* - * **************************************************************************** - * * STOPPING STATE HANDLERS - * **************************************************************************** */ - -/* - * This method takes the struct scic_sds_port that is in a stopping state and handles - * the complete io request. Should the request count reach 0 then the port - * object will transition to the stopped state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_stopping_state_complete_io_handler( - struct scic_sds_port *sci_port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - scic_sds_port_decrement_request_count(sci_port); - - if (sci_port->started_request_count == 0) { - sci_base_state_machine_change_state(&sci_port->state_machine, - SCI_BASE_PORT_STATE_STOPPED); - } - - return SCI_SUCCESS; -} - -/* - * **************************************************************************** - * * RESETTING STATE HANDLERS - * **************************************************************************** */ - -/** - * - * @port: This is the port object which is being requested to stop. - * - * This method will stop a failed port. This causes a transition to the - * stopping state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_reset_state_stop_handler( - struct scic_sds_port *port) -{ - sci_base_state_machine_change_state( - &port->state_machine, - SCI_BASE_PORT_STATE_STOPPING - ); - - return SCI_SUCCESS; -} - -/* - * This method will transition a failed port to its ready state. The port - * failed because a hard reset request timed out but at some time later one or - * more phys in the port became ready. enum sci_status SCI_SUCCESS - */ -static void scic_sds_port_reset_state_link_up_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - /* - * / @todo We should make sure that the phy that has gone link up is the same - * / one on which we sent the reset. It is possible that the phy on - * / which we sent the reset is not the one that has gone link up and we - * / want to make sure that phy being reset comes back. Consider the - * / case where a reset is sent but before the hardware processes the - * / reset it get a link up on the port because of a hot plug event. - * / because of the reset request this phy will go link down almost - * / immediately. */ - - /* - * In the resetting state we don't notify the user regarding - * link up and link down notifications. */ - scic_sds_port_general_link_up_handler(port, phy, false); -} - -/* - * This method process link down notifications that occur during a port reset - * operation. Link downs can occur during the reset operation. enum sci_status - * SCI_SUCCESS - */ -static void scic_sds_port_reset_state_link_down_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - /* - * In the resetting state we don't notify the user regarding - * link up and link down notifications. */ - scic_sds_port_deactivate_phy(port, phy, false); -} - -static struct scic_sds_port_state_handler -scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = -{ - /* SCI_BASE_PORT_STATE_STOPPED */ - { - scic_sds_port_stopped_state_start_handler, - scic_sds_port_stopped_state_stop_handler, - scic_sds_port_stopped_state_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_stopped_state_add_phy_handler, - scic_sds_port_stopped_state_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_default_complete_io_handler - }, - /* SCI_BASE_PORT_STATE_STOPPING */ - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_stopping_state_complete_io_handler - }, - /* SCI_BASE_PORT_STATE_READY */ - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_general_complete_io_handler - }, - /* SCI_BASE_PORT_STATE_RESETTING */ - { - scic_sds_port_default_start_handler, - scic_sds_port_reset_state_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_reset_state_link_up_handler, - scic_sds_port_reset_state_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_general_complete_io_handler - }, - /* SCI_BASE_PORT_STATE_FAILED */ - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_general_complete_io_handler - } -}; - -/* - * ****************************************************************************** - * * PORT STATE PRIVATE METHODS - * ****************************************************************************** */ - -/** - * - * @sci_port: This is the port object which to suspend. - * - * This method will enable the SCU Port Task Scheduler for this port object but - * will leave the port task scheduler in a suspended state. none - */ -static void -scic_sds_port_enable_port_task_scheduler(struct scic_sds_port *port) -{ - u32 pts_control_value; - - pts_control_value = readl(&port->port_task_scheduler_registers->control); - pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND); - writel(pts_control_value, &port->port_task_scheduler_registers->control); -} - -/** - * - * @sci_port: This is the port object which to resume. - * - * This method will disable the SCU port task scheduler for this port object. - * none - */ -static void -scic_sds_port_disable_port_task_scheduler(struct scic_sds_port *port) -{ - u32 pts_control_value; - - pts_control_value = readl(&port->port_task_scheduler_registers->control); - pts_control_value &= - ~(SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND)); - writel(pts_control_value, &port->port_task_scheduler_registers->control); -} - -static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - u8 phys_index = sci_port->physical_port_index; - union scu_remote_node_context *rnc; - u16 rni = sci_port->reserved_rni; - u32 command; - - rnc = &scic->remote_node_context_table[rni]; - rnc->ssp.is_valid = true; - - command = SCU_CONTEXT_COMMAND_POST_RNC_32 | - phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - - scic_sds_controller_post_request(scic, command); - - /* ensure hardware has seen the post rnc command and give it - * ample time to act before sending the suspend - */ - readl(&scic->smu_registers->interrupt_status); /* flush */ - udelay(10); - - command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX | - phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - - scic_sds_controller_post_request(scic, command); -} - -static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - u8 phys_index = sci_port->physical_port_index; - union scu_remote_node_context *rnc; - u16 rni = sci_port->reserved_rni; - u32 command; - - rnc = &scic->remote_node_context_table[rni]; - - rnc->ssp.is_valid = false; - - /* ensure the preceding tc abort request has reached the - * controller and give it ample time to act before posting the rnc - * invalidate - */ - readl(&scic->smu_registers->interrupt_status); /* flush */ - udelay(10); - - command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | - phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - - scic_sds_controller_post_request(scic, command); -} - -/* - * ****************************************************************************** - * * PORT STATE METHODS - * ****************************************************************************** */ - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped - * state handlers for the struct scic_sds_port object and disables the port task - * scheduler in the hardware. none - */ -static void scic_sds_port_stopped_state_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - - scic_sds_port_set_base_state_handlers( - sci_port, SCI_BASE_PORT_STATE_STOPPED - ); - - if ( - SCI_BASE_PORT_STATE_STOPPING - == sci_port->state_machine.previous_state_id - ) { - /* - * If we enter this state becasuse of a request to stop - * the port then we want to disable the hardwares port - * task scheduler. */ - scic_sds_port_disable_port_task_scheduler(sci_port); - } -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware - * port task scheduler. none - */ -static void scic_sds_port_stopped_state_exit(void *object) -{ - struct scic_sds_port *sci_port = object; - - /* Enable and suspend the port task scheduler */ - scic_sds_port_enable_port_task_scheduler(sci_port); -} - -/** - * scic_sds_port_ready_state_enter - - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state - * handlers for the struct scic_sds_port object, reports the port object as - * not ready and starts the ready substate machine. none - */ -static void scic_sds_port_ready_state_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port_to_iport(sci_port); - u32 prev_state; - - /* Put the ready state handlers in place though they will not be there long */ - scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_READY); - - prev_state = sci_port->state_machine.previous_state_id; - if (prev_state == SCI_BASE_PORT_STATE_RESETTING) - isci_port_hard_reset_complete(iport, SCI_SUCCESS); - else - isci_port_not_ready(ihost, iport); - - /* Post and suspend the dummy remote node context for this port. */ - scic_sds_port_post_dummy_remote_node(sci_port); - - /* Start the ready substate machine */ - sci_base_state_machine_start(&sci_port->ready_substate_machine); -} - -static void scic_sds_port_ready_state_exit(void *object) -{ - struct scic_sds_port *sci_port = object; - - sci_base_state_machine_stop(&sci_port->ready_substate_machine); - scic_sds_port_invalidate_dummy_remote_node(sci_port); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting - * state handlers for the struct scic_sds_port object. none - */ -static void scic_sds_port_resetting_state_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - - scic_sds_port_set_base_state_handlers( - sci_port, SCI_BASE_PORT_STATE_RESETTING - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This function will perform the actions required by the - * struct scic_sds_port on - * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none - */ -static inline void scic_sds_port_resetting_state_exit(void *object) -{ - struct scic_sds_port *sci_port = object; - - isci_timer_stop(sci_port->timer_handle); -} - -/** - * - * @object: This is the void object which is cast to a - * struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping - * state handlers for the struct scic_sds_port object. none - */ -static void scic_sds_port_stopping_state_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - - scic_sds_port_set_base_state_handlers( - sci_port, SCI_BASE_PORT_STATE_STOPPING - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This function will perform the actions required by the - * struct scic_sds_port on - * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none - */ -static inline void -scic_sds_port_stopping_state_exit(void *object) -{ - struct scic_sds_port *sci_port = object; - - isci_timer_stop(sci_port->timer_handle); - - scic_sds_port_destroy_dummy_resources(sci_port); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This function will perform the actions required by the - * struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping - * state handlers for the struct scic_sds_port object. none - */ -static void scic_sds_port_failed_state_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - struct isci_port *iport = sci_port_to_iport(sci_port); - - scic_sds_port_set_base_state_handlers(sci_port, - SCI_BASE_PORT_STATE_FAILED); - - isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_port_state_table[] = { - [SCI_BASE_PORT_STATE_STOPPED] = { - .enter_state = scic_sds_port_stopped_state_enter, - .exit_state = scic_sds_port_stopped_state_exit - }, - [SCI_BASE_PORT_STATE_STOPPING] = { - .enter_state = scic_sds_port_stopping_state_enter, - .exit_state = scic_sds_port_stopping_state_exit - }, - [SCI_BASE_PORT_STATE_READY] = { - .enter_state = scic_sds_port_ready_state_enter, - .exit_state = scic_sds_port_ready_state_exit - }, - [SCI_BASE_PORT_STATE_RESETTING] = { - .enter_state = scic_sds_port_resetting_state_enter, - .exit_state = scic_sds_port_resetting_state_exit - }, - [SCI_BASE_PORT_STATE_FAILED] = { - .enter_state = scic_sds_port_failed_state_enter, - } -}; - -void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, - struct scic_sds_controller *scic) -{ - sci_base_state_machine_construct(&sci_port->state_machine, - sci_port, - scic_sds_port_state_table, - SCI_BASE_PORT_STATE_STOPPED); - - sci_base_state_machine_start(&sci_port->state_machine); - - sci_base_state_machine_construct(&sci_port->ready_substate_machine, - sci_port, - scic_sds_port_ready_substate_table, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); - - sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; - sci_port->physical_port_index = index; - sci_port->active_phy_mask = 0; - - sci_port->owning_controller = scic; - - sci_port->started_request_count = 0; - sci_port->assigned_device_count = 0; - - sci_port->reserved_rni = SCU_DUMMY_INDEX; - sci_port->reserved_tci = SCU_DUMMY_INDEX; - - sci_port->timer_handle = NULL; - sci_port->port_task_scheduler_registers = NULL; - - for (index = 0; index < SCI_MAX_PHYS; index++) - sci_port->phy_table[index] = NULL; -} diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h deleted file mode 100644 index a351525b1c49..000000000000 --- a/drivers/scsi/isci/core/scic_sds_port.h +++ /dev/null @@ -1,435 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_PORT_H_ -#define _SCIC_SDS_PORT_H_ - -#include -#include "isci.h" -#include "sas.h" -#include "registers.h" -#include "state_machine.h" - -struct scic_sds_controller; -struct scic_sds_phy; -struct scic_sds_remote_device; -struct scic_sds_request; - -#define SCIC_SDS_DUMMY_PORT 0xFF - -/** - * enum SCIC_SDS_PORT_READY_SUBSTATES - - * - * This enumeration depicts all of the states for the core port ready substate - * machine. - */ -enum scic_sds_port_ready_substates { - /** - * The substate where the port is started and ready but has no - * active phys. - */ - SCIC_SDS_PORT_READY_SUBSTATE_WAITING, - - /** - * The substate where the port is started and ready and there is - * at least one phy operational. - */ - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, - - /** - * The substate where the port is started and there was an - * add/remove phy event. This state is only used in Automatic - * Port Configuration Mode (APC) - */ - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, - - SCIC_SDS_PORT_READY_MAX_SUBSTATES -}; - -/** - * enum scic_sds_port_states - This enumeration depicts all the states for the - * common port state machine. - * - * - */ -enum scic_sds_port_states { - /** - * This state indicates that the port has successfully been stopped. - * In this state no new IO operations are permitted. - * This state is entered from the STOPPING state. - */ - SCI_BASE_PORT_STATE_STOPPED, - - /** - * This state indicates that the port is in the process of stopping. - * In this state no new IO operations are permitted, but existing IO - * operations are allowed to complete. - * This state is entered from the READY state. - */ - SCI_BASE_PORT_STATE_STOPPING, - - /** - * This state indicates the port is now ready. Thus, the user is - * able to perform IO operations on this port. - * This state is entered from the STARTING state. - */ - SCI_BASE_PORT_STATE_READY, - - /** - * This state indicates the port is in the process of performing a hard - * reset. Thus, the user is unable to perform IO operations on this - * port. - * This state is entered from the READY state. - */ - SCI_BASE_PORT_STATE_RESETTING, - - /** - * This state indicates the port has failed a reset request. This state - * is entered when a port reset request times out. - * This state is entered from the RESETTING state. - */ - SCI_BASE_PORT_STATE_FAILED, - - SCI_BASE_PORT_MAX_STATES - -}; - -/** - * struct scic_sds_port - * - * The core port object provides the the abstraction for an SCU port. - */ -struct scic_sds_port { - - /** - * This field contains the information for the base port state machine. - */ - struct sci_base_state_machine state_machine; - - /** - * This field is the port index that is reported to the SCI USER. - * This allows the actual hardware physical port to change without - * the SCI USER getting a different answer for the get port index. - */ - u8 logical_port_index; - - /** - * This field is the port index used to program the SCU hardware. - */ - u8 physical_port_index; - - /** - * This field contains the active phy mask for the port. - * This mask is used in conjunction with the phy state to determine - * which phy to select for some port operations. - */ - u8 active_phy_mask; - - u16 reserved_rni; - u16 reserved_tci; - - /** - * This field contains the count of the io requests started on this port - * object. It is used to control controller shutdown. - */ - u32 started_request_count; - - /** - * This field contains the number of devices assigned to this port. - * It is used to control port start requests. - */ - u32 assigned_device_count; - - /** - * This field contains the reason for the port not going ready. It is - * assigned in the state handlers and used in the state transition. - */ - u32 not_ready_reason; - - /** - * This field is the table of phys assigned to the port. - */ - struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; - - /** - * This field is a pointer back to the controller that owns this - * port object. - */ - struct scic_sds_controller *owning_controller; - - /** - * This field contains the port start/stop timer handle. - */ - void *timer_handle; - - /** - * This field points to the current set of state handlers for this port - * object. These state handlers are assigned at each enter state of - * the state machine. - */ - struct scic_sds_port_state_handler *state_handlers; - - /** - * This field is the ready substate machine for the port. - */ - struct sci_base_state_machine ready_substate_machine; - - /* / Memory mapped hardware register space */ - - /** - * This field is the pointer to the port task scheduler registers - * for the SCU hardware. - */ - struct scu_port_task_scheduler_registers __iomem - *port_task_scheduler_registers; - - /** - * This field is identical for all port objects and points to the port - * task scheduler group PE configuration registers. - * It is used to assign PEs to a port. - */ - u32 __iomem *port_pe_configuration_register; - - /** - * This field is the VIIT register space for ths port object. - */ - struct scu_viit_entry __iomem *viit_registers; - -}; - -typedef enum sci_status (*scic_sds_port_handler_t)(struct scic_sds_port *); - -typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *, - struct scic_sds_phy *); - -typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *, - u32 timeout); - -typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32); - -typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, u32); - -typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *); - -typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_port *, - struct scic_sds_remote_device *, - struct scic_sds_request *); - -struct scic_sds_port_state_handler { - /** - * The start_handler specifies the method invoked when a user - * attempts to start a port. - */ - scic_sds_port_handler_t start_handler; - - /** - * The stop_handler specifies the method invoked when a user - * attempts to stop a port. - */ - scic_sds_port_handler_t stop_handler; - - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a port. - */ - scic_sds_port_handler_t destruct_handler; - - /** - * The reset_handler specifies the method invoked when a user - * attempts to hard reset a port. - */ - scic_sds_port_reset_handler_t reset_handler; - - /** - * The add_phy_handler specifies the method invoked when a user - * attempts to add another phy into the port. - */ - scic_sds_port_phy_handler_t add_phy_handler; - - /** - * The remove_phy_handler specifies the method invoked when a user - * attempts to remove a phy from the port. - */ - scic_sds_port_phy_handler_t remove_phy_handler; - - scic_sds_port_frame_handler_t frame_handler; - scic_sds_port_event_handler_t event_handler; - - scic_sds_port_link_handler_t link_up_handler; - scic_sds_port_link_handler_t link_down_handler; - - scic_sds_port_io_request_handler_t start_io_handler; - scic_sds_port_io_request_handler_t complete_io_handler; - -}; - -/** - * scic_sds_port_get_controller() - - * - * Helper macro to get the owning controller of this port - */ -#define scic_sds_port_get_controller(this_port) \ - ((this_port)->owning_controller) - -/** - * scic_sds_port_set_base_state_handlers() - - * - * This macro will change the state handlers to those of the specified state id - */ -#define scic_sds_port_set_base_state_handlers(this_port, state_id) \ - scic_sds_port_set_state_handlers(\ - (this_port), &scic_sds_port_state_handler_table[(state_id)]) - -/** - * scic_sds_port_set_state_handlers() - - * - * Helper macro to set the port object state handlers - */ -#define scic_sds_port_set_state_handlers(this_port, handlers) \ - ((this_port)->state_handlers = (handlers)) - -/** - * scic_sds_port_get_index() - - * - * This macro returns the physical port index for this port object - */ -#define scic_sds_port_get_index(this_port) \ - ((this_port)->physical_port_index) - - -static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) -{ - if (WARN_ONCE(sci_port->started_request_count == 0, - "%s: tried to decrement started_request_count past 0!?", - __func__)) - /* pass */; - else - sci_port->started_request_count--; -} - -#define scic_sds_port_active_phy(port, phy) \ - (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) - -void scic_sds_port_construct( - struct scic_sds_port *sci_port, - u8 port_index, - struct scic_sds_controller *scic); - -enum sci_status scic_sds_port_initialize( - struct scic_sds_port *sci_port, - void __iomem *port_task_scheduler_registers, - void __iomem *port_configuration_regsiter, - void __iomem *viit_registers); - -enum sci_status scic_sds_port_add_phy( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -enum sci_status scic_sds_port_remove_phy( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -void scic_sds_port_setup_transports( - struct scic_sds_port *sci_port, - u32 device_id); - - -void scic_sds_port_deactivate_phy( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, - bool do_notify_user); - -bool scic_sds_port_link_detected( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -void scic_sds_port_link_up( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -void scic_sds_port_link_down( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -enum sci_status scic_sds_port_start_io( - struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req); - -enum sci_status scic_sds_port_complete_io( - struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req); - -enum sas_linkrate scic_sds_port_get_max_allowed_speed( - struct scic_sds_port *sci_port); - -void scic_sds_port_broadcast_change_received( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -bool scic_sds_port_is_valid_phy_assignment( - struct scic_sds_port *sci_port, - u32 phy_index); - -void scic_sds_port_get_sas_address( - struct scic_sds_port *sci_port, - struct sci_sas_address *sas_address); - -void scic_sds_port_get_attached_sas_address( - struct scic_sds_port *sci_port, - struct sci_sas_address *sas_address); - -#endif /* _SCIC_SDS_PORT_H_ */ diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c deleted file mode 100644 index a5871fddc09a..000000000000 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "host.h" -#include "scic_sds_port_configuration_agent.h" -#include "timers.h" - -#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) -#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) -#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100) - -enum SCIC_SDS_APC_ACTIVITY { - SCIC_SDS_APC_SKIP_PHY, - SCIC_SDS_APC_ADD_PHY, - SCIC_SDS_APC_START_TIMER, - - SCIC_SDS_APC_ACTIVITY_MAX -}; - -/* - * ****************************************************************************** - * General port configuration agent routines - * ****************************************************************************** */ - -/** - * - * @address_one: A SAS Address to be compared. - * @address_two: A SAS Address to be compared. - * - * Compare the two SAS Address and if SAS Address One is greater than SAS - * Address Two then return > 0 else if SAS Address One is less than SAS Address - * Two return < 0 Otherwise they are the same return 0 A signed value of x > 0 - * > y where x is returned for Address One > Address Two y is returned for - * Address One < Address Two 0 is returned ofr Address One = Address Two - */ -static s32 sci_sas_address_compare( - struct sci_sas_address address_one, - struct sci_sas_address address_two) -{ - if (address_one.high > address_two.high) { - return 1; - } else if (address_one.high < address_two.high) { - return -1; - } else if (address_one.low > address_two.low) { - return 1; - } else if (address_one.low < address_two.low) { - return -1; - } - - /* The two SAS Address must be identical */ - return 0; -} - -/** - * - * @controller: The controller object used for the port search. - * @phy: The phy object to match. - * - * This routine will find a matching port for the phy. This means that the - * port and phy both have the same broadcast sas address and same received sas - * address. The port address or the NULL if there is no matching - * port. port address if the port can be found to match the phy. - * NULL if there is no matching port for the phy. - */ -static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( - struct scic_sds_controller *scic, - struct scic_sds_phy *phy) -{ - u8 i; - struct sci_sas_address port_sas_address; - struct sci_sas_address port_attached_device_address; - struct sci_sas_address phy_sas_address; - struct sci_sas_address phy_attached_device_address; - - /* - * Since this phy can be a member of a wide port check to see if one or - * more phys match the sent and received SAS address as this phy in which - * case it should participate in the same port. - */ - scic_sds_phy_get_sas_address(phy, &phy_sas_address); - scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); - - for (i = 0; i < scic->logical_port_entries; i++) { - struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_port *sci_port = &ihost->ports[i].sci; - - scic_sds_port_get_sas_address(sci_port, &port_sas_address); - scic_sds_port_get_attached_sas_address(sci_port, &port_attached_device_address); - - if (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0 && - sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) - return sci_port; - } - - return NULL; -} - -/** - * - * @controller: This is the controller object that contains the port agent - * @port_agent: This is the port configruation agent for the controller. - * - * This routine will validate the port configuration is correct for the SCU - * hardware. The SCU hardware allows for port configurations as follows. LP0 - * -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2, - * PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for - * this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION - * the port configuration is not valid for this port configuration agent. - */ -static enum sci_status scic_sds_port_configuration_agent_validate_ports( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent) -{ - struct isci_host *ihost = scic_to_ihost(controller); - struct sci_sas_address first_address; - struct sci_sas_address second_address; - - /* - * Sanity check the max ranges for all the phys the max index - * is always equal to the port range index */ - if (port_agent->phy_valid_port_range[0].max_index != 0 || - port_agent->phy_valid_port_range[1].max_index != 1 || - port_agent->phy_valid_port_range[2].max_index != 2 || - port_agent->phy_valid_port_range[3].max_index != 3) - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - - /* - * This is a request to configure a single x4 port or at least attempt - * to make all the phys into a single port */ - if (port_agent->phy_valid_port_range[0].min_index == 0 && - port_agent->phy_valid_port_range[1].min_index == 0 && - port_agent->phy_valid_port_range[2].min_index == 0 && - port_agent->phy_valid_port_range[3].min_index == 0) - return SCI_SUCCESS; - - /* - * This is a degenerate case where phy 1 and phy 2 are assigned - * to the same port this is explicitly disallowed by the hardware - * unless they are part of the same x4 port and this condition was - * already checked above. */ - if (port_agent->phy_valid_port_range[2].min_index == 1) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - - /* - * PE0 and PE3 can never have the same SAS Address unless they - * are part of the same x4 wide port and we have already checked - * for this condition. */ - scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address); - - if (sci_sas_address_compare(first_address, second_address) == 0) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - - /* - * PE0 and PE1 are configured into a 2x1 ports make sure that the - * SAS Address for PE0 and PE2 are different since they can not be - * part of the same port. */ - if (port_agent->phy_valid_port_range[0].min_index == 0 && - port_agent->phy_valid_port_range[1].min_index == 1) { - scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[2].sci, &second_address); - - if (sci_sas_address_compare(first_address, second_address) == 0) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - } - - /* - * PE2 and PE3 are configured into a 2x1 ports make sure that the - * SAS Address for PE1 and PE3 are different since they can not be - * part of the same port. */ - if (port_agent->phy_valid_port_range[2].min_index == 2 && - port_agent->phy_valid_port_range[3].min_index == 3) { - scic_sds_phy_get_sas_address(&ihost->phys[1].sci, &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address); - - if (sci_sas_address_compare(first_address, second_address) == 0) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - } - - return SCI_SUCCESS; -} - -/* - * ****************************************************************************** - * Manual port configuration agent routines - * ****************************************************************************** */ - -/** - * - * - * This routine will verify that all of the phys in the same port are using the - * same SAS address. - */ -static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent) -{ - struct isci_host *ihost = scic_to_ihost(controller); - u32 phy_mask; - u32 assigned_phy_mask; - struct sci_sas_address sas_address; - struct sci_sas_address phy_assigned_address; - u8 port_index; - u8 phy_index; - - assigned_phy_mask = 0; - sas_address.high = 0; - sas_address.low = 0; - - for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { - phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask; - - if (!phy_mask) - continue; - /* - * Make sure that one or more of the phys were not already assinged to - * a different port. */ - if ((phy_mask & ~assigned_phy_mask) == 0) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - - /* Find the starting phy index for this round through the loop */ - for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { - if ((phy_mask & (1 << phy_index)) == 0) - continue; - scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, - &sas_address); - - /* - * The phy_index can be used as the starting point for the - * port range since the hardware starts all logical ports - * the same as the PE index. */ - port_agent->phy_valid_port_range[phy_index].min_index = port_index; - port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - - if (phy_index != port_index) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - - break; - } - - /* - * See how many additional phys are being added to this logical port. - * Note: We have not moved the current phy_index so we will actually - * compare the startting phy with itself. - * This is expected and required to add the phy to the port. */ - while (phy_index < SCI_MAX_PHYS) { - if ((phy_mask & (1 << phy_index)) == 0) - continue; - scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, - &phy_assigned_address); - - if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { - /* - * The phy mask specified that this phy is part of the same port - * as the starting phy and it is not so fail this configuration */ - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - - port_agent->phy_valid_port_range[phy_index].min_index = port_index; - port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - - scic_sds_port_add_phy(&ihost->ports[port_index].sci, - &ihost->phys[phy_index].sci); - - assigned_phy_mask |= (1 << phy_index); - } - - phy_index++; - } - - return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); -} - -/** - * - * - * This timer routine is used to allow the SCI User to rediscover or change - * device objects before a new series of link up notifications because a link - * down has allowed a better port configuration. - */ -static void scic_sds_mpc_agent_timeout_handler(void *object) -{ - u8 index; - struct scic_sds_controller *scic = object; - struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_port_configuration_agent *port_agent = &scic->port_agent; - u16 configure_phy_mask; - - port_agent->timer_pending = false; - - /* Find the mask of phys that are reported read but as yet unconfigured into a port */ - configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - struct scic_sds_phy *sci_phy = &ihost->phys[index].sci; - - if (configure_phy_mask & (1 << index)) { - port_agent->link_up_handler(scic, port_agent, - scic_sds_phy_get_port(sci_phy), - sci_phy); - } - } -} - -/** - * - * @controller: This is the controller object that receives the link up - * notification. - * @port: This is the port object associated with the phy. If the is no - * associated port this is an NULL. - * @phy: This is the phy object which has gone ready. - * - * This method handles the manual port configuration link up notifications. - * Since all ports and phys are associate at initialization time we just turn - * around and notifiy the port object that there is a link up. If this PHY is - * not associated with a port there is no action taken. Is it possible to get a - * link up notification from a phy that has no assocoated port? - */ -static void scic_sds_mpc_agent_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - /* - * If the port has an invalid handle then the phy was not assigned to - * a port. This is because the phy was not given the same SAS Address - * as the other PHYs in the port. */ - if (port != NULL) { - port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); - - scic_sds_port_link_up(port, phy); - - if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0) { - port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy)); - } - } -} - -/** - * - * @controller: This is the controller object that receives the link down - * notification. - * @port: This is the port object associated with the phy. If the is no - * associated port this is an NULL. The port is an invalid - * handle only if the phy was never port of this port. This happens when - * the phy is not broadcasting the same SAS address as the other phys in the - * assigned port. - * @phy: This is the phy object which has gone link down. - * - * This function handles the manual port configuration link down notifications. - * Since all ports and phys are associated at initialization time we just turn - * around and notifiy the port object of the link down event. If this PHY is - * not associated with a port there is no action taken. Is it possible to get a - * link down notification from a phy that has no assocoated port? - */ -static void scic_sds_mpc_agent_link_down( - struct scic_sds_controller *scic, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - if (sci_port != NULL) { - /* - * If we can form a new port from the remainder of the phys - * then we want to start the timer to allow the SCI User to - * cleanup old devices and rediscover the port before - * rebuilding the port with the phys that remain in the ready - * state. - */ - port_agent->phy_ready_mask &= - ~(1 << scic_sds_phy_get_index(sci_phy)); - port_agent->phy_configured_mask &= - ~(1 << scic_sds_phy_get_index(sci_phy)); - - /* - * Check to see if there are more phys waiting to be - * configured into a port. If there are allow the SCI User - * to tear down this port, if necessary, and then reconstruct - * the port after the timeout. - */ - if ((port_agent->phy_configured_mask == 0x0000) && - (port_agent->phy_ready_mask != 0x0000) && - !port_agent->timer_pending) { - port_agent->timer_pending = true; - - isci_timer_start(port_agent->timer, - SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT); - } - - scic_sds_port_link_down(sci_port, sci_phy); - } -} - -/* - * ****************************************************************************** - * Automatic port configuration agent routines - * ****************************************************************************** */ - -/** - * - * - * This routine will verify that the phys are assigned a valid SAS address for - * automatic port configuration mode. - */ -static enum sci_status scic_sds_apc_agent_validate_phy_configuration( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent) -{ - u8 phy_index; - u8 port_index; - struct sci_sas_address sas_address; - struct sci_sas_address phy_assigned_address; - struct isci_host *ihost = scic_to_ihost(controller); - - phy_index = 0; - - while (phy_index < SCI_MAX_PHYS) { - port_index = phy_index; - - /* Get the assigned SAS Address for the first PHY on the controller. */ - scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, - &sas_address); - - while (++phy_index < SCI_MAX_PHYS) { - scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, - &phy_assigned_address); - - /* Verify each of the SAS address are all the same for every PHY */ - if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) { - port_agent->phy_valid_port_range[phy_index].min_index = port_index; - port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - } else { - port_agent->phy_valid_port_range[phy_index].min_index = phy_index; - port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - break; - } - } - } - - return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); -} - -/** - * - * @controller: This is the controller that to which the port agent is assigned. - * @port_agent: This is the port agent that is requesting the timer start - * operation. - * @phy: This is the phy that has caused the timer operation to be scheduled. - * - * This routine will restart the automatic port configuration timeout timer for - * the next time period. This could be caused by either a link down event or a - * link up event where we can not yet tell to which port a phy belongs. - */ -static inline void scic_sds_apc_agent_start_timer( - struct scic_sds_controller *scic, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_phy *sci_phy, - u32 timeout) -{ - if (port_agent->timer_pending) - isci_timer_stop(port_agent->timer); - - port_agent->timer_pending = true; - - isci_timer_start(port_agent->timer, timeout); -} - -/** - * - * @controller: This is the controller object that receives the link up - * notification. - * @phy: This is the phy object which has gone link up. - * - * This method handles the automatic port configuration for link up - * notifications. - */ -static void scic_sds_apc_agent_configure_ports( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_phy *phy, - bool start_timer) -{ - u8 port_index; - enum sci_status status; - struct scic_sds_port *port; - enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; - struct isci_host *ihost = scic_to_ihost(controller); - - port = scic_sds_port_configuration_agent_find_port(controller, phy); - - if (port != NULL) { - if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) - apc_activity = SCIC_SDS_APC_ADD_PHY; - else - apc_activity = SCIC_SDS_APC_SKIP_PHY; - } else { - /* - * There is no matching Port for this PHY so lets search through the - * Ports and see if we can add the PHY to its own port or maybe start - * the timer and wait to see if a wider port can be made. - * - * Note the break when we reach the condition of the port id == phy id */ - for ( - port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index; - port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index; - port_index++ - ) { - - port = &ihost->ports[port_index].sci; - - /* First we must make sure that this PHY can be added to this Port. */ - if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) { - /* - * Port contains a PHY with a greater PHY ID than the current - * PHY that has gone link up. This phy can not be part of any - * port so skip it and move on. */ - if (port->active_phy_mask > (1 << phy->phy_index)) { - apc_activity = SCIC_SDS_APC_SKIP_PHY; - break; - } - - /* - * We have reached the end of our Port list and have not found - * any reason why we should not either add the PHY to the port - * or wait for more phys to become active. */ - if (port->physical_port_index == phy->phy_index) { - /* - * The Port either has no active PHYs. - * Consider that if the port had any active PHYs we would have - * or active PHYs with - * a lower PHY Id than this PHY. */ - if (apc_activity != SCIC_SDS_APC_START_TIMER) { - apc_activity = SCIC_SDS_APC_ADD_PHY; - } - - break; - } - - /* - * The current Port has no active PHYs and this PHY could be part - * of this Port. Since we dont know as yet setup to start the - * timer and see if there is a better configuration. */ - if (port->active_phy_mask == 0) { - apc_activity = SCIC_SDS_APC_START_TIMER; - } - } else if (port->active_phy_mask != 0) { - /* - * The Port has an active phy and the current Phy can not - * participate in this port so skip the PHY and see if - * there is a better configuration. */ - apc_activity = SCIC_SDS_APC_SKIP_PHY; - } - } - } - - /* - * Check to see if the start timer operations should instead map to an - * add phy operation. This is caused because we have been waiting to - * add a phy to a port but could not becuase the automatic port - * configuration engine had a choice of possible ports for the phy. - * Since we have gone through a timeout we are going to restrict the - * choice to the smallest possible port. */ - if ( - (start_timer == false) - && (apc_activity == SCIC_SDS_APC_START_TIMER) - ) { - apc_activity = SCIC_SDS_APC_ADD_PHY; - } - - switch (apc_activity) { - case SCIC_SDS_APC_ADD_PHY: - status = scic_sds_port_add_phy(port, phy); - - if (status == SCI_SUCCESS) { - port_agent->phy_configured_mask |= (1 << phy->phy_index); - } - break; - - case SCIC_SDS_APC_START_TIMER: - scic_sds_apc_agent_start_timer( - controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION - ); - break; - - case SCIC_SDS_APC_SKIP_PHY: - default: - /* do nothing the PHY can not be made part of a port at this time. */ - break; - } -} - -/** - * scic_sds_apc_agent_link_up - handle apc link up events - * @scic: This is the controller object that receives the link up - * notification. - * @sci_port: This is the port object associated with the phy. If the is no - * associated port this is an NULL. - * @sci_phy: This is the phy object which has gone link up. - * - * This method handles the automatic port configuration for link up - * notifications. Is it possible to get a link down notification from a phy - * that has no assocoated port? - */ -static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - u8 phy_index = sci_phy->phy_index; - - if (!sci_port) { - /* the phy is not the part of this port */ - port_agent->phy_ready_mask |= 1 << phy_index; - scic_sds_apc_agent_configure_ports(scic, port_agent, sci_phy, true); - } else { - /* the phy is already the part of the port */ - u32 port_state = sci_port->state_machine.current_state_id; - - /* if the PORT'S state is resetting then the link up is from - * port hard reset in this case, we need to tell the port - * that link up is recieved - */ - BUG_ON(port_state != SCI_BASE_PORT_STATE_RESETTING); - port_agent->phy_ready_mask |= 1 << phy_index; - scic_sds_port_link_up(sci_port, sci_phy); - } -} - -/** - * - * @controller: This is the controller object that receives the link down - * notification. - * @port: This is the port object associated with the phy. If the is no - * associated port this is an NULL. - * @phy: This is the phy object which has gone link down. - * - * This method handles the automatic port configuration link down - * notifications. not associated with a port there is no action taken. Is it - * possible to get a link down notification from a phy that has no assocoated - * port? - */ -static void scic_sds_apc_agent_link_down( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); - - if (port != NULL) { - if (port_agent->phy_configured_mask & (1 << phy->phy_index)) { - enum sci_status status; - - status = scic_sds_port_remove_phy(port, phy); - - if (status == SCI_SUCCESS) { - port_agent->phy_configured_mask &= ~(1 << phy->phy_index); - } - } - } -} - -/* configure the phys into ports when the timer fires */ -static void scic_sds_apc_agent_timeout_handler(void *object) -{ - u32 index; - struct scic_sds_port_configuration_agent *port_agent; - struct scic_sds_controller *scic = object; - struct isci_host *ihost = scic_to_ihost(scic); - u16 configure_phy_mask; - - port_agent = scic_sds_controller_get_port_configuration_agent(scic); - - port_agent->timer_pending = false; - - configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; - - if (!configure_phy_mask) - return; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if ((configure_phy_mask & (1 << index)) == 0) - continue; - - scic_sds_apc_agent_configure_ports(scic, port_agent, - &ihost->phys[index].sci, false); - } -} - -/* - * ****************************************************************************** - * Public port configuration agent routines - * ****************************************************************************** */ - -/** - * - * - * This method will construct the port configuration agent for operation. This - * call is universal for both manual port configuration and automatic port - * configuration modes. - */ -void scic_sds_port_configuration_agent_construct( - struct scic_sds_port_configuration_agent *port_agent) -{ - u32 index; - - port_agent->phy_configured_mask = 0x00; - port_agent->phy_ready_mask = 0x00; - - port_agent->link_up_handler = NULL; - port_agent->link_down_handler = NULL; - - port_agent->timer_pending = false; - port_agent->timer = NULL; - - for (index = 0; index < SCI_MAX_PORTS; index++) { - port_agent->phy_valid_port_range[index].min_index = 0; - port_agent->phy_valid_port_range[index].max_index = 0; - } -} - -enum sci_status scic_sds_port_configuration_agent_initialize( - struct scic_sds_controller *scic, - struct scic_sds_port_configuration_agent *port_agent) -{ - enum sci_status status = SCI_SUCCESS; - enum scic_port_configuration_mode mode; - struct isci_host *ihost = scic_to_ihost(scic); - - mode = scic->oem_parameters.sds1.controller.mode_type; - - if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { - status = scic_sds_mpc_agent_validate_phy_configuration( - scic, port_agent); - - port_agent->link_up_handler = scic_sds_mpc_agent_link_up; - port_agent->link_down_handler = scic_sds_mpc_agent_link_down; - - port_agent->timer = isci_timer_create( - ihost, - scic, - scic_sds_mpc_agent_timeout_handler); - } else { - status = scic_sds_apc_agent_validate_phy_configuration( - scic, port_agent); - - port_agent->link_up_handler = scic_sds_apc_agent_link_up; - port_agent->link_down_handler = scic_sds_apc_agent_link_down; - - port_agent->timer = isci_timer_create( - ihost, - scic, - scic_sds_apc_agent_timeout_handler); - } - - /* Make sure we have actually gotten a timer */ - if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) { - dev_err(scic_to_dev(scic), - "%s: Controller 0x%p automatic port configuration " - "agent could not get timer.\n", - __func__, - scic); - - status = SCI_FAILURE; - } - - return status; -} diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h deleted file mode 100644 index 7fd161700475..000000000000 --- a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ -#define _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ - -/** - * This file contains the structures, constants and prototypes used for the - * core controller automatic port configuration engine. - * - * - */ - -#include "scic_sds_port.h" - -struct scic_sds_controller; -struct scic_sds_port_configuration_agent; -struct scic_sds_port; -struct scic_sds_phy; - -typedef void (*scic_sds_port_configuration_agent_phy_handler_t)( - struct scic_sds_controller *, - struct scic_sds_port_configuration_agent *, - struct scic_sds_port *, - struct scic_sds_phy * - ); - -struct SCIC_SDS_PORT_RANGE { - u8 min_index; - u8 max_index; -}; - -struct scic_sds_port_configuration_agent { - u16 phy_configured_mask; - u16 phy_ready_mask; - - struct SCIC_SDS_PORT_RANGE phy_valid_port_range[SCI_MAX_PHYS]; - - bool timer_pending; - - scic_sds_port_configuration_agent_phy_handler_t link_up_handler; - scic_sds_port_configuration_agent_phy_handler_t link_down_handler; - - void *timer; - -}; - -void scic_sds_port_configuration_agent_construct( - struct scic_sds_port_configuration_agent *port_agent); - -enum sci_status scic_sds_port_configuration_agent_initialize( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent); - -#endif /* _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ */ diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index e1930da08d4e..2bb9f1073e73 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -61,7 +61,6 @@ #include "probe_roms.h" #include "remote_device.h" #include "request.h" -#include "scic_sds_port_configuration_agent.h" #include "scu_completion_codes.h" #include "scu_event_codes.h" #include "registers.h" diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 9c5d121ce791..784e1355e8ec 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -55,7 +55,6 @@ #ifndef _SCI_HOST_H_ #define _SCI_HOST_H_ -#include "scic_config_parameters.h" #include "remote_device.h" #include "phy.h" #include "pool.h" @@ -64,11 +63,12 @@ #include "registers.h" #include "scu_unsolicited_frame.h" #include "unsolicited_frame_control.h" -#include "scic_sds_port_configuration_agent.h" +#include "probe_roms.h" struct scic_sds_request; struct scu_task_context; + /** * struct scic_power_control - * @@ -107,6 +107,24 @@ struct scic_power_control { }; +struct scic_sds_port_configuration_agent; +typedef void (*port_config_fn)(struct scic_sds_controller *, + struct scic_sds_port_configuration_agent *, + struct scic_sds_port *, struct scic_sds_phy *); + +struct scic_sds_port_configuration_agent { + u16 phy_configured_mask; + u16 phy_ready_mask; + struct { + u8 min_index; + u8 max_index; + } phy_valid_port_range[SCI_MAX_PHYS]; + bool timer_pending; + port_config_fn link_up_handler; + port_config_fn link_down_handler; + void *timer; +}; + /** * struct scic_sds_controller - * @@ -800,4 +818,11 @@ u16 scic_controller_allocate_io_tag( enum sci_status scic_controller_free_io_tag( struct scic_sds_controller *scic, u16 io_tag); + +void scic_sds_port_configuration_agent_construct( + struct scic_sds_port_configuration_agent *port_agent); + +enum sci_status scic_sds_port_configuration_agent_initialize( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent); #endif diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index b92d51f25481..0f64605200ff 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -57,9 +57,8 @@ #include "host.h" #include "phy.h" #include "scu_event_codes.h" -#include "scic_port.h" -#include "scic_config_parameters.h" #include "timers.h" +#include "probe_roms.h" /* Maximum arbitration wait time in micro-seconds */ #define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 093fd473366c..f1800368eda5 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -58,6 +58,7 @@ #include #include #include "state_machine.h" +#include "sas.h" /* This is the timeout value for the SATA phy to wait for a SIGNATURE FIS * before restarting the starting state machine. Technically, the old parallel diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 321935d9560b..dbff28396dd8 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -53,11 +53,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include "isci.h" -#include "scic_port.h" #include "port.h" #include "request.h" +#include "timers.h" + +#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) +#define SCU_DUMMY_INDEX (0xFFFF) static void isci_port_change_state(struct isci_port *iport, enum isci_status status) { @@ -73,44 +75,87 @@ static void isci_port_change_state(struct isci_port *iport, enum isci_status sta spin_unlock_irqrestore(&iport->state_lock, flags); } -void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index) +/* + * This function will indicate which protocols are supported by this port. + * @sci_port: a handle corresponding to the SAS port for which to return the + * supported protocols. + * @protocols: This parameter specifies a pointer to a data structure + * which the core will copy the protocol values for the port from the + * transmit_identification register. + */ +static void +scic_sds_port_get_protocols(struct scic_sds_port *sci_port, + struct scic_phy_proto *protocols) { - INIT_LIST_HEAD(&iport->remote_dev_list); - INIT_LIST_HEAD(&iport->domain_dev_list); - spin_lock_init(&iport->state_lock); - init_completion(&iport->start_complete); - iport->isci_host = ihost; - isci_port_change_state(iport, isci_freed); + u8 index; + + protocols->all = 0; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (sci_port->phy_table[index] != NULL) { + scic_sds_phy_get_protocols(sci_port->phy_table[index], + protocols); + } + } } /** - * isci_port_get_state() - This function gets the status of the port object. - * @isci_port: This parameter points to the isci_port object + * This method requests a list (mask) of the phys contained in the supplied SAS + * port. + * @sci_port: a handle corresponding to the SAS port for which to return the + * phy mask. * - * status of the object as a isci_status enum. + * Return a bit mask indicating which phys are a part of this port. Each bit + * corresponds to a phy identifier (e.g. bit 0 = phy id 0). */ -enum isci_status isci_port_get_state( - struct isci_port *isci_port) +static u32 scic_sds_port_get_phys(struct scic_sds_port *sci_port) { - return isci_port->status; + u32 index; + u32 mask; + + mask = 0; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (sci_port->phy_table[index] != NULL) { + mask |= (1 << index); + } + } + + return mask; } -void isci_port_bc_change_received(struct isci_host *ihost, - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) +/** + * scic_port_get_properties() - This method simply returns the properties + * regarding the port, such as: physical index, protocols, sas address, etc. + * @port: this parameter specifies the port for which to retrieve the physical + * index. + * @properties: This parameter specifies the properties structure into which to + * copy the requested information. + * + * Indicate if the user specified a valid port. SCI_SUCCESS This value is + * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This + * value is returned if the specified port is not valid. When this value is + * returned, no data is copied to the properties output parameter. + */ +static enum sci_status scic_port_get_properties(struct scic_sds_port *port, + struct scic_port_properties *prop) { - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + if ((port == NULL) || + (port->logical_port_index == SCIC_SDS_DUMMY_PORT)) + return SCI_FAILURE_INVALID_PORT; - dev_dbg(&ihost->pdev->dev, "%s: iphy = %p, sas_phy = %p\n", - __func__, iphy, &iphy->sas_phy); + prop->index = port->logical_port_index; + prop->phy_mask = scic_sds_port_get_phys(port); + scic_sds_port_get_sas_address(port, &prop->local.sas_address); + scic_sds_port_get_protocols(port, &prop->local.protocols); + scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address); - ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); - scic_port_enable_broadcast_change_notification(sci_port); + return SCI_SUCCESS; } -void isci_port_link_up(struct isci_host *isci_host, - struct scic_sds_port *port, - struct scic_sds_phy *phy) +static void isci_port_link_up(struct isci_host *isci_host, + struct scic_sds_port *port, + struct scic_sds_phy *phy) { unsigned long flags; struct scic_port_properties properties; @@ -184,8 +229,9 @@ void isci_port_link_up(struct isci_host *isci_host, * @port: This parameter specifies the isci port with the active link. * */ -void isci_port_link_down(struct isci_host *isci_host, struct isci_phy *isci_phy, - struct isci_port *isci_port) +static void isci_port_link_down(struct isci_host *isci_host, + struct isci_phy *isci_phy, + struct isci_port *isci_port) { struct isci_remote_device *isci_device; @@ -230,30 +276,6 @@ void isci_port_link_down(struct isci_host *isci_host, struct isci_phy *isci_phy, } -/** - * isci_port_deformed() - This function is called by libsas when a port becomes - * inactive. - * @phy: This parameter specifies the libsas phy with the inactive port. - * - */ -void isci_port_deformed( - struct asd_sas_phy *phy) -{ - pr_debug("%s: sas_phy = %p\n", __func__, phy); -} - -/** - * isci_port_formed() - This function is called by libsas when a port becomes - * active. - * @phy: This parameter specifies the libsas phy with the active port. - * - */ -void isci_port_formed( - struct asd_sas_phy *phy) -{ - pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port); -} - /** * isci_port_ready() - This function is called by the sci core when a link * becomes ready. @@ -261,7 +283,7 @@ void isci_port_formed( * @port: This parameter specifies the sci port with the active link. * */ -void isci_port_ready(struct isci_host *isci_host, struct isci_port *isci_port) +static void isci_port_ready(struct isci_host *isci_host, struct isci_port *isci_port) { dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", __func__, isci_port); @@ -279,12 +301,19 @@ void isci_port_ready(struct isci_host *isci_host, struct isci_port *isci_port) * @port: This parameter specifies the sci port with the active link. * */ -void isci_port_not_ready(struct isci_host *isci_host, struct isci_port *isci_port) +static void isci_port_not_ready(struct isci_host *isci_host, struct isci_port *isci_port) { dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", __func__, isci_port); } +static void isci_port_stop_complete(struct scic_sds_controller *scic, + struct scic_sds_port *sci_port, + enum sci_status completion_status) +{ + dev_dbg(&scic_to_ihost(scic)->pdev->dev, "Port stop complete\n"); +} + /** * isci_port_hard_reset_complete() - This function is called by the sci core * when the hard reset complete notification has been received. @@ -293,8 +322,8 @@ void isci_port_not_ready(struct isci_host *isci_host, struct isci_port *isci_por * process. * */ -void isci_port_hard_reset_complete(struct isci_port *isci_port, - enum sci_status completion_status) +static void isci_port_hard_reset_complete(struct isci_port *isci_port, + enum sci_status completion_status) { dev_dbg(&isci_port->isci_host->pdev->dev, "%s: isci_port = %p, completion_status=%x\n", @@ -306,62 +335,2364 @@ void isci_port_hard_reset_complete(struct isci_port *isci_port, complete_all(&isci_port->hard_reset_complete); } -int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, - struct isci_phy *iphy) +/* This method will return a true value if the specified phy can be assigned to + * this port The following is a list of phys for each port that are allowed: - + * Port 0 - 3 2 1 0 - Port 1 - 1 - Port 2 - 3 2 - Port 3 - 3 This method + * doesn't preclude all configurations. It merely ensures that a phy is part + * of the allowable set of phy identifiers for that port. For example, one + * could assign phy 3 to port 0 and no other phys. Please refer to + * scic_sds_port_is_phy_mask_valid() for information regarding whether the + * phy_mask for a port can be supported. bool true if this is a valid phy + * assignment for the port false if this is not a valid phy assignment for the + * port + */ +bool scic_sds_port_is_valid_phy_assignment(struct scic_sds_port *sci_port, + u32 phy_index) { - unsigned long flags; - enum sci_status status; - int ret = TMF_RESP_FUNC_COMPLETE; + /* Initialize to invalid value. */ + u32 existing_phy_index = SCI_MAX_PHYS; + u32 index; - dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n", - __func__, iport); + if ((sci_port->physical_port_index == 1) && (phy_index != 1)) { + return false; + } - init_completion(&iport->hard_reset_complete); + if (sci_port->physical_port_index == 3 && phy_index != 3) { + return false; + } - spin_lock_irqsave(&ihost->scic_lock, flags); + if ( + (sci_port->physical_port_index == 2) + && ((phy_index == 0) || (phy_index == 1)) + ) { + return false; + } - #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT - status = scic_port_hard_reset(&iport->sci, ISCI_PORT_RESET_TIMEOUT); + for (index = 0; index < SCI_MAX_PHYS; index++) { + if ((sci_port->phy_table[index] != NULL) + && (index != phy_index)) { + existing_phy_index = index; + } + } - spin_unlock_irqrestore(&ihost->scic_lock, flags); + /* + * Ensure that all of the phys in the port are capable of + * operating at the same maximum link rate. */ + if ( + (existing_phy_index < SCI_MAX_PHYS) + && (sci_port->owning_controller->user_parameters.sds1.phys[ + phy_index].max_speed_generation != + sci_port->owning_controller->user_parameters.sds1.phys[ + existing_phy_index].max_speed_generation) + ) + return false; - if (status == SCI_SUCCESS) { - wait_for_completion(&iport->hard_reset_complete); + return true; +} - dev_dbg(&ihost->pdev->dev, - "%s: iport = %p; hard reset completion\n", - __func__, iport); +/** + * + * @sci_port: This is the port object for which to determine if the phy mask + * can be supported. + * + * This method will return a true value if the port's phy mask can be supported + * by the SCU. The following is a list of valid PHY mask configurations for + * each port: - Port 0 - [[3 2] 1] 0 - Port 1 - [1] - Port 2 - [[3] 2] + * - Port 3 - [3] This method returns a boolean indication specifying if the + * phy mask can be supported. true if this is a valid phy assignment for the + * port false if this is not a valid phy assignment for the port + */ +static bool scic_sds_port_is_phy_mask_valid( + struct scic_sds_port *sci_port, + u32 phy_mask) +{ + if (sci_port->physical_port_index == 0) { + if (((phy_mask & 0x0F) == 0x0F) + || ((phy_mask & 0x03) == 0x03) + || ((phy_mask & 0x01) == 0x01) + || (phy_mask == 0)) + return true; + } else if (sci_port->physical_port_index == 1) { + if (((phy_mask & 0x02) == 0x02) + || (phy_mask == 0)) + return true; + } else if (sci_port->physical_port_index == 2) { + if (((phy_mask & 0x0C) == 0x0C) + || ((phy_mask & 0x04) == 0x04) + || (phy_mask == 0)) + return true; + } else if (sci_port->physical_port_index == 3) { + if (((phy_mask & 0x08) == 0x08) + || (phy_mask == 0)) + return true; + } - if (iport->hard_reset_status != SCI_SUCCESS) - ret = TMF_RESP_FUNC_FAILED; - } else { - ret = TMF_RESP_FUNC_FAILED; + return false; +} - dev_err(&ihost->pdev->dev, - "%s: iport = %p; scic_port_hard_reset call" - " failed 0x%x\n", - __func__, iport, status); +/** + * + * @sci_port: This parameter specifies the port from which to return a + * connected phy. + * + * This method retrieves a currently active (i.e. connected) phy contained in + * the port. Currently, the lowest order phy that is connected is returned. + * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is + * returned if there are no currently active (i.e. connected to a remote end + * point) phys contained in the port. All other values specify a struct scic_sds_phy + * object that is active in the port. + */ +static struct scic_sds_phy *scic_sds_port_get_a_connected_phy( + struct scic_sds_port *sci_port + ) { + u32 index; + struct scic_sds_phy *phy; + for (index = 0; index < SCI_MAX_PHYS; index++) { + /* + * Ensure that the phy is both part of the port and currently + * connected to the remote end-point. */ + phy = sci_port->phy_table[index]; + if ( + (phy != NULL) + && scic_sds_port_active_phy(sci_port, phy) + ) { + return phy; + } } - /* If the hard reset for the port has failed, consider this - * the same as link failures on all phys in the port. + return NULL; +} + +/** + * scic_sds_port_set_phy() - + * @out]: port The port object to which the phy assignement is being made. + * @out]: phy The phy which is being assigned to the port. + * + * This method attempts to make the assignment of the phy to the port. If + * successful the phy is assigned to the ports phy table. bool true if the phy + * assignment can be made. false if the phy assignement can not be made. This + * is a functional test that only fails if the phy is currently assigned to a + * different port. + */ +static enum sci_status scic_sds_port_set_phy( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + /* + * Check to see if we can add this phy to a port + * that means that the phy is not part of a port and that the port does + * not already have a phy assinged to the phy index. */ + if ( + (port->phy_table[phy->phy_index] == NULL) + && (scic_sds_phy_get_port(phy) == NULL) + && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index) + ) { + /* + * Phy is being added in the stopped state so we are in MPC mode + * make logical port index = physical port index */ + port->logical_port_index = port->physical_port_index; + port->phy_table[phy->phy_index] = phy; + scic_sds_phy_set_port(phy, port); + + return SCI_SUCCESS; + } + + return SCI_FAILURE; +} + +/** + * scic_sds_port_clear_phy() - + * @out]: port The port from which the phy is being cleared. + * @out]: phy The phy being cleared from the port. + * + * This method will clear the phy assigned to this port. This method fails if + * this phy is not currently assinged to this port. bool true if the phy is + * removed from the port. false if this phy is not assined to this port. + */ +static enum sci_status scic_sds_port_clear_phy( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + /* Make sure that this phy is part of this port */ + if (port->phy_table[phy->phy_index] == phy && + scic_sds_phy_get_port(phy) == port) { + struct scic_sds_controller *scic = port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + + /* Yep it is assigned to this port so remove it */ + scic_sds_phy_set_port(phy, &ihost->ports[SCI_MAX_PORTS].sci); + port->phy_table[phy->phy_index] = NULL; + return SCI_SUCCESS; + } + + return SCI_FAILURE; +} + +/** + * scic_sds_port_add_phy() - + * @sci_port: This parameter specifies the port in which the phy will be added. + * @sci_phy: This parameter is the phy which is to be added to the port. + * + * This method will add a PHY to the selected port. This method returns an + * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status + * is failre to add the phy to the port. + */ +enum sci_status scic_sds_port_add_phy( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + return sci_port->state_handlers->add_phy_handler( + sci_port, sci_phy); +} + + +/** + * scic_sds_port_remove_phy() - + * @sci_port: This parameter specifies the port in which the phy will be added. + * @sci_phy: This parameter is the phy which is to be added to the port. + * + * This method will remove the PHY from the selected PORT. This method returns + * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other + * status is failre to add the phy to the port. + */ +enum sci_status scic_sds_port_remove_phy( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + return sci_port->state_handlers->remove_phy_handler( + sci_port, sci_phy); +} + +/** + * This method requests the SAS address for the supplied SAS port from the SCI + * implementation. + * @sci_port: a handle corresponding to the SAS port for which to return the + * SAS address. + * @sas_address: This parameter specifies a pointer to a SAS address structure + * into which the core will copy the SAS address for the port. + * + */ +void scic_sds_port_get_sas_address( + struct scic_sds_port *sci_port, + struct sci_sas_address *sas_address) +{ + u32 index; + + sas_address->high = 0; + sas_address->low = 0; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (sci_port->phy_table[index] != NULL) { + scic_sds_phy_get_sas_address(sci_port->phy_table[index], sas_address); + } + } +} + +/* + * This function requests the SAS address for the device directly attached to + * this SAS port. + * @sci_port: a handle corresponding to the SAS port for which to return the + * SAS address. + * @sas_address: This parameter specifies a pointer to a SAS address structure + * into which the core will copy the SAS address for the device directly + * attached to the port. + * + */ +void scic_sds_port_get_attached_sas_address( + struct scic_sds_port *sci_port, + struct sci_sas_address *sas_address) +{ + struct scic_sds_phy *sci_phy; + + /* + * Ensure that the phy is both part of the port and currently + * connected to the remote end-point. */ - if (ret != TMF_RESP_FUNC_COMPLETE) { - dev_err(&ihost->pdev->dev, - "%s: iport = %p; hard reset failed " - "(0x%x) - sending link down to libsas for phy %p\n", - __func__, iport, iport->hard_reset_status, iphy); + sci_phy = scic_sds_port_get_a_connected_phy(sci_port); + if (sci_phy) { + if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) { + scic_sds_phy_get_attached_sas_address(sci_phy, + sas_address); + } else { + scic_sds_phy_get_sas_address(sci_phy, sas_address); + sas_address->low += sci_phy->phy_index; + } + } else { + sas_address->high = 0; + sas_address->low = 0; + } +} - isci_port_link_down(ihost, iphy, iport); +/** + * scic_sds_port_construct_dummy_rnc() - create dummy rnc for si workaround + * + * @sci_port: logical port on which we need to create the remote node context + * @rni: remote node index for this remote node context. + * + * This routine will construct a dummy remote node context data structure + * This structure will be posted to the hardware to work around a scheduler + * error in the hardware. + */ +static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni) +{ + union scu_remote_node_context *rnc; + + rnc = &sci_port->owning_controller->remote_node_context_table[rni]; + + memset(rnc, 0, sizeof(union scu_remote_node_context)); + + rnc->ssp.remote_sas_address_hi = 0; + rnc->ssp.remote_sas_address_lo = 0; + + rnc->ssp.remote_node_index = rni; + rnc->ssp.remote_node_port_width = 1; + rnc->ssp.logical_port_index = sci_port->physical_port_index; + + rnc->ssp.nexus_loss_timer_enable = false; + rnc->ssp.check_bit = false; + rnc->ssp.is_valid = true; + rnc->ssp.is_remote_node_context = true; + rnc->ssp.function_number = 0; + rnc->ssp.arbitration_wait_time = 0; +} + +/** + * scic_sds_port_construct_dummy_task() - create dummy task for si workaround + * @sci_port The logical port on which we need to create the + * remote node context. + * context. + * @tci The remote node index for this remote node context. + * + * This routine will construct a dummy task context data structure. This + * structure will be posted to the hardwre to work around a scheduler error + * in the hardware. + * + */ +static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci) +{ + struct scu_task_context *task_context; + + task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tci); + + memset(task_context, 0, sizeof(struct scu_task_context)); + + task_context->abort = 0; + task_context->priority = 0; + task_context->initiator_request = 1; + task_context->connection_rate = 1; + task_context->protocol_engine_index = 0; + task_context->logical_port_index = sci_port->physical_port_index; + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; + task_context->task_index = scic_sds_io_tag_get_index(tci); + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + task_context->remote_node_index = sci_port->reserved_rni; + task_context->command_code = 0; + + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 0; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + task_context->address_modifier = 0; + + task_context->task_phase = 0x01; +} + +static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + + if (sci_port->reserved_tci != SCU_DUMMY_INDEX) + scic_controller_free_io_tag(scic, sci_port->reserved_tci); + + if (sci_port->reserved_rni != SCU_DUMMY_INDEX) + scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes, + 1, sci_port->reserved_rni); + + sci_port->reserved_rni = SCU_DUMMY_INDEX; + sci_port->reserved_tci = SCU_DUMMY_INDEX; +} + +/** + * This method performs initialization of the supplied port. Initialization + * includes: - state machine initialization - member variable initialization + * - configuring the phy_mask + * @sci_port: + * @transport_layer_registers: + * @port_task_scheduler_registers: + * @port_configuration_regsiter: + * + * enum sci_status SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned + * if the phy being added to the port + */ +enum sci_status scic_sds_port_initialize( + struct scic_sds_port *sci_port, + void __iomem *port_task_scheduler_registers, + void __iomem *port_configuration_regsiter, + void __iomem *viit_registers) +{ + sci_port->port_task_scheduler_registers = port_task_scheduler_registers; + sci_port->port_pe_configuration_register = port_configuration_regsiter; + sci_port->viit_registers = viit_registers; + + return SCI_SUCCESS; +} + +/** + * scic_port_hard_reset() - perform port hard reset + * @port: a handle corresponding to the SAS port to be hard reset. + * @reset_timeout: This parameter specifies the number of milliseconds in which + * the port reset operation should complete. + * + * The SCI User callback in scic_user_callbacks_t will only be called once for + * each phy in the SAS Port at completion of the hard reset sequence. Return a + * status indicating whether the hard reset started successfully. SCI_SUCCESS + * This value is returned if the hard reset operation started successfully. + */ +static enum sci_status scic_port_hard_reset(struct scic_sds_port *port, + u32 reset_timeout) +{ + return port->state_handlers->reset_handler( + port, reset_timeout); +} + +/** + * This method assigns the direct attached device ID for this port. + * + * @param[in] sci_port The port for which the direct attached device id is to + * be assigned. + * @param[in] device_id The direct attached device ID to assign to the port. + * This will be the RNi for the device + */ +void scic_sds_port_setup_transports( + struct scic_sds_port *sci_port, + u32 device_id) +{ + u8 index; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (sci_port->active_phy_mask & (1 << index)) + scic_sds_phy_setup_transport(sci_port->phy_table[index], device_id); } +} - return ret; +/** + * + * @sci_port: This is the port on which the phy should be enabled. + * @sci_phy: This is the specific phy which to enable. + * @do_notify_user: This parameter specifies whether to inform the user (via + * scic_cb_port_link_up()) as to the fact that a new phy as become ready. + * + * This function will activate the phy in the port. + * Activation includes: - adding + * the phy to the port - enabling the Protocol Engine in the silicon. - + * notifying the user that the link is up. none + */ +static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + + if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) + scic_sds_phy_resume(sci_phy); + + sci_port->active_phy_mask |= 1 << sci_phy->phy_index; + + scic_sds_controller_clear_invalid_phy(scic, sci_phy); + + if (do_notify_user == true) + isci_port_link_up(ihost, sci_port, sci_phy); } -void isci_port_stop_complete(struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, - enum sci_status completion_status) +void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user) { - dev_dbg(&scic_to_ihost(scic)->pdev->dev, "Port stop complete\n"); + struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); + struct isci_port *iport = sci_port_to_iport(sci_port); + struct isci_host *ihost = scic_to_ihost(scic); + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); + + sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; + + /* Re-assign the phy back to the LP as if it were a narrow port */ + writel(sci_phy->phy_index, + &sci_port->port_pe_configuration_register[sci_phy->phy_index]); + + if (do_notify_user == true) + isci_port_link_down(ihost, iphy, iport); +} + +/** + * + * @sci_port: This is the port on which the phy should be disabled. + * @sci_phy: This is the specific phy which to disabled. + * + * This function will disable the phy and report that the phy is not valid for + * this port object. None + */ +static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + + /* + * Check to see if we have alreay reported this link as bad and if + * not go ahead and tell the SCI_USER that we have discovered an + * invalid link. + */ + if ((scic->invalid_phy_mask & (1 << sci_phy->phy_index)) == 0) { + scic_sds_controller_set_invalid_phy(scic, sci_phy); + dev_warn(&scic_to_ihost(scic)->pdev->dev, "Invalid link up!\n"); + } +} + +/** + * scic_sds_port_general_link_up_handler - phy can be assigned to port? + * @sci_port: scic_sds_port object for which has a phy that has gone link up. + * @sci_phy: This is the struct scic_sds_phy object that has gone link up. + * @do_notify_user: This parameter specifies whether to inform the user (via + * scic_cb_port_link_up()) as to the fact that a new phy as become ready. + * + * Determine if this phy can be assigned to this + * port . If the phy is not a valid PHY for + * this port then the function will notify the user. A PHY can only be + * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in + * the same port. none + */ +static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user) +{ + struct sci_sas_address port_sas_address; + struct sci_sas_address phy_sas_address; + + scic_sds_port_get_attached_sas_address(sci_port, &port_sas_address); + scic_sds_phy_get_attached_sas_address(sci_phy, &phy_sas_address); + + /* If the SAS address of the new phy matches the SAS address of + * other phys in the port OR this is the first phy in the port, + * then activate the phy and allow it to be used for operations + * in this port. + */ + if ((phy_sas_address.high == port_sas_address.high && + phy_sas_address.low == port_sas_address.low) || + sci_port->active_phy_mask == 0) { + struct sci_base_state_machine *sm = &sci_port->state_machine; + + scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); + if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING) + sci_base_state_machine_change_state(sm, SCI_BASE_PORT_STATE_READY); + } else + scic_sds_port_invalid_link_up(sci_port, sci_phy); +} + + + +/** + * This method returns false if the port only has a single phy object assigned. + * If there are no phys or more than one phy then the method will return + * true. + * @sci_port: The port for which the wide port condition is to be checked. + * + * bool true Is returned if this is a wide ported port. false Is returned if + * this is a narrow port. + */ +static bool scic_sds_port_is_wide(struct scic_sds_port *sci_port) +{ + u32 index; + u32 phy_count = 0; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (sci_port->phy_table[index] != NULL) { + phy_count++; + } + } + + return phy_count != 1; +} + +/** + * This method is called by the PHY object when the link is detected. if the + * port wants the PHY to continue on to the link up state then the port + * layer must return true. If the port object returns false the phy object + * must halt its attempt to go link up. + * @sci_port: The port associated with the phy object. + * @sci_phy: The phy object that is trying to go link up. + * + * true if the phy object can continue to the link up condition. true Is + * returned if this phy can continue to the ready state. false Is returned if + * can not continue on to the ready state. This notification is in place for + * wide ports and direct attached phys. Since there are no wide ported SATA + * devices this could become an invalid port configuration. + */ +bool scic_sds_port_link_detected( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + if ((sci_port->logical_port_index != SCIC_SDS_DUMMY_PORT) && + (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && + scic_sds_port_is_wide(sci_port)) { + scic_sds_port_invalid_link_up(sci_port, sci_phy); + + return false; + } + + return true; +} + +/** + * This method is the entry point for the phy to inform the port that it is now + * in a ready state + * @sci_port: + * + * + */ +void scic_sds_port_link_up( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + sci_phy->is_in_link_training = false; + + sci_port->state_handlers->link_up_handler(sci_port, sci_phy); +} + +/** + * This method is the entry point for the phy to inform the port that it is no + * longer in a ready state + * @sci_port: + * + * + */ +void scic_sds_port_link_down( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + sci_port->state_handlers->link_down_handler(sci_port, sci_phy); +} + +/** + * This method is called to start an IO request on this port. + * @sci_port: + * @sci_dev: + * @sci_req: + * + * enum sci_status + */ +enum sci_status scic_sds_port_start_io( + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + return sci_port->state_handlers->start_io_handler( + sci_port, sci_dev, sci_req); +} + +/** + * This method is called to complete an IO request to the port. + * @sci_port: + * @sci_dev: + * @sci_req: + * + * enum sci_status + */ +enum sci_status scic_sds_port_complete_io( + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + return sci_port->state_handlers->complete_io_handler( + sci_port, sci_dev, sci_req); +} + +/** + * This method is provided to timeout requests for port operations. Mostly its + * for the port reset operation. + * + * + */ +static void scic_sds_port_timeout_handler(void *port) +{ + struct scic_sds_port *sci_port = port; + u32 current_state; + + current_state = sci_base_state_machine_get_state( + &sci_port->state_machine); + + if (current_state == SCI_BASE_PORT_STATE_RESETTING) { + /* + * if the port is still in the resetting state then the + * timeout fired before the reset completed. + */ + sci_base_state_machine_change_state( + &sci_port->state_machine, + SCI_BASE_PORT_STATE_FAILED); + } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { + /* + * if the port is stopped then the start request failed + * In this case stay in the stopped state. + */ + dev_err(sciport_to_dev(sci_port), + "%s: SCIC Port 0x%p failed to stop before tiemout.\n", + __func__, + sci_port); + } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { + /* + * if the port is still stopping then the stop has not + * completed + */ + isci_port_stop_complete( + scic_sds_port_get_controller(sci_port), + sci_port, + SCI_FAILURE_TIMEOUT); + } else { + /* + * The port is in the ready state and we have a timer + * reporting a timeout this should not happen. + */ + dev_err(sciport_to_dev(sci_port), + "%s: SCIC Port 0x%p is processing a timeout operation " + "in state %d.\n", + __func__, + sci_port, + current_state); + } +} + +/* --------------------------------------------------------------------------- */ + +/** + * This function updates the hardwares VIIT entry for this port. + * + * + */ +static void scic_sds_port_update_viit_entry(struct scic_sds_port *sci_port) +{ + struct sci_sas_address sas_address; + + scic_sds_port_get_sas_address(sci_port, &sas_address); + + writel(sas_address.high, + &sci_port->viit_registers->initiator_sas_address_hi); + writel(sas_address.low, + &sci_port->viit_registers->initiator_sas_address_lo); + + /* This value get cleared just in case its not already cleared */ + writel(0, &sci_port->viit_registers->reserved); + + /* We are required to update the status register last */ + writel(SCU_VIIT_ENTRY_ID_VIIT | + SCU_VIIT_IPPT_INITIATOR | + ((1 << sci_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) | + SCU_VIIT_STATUS_ALL_VALID, + &sci_port->viit_registers->status); +} + +/** + * This method returns the maximum allowed speed for data transfers on this + * port. This maximum allowed speed evaluates to the maximum speed of the + * slowest phy in the port. + * @sci_port: This parameter specifies the port for which to retrieve the + * maximum allowed speed. + * + * This method returns the maximum negotiated speed of the slowest phy in the + * port. + */ +enum sas_linkrate scic_sds_port_get_max_allowed_speed( + struct scic_sds_port *sci_port) +{ + u16 index; + enum sas_linkrate max_allowed_speed = SAS_LINK_RATE_6_0_GBPS; + struct scic_sds_phy *phy = NULL; + + /* + * Loop through all of the phys in this port and find the phy with the + * lowest maximum link rate. */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + phy = sci_port->phy_table[index]; + if ( + (phy != NULL) + && (scic_sds_port_active_phy(sci_port, phy) == true) + && (phy->max_negotiated_speed < max_allowed_speed) + ) + max_allowed_speed = phy->max_negotiated_speed; + } + + return max_allowed_speed; +} + +static void scic_port_enable_broadcast_change_notification(struct scic_sds_port *port) +{ + struct scic_sds_phy *phy; + u32 register_value; + u8 index; + + /* Loop through all of the phys to enable BCN. */ + for (index = 0; index < SCI_MAX_PHYS; index++) { + phy = port->phy_table[index]; + if (phy != NULL) { + register_value = + readl(&phy->link_layer_registers->link_layer_control); + + /* clear the bit by writing 1. */ + writel(register_value, + &phy->link_layer_registers->link_layer_control); + } + } +} + +/* + * **************************************************************************** + * * READY SUBSTATE HANDLERS + * **************************************************************************** */ + +/* + * This method is the general ready state stop handler for the struct scic_sds_port + * object. This function will transition the ready substate machine to its + * final state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_ready_substate_stop_handler( + struct scic_sds_port *port) +{ + sci_base_state_machine_change_state( + &port->state_machine, + SCI_BASE_PORT_STATE_STOPPING + ); + + return SCI_SUCCESS; +} + +/* + * This method is the general ready substate complete io handler for the + * struct scic_sds_port object. This function decrments the outstanding request count + * for this port object. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_ready_substate_complete_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + scic_sds_port_decrement_request_count(port); + + return SCI_SUCCESS; +} + +static enum sci_status scic_sds_port_ready_substate_add_phy_handler( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + enum sci_status status; + + status = scic_sds_port_set_phy(port, phy); + + if (status == SCI_SUCCESS) { + scic_sds_port_general_link_up_handler(port, phy, true); + + port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + + sci_base_state_machine_change_state( + &port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + } + + return status; +} + + +static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + enum sci_status status; + + status = scic_sds_port_clear_phy(port, phy); + + if (status == SCI_SUCCESS) { + scic_sds_port_deactivate_phy(port, phy, true); + + port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + + sci_base_state_machine_change_state( + &port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + } + + return status; +} + +/* + * **************************************************************************** + * * READY SUBSTATE WAITING HANDLERS + * **************************************************************************** */ + +/** + * + * @sci_port: This is the struct scic_sds_port object that which has a phy that has + * gone link up. + * @sci_phy: This is the struct scic_sds_phy object that has gone link up. + * + * This method is the ready waiting substate link up handler for the + * struct scic_sds_port object. This methos will report the link up condition for + * this port and will transition to the ready operational substate. none + */ +static void scic_sds_port_ready_waiting_substate_link_up_handler( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + /* + * Since this is the first phy going link up for the port we can just enable + * it and continue. */ + scic_sds_port_activate_phy(sci_port, sci_phy, true); + + sci_base_state_machine_change_state( + &sci_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL + ); +} + +/* + * This method is the ready waiting substate start io handler for the + * struct scic_sds_port object. The port object can not accept new requests so the + * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + return SCI_FAILURE_INVALID_STATE; +} + +/* + * **************************************************************************** + * * READY SUBSTATE OPERATIONAL HANDLERS + * **************************************************************************** */ + +/* + * This method will casue the port to reset. enum sci_status SCI_SUCCESS + */ +static enum +sci_status scic_sds_port_ready_operational_substate_reset_handler( + struct scic_sds_port *port, + u32 timeout) +{ + enum sci_status status = SCI_FAILURE_INVALID_PHY; + u32 phy_index; + struct scic_sds_phy *selected_phy = NULL; + + + /* Select a phy on which we can send the hard reset request. */ + for (phy_index = 0; + (phy_index < SCI_MAX_PHYS) && (selected_phy == NULL); + phy_index++) { + selected_phy = port->phy_table[phy_index]; + + if ((selected_phy != NULL) && + !scic_sds_port_active_phy(port, selected_phy)) { + /* + * We found a phy but it is not ready select + * different phy + */ + selected_phy = NULL; + } + } + + /* If we have a phy then go ahead and start the reset procedure */ + if (selected_phy != NULL) { + status = scic_sds_phy_reset(selected_phy); + + if (status == SCI_SUCCESS) { + isci_timer_start(port->timer_handle, timeout); + port->not_ready_reason = + SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; + + sci_base_state_machine_change_state( + &port->state_machine, + SCI_BASE_PORT_STATE_RESETTING); + } + } + + return status; +} + +/** + * scic_sds_port_ready_operational_substate_link_up_handler() - + * @sci_port: This is the struct scic_sds_port object that which has a phy that has + * gone link up. + * @sci_phy: This is the struct scic_sds_phy object that has gone link up. + * + * This method is the ready operational substate link up handler for the + * struct scic_sds_port object. This function notifies the SCI User that the phy has + * gone link up. none + */ +static void scic_sds_port_ready_operational_substate_link_up_handler( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); +} + +/** + * scic_sds_port_ready_operational_substate_link_down_handler() - + * @sci_port: This is the struct scic_sds_port object that which has a phy that has + * gone link down. + * @sci_phy: This is the struct scic_sds_phy object that has gone link down. + * + * This method is the ready operational substate link down handler for the + * struct scic_sds_port object. This function notifies the SCI User that the phy has + * gone link down and if this is the last phy in the port the port will change + * state to the ready waiting substate. none + */ +static void scic_sds_port_ready_operational_substate_link_down_handler( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + scic_sds_port_deactivate_phy(sci_port, sci_phy, true); + + /* + * If there are no active phys left in the port, then transition + * the port to the WAITING state until such time as a phy goes + * link up. */ + if (sci_port->active_phy_mask == 0) + sci_base_state_machine_change_state(&sci_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); +} + +/* + * This method is the ready operational substate start io handler for the + * struct scic_sds_port object. This function incremetns the outstanding request + * count for this port object. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + port->started_request_count++; + return SCI_SUCCESS; +} + +/* + * **************************************************************************** + * * READY SUBSTATE OPERATIONAL HANDLERS + * **************************************************************************** */ + +/* + * This is the default method for a port add phy request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + enum sci_status status; + + status = scic_sds_port_set_phy(port, phy); + + if (status == SCI_SUCCESS) { + scic_sds_port_general_link_up_handler(port, phy, true); + + /* + * Re-enter the configuring state since this may be the last phy in + * the port. */ + sci_base_state_machine_change_state( + &port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + } + + return status; +} + +/* + * This is the default method for a port remove phy request. It will report a + * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE + */ +static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + enum sci_status status; + + status = scic_sds_port_clear_phy(port, phy); + + if (status == SCI_SUCCESS) { + scic_sds_port_deactivate_phy(port, phy, true); + + /* + * Re-enter the configuring state since this may be the last phy in + * the port. */ + sci_base_state_machine_change_state( + &port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING + ); + } + + return status; +} + +/** + * scic_sds_port_ready_configuring_substate_complete_io_handler() - + * @port: This is the port that is being requested to complete the io request. + * @device: This is the device on which the io is completing. + * + * This method will decrement the outstanding request count for this port. If + * the request count goes to 0 then the port can be reprogrammed with its new + * phy data. + */ +static enum sci_status +scic_sds_port_ready_configuring_substate_complete_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + scic_sds_port_decrement_request_count(port); + + if (port->started_request_count == 0) { + sci_base_state_machine_change_state( + &port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL + ); + } + + return SCI_SUCCESS; +} + +static enum sci_status default_port_handler(struct scic_sds_port *sci_port, + const char *func) +{ + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", func, + sci_base_state_machine_get_state(&sci_port->state_machine)); + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status +scic_sds_port_default_start_handler(struct scic_sds_port *sci_port) +{ + return default_port_handler(sci_port, __func__); +} + +static enum sci_status +scic_sds_port_default_stop_handler(struct scic_sds_port *sci_port) +{ + return default_port_handler(sci_port, __func__); +} + +static enum sci_status +scic_sds_port_default_destruct_handler(struct scic_sds_port *sci_port) +{ + return default_port_handler(sci_port, __func__); +} + +static enum sci_status +scic_sds_port_default_reset_handler(struct scic_sds_port *sci_port, + u32 timeout) +{ + return default_port_handler(sci_port, __func__); +} + +static enum sci_status +scic_sds_port_default_add_phy_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *base_phy) +{ + return default_port_handler(sci_port, __func__); +} + +static enum sci_status +scic_sds_port_default_remove_phy_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *base_phy) +{ + return default_port_handler(sci_port, __func__); +} + +/* + * This is the default method for a port unsolicited frame request. It will + * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even + * possible to receive an unsolicited frame directed to a port object? It + * seems possible if we implementing virtual functions but until then? + */ +static enum sci_status +scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port, + u32 frame_index) +{ + struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); + + default_port_handler(sci_port, __func__); + scic_sds_controller_release_frame(scic, frame_index); + + return SCI_FAILURE_INVALID_STATE; +} + +static enum sci_status scic_sds_port_default_event_handler(struct scic_sds_port *sci_port, + u32 event_code) +{ + return default_port_handler(sci_port, __func__); +} + +static void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + default_port_handler(sci_port, __func__); +} + +static void scic_sds_port_default_link_down_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + default_port_handler(sci_port, __func__); +} + +static enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + return default_port_handler(sci_port, __func__); +} + +static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + return default_port_handler(sci_port, __func__); +} + + + +static struct scic_sds_port_state_handler +scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = { + { + /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */ + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_ready_substate_add_phy_handler, + scic_sds_port_default_remove_phy_handler, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_ready_waiting_substate_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_ready_waiting_substate_start_io_handler, + scic_sds_port_ready_substate_complete_io_handler, + }, + + { + /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */ + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_ready_operational_substate_reset_handler, + scic_sds_port_ready_substate_add_phy_handler, + scic_sds_port_ready_substate_remove_phy_handler, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_ready_operational_substate_link_up_handler, + scic_sds_port_ready_operational_substate_link_down_handler, + scic_sds_port_ready_operational_substate_start_io_handler, + scic_sds_port_ready_substate_complete_io_handler, + }, + + { + /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */ + scic_sds_port_default_start_handler, + scic_sds_port_ready_substate_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_ready_configuring_substate_add_phy_handler, + scic_sds_port_ready_configuring_substate_remove_phy_handler, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_ready_configuring_substate_complete_io_handler + } +}; + +/** + * scic_sds_port_set_ready_state_handlers() - + * + * This macro sets the port ready substate handlers. + */ +#define scic_sds_port_set_ready_state_handlers(port, state_id) \ + scic_sds_port_set_state_handlers(\ + port, &scic_sds_port_ready_substate_handler_table[(state_id)] \ + ) + +/* + * ****************************************************************************** + * * PORT STATE PRIVATE METHODS + * ****************************************************************************** */ + +/** + * + * @sci_port: This is the struct scic_sds_port object to suspend. + * + * This method will susped the port task scheduler for this port object. none + */ +static void +scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port) +{ + u32 pts_control_value; + + pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND); + writel(pts_control_value, &port->port_task_scheduler_registers->control); +} + +/** + * scic_sds_port_post_dummy_request() - post dummy/workaround request + * @sci_port: port to post task + * + * Prevent the hardware scheduler from posting new requests to the front + * of the scheduler queue causing a starvation problem for currently + * ongoing requests. + * + */ +static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) +{ + u32 command; + struct scu_task_context *task_context; + struct scic_sds_controller *scic = sci_port->owning_controller; + u16 tci = sci_port->reserved_tci; + + task_context = scic_sds_controller_get_task_context_buffer(scic, tci); + + task_context->abort = 0; + + command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | + tci; + + scic_sds_controller_post_request(scic, command); +} + +/** + * This routine will abort the dummy request. This will alow the hardware to + * power down parts of the silicon to save power. + * + * @sci_port: The port on which the task must be aborted. + * + */ +static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + u16 tci = sci_port->reserved_tci; + struct scu_task_context *tc; + u32 command; + + tc = scic_sds_controller_get_task_context_buffer(scic, tci); + + tc->abort = 1; + + command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT | + sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | + tci; + + scic_sds_controller_post_request(scic, command); +} + +/** + * + * @sci_port: This is the struct scic_sds_port object to resume. + * + * This method will resume the port task scheduler for this port object. none + */ +static void +scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) +{ + u32 pts_control_value; + + pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND); + writel(pts_control_value, &port->port_task_scheduler_registers->control); +} + +/* + * ****************************************************************************** + * * PORT READY SUBSTATE METHODS + * ****************************************************************************** */ + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the + * port for any ready phys. If there is at least one phy in a ready state then + * the port transitions to the ready operational substate. none + */ +static void scic_sds_port_ready_substate_waiting_enter(void *object) +{ + struct scic_sds_port *sci_port = object; + + scic_sds_port_set_ready_state_handlers( + sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING + ); + + scic_sds_port_suspend_port_task_scheduler(sci_port); + + sci_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; + + if (sci_port->active_phy_mask != 0) { + /* At least one of the phys on the port is ready */ + sci_base_state_machine_change_state( + &sci_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL + ); + } +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This function will perform the actions required by the struct scic_sds_port + * on entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets + * the state handlers for the port object, notifies the SCI User that the port + * is ready, and resumes port operations. none + */ +static void scic_sds_port_ready_substate_operational_enter(void *object) +{ + u32 index; + struct scic_sds_port *sci_port = object; + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + struct isci_port *iport = sci_port_to_iport(sci_port); + + scic_sds_port_set_ready_state_handlers( + sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); + + isci_port_ready(ihost, iport); + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if (sci_port->phy_table[index]) { + writel(sci_port->physical_port_index, + &sci_port->port_pe_configuration_register[ + sci_port->phy_table[index]->phy_index]); + } + } + + scic_sds_port_update_viit_entry(sci_port); + + scic_sds_port_resume_port_task_scheduler(sci_port); + + /* + * Post the dummy task for the port so the hardware can schedule + * io correctly + */ + scic_sds_port_post_dummy_request(sci_port); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports + * the port not ready and suspends the port task scheduler. none + */ +static void scic_sds_port_ready_substate_operational_exit(void *object) +{ + struct scic_sds_port *sci_port = object; + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + struct isci_port *iport = sci_port_to_iport(sci_port); + + /* + * Kill the dummy task for this port if it has not yet posted + * the hardware will treat this as a NOP and just return abort + * complete. + */ + scic_sds_port_abort_dummy_request(sci_port); + + isci_port_not_ready(ihost, iport); +} + +/* + * ****************************************************************************** + * * PORT READY CONFIGURING METHODS + * ****************************************************************************** */ + +/** + * scic_sds_port_ready_substate_configuring_enter() - + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports + * the port not ready and suspends the port task scheduler. none + */ +static void scic_sds_port_ready_substate_configuring_enter(void *object) +{ + struct scic_sds_port *sci_port = object; + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + struct isci_port *iport = sci_port_to_iport(sci_port); + + scic_sds_port_set_ready_state_handlers( + sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + + if (sci_port->active_phy_mask == 0) { + isci_port_not_ready(ihost, iport); + + sci_base_state_machine_change_state( + &sci_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + } else if (sci_port->started_request_count == 0) + sci_base_state_machine_change_state( + &sci_port->ready_substate_machine, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); +} + +static void scic_sds_port_ready_substate_configuring_exit(void *object) +{ + struct scic_sds_port *sci_port = object; + + scic_sds_port_suspend_port_task_scheduler(sci_port); +} + +/* --------------------------------------------------------------------------- */ + +static const struct sci_base_state scic_sds_port_ready_substate_table[] = { + [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { + .enter_state = scic_sds_port_ready_substate_waiting_enter, + }, + [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { + .enter_state = scic_sds_port_ready_substate_operational_enter, + .exit_state = scic_sds_port_ready_substate_operational_exit + }, + [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { + .enter_state = scic_sds_port_ready_substate_configuring_enter, + .exit_state = scic_sds_port_ready_substate_configuring_exit + }, +}; + +/** + * + * @port: This is the struct scic_sds_port object on which the io request count will + * be decremented. + * @device: This is the struct scic_sds_remote_device object to which the io request + * is being directed. This parameter is not required to complete this + * operation. + * @io_request: This is the request that is being completed on this port + * object. This parameter is not required to complete this operation. + * + * This is a general complete io request handler for the struct scic_sds_port object. + * enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_general_complete_io_handler( + struct scic_sds_port *port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + scic_sds_port_decrement_request_count(port); + + return SCI_SUCCESS; +} + +/** + * scic_sds_port_stopped_state_start_handler() - stop a port from "started" + * + * @port: This is the struct scic_sds_port object which is cast into a + * struct scic_sds_port object. + * + * This function takes the struct scic_sds_port from a stopped state and + * attempts to start it. To start a port it must have no assiged devices and + * it must have at least one phy assigned to it. If those conditions are + * met then the port can transition to the ready state. + * enum sci_status + * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION + * This struct scic_sds_port object could not be started because the port + * configuration is not valid. + * SCI_SUCCESS + * the start request is successful and the struct scic_sds_port object + * has transitioned to the SCI_BASE_PORT_STATE_READY. + */ +static enum sci_status +scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + enum sci_status status = SCI_SUCCESS; + u32 phy_mask; + + if (sci_port->assigned_device_count > 0) { + /* + * @todo This is a start failure operation because + * there are still devices assigned to this port. + * There must be no devices assigned to a port on a + * start operation. + */ + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + sci_port->timer_handle = + isci_timer_create(ihost, + sci_port, + scic_sds_port_timeout_handler); + + if (!sci_port->timer_handle) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + + if (sci_port->reserved_rni == SCU_DUMMY_INDEX) { + u16 rni = scic_sds_remote_node_table_allocate_remote_node( + &scic->available_remote_nodes, 1); + + if (rni != SCU_DUMMY_INDEX) + scic_sds_port_construct_dummy_rnc(sci_port, rni); + else + status = SCI_FAILURE_INSUFFICIENT_RESOURCES; + sci_port->reserved_rni = rni; + } + + if (sci_port->reserved_tci == SCU_DUMMY_INDEX) { + /* Allocate a TCI and remove the sequence nibble */ + u16 tci = scic_controller_allocate_io_tag(scic); + + if (tci != SCU_DUMMY_INDEX) + scic_sds_port_construct_dummy_task(sci_port, tci); + else + status = SCI_FAILURE_INSUFFICIENT_RESOURCES; + sci_port->reserved_tci = tci; + } + + if (status == SCI_SUCCESS) { + phy_mask = scic_sds_port_get_phys(sci_port); + + /* + * There are one or more phys assigned to this port. Make sure + * the port's phy mask is in fact legal and supported by the + * silicon. + */ + if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { + sci_base_state_machine_change_state( + &sci_port->state_machine, + SCI_BASE_PORT_STATE_READY); + + return SCI_SUCCESS; + } else + status = SCI_FAILURE; + } + + if (status != SCI_SUCCESS) + scic_sds_port_destroy_dummy_resources(sci_port); + + return status; +} + +/* + * This method takes the struct scic_sds_port that is in a stopped state and handles a + * stop request. This function takes no action. enum sci_status SCI_SUCCESS the + * stop request is successful as the struct scic_sds_port object is already stopped. + */ +static enum sci_status scic_sds_port_stopped_state_stop_handler( + struct scic_sds_port *port) +{ + /* We are already stopped so there is nothing to do here */ + return SCI_SUCCESS; +} + +/* + * This method takes the struct scic_sds_port that is in a stopped state and handles + * the destruct request. The stopped state is the only state in which the + * struct scic_sds_port can be destroyed. This function causes the port object to + * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_stopped_state_destruct_handler( + struct scic_sds_port *port) +{ + sci_base_state_machine_stop(&port->state_machine); + + return SCI_SUCCESS; +} + +/* + * This method takes the struct scic_sds_port that is in a stopped state and handles + * the add phy request. In MPC mode the only time a phy can be added to a port + * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status + * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not + * be added to the port. SCI_SUCCESS if the phy is added to the port. + */ +static enum sci_status scic_sds_port_stopped_state_add_phy_handler( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + struct sci_sas_address port_sas_address; + + /* Read the port assigned SAS Address if there is one */ + scic_sds_port_get_sas_address(port, &port_sas_address); + + if (port_sas_address.high != 0 && port_sas_address.low != 0) { + struct sci_sas_address phy_sas_address; + + /* + * Make sure that the PHY SAS Address matches the SAS Address + * for this port. */ + scic_sds_phy_get_sas_address(phy, &phy_sas_address); + + if ( + (port_sas_address.high != phy_sas_address.high) + || (port_sas_address.low != phy_sas_address.low) + ) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + } + + return scic_sds_port_set_phy(port, phy); +} + +/* + * This method takes the struct scic_sds_port that is in a stopped state and handles + * the remove phy request. In MPC mode the only time a phy can be removed from + * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status + * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not + * be added to the port. SCI_SUCCESS if the phy is added to the port. + */ +static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + return scic_sds_port_clear_phy(port, phy); +} + +/* + * **************************************************************************** + * * READY STATE HANDLERS + * **************************************************************************** */ + +/* + * **************************************************************************** + * * RESETTING STATE HANDLERS + * **************************************************************************** */ + +/* + * **************************************************************************** + * * STOPPING STATE HANDLERS + * **************************************************************************** */ + +/* + * This method takes the struct scic_sds_port that is in a stopping state and handles + * the complete io request. Should the request count reach 0 then the port + * object will transition to the stopped state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_stopping_state_complete_io_handler( + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *device, + struct scic_sds_request *io_request) +{ + scic_sds_port_decrement_request_count(sci_port); + + if (sci_port->started_request_count == 0) { + sci_base_state_machine_change_state(&sci_port->state_machine, + SCI_BASE_PORT_STATE_STOPPED); + } + + return SCI_SUCCESS; +} + +/* + * **************************************************************************** + * * RESETTING STATE HANDLERS + * **************************************************************************** */ + +/** + * + * @port: This is the port object which is being requested to stop. + * + * This method will stop a failed port. This causes a transition to the + * stopping state. enum sci_status SCI_SUCCESS + */ +static enum sci_status scic_sds_port_reset_state_stop_handler( + struct scic_sds_port *port) +{ + sci_base_state_machine_change_state( + &port->state_machine, + SCI_BASE_PORT_STATE_STOPPING + ); + + return SCI_SUCCESS; +} + +/* + * This method will transition a failed port to its ready state. The port + * failed because a hard reset request timed out but at some time later one or + * more phys in the port became ready. enum sci_status SCI_SUCCESS + */ +static void scic_sds_port_reset_state_link_up_handler( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + /* + * / @todo We should make sure that the phy that has gone link up is the same + * / one on which we sent the reset. It is possible that the phy on + * / which we sent the reset is not the one that has gone link up and we + * / want to make sure that phy being reset comes back. Consider the + * / case where a reset is sent but before the hardware processes the + * / reset it get a link up on the port because of a hot plug event. + * / because of the reset request this phy will go link down almost + * / immediately. */ + + /* + * In the resetting state we don't notify the user regarding + * link up and link down notifications. */ + scic_sds_port_general_link_up_handler(port, phy, false); +} + +/* + * This method process link down notifications that occur during a port reset + * operation. Link downs can occur during the reset operation. enum sci_status + * SCI_SUCCESS + */ +static void scic_sds_port_reset_state_link_down_handler( + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + /* + * In the resetting state we don't notify the user regarding + * link up and link down notifications. */ + scic_sds_port_deactivate_phy(port, phy, false); +} + +static struct scic_sds_port_state_handler +scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = +{ + /* SCI_BASE_PORT_STATE_STOPPED */ + { + scic_sds_port_stopped_state_start_handler, + scic_sds_port_stopped_state_stop_handler, + scic_sds_port_stopped_state_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_stopped_state_add_phy_handler, + scic_sds_port_stopped_state_remove_phy_handler, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_default_complete_io_handler + }, + /* SCI_BASE_PORT_STATE_STOPPING */ + { + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_stopping_state_complete_io_handler + }, + /* SCI_BASE_PORT_STATE_READY */ + { + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_general_complete_io_handler + }, + /* SCI_BASE_PORT_STATE_RESETTING */ + { + scic_sds_port_default_start_handler, + scic_sds_port_reset_state_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_reset_state_link_up_handler, + scic_sds_port_reset_state_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_general_complete_io_handler + }, + /* SCI_BASE_PORT_STATE_FAILED */ + { + scic_sds_port_default_start_handler, + scic_sds_port_default_stop_handler, + scic_sds_port_default_destruct_handler, + scic_sds_port_default_reset_handler, + scic_sds_port_default_add_phy_handler, + scic_sds_port_default_remove_phy_handler, + scic_sds_port_default_frame_handler, + scic_sds_port_default_event_handler, + scic_sds_port_default_link_up_handler, + scic_sds_port_default_link_down_handler, + scic_sds_port_default_start_io_handler, + scic_sds_port_general_complete_io_handler + } +}; + +/* + * ****************************************************************************** + * * PORT STATE PRIVATE METHODS + * ****************************************************************************** */ + +/** + * + * @sci_port: This is the port object which to suspend. + * + * This method will enable the SCU Port Task Scheduler for this port object but + * will leave the port task scheduler in a suspended state. none + */ +static void +scic_sds_port_enable_port_task_scheduler(struct scic_sds_port *port) +{ + u32 pts_control_value; + + pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND); + writel(pts_control_value, &port->port_task_scheduler_registers->control); +} + +/** + * + * @sci_port: This is the port object which to resume. + * + * This method will disable the SCU port task scheduler for this port object. + * none + */ +static void +scic_sds_port_disable_port_task_scheduler(struct scic_sds_port *port) +{ + u32 pts_control_value; + + pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value &= + ~(SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND)); + writel(pts_control_value, &port->port_task_scheduler_registers->control); +} + +static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + u8 phys_index = sci_port->physical_port_index; + union scu_remote_node_context *rnc; + u16 rni = sci_port->reserved_rni; + u32 command; + + rnc = &scic->remote_node_context_table[rni]; + rnc->ssp.is_valid = true; + + command = SCU_CONTEXT_COMMAND_POST_RNC_32 | + phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; + + scic_sds_controller_post_request(scic, command); + + /* ensure hardware has seen the post rnc command and give it + * ample time to act before sending the suspend + */ + readl(&scic->smu_registers->interrupt_status); /* flush */ + udelay(10); + + command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX | + phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; + + scic_sds_controller_post_request(scic, command); +} + +static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + u8 phys_index = sci_port->physical_port_index; + union scu_remote_node_context *rnc; + u16 rni = sci_port->reserved_rni; + u32 command; + + rnc = &scic->remote_node_context_table[rni]; + + rnc->ssp.is_valid = false; + + /* ensure the preceding tc abort request has reached the + * controller and give it ample time to act before posting the rnc + * invalidate + */ + readl(&scic->smu_registers->interrupt_status); /* flush */ + udelay(10); + + command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | + phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; + + scic_sds_controller_post_request(scic, command); +} + +/* + * ****************************************************************************** + * * PORT STATE METHODS + * ****************************************************************************** */ + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped + * state handlers for the struct scic_sds_port object and disables the port task + * scheduler in the hardware. none + */ +static void scic_sds_port_stopped_state_enter(void *object) +{ + struct scic_sds_port *sci_port = object; + + scic_sds_port_set_base_state_handlers( + sci_port, SCI_BASE_PORT_STATE_STOPPED + ); + + if ( + SCI_BASE_PORT_STATE_STOPPING + == sci_port->state_machine.previous_state_id + ) { + /* + * If we enter this state becasuse of a request to stop + * the port then we want to disable the hardwares port + * task scheduler. */ + scic_sds_port_disable_port_task_scheduler(sci_port); + } +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware + * port task scheduler. none + */ +static void scic_sds_port_stopped_state_exit(void *object) +{ + struct scic_sds_port *sci_port = object; + + /* Enable and suspend the port task scheduler */ + scic_sds_port_enable_port_task_scheduler(sci_port); +} + +/** + * scic_sds_port_ready_state_enter - + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state + * handlers for the struct scic_sds_port object, reports the port object as + * not ready and starts the ready substate machine. none + */ +static void scic_sds_port_ready_state_enter(void *object) +{ + struct scic_sds_port *sci_port = object; + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + struct isci_port *iport = sci_port_to_iport(sci_port); + u32 prev_state; + + /* Put the ready state handlers in place though they will not be there long */ + scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_READY); + + prev_state = sci_port->state_machine.previous_state_id; + if (prev_state == SCI_BASE_PORT_STATE_RESETTING) + isci_port_hard_reset_complete(iport, SCI_SUCCESS); + else + isci_port_not_ready(ihost, iport); + + /* Post and suspend the dummy remote node context for this port. */ + scic_sds_port_post_dummy_remote_node(sci_port); + + /* Start the ready substate machine */ + sci_base_state_machine_start(&sci_port->ready_substate_machine); +} + +static void scic_sds_port_ready_state_exit(void *object) +{ + struct scic_sds_port *sci_port = object; + + sci_base_state_machine_stop(&sci_port->ready_substate_machine); + scic_sds_port_invalidate_dummy_remote_node(sci_port); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting + * state handlers for the struct scic_sds_port object. none + */ +static void scic_sds_port_resetting_state_enter(void *object) +{ + struct scic_sds_port *sci_port = object; + + scic_sds_port_set_base_state_handlers( + sci_port, SCI_BASE_PORT_STATE_RESETTING + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This function will perform the actions required by the + * struct scic_sds_port on + * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none + */ +static inline void scic_sds_port_resetting_state_exit(void *object) +{ + struct scic_sds_port *sci_port = object; + + isci_timer_stop(sci_port->timer_handle); +} + +/** + * + * @object: This is the void object which is cast to a + * struct scic_sds_port object. + * + * This method will perform the actions required by the struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping + * state handlers for the struct scic_sds_port object. none + */ +static void scic_sds_port_stopping_state_enter(void *object) +{ + struct scic_sds_port *sci_port = object; + + scic_sds_port_set_base_state_handlers( + sci_port, SCI_BASE_PORT_STATE_STOPPING + ); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This function will perform the actions required by the + * struct scic_sds_port on + * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none + */ +static inline void +scic_sds_port_stopping_state_exit(void *object) +{ + struct scic_sds_port *sci_port = object; + + isci_timer_stop(sci_port->timer_handle); + + scic_sds_port_destroy_dummy_resources(sci_port); +} + +/** + * + * @object: This is the object which is cast to a struct scic_sds_port object. + * + * This function will perform the actions required by the + * struct scic_sds_port on + * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping + * state handlers for the struct scic_sds_port object. none + */ +static void scic_sds_port_failed_state_enter(void *object) +{ + struct scic_sds_port *sci_port = object; + struct isci_port *iport = sci_port_to_iport(sci_port); + + scic_sds_port_set_base_state_handlers(sci_port, + SCI_BASE_PORT_STATE_FAILED); + + isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); +} + +/* --------------------------------------------------------------------------- */ + +static const struct sci_base_state scic_sds_port_state_table[] = { + [SCI_BASE_PORT_STATE_STOPPED] = { + .enter_state = scic_sds_port_stopped_state_enter, + .exit_state = scic_sds_port_stopped_state_exit + }, + [SCI_BASE_PORT_STATE_STOPPING] = { + .enter_state = scic_sds_port_stopping_state_enter, + .exit_state = scic_sds_port_stopping_state_exit + }, + [SCI_BASE_PORT_STATE_READY] = { + .enter_state = scic_sds_port_ready_state_enter, + .exit_state = scic_sds_port_ready_state_exit + }, + [SCI_BASE_PORT_STATE_RESETTING] = { + .enter_state = scic_sds_port_resetting_state_enter, + .exit_state = scic_sds_port_resetting_state_exit + }, + [SCI_BASE_PORT_STATE_FAILED] = { + .enter_state = scic_sds_port_failed_state_enter, + } +}; + +void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, + struct scic_sds_controller *scic) +{ + sci_base_state_machine_construct(&sci_port->state_machine, + sci_port, + scic_sds_port_state_table, + SCI_BASE_PORT_STATE_STOPPED); + + sci_base_state_machine_start(&sci_port->state_machine); + + sci_base_state_machine_construct(&sci_port->ready_substate_machine, + sci_port, + scic_sds_port_ready_substate_table, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + + sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; + sci_port->physical_port_index = index; + sci_port->active_phy_mask = 0; + + sci_port->owning_controller = scic; + + sci_port->started_request_count = 0; + sci_port->assigned_device_count = 0; + + sci_port->reserved_rni = SCU_DUMMY_INDEX; + sci_port->reserved_tci = SCU_DUMMY_INDEX; + + sci_port->timer_handle = NULL; + sci_port->port_task_scheduler_registers = NULL; + + for (index = 0; index < SCI_MAX_PHYS; index++) + sci_port->phy_table[index] = NULL; +} + +void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index) +{ + INIT_LIST_HEAD(&iport->remote_dev_list); + INIT_LIST_HEAD(&iport->domain_dev_list); + spin_lock_init(&iport->state_lock); + init_completion(&iport->start_complete); + iport->isci_host = ihost; + isci_port_change_state(iport, isci_freed); +} + +/** + * isci_port_get_state() - This function gets the status of the port object. + * @isci_port: This parameter points to the isci_port object + * + * status of the object as a isci_status enum. + */ +enum isci_status isci_port_get_state( + struct isci_port *isci_port) +{ + return isci_port->status; +} + +static void isci_port_bc_change_received(struct isci_host *ihost, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + dev_dbg(&ihost->pdev->dev, "%s: iphy = %p, sas_phy = %p\n", + __func__, iphy, &iphy->sas_phy); + + ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); + scic_port_enable_broadcast_change_notification(sci_port); +} + +void scic_sds_port_broadcast_change_received( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + + /* notify the user. */ + isci_port_bc_change_received(ihost, sci_port, sci_phy); +} + +int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, + struct isci_phy *iphy) +{ + unsigned long flags; + enum sci_status status; + int ret = TMF_RESP_FUNC_COMPLETE; + + dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n", + __func__, iport); + + init_completion(&iport->hard_reset_complete); + + spin_lock_irqsave(&ihost->scic_lock, flags); + + #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT + status = scic_port_hard_reset(&iport->sci, ISCI_PORT_RESET_TIMEOUT); + + spin_unlock_irqrestore(&ihost->scic_lock, flags); + + if (status == SCI_SUCCESS) { + wait_for_completion(&iport->hard_reset_complete); + + dev_dbg(&ihost->pdev->dev, + "%s: iport = %p; hard reset completion\n", + __func__, iport); + + if (iport->hard_reset_status != SCI_SUCCESS) + ret = TMF_RESP_FUNC_FAILED; + } else { + ret = TMF_RESP_FUNC_FAILED; + + dev_err(&ihost->pdev->dev, + "%s: iport = %p; scic_port_hard_reset call" + " failed 0x%x\n", + __func__, iport, status); + + } + + /* If the hard reset for the port has failed, consider this + * the same as link failures on all phys in the port. + */ + if (ret != TMF_RESP_FUNC_COMPLETE) { + dev_err(&ihost->pdev->dev, + "%s: iport = %p; hard reset failed " + "(0x%x) - sending link down to libsas for phy %p\n", + __func__, iport, iport->hard_reset_status, iphy); + + isci_port_link_down(ihost, iphy, iport); + } + + return ret; +} + +/** + * isci_port_deformed() - This function is called by libsas when a port becomes + * inactive. + * @phy: This parameter specifies the libsas phy with the inactive port. + * + */ +void isci_port_deformed(struct asd_sas_phy *phy) +{ + pr_debug("%s: sas_phy = %p\n", __func__, phy); +} + +/** + * isci_port_formed() - This function is called by libsas when a port becomes + * active. + * @phy: This parameter specifies the libsas phy with the active port. + * + */ +void isci_port_formed(struct asd_sas_phy *phy) +{ + pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port); } diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 59505cbf2bb3..ea41dcead3ae 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -58,7 +58,10 @@ #include #include "isci.h" -#include "scic_sds_port.h" +#include "sas.h" +#include "phy.h" + +#define SCIC_SDS_DUMMY_PORT 0xFF struct isci_phy; struct isci_host; @@ -72,6 +75,111 @@ enum isci_status { isci_stopped = 0x05, }; +/** + * struct scic_sds_port + * + * The core port object provides the the abstraction for an SCU port. + */ +struct scic_sds_port { + + /** + * This field contains the information for the base port state machine. + */ + struct sci_base_state_machine state_machine; + + /** + * This field is the port index that is reported to the SCI USER. + * This allows the actual hardware physical port to change without + * the SCI USER getting a different answer for the get port index. + */ + u8 logical_port_index; + + /** + * This field is the port index used to program the SCU hardware. + */ + u8 physical_port_index; + + /** + * This field contains the active phy mask for the port. + * This mask is used in conjunction with the phy state to determine + * which phy to select for some port operations. + */ + u8 active_phy_mask; + + u16 reserved_rni; + u16 reserved_tci; + + /** + * This field contains the count of the io requests started on this port + * object. It is used to control controller shutdown. + */ + u32 started_request_count; + + /** + * This field contains the number of devices assigned to this port. + * It is used to control port start requests. + */ + u32 assigned_device_count; + + /** + * This field contains the reason for the port not going ready. It is + * assigned in the state handlers and used in the state transition. + */ + u32 not_ready_reason; + + /** + * This field is the table of phys assigned to the port. + */ + struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; + + /** + * This field is a pointer back to the controller that owns this + * port object. + */ + struct scic_sds_controller *owning_controller; + + /** + * This field contains the port start/stop timer handle. + */ + void *timer_handle; + + /** + * This field points to the current set of state handlers for this port + * object. These state handlers are assigned at each enter state of + * the state machine. + */ + struct scic_sds_port_state_handler *state_handlers; + + /** + * This field is the ready substate machine for the port. + */ + struct sci_base_state_machine ready_substate_machine; + + /* / Memory mapped hardware register space */ + + /** + * This field is the pointer to the port task scheduler registers + * for the SCU hardware. + */ + struct scu_port_task_scheduler_registers __iomem + *port_task_scheduler_registers; + + /** + * This field is identical for all port objects and points to the port + * task scheduler group PE configuration registers. + * It is used to assign PEs to a port. + */ + u32 __iomem *port_pe_configuration_register; + + /** + * This field is the VIIT register space for ths port object. + */ + struct scu_viit_entry __iomem *viit_registers; + +}; + + + /** * struct isci_port - This class represents the port object used to internally * represent libsas port objects. It also keeps a list of remote device @@ -99,54 +207,301 @@ static inline struct isci_port *sci_port_to_iport(struct scic_sds_port *sci_port return iport; } -enum isci_status isci_port_get_state( - struct isci_port *isci_port); +enum scic_port_not_ready_reason_code { + SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, + SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, + SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, + SCIC_PORT_NOT_READY_RECONFIGURING, + + SCIC_PORT_NOT_READY_REASON_CODE_MAX +}; + +struct scic_port_end_point_properties { + struct sci_sas_address sas_address; + struct scic_phy_proto protocols; +}; + +struct scic_port_properties { + u32 index; + struct scic_port_end_point_properties local; + struct scic_port_end_point_properties remote; + u32 phy_mask; +}; + +/** + * enum SCIC_SDS_PORT_READY_SUBSTATES - + * + * This enumeration depicts all of the states for the core port ready substate + * machine. + */ +enum scic_sds_port_ready_substates { + /** + * The substate where the port is started and ready but has no + * active phys. + */ + SCIC_SDS_PORT_READY_SUBSTATE_WAITING, + + /** + * The substate where the port is started and ready and there is + * at least one phy operational. + */ + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, + + /** + * The substate where the port is started and there was an + * add/remove phy event. This state is only used in Automatic + * Port Configuration Mode (APC) + */ + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, + + SCIC_SDS_PORT_READY_MAX_SUBSTATES +}; + +/** + * enum scic_sds_port_states - This enumeration depicts all the states for the + * common port state machine. + * + * + */ +enum scic_sds_port_states { + /** + * This state indicates that the port has successfully been stopped. + * In this state no new IO operations are permitted. + * This state is entered from the STOPPING state. + */ + SCI_BASE_PORT_STATE_STOPPED, + + /** + * This state indicates that the port is in the process of stopping. + * In this state no new IO operations are permitted, but existing IO + * operations are allowed to complete. + * This state is entered from the READY state. + */ + SCI_BASE_PORT_STATE_STOPPING, + + /** + * This state indicates the port is now ready. Thus, the user is + * able to perform IO operations on this port. + * This state is entered from the STARTING state. + */ + SCI_BASE_PORT_STATE_READY, + + /** + * This state indicates the port is in the process of performing a hard + * reset. Thus, the user is unable to perform IO operations on this + * port. + * This state is entered from the READY state. + */ + SCI_BASE_PORT_STATE_RESETTING, + + /** + * This state indicates the port has failed a reset request. This state + * is entered when a port reset request times out. + * This state is entered from the RESETTING state. + */ + SCI_BASE_PORT_STATE_FAILED, + + SCI_BASE_PORT_MAX_STATES + +}; + +struct scic_sds_remote_device; +struct scic_sds_request; + +typedef enum sci_status (*scic_sds_port_handler_t)(struct scic_sds_port *); -void isci_port_formed( - struct asd_sas_phy *); +typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *, + struct scic_sds_phy *); -void isci_port_deformed( - struct asd_sas_phy *); +typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *, + u32 timeout); -void isci_port_bc_change_received( - struct isci_host *isci_host, - struct scic_sds_port *port, - struct scic_sds_phy *phy); +typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32); -void isci_port_link_up( - struct isci_host *isci_host, - struct scic_sds_port *port, - struct scic_sds_phy *phy); +typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, u32); -void isci_port_link_down( - struct isci_host *isci_host, - struct isci_phy *isci_phy, - struct isci_port *port); +typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *); -void isci_port_ready( - struct isci_host *isci_host, +typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_port *, + struct scic_sds_remote_device *, + struct scic_sds_request *); + +struct scic_sds_port_state_handler { + /** + * The start_handler specifies the method invoked when a user + * attempts to start a port. + */ + scic_sds_port_handler_t start_handler; + + /** + * The stop_handler specifies the method invoked when a user + * attempts to stop a port. + */ + scic_sds_port_handler_t stop_handler; + + /** + * The destruct_handler specifies the method invoked when attempting to + * destruct a port. + */ + scic_sds_port_handler_t destruct_handler; + + /** + * The reset_handler specifies the method invoked when a user + * attempts to hard reset a port. + */ + scic_sds_port_reset_handler_t reset_handler; + + /** + * The add_phy_handler specifies the method invoked when a user + * attempts to add another phy into the port. + */ + scic_sds_port_phy_handler_t add_phy_handler; + + /** + * The remove_phy_handler specifies the method invoked when a user + * attempts to remove a phy from the port. + */ + scic_sds_port_phy_handler_t remove_phy_handler; + + scic_sds_port_frame_handler_t frame_handler; + scic_sds_port_event_handler_t event_handler; + + scic_sds_port_link_handler_t link_up_handler; + scic_sds_port_link_handler_t link_down_handler; + + scic_sds_port_io_request_handler_t start_io_handler; + scic_sds_port_io_request_handler_t complete_io_handler; + +}; + +/** + * scic_sds_port_get_controller() - + * + * Helper macro to get the owning controller of this port + */ +#define scic_sds_port_get_controller(this_port) \ + ((this_port)->owning_controller) + +/** + * scic_sds_port_set_base_state_handlers() - + * + * This macro will change the state handlers to those of the specified state id + */ +#define scic_sds_port_set_base_state_handlers(this_port, state_id) \ + scic_sds_port_set_state_handlers(\ + (this_port), &scic_sds_port_state_handler_table[(state_id)]) + +/** + * scic_sds_port_set_state_handlers() - + * + * Helper macro to set the port object state handlers + */ +#define scic_sds_port_set_state_handlers(this_port, handlers) \ + ((this_port)->state_handlers = (handlers)) + +/** + * scic_sds_port_get_index() - + * + * This macro returns the physical port index for this port object + */ +#define scic_sds_port_get_index(this_port) \ + ((this_port)->physical_port_index) + + +static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) +{ + if (WARN_ONCE(sci_port->started_request_count == 0, + "%s: tried to decrement started_request_count past 0!?", + __func__)) + /* pass */; + else + sci_port->started_request_count--; +} + +#define scic_sds_port_active_phy(port, phy) \ + (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) + +void scic_sds_port_construct( + struct scic_sds_port *sci_port, + u8 port_index, + struct scic_sds_controller *scic); + +enum sci_status scic_sds_port_initialize( + struct scic_sds_port *sci_port, + void __iomem *port_task_scheduler_registers, + void __iomem *port_configuration_regsiter, + void __iomem *viit_registers); + +enum sci_status scic_sds_port_add_phy( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +enum sci_status scic_sds_port_remove_phy( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +void scic_sds_port_setup_transports( + struct scic_sds_port *sci_port, + u32 device_id); + + +void scic_sds_port_deactivate_phy( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy, + bool do_notify_user); + +bool scic_sds_port_link_detected( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +void scic_sds_port_link_up( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +void scic_sds_port_link_down( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +enum sci_status scic_sds_port_start_io( + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req); + +enum sci_status scic_sds_port_complete_io( + struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req); + +enum sas_linkrate scic_sds_port_get_max_allowed_speed( + struct scic_sds_port *sci_port); + +void scic_sds_port_broadcast_change_received( + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); + +bool scic_sds_port_is_valid_phy_assignment( + struct scic_sds_port *sci_port, + u32 phy_index); + +void scic_sds_port_get_sas_address( + struct scic_sds_port *sci_port, + struct sci_sas_address *sas_address); + +void scic_sds_port_get_attached_sas_address( + struct scic_sds_port *sci_port, + struct sci_sas_address *sas_address); + +enum isci_status isci_port_get_state( struct isci_port *isci_port); -void isci_port_not_ready( - struct isci_host *isci_host, - struct isci_port *port); +void isci_port_formed(struct asd_sas_phy *); +void isci_port_deformed(struct asd_sas_phy *); void isci_port_init( struct isci_port *port, struct isci_host *host, int index); -void isci_port_hard_reset_complete( - struct isci_port *isci_port, - enum sci_status completion_status); - int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy); - -void isci_port_stop_complete( - struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, - enum sci_status completion_status); - #endif /* !defined(_ISCI_PORT_H_) */ - diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c new file mode 100644 index 000000000000..028ffa370c90 --- /dev/null +++ b/drivers/scsi/isci/port_config.c @@ -0,0 +1,826 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "host.h" +#include "timers.h" + +#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) +#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) +#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100) + +enum SCIC_SDS_APC_ACTIVITY { + SCIC_SDS_APC_SKIP_PHY, + SCIC_SDS_APC_ADD_PHY, + SCIC_SDS_APC_START_TIMER, + + SCIC_SDS_APC_ACTIVITY_MAX +}; + +/* + * ****************************************************************************** + * General port configuration agent routines + * ****************************************************************************** */ + +/** + * + * @address_one: A SAS Address to be compared. + * @address_two: A SAS Address to be compared. + * + * Compare the two SAS Address and if SAS Address One is greater than SAS + * Address Two then return > 0 else if SAS Address One is less than SAS Address + * Two return < 0 Otherwise they are the same return 0 A signed value of x > 0 + * > y where x is returned for Address One > Address Two y is returned for + * Address One < Address Two 0 is returned ofr Address One = Address Two + */ +static s32 sci_sas_address_compare( + struct sci_sas_address address_one, + struct sci_sas_address address_two) +{ + if (address_one.high > address_two.high) { + return 1; + } else if (address_one.high < address_two.high) { + return -1; + } else if (address_one.low > address_two.low) { + return 1; + } else if (address_one.low < address_two.low) { + return -1; + } + + /* The two SAS Address must be identical */ + return 0; +} + +/** + * + * @controller: The controller object used for the port search. + * @phy: The phy object to match. + * + * This routine will find a matching port for the phy. This means that the + * port and phy both have the same broadcast sas address and same received sas + * address. The port address or the NULL if there is no matching + * port. port address if the port can be found to match the phy. + * NULL if there is no matching port for the phy. + */ +static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( + struct scic_sds_controller *scic, + struct scic_sds_phy *phy) +{ + u8 i; + struct sci_sas_address port_sas_address; + struct sci_sas_address port_attached_device_address; + struct sci_sas_address phy_sas_address; + struct sci_sas_address phy_attached_device_address; + + /* + * Since this phy can be a member of a wide port check to see if one or + * more phys match the sent and received SAS address as this phy in which + * case it should participate in the same port. + */ + scic_sds_phy_get_sas_address(phy, &phy_sas_address); + scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); + + for (i = 0; i < scic->logical_port_entries; i++) { + struct isci_host *ihost = scic_to_ihost(scic); + struct scic_sds_port *sci_port = &ihost->ports[i].sci; + + scic_sds_port_get_sas_address(sci_port, &port_sas_address); + scic_sds_port_get_attached_sas_address(sci_port, &port_attached_device_address); + + if (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0 && + sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) + return sci_port; + } + + return NULL; +} + +/** + * + * @controller: This is the controller object that contains the port agent + * @port_agent: This is the port configruation agent for the controller. + * + * This routine will validate the port configuration is correct for the SCU + * hardware. The SCU hardware allows for port configurations as follows. LP0 + * -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2, + * PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for + * this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION + * the port configuration is not valid for this port configuration agent. + */ +static enum sci_status scic_sds_port_configuration_agent_validate_ports( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent) +{ + struct isci_host *ihost = scic_to_ihost(controller); + struct sci_sas_address first_address; + struct sci_sas_address second_address; + + /* + * Sanity check the max ranges for all the phys the max index + * is always equal to the port range index */ + if (port_agent->phy_valid_port_range[0].max_index != 0 || + port_agent->phy_valid_port_range[1].max_index != 1 || + port_agent->phy_valid_port_range[2].max_index != 2 || + port_agent->phy_valid_port_range[3].max_index != 3) + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + + /* + * This is a request to configure a single x4 port or at least attempt + * to make all the phys into a single port */ + if (port_agent->phy_valid_port_range[0].min_index == 0 && + port_agent->phy_valid_port_range[1].min_index == 0 && + port_agent->phy_valid_port_range[2].min_index == 0 && + port_agent->phy_valid_port_range[3].min_index == 0) + return SCI_SUCCESS; + + /* + * This is a degenerate case where phy 1 and phy 2 are assigned + * to the same port this is explicitly disallowed by the hardware + * unless they are part of the same x4 port and this condition was + * already checked above. */ + if (port_agent->phy_valid_port_range[2].min_index == 1) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + /* + * PE0 and PE3 can never have the same SAS Address unless they + * are part of the same x4 wide port and we have already checked + * for this condition. */ + scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address); + + if (sci_sas_address_compare(first_address, second_address) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + /* + * PE0 and PE1 are configured into a 2x1 ports make sure that the + * SAS Address for PE0 and PE2 are different since they can not be + * part of the same port. */ + if (port_agent->phy_valid_port_range[0].min_index == 0 && + port_agent->phy_valid_port_range[1].min_index == 1) { + scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[2].sci, &second_address); + + if (sci_sas_address_compare(first_address, second_address) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + } + + /* + * PE2 and PE3 are configured into a 2x1 ports make sure that the + * SAS Address for PE1 and PE3 are different since they can not be + * part of the same port. */ + if (port_agent->phy_valid_port_range[2].min_index == 2 && + port_agent->phy_valid_port_range[3].min_index == 3) { + scic_sds_phy_get_sas_address(&ihost->phys[1].sci, &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address); + + if (sci_sas_address_compare(first_address, second_address) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + } + + return SCI_SUCCESS; +} + +/* + * ****************************************************************************** + * Manual port configuration agent routines + * ****************************************************************************** */ + +/** + * + * + * This routine will verify that all of the phys in the same port are using the + * same SAS address. + */ +static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent) +{ + struct isci_host *ihost = scic_to_ihost(controller); + u32 phy_mask; + u32 assigned_phy_mask; + struct sci_sas_address sas_address; + struct sci_sas_address phy_assigned_address; + u8 port_index; + u8 phy_index; + + assigned_phy_mask = 0; + sas_address.high = 0; + sas_address.low = 0; + + for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { + phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask; + + if (!phy_mask) + continue; + /* + * Make sure that one or more of the phys were not already assinged to + * a different port. */ + if ((phy_mask & ~assigned_phy_mask) == 0) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + /* Find the starting phy index for this round through the loop */ + for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { + if ((phy_mask & (1 << phy_index)) == 0) + continue; + scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + &sas_address); + + /* + * The phy_index can be used as the starting point for the + * port range since the hardware starts all logical ports + * the same as the PE index. */ + port_agent->phy_valid_port_range[phy_index].min_index = port_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + + if (phy_index != port_index) { + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + break; + } + + /* + * See how many additional phys are being added to this logical port. + * Note: We have not moved the current phy_index so we will actually + * compare the startting phy with itself. + * This is expected and required to add the phy to the port. */ + while (phy_index < SCI_MAX_PHYS) { + if ((phy_mask & (1 << phy_index)) == 0) + continue; + scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + &phy_assigned_address); + + if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { + /* + * The phy mask specified that this phy is part of the same port + * as the starting phy and it is not so fail this configuration */ + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + port_agent->phy_valid_port_range[phy_index].min_index = port_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + + scic_sds_port_add_phy(&ihost->ports[port_index].sci, + &ihost->phys[phy_index].sci); + + assigned_phy_mask |= (1 << phy_index); + } + + phy_index++; + } + + return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); +} + +/** + * + * + * This timer routine is used to allow the SCI User to rediscover or change + * device objects before a new series of link up notifications because a link + * down has allowed a better port configuration. + */ +static void scic_sds_mpc_agent_timeout_handler(void *object) +{ + u8 index; + struct scic_sds_controller *scic = object; + struct isci_host *ihost = scic_to_ihost(scic); + struct scic_sds_port_configuration_agent *port_agent = &scic->port_agent; + u16 configure_phy_mask; + + port_agent->timer_pending = false; + + /* Find the mask of phys that are reported read but as yet unconfigured into a port */ + configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + struct scic_sds_phy *sci_phy = &ihost->phys[index].sci; + + if (configure_phy_mask & (1 << index)) { + port_agent->link_up_handler(scic, port_agent, + scic_sds_phy_get_port(sci_phy), + sci_phy); + } + } +} + +/** + * + * @controller: This is the controller object that receives the link up + * notification. + * @port: This is the port object associated with the phy. If the is no + * associated port this is an NULL. + * @phy: This is the phy object which has gone ready. + * + * This method handles the manual port configuration link up notifications. + * Since all ports and phys are associate at initialization time we just turn + * around and notifiy the port object that there is a link up. If this PHY is + * not associated with a port there is no action taken. Is it possible to get a + * link up notification from a phy that has no assocoated port? + */ +static void scic_sds_mpc_agent_link_up( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + /* + * If the port has an invalid handle then the phy was not assigned to + * a port. This is because the phy was not given the same SAS Address + * as the other PHYs in the port. */ + if (port != NULL) { + port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); + + scic_sds_port_link_up(port, phy); + + if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0) { + port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy)); + } + } +} + +/** + * + * @controller: This is the controller object that receives the link down + * notification. + * @port: This is the port object associated with the phy. If the is no + * associated port this is an NULL. The port is an invalid + * handle only if the phy was never port of this port. This happens when + * the phy is not broadcasting the same SAS address as the other phys in the + * assigned port. + * @phy: This is the phy object which has gone link down. + * + * This function handles the manual port configuration link down notifications. + * Since all ports and phys are associated at initialization time we just turn + * around and notifiy the port object of the link down event. If this PHY is + * not associated with a port there is no action taken. Is it possible to get a + * link down notification from a phy that has no assocoated port? + */ +static void scic_sds_mpc_agent_link_down( + struct scic_sds_controller *scic, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + if (sci_port != NULL) { + /* + * If we can form a new port from the remainder of the phys + * then we want to start the timer to allow the SCI User to + * cleanup old devices and rediscover the port before + * rebuilding the port with the phys that remain in the ready + * state. + */ + port_agent->phy_ready_mask &= + ~(1 << scic_sds_phy_get_index(sci_phy)); + port_agent->phy_configured_mask &= + ~(1 << scic_sds_phy_get_index(sci_phy)); + + /* + * Check to see if there are more phys waiting to be + * configured into a port. If there are allow the SCI User + * to tear down this port, if necessary, and then reconstruct + * the port after the timeout. + */ + if ((port_agent->phy_configured_mask == 0x0000) && + (port_agent->phy_ready_mask != 0x0000) && + !port_agent->timer_pending) { + port_agent->timer_pending = true; + + isci_timer_start(port_agent->timer, + SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT); + } + + scic_sds_port_link_down(sci_port, sci_phy); + } +} + +/* + * ****************************************************************************** + * Automatic port configuration agent routines + * ****************************************************************************** */ + +/** + * + * + * This routine will verify that the phys are assigned a valid SAS address for + * automatic port configuration mode. + */ +static enum sci_status scic_sds_apc_agent_validate_phy_configuration( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent) +{ + u8 phy_index; + u8 port_index; + struct sci_sas_address sas_address; + struct sci_sas_address phy_assigned_address; + struct isci_host *ihost = scic_to_ihost(controller); + + phy_index = 0; + + while (phy_index < SCI_MAX_PHYS) { + port_index = phy_index; + + /* Get the assigned SAS Address for the first PHY on the controller. */ + scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + &sas_address); + + while (++phy_index < SCI_MAX_PHYS) { + scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + &phy_assigned_address); + + /* Verify each of the SAS address are all the same for every PHY */ + if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) { + port_agent->phy_valid_port_range[phy_index].min_index = port_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + } else { + port_agent->phy_valid_port_range[phy_index].min_index = phy_index; + port_agent->phy_valid_port_range[phy_index].max_index = phy_index; + break; + } + } + } + + return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); +} + +/** + * + * @controller: This is the controller that to which the port agent is assigned. + * @port_agent: This is the port agent that is requesting the timer start + * operation. + * @phy: This is the phy that has caused the timer operation to be scheduled. + * + * This routine will restart the automatic port configuration timeout timer for + * the next time period. This could be caused by either a link down event or a + * link up event where we can not yet tell to which port a phy belongs. + */ +static inline void scic_sds_apc_agent_start_timer( + struct scic_sds_controller *scic, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_phy *sci_phy, + u32 timeout) +{ + if (port_agent->timer_pending) + isci_timer_stop(port_agent->timer); + + port_agent->timer_pending = true; + + isci_timer_start(port_agent->timer, timeout); +} + +/** + * + * @controller: This is the controller object that receives the link up + * notification. + * @phy: This is the phy object which has gone link up. + * + * This method handles the automatic port configuration for link up + * notifications. + */ +static void scic_sds_apc_agent_configure_ports( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_phy *phy, + bool start_timer) +{ + u8 port_index; + enum sci_status status; + struct scic_sds_port *port; + enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; + struct isci_host *ihost = scic_to_ihost(controller); + + port = scic_sds_port_configuration_agent_find_port(controller, phy); + + if (port != NULL) { + if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) + apc_activity = SCIC_SDS_APC_ADD_PHY; + else + apc_activity = SCIC_SDS_APC_SKIP_PHY; + } else { + /* + * There is no matching Port for this PHY so lets search through the + * Ports and see if we can add the PHY to its own port or maybe start + * the timer and wait to see if a wider port can be made. + * + * Note the break when we reach the condition of the port id == phy id */ + for ( + port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index; + port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index; + port_index++ + ) { + + port = &ihost->ports[port_index].sci; + + /* First we must make sure that this PHY can be added to this Port. */ + if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) { + /* + * Port contains a PHY with a greater PHY ID than the current + * PHY that has gone link up. This phy can not be part of any + * port so skip it and move on. */ + if (port->active_phy_mask > (1 << phy->phy_index)) { + apc_activity = SCIC_SDS_APC_SKIP_PHY; + break; + } + + /* + * We have reached the end of our Port list and have not found + * any reason why we should not either add the PHY to the port + * or wait for more phys to become active. */ + if (port->physical_port_index == phy->phy_index) { + /* + * The Port either has no active PHYs. + * Consider that if the port had any active PHYs we would have + * or active PHYs with + * a lower PHY Id than this PHY. */ + if (apc_activity != SCIC_SDS_APC_START_TIMER) { + apc_activity = SCIC_SDS_APC_ADD_PHY; + } + + break; + } + + /* + * The current Port has no active PHYs and this PHY could be part + * of this Port. Since we dont know as yet setup to start the + * timer and see if there is a better configuration. */ + if (port->active_phy_mask == 0) { + apc_activity = SCIC_SDS_APC_START_TIMER; + } + } else if (port->active_phy_mask != 0) { + /* + * The Port has an active phy and the current Phy can not + * participate in this port so skip the PHY and see if + * there is a better configuration. */ + apc_activity = SCIC_SDS_APC_SKIP_PHY; + } + } + } + + /* + * Check to see if the start timer operations should instead map to an + * add phy operation. This is caused because we have been waiting to + * add a phy to a port but could not becuase the automatic port + * configuration engine had a choice of possible ports for the phy. + * Since we have gone through a timeout we are going to restrict the + * choice to the smallest possible port. */ + if ( + (start_timer == false) + && (apc_activity == SCIC_SDS_APC_START_TIMER) + ) { + apc_activity = SCIC_SDS_APC_ADD_PHY; + } + + switch (apc_activity) { + case SCIC_SDS_APC_ADD_PHY: + status = scic_sds_port_add_phy(port, phy); + + if (status == SCI_SUCCESS) { + port_agent->phy_configured_mask |= (1 << phy->phy_index); + } + break; + + case SCIC_SDS_APC_START_TIMER: + scic_sds_apc_agent_start_timer( + controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION + ); + break; + + case SCIC_SDS_APC_SKIP_PHY: + default: + /* do nothing the PHY can not be made part of a port at this time. */ + break; + } +} + +/** + * scic_sds_apc_agent_link_up - handle apc link up events + * @scic: This is the controller object that receives the link up + * notification. + * @sci_port: This is the port object associated with the phy. If the is no + * associated port this is an NULL. + * @sci_phy: This is the phy object which has gone link up. + * + * This method handles the automatic port configuration for link up + * notifications. Is it possible to get a link down notification from a phy + * that has no assocoated port? + */ +static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + u8 phy_index = sci_phy->phy_index; + + if (!sci_port) { + /* the phy is not the part of this port */ + port_agent->phy_ready_mask |= 1 << phy_index; + scic_sds_apc_agent_configure_ports(scic, port_agent, sci_phy, true); + } else { + /* the phy is already the part of the port */ + u32 port_state = sci_port->state_machine.current_state_id; + + /* if the PORT'S state is resetting then the link up is from + * port hard reset in this case, we need to tell the port + * that link up is recieved + */ + BUG_ON(port_state != SCI_BASE_PORT_STATE_RESETTING); + port_agent->phy_ready_mask |= 1 << phy_index; + scic_sds_port_link_up(sci_port, sci_phy); + } +} + +/** + * + * @controller: This is the controller object that receives the link down + * notification. + * @port: This is the port object associated with the phy. If the is no + * associated port this is an NULL. + * @phy: This is the phy object which has gone link down. + * + * This method handles the automatic port configuration link down + * notifications. not associated with a port there is no action taken. Is it + * possible to get a link down notification from a phy that has no assocoated + * port? + */ +static void scic_sds_apc_agent_link_down( + struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *port, + struct scic_sds_phy *phy) +{ + port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); + + if (port != NULL) { + if (port_agent->phy_configured_mask & (1 << phy->phy_index)) { + enum sci_status status; + + status = scic_sds_port_remove_phy(port, phy); + + if (status == SCI_SUCCESS) { + port_agent->phy_configured_mask &= ~(1 << phy->phy_index); + } + } + } +} + +/* configure the phys into ports when the timer fires */ +static void scic_sds_apc_agent_timeout_handler(void *object) +{ + u32 index; + struct scic_sds_port_configuration_agent *port_agent; + struct scic_sds_controller *scic = object; + struct isci_host *ihost = scic_to_ihost(scic); + u16 configure_phy_mask; + + port_agent = scic_sds_controller_get_port_configuration_agent(scic); + + port_agent->timer_pending = false; + + configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; + + if (!configure_phy_mask) + return; + + for (index = 0; index < SCI_MAX_PHYS; index++) { + if ((configure_phy_mask & (1 << index)) == 0) + continue; + + scic_sds_apc_agent_configure_ports(scic, port_agent, + &ihost->phys[index].sci, false); + } +} + +/* + * ****************************************************************************** + * Public port configuration agent routines + * ****************************************************************************** */ + +/** + * + * + * This method will construct the port configuration agent for operation. This + * call is universal for both manual port configuration and automatic port + * configuration modes. + */ +void scic_sds_port_configuration_agent_construct( + struct scic_sds_port_configuration_agent *port_agent) +{ + u32 index; + + port_agent->phy_configured_mask = 0x00; + port_agent->phy_ready_mask = 0x00; + + port_agent->link_up_handler = NULL; + port_agent->link_down_handler = NULL; + + port_agent->timer_pending = false; + port_agent->timer = NULL; + + for (index = 0; index < SCI_MAX_PORTS; index++) { + port_agent->phy_valid_port_range[index].min_index = 0; + port_agent->phy_valid_port_range[index].max_index = 0; + } +} + +enum sci_status scic_sds_port_configuration_agent_initialize( + struct scic_sds_controller *scic, + struct scic_sds_port_configuration_agent *port_agent) +{ + enum sci_status status = SCI_SUCCESS; + enum scic_port_configuration_mode mode; + struct isci_host *ihost = scic_to_ihost(scic); + + mode = scic->oem_parameters.sds1.controller.mode_type; + + if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { + status = scic_sds_mpc_agent_validate_phy_configuration( + scic, port_agent); + + port_agent->link_up_handler = scic_sds_mpc_agent_link_up; + port_agent->link_down_handler = scic_sds_mpc_agent_link_down; + + port_agent->timer = isci_timer_create( + ihost, + scic, + scic_sds_mpc_agent_timeout_handler); + } else { + status = scic_sds_apc_agent_validate_phy_configuration( + scic, port_agent); + + port_agent->link_up_handler = scic_sds_apc_agent_link_up; + port_agent->link_down_handler = scic_sds_apc_agent_link_down; + + port_agent->timer = isci_timer_create( + ihost, + scic, + scic_sds_apc_agent_timeout_handler); + } + + /* Make sure we have actually gotten a timer */ + if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) { + dev_err(scic_to_dev(scic), + "%s: Controller 0x%p automatic port configuration " + "agent could not get timer.\n", + __func__, + scic); + + status = SCI_FAILURE; + } + + return status; +} diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index f4ef19ac281c..7e3e6d7a0a47 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -60,15 +60,117 @@ #include #include "isci.h" -struct isci_orom *isci_request_oprom(struct pci_dev *pdev); +#define SCIC_SDS_PARM_NO_SPEED 0 + +/* generation 1 (i.e. 1.5 Gb/s) */ +#define SCIC_SDS_PARM_GEN1_SPEED 1 + +/* generation 2 (i.e. 3.0 Gb/s) */ +#define SCIC_SDS_PARM_GEN2_SPEED 2 + +/* generation 3 (i.e. 6.0 Gb/s) */ +#define SCIC_SDS_PARM_GEN3_SPEED 3 +#define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED + +/* parameters that can be set by module parameters */ +struct scic_sds_user_parameters { + struct sci_phy_user_params { + /** + * This field specifies the NOTIFY (ENABLE SPIN UP) primitive + * insertion frequency for this phy index. + */ + u32 notify_enable_spin_up_insertion_frequency; + + /** + * This method specifies the number of transmitted DWORDs within which + * to transmit a single ALIGN primitive. This value applies regardless + * of what type of device is attached or connection state. A value of + * 0 indicates that no ALIGN primitives will be inserted. + */ + u16 align_insertion_frequency; + + /** + * This method specifies the number of transmitted DWORDs within which + * to transmit 2 ALIGN primitives. This applies for SAS connections + * only. A minimum value of 3 is required for this field. + */ + u16 in_connection_align_insertion_frequency; + + /** + * This field indicates the maximum speed generation to be utilized + * by phys in the supplied port. + * - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s). + * - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s). + * - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s). + */ + u8 max_speed_generation; + + } phys[SCI_MAX_PHYS]; + + /** + * This field specifies the maximum number of direct attached devices + * that can have power supplied to them simultaneously. + */ + u8 max_number_concurrent_device_spin_up; + + /** + * This field specifies the number of seconds to allow a phy to consume + * power before yielding to another phy. + * + */ + u8 phy_spin_up_delay_interval; + + /** + * These timer values specifies how long a link will remain open with no + * activity in increments of a microsecond, it can be in increments of + * 100 microseconds if the upper most bit is set. + * + */ + u16 stp_inactivity_timeout; + u16 ssp_inactivity_timeout; + + /** + * These timer values specifies how long a link will remain open in increments + * of 100 microseconds. + * + */ + u16 stp_max_occupancy_timeout; + u16 ssp_max_occupancy_timeout; + + /** + * This timer value specifies how long a link will remain open with no + * outbound traffic in increments of a microsecond. + * + */ + u8 no_outbound_task_timeout; + +}; + +/* XXX kill this union */ +union scic_user_parameters { + /** + * This field specifies the user parameters specific to the + * Storage Controller Unit (SCU) Driver Standard (SDS) version + * 1. + */ + struct scic_sds_user_parameters sds1; +}; + +#define SCIC_SDS_PARM_PHY_MASK_MIN 0x0 +#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF +#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4 + +struct scic_sds_oem_params; +int scic_oem_parameters_validate(struct scic_sds_oem_params *oem); union scic_oem_parameters; -struct isci_orom; +void scic_oem_parameters_get(struct scic_sds_controller *scic, + union scic_oem_parameters *oem); -enum sci_status isci_parse_oem_parameters( - union scic_oem_parameters *oem_params, - struct isci_orom *orom, - int scu_index); +struct isci_orom; +struct isci_orom *isci_request_oprom(struct pci_dev *pdev); +enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem, + struct isci_orom *orom, int scu_index); struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); @@ -153,6 +255,16 @@ struct scic_sds_oem_params { } phys[SCI_MAX_PHYS]; } __attribute__ ((packed)); +/* XXX kill this union */ +union scic_oem_parameters { + /** + * This field specifies the OEM parameters specific to the + * Storage Controller Unit (SCU) Driver Standard (SDS) version + * 1. + */ + struct scic_sds_oem_params sds1; +}; + struct isci_orom { struct sci_bios_oem_param_block_hdr hdr; struct scic_sds_oem_params ctrl[SCI_MAX_CONTROLLERS]; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 2baa215cb275..0bb639dfbada 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -57,8 +57,6 @@ #include "port.h" #include "remote_device.h" #include "request.h" -#include "scic_port.h" -#include "scic_sds_port.h" #include "remote_node_context.h" #include "scu_event_codes.h" #include "task.h" diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 35231e7407b1..aef258b959f8 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -55,7 +55,6 @@ #include "host.h" #include "state_machine.h" -#include "scic_sds_port.h" #include "remote_device.h" #include "remote_node_context.h" #include "scu_event_codes.h" diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 857ad067f11c..48e2dac72528 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -54,7 +54,6 @@ */ #include "isci.h" -#include "scic_port.h" #include "task.h" #include "request.h" #include "sata.h" -- cgit v1.2.3 From f139303d17c47eff4c5b5407dee0a6d43e8fd146 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 May 2011 02:28:47 -0700 Subject: isci: merge ssp task management substates into primary state machine Remove usage of the request substate machine for ssp task management requests identified by: ireq->ttype == tmf_task && dev->dev_type == SAS_END_DEV; The only routine that checks the base 'started' state is scic_sds_io_request_tc_completion which calls the substate machine handler if we are not in the 'started' state or we are 'started' and no substate machine is defined. This routine requires no conversion because we have transitioned out of 'started' and the substate routine will be called naturally as a result. There are also no side effects of this conversion on exiting the 'started', state because it only stops the substate machine, which is no longer relevant for this transaction type. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 1 - drivers/scsi/isci/request.c | 185 +++++++++++++++++++++++++++---- drivers/scsi/isci/request.h | 38 +++---- drivers/scsi/isci/ssp_request.c | 240 ---------------------------------------- 4 files changed, 178 insertions(+), 286 deletions(-) delete mode 100644 drivers/scsi/isci/ssp_request.c diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 48218ca908fe..43d2c050bd49 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -7,6 +7,5 @@ isci-objs := init.o phy.o request.o sata.o \ remote_node_table.o \ unsolicited_frame_control.o \ stp_request.o \ - ssp_request.o \ smp_request.o \ port_config.o \ diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 48e2dac72528..5f5168110556 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -656,7 +656,7 @@ enum sci_status scic_sds_io_request_frame_handler( * @sci_req: This parameter specifies the request object for which to copy * the response data. */ -void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) +static void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) { void *resp_buf; u32 len; @@ -978,7 +978,6 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completi sci_base_state_machine_get_state(&request->state_machine)); return SCI_FAILURE_INVALID_STATE; - } /* @@ -1151,9 +1150,119 @@ static enum sci_status scic_sds_request_aborting_state_frame_handler( return SCI_SUCCESS; } +/** + * This method processes the completions transport layer (TL) status to + * determine if the RAW task management frame was sent successfully. If the + * raw frame was sent successfully, then the state for the task request + * transitions to waiting for a response frame. + * @sci_req: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + SCI_SUCCESS); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): + /* + * Currently, the decision is to simply allow the task request to + * timeout if the task IU wasn't received successfully. + * There is a potential for receiving multiple task responses if we + * decide to send the task IU again. */ + dev_warn(scic_to_dev(sci_req->owning_controller), + "%s: TaskRequest:0x%p CompletionCode:%x - " + "ACK/NAK timeout\n", + __func__, + sci_req, + completion_code); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + +/** + * This method is responsible for processing a terminate/abort request for this + * TC while the request is waiting for the task management response + * unsolicited frame. + * @sci_req: This parameter specifies the request for which the + * termination was requested. + * + * This method returns an indication as to whether the abort request was + * successfully handled. need to update to ensure the received UF doesn't cause + * damage to subsequent requests (i.e. put the extended tag in a holding + * pattern for this particular device). + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( + struct scic_sds_request *request) +{ + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_ABORTING); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + return SCI_SUCCESS; +} + +/** + * This method processes an unsolicited frame while the task mgmt request is + * waiting for a response frame. It will copy the response data, release + * the unsolicited frame, and transition the request to the + * SCI_BASE_REQUEST_STATE_COMPLETED state. + * @sci_req: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This method returns an indication of whether the TC response frame was + * handled successfully or not. SCI_SUCCESS Currently this value is always + * returned and indicates successful processing of the TC response. Should + * probably update to check frame type and make sure it is a response frame. + */ +static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( + struct scic_sds_request *request, + u32 frame_index) +{ + scic_sds_io_request_copy_response(request); + + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + scic_sds_controller_release_frame(request->owning_controller, + frame_index); + return SCI_SUCCESS; +} + static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { - [SCI_BASE_REQUEST_STATE_INITIAL] = { - }, + [SCI_BASE_REQUEST_STATE_INITIAL] = { }, [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { .start_handler = scic_sds_request_constructed_state_start_handler, .abort_handler = scic_sds_request_constructed_state_abort_handler, @@ -1163,6 +1272,14 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, .frame_handler = scic_sds_request_started_state_frame_handler, }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, + }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { + .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, + .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, + }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .complete_handler = scic_sds_request_completed_state_complete_handler, }, @@ -1171,8 +1288,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, .frame_handler = scic_sds_request_aborting_state_frame_handler, }, - [SCI_BASE_REQUEST_STATE_FINAL] = { - }, + [SCI_BASE_REQUEST_STATE_FINAL] = { }, }; @@ -1919,6 +2035,9 @@ static void scic_sds_request_constructed_state_enter(void *object) static void scic_sds_request_started_state_enter(void *object) { struct scic_sds_request *sci_req = object; + struct sci_base_state_machine *sm = &sci_req->state_machine; + struct isci_request *ireq = sci_req_to_ireq(sci_req); + struct domain_device *dev = sci_dev_to_domain(sci_req->target_device); SET_STATE_HANDLER( sci_req, @@ -1926,9 +2045,13 @@ static void scic_sds_request_started_state_enter(void *object) SCI_BASE_REQUEST_STATE_STARTED ); - /* - * Most of the request state machines have a started substate machine so - * start its execution on the entry to the started state. */ + if (ireq->ttype == tmf_task && dev->dev_type == SAS_END_DEV) + sci_base_state_machine_change_state(sm, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION); + + /* Most of the request state machines have a started substate machine so + * start its execution on the entry to the started state. + */ if (sci_req->has_started_substate_machine == true) sci_base_state_machine_start(&sci_req->started_substate_machine); } @@ -2026,6 +2149,30 @@ static void scic_sds_request_final_state_enter(void *object) ); } +static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION + ); +} + +static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE + ); +} + static const struct sci_base_state scic_sds_request_state_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { .enter_state = scic_sds_request_initial_state_enter, @@ -2037,6 +2184,12 @@ static const struct sci_base_state scic_sds_request_state_table[] = { .enter_state = scic_sds_request_started_state_enter, .exit_state = scic_sds_request_started_state_exit }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { + .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, + }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { + .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, + }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .enter_state = scic_sds_request_completed_state_enter, }, @@ -2126,19 +2279,9 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, /* Build the common part of the request */ scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); - if (dev->dev_type == SAS_END_DEV) { + if (dev->dev_type == SAS_END_DEV) scic_sds_ssp_task_request_assign_buffers(sci_req); - - sci_req->has_started_substate_machine = true; - - /* Construct the started sub-state machine. */ - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - sci_req, - scic_sds_io_request_started_task_mgmt_substate_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION - ); - } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) + else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) scic_sds_stp_request_assign_buffers(sci_req); else status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 932ea767c8c2..b5c5b063a369 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -295,6 +295,20 @@ enum sci_base_request_states { */ SCI_BASE_REQUEST_STATE_STARTED, + /** + * The AWAIT_TC_COMPLETION sub-state indicates that the started raw + * task management request is waiting for the transmission of the + * initial frame (i.e. command, task, etc.). + */ + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, + + /** + * This sub-state indicates that the started task management request + * is waiting for the reception of an unsolicited frame + * (i.e. response IU). + */ + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, + /** * This state indicates that the request has completed. * This state is entered from the STARTED state. This state is entered from @@ -451,7 +465,6 @@ void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req); void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req); enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); -void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, u32 event_code); enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, @@ -459,29 +472,6 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req); enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); -/** - * enum _scic_sds_io_request_started_task_mgmt_substates - This enumeration - * depicts all of the substates for a task management request to be - * performed in the STARTED super-state. - * - * - */ -enum scic_sds_raw_request_started_task_mgmt_substates { - /** - * The AWAIT_TC_COMPLETION sub-state indicates that the started raw - * task management request is waiting for the transmission of the - * initial frame (i.e. command, task, etc.). - */ - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, - - /** - * This sub-state indicates that the started task management request - * is waiting for the reception of an unsolicited frame - * (i.e. response IU). - */ - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, -}; - /** * enum _scic_sds_smp_request_started_substates - This enumeration depicts all diff --git a/drivers/scsi/isci/ssp_request.c b/drivers/scsi/isci/ssp_request.c deleted file mode 100644 index 4b6317aeef7d..000000000000 --- a/drivers/scsi/isci/ssp_request.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "host.h" -#include "request.h" -#include "state_machine.h" -#include "scu_task_context.h" -#include "scu_completion_codes.h" - -/** - * This method processes the completions transport layer (TL) status to - * determine if the RAW task management frame was sent successfully. If the - * raw frame was sent successfully, then the state for the task request - * transitions to waiting for a response frame. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE - ); - break; - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): - /* - * Currently, the decision is to simply allow the task request to - * timeout if the task IU wasn't received successfully. - * There is a potential for receiving multiple task responses if we - * decide to send the task IU again. */ - dev_warn(scic_to_dev(sci_req->owning_controller), - "%s: TaskRequest:0x%p CompletionCode:%x - " - "ACK/NAK timeout\n", - __func__, - sci_req, - completion_code); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - -/** - * This method is responsible for processing a terminate/abort request for this - * TC while the request is waiting for the task management response - * unsolicited frame. - * @sci_req: This parameter specifies the request for which the - * termination was requested. - * - * This method returns an indication as to whether the abort request was - * successfully handled. need to update to ensure the received UF doesn't cause - * damage to subsequent requests (i.e. put the extended tag in a holding - * pattern for this particular device). - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( - struct scic_sds_request *request) -{ - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - return SCI_SUCCESS; -} - -/** - * This method processes an unsolicited frame while the task mgmt request is - * waiting for a response frame. It will copy the response data, release - * the unsolicited frame, and transition the request to the - * SCI_BASE_REQUEST_STATE_COMPLETED state. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This method returns an indication of whether the TC response frame was - * handled successfully or not. SCI_SUCCESS Currently this value is always - * returned and indicates successful processing of the TC response. Should - * probably update to check frame type and make sure it is a response frame. - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - scic_sds_io_request_copy_response(request); - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - scic_sds_controller_release_frame(request->owning_controller, - frame_index); - return SCI_SUCCESS; -} - -static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, - }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, - .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, - } -}; - -/** - * This method performs the actions required when entering the - * SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION - * sub-state. This includes setting the IO request state handlers for this - * sub-state. - * @object: This parameter specifies the request object for which the sub-state - * change is occurring. - * - * none. - */ -static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_ssp_task_request_started_substate_handler_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION - ); -} - -/** - * This method performs the actions required when entering the - * SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This - * includes setting the IO request state handlers for this sub-state. - * @object: This parameter specifies the request object for which the sub-state - * change is occurring. - * - * none. - */ -static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_ssp_task_request_started_substate_handler_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE - ); -} - -const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = { - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, - }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, - }, -}; - -- cgit v1.2.3 From c72086e3c2897eaca5b99c005dd9844fdc784981 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 May 2011 02:28:48 -0700 Subject: isci: merge smp request substates into primary state machine Remove usage of the request substate machine for smp requests identified by: task->task_proto == SAS_PROTOCOL_SMP While merging over the smp_request infrastructure noticed that all the assign buffer implementations are now equal, so moved it to scic_sds_general_request_construct. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 1 - drivers/scsi/isci/request.c | 462 +++++++++++++++++++++++++++++++---- drivers/scsi/isci/request.h | 42 ++-- drivers/scsi/isci/smp_request.c | 518 ---------------------------------------- drivers/scsi/isci/stp_request.c | 6 - 5 files changed, 436 insertions(+), 593 deletions(-) delete mode 100644 drivers/scsi/isci/smp_request.c diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 43d2c050bd49..be2b67d0df89 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -7,5 +7,4 @@ isci-objs := init.o phy.o request.o sata.o \ remote_node_table.o \ unsolicited_frame_control.o \ stp_request.o \ - smp_request.o \ port_config.o \ diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 5f5168110556..5201dc58a191 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -158,12 +158,6 @@ void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) } } -static void scic_sds_ssp_io_request_assign_buffers(struct scic_sds_request *sci_req) -{ - if (sci_req->was_tag_assigned_by_user == false) - sci_req->task_context_buffer = &sci_req->tc; -} - static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) { struct ssp_cmd_iu *cmd_iu; @@ -341,12 +335,6 @@ static void scu_ssp_io_request_construct_task_context( scic_sds_request_build_sgl(sci_req); } -static void scic_sds_ssp_task_request_assign_buffers(struct scic_sds_request *sci_req) -{ - if (sci_req->was_tag_assigned_by_user == false) - sci_req->task_context_buffer = &sci_req->tc; -} - /** * This method will fill in the SCU Task Context for a SSP Task request. The * following important settings are utilized: -# priority == @@ -1261,6 +1249,196 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler return SCI_SUCCESS; } +/** + * This method processes an abnormal TC completion while the SMP request is + * waiting for a response frame. It decides what happened to the IO based + * on TC completion status. + * @sci_req: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + /* + * In the AWAIT RESPONSE state, any TC completion is unexpected. + * but if the TC has success status, we complete the IO anyway. */ + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): + /* + * These status has been seen in a specific LSI expander, which sometimes + * is not able to send smp response within 2 ms. This causes our hardware + * break the connection and set TC completion with one of these SMP_XXX_XX_ERR + * status. For these type of error, we ask scic user to retry the request. */ + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + +/* + * This function processes an unsolicited frame while the SMP request is waiting + * for a response frame. It will copy the response data, release the + * unsolicited frame, and transition the request to the + * SCI_BASE_REQUEST_STATE_COMPLETED state. + * @sci_req: This parameter specifies the request for which the + * unsolicited frame was received. + * @frame_index: This parameter indicates the unsolicited frame index that + * should contain the response. + * + * This function returns an indication of whether the response frame was handled + * successfully or not. SCI_SUCCESS Currently this value is always returned and + * indicates successful processing of the TC response. + */ +static enum sci_status +scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + void *frame_header; + struct smp_resp *rsp_hdr = &sci_req->smp.rsp; + ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); + + status = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_request_get_controller(sci_req)->uf_control), + frame_index, + &frame_header); + + /* byte swap the header. */ + sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); + + if (rsp_hdr->frame_type == SMP_RESPONSE) { + void *smp_resp; + + status = scic_sds_unsolicited_frame_control_get_buffer( + &(scic_sds_request_get_controller(sci_req)->uf_control), + frame_index, + &smp_resp); + + word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / + sizeof(u32); + + sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, + smp_resp, word_cnt); + + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); + } else { + /* This was not a response frame why did it get forwarded? */ + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: SCIC SMP Request 0x%p received unexpected frame " + "%d type 0x%02x\n", + __func__, + sci_req, + frame_index, + rsp_hdr->frame_type); + + scic_sds_request_set_status( + sci_req, + SCU_TASK_DONE_SMP_FRM_TYPE_ERR, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + } + + scic_sds_controller_release_frame(sci_req->owning_controller, + frame_index); + + return SCI_SUCCESS; +} + +/** + * This method processes the completions transport layer (TL) status to + * determine if the SMP request was sent successfully. If the SMP request + * was sent successfully, then the state for the SMP request transits to + * waiting for a response frame. + * @sci_req: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { }, [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { @@ -1280,6 +1458,15 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, + .frame_handler = scic_sds_smp_request_await_response_frame_handler, + }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, + }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .complete_handler = scic_sds_request_completed_state_complete_handler, }, @@ -2038,6 +2225,12 @@ static void scic_sds_request_started_state_enter(void *object) struct sci_base_state_machine *sm = &sci_req->state_machine; struct isci_request *ireq = sci_req_to_ireq(sci_req); struct domain_device *dev = sci_dev_to_domain(sci_req->target_device); + struct sas_task *task; + + /* XXX as hch said always creating an internal sas_task for tmf + * requests would simplify the driver + */ + task = ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL; SET_STATE_HANDLER( sci_req, @@ -2045,15 +2238,19 @@ static void scic_sds_request_started_state_enter(void *object) SCI_BASE_REQUEST_STATE_STARTED ); - if (ireq->ttype == tmf_task && dev->dev_type == SAS_END_DEV) - sci_base_state_machine_change_state(sm, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION); - /* Most of the request state machines have a started substate machine so * start its execution on the entry to the started state. */ if (sci_req->has_started_substate_machine == true) sci_base_state_machine_start(&sci_req->started_substate_machine); + + if (!task && dev->dev_type == SAS_END_DEV) { + sci_base_state_machine_change_state(sm, + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION); + } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { + sci_base_state_machine_change_state(sm, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE); + } } /** @@ -2173,6 +2370,28 @@ static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_e ); } +static void scic_sds_smp_request_started_await_response_substate_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE + ); +} + +static void scic_sds_smp_request_started_await_tc_completion_substate_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION + ); +} + static const struct sci_base_state scic_sds_request_state_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { .enter_state = scic_sds_request_initial_state_enter, @@ -2190,6 +2409,12 @@ static const struct sci_base_state scic_sds_request_state_table[] = { [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { + .enter_state = scic_sds_smp_request_started_await_response_substate_enter, + }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { + .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, + }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .enter_state = scic_sds_request_completed_state_enter, }, @@ -2225,7 +2450,7 @@ static void scic_sds_general_request_construct(struct scic_sds_controller *scic, if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { sci_req->was_tag_assigned_by_user = false; - sci_req->task_context_buffer = NULL; + sci_req->task_context_buffer = &sci_req->tc; } else { sci_req->was_tag_assigned_by_user = true; @@ -2245,26 +2470,20 @@ scic_io_request_construct(struct scic_sds_controller *scic, /* Build the common part of the request */ scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); - if (sci_dev->rnc.remote_node_index == - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) + if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; if (dev->dev_type == SAS_END_DEV) - scic_sds_ssp_io_request_assign_buffers(sci_req); - else if ((dev->dev_type == SATA_DEV) || - (dev->tproto & SAS_PROTOCOL_STP)) { - scic_sds_stp_request_assign_buffers(sci_req); + /* pass */; + else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); - } else if (dev_is_expander(dev)) { - scic_sds_smp_request_assign_buffers(sci_req); + else if (dev_is_expander(dev)) memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); - } else - status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; + else + return SCI_FAILURE_UNSUPPORTED_PROTOCOL; - if (status == SCI_SUCCESS) { - memset(sci_req->task_context_buffer, 0, - offsetof(struct scu_task_context, sgl_pair_ab)); - } + memset(sci_req->task_context_buffer, 0, + offsetof(struct scu_task_context, sgl_pair_ab)); return status; } @@ -2279,17 +2498,12 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, /* Build the common part of the request */ scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); - if (dev->dev_type == SAS_END_DEV) - scic_sds_ssp_task_request_assign_buffers(sci_req); - else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) - scic_sds_stp_request_assign_buffers(sci_req); - else - status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - - if (status == SCI_SUCCESS) { + if (dev->dev_type == SAS_END_DEV || + dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { sci_req->is_task_management_request = true; memset(sci_req->task_context_buffer, 0, sizeof(struct scu_task_context)); - } + } else + status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; return status; } @@ -2340,6 +2554,174 @@ static enum sci_status isci_request_stp_request_construct( return status; } +/* + * This function will fill in the SCU Task Context for a SMP request. The + * following important settings are utilized: -# task_type == + * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type + * (i.e. non-raw frame) is being utilized to perform task management. -# + * control_frame == 1. This ensures that the proper endianess is set so + * that the bytes are transmitted in the right order for a smp request frame. + * @sci_req: This parameter specifies the smp request object being + * constructed. + * + */ +static void +scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, + struct smp_req *smp_req) +{ + dma_addr_t dma_addr; + struct scic_sds_controller *scic; + struct scic_sds_remote_device *sci_dev; + struct scic_sds_port *sci_port; + struct scu_task_context *task_context; + ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); + + /* byte swap the smp request. */ + sci_swab32_cpy(&sci_req->smp.cmd, smp_req, + word_cnt); + + task_context = scic_sds_request_get_task_context(sci_req); + + scic = scic_sds_request_get_controller(sci_req); + sci_dev = scic_sds_request_get_device(sci_req); + sci_port = scic_sds_request_get_port(sci_req); + + /* + * Fill in the TC with the its required data + * 00h + */ + task_context->priority = 0; + task_context->initiator_request = 1; + task_context->connection_rate = sci_dev->connection_rate; + task_context->protocol_engine_index = + scic_sds_controller_get_protocol_engine_group(scic); + task_context->logical_port_index = scic_sds_port_get_index(sci_port); + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; + task_context->abort = 0; + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + /* 04h */ + task_context->remote_node_index = sci_dev->rnc.remote_node_index; + task_context->command_code = 0; + task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; + + /* 08h */ + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 1; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + /* 0ch */ + task_context->address_modifier = 0; + + /* 10h */ + task_context->ssp_command_iu_length = smp_req->req_len; + + /* 14h */ + task_context->transfer_length_bytes = 0; + + /* + * 18h ~ 30h, protocol specific + * since commandIU has been build by framework at this point, we just + * copy the frist DWord from command IU to this location. */ + memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); + + /* + * 40h + * "For SMP you could program it to zero. We would prefer that way + * so that done code will be consistent." - Venki + */ + task_context->task_phase = 0; + + if (sci_req->was_tag_assigned_by_user) { + /* + * Build the task context now since we have already read + * the data + */ + sci_req->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group(scic) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(sci_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + scic_sds_io_tag_get_index(sci_req->io_tag)); + } else { + /* + * Build the task context now since we have already read + * the data. + * I/O tag index is not assigned because we have to wait + * until we get a TCi. + */ + sci_req->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group(scic) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(sci_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); + } + + /* + * Copy the physical address for the command buffer to the SCU Task + * Context command buffer should not contain command header. + */ + dma_addr = scic_io_request_get_dma_addr(sci_req, + ((char *) &sci_req->smp.cmd) + + sizeof(u32)); + + task_context->command_iu_upper = upper_32_bits(dma_addr); + task_context->command_iu_lower = lower_32_bits(dma_addr); + + /* SMP response comes as UF, so no need to set response IU address. */ + task_context->response_iu_upper = 0; + task_context->response_iu_lower = 0; +} + +static enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) +{ + struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); + + if (!smp_req) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + + sci_req->protocol = SCIC_SMP_PROTOCOL; + + /* Construct the SMP SCU Task Context */ + memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req)); + + /* + * Look at the SMP requests' header fields; for certain SAS 1.x SMP + * functions under SAS 2.0, a zero request length really indicates + * a non-zero default length. */ + if (smp_req->req_len == 0) { + switch (smp_req->func) { + case SMP_DISCOVER: + case SMP_REPORT_PHY_ERR_LOG: + case SMP_REPORT_PHY_SATA: + case SMP_REPORT_ROUTE_INFO: + smp_req->req_len = 2; + break; + case SMP_CONF_ROUTE_INFO: + case SMP_PHY_CONTROL: + case SMP_PHY_TEST_FUNCTION: + smp_req->req_len = 9; + break; + /* Default - zero is a valid default for 2.0. */ + } + } + + scu_smp_request_construct_task_context(sci_req, smp_req); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); + + kfree(smp_req); + + return SCI_SUCCESS; +} + /* * isci_smp_request_build() - This function builds the smp request. * @ireq: This parameter points to the isci_request allocated in the diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index b5c5b063a369..d090cb1a14d6 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -88,7 +88,7 @@ enum sci_request_protocol { SCIC_SMP_PROTOCOL, SCIC_SSP_PROTOCOL, SCIC_STP_PROTOCOL -}; /* XXX remove me, use sas_task.dev instead */; +}; /* XXX remove me, use sas_task.{dev|task_proto} instead */; struct scic_sds_request { /** @@ -309,6 +309,19 @@ enum sci_base_request_states { */ SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, + /** + * This sub-state indicates that the started task management request + * is waiting for the reception of an unsolicited frame + * (i.e. response IU). + */ + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, + + /** + * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is + * waiting for the transmission of the initial frame (i.e. command, task, etc.). + */ + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, + /** * This state indicates that the request has completed. * This state is entered from the STARTED state. This state is entered from @@ -461,8 +474,6 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completi } void scic_sds_request_build_sgl(struct scic_sds_request *sci_req); -void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req); -void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req); enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, @@ -473,30 +484,6 @@ enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); -/** - * enum _scic_sds_smp_request_started_substates - This enumeration depicts all - * of the substates for a SMP request to be performed in the STARTED - * super-state. - * - * - */ -enum scic_sds_smp_request_started_substates { - /** - * This sub-state indicates that the started task management request - * is waiting for the reception of an unsolicited frame - * (i.e. response IU). - */ - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, - - /** - * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is - * waiting for the transmission of the initial frame (i.e. command, task, etc.). - */ - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, -}; - - - /* XXX open code in caller */ static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, dma_addr_t phys_addr) @@ -791,7 +778,6 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_request *sci_req); enum sci_status scic_task_request_construct_ssp(struct scic_sds_request *sci_req); enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req); -enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req); void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); #endif /* !defined(_ISCI_REQUEST_H_) */ diff --git a/drivers/scsi/isci/smp_request.c b/drivers/scsi/isci/smp_request.c deleted file mode 100644 index d4750a761c58..000000000000 --- a/drivers/scsi/isci/smp_request.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "state_machine.h" -#include "remote_device.h" -#include "request.h" -#include "scu_completion_codes.h" -#include "scu_task_context.h" -#include "host.h" - -static void scu_smp_request_construct_task_context( - struct scic_sds_request *sci_req, - struct smp_req *smp_req); - -void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req) -{ - if (sci_req->was_tag_assigned_by_user == false) - sci_req->task_context_buffer = &sci_req->tc; -} - -/* - * This function will fill in the SCU Task Context for a SMP request. The - * following important settings are utilized: -# task_type == - * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type - * (i.e. non-raw frame) is being utilized to perform task management. -# - * control_frame == 1. This ensures that the proper endianess is set so - * that the bytes are transmitted in the right order for a smp request frame. - * @sci_req: This parameter specifies the smp request object being - * constructed. - * - */ -static void -scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, - struct smp_req *smp_req) -{ - dma_addr_t dma_addr; - struct scic_sds_controller *scic; - struct scic_sds_remote_device *sci_dev; - struct scic_sds_port *sci_port; - struct scu_task_context *task_context; - ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); - - /* byte swap the smp request. */ - sci_swab32_cpy(&sci_req->smp.cmd, smp_req, - word_cnt); - - task_context = scic_sds_request_get_task_context(sci_req); - - scic = scic_sds_request_get_controller(sci_req); - sci_dev = scic_sds_request_get_device(sci_req); - sci_port = scic_sds_request_get_port(sci_req); - - /* - * Fill in the TC with the its required data - * 00h - */ - task_context->priority = 0; - task_context->initiator_request = 1; - task_context->connection_rate = sci_dev->connection_rate; - task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(scic); - task_context->logical_port_index = scic_sds_port_get_index(sci_port); - task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; - task_context->abort = 0; - task_context->valid = SCU_TASK_CONTEXT_VALID; - task_context->context_type = SCU_TASK_CONTEXT_TYPE; - - /* 04h */ - task_context->remote_node_index = sci_dev->rnc.remote_node_index; - task_context->command_code = 0; - task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; - - /* 08h */ - task_context->link_layer_control = 0; - task_context->do_not_dma_ssp_good_response = 1; - task_context->strict_ordering = 0; - task_context->control_frame = 1; - task_context->timeout_enable = 0; - task_context->block_guard_enable = 0; - - /* 0ch */ - task_context->address_modifier = 0; - - /* 10h */ - task_context->ssp_command_iu_length = smp_req->req_len; - - /* 14h */ - task_context->transfer_length_bytes = 0; - - /* - * 18h ~ 30h, protocol specific - * since commandIU has been build by framework at this point, we just - * copy the frist DWord from command IU to this location. */ - memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); - - /* - * 40h - * "For SMP you could program it to zero. We would prefer that way - * so that done code will be consistent." - Venki - */ - task_context->task_phase = 0; - - if (sci_req->was_tag_assigned_by_user) { - /* - * Build the task context now since we have already read - * the data - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(scic) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(sci_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sci_req->io_tag)); - } else { - /* - * Build the task context now since we have already read - * the data. - * I/O tag index is not assigned because we have to wait - * until we get a TCi. - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(scic) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(sci_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); - } - - /* - * Copy the physical address for the command buffer to the SCU Task - * Context command buffer should not contain command header. - */ - dma_addr = scic_io_request_get_dma_addr(sci_req, - ((char *) &sci_req->smp.cmd) + - sizeof(u32)); - - task_context->command_iu_upper = upper_32_bits(dma_addr); - task_context->command_iu_lower = lower_32_bits(dma_addr); - - /* SMP response comes as UF, so no need to set response IU address. */ - task_context->response_iu_upper = 0; - task_context->response_iu_lower = 0; -} - -/* - * This function processes an unsolicited frame while the SMP request is waiting - * for a response frame. It will copy the response data, release the - * unsolicited frame, and transition the request to the - * SCI_BASE_REQUEST_STATE_COMPLETED state. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This function returns an indication of whether the response frame was handled - * successfully or not. SCI_SUCCESS Currently this value is always returned and - * indicates successful processing of the TC response. - */ -static enum sci_status -scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - void *frame_header; - struct smp_resp *rsp_hdr = &sci_req->smp.rsp; - ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); - - status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - &frame_header); - - /* byte swap the header. */ - sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); - - if (rsp_hdr->frame_type == SMP_RESPONSE) { - void *smp_resp; - - status = scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - &smp_resp); - - word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / - sizeof(u32); - - sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, - smp_resp, word_cnt); - - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); - } else { - /* This was not a response frame why did it get forwarded? */ - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC SMP Request 0x%p received unexpected frame " - "%d type 0x%02x\n", - __func__, - sci_req, - frame_index, - rsp_hdr->frame_type); - - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_SMP_FRM_TYPE_ERR, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - } - - scic_sds_controller_release_frame(sci_req->owning_controller, - frame_index); - - return SCI_SUCCESS; -} - - -/** - * This method processes an abnormal TC completion while the SMP request is - * waiting for a response frame. It decides what happened to the IO based - * on TC completion status. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - /* - * In the AWAIT RESPONSE state, any TC completion is unexpected. - * but if the TC has success status, we complete the IO anyway. */ - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): - /* - * These status has been seen in a specific LSI expander, which sometimes - * is not able to send smp response within 2 ms. This causes our hardware - * break the connection and set TC completion with one of these SMP_XXX_XX_ERR - * status. For these type of error, we ask scic user to retry the request. */ - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - - -/** - * This method processes the completions transport layer (TL) status to - * determine if the SMP request was sent successfully. If the SMP request - * was sent successfully, then the state for the SMP request transits to - * waiting for a response frame. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - - -static const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, - .frame_handler = scic_sds_smp_request_await_response_frame_handler, - }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, - } -}; - -/** - * This method performs the actions required when entering the - * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This - * includes setting the IO request state handlers for this sub-state. - * @object: This parameter specifies the request object for which the sub-state - * change is occurring. - * - * none. - */ -static void scic_sds_smp_request_started_await_response_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_smp_request_started_substate_handler_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE - ); -} - -/** - * This method performs the actions required when entering the - * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state. - * This includes setting the SMP request state handlers for this sub-state. - * @object: This parameter specifies the request object for which the sub-state - * change is occurring. - * - * none. - */ -static void scic_sds_smp_request_started_await_tc_completion_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_smp_request_started_substate_handler_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION - ); -} - -static const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .enter_state = scic_sds_smp_request_started_await_response_substate_enter, - }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, - }, -}; - -/** - * This method is called by the SCI user to build an SMP IO request. - * - * - The user must have previously called scic_io_request_construct() on the - * supplied IO request. Indicate if the controller successfully built the IO - * request. SCI_SUCCESS This value is returned if the IO request was - * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned - * if the remote_device does not support the SMP protocol. - * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not - * properly set the association between the SCIC IO request and the user's IO - * request. - */ -enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) -{ - struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); - - if (!smp_req) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - - sci_req->protocol = SCIC_SMP_PROTOCOL; - sci_req->has_started_substate_machine = true; - - /* Construct the started sub-state machine. */ - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - sci_req, - scic_sds_smp_request_started_substate_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE - ); - - /* Construct the SMP SCU Task Context */ - memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req)); - - /* - * Look at the SMP requests' header fields; for certain SAS 1.x SMP - * functions under SAS 2.0, a zero request length really indicates - * a non-zero default length. */ - if (smp_req->req_len == 0) { - switch (smp_req->func) { - case SMP_DISCOVER: - case SMP_REPORT_PHY_ERR_LOG: - case SMP_REPORT_PHY_SATA: - case SMP_REPORT_ROUTE_INFO: - smp_req->req_len = 2; - break; - case SMP_CONF_ROUTE_INFO: - case SMP_PHY_CONTROL: - case SMP_PHY_TEST_FUNCTION: - smp_req->req_len = 9; - break; - /* Default - zero is a valid default for 2.0. */ - } - } - - scu_smp_request_construct_task_context(sci_req, smp_req); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); - - kfree(smp_req); - - return SCI_SUCCESS; -} diff --git a/drivers/scsi/isci/stp_request.c b/drivers/scsi/isci/stp_request.c index 298086afa5aa..e94ece81ed9d 100644 --- a/drivers/scsi/isci/stp_request.c +++ b/drivers/scsi/isci/stp_request.c @@ -64,12 +64,6 @@ #include "scu_task_context.h" #include "request.h" -void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req) -{ - if (sci_req->was_tag_assigned_by_user == false) - sci_req->task_context_buffer = &sci_req->tc; -} - /** * This method is will fill in the SCU Task Context for any type of SATA * request. This is called from the various SATA constructors. -- cgit v1.2.3 From 5dec6f4e41340196d223caf922578c44dfe2295a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 May 2011 02:28:49 -0700 Subject: isci: merge stp request substates into primary state machine Remove usage of the request substate machine for stp requests, and kill the request substate infrastructure. Similar to the previous conversions this adds the substates to the primary state machine and arranges for the 'started' state to transition to the proper stp substate. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 1 - drivers/scsi/isci/request.c | 1649 +++++++++++++++++++++++++++++++++++---- drivers/scsi/isci/request.h | 113 ++- drivers/scsi/isci/stp_request.c | 1584 ------------------------------------- drivers/scsi/isci/stp_request.h | 195 ----- 5 files changed, 1593 insertions(+), 1949 deletions(-) delete mode 100644 drivers/scsi/isci/stp_request.c delete mode 100644 drivers/scsi/isci/stp_request.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index be2b67d0df89..86b0c88e91a6 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -6,5 +6,4 @@ isci-objs := init.o phy.o request.o sata.o \ remote_node_context.o \ remote_node_table.o \ unsolicited_frame_control.o \ - stp_request.o \ port_config.o \ diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 5201dc58a191..f503e3e18d8f 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -58,6 +58,7 @@ #include "request.h" #include "sata.h" #include "scu_completion_codes.h" +#include "scu_event_codes.h" #include "sas.h" /** @@ -92,7 +93,7 @@ static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( * the Scatter-Gather List. * */ -void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) +static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) { struct isci_request *isci_request = sci_req_to_ireq(sds_request); struct isci_host *isci_host = isci_request->isci_host; @@ -366,27 +367,214 @@ static void scu_ssp_task_request_construct_task_context( sizeof(struct ssp_task_iu) / sizeof(u32); } +/** + * This method is will fill in the SCU Task Context for any type of SATA + * request. This is called from the various SATA constructors. + * @sci_req: The general IO request object which is to be used in + * constructing the SCU task context. + * @task_context: The buffer pointer for the SCU task context which is being + * constructed. + * + * The general io request construction is complete. The buffer assignment for + * the command buffer is complete. none Revisit task context construction to + * determine what is common for SSP/SMP/STP task context structures. + */ +static void scu_sata_reqeust_construct_task_context( + struct scic_sds_request *sci_req, + struct scu_task_context *task_context) +{ + dma_addr_t dma_addr; + struct scic_sds_controller *controller; + struct scic_sds_remote_device *target_device; + struct scic_sds_port *target_port; + + controller = scic_sds_request_get_controller(sci_req); + target_device = scic_sds_request_get_device(sci_req); + target_port = scic_sds_request_get_port(sci_req); + + /* Fill in the TC with the its required data */ + task_context->abort = 0; + task_context->priority = SCU_TASK_PRIORITY_NORMAL; + task_context->initiator_request = 1; + task_context->connection_rate = target_device->connection_rate; + task_context->protocol_engine_index = + scic_sds_controller_get_protocol_engine_group(controller); + task_context->logical_port_index = + scic_sds_port_get_index(target_port); + task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; + task_context->valid = SCU_TASK_CONTEXT_VALID; + task_context->context_type = SCU_TASK_CONTEXT_TYPE; + + task_context->remote_node_index = + scic_sds_remote_device_get_index(sci_req->target_device); + task_context->command_code = 0; + + task_context->link_layer_control = 0; + task_context->do_not_dma_ssp_good_response = 1; + task_context->strict_ordering = 0; + task_context->control_frame = 0; + task_context->timeout_enable = 0; + task_context->block_guard_enable = 0; + + task_context->address_modifier = 0; + task_context->task_phase = 0x01; + + task_context->ssp_command_iu_length = + (sizeof(struct host_to_dev_fis) - sizeof(u32)) / sizeof(u32); + + /* Set the first word of the H2D REG FIS */ + task_context->type.words[0] = *(u32 *)&sci_req->stp.cmd; + + if (sci_req->was_tag_assigned_by_user) { + /* + * Build the task context now since we have already read + * the data + */ + sci_req->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + scic_sds_io_tag_get_index(sci_req->io_tag)); + } else { + /* + * Build the task context now since we have already read + * the data. + * I/O tag index is not assigned because we have to wait + * until we get a TCi. + */ + sci_req->post_context = + (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group( + controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); + } + + /* + * Copy the physical address for the command buffer to the SCU Task + * Context. We must offset the command buffer by 4 bytes because the + * first 4 bytes are transfered in the body of the TC. + */ + dma_addr = scic_io_request_get_dma_addr(sci_req, + ((char *) &sci_req->stp.cmd) + + sizeof(u32)); + + task_context->command_iu_upper = upper_32_bits(dma_addr); + task_context->command_iu_lower = lower_32_bits(dma_addr); + + /* SATA Requests do not have a response buffer */ + task_context->response_iu_upper = 0; + task_context->response_iu_lower = 0; +} + + /** - * This method constructs the SSP Command IU data for this ssp passthrough - * comand request object. - * @sci_req: This parameter specifies the request object for which the SSP - * command information unit is being built. + * scu_stp_raw_request_construct_task_context - + * @sci_req: This parameter specifies the STP request object for which to + * construct a RAW command frame task context. + * @task_context: This parameter specifies the SCU specific task context buffer + * to construct. * - * enum sci_status, returns invalid parameter is cdb > 16 + * This method performs the operations common to all SATA/STP requests + * utilizing the raw frame method. none */ +static void scu_stp_raw_request_construct_task_context(struct scic_sds_stp_request *stp_req, + struct scu_task_context *task_context) +{ + struct scic_sds_request *sci_req = to_sci_req(stp_req); + + scu_sata_reqeust_construct_task_context(sci_req, task_context); + + task_context->control_frame = 0; + task_context->priority = SCU_TASK_PRIORITY_NORMAL; + task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; + task_context->type.stp.fis_type = FIS_REGH2D; + task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32); +} + +static enum sci_status +scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, + bool copy_rx_frame) +{ + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; + + scu_stp_raw_request_construct_task_context(stp_req, + sci_req->task_context_buffer); + + pio->current_transfer_bytes = 0; + pio->ending_error = 0; + pio->ending_status = 0; + + pio->request_current.sgl_offset = 0; + pio->request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; + + if (copy_rx_frame) { + scic_sds_request_build_sgl(sci_req); + /* Since the IO request copy of the TC contains the same data as + * the actual TC this pointer is vaild for either. + */ + pio->request_current.sgl_pair = &sci_req->task_context_buffer->sgl_pair_ab; + } else { + /* The user does not want the data copied to the SGL buffer location */ + pio->request_current.sgl_pair = NULL; + } + return SCI_SUCCESS; +} /** - * This method constructs the SATA request object. - * @sci_req: - * @sat_protocol: - * @transfer_length: - * @data_direction: - * @copy_rx_frame: * - * enum sci_status + * @sci_req: This parameter specifies the request to be constructed as an + * optimized request. + * @optimized_task_type: This parameter specifies whether the request is to be + * an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A + * value of 1 indicates NCQ. + * + * This method will perform request construction common to all types of STP + * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method + * returns an indication as to whether the construction was successful. */ +static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sci_req, + u8 optimized_task_type, + u32 len, + enum dma_data_direction dir) +{ + struct scu_task_context *task_context = sci_req->task_context_buffer; + + /* Build the STP task context structure */ + scu_sata_reqeust_construct_task_context(sci_req, task_context); + + /* Copy over the SGL elements */ + scic_sds_request_build_sgl(sci_req); + + /* Copy over the number of bytes to be transfered */ + task_context->transfer_length_bytes = len; + + if (dir == DMA_TO_DEVICE) { + /* + * The difference between the DMA IN and DMA OUT request task type + * values are consistent with the difference between FPDMA READ + * and FPDMA WRITE values. Add the supplied task type parameter + * to this difference to set the task type properly for this + * DATA OUT (WRITE) case. */ + task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT + - SCU_TASK_TYPE_DMA_IN); + } else { + /* + * For the DATA IN (READ) case, simply save the supplied + * optimized task type. */ + task_context->task_type = optimized_task_type; + } +} + + + static enum sci_status scic_io_request_construct_sata(struct scic_sds_request *sci_req, u32 len, @@ -402,9 +590,11 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, struct isci_tmf *tmf = isci_request_access_tmf(ireq); if (tmf->tmf_code == isci_tmf_sata_srst_high || - tmf->tmf_code == isci_tmf_sata_srst_low) - return scic_sds_stp_soft_reset_request_construct(sci_req); - else { + tmf->tmf_code == isci_tmf_sata_srst_low) { + scu_stp_raw_request_construct_task_context(&sci_req->stp.req, + sci_req->task_context_buffer); + return SCI_SUCCESS; + } else { dev_err(scic_to_dev(sci_req->owning_controller), "%s: Request 0x%p received un-handled SAT " "management protocol 0x%x.\n", @@ -424,17 +614,27 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, } /* non data */ - if (task->data_dir == DMA_NONE) - return scic_sds_stp_non_data_request_construct(sci_req); + if (task->data_dir == DMA_NONE) { + scu_stp_raw_request_construct_task_context(&sci_req->stp.req, + sci_req->task_context_buffer); + return SCI_SUCCESS; + } /* NCQ */ - if (task->ata_task.use_ncq) - return scic_sds_stp_ncq_request_construct(sci_req, len, dir); + if (task->ata_task.use_ncq) { + scic_sds_stp_optimized_request_construct(sci_req, + SCU_TASK_TYPE_FPDMAQ_READ, + len, dir); + return SCI_SUCCESS; + } /* DMA */ - if (task->ata_task.dma_xfer) - return scic_sds_stp_udma_request_construct(sci_req, len, dir); - else /* PIO */ + if (task->ata_task.dma_xfer) { + scic_sds_stp_optimized_request_construct(sci_req, + SCU_TASK_TYPE_DMA_IN, + len, dir); + return SCI_SUCCESS; + } else /* PIO */ return scic_sds_stp_pio_request_construct(sci_req, copy); return status; @@ -453,9 +653,8 @@ static enum sci_status scic_io_request_construct_basic_ssp(struct scic_sds_reque scic_sds_io_request_build_ssp_command_iu(sci_req); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return SCI_SUCCESS; } @@ -470,12 +669,11 @@ enum sci_status scic_task_request_construct_ssp( scic_sds_task_request_build_ssp_task_iu(sci_req); sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return SCI_SUCCESS; } - static enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_request *sci_req) { enum sci_status status; @@ -496,12 +694,11 @@ static enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_requ if (status == SCI_SUCCESS) sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return status; } - enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req) { enum sci_status status = SCI_SUCCESS; @@ -513,7 +710,8 @@ enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_re if (tmf->tmf_code == isci_tmf_sata_srst_high || tmf->tmf_code == isci_tmf_sata_srst_low) { - status = scic_sds_stp_soft_reset_request_construct(sci_req); + scu_stp_raw_request_construct_task_context(&sci_req->stp.req, + sci_req->task_context_buffer); } else { dev_err(scic_to_dev(sci_req->owning_controller), "%s: Request 0x%p received un-handled SAT " @@ -524,10 +722,10 @@ enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_re } } - if (status == SCI_SUCCESS) - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + if (status != SCI_SUCCESS) + return status; + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return status; } @@ -724,7 +922,7 @@ static enum sci_status scic_sds_request_constructed_state_start_handler( /* Everything is good go ahead and change state */ sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_STARTED); + SCI_BASE_REQUEST_STATE_STARTED); return SCI_SUCCESS; } @@ -749,29 +947,14 @@ static enum sci_status scic_sds_request_constructed_state_abort_handler( SCI_FAILURE_IO_TERMINATED); sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } -/* - * ***************************************************************************** - * * STARTED STATE HANDLERS - * ***************************************************************************** */ - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_terminate() request. Since the request - * has been posted to the hardware the io request state is changed to the - * aborting state. enum sci_status SCI_SUCCESS - */ -enum sci_status scic_sds_request_started_state_abort_handler( - struct scic_sds_request *request) +static enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req) { - if (request->has_started_substate_machine) - sci_base_state_machine_stop(&request->started_substate_machine); - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_ABORTING); return SCI_SUCCESS; } @@ -943,19 +1126,15 @@ scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sc */ /* In all cases we will treat this as the completion of the IO req. */ - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } enum sci_status scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code) { - if (request->state_machine.current_state_id == SCI_BASE_REQUEST_STATE_STARTED && - request->has_started_substate_machine == false) - return scic_sds_request_started_state_tc_completion_handler(request, completion_code); - else if (request->state_handlers->tc_completion_handler) + if (request->state_handlers->tc_completion_handler) return request->state_handlers->tc_completion_handler(request, completion_code); dev_warn(scic_to_dev(request->owning_controller), @@ -1064,7 +1243,7 @@ static enum sci_status scic_sds_request_completed_state_complete_handler( } sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_FINAL); + SCI_BASE_REQUEST_STATE_FINAL); return SCI_SUCCESS; } @@ -1084,7 +1263,7 @@ static enum sci_status scic_sds_request_aborting_state_abort_handler( struct scic_sds_request *request) { sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } @@ -1107,7 +1286,7 @@ static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( ); sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + SCI_BASE_REQUEST_STATE_COMPLETED); break; default: @@ -1161,7 +1340,7 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi SCI_SUCCESS); sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): @@ -1178,7 +1357,7 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi completion_code); sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); + SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); break; default: @@ -1192,7 +1371,7 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi ); sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -1215,9 +1394,9 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler struct scic_sds_request *request) { sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); + SCI_BASE_REQUEST_STATE_ABORTING); sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + SCI_BASE_REQUEST_STATE_COMPLETED); return SCI_SUCCESS; } @@ -1243,7 +1422,7 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler scic_sds_io_request_copy_response(request); sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + SCI_BASE_REQUEST_STATE_COMPLETED); scic_sds_controller_release_frame(request->owning_controller, frame_index); return SCI_SUCCESS; @@ -1270,13 +1449,11 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler /* * In the AWAIT RESPONSE state, any TC completion is unexpected. * but if the TC has success status, we complete the IO anyway. */ - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + SCI_SUCCESS); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): @@ -1288,13 +1465,11 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler * is not able to send smp response within 2 ms. This causes our hardware * break the connection and set TC completion with one of these SMP_XXX_XX_ERR * status. For these type of error, we ask scic user to retry the request. */ - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED - ); + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, + SCI_FAILURE_RETRY_REQUIRED); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; default: @@ -1307,9 +1482,8 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -1365,7 +1539,7 @@ scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_r sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); } else { /* This was not a response frame why did it get forwarded? */ dev_err(scic_to_dev(sci_req->owning_controller), @@ -1378,46 +1552,921 @@ scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_r scic_sds_request_set_status( sci_req, - SCU_TASK_DONE_SMP_FRM_TYPE_ERR, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + SCU_TASK_DONE_SMP_FRM_TYPE_ERR, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + } + + scic_sds_controller_release_frame(sci_req->owning_controller, + frame_index); + + return SCI_SUCCESS; +} + +/** + * This method processes the completions transport layer (TL) status to + * determine if the SMP request was sent successfully. If the SMP request + * was sent successfully, then the state for the SMP request transits to + * waiting for a response frame. + * @sci_req: This parameter specifies the request for which the TC + * completion was received. + * @completion_code: This parameter indicates the completion status information + * for the TC. + * + * Indicate if the tc completion handler was successful. SCI_SUCCESS currently + * this method always returns success. + */ +static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + SCI_SUCCESS); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + +void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *req, + u16 ncq_tag) +{ + /** + * @note This could be made to return an error to the user if the user + * attempts to set the NCQ tag in the wrong state. + */ + req->task_context_buffer->type.stp.ncq_tag = ncq_tag; +} + +/** + * + * @sci_req: + * + * Get the next SGL element from the request. - Check on which SGL element pair + * we are working - if working on SLG pair element A - advance to element B - + * else - check to see if there are more SGL element pairs for this IO request + * - if there are more SGL element pairs - advance to the next pair and return + * element A struct scu_sgl_element* + */ +static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) +{ + struct scu_sgl_element *current_sgl; + struct scic_sds_request *sci_req = to_sci_req(stp_req); + struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current; + + if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + if (pio_sgl->sgl_pair->B.address_lower == 0 && + pio_sgl->sgl_pair->B.address_upper == 0) { + current_sgl = NULL; + } else { + pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B; + current_sgl = &pio_sgl->sgl_pair->B; + } + } else { + if (pio_sgl->sgl_pair->next_pair_lower == 0 && + pio_sgl->sgl_pair->next_pair_upper == 0) { + current_sgl = NULL; + } else { + u64 phys_addr; + + phys_addr = pio_sgl->sgl_pair->next_pair_upper; + phys_addr <<= 32; + phys_addr |= pio_sgl->sgl_pair->next_pair_lower; + + pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr); + pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A; + current_sgl = &pio_sgl->sgl_pair->A; + } + } + + return current_sgl; +} + +/** + * + * @sci_req: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. + */ +static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); + break; + } + + return SCI_SUCCESS; +} + +/** + * + * @request: This parameter specifies the request for which a frame has been + * received. + * @frame_index: This parameter specifies the index of the frame that has been + * received. + * + * This method processes frames received from the target while waiting for a + * device to host register FIS. If a non-register FIS is received during this + * time, it is treated as a protocol violation from an IO perspective. Indicate + * if the received frame was processed successfully. + */ +static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( + struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + struct dev_to_host_fis *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(sci_req->owning_controller), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + + return status; + } + + switch (frame_header->fis_type) { + case FIS_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + /* The command has completed with error */ + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", __func__, stp_req, + frame_index); + + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION); + break; + } + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + +#define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ + +/* transmit DATA_FIS from (current sgl + offset) for input + * parameter length. current sgl and offset is alreay stored in the IO request + */ +static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( + struct scic_sds_request *sci_req, + u32 length) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scu_task_context *task_context; + struct scu_sgl_element *current_sgl; + + /* Recycle the TC and reconstruct it for sending out DATA FIS containing + * for the data from current_sgl+offset for the input length + */ + task_context = scic_sds_controller_get_task_context_buffer(scic, + sci_req->io_tag); + + if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) + current_sgl = &stp_req->type.pio.request_current.sgl_pair->A; + else + current_sgl = &stp_req->type.pio.request_current.sgl_pair->B; + + /* update the TC */ + task_context->command_iu_upper = current_sgl->address_upper; + task_context->command_iu_lower = current_sgl->address_lower; + task_context->transfer_length_bytes = length; + task_context->type.stp.fis_type = FIS_DATA; + + /* send the new TC out. */ + return scic_controller_continue_io(sci_req); +} + +static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct scic_sds_request *sci_req) +{ + + struct scu_sgl_element *current_sgl; + u32 sgl_offset; + u32 remaining_bytes_in_current_sgl = 0; + enum sci_status status = SCI_SUCCESS; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + + sgl_offset = stp_req->type.pio.request_current.sgl_offset; + + if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A); + remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->A.length - sgl_offset; + } else { + current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B); + remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->B.length - sgl_offset; + } + + + if (stp_req->type.pio.pio_transfer_bytes > 0) { + if (stp_req->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { + /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ + status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, remaining_bytes_in_current_sgl); + if (status == SCI_SUCCESS) { + stp_req->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; + + /* update the current sgl, sgl_offset and save for future */ + current_sgl = scic_sds_stp_request_pio_get_next_sgl(stp_req); + sgl_offset = 0; + } + } else if (stp_req->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { + /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */ + scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->type.pio.pio_transfer_bytes); + + if (status == SCI_SUCCESS) { + /* Sgl offset will be adjusted and saved for future */ + sgl_offset += stp_req->type.pio.pio_transfer_bytes; + current_sgl->address_lower += stp_req->type.pio.pio_transfer_bytes; + stp_req->type.pio.pio_transfer_bytes = 0; + } + } + } + + if (status == SCI_SUCCESS) { + stp_req->type.pio.request_current.sgl_offset = sgl_offset; + } + + return status; +} + +/** + * + * @stp_request: The request that is used for the SGL processing. + * @data_buffer: The buffer of data to be copied. + * @length: The length of the data transfer. + * + * Copy the data from the buffer for the length specified to the IO reqeust SGL + * specified data region. enum sci_status + */ +static enum sci_status +scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req, + u8 *data_buf, u32 len) +{ + struct scic_sds_request *sci_req; + struct isci_request *ireq; + u8 *src_addr; + int copy_len; + struct sas_task *task; + struct scatterlist *sg; + void *kaddr; + int total_len = len; + + sci_req = to_sci_req(stp_req); + ireq = sci_req_to_ireq(sci_req); + task = isci_request_access_task(ireq); + src_addr = data_buf; + + if (task->num_scatter > 0) { + sg = task->scatter; + + while (total_len > 0) { + struct page *page = sg_page(sg); + + copy_len = min_t(int, total_len, sg_dma_len(sg)); + kaddr = kmap_atomic(page, KM_IRQ0); + memcpy(kaddr + sg->offset, src_addr, copy_len); + kunmap_atomic(kaddr, KM_IRQ0); + total_len -= copy_len; + src_addr += copy_len; + sg = sg_next(sg); + } + } else { + BUG_ON(task->total_xfer_len < total_len); + memcpy(task->scatter, src_addr, total_len); + } + + return SCI_SUCCESS; +} + +/** + * + * @sci_req: The PIO DATA IN request that is to receive the data. + * @data_buffer: The buffer to copy from. + * + * Copy the data buffer to the io request data region. enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( + struct scic_sds_stp_request *sci_req, + u8 *data_buffer) +{ + enum sci_status status; + + /* + * If there is less than 1K remaining in the transfer request + * copy just the data for the transfer */ + if (sci_req->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { + status = scic_sds_stp_request_pio_data_in_copy_data_buffer( + sci_req, data_buffer, sci_req->type.pio.pio_transfer_bytes); + + if (status == SCI_SUCCESS) + sci_req->type.pio.pio_transfer_bytes = 0; + } else { + /* We are transfering the whole frame so copy */ + status = scic_sds_stp_request_pio_data_in_copy_data_buffer( + sci_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); + + if (status == SCI_SUCCESS) + sci_req->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; + } + + return status; +} + +/** + * + * @sci_req: + * @completion_code: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return status; +} + +static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct isci_request *ireq = sci_req_to_ireq(sci_req); + struct sas_task *task = isci_request_access_task(ireq); + struct dev_to_host_fis *frame_header; + enum sci_status status; + u32 *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + switch (frame_header->fis_type) { + case FIS_PIO_SETUP: + /* Get from the frame buffer the PIO Setup Data */ + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + /* Get the data from the PIO Setup The SCU Hardware returns + * first word in the frame_header and the rest of the data is in + * the frame buffer so we need to back up one dword + */ + + /* transfer_count: first 16bits in the 4th dword */ + stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff; + + /* ending_status: 4th byte in the 3rd dword */ + stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + sci_req->stp.rsp.status = stp_req->type.pio.ending_status; + + /* The next state is dependent on whether the + * request was PIO Data-in or Data out + */ + if (task->data_dir == DMA_FROM_DEVICE) { + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); + } else if (task->data_dir == DMA_TO_DEVICE) { + /* Transmit data */ + status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); + if (status != SCI_SUCCESS) + break; + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); + } + break; + case FIS_SETDEVBITS: + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + break; + case FIS_REGD2H: + if (frame_header->status & ATA_BUSY) { + /* Now why is the drive sending a D2H Register FIS when + * it is still busy? Do nothing since we are still in + * the right state. + */ + dev_dbg(scic_to_dev(scic), + "%s: SCIC PIO Request 0x%p received " + "D2H Register FIS with BSY status " + "0x%x\n", __func__, stp_req, + frame_header->status); + break; + } + + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.req, + frame_header, + frame_buffer); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + default: + /* FIXME: what do we do here? */ + break; + } + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + +static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + struct dev_to_host_fis *frame_header; + struct sata_fis_data *frame_buffer; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + if (frame_header->fis_type == FIS_DATA) { + if (stp_req->type.pio.request_current.sgl_pair == NULL) { + sci_req->saved_rx_frame_index = frame_index; + stp_req->type.pio.pio_transfer_bytes = 0; + } else { + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + status = scic_sds_stp_request_pio_data_in_copy_data(stp_req, + (u8 *)frame_buffer); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + } + + /* Check for the end of the transfer, are there more + * bytes remaining for this data transfer + */ + if (status != SCI_SUCCESS || + stp_req->type.pio.pio_transfer_bytes != 0) + return status; + + if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) { + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + } else { + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + } + } else { + dev_err(scic_to_dev(scic), + "%s: SCIC PIO Request 0x%p received frame %d " + "with fis type 0x%02x when expecting a data " + "fis.\n", __func__, stp_req, frame_index, + frame_header->fis_type); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + } + + return status; +} + + +/** + * + * @sci_req: + * @completion_code: + * + * enum sci_status + */ +static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( + + struct scic_sds_request *sci_req, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + bool all_frames_transferred = false; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + /* Transmit data */ + if (stp_req->type.pio.pio_transfer_bytes != 0) { + status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); + if (status == SCI_SUCCESS) { + if (stp_req->type.pio.pio_transfer_bytes == 0) + all_frames_transferred = true; + } + } else if (stp_req->type.pio.pio_transfer_bytes == 0) { + /* + * this will happen if the all data is written at the + * first time after the pio setup fis is received + */ + all_frames_transferred = true; + } + + /* all data transferred. */ + if (all_frames_transferred) { + /* + * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE + * and wait for PIO_SETUP fis / or D2H REg fis. */ + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + } + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); + break; + } + + return status; +} + +/** + * + * @request: This is the request which is receiving the event. + * @event_code: This is the event code that the request on which the request is + * expected to take action. + * + * This method will handle any link layer events while waiting for the data + * frame. enum sci_status SCI_SUCCESS SCI_FAILURE + */ +static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler( + struct scic_sds_request *request, + u32 event_code) +{ + enum sci_status status; + + switch (scu_get_event_specifier(event_code)) { + case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: + /* + * We are waiting for data and the SCU has R_ERR the data frame. + * Go back to waiting for the D2H Register FIS */ + sci_base_state_machine_change_state( + &request->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + + status = SCI_SUCCESS; + break; + + default: + dev_err(scic_to_dev(request->owning_controller), + "%s: SCIC PIO Request 0x%p received unexpected " + "event 0x%08x\n", + __func__, request, event_code); + + /* / @todo Should we fail the PIO request when we get an unexpected event? */ + status = SCI_FAILURE; + break; + } + + return status; +} + +static void scic_sds_stp_request_udma_complete_request( + struct scic_sds_request *request, + u32 scu_status, + enum sci_status sci_status) +{ + scic_sds_request_set_status(request, scu_status, sci_status); + sci_base_state_machine_change_state(&request->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); +} + +static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; + struct dev_to_host_fis *frame_header; + enum sci_status status; + u32 *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if ((status == SCI_SUCCESS) && + (frame_header->fis_type == FIS_REGD2H)) { + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + } + + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + +static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + enum sci_status status = SCI_SUCCESS; + + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS); + break; + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): + /* + * We must check ther response buffer to see if the D2H Register FIS was + * received before we got the TC completion. */ + if (sci_req->stp.rsp.fis_type == FIS_REGD2H) { + scic_sds_remote_device_suspend(sci_req->target_device, + SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); + + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + } else { + /* + * If we have an error completion status for the TC then we can expect a + * D2H register FIS from the device so we must change state to wait for it */ + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE); + } + break; + + /* + * / @todo Check to see if any of these completion status need to wait for + * / the device to host register fis. */ + /* / @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 */ + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): + scic_sds_remote_device_suspend(sci_req->target_device, + SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); + /* Fall through to the default case */ + default: + /* All other completion status cause the IO to be complete. */ + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + break; + } + + return status; +} + +static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( + struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + + /* Use the general frame handler to copy the resposne data */ + status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); + + if (status != SCI_SUCCESS) + return status; + + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + return status; +} + +enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, + u32 len, + enum dma_data_direction dir) +{ + return SCI_SUCCESS; +} + +/** + * + * @sci_req: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. + */ +static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( + struct scic_sds_request *sci_req, + u32 completion_code) +{ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + scic_sds_request_set_status( + sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE + ); + break; + + default: + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); + break; } - scic_sds_controller_release_frame(sci_req->owning_controller, - frame_index); - return SCI_SUCCESS; } /** - * This method processes the completions transport layer (TL) status to - * determine if the SMP request was sent successfully. If the SMP request - * was sent successfully, then the state for the SMP request transits to - * waiting for a response frame. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. + * @sci_req: + * @completion_code: + * + * This method processes a TC completion. The expected TC completion is for + * the transmission of the H2D register FIS containing the SATA/STP non-data + * request. This method always successfully processes the TC completion. + * SCI_SUCCESS This value is always returned. */ -static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( +static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + SCI_SUCCESS); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE); break; default: @@ -1430,15 +2479,83 @@ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_ha SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } return SCI_SUCCESS; } +/** + * + * @request: This parameter specifies the request for which a frame has been + * received. + * @frame_index: This parameter specifies the index of the frame that has been + * received. + * + * This method processes frames received from the target while waiting for a + * device to host register FIS. If a non-register FIS is received during this + * time, it is treated as a protocol violation from an IO perspective. Indicate + * if the received frame was processed successfully. + */ +static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( + struct scic_sds_request *sci_req, + u32 frame_index) +{ + enum sci_status status; + struct dev_to_host_fis *frame_header; + u32 *frame_buffer; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = sci_req->owning_controller; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + switch (frame_header->fis_type) { + case FIS_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + /* The command has completed with error */ + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", __func__, stp_req, + frame_index); + + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION); + break; + } + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; +} + static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { }, [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { @@ -1467,6 +2584,52 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, + .frame_handler = scic_sds_stp_request_udma_general_frame_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, + .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { + .abort_handler = scic_sds_request_started_state_abort_handler, + .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, + }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .complete_handler = scic_sds_request_completed_state_complete_handler, }, @@ -2210,15 +3373,6 @@ static void scic_sds_request_constructed_state_enter(void *object) ); } -/** - * scic_sds_request_started_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This is cast into a SCIC_SDS_IO_REQUEST object. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a - * SCSI Task request we must enter the started substate machine. none - */ static void scic_sds_request_started_state_enter(void *object) { struct scic_sds_request *sci_req = object; @@ -2238,39 +3392,35 @@ static void scic_sds_request_started_state_enter(void *object) SCI_BASE_REQUEST_STATE_STARTED ); - /* Most of the request state machines have a started substate machine so - * start its execution on the entry to the started state. + /* all unaccelerated request types (non ssp or ncq) handled with + * substates */ - if (sci_req->has_started_substate_machine == true) - sci_base_state_machine_start(&sci_req->started_substate_machine); - if (!task && dev->dev_type == SAS_END_DEV) { sci_base_state_machine_change_state(sm, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION); + } else if (!task && + (isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high || + isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) { + sci_base_state_machine_change_state(sm, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE); } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { sci_base_state_machine_change_state(sm, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE); + } else if (task && sas_protocol_ata(task->task_proto) && + !task->ata_task.use_ncq) { + u32 state; + + if (task->data_dir == DMA_NONE) + state = SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE; + else if (task->ata_task.dma_xfer) + state = SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE; + else /* PIO */ + state = SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE; + + sci_base_state_machine_change_state(sm, state); } } -/** - * scic_sds_request_started_state_exit() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST - * object. - * - * This method implements the actions taken when exiting the - * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be - * to stop the started substate machine. none - */ -static void scic_sds_request_started_state_exit(void *object) -{ - struct scic_sds_request *sci_req = object; - - if (sci_req->has_started_substate_machine == true) - sci_base_state_machine_stop(&sci_req->started_substate_machine); -} - /** * scic_sds_request_completed_state_enter() - * @object: This parameter specifies the base object for which the state @@ -2392,6 +3542,175 @@ static void scic_sds_smp_request_started_await_tc_completion_substate_enter(void ); } +static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + sci_req->target_device, sci_req + ); +} + +static void scic_sds_stp_request_started_non_data_await_d2h_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE + ); +} + + + +static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + sci_req->target_device, sci_req); +} + +static void scic_sds_stp_request_started_pio_await_frame_enter(void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); +} + +static void scic_sds_stp_request_started_pio_data_in_await_data_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE + ); +} + +static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE + ); +} + + + +static void scic_sds_stp_request_started_udma_await_tc_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE + ); +} + +/** + * + * + * This state is entered when there is an TC completion failure. The hardware + * received an unexpected condition while processing the IO request and now + * will UF the D2H register FIS to complete the IO. + */ +static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE + ); +} + + + +static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE + ); + + scic_sds_remote_device_set_working_request( + sci_req->target_device, sci_req + ); +} + +static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + struct scu_task_context *task_context; + struct host_to_dev_fis *h2d_fis; + enum sci_status status; + + /* Clear the SRST bit */ + h2d_fis = &sci_req->stp.cmd; + h2d_fis->control = 0; + + /* Clear the TC control bit */ + task_context = scic_sds_controller_get_task_context_buffer( + sci_req->owning_controller, sci_req->io_tag); + task_context->control_frame = 0; + + status = scic_controller_continue_io(sci_req); + if (status == SCI_SUCCESS) { + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE + ); + } +} + +static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( + void *object) +{ + struct scic_sds_request *sci_req = object; + + SET_STATE_HANDLER( + sci_req, + scic_sds_request_state_handler_table, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE + ); +} + static const struct sci_base_state scic_sds_request_state_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = { .enter_state = scic_sds_request_initial_state_enter, @@ -2401,7 +3720,39 @@ static const struct sci_base_state scic_sds_request_state_table[] = { }, [SCI_BASE_REQUEST_STATE_STARTED] = { .enter_state = scic_sds_request_started_state_enter, - .exit_state = scic_sds_request_started_state_exit + }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_await_frame_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, + }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { + .enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter, }, [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, @@ -2437,7 +3788,6 @@ static void scic_sds_general_request_construct(struct scic_sds_controller *scic, sci_req->io_tag = io_tag; sci_req->owning_controller = scic; sci_req->target_device = sci_dev; - sci_req->has_started_substate_machine = false; sci_req->protocol = SCIC_NO_PROTOCOL; sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; sci_req->device_sequence = scic_sds_remote_device_get_sequence(sci_dev); @@ -3065,6 +4415,3 @@ int isci_request_execute( *isci_request = request; return ret; } - - - diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index d090cb1a14d6..95b65891fc41 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -59,7 +59,6 @@ #include "isci.h" #include "host.h" #include "scu_task_context.h" -#include "stp_request.h" /** * struct isci_request_status - This enum defines the possible states of an I/O @@ -90,6 +89,63 @@ enum sci_request_protocol { SCIC_STP_PROTOCOL }; /* XXX remove me, use sas_task.{dev|task_proto} instead */; +struct scic_sds_stp_request { + union { + u32 ncq; + + u32 udma; + + struct scic_sds_stp_pio_request { + /** + * Total transfer for the entire PIO request recorded at request constuction + * time. + * + * @todo Should we just decrement this value for each byte of data transitted + * or received to elemenate the current_transfer_bytes field? + */ + u32 total_transfer_bytes; + + /** + * Total number of bytes received/transmitted in data frames since the start + * of the IO request. At the end of the IO request this should equal the + * total_transfer_bytes. + */ + u32 current_transfer_bytes; + + /** + * The number of bytes requested in the in the PIO setup. + */ + u32 pio_transfer_bytes; + + /** + * PIO Setup ending status value to tell us if we need to wait for another FIS + * or if the transfer is complete. On the receipt of a D2H FIS this will be + * the status field of that FIS. + */ + u8 ending_status; + + /** + * On receipt of a D2H FIS this will be the ending error field if the + * ending_status has the SATA_STATUS_ERR bit set. + */ + u8 ending_error; + + struct scic_sds_request_pio_sgl { + struct scu_sgl_element_pair *sgl_pair; + u8 sgl_set; + u32 sgl_offset; + } request_current; + } pio; + + struct { + /** + * The number of bytes requested in the PIO setup before CDB data frame. + */ + u32 device_preferred_cdb_length; + } packet; + } type; +}; + struct scic_sds_request { /** * This field contains the information for the base request state machine. @@ -158,12 +214,6 @@ struct scic_sds_request { */ bool is_task_management_request; - /** - * This field indicates that this request contains an initialized started - * substate machine. - */ - bool has_started_substate_machine; - /** * This field is a pointer to the stored rx frame data. It is used in STP * internal requests and SMP response frames. If this field is non-NULL the @@ -173,12 +223,6 @@ struct scic_sds_request { */ u32 saved_rx_frame_index; - /** - * This field specifies the data necessary to manage the sub-state - * machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state. - */ - struct sci_base_state_machine started_substate_machine; - /** * This field specifies the current state handlers in place for this * IO Request object. This field is updated each time the request @@ -295,6 +339,41 @@ enum sci_base_request_states { */ SCI_BASE_REQUEST_STATE_STARTED, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, + + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, + + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, + + /** + * While in this state the IO request object is waiting for the TC completion + * notification for the H2D Register FIS + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE, + + /** + * While in this state the IO request object is waiting for either a PIO Setup + * FIS or a D2H register FIS. The type of frame received is based on the + * result of the prior frame and line conditions. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE, + + /** + * While in this state the IO request object is waiting for a DATA frame from + * the device. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE, + + /** + * While in this state the IO request object is waiting to transmit the next data + * frame to the device. + */ + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, + /** * The AWAIT_TC_COMPLETION sub-state indicates that the started raw * task management request is waiting for the transmission of the @@ -383,8 +462,6 @@ struct scic_sds_io_request_state_handler { }; -extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[]; - /** * scic_sds_request_get_controller() - * @@ -473,7 +550,6 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completi (scu_sge).address_modifier = 0; \ } -void scic_sds_request_build_sgl(struct scic_sds_request *sci_req); enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, @@ -481,8 +557,6 @@ enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_r enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, u32 frame_index); enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req); -enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); - /* XXX open code in caller */ static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, @@ -778,6 +852,9 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_request *sci_req); enum sci_status scic_task_request_construct_ssp(struct scic_sds_request *sci_req); enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req); +enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, + u32 transfer_length, + enum dma_data_direction dir); void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); #endif /* !defined(_ISCI_REQUEST_H_) */ diff --git a/drivers/scsi/isci/stp_request.c b/drivers/scsi/isci/stp_request.c deleted file mode 100644 index e94ece81ed9d..000000000000 --- a/drivers/scsi/isci/stp_request.c +++ /dev/null @@ -1,1584 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "sas.h" -#include "state_machine.h" -#include "remote_device.h" -#include "stp_request.h" -#include "unsolicited_frame_control.h" -#include "scu_completion_codes.h" -#include "scu_event_codes.h" -#include "scu_task_context.h" -#include "request.h" - -/** - * This method is will fill in the SCU Task Context for any type of SATA - * request. This is called from the various SATA constructors. - * @sci_req: The general IO request object which is to be used in - * constructing the SCU task context. - * @task_context: The buffer pointer for the SCU task context which is being - * constructed. - * - * The general io request construction is complete. The buffer assignment for - * the command buffer is complete. none Revisit task context construction to - * determine what is common for SSP/SMP/STP task context structures. - */ -static void scu_sata_reqeust_construct_task_context( - struct scic_sds_request *sci_req, - struct scu_task_context *task_context) -{ - dma_addr_t dma_addr; - struct scic_sds_controller *controller; - struct scic_sds_remote_device *target_device; - struct scic_sds_port *target_port; - - controller = scic_sds_request_get_controller(sci_req); - target_device = scic_sds_request_get_device(sci_req); - target_port = scic_sds_request_get_port(sci_req); - - /* Fill in the TC with the its required data */ - task_context->abort = 0; - task_context->priority = SCU_TASK_PRIORITY_NORMAL; - task_context->initiator_request = 1; - task_context->connection_rate = target_device->connection_rate; - task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(controller); - task_context->logical_port_index = - scic_sds_port_get_index(target_port); - task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; - task_context->valid = SCU_TASK_CONTEXT_VALID; - task_context->context_type = SCU_TASK_CONTEXT_TYPE; - - task_context->remote_node_index = - scic_sds_remote_device_get_index(sci_req->target_device); - task_context->command_code = 0; - - task_context->link_layer_control = 0; - task_context->do_not_dma_ssp_good_response = 1; - task_context->strict_ordering = 0; - task_context->control_frame = 0; - task_context->timeout_enable = 0; - task_context->block_guard_enable = 0; - - task_context->address_modifier = 0; - task_context->task_phase = 0x01; - - task_context->ssp_command_iu_length = - (sizeof(struct host_to_dev_fis) - sizeof(u32)) / sizeof(u32); - - /* Set the first word of the H2D REG FIS */ - task_context->type.words[0] = *(u32 *)&sci_req->stp.cmd; - - if (sci_req->was_tag_assigned_by_user) { - /* - * Build the task context now since we have already read - * the data - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sci_req->io_tag)); - } else { - /* - * Build the task context now since we have already read - * the data. - * I/O tag index is not assigned because we have to wait - * until we get a TCi. - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); - } - - /* - * Copy the physical address for the command buffer to the SCU Task - * Context. We must offset the command buffer by 4 bytes because the - * first 4 bytes are transfered in the body of the TC. - */ - dma_addr = scic_io_request_get_dma_addr(sci_req, - ((char *) &sci_req->stp.cmd) + - sizeof(u32)); - - task_context->command_iu_upper = upper_32_bits(dma_addr); - task_context->command_iu_lower = lower_32_bits(dma_addr); - - /* SATA Requests do not have a response buffer */ - task_context->response_iu_upper = 0; - task_context->response_iu_lower = 0; -} - -/** - * - * @sci_req: - * - * This method will perform any general sata request construction. What part of - * SATA IO request construction is general? none - */ -static void scic_sds_stp_non_ncq_request_construct( - struct scic_sds_request *sci_req) -{ - sci_req->has_started_substate_machine = true; -} - -/** - * - * @sci_req: This parameter specifies the request to be constructed as an - * optimized request. - * @optimized_task_type: This parameter specifies whether the request is to be - * an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A - * value of 1 indicates NCQ. - * - * This method will perform request construction common to all types of STP - * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method - * returns an indication as to whether the construction was successful. - */ -static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sci_req, - u8 optimized_task_type, - u32 len, - enum dma_data_direction dir) -{ - struct scu_task_context *task_context = sci_req->task_context_buffer; - - /* Build the STP task context structure */ - scu_sata_reqeust_construct_task_context(sci_req, task_context); - - /* Copy over the SGL elements */ - scic_sds_request_build_sgl(sci_req); - - /* Copy over the number of bytes to be transfered */ - task_context->transfer_length_bytes = len; - - if (dir == DMA_TO_DEVICE) { - /* - * The difference between the DMA IN and DMA OUT request task type - * values are consistent with the difference between FPDMA READ - * and FPDMA WRITE values. Add the supplied task type parameter - * to this difference to set the task type properly for this - * DATA OUT (WRITE) case. */ - task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT - - SCU_TASK_TYPE_DMA_IN); - } else { - /* - * For the DATA IN (READ) case, simply save the supplied - * optimized task type. */ - task_context->task_type = optimized_task_type; - } -} - -/** - * - * @sci_req: This parameter specifies the request to be constructed. - * - * This method will construct the STP UDMA request and its associated TC data. - * This method returns an indication as to whether the construction was - * successful. SCI_SUCCESS Currently this method always returns this value. - */ -enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_req, - u32 len, - enum dma_data_direction dir) -{ - scic_sds_stp_optimized_request_construct(sci_req, - SCU_TASK_TYPE_FPDMAQ_READ, - len, dir); - return SCI_SUCCESS; -} - -/** - * scu_stp_raw_request_construct_task_context - - * @sci_req: This parameter specifies the STP request object for which to - * construct a RAW command frame task context. - * @task_context: This parameter specifies the SCU specific task context buffer - * to construct. - * - * This method performs the operations common to all SATA/STP requests - * utilizing the raw frame method. none - */ -static void scu_stp_raw_request_construct_task_context( - struct scic_sds_stp_request *stp_req, - struct scu_task_context *task_context) -{ - struct scic_sds_request *sci_req = to_sci_req(stp_req); - - scu_sata_reqeust_construct_task_context(sci_req, task_context); - - task_context->control_frame = 0; - task_context->priority = SCU_TASK_PRIORITY_NORMAL; - task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; - task_context->type.stp.fis_type = FIS_REGH2D; - task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32); -} - -void scic_stp_io_request_set_ncq_tag( - struct scic_sds_request *req, - u16 ncq_tag) -{ - /** - * @note This could be made to return an error to the user if the user - * attempts to set the NCQ tag in the wrong state. - */ - req->task_context_buffer->type.stp.ncq_tag = ncq_tag; -} - -/** - * - * @sci_req: - * - * Get the next SGL element from the request. - Check on which SGL element pair - * we are working - if working on SLG pair element A - advance to element B - - * else - check to see if there are more SGL element pairs for this IO request - * - if there are more SGL element pairs - advance to the next pair and return - * element A struct scu_sgl_element* - */ -static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) -{ - struct scu_sgl_element *current_sgl; - struct scic_sds_request *sci_req = to_sci_req(stp_req); - struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current; - - if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - if (pio_sgl->sgl_pair->B.address_lower == 0 && - pio_sgl->sgl_pair->B.address_upper == 0) { - current_sgl = NULL; - } else { - pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B; - current_sgl = &pio_sgl->sgl_pair->B; - } - } else { - if (pio_sgl->sgl_pair->next_pair_lower == 0 && - pio_sgl->sgl_pair->next_pair_upper == 0) { - current_sgl = NULL; - } else { - u64 phys_addr; - - phys_addr = pio_sgl->sgl_pair->next_pair_upper; - phys_addr <<= 32; - phys_addr |= pio_sgl->sgl_pair->next_pair_lower; - - pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr); - pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A; - current_sgl = &pio_sgl->sgl_pair->A; - } - } - - return current_sgl; -} - -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - -/** - * - * @request: This parameter specifies the request for which a frame has been - * received. - * @frame_index: This parameter specifies the index of the frame that has been - * received. - * - * This method processes frames received from the target while waiting for a - * device to host register FIS. If a non-register FIS is received during this - * time, it is treated as a protocol violation from an IO perspective. Indicate - * if the received frame was processed successfully. - */ -static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - - return status; - } - - switch (frame_header->fis_type) { - case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - /* The command has completed with error */ - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", __func__, stp_req, - frame_index); - - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); - break; - } - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, - } -}; - -static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_non_data_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req - ); -} - -static void scic_sds_stp_request_started_non_data_await_d2h_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_non_data_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE - ); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter, - }, -}; - -enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req) -{ - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - scic_sds_stp_non_ncq_request_construct(sci_req); - - /* Build the STP task context structure */ - scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); - - sci_base_state_machine_construct(&sci_req->started_substate_machine, - sci_req, - scic_sds_stp_request_started_non_data_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE); - - return SCI_SUCCESS; -} - -#define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ - -/* transmit DATA_FIS from (current sgl + offset) for input - * parameter length. current sgl and offset is alreay stored in the IO request - */ -static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( - struct scic_sds_request *sci_req, - u32 length) -{ - struct scic_sds_controller *scic = sci_req->owning_controller; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scu_task_context *task_context; - struct scu_sgl_element *current_sgl; - - /* Recycle the TC and reconstruct it for sending out DATA FIS containing - * for the data from current_sgl+offset for the input length - */ - task_context = scic_sds_controller_get_task_context_buffer(scic, - sci_req->io_tag); - - if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) - current_sgl = &stp_req->type.pio.request_current.sgl_pair->A; - else - current_sgl = &stp_req->type.pio.request_current.sgl_pair->B; - - /* update the TC */ - task_context->command_iu_upper = current_sgl->address_upper; - task_context->command_iu_lower = current_sgl->address_lower; - task_context->transfer_length_bytes = length; - task_context->type.stp.fis_type = FIS_DATA; - - /* send the new TC out. */ - return scic_controller_continue_io(sci_req); -} - -static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct scic_sds_request *sci_req) -{ - - struct scu_sgl_element *current_sgl; - u32 sgl_offset; - u32 remaining_bytes_in_current_sgl = 0; - enum sci_status status = SCI_SUCCESS; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - sgl_offset = stp_req->type.pio.request_current.sgl_offset; - - if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A); - remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->A.length - sgl_offset; - } else { - current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B); - remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->B.length - sgl_offset; - } - - - if (stp_req->type.pio.pio_transfer_bytes > 0) { - if (stp_req->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { - /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ - status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, remaining_bytes_in_current_sgl); - if (status == SCI_SUCCESS) { - stp_req->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; - - /* update the current sgl, sgl_offset and save for future */ - current_sgl = scic_sds_stp_request_pio_get_next_sgl(stp_req); - sgl_offset = 0; - } - } else if (stp_req->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { - /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */ - scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->type.pio.pio_transfer_bytes); - - if (status == SCI_SUCCESS) { - /* Sgl offset will be adjusted and saved for future */ - sgl_offset += stp_req->type.pio.pio_transfer_bytes; - current_sgl->address_lower += stp_req->type.pio.pio_transfer_bytes; - stp_req->type.pio.pio_transfer_bytes = 0; - } - } - } - - if (status == SCI_SUCCESS) { - stp_req->type.pio.request_current.sgl_offset = sgl_offset; - } - - return status; -} - -/** - * - * @stp_request: The request that is used for the SGL processing. - * @data_buffer: The buffer of data to be copied. - * @length: The length of the data transfer. - * - * Copy the data from the buffer for the length specified to the IO reqeust SGL - * specified data region. enum sci_status - */ -static enum sci_status -scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req, - u8 *data_buf, u32 len) -{ - struct scic_sds_request *sci_req; - struct isci_request *ireq; - u8 *src_addr; - int copy_len; - struct sas_task *task; - struct scatterlist *sg; - void *kaddr; - int total_len = len; - - sci_req = to_sci_req(stp_req); - ireq = sci_req_to_ireq(sci_req); - task = isci_request_access_task(ireq); - src_addr = data_buf; - - if (task->num_scatter > 0) { - sg = task->scatter; - - while (total_len > 0) { - struct page *page = sg_page(sg); - - copy_len = min_t(int, total_len, sg_dma_len(sg)); - kaddr = kmap_atomic(page, KM_IRQ0); - memcpy(kaddr + sg->offset, src_addr, copy_len); - kunmap_atomic(kaddr, KM_IRQ0); - total_len -= copy_len; - src_addr += copy_len; - sg = sg_next(sg); - } - } else { - BUG_ON(task->total_xfer_len < total_len); - memcpy(task->scatter, src_addr, total_len); - } - - return SCI_SUCCESS; -} - -/** - * - * @sci_req: The PIO DATA IN request that is to receive the data. - * @data_buffer: The buffer to copy from. - * - * Copy the data buffer to the io request data region. enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( - struct scic_sds_stp_request *sci_req, - u8 *data_buffer) -{ - enum sci_status status; - - /* - * If there is less than 1K remaining in the transfer request - * copy just the data for the transfer */ - if (sci_req->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { - status = scic_sds_stp_request_pio_data_in_copy_data_buffer( - sci_req, data_buffer, sci_req->type.pio.pio_transfer_bytes); - - if (status == SCI_SUCCESS) - sci_req->type.pio.pio_transfer_bytes = 0; - } else { - /* We are transfering the whole frame so copy */ - status = scic_sds_stp_request_pio_data_in_copy_data_buffer( - sci_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); - - if (status == SCI_SUCCESS) - sci_req->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; - } - - return status; -} - -/** - * - * @sci_req: - * @completion_code: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - break; - } - - return status; -} - -static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - struct scic_sds_controller *scic = sci_req->owning_controller; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(ireq); - struct dev_to_host_fis *frame_header; - enum sci_status status; - u32 *frame_buffer; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - - switch (frame_header->fis_type) { - case FIS_PIO_SETUP: - /* Get from the frame buffer the PIO Setup Data */ - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - /* Get the data from the PIO Setup The SCU Hardware returns - * first word in the frame_header and the rest of the data is in - * the frame buffer so we need to back up one dword - */ - - /* transfer_count: first 16bits in the 4th dword */ - stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff; - - /* ending_status: 4th byte in the 3rd dword */ - stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - sci_req->stp.rsp.status = stp_req->type.pio.ending_status; - - /* The next state is dependent on whether the - * request was PIO Data-in or Data out - */ - if (task->data_dir == DMA_FROM_DEVICE) { - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); - } else if (task->data_dir == DMA_TO_DEVICE) { - /* Transmit data */ - status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); - if (status != SCI_SUCCESS) - break; - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); - } - break; - case FIS_SETDEVBITS: - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); - break; - case FIS_REGD2H: - if (frame_header->status & ATA_BUSY) { - /* Now why is the drive sending a D2H Register FIS when - * it is still busy? Do nothing since we are still in - * the right state. - */ - dev_dbg(scic_to_dev(scic), - "%s: SCIC PIO Request 0x%p received " - "D2H Register FIS with BSY status " - "0x%x\n", __func__, stp_req, - frame_header->status); - break; - } - - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.req, - frame_header, - frame_buffer); - - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - default: - /* FIXME: what do we do here? */ - break; - } - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - struct sata_fis_data *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - - if (frame_header->fis_type == FIS_DATA) { - if (stp_req->type.pio.request_current.sgl_pair == NULL) { - sci_req->saved_rx_frame_index = frame_index; - stp_req->type.pio.pio_transfer_bytes = 0; - } else { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - status = scic_sds_stp_request_pio_data_in_copy_data(stp_req, - (u8 *)frame_buffer); - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - } - - /* Check for the end of the transfer, are there more - * bytes remaining for this data transfer - */ - if (status != SCI_SUCCESS || - stp_req->type.pio.pio_transfer_bytes != 0) - return status; - - if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) { - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - } else { - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); - } - } else { - dev_err(scic_to_dev(scic), - "%s: SCIC PIO Request 0x%p received frame %d " - "with fis type 0x%02x when expecting a data " - "fis.\n", __func__, stp_req, frame_index, - frame_header->fis_type); - - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_GOOD, - SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - } - - return status; -} - - -/** - * - * @sci_req: - * @completion_code: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( - - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - bool all_frames_transferred = false; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - /* Transmit data */ - if (stp_req->type.pio.pio_transfer_bytes != 0) { - status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); - if (status == SCI_SUCCESS) { - if (stp_req->type.pio.pio_transfer_bytes == 0) - all_frames_transferred = true; - } - } else if (stp_req->type.pio.pio_transfer_bytes == 0) { - /* - * this will happen if the all data is written at the - * first time after the pio setup fis is received - */ - all_frames_transferred = true; - } - - /* all data transferred. */ - if (all_frames_transferred) { - /* - * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE - * and wait for PIO_SETUP fis / or D2H REg fis. */ - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); - } - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); - break; - } - - return status; -} - -/** - * - * @request: This is the request which is receiving the event. - * @event_code: This is the event code that the request on which the request is - * expected to take action. - * - * This method will handle any link layer events while waiting for the data - * frame. enum sci_status SCI_SUCCESS SCI_FAILURE - */ -static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler( - struct scic_sds_request *request, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_specifier(event_code)) { - case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: - /* - * We are waiting for data and the SCU has R_ERR the data frame. - * Go back to waiting for the D2H Register FIS */ - sci_base_state_machine_change_state( - &request->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); - - status = SCI_SUCCESS; - break; - - default: - dev_err(scic_to_dev(request->owning_controller), - "%s: SCIC PIO Request 0x%p received unexpected " - "event 0x%08x\n", - __func__, request, event_code); - - /* / @todo Should we fail the PIO request when we get an unexpected event? */ - status = SCI_FAILURE; - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, - .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, - } -}; - -static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_pio_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req); -} - -static void scic_sds_stp_request_started_pio_await_frame_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_pio_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); -} - -static void scic_sds_stp_request_started_pio_data_in_await_data_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_pio_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE - ); -} - -static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_pio_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE - ); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_await_frame_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter, - } -}; - -enum sci_status -scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, - bool copy_rx_frame) -{ - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; - - scic_sds_stp_non_ncq_request_construct(sci_req); - - scu_stp_raw_request_construct_task_context(stp_req, - sci_req->task_context_buffer); - - pio->current_transfer_bytes = 0; - pio->ending_error = 0; - pio->ending_status = 0; - - pio->request_current.sgl_offset = 0; - pio->request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; - - if (copy_rx_frame) { - scic_sds_request_build_sgl(sci_req); - /* Since the IO request copy of the TC contains the same data as - * the actual TC this pointer is vaild for either. - */ - pio->request_current.sgl_pair = &sci_req->task_context_buffer->sgl_pair_ab; - } else { - /* The user does not want the data copied to the SGL buffer location */ - pio->request_current.sgl_pair = NULL; - } - - sci_base_state_machine_construct(&sci_req->started_substate_machine, - sci_req, - scic_sds_stp_request_started_pio_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE); - - return SCI_SUCCESS; -} - -static void scic_sds_stp_request_udma_complete_request( - struct scic_sds_request *request, - u32 scu_status, - enum sci_status sci_status) -{ - scic_sds_request_set_status(request, scu_status, sci_status); - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); -} - -static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - struct scic_sds_controller *scic = sci_req->owning_controller; - struct dev_to_host_fis *frame_header; - enum sci_status status; - u32 *frame_buffer; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if ((status == SCI_SUCCESS) && - (frame_header->fis_type == FIS_REGD2H)) { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - } - - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - break; - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): - /* - * We must check ther response buffer to see if the D2H Register FIS was - * received before we got the TC completion. */ - if (sci_req->stp.rsp.fis_type == FIS_REGD2H) { - scic_sds_remote_device_suspend(sci_req->target_device, - SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); - - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - } else { - /* - * If we have an error completion status for the TC then we can expect a - * D2H register FIS from the device so we must change state to wait for it */ - sci_base_state_machine_change_state(&sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE); - } - break; - - /* - * / @todo Check to see if any of these completion status need to wait for - * / the device to host register fis. */ - /* / @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 */ - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): - scic_sds_remote_device_suspend(sci_req->target_device, - SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); - /* Fall through to the default case */ - default: - /* All other completion status cause the IO to be complete. */ - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - break; - } - - return status; -} - -static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - - /* Use the general frame handler to copy the resposne data */ - status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); - - if (status != SCI_SUCCESS) - return status; - - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, - .frame_handler = scic_sds_stp_request_udma_general_frame_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, - }, -}; - -static void scic_sds_stp_request_started_udma_await_tc_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_udma_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE - ); -} - -/** - * - * - * This state is entered when there is an TC completion failure. The hardware - * received an unexpected condition while processing the IO request and now - * will UF the D2H register FIS to complete the IO. - */ -static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_udma_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE - ); -} - -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter, - }, -}; - -enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, - u32 len, - enum dma_data_direction dir) -{ - scic_sds_stp_non_ncq_request_construct(sci_req); - - scic_sds_stp_optimized_request_construct(sci_req, SCU_TASK_TYPE_DMA_IN, - len, dir); - - sci_base_state_machine_construct( - &sci_req->started_substate_machine, - sci_req, - scic_sds_stp_request_started_udma_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE - ); - - return SCI_SUCCESS; -} - -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) -{ - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); - - sci_base_state_machine_change_state( - &sci_req->started_substate_machine, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE - ); - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - break; - } - - return SCI_SUCCESS; -} - -/** - * - * @request: This parameter specifies the request for which a frame has been - * received. - * @frame_index: This parameter specifies the index of the frame that has been - * received. - * - * This method processes frames received from the target while waiting for a - * device to host register FIS. If a non-register FIS is received during this - * time, it is treated as a protocol violation from an IO perspective. Indicate - * if the received frame was processed successfully. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - - switch (frame_header->fis_type) { - case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - /* The command has completed with error */ - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", __func__, stp_req, - frame_index); - - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); - break; - } - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, - .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, - }, -}; - -static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_soft_reset_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req - ); -} - -static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - struct scu_task_context *task_context; - struct host_to_dev_fis *h2d_fis; - enum sci_status status; - - /* Clear the SRST bit */ - h2d_fis = &sci_req->stp.cmd; - h2d_fis->control = 0; - - /* Clear the TC control bit */ - task_context = scic_sds_controller_get_task_context_buffer( - sci_req->owning_controller, sci_req->io_tag); - task_context->control_frame = 0; - - status = scic_controller_continue_io(sci_req); - if (status == SCI_SUCCESS) { - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_soft_reset_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE - ); - } -} - -static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_stp_request_started_soft_reset_substate_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE - ); -} - -static const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = { - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter, - }, -}; - -enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req) -{ - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - scic_sds_stp_non_ncq_request_construct(sci_req); - - /* Build the STP task context structure */ - scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer); - - sci_base_state_machine_construct(&sci_req->started_substate_machine, - sci_req, - scic_sds_stp_request_started_soft_reset_substate_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE); - - return SCI_SUCCESS; -} diff --git a/drivers/scsi/isci/stp_request.h b/drivers/scsi/isci/stp_request.h deleted file mode 100644 index eb14874ceda3..000000000000 --- a/drivers/scsi/isci/stp_request.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCIC_SDS_STP_REQUEST_T_ -#define _SCIC_SDS_STP_REQUEST_T_ - -#include -#include - -struct scic_sds_stp_request { - union { - u32 ncq; - - u32 udma; - - struct scic_sds_stp_pio_request { - /** - * Total transfer for the entire PIO request recorded at request constuction - * time. - * - * @todo Should we just decrement this value for each byte of data transitted - * or received to elemenate the current_transfer_bytes field? - */ - u32 total_transfer_bytes; - - /** - * Total number of bytes received/transmitted in data frames since the start - * of the IO request. At the end of the IO request this should equal the - * total_transfer_bytes. - */ - u32 current_transfer_bytes; - - /** - * The number of bytes requested in the in the PIO setup. - */ - u32 pio_transfer_bytes; - - /** - * PIO Setup ending status value to tell us if we need to wait for another FIS - * or if the transfer is complete. On the receipt of a D2H FIS this will be - * the status field of that FIS. - */ - u8 ending_status; - - /** - * On receipt of a D2H FIS this will be the ending error field if the - * ending_status has the SATA_STATUS_ERR bit set. - */ - u8 ending_error; - - struct scic_sds_request_pio_sgl { - struct scu_sgl_element_pair *sgl_pair; - u8 sgl_set; - u32 sgl_offset; - } request_current; - } pio; - - struct { - /** - * The number of bytes requested in the PIO setup before CDB data frame. - */ - u32 device_preferred_cdb_length; - } packet; - } type; -}; - -/** - * enum scic_sds_stp_request_started_udma_substates - This enumeration depicts - * the various sub-states associated with a SATA/STP UDMA protocol operation. - * - * - */ -enum scic_sds_stp_request_started_udma_substates { - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, -}; - -/** - * enum scic_sds_stp_request_started_non_data_substates - This enumeration - * depicts the various sub-states associated with a SATA/STP non-data - * protocol operation. - * - * - */ -enum scic_sds_stp_request_started_non_data_substates { - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, -}; - -/** - * enum scic_sds_stp_request_started_soft_reset_substates - THis enumeration - * depicts the various sub-states associated with a SATA/STP soft reset - * operation. - * - * - */ -enum scic_sds_stp_request_started_soft_reset_substates { - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, -}; - -/* This is the enumeration of the SATA PIO DATA IN started substate machine. */ -enum _scic_sds_stp_request_started_pio_substates { - /** - * While in this state the IO request object is waiting for the TC completion - * notification for the H2D Register FIS - */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE, - - /** - * While in this state the IO request object is waiting for either a PIO Setup - * FIS or a D2H register FIS. The type of frame received is based on the - * result of the prior frame and line conditions. - */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE, - - /** - * While in this state the IO request object is waiting for a DATA frame from - * the device. - */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE, - - /** - * While in this state the IO request object is waiting to transmit the next data - * frame to the device. - */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, -}; - -struct scic_sds_request; - -enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, - bool copy_rx_frame); -enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, - u32 transfer_length, - enum dma_data_direction dir); -enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req); -enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req); -enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_req, - u32 transfer_length, - enum dma_data_direction dir); -#endif /* _SCIC_SDS_STP_REQUEST_T_ */ -- cgit v1.2.3 From f00e6ba4996a34f098fe50c78077f0568fd838ec Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 May 2011 02:39:11 -0700 Subject: isci: unify request abort handlers Unify the implementation in scic_sds_io_request_terminate and kill the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 146 +++++++++++++++----------------------------- drivers/scsi/isci/request.h | 7 --- 2 files changed, 50 insertions(+), 103 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index f503e3e18d8f..69688636347e 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -777,16 +777,58 @@ scic_sds_request_start(struct scic_sds_request *request) } enum sci_status -scic_sds_io_request_terminate(struct scic_sds_request *request) +scic_sds_io_request_terminate(struct scic_sds_request *sci_req) { - if (request->state_handlers->abort_handler) - return request->state_handlers->abort_handler(request); + enum sci_base_request_states state; - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to abort while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); + state = sci_req->state_machine.current_state_id; + + switch (state) { + case SCI_BASE_REQUEST_STATE_CONSTRUCTED: + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_TASK_ABORT, + SCI_FAILURE_IO_TERMINATED); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + return SCI_SUCCESS; + case SCI_BASE_REQUEST_STATE_STARTED: + case SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION: + case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE: + case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION: + case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE: + case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE: + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_ABORTING); + return SCI_SUCCESS; + case SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE: + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_ABORTING); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + return SCI_SUCCESS; + case SCI_BASE_REQUEST_STATE_ABORTING: + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + return SCI_SUCCESS; + case SCI_BASE_REQUEST_STATE_COMPLETED: + default: + dev_warn(scic_to_dev(sci_req->owning_controller), + "%s: SCIC IO Request requested to abort while in wrong " + "state %d\n", + __func__, + sci_base_state_machine_get_state(&sci_req->state_machine)); + break; + } return SCI_FAILURE_INVALID_STATE; } @@ -930,34 +972,6 @@ static enum sci_status scic_sds_request_constructed_state_start_handler( return SCI_FAILURE_INSUFFICIENT_RESOURCES; } -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_terminate() request. Since the request - * has not yet been posted to the hardware the request transitions to the - * completed state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_constructed_state_abort_handler( - struct scic_sds_request *request) -{ - /* - * This request has been terminated by the user make sure that the correct - * status code is returned */ - scic_sds_request_set_status(request, - SCU_TASK_DONE_TASK_ABORT, - SCI_FAILURE_IO_TERMINATED); - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - return SCI_SUCCESS; -} - -static enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req) -{ - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); - return SCI_SUCCESS; -} - /* * scic_sds_request_started_state_tc_completion_handler() - This method process * TC (task context) completions for normal IO request (i.e. Task/Abort @@ -1247,26 +1261,6 @@ static enum sci_status scic_sds_request_completed_state_complete_handler( return SCI_SUCCESS; } -/* - * ***************************************************************************** - * * ABORTING STATE HANDLERS - * ***************************************************************************** */ - -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_terminate() request. This method is the - * io request aborting state abort handlers. On receipt of a multiple - * terminate requests the io request will transition to the completed state. - * This should not happen in normal operation. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_aborting_state_abort_handler( - struct scic_sds_request *request) -{ - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - return SCI_SUCCESS; -} - /* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_task_completion() request. This method @@ -1378,28 +1372,6 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi return SCI_SUCCESS; } -/** - * This method is responsible for processing a terminate/abort request for this - * TC while the request is waiting for the task management response - * unsolicited frame. - * @sci_req: This parameter specifies the request for which the - * termination was requested. - * - * This method returns an indication as to whether the abort request was - * successfully handled. need to update to ensure the received UF doesn't cause - * damage to subsequent requests (i.e. put the extended tag in a holding - * pattern for this particular device). - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( - struct scic_sds_request *request) -{ - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - return SCI_SUCCESS; -} - /** * This method processes an unsolicited frame while the task mgmt request is * waiting for a response frame. It will copy the response data, release @@ -2560,81 +2532,63 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han [SCI_BASE_REQUEST_STATE_INITIAL] = { }, [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { .start_handler = scic_sds_request_constructed_state_start_handler, - .abort_handler = scic_sds_request_constructed_state_abort_handler, }, [SCI_BASE_REQUEST_STATE_STARTED] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, .frame_handler = scic_sds_request_started_state_frame_handler, }, [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, }, [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, }, [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, .frame_handler = scic_sds_smp_request_await_response_frame_handler, }, [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, .frame_handler = scic_sds_stp_request_udma_general_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .abort_handler = scic_sds_request_started_state_abort_handler, .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .complete_handler = scic_sds_request_completed_state_complete_handler, }, [SCI_BASE_REQUEST_STATE_ABORTING] = { - .abort_handler = scic_sds_request_aborting_state_abort_handler, .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, .frame_handler = scic_sds_request_aborting_state_frame_handler, }, diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 95b65891fc41..b17336952314 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -444,12 +444,6 @@ struct scic_sds_io_request_state_handler { */ scic_sds_io_request_handler_t start_handler; - /** - * The abort_handler specifies the method invoked when a user attempts to - * abort a request. - */ - scic_sds_io_request_handler_t abort_handler; - /** * The complete_handler specifies the method invoked when a user attempts to * complete a request. @@ -459,7 +453,6 @@ struct scic_sds_io_request_state_handler { scic_sds_io_request_task_completion_handler_t tc_completion_handler; scic_sds_io_request_event_handler_t event_handler; scic_sds_io_request_frame_handler_t frame_handler; - }; /** -- cgit v1.2.3 From f4636a7b2ab8288466b83a8459d47c43143a70dc Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Tue, 10 May 2011 23:50:32 +0000 Subject: isci: unify request start handlers Unify the implementation in scic_sds_request_start and kill the state handler. Reported-by: Christoph Hellwig Signed-off-by: Piotr Sawicki [remove scic_sds_request_constructed_state_start_handler] Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 6 +- drivers/scsi/isci/request.c | 156 +++++++++++++++++--------------------- drivers/scsi/isci/request.h | 6 -- 3 files changed, 74 insertions(+), 94 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 0bb639dfbada..606ee2be154e 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -515,7 +515,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic if (status != SCI_SUCCESS) break; - status = sci_req->state_handlers->start_handler(sci_req); + status = scic_sds_request_start(sci_req); if (status != SCI_SUCCESS) break; @@ -540,7 +540,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic if (status != SCI_SUCCESS) break; - status = sci_req->state_handlers->start_handler(sci_req); + status = scic_sds_request_start(sci_req); } else return SCI_FAILURE_INVALID_STATE; break; @@ -709,7 +709,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc if (status != SCI_SUCCESS) goto out; - status = sci_req->state_handlers->start_handler(sci_req); + status = scic_sds_request_start(sci_req); if (status != SCI_SUCCESS) goto out; diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 69688636347e..41a418d8b337 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -757,23 +757,80 @@ static u32 sci_req_tx_bytes(struct scic_sds_request *sci_req) return ret_val; } -enum sci_status -scic_sds_request_start(struct scic_sds_request *request) +enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) { - if (request->device_sequence != - scic_sds_remote_device_get_sequence(request->target_device)) + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scu_task_context *task_context; + enum sci_base_request_states state; + + if (sci_req->device_sequence != + scic_sds_remote_device_get_sequence(sci_req->target_device)) return SCI_FAILURE; - if (request->state_handlers->start_handler) - return request->state_handlers->start_handler(request); + state = sci_req->state_machine.current_state_id; + if (state != SCI_BASE_REQUEST_STATE_CONSTRUCTED) { + dev_warn(scic_to_dev(scic), + "%s: SCIC IO Request requested to start while in wrong " + "state %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request requested to start while in wrong " - "state %d\n", - __func__, - sci_base_state_machine_get_state(&request->state_machine)); + /* if necessary, allocate a TCi for the io request object and then will, + * if necessary, copy the constructed TC data into the actual TC buffer. + * If everything is successful the post context field is updated with + * the TCi so the controller can post the request to the hardware. + */ + if (sci_req->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) + sci_req->io_tag = scic_controller_allocate_io_tag(scic); - return SCI_FAILURE_INVALID_STATE; + /* Record the IO Tag in the request */ + if (sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { + task_context = sci_req->task_context_buffer; + + task_context->task_index = scic_sds_io_tag_get_index(sci_req->io_tag); + + switch (task_context->protocol_type) { + case SCU_TASK_CONTEXT_PROTOCOL_SMP: + case SCU_TASK_CONTEXT_PROTOCOL_SSP: + /* SSP/SMP Frame */ + task_context->type.ssp.tag = sci_req->io_tag; + task_context->type.ssp.target_port_transfer_tag = + 0xFFFF; + break; + + case SCU_TASK_CONTEXT_PROTOCOL_STP: + /* STP/SATA Frame + * task_context->type.stp.ncq_tag = sci_req->ncq_tag; + */ + break; + + case SCU_TASK_CONTEXT_PROTOCOL_NONE: + /* / @todo When do we set no protocol type? */ + break; + + default: + /* This should never happen since we build the IO + * requests */ + break; + } + + /* + * Check to see if we need to copy the task context buffer + * or have been building into the task context buffer */ + if (sci_req->was_tag_assigned_by_user == false) + scic_sds_controller_copy_task_context(scic, sci_req); + + /* Add to the post_context the io tag value */ + sci_req->post_context |= scic_sds_io_tag_get_index(sci_req->io_tag); + + /* Everything is good go ahead and change state */ + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_STARTED); + + return SCI_SUCCESS; + } + + return SCI_FAILURE_INSUFFICIENT_RESOURCES; } enum sci_status @@ -903,75 +960,6 @@ static void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) memcpy(resp_buf, ssp_response->resp_data, len); } -/* - * This method implements the action taken when a constructed - * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request. - * This method will, if necessary, allocate a TCi for the io request object and - * then will, if necessary, copy the constructed TC data into the actual TC - * buffer. If everything is successful the post context field is updated with - * the TCi so the controller can post the request to the hardware. enum sci_status - * SCI_SUCCESS SCI_FAILURE_INSUFFICIENT_RESOURCES - */ -static enum sci_status scic_sds_request_constructed_state_start_handler( - struct scic_sds_request *request) -{ - struct scu_task_context *task_context; - - if (request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { - request->io_tag = - scic_controller_allocate_io_tag(request->owning_controller); - } - - /* Record the IO Tag in the request */ - if (request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { - task_context = request->task_context_buffer; - - task_context->task_index = scic_sds_io_tag_get_index(request->io_tag); - - switch (task_context->protocol_type) { - case SCU_TASK_CONTEXT_PROTOCOL_SMP: - case SCU_TASK_CONTEXT_PROTOCOL_SSP: - /* SSP/SMP Frame */ - task_context->type.ssp.tag = request->io_tag; - task_context->type.ssp.target_port_transfer_tag = 0xFFFF; - break; - - case SCU_TASK_CONTEXT_PROTOCOL_STP: - /* - * STP/SATA Frame - * task_context->type.stp.ncq_tag = request->ncq_tag; */ - break; - - case SCU_TASK_CONTEXT_PROTOCOL_NONE: - /* / @todo When do we set no protocol type? */ - break; - - default: - /* This should never happen since we build the IO requests */ - break; - } - - /* - * Check to see if we need to copy the task context buffer - * or have been building into the task context buffer */ - if (request->was_tag_assigned_by_user == false) { - scic_sds_controller_copy_task_context( - request->owning_controller, request); - } - - /* Add to the post_context the io tag value */ - request->post_context |= scic_sds_io_tag_get_index(request->io_tag); - - /* Everything is good go ahead and change state */ - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_STARTED); - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INSUFFICIENT_RESOURCES; -} - /* * scic_sds_request_started_state_tc_completion_handler() - This method process * TC (task context) completions for normal IO request (i.e. Task/Abort @@ -2529,10 +2517,8 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( } static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { - [SCI_BASE_REQUEST_STATE_INITIAL] = { }, - [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { - .start_handler = scic_sds_request_constructed_state_start_handler, - }, + [SCI_BASE_REQUEST_STATE_INITIAL] = {}, + [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = {}, [SCI_BASE_REQUEST_STATE_STARTED] = { .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, .frame_handler = scic_sds_request_started_state_frame_handler, diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index b17336952314..bf8ac1860850 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -438,12 +438,6 @@ typedef enum sci_status (*scic_sds_io_request_task_completion_handler_t) * */ struct scic_sds_io_request_state_handler { - /** - * The start_handler specifies the method invoked when a user attempts to - * start a request. - */ - scic_sds_io_request_handler_t start_handler; - /** * The complete_handler specifies the method invoked when a user attempts to * complete a request. -- cgit v1.2.3 From d1c637c35b33ddd2b405956e04b50939bb10ed2a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 11 May 2011 08:27:47 -0700 Subject: isci: unify request frame handlers Unify the implementation in scic_sds_io_request_frame_handler and kill the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 3 +- drivers/scsi/isci/request.c | 1106 ++++++++++++++++--------------------- drivers/scsi/isci/request.h | 6 - 3 files changed, 465 insertions(+), 650 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 606ee2be154e..b900e2c1b63e 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -310,8 +310,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi sci_req = scic_request_by_tag(scic, be16_to_cpu(hdr.tag)); if (sci_req && sci_req->target_device == sci_dev) { /* The IO request is now in charge of releasing the frame */ - status = sci_req->state_handlers->frame_handler(sci_req, - frame_index); + status = scic_sds_io_request_frame_handler(sci_req, frame_index); } else { /* We could not map this tag to a valid IO * request Just toss the frame and continue diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 41a418d8b337..b9f97e8cc5e0 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -907,34 +907,6 @@ enum sci_status scic_sds_io_request_event_handler( return SCI_FAILURE_INVALID_STATE; } -/** - * - * @sci_req: The SCIC_SDS_IO_REQUEST_T object for which the start - * operation is to be executed. - * @frame_index: The frame index returned by the hardware for the reqeust - * object. - * - * This method invokes the core state frame handler for the - * SCIC_SDS_IO_REQUEST_T object. enum sci_status - */ -enum sci_status scic_sds_io_request_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - if (request->state_handlers->frame_handler) - return request->state_handlers->frame_handler(request, frame_index); - - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given unexpected frame %x while in " - "state %d\n", - __func__, - frame_index, - sci_base_state_machine_get_state(&request->state_machine)); - - scic_sds_controller_release_frame(request->owning_controller, frame_index); - return SCI_FAILURE_INVALID_STATE; -} - /* * This function copies response data for requests returning response data * instead of sense data. @@ -1149,81 +1121,6 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completi return SCI_FAILURE_INVALID_STATE; } -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_frame_handler() request. This method - * first determines the frame type received. If this is a response frame then - * the response data is copied to the io request response buffer for processing - * at completion time. If the frame type is not a response buffer an error is - * logged. enum sci_status SCI_SUCCESS SCI_FAILURE_INVALID_PARAMETER_VALUE - */ -static enum sci_status -scic_sds_request_started_state_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - u32 *frame_header; - struct ssp_frame_hdr ssp_hdr; - ssize_t word_cnt; - - status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - (void **)&frame_header); - - word_cnt = sizeof(struct ssp_frame_hdr) / sizeof(u32); - sci_swab32_cpy(&ssp_hdr, frame_header, word_cnt); - - if (ssp_hdr.frame_type == SSP_RESPONSE) { - struct ssp_response_iu *resp_iu; - ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - - status = scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - (void **)&resp_iu); - - sci_swab32_cpy(&sci_req->ssp.rsp, - resp_iu, word_cnt); - - resp_iu = &sci_req->ssp.rsp; - - if ((resp_iu->datapres == 0x01) || - (resp_iu->datapres == 0x02)) { - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - } else - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - } else { - /* This was not a response frame why did it get forwarded? */ - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p received unexpected " - "frame %d type 0x%02x\n", - __func__, - sci_req, - frame_index, - ssp_hdr.frame_type); - } - - /* - * In any case we are done with this frame buffer return it to the - * controller - */ - scic_sds_controller_release_frame( - sci_req->owning_controller, frame_index); - - return SCI_SUCCESS; -} - -/* - * ***************************************************************************** - * * COMPLETED STATE HANDLERS - * ***************************************************************************** */ - - /* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_complete() request. This method frees up @@ -1281,24 +1178,6 @@ static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( return SCI_SUCCESS; } -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_frame_handler() request. This method - * discards the unsolicited frame since we are waiting for the abort task - * completion. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_aborting_state_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - /* TODO: Is it even possible to get an unsolicited frame in the aborting state? */ - - scic_sds_controller_release_frame( - sci_req->owning_controller, frame_index); - - return SCI_SUCCESS; -} - /** * This method processes the completions transport layer (TL) status to * determine if the RAW task management frame was sent successfully. If the @@ -1360,34 +1239,6 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi return SCI_SUCCESS; } -/** - * This method processes an unsolicited frame while the task mgmt request is - * waiting for a response frame. It will copy the response data, release - * the unsolicited frame, and transition the request to the - * SCI_BASE_REQUEST_STATE_COMPLETED state. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This method returns an indication of whether the TC response frame was - * handled successfully or not. SCI_SUCCESS Currently this value is always - * returned and indicates successful processing of the TC response. Should - * probably update to check frame type and make sure it is a response frame. - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( - struct scic_sds_request *request, - u32 frame_index) -{ - scic_sds_io_request_copy_response(request); - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - scic_sds_controller_release_frame(request->owning_controller, - frame_index); - return SCI_SUCCESS; -} - /** * This method processes an abnormal TC completion while the SMP request is * waiting for a response frame. It decides what happened to the IO based @@ -1450,81 +1301,6 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler return SCI_SUCCESS; } -/* - * This function processes an unsolicited frame while the SMP request is waiting - * for a response frame. It will copy the response data, release the - * unsolicited frame, and transition the request to the - * SCI_BASE_REQUEST_STATE_COMPLETED state. - * @sci_req: This parameter specifies the request for which the - * unsolicited frame was received. - * @frame_index: This parameter indicates the unsolicited frame index that - * should contain the response. - * - * This function returns an indication of whether the response frame was handled - * successfully or not. SCI_SUCCESS Currently this value is always returned and - * indicates successful processing of the TC response. - */ -static enum sci_status -scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - void *frame_header; - struct smp_resp *rsp_hdr = &sci_req->smp.rsp; - ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); - - status = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - &frame_header); - - /* byte swap the header. */ - sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); - - if (rsp_hdr->frame_type == SMP_RESPONSE) { - void *smp_resp; - - status = scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_request_get_controller(sci_req)->uf_control), - frame_index, - &smp_resp); - - word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / - sizeof(u32); - - sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, - smp_resp, word_cnt); - - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); - } else { - /* This was not a response frame why did it get forwarded? */ - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC SMP Request 0x%p received unexpected frame " - "%d type 0x%02x\n", - __func__, - sci_req, - frame_index, - rsp_hdr->frame_type); - - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_SMP_FRM_TYPE_ERR, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - } - - scic_sds_controller_release_frame(sci_req->owning_controller, - frame_index); - - return SCI_SUCCESS; -} - /** * This method processes the completions transport layer (TL) status to * determine if the SMP request was sent successfully. If the SMP request @@ -1668,76 +1444,6 @@ static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_han return SCI_SUCCESS; } -/** - * - * @request: This parameter specifies the request for which a frame has been - * received. - * @frame_index: This parameter specifies the index of the frame that has been - * received. - * - * This method processes frames received from the target while waiting for a - * device to host register FIS. If a non-register FIS is received during this - * time, it is treated as a protocol violation from an IO perspective. Indicate - * if the received frame was processed successfully. - */ -static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(sci_req->owning_controller), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - - return status; - } - - switch (frame_header->fis_type) { - case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - /* The command has completed with error */ - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", __func__, stp_req, - frame_index); - - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); - break; - } - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - #define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ /* transmit DATA_FIS from (current sgl + offset) for input @@ -1952,248 +1658,58 @@ static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completi return status; } -static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) +static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( + + struct scic_sds_request *sci_req, + u32 completion_code) { - struct scic_sds_controller *scic = sci_req->owning_controller; + enum sci_status status = SCI_SUCCESS; + bool all_frames_transferred = false; struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(ireq); - struct dev_to_host_fis *frame_header; - enum sci_status status; - u32 *frame_buffer; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - switch (frame_header->fis_type) { - case FIS_PIO_SETUP: - /* Get from the frame buffer the PIO Setup Data */ - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - /* Get the data from the PIO Setup The SCU Hardware returns - * first word in the frame_header and the rest of the data is in - * the frame buffer so we need to back up one dword - */ - - /* transfer_count: first 16bits in the 4th dword */ - stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff; - - /* ending_status: 4th byte in the 3rd dword */ - stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - sci_req->stp.rsp.status = stp_req->type.pio.ending_status; - - /* The next state is dependent on whether the - * request was PIO Data-in or Data out - */ - if (task->data_dir == DMA_FROM_DEVICE) { - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); - } else if (task->data_dir == DMA_TO_DEVICE) { - /* Transmit data */ + switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): + /* Transmit data */ + if (stp_req->type.pio.pio_transfer_bytes != 0) { status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); - if (status != SCI_SUCCESS) - break; - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); - } - break; - case FIS_SETDEVBITS: - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); - break; - case FIS_REGD2H: - if (frame_header->status & ATA_BUSY) { - /* Now why is the drive sending a D2H Register FIS when - * it is still busy? Do nothing since we are still in - * the right state. + if (status == SCI_SUCCESS) { + if (stp_req->type.pio.pio_transfer_bytes == 0) + all_frames_transferred = true; + } + } else if (stp_req->type.pio.pio_transfer_bytes == 0) { + /* + * this will happen if the all data is written at the + * first time after the pio setup fis is received */ - dev_dbg(scic_to_dev(scic), - "%s: SCIC PIO Request 0x%p received " - "D2H Register FIS with BSY status " - "0x%x\n", __func__, stp_req, - frame_header->status); - break; + all_frames_transferred = true; } - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.req, - frame_header, - frame_buffer); - - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + /* all data transferred. */ + if (all_frames_transferred) { + /* + * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE + * and wait for PIO_SETUP fis / or D2H REg fis. */ + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE + ); + } break; + default: - /* FIXME: what do we do here? */ - break; - } - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - -static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - struct sata_fis_data *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - - if (frame_header->fis_type == FIS_DATA) { - if (stp_req->type.pio.request_current.sgl_pair == NULL) { - sci_req->saved_rx_frame_index = frame_index; - stp_req->type.pio.pio_transfer_bytes = 0; - } else { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - status = scic_sds_stp_request_pio_data_in_copy_data(stp_req, - (u8 *)frame_buffer); - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - } - - /* Check for the end of the transfer, are there more - * bytes remaining for this data transfer - */ - if (status != SCI_SUCCESS || - stp_req->type.pio.pio_transfer_bytes != 0) - return status; - - if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) { - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - } else { - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); - } - } else { - dev_err(scic_to_dev(scic), - "%s: SCIC PIO Request 0x%p received frame %d " - "with fis type 0x%02x when expecting a data " - "fis.\n", __func__, stp_req, frame_index, - frame_header->fis_type); - - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_GOOD, - SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - } - - return status; -} - - -/** - * - * @sci_req: - * @completion_code: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( - - struct scic_sds_request *sci_req, - u32 completion_code) -{ - enum sci_status status = SCI_SUCCESS; - bool all_frames_transferred = false; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - - switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - /* Transmit data */ - if (stp_req->type.pio.pio_transfer_bytes != 0) { - status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); - if (status == SCI_SUCCESS) { - if (stp_req->type.pio.pio_transfer_bytes == 0) - all_frames_transferred = true; - } - } else if (stp_req->type.pio.pio_transfer_bytes == 0) { - /* - * this will happen if the all data is written at the - * first time after the pio setup fis is received - */ - all_frames_transferred = true; - } - - /* all data transferred. */ - if (all_frames_transferred) { - /* - * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE - * and wait for PIO_SETUP fis / or D2H REg fis. */ - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); - } - break; - - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); - - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + /* + * All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. */ + scic_sds_request_set_status( + sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR + ); + + sci_base_state_machine_change_state( + &sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED + ); break; } @@ -2280,6 +1796,422 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct sc return status; } +enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) +{ + struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + enum sci_base_request_states state; + enum sci_status status; + ssize_t word_cnt; + + state = sci_req->state_machine.current_state_id; + switch (state) { + case SCI_BASE_REQUEST_STATE_STARTED: { + struct ssp_frame_hdr ssp_hdr; + void *frame_header; + + scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + &frame_header); + + word_cnt = sizeof(struct ssp_frame_hdr) / sizeof(u32); + sci_swab32_cpy(&ssp_hdr, frame_header, word_cnt); + + if (ssp_hdr.frame_type == SSP_RESPONSE) { + struct ssp_response_iu *resp_iu; + ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); + + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&resp_iu); + + sci_swab32_cpy(&sci_req->ssp.rsp, resp_iu, word_cnt); + + resp_iu = &sci_req->ssp.rsp; + + if (resp_iu->datapres == 0x01 || + resp_iu->datapres == 0x02) { + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + } else + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS); + } else { + /* not a response frame, why did it get forwarded? */ + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p received unexpected " + "frame %d type 0x%02x\n", __func__, sci_req, + frame_index, ssp_hdr.frame_type); + } + + /* + * In any case we are done with this frame buffer return it to the + * controller + */ + scic_sds_controller_release_frame(scic, frame_index); + + return SCI_SUCCESS; + } + case SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE: + scic_sds_io_request_copy_response(sci_req); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + scic_sds_controller_release_frame(scic,frame_index); + return SCI_SUCCESS; + case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE: { + struct smp_resp *rsp_hdr = &sci_req->smp.rsp; + void *frame_header; + + scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + &frame_header); + + /* byte swap the header. */ + word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); + sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); + + if (rsp_hdr->frame_type == SMP_RESPONSE) { + void *smp_resp; + + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + &smp_resp); + + word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / + sizeof(u32); + + sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, + smp_resp, word_cnt); + + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + SCI_SUCCESS); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); + } else { + /* This was not a response frame why did it get forwarded? */ + dev_err(scic_to_dev(scic), + "%s: SCIC SMP Request 0x%p received unexpected frame " + "%d type 0x%02x\n", __func__, sci_req, + frame_index, rsp_hdr->frame_type); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_SMP_FRM_TYPE_ERR, + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + } + + scic_sds_controller_release_frame(scic, frame_index); + + return SCI_SUCCESS; + } + case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE: + return scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); + case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE: + /* Use the general frame handler to copy the resposne data */ + status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); + + if (status != SCI_SUCCESS) + return status; + + scic_sds_stp_request_udma_complete_request(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + return SCI_SUCCESS; + case SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE: { + struct dev_to_host_fis *frame_header; + u32 *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + + return status; + } + + switch (frame_header->fis_type) { + case FIS_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + /* The command has completed with error */ + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + break; + + default: + dev_warn(scic_to_dev(scic), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", __func__, stp_req, + frame_index); + + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION); + break; + } + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; + } + case SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE: { + struct isci_request *ireq = sci_req_to_ireq(sci_req); + struct sas_task *task = isci_request_access_task(ireq); + struct dev_to_host_fis *frame_header; + u32 *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + switch (frame_header->fis_type) { + case FIS_PIO_SETUP: + /* Get from the frame buffer the PIO Setup Data */ + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + /* Get the data from the PIO Setup The SCU Hardware returns + * first word in the frame_header and the rest of the data is in + * the frame buffer so we need to back up one dword + */ + + /* transfer_count: first 16bits in the 4th dword */ + stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff; + + /* ending_status: 4th byte in the 3rd dword */ + stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + sci_req->stp.rsp.status = stp_req->type.pio.ending_status; + + /* The next state is dependent on whether the + * request was PIO Data-in or Data out + */ + if (task->data_dir == DMA_FROM_DEVICE) { + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); + } else if (task->data_dir == DMA_TO_DEVICE) { + /* Transmit data */ + status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); + if (status != SCI_SUCCESS) + break; + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); + } + break; + case FIS_SETDEVBITS: + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + break; + case FIS_REGD2H: + if (frame_header->status & ATA_BUSY) { + /* Now why is the drive sending a D2H Register FIS when + * it is still busy? Do nothing since we are still in + * the right state. + */ + dev_dbg(scic_to_dev(scic), + "%s: SCIC PIO Request 0x%p received " + "D2H Register FIS with BSY status " + "0x%x\n", __func__, stp_req, + frame_header->status); + break; + } + + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.req, + frame_header, + frame_buffer); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + break; + default: + /* FIXME: what do we do here? */ + break; + } + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; + } + case SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE: { + struct dev_to_host_fis *frame_header; + struct sata_fis_data *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + if (frame_header->fis_type != FIS_DATA) { + dev_err(scic_to_dev(scic), + "%s: SCIC PIO Request 0x%p received frame %d " + "with fis type 0x%02x when expecting a data " + "fis.\n", __func__, stp_req, frame_index, + frame_header->fis_type); + + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + return status; + } + + if (stp_req->type.pio.request_current.sgl_pair == NULL) { + sci_req->saved_rx_frame_index = frame_index; + stp_req->type.pio.pio_transfer_bytes = 0; + } else { + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + status = scic_sds_stp_request_pio_data_in_copy_data(stp_req, + (u8 *)frame_buffer); + + /* Frame is decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + } + + /* Check for the end of the transfer, are there more + * bytes remaining for this data transfer + */ + if (status != SCI_SUCCESS || + stp_req->type.pio.pio_transfer_bytes != 0) + return status; + + if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) { + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + } else { + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + } + return status; + } + case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE: { + struct dev_to_host_fis *frame_header; + u32 *frame_buffer; + + status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_header); + if (status != SCI_SUCCESS) { + dev_err(scic_to_dev(scic), + "%s: SCIC IO Request 0x%p could not get frame header " + "for frame index %d, status %x\n", + __func__, stp_req, frame_index, status); + return status; + } + + switch (frame_header->fis_type) { + case FIS_REGD2H: + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&frame_buffer); + + scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + frame_header, + frame_buffer); + + /* The command has completed with error */ + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); + break; + default: + dev_warn(scic_to_dev(scic), + "%s: IO Request:0x%p Frame Id:%d protocol " + "violation occurred\n", __func__, stp_req, + frame_index); + + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + SCI_FAILURE_PROTOCOL_VIOLATION); + break; + } + + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); + + /* Frame has been decoded return it to the controller */ + scic_sds_controller_release_frame(scic, frame_index); + + return status; + } + case SCI_BASE_REQUEST_STATE_ABORTING: + /* TODO: Is it even possible to get an unsolicited frame in the + * aborting state? + */ + scic_sds_controller_release_frame(scic, frame_index); + return SCI_SUCCESS; + default: + dev_warn(scic_to_dev(scic), + "%s: SCIC IO Request given unexpected frame %x while in " + "state %d\n", __func__, frame_index, state); + + scic_sds_controller_release_frame(scic, frame_index); + return SCI_FAILURE_INVALID_STATE; + } +} + + + + static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( struct scic_sds_request *sci_req, u32 completion_code) @@ -2336,32 +2268,6 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi return status; } -static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - - /* Use the general frame handler to copy the resposne data */ - status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); - - if (status != SCI_SUCCESS) - return status; - - scic_sds_stp_request_udma_complete_request(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - - return status; -} - -enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, - u32 len, - enum dma_data_direction dir) -{ - return SCI_SUCCESS; -} - /** * * @sci_req: @@ -2447,117 +2353,36 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_c return SCI_SUCCESS; } -/** - * - * @request: This parameter specifies the request for which a frame has been - * received. - * @frame_index: This parameter specifies the index of the frame that has been - * received. - * - * This method processes frames received from the target while waiting for a - * device to host register FIS. If a non-register FIS is received during this - * time, it is treated as a protocol violation from an IO perspective. Indicate - * if the received frame was processed successfully. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( - struct scic_sds_request *sci_req, - u32 frame_index) -{ - enum sci_status status; - struct dev_to_host_fis *frame_header; - u32 *frame_buffer; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_controller *scic = sci_req->owning_controller; - - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_header); - if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); - return status; - } - - switch (frame_header->fis_type) { - case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&frame_buffer); - - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, - frame_header, - frame_buffer); - - /* The command has completed with error */ - scic_sds_request_set_status(sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - break; - - default: - dev_warn(scic_to_dev(scic), - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", __func__, stp_req, - frame_index); - - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); - break; - } - - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); - - /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); - - return status; -} - static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = {}, [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = {}, [SCI_BASE_REQUEST_STATE_STARTED] = { .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, - .frame_handler = scic_sds_request_started_state_frame_handler, }, [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, - }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { }, [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, - .frame_handler = scic_sds_smp_request_await_response_frame_handler, }, [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, }, [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, - .frame_handler = scic_sds_stp_request_udma_general_frame_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, - }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler - }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, - .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, @@ -2568,15 +2393,12 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, - }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .complete_handler = scic_sds_request_completed_state_complete_handler, }, [SCI_BASE_REQUEST_STATE_ABORTING] = { .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, - .frame_handler = scic_sds_request_aborting_state_frame_handler, }, [SCI_BASE_REQUEST_STATE_FINAL] = { }, }; diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index bf8ac1860850..c9070e708948 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -424,8 +424,6 @@ enum sci_base_request_states { typedef enum sci_status (*scic_sds_io_request_handler_t) (struct scic_sds_request *request); -typedef enum sci_status (*scic_sds_io_request_frame_handler_t) - (struct scic_sds_request *req, u32 frame); typedef enum sci_status (*scic_sds_io_request_event_handler_t) (struct scic_sds_request *req, u32 event); typedef enum sci_status (*scic_sds_io_request_task_completion_handler_t) @@ -446,7 +444,6 @@ struct scic_sds_io_request_state_handler { scic_sds_io_request_task_completion_handler_t tc_completion_handler; scic_sds_io_request_event_handler_t event_handler; - scic_sds_io_request_frame_handler_t frame_handler; }; /** @@ -839,9 +836,6 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_request *sci_req); enum sci_status scic_task_request_construct_ssp(struct scic_sds_request *sci_req); enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req); -enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req, - u32 transfer_length, - enum dma_data_direction dir); void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); #endif /* !defined(_ISCI_REQUEST_H_) */ -- cgit v1.2.3 From a7e255a34220ba57eeeb75637c911974e54c08e7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 11 May 2011 08:27:47 -0700 Subject: isci: remove request task context completion state handler Unlike the other conversions this only updates scic_sds_io_request_tc_completion() to call the old state handlers directly (with less verbose names). This was done for future patch readability, the implementations have only minor differences for different completion codes. Without a reference to the function name it would be difficult to dicern which state is being updated. Considered changing the order to look up the completion code before the state but that was not a clean conversion either. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 531 ++++++++++++++++---------------------------- drivers/scsi/isci/request.h | 3 - 2 files changed, 197 insertions(+), 337 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index b9f97e8cc5e0..cb13b78d8026 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -932,27 +932,14 @@ static void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) memcpy(resp_buf, ssp_response->resp_data, len); } -/* - * scic_sds_request_started_state_tc_completion_handler() - This method process - * TC (task context) completions for normal IO request (i.e. Task/Abort - * Completions of type 0). This method will update the - * SCIC_SDS_IO_REQUEST_T::status field. - * @sci_req: This parameter specifies the request for which a completion - * occurred. - * @completion_code: This parameter specifies the completion code received from - * the SCU. - * - */ -static enum sci_status -scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status request_started_state_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { - u8 datapres; struct ssp_response_iu *resp_iu; + u8 datapres; - /* - * TODO: Any SDMA return code of other than 0 is bad - * decode 0x003C0000 to determine SDMA status + /* TODO: Any SDMA return code of other than 0 is bad decode 0x003C0000 + * to determine SDMA status */ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): @@ -960,11 +947,8 @@ scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sc SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): - { - /* - * There are times when the SCU hardware will return an early + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): { + /* There are times when the SCU hardware will return an early * response because the io request specified more data than is * returned by the target device (mode pages, inquiry data, * etc.). We must check the response stats to see if this is @@ -979,21 +963,17 @@ scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sc word_cnt); if (resp->status == 0) { - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS_IO_DONE_EARLY); + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS_IO_DONE_EARLY); } else { - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); } + break; } - break; - - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): - { + case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): { ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); sci_swab32_cpy(&sci_req->ssp.rsp, @@ -1007,24 +987,22 @@ scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sc } case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR): - /* - * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame + /* TODO With TASK_DONE_RESP_LEN_ERR is the response frame * guaranteed to be received before this completion status is * posted? */ resp_iu = &sci_req->ssp.rsp; datapres = resp_iu->datapres; - if ((datapres == 0x01) || (datapres == 0x02)) { - scic_sds_request_set_status( - sci_req, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); + if (datapres == 1 || datapres == 2) { + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_CHECK_RESPONSE, + SCI_FAILURE_IO_RESPONSE_VALID); } else - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS); break; - /* only stp device gets suspended. */ case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR): @@ -1038,14 +1016,12 @@ scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sc case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): if (sci_req->protocol == SCIC_STP_PROTOCOL) { - scic_sds_request_set_status( - sci_req, + scic_sds_request_set_status(sci_req, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); } else { - scic_sds_request_set_status( - sci_req, + scic_sds_request_set_status(sci_req, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -1063,11 +1039,10 @@ scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sc case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): - scic_sds_request_set_status( - sci_req, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); + scic_sds_request_set_status(sci_req, + SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT, + SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); break; /* neither ssp nor stp gets suspended. */ @@ -1105,22 +1080,6 @@ scic_sds_request_started_state_tc_completion_handler(struct scic_sds_request *sc return SCI_SUCCESS; } -enum sci_status -scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code) -{ - if (request->state_handlers->tc_completion_handler) - return request->state_handlers->tc_completion_handler(request, completion_code); - - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given task completion notification %x " - "while in wrong state %d\n", - __func__, - completion_code, - sci_base_state_machine_get_state(&request->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - /* * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T * object receives a scic_sds_request_complete() request. This method frees up @@ -1146,54 +1105,32 @@ static enum sci_status scic_sds_request_completed_state_complete_handler( return SCI_SUCCESS; } -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_task_completion() request. This method - * decodes the completion type waiting for the abort task complete - * notification. When the abort task complete is received the io request - * transitions to the completed state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( +static enum sci_status request_aborting_state_tc_event( struct scic_sds_request *sci_req, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED - ); + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_TASK_ABORT, + SCI_FAILURE_IO_TERMINATED); sci_base_state_machine_change_state(&sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; default: - /* - * Unless we get some strange error wait for the task abort to complete - * TODO: Should there be a state change for this completion? */ + /* Unless we get some strange error wait for the task abort to complete + * TODO: Should there be a state change for this completion? + */ break; } return SCI_SUCCESS; } -/** - * This method processes the completions transport layer (TL) status to - * determine if the RAW task management frame was sent successfully. If the - * raw frame was sent successfully, then the state for the task request - * transitions to waiting for a response frame. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status ssp_task_request_await_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): @@ -1203,33 +1140,27 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi sci_base_state_machine_change_state(&sci_req->state_machine, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); break; - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): - /* - * Currently, the decision is to simply allow the task request to - * timeout if the task IU wasn't received successfully. - * There is a potential for receiving multiple task responses if we - * decide to send the task IU again. */ + /* Currently, the decision is to simply allow the task request + * to timeout if the task IU wasn't received successfully. + * There is a potential for receiving multiple task responses if + * we decide to send the task IU again. + */ dev_warn(scic_to_dev(sci_req->owning_controller), "%s: TaskRequest:0x%p CompletionCode:%x - " - "ACK/NAK timeout\n", - __func__, - sci_req, + "ACK/NAK timeout\n", __func__, sci_req, completion_code); sci_base_state_machine_change_state(&sci_req->state_machine, SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); break; - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, + /* All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request. + */ + scic_sds_request_set_status(sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); sci_base_state_machine_change_state(&sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); @@ -1239,27 +1170,15 @@ static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completi return SCI_SUCCESS; } -/** - * This method processes an abnormal TC completion while the SMP request is - * waiting for a response frame. It decides what happened to the IO based - * on TC completion status. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status smp_request_await_response_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - /* - * In the AWAIT RESPONSE state, any TC completion is unexpected. - * but if the TC has success status, we complete the IO anyway. */ + /* In the AWAIT RESPONSE state, any TC completion is + * unexpected. but if the TC has success status, we + * complete the IO anyway. + */ scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); @@ -1271,11 +1190,13 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): - /* - * These status has been seen in a specific LSI expander, which sometimes - * is not able to send smp response within 2 ms. This causes our hardware - * break the connection and set TC completion with one of these SMP_XXX_XX_ERR - * status. For these type of error, we ask scic user to retry the request. */ + /* These status has been seen in a specific LSI + * expander, which sometimes is not able to send smp + * response within 2 ms. This causes our hardware break + * the connection and set TC completion with one of + * these SMP_XXX_XX_ERR status. For these type of error, + * we ask scic user to retry the request. + */ scic_sds_request_set_status(sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED); @@ -1284,14 +1205,12 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler break; default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + /* All other completion status cause the IO to be complete. If a NAK + * was received, then it is up to the user to retry the request + */ + scic_sds_request_set_status(sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); sci_base_state_machine_change_state(&sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); @@ -1301,22 +1220,8 @@ static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler return SCI_SUCCESS; } -/** - * This method processes the completions transport layer (TL) status to - * determine if the SMP request was sent successfully. If the SMP request - * was sent successfully, then the state for the SMP request transits to - * waiting for a response frame. - * @sci_req: This parameter specifies the request for which the TC - * completion was received. - * @completion_code: This parameter indicates the completion status information - * for the TC. - * - * Indicate if the tc completion handler was successful. SCI_SUCCESS currently - * this method always returns success. - */ -static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status smp_request_await_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): @@ -1326,20 +1231,17 @@ static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_ha sci_base_state_machine_change_state(&sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); break; - default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + /* All other completion status cause the IO to be + * complete. If a NAK was received, then it is up to + * the user to retry the request. + */ + scic_sds_request_set_status(sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -1400,44 +1302,29 @@ static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic return current_sgl; } -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status stp_request_non_data_await_h2d_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + SCI_SUCCESS); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE); break; default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + /* All other completion status cause the IO to be + * complete. If a NAK was received, then it is up to + * the user to retry the request. + */ + scic_sds_request_set_status(sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state( - &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } @@ -1613,55 +1500,38 @@ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( return status; } -/** - * - * @sci_req: - * @completion_code: - * - * enum sci_status - */ -static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status stp_request_pio_await_h2d_completion_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { enum sci_status status = SCI_SUCCESS; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); break; default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + /* All other completion status cause the IO to be + * complete. If a NAK was received, then it is up to + * the user to retry the request. + */ + scic_sds_request_set_status(sci_req, + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } return status; } -static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( - - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status pio_data_out_tx_done_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { enum sci_status status = SCI_SUCCESS; bool all_frames_transferred = false; @@ -1695,7 +1565,6 @@ static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_com ); } break; - default: /* * All other completion status cause the IO to be complete. If a NAK @@ -2209,12 +2078,8 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r } } - - - -static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status stp_request_udma_await_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { enum sci_status status = SCI_SUCCESS; @@ -2226,9 +2091,10 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): - /* - * We must check ther response buffer to see if the D2H Register FIS was - * received before we got the TC completion. */ + /* We must check ther response buffer to see if the D2H + * Register FIS was received before we got the TC + * completion. + */ if (sci_req->stp.rsp.fis_type == FIS_REGD2H) { scic_sds_remote_device_suspend(sci_req->target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); @@ -2237,18 +2103,22 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); } else { - /* - * If we have an error completion status for the TC then we can expect a - * D2H register FIS from the device so we must change state to wait for it */ + /* If we have an error completion status for the + * TC then we can expect a D2H register FIS from + * the device so we must change state to wait + * for it + */ sci_base_state_machine_change_state(&sci_req->state_machine, SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE); } break; - /* - * / @todo Check to see if any of these completion status need to wait for - * / the device to host register fis. */ - /* / @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 */ + /* TODO Check to see if any of these completion status need to + * wait for the device to host register fis. + */ + /* TODO We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR + * - this comes only for B0 + */ case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): @@ -2268,61 +2138,35 @@ static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completi return status; } -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status stp_request_soft_reset_await_h2d_asserted_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status( - sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS - ); + scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + SCI_SUCCESS); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE - ); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE); break; default: /* * All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, + scic_sds_request_set_status(sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state( - &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED); + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_COMPLETED); break; } return SCI_SUCCESS; } -/** - * - * @sci_req: - * @completion_code: - * - * This method processes a TC completion. The expected TC completion is for - * the transmission of the H2D register FIS containing the SATA/STP non-data - * request. This method always successfully processes the TC completion. - * SCI_SUCCESS This value is always returned. - */ -static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( +static enum sci_status stp_request_soft_reset_await_h2d_diagnostic_tc_event( struct scic_sds_request *sci_req, u32 completion_code) { @@ -2336,70 +2180,89 @@ static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_c break; default: - /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ - scic_sds_request_set_status( - sci_req, + /* All other completion status cause the IO to be complete. If + * a NAK was received, then it is up to the user to retry the + * request. + */ + scic_sds_request_set_status(sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + SCI_BASE_REQUEST_STATE_COMPLETED); break; } return SCI_SUCCESS; } +enum sci_status +scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, u32 completion_code) +{ + enum sci_base_request_states state; + struct scic_sds_controller *scic = sci_req->owning_controller; + + state = sci_req->state_machine.current_state_id; + + switch (state) { + case SCI_BASE_REQUEST_STATE_STARTED: + return request_started_state_tc_event(sci_req, completion_code); + case SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION: + return ssp_task_request_await_tc_event(sci_req, completion_code); + case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE: + return smp_request_await_response_tc_event(sci_req, completion_code); + case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION: + return smp_request_await_tc_event(sci_req, completion_code); + case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE: + return stp_request_udma_await_tc_event(sci_req, completion_code); + case SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE: + return stp_request_non_data_await_h2d_tc_event(sci_req, completion_code); + case SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE: + return stp_request_pio_await_h2d_completion_tc_event(sci_req, completion_code); + case SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE: + return pio_data_out_tx_done_tc_event(sci_req, completion_code); + case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE: + return stp_request_soft_reset_await_h2d_asserted_tc_event(sci_req, completion_code); + case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE: + return stp_request_soft_reset_await_h2d_diagnostic_tc_event(sci_req, completion_code); + case SCI_BASE_REQUEST_STATE_ABORTING: + return request_aborting_state_tc_event(sci_req, completion_code); + default: + dev_warn(scic_to_dev(scic), + "%s: SCIC IO Request given task completion notification %x " + "while in wrong state %d\n", __func__, completion_code, + state); + return SCI_FAILURE_INVALID_STATE; + } +} + + + static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { [SCI_BASE_REQUEST_STATE_INITIAL] = {}, [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = {}, - [SCI_BASE_REQUEST_STATE_STARTED] = { - .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, - }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, - }, + [SCI_BASE_REQUEST_STATE_STARTED] = { }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { }, [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, - }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, - }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, - }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { - .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, - }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { - .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { - .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, - }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .complete_handler = scic_sds_request_completed_state_complete_handler, }, - [SCI_BASE_REQUEST_STATE_ABORTING] = { - .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, - }, + [SCI_BASE_REQUEST_STATE_ABORTING] = { }, [SCI_BASE_REQUEST_STATE_FINAL] = { }, }; diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index c9070e708948..e13ca3f7c8d7 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -426,8 +426,6 @@ typedef enum sci_status (*scic_sds_io_request_handler_t) (struct scic_sds_request *request); typedef enum sci_status (*scic_sds_io_request_event_handler_t) (struct scic_sds_request *req, u32 event); -typedef enum sci_status (*scic_sds_io_request_task_completion_handler_t) - (struct scic_sds_request *req, u32 completion_code); /** * struct scic_sds_io_request_state_handler - This is the SDS core definition @@ -442,7 +440,6 @@ struct scic_sds_io_request_state_handler { */ scic_sds_io_request_handler_t complete_handler; - scic_sds_io_request_task_completion_handler_t tc_completion_handler; scic_sds_io_request_event_handler_t event_handler; }; -- cgit v1.2.3 From 79e2b6b27699c916e3c7cda18a26d47fea6017fb Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 11 May 2011 08:29:56 -0700 Subject: isci: remove the completion and event state handlers With these handlers gone the rest of the state handler infrastructure is removed. Added some WARN_ONCEs where previously we would cause NULL pointer dereferences or silently run handlers from a previous state. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 514 +++++++------------------------------------- drivers/scsi/isci/request.h | 37 +--- 2 files changed, 82 insertions(+), 469 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index cb13b78d8026..c63064ede38d 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -890,21 +890,62 @@ scic_sds_io_request_terminate(struct scic_sds_request *sci_req) return SCI_FAILURE_INVALID_STATE; } -enum sci_status scic_sds_io_request_event_handler( - struct scic_sds_request *request, - u32 event_code) +enum sci_status scic_sds_request_complete(struct scic_sds_request *sci_req) { - if (request->state_handlers->event_handler) - return request->state_handlers->event_handler(request, event_code); + enum sci_base_request_states state; + struct scic_sds_controller *scic = sci_req->owning_controller; + + state = sci_req->state_machine.current_state_id; + if (WARN_ONCE(state != SCI_BASE_REQUEST_STATE_COMPLETED, + "isci: request completion from wrong state (%d)\n", state)) + return SCI_FAILURE_INVALID_STATE; - dev_warn(scic_to_dev(request->owning_controller), - "%s: SCIC IO Request given event code notification %x while " - "in wrong state %d\n", - __func__, - event_code, - sci_base_state_machine_get_state(&request->state_machine)); + if (!sci_req->was_tag_assigned_by_user) + scic_controller_free_io_tag(scic, sci_req->io_tag); - return SCI_FAILURE_INVALID_STATE; + if (sci_req->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) + scic_sds_controller_release_frame(scic, + sci_req->saved_rx_frame_index); + + /* XXX can we just stop the machine and remove the 'final' state? */ + sci_base_state_machine_change_state(&sci_req->state_machine, + SCI_BASE_REQUEST_STATE_FINAL); + return SCI_SUCCESS; +} + +enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, + u32 event_code) +{ + enum sci_base_request_states state; + struct scic_sds_controller *scic = sci_req->owning_controller; + + state = sci_req->state_machine.current_state_id; + + if (state != SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE) { + dev_warn(scic_to_dev(scic), "%s: (%x) in wrong state %d\n", + __func__, event_code, state); + + return SCI_FAILURE_INVALID_STATE; + } + + switch (scu_get_event_specifier(event_code)) { + case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: + /* We are waiting for data and the SCU has R_ERR the data frame. + * Go back to waiting for the D2H Register FIS + */ + sci_base_state_machine_change_state(&sci_req->state_machine, + SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + return SCI_SUCCESS; + default: + dev_err(scic_to_dev(scic), + "%s: pio request unexpected event %#x\n", + __func__, event_code); + + /* TODO Should we fail the PIO request when we get an + * unexpected event? + */ + return SCI_FAILURE; + } } /* @@ -1080,34 +1121,8 @@ static enum sci_status request_started_state_tc_event(struct scic_sds_request *s return SCI_SUCCESS; } -/* - * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T - * object receives a scic_sds_request_complete() request. This method frees up - * any io request resources that have been allocated and transitions the - * request to its final state. Consider stopping the state machine instead of - * transitioning to the final state? enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_request_completed_state_complete_handler( - struct scic_sds_request *request) -{ - if (request->was_tag_assigned_by_user != true) { - scic_controller_free_io_tag( - request->owning_controller, request->io_tag); - } - - if (request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) { - scic_sds_controller_release_frame( - request->owning_controller, request->saved_rx_frame_index); - } - - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_FINAL); - return SCI_SUCCESS; -} - -static enum sci_status request_aborting_state_tc_event( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status request_aborting_state_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): @@ -1585,48 +1600,6 @@ static enum sci_status pio_data_out_tx_done_tc_event(struct scic_sds_request *sc return status; } -/** - * - * @request: This is the request which is receiving the event. - * @event_code: This is the event code that the request on which the request is - * expected to take action. - * - * This method will handle any link layer events while waiting for the data - * frame. enum sci_status SCI_SUCCESS SCI_FAILURE - */ -static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler( - struct scic_sds_request *request, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_specifier(event_code)) { - case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: - /* - * We are waiting for data and the SCU has R_ERR the data frame. - * Go back to waiting for the D2H Register FIS */ - sci_base_state_machine_change_state( - &request->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); - - status = SCI_SUCCESS; - break; - - default: - dev_err(scic_to_dev(request->owning_controller), - "%s: SCIC PIO Request 0x%p received unexpected " - "event 0x%08x\n", - __func__, request, event_code); - - /* / @todo Should we fail the PIO request when we get an unexpected event? */ - status = SCI_FAILURE; - break; - } - - return status; -} - static void scic_sds_stp_request_udma_complete_request( struct scic_sds_request *request, u32 scu_status, @@ -2236,37 +2209,6 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, u32 completi } } - - -static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { - [SCI_BASE_REQUEST_STATE_INITIAL] = {}, - [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = {}, - [SCI_BASE_REQUEST_STATE_STARTED] = { }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { }, - [SCI_BASE_REQUEST_STATE_COMPLETED] = { - .complete_handler = scic_sds_request_completed_state_complete_handler, - }, - [SCI_BASE_REQUEST_STATE_ABORTING] = { }, - [SCI_BASE_REQUEST_STATE_FINAL] = { }, -}; - - /** * isci_request_process_response_iu() - This function sets the status and * response iu, in the task struct, from the request object for the upper @@ -2958,46 +2900,6 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, isci_host_can_dequeue(isci_host, 1); } -/** - * scic_sds_request_initial_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the initial - * base request is constructed. Entry into the initial state sets all handlers - * for the io request object to their default handlers. none - */ -static void scic_sds_request_initial_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_INITIAL - ); -} - -/** - * scic_sds_request_constructed_state_enter() - - * @object: The io request object that is to enter the constructed state. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_CONSTRUCTED state. The method sets the state handlers - * for the the constructed state. none - */ -static void scic_sds_request_constructed_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_CONSTRUCTED - ); -} - static void scic_sds_request_started_state_enter(void *object) { struct scic_sds_request *sci_req = object; @@ -3011,12 +2913,6 @@ static void scic_sds_request_started_state_enter(void *object) */ task = ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL; - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_STARTED - ); - /* all unaccelerated request types (non ssp or ncq) handled with * substates */ @@ -3046,30 +2942,13 @@ static void scic_sds_request_started_state_enter(void *object) } } -/** - * scic_sds_request_completed_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST - * object. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_COMPLETED state. This state is entered when the - * SCIC_SDS_IO_REQUEST has completed. The method will decode the request - * completion status and convert it to an enum sci_status to return in the - * completion callback function. none - */ static void scic_sds_request_completed_state_enter(void *object) { struct scic_sds_request *sci_req = object; - struct scic_sds_controller *scic = - scic_sds_request_get_controller(sci_req); + struct scic_sds_controller *scic = sci_req->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_request *ireq = sci_req_to_ireq(sci_req); - SET_STATE_HANDLER(sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_COMPLETED); - /* Tell the SCI_USER that the IO request is complete */ if (sci_req->is_task_management_request == false) isci_request_io_request_complete(ihost, ireq, @@ -3078,93 +2957,12 @@ static void scic_sds_request_completed_state_enter(void *object) isci_task_request_complete(ihost, ireq, sci_req->sci_status); } -/** - * scic_sds_request_aborting_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This object is cast into a SCIC_SDS_IO_REQUEST - * object. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_ABORTING state. none - */ static void scic_sds_request_aborting_state_enter(void *object) { struct scic_sds_request *sci_req = object; /* Setting the abort bit in the Task Context is required by the silicon. */ sci_req->task_context_buffer->abort = 1; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_ABORTING - ); -} - -/** - * scic_sds_request_final_state_enter() - - * @object: This parameter specifies the base object for which the state - * transition is occurring. This is cast into a SCIC_SDS_IO_REQUEST object. - * - * This method implements the actions taken when entering the - * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the - * state handlers in place. none - */ -static void scic_sds_request_final_state_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCI_BASE_REQUEST_STATE_FINAL - ); -} - -static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION - ); -} - -static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE - ); -} - -static void scic_sds_smp_request_started_await_response_substate_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE - ); -} - -static void scic_sds_smp_request_started_await_tc_completion_substate_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION - ); } static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( @@ -3172,133 +2970,27 @@ static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( { struct scic_sds_request *sci_req = object; - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req - ); -} - -static void scic_sds_stp_request_started_non_data_await_d2h_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE - ); -} - - - -static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req); -} - -static void scic_sds_stp_request_started_pio_await_frame_enter(void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); + scic_sds_remote_device_set_working_request(sci_req->target_device, + sci_req); } -static void scic_sds_stp_request_started_pio_data_in_await_data_enter( - void *object) +static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(void *object) { struct scic_sds_request *sci_req = object; - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE - ); + scic_sds_remote_device_set_working_request(sci_req->target_device, + sci_req); } -static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( - void *object) +static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(void *object) { struct scic_sds_request *sci_req = object; - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE - ); + scic_sds_remote_device_set_working_request(sci_req->target_device, + sci_req); } - - -static void scic_sds_stp_request_started_udma_await_tc_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE - ); -} - -/** - * - * - * This state is entered when there is an TC completion failure. The hardware - * received an unexpected condition while processing the IO request and now - * will UF the D2H register FIS to complete the IO. - */ -static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE - ); -} - - - -static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE - ); - - scic_sds_remote_device_set_working_request( - sci_req->target_device, sci_req - ); -} - -static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( - void *object) +static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(void *object) { struct scic_sds_request *sci_req = object; struct scu_task_context *task_context; @@ -3315,91 +3007,45 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet task_context->control_frame = 0; status = scic_controller_continue_io(sci_req); - if (status == SCI_SUCCESS) { - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE - ); - } -} - -static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( - void *object) -{ - struct scic_sds_request *sci_req = object; - - SET_STATE_HANDLER( - sci_req, - scic_sds_request_state_handler_table, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE - ); + WARN_ONCE(status != SCI_SUCCESS, "isci: continue io failure\n"); } static const struct sci_base_state scic_sds_request_state_table[] = { - [SCI_BASE_REQUEST_STATE_INITIAL] = { - .enter_state = scic_sds_request_initial_state_enter, - }, - [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { - .enter_state = scic_sds_request_constructed_state_enter, - }, + [SCI_BASE_REQUEST_STATE_INITIAL] = { }, + [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { }, [SCI_BASE_REQUEST_STATE_STARTED] = { .enter_state = scic_sds_request_started_state_enter, }, [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter, - }, + [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_await_frame_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter, - }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter, - }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { }, + [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { }, + [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, }, [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter, - }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { - .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, - }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { - .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, - }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { - .enter_state = scic_sds_smp_request_started_await_response_substate_enter, - }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { - .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, - }, + [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { }, + [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { }, + [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { }, [SCI_BASE_REQUEST_STATE_COMPLETED] = { .enter_state = scic_sds_request_completed_state_enter, }, [SCI_BASE_REQUEST_STATE_ABORTING] = { .enter_state = scic_sds_request_aborting_state_enter, }, - [SCI_BASE_REQUEST_STATE_FINAL] = { - .enter_state = scic_sds_request_final_state_enter, - }, + [SCI_BASE_REQUEST_STATE_FINAL] = { }, }; static void scic_sds_general_request_construct(struct scic_sds_controller *scic, diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index e13ca3f7c8d7..31d6d5717473 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -223,13 +223,6 @@ struct scic_sds_request { */ u32 saved_rx_frame_index; - /** - * This field specifies the current state handlers in place for this - * IO Request object. This field is updated each time the request - * changes state. - */ - const struct scic_sds_io_request_state_handler *state_handlers; - /** * This field in the recorded device sequence for the io request. This is * recorded during the build operation and is compared in the start @@ -422,27 +415,6 @@ enum sci_base_request_states { SCI_BASE_REQUEST_STATE_FINAL, }; -typedef enum sci_status (*scic_sds_io_request_handler_t) - (struct scic_sds_request *request); -typedef enum sci_status (*scic_sds_io_request_event_handler_t) - (struct scic_sds_request *req, u32 event); - -/** - * struct scic_sds_io_request_state_handler - This is the SDS core definition - * of the state handlers. - * - * - */ -struct scic_sds_io_request_state_handler { - /** - * The complete_handler specifies the method invoked when a user attempts to - * complete a request. - */ - scic_sds_io_request_handler_t complete_handler; - - scic_sds_io_request_event_handler_t event_handler; -}; - /** * scic_sds_request_get_controller() - * @@ -495,13 +467,6 @@ struct scic_sds_io_request_state_handler { (request)->sci_status = (sci_status_code); \ } -#define scic_sds_request_complete(a_request) \ - ((a_request)->state_handlers->complete_handler(a_request)) - - -extern enum sci_status -scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completion_code); - /** * SCU_SGL_ZERO() - * @@ -538,6 +503,8 @@ enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_r enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, u32 frame_index); enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req); +extern enum sci_status scic_sds_request_complete(struct scic_sds_request *sci_req); +extern enum sci_status scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, u32 code); /* XXX open code in caller */ static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, -- cgit v1.2.3 From 4a33c525f0e94b57602abd1e43644cbf6f5418f4 Mon Sep 17 00:00:00 2001 From: Adam Gruchala Date: Tue, 10 May 2011 23:54:23 +0000 Subject: isci: merge phy substates Merged states and substates into one state machine, as we always unconditionally transitioned to the substate machine it was straightforward to enter that substate from the starting state. Reported-by: Christoph Hellwig Signed-off-by: Adam Gruchala [fixed construction, starting_state_enter, and starting check] Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 24 ++- drivers/scsi/isci/phy.c | 500 ++++++++++++++++++++++------------------------- drivers/scsi/isci/phy.h | 51 ++--- 3 files changed, 276 insertions(+), 299 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 2bb9f1073e73..675eddd3963e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -932,6 +932,28 @@ static void scic_sds_controller_phy_timer_start(struct scic_sds_controller *scic scic->phy_startup_timer_pending = true; } +static bool is_phy_starting(struct scic_sds_phy *sci_phy) +{ + enum scic_sds_phy_states state; + + state = sci_phy->state_machine.current_state_id; + switch (state) { + case SCI_BASE_PHY_STATE_STARTING: + case SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: + case SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL: + return true; + default: + return false; + } +} + /** * scic_sds_controller_start_next_phy - start phy * @scic: controller @@ -975,7 +997,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro (sci_phy->is_in_link_training == false && state == SCI_BASE_PHY_STATE_STOPPED) || (sci_phy->is_in_link_training == true && - state == SCI_BASE_PHY_STATE_STARTING)) { + is_phy_starting(sci_phy))) { is_controller_start_complete = false; break; } diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 0f64605200ff..e5ae676926f2 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -271,8 +271,6 @@ static void scic_sds_phy_sata_timeout(void *phy) __func__, sci_phy); - sci_base_state_machine_stop(&sci_phy->starting_substate_machine); - sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STARTING); } @@ -546,7 +544,7 @@ static void scic_sds_phy_start_sas_link_training( &sci_phy->link_layer_registers->phy_configuration); sci_base_state_machine_change_state( - &sci_phy->starting_substate_machine, + &sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN ); @@ -565,7 +563,7 @@ static void scic_sds_phy_start_sata_link_training( struct scic_sds_phy *sci_phy) { sci_base_state_machine_change_state( - &sci_phy->starting_substate_machine, + &sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER ); @@ -590,16 +588,13 @@ static void scic_sds_phy_complete_link_training( { sci_phy->max_negotiated_speed = max_link_rate; - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, next_state); } static void scic_sds_phy_restart_starting_state( struct scic_sds_phy *sci_phy) { - /* Stop the current substate machine */ - sci_base_state_machine_stop(&sci_phy->starting_substate_machine); - /* Re-enter the base state machine starting state */ sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STARTING); @@ -611,8 +606,6 @@ static void scic_sds_phy_restart_starting_state( static enum sci_status scic_sds_phy_starting_substate_general_stop_handler( struct scic_sds_phy *phy) { - sci_base_state_machine_stop(&phy->starting_substate_machine); - sci_base_state_machine_change_state(&phy->state_machine, SCI_BASE_PHY_STATE_STOPPED); @@ -919,7 +912,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handl sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; /* We have received the SATA PHY notification change state */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); break; @@ -1042,7 +1035,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handle switch (scu_get_event_code(event_code)) { case SCU_EVENT_SATA_PHY_DETECTED: /* Backup the state machine */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); break; @@ -1118,7 +1111,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; } sci_base_state_machine_change_state( - &sci_phy->starting_substate_machine, + &sci_phy->state_machine, state); result = SCI_SUCCESS; } else @@ -1177,7 +1170,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handle fis_frame_data); /* got IAF we can now go to the await spinup semaphore state */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); result = SCI_SUCCESS; @@ -1216,7 +1209,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_po writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control); /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); return SCI_SUCCESS; @@ -1248,7 +1241,7 @@ static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_p &sci_phy->link_layer_registers->phy_configuration); /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); return SCI_SUCCESS; @@ -1312,9 +1305,156 @@ scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) return default_phy_handler(sci_phy, __func__); } +/* + * This method takes the struct scic_sds_phy from a stopped state and + * attempts to start it. - The phy state machine is transitioned to the + * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS + */ +static enum sci_status +scic_sds_phy_stopped_state_start_handler(struct scic_sds_phy *sci_phy) +{ + struct isci_host *ihost; + struct scic_sds_controller *scic; + + scic = scic_sds_phy_get_controller(sci_phy), + ihost = scic_to_ihost(scic); + /* Create the SIGNATURE FIS Timeout timer for this phy */ + sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, + scic_sds_phy_sata_timeout); + + if (sci_phy->sata_timeout_timer) + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + + return SCI_SUCCESS; +} + +static enum sci_status +scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) +{ + return SCI_SUCCESS; +} + +static enum sci_status +scic_sds_phy_ready_state_stop_handler(struct scic_sds_phy *sci_phy) +{ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STOPPED); + + return SCI_SUCCESS; +} + +static enum sci_status +scic_sds_phy_ready_state_reset_handler(struct scic_sds_phy *sci_phy) +{ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_RESETTING); + + return SCI_SUCCESS; +} -static const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_handler_table[] = { +/** + * scic_sds_phy_ready_state_event_handler - + * @phy: This is the struct scic_sds_phy object which has received the event. + * + * This method request the struct scic_sds_phy handle the received event. The only + * event that we are interested in while in the ready state is the link failure + * event. - decoded event is a link failure - transition the struct scic_sds_phy back + * to the SCI_BASE_PHY_STATE_STARTING state. - any other event received will + * report a warning message enum sci_status SCI_SUCCESS if the event received is a + * link failure SCI_FAILURE_INVALID_STATE for any other event received. + */ +static enum sci_status scic_sds_phy_ready_state_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) +{ + enum sci_status result = SCI_FAILURE; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + result = SCI_SUCCESS; + break; + + case SCU_EVENT_BROADCAST_CHANGE: + /* Broadcast change received. Notify the port. */ + if (scic_sds_phy_get_port(sci_phy) != NULL) + scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); + else + sci_phy->bcn_received_while_port_unassigned = true; + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%sP SCIC PHY 0x%p ready state machine received " + "unexpected event_code %x\n", + __func__, sci_phy, event_code); + + result = SCI_FAILURE_INVALID_STATE; + break; + } + + return result; +} + +static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) +{ + enum sci_status result = SCI_FAILURE; + + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_HARD_RESET_TRANSMITTED: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + result = SCI_SUCCESS; + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: SCIC PHY 0x%p resetting state machine received " + "unexpected event_code %x\n", + __func__, sci_phy, event_code); + + result = SCI_FAILURE_INVALID_STATE; + break; + } + + return result; +} + +/* --------------------------------------------------------------------------- */ + +static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { + [SCI_BASE_PHY_STATE_INITIAL] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_STOPPED] = { + .start_handler = scic_sds_phy_stopped_state_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_STARTING] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, @@ -1404,20 +1544,36 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_starting_substate_ha .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_READY] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_ready_state_stop_handler, + .reset_handler = scic_sds_phy_ready_state_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_ready_state_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_RESETTING] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_resetting_state_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler + }, + [SCI_BASE_PHY_STATE_FINAL] = { + .start_handler = scic_sds_phy_default_start_handler, + .stop_handler = scic_sds_phy_default_stop_handler, + .reset_handler = scic_sds_phy_default_reset_handler, + .destruct_handler = scic_sds_phy_default_destroy_handler, + .frame_handler = scic_sds_phy_default_frame_handler, + .event_handler = scic_sds_phy_default_event_handler, + .consume_power_handler = scic_sds_phy_default_consume_power_handler } }; -/** - * scic_sds_phy_set_starting_substate_handlers() - - * - * This macro sets the starting substate handlers by state_id - */ -#define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \ - scic_sds_phy_set_state_handlers(\ - (phy), \ - &scic_sds_phy_starting_substate_handler_table[(state_id)] \ - ) - /* * **************************************************************************** * * PHY STARTING SUBSTATE METHODS @@ -1436,11 +1592,11 @@ static void scic_sds_phy_starting_initial_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); /* This is just an temporary state go off to the starting state */ - sci_base_state_machine_change_state(&sci_phy->starting_substate_machine, + sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN); } @@ -1456,7 +1612,7 @@ static void scic_sds_phy_starting_await_ossp_en_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN ); } @@ -1474,7 +1630,7 @@ static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN ); } @@ -1491,7 +1647,7 @@ static void scic_sds_phy_starting_await_iaf_uf_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF ); } @@ -1509,7 +1665,7 @@ static void scic_sds_phy_starting_await_sas_power_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER ); @@ -1549,7 +1705,7 @@ static void scic_sds_phy_starting_await_sata_power_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER ); @@ -1589,7 +1745,7 @@ static void scic_sds_phy_starting_await_sata_phy_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); @@ -1626,7 +1782,7 @@ static void scic_sds_phy_starting_await_sata_speed_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); @@ -1666,7 +1822,7 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) bool continue_to_ready_state; struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers( + scic_sds_phy_set_base_state_handlers( sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); @@ -1719,7 +1875,7 @@ static void scic_sds_phy_starting_final_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_starting_substate_handlers(sci_phy, + scic_sds_phy_set_base_state_handlers(sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); /* State machine has run to completion so exit out and change @@ -1729,225 +1885,6 @@ static void scic_sds_phy_starting_final_substate_enter(void *object) SCI_BASE_PHY_STATE_READY); } -/* --------------------------------------------------------------------------- */ - -static const struct sci_base_state scic_sds_phy_starting_substates[] = { - [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .enter_state = scic_sds_phy_starting_initial_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .enter_state = scic_sds_phy_starting_await_ossp_en_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .enter_state = scic_sds_phy_starting_await_sas_speed_en_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .enter_state = scic_sds_phy_starting_await_iaf_uf_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, - .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter, - .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .enter_state = scic_sds_phy_starting_final_substate_enter, - } -}; - -/* - * This method takes the struct scic_sds_phy from a stopped state and - * attempts to start it. - The phy state machine is transitioned to the - * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS - */ -static enum sci_status -scic_sds_phy_stopped_state_start_handler(struct scic_sds_phy *sci_phy) -{ - struct isci_host *ihost; - struct scic_sds_controller *scic; - - scic = scic_sds_phy_get_controller(sci_phy), - ihost = scic_to_ihost(scic); - - /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, - scic_sds_phy_sata_timeout); - - if (sci_phy->sata_timeout_timer) - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - - return SCI_SUCCESS; -} - -static enum sci_status -scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) -{ - return SCI_SUCCESS; -} - -static enum sci_status -scic_sds_phy_ready_state_stop_handler(struct scic_sds_phy *sci_phy) -{ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); - - return SCI_SUCCESS; -} - -static enum sci_status -scic_sds_phy_ready_state_reset_handler(struct scic_sds_phy *sci_phy) -{ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_RESETTING); - - return SCI_SUCCESS; -} - -/** - * scic_sds_phy_ready_state_event_handler - - * @phy: This is the struct scic_sds_phy object which has received the event. - * - * This method request the struct scic_sds_phy handle the received event. The only - * event that we are interested in while in the ready state is the link failure - * event. - decoded event is a link failure - transition the struct scic_sds_phy back - * to the SCI_BASE_PHY_STATE_STARTING state. - any other event received will - * report a warning message enum sci_status SCI_SUCCESS if the event received is a - * link failure SCI_FAILURE_INVALID_STATE for any other event received. - */ -static enum sci_status scic_sds_phy_ready_state_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) -{ - enum sci_status result = SCI_FAILURE; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - result = SCI_SUCCESS; - break; - - case SCU_EVENT_BROADCAST_CHANGE: - /* Broadcast change received. Notify the port. */ - if (scic_sds_phy_get_port(sci_phy) != NULL) - scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); - else - sci_phy->bcn_received_while_port_unassigned = true; - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%sP SCIC PHY 0x%p ready state machine received " - "unexpected event_code %x\n", - __func__, sci_phy, event_code); - - result = SCI_FAILURE_INVALID_STATE; - break; - } - - return result; -} - -static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) -{ - enum sci_status result = SCI_FAILURE; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_HARD_RESET_TRANSMITTED: - /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - result = SCI_SUCCESS; - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: SCIC PHY 0x%p resetting state machine received " - "unexpected event_code %x\n", - __func__, sci_phy, event_code); - - result = SCI_FAILURE_INVALID_STATE; - break; - } - - return result; -} - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { - [SCI_BASE_PHY_STATE_INITIAL] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_STOPPED] = { - .start_handler = scic_sds_phy_stopped_state_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_STARTING] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_READY] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_ready_state_stop_handler, - .reset_handler = scic_sds_phy_ready_state_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_ready_state_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_RESETTING] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_resetting_state_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_FINAL] = { - .start_handler = scic_sds_phy_default_start_handler, - .stop_handler = scic_sds_phy_default_stop_handler, - .reset_handler = scic_sds_phy_default_reset_handler, - .destruct_handler = scic_sds_phy_default_destroy_handler, - .frame_handler = scic_sds_phy_default_frame_handler, - .event_handler = scic_sds_phy_default_event_handler, - .consume_power_handler = scic_sds_phy_default_consume_power_handler - } -}; - /* * **************************************************************************** * * PHY STATE PRIVATE METHODS @@ -2118,9 +2055,6 @@ static void scic_sds_phy_starting_state_enter(void *object) sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; sci_phy->bcn_received_while_port_unassigned = false; - /* Change over to the starting substate machine to continue */ - sci_base_state_machine_start(&sci_phy->starting_substate_machine); - if (sci_phy->state_machine.previous_state_id == SCI_BASE_PHY_STATE_READY) { scic_sds_controller_link_down( @@ -2129,6 +2063,9 @@ static void scic_sds_phy_starting_state_enter(void *object) sci_phy ); } + + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); } /** @@ -2231,6 +2168,41 @@ static const struct sci_base_state scic_sds_phy_state_table[] = { [SCI_BASE_PHY_STATE_STARTING] = { .enter_state = scic_sds_phy_starting_state_enter, }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { + .enter_state = scic_sds_phy_starting_initial_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { + .enter_state = scic_sds_phy_starting_await_ossp_en_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { + .enter_state = scic_sds_phy_starting_await_sas_speed_en_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { + .enter_state = scic_sds_phy_starting_await_iaf_uf_substate_enter, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { + .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, + .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { + .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { + .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { + .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter, + .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { + .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter, + .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit + }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { + .enter_state = scic_sds_phy_starting_final_substate_enter, + }, [SCI_BASE_PHY_STATE_READY] = { .enter_state = scic_sds_phy_ready_state_enter, .exit_state = scic_sds_phy_ready_state_exit, @@ -2261,12 +2233,6 @@ void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, sci_phy->link_layer_registers = NULL; sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; sci_phy->sata_timeout_timer = NULL; - - /* Initialize the the substate machines */ - sci_base_state_machine_construct(&sci_phy->starting_substate_machine, - sci_phy, - scic_sds_phy_starting_substates, - SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); } void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index) diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index f1800368eda5..bf0296463c80 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -142,8 +142,6 @@ struct scic_sds_phy { const struct scic_sds_phy_state_handler *state_handlers; - struct sci_base_state_machine starting_substate_machine; - /** * This field is the pointer to the transport layer register for the SCU * hardware. @@ -435,34 +433,6 @@ enum scic_sds_phy_states { */ SCI_BASE_PHY_STATE_STARTING, - /** - * This state indicates the the phy is now ready. Thus, the user - * is able to perform IO operations utilizing this phy as long as it - * is currently part of a valid port. - * This state is entered from the STARTING state. - */ - SCI_BASE_PHY_STATE_READY, - - /** - * This state indicates that the phy is in the process of being reset. - * In this state no new IO operations are permitted on this phy. - * This state is entered from the READY state. - */ - SCI_BASE_PHY_STATE_RESETTING, - - /** - * Simply the final state for the base phy state machine. - */ - SCI_BASE_PHY_STATE_FINAL, -}; - - -/** - * enum scic_sds_phy_starting_substates - - * - * - */ -enum scic_sds_phy_starting_substates { /** * Initial state */ @@ -512,8 +482,27 @@ enum scic_sds_phy_starting_substates { * Exit state for this state machine */ SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL, -}; + /** + * This state indicates the the phy is now ready. Thus, the user + * is able to perform IO operations utilizing this phy as long as it + * is currently part of a valid port. + * This state is entered from the STARTING state. + */ + SCI_BASE_PHY_STATE_READY, + + /** + * This state indicates that the phy is in the process of being reset. + * In this state no new IO operations are permitted on this phy. + * This state is entered from the READY state. + */ + SCI_BASE_PHY_STATE_RESETTING, + + /** + * Simply the final state for the base phy state machine. + */ + SCI_BASE_PHY_STATE_FINAL, +}; typedef enum sci_status (*scic_sds_phy_handler_t)(struct scic_sds_phy *); -- cgit v1.2.3 From 966699b50c61940e06ff39fb1085bea813f9a51d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 03:44:24 -0700 Subject: isci: unify phy start handlers Implement all handlers in scic_sds_phy_start(), and kill the state handler Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 74 +++++++++++++------------------------------------ drivers/scsi/isci/phy.h | 6 ---- 2 files changed, 19 insertions(+), 61 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index e5ae676926f2..7cae192a2a30 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -440,16 +440,27 @@ void scic_sds_phy_get_protocols(struct scic_sds_phy *sci_phy, 0x0000FFFF); } -/** - * This method will attempt to start the phy object. This request is only valid - * when the phy is in the stopped state - * @sci_phy: - * - * enum sci_status - */ enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) { - return sci_phy->state_handlers->start_handler(sci_phy); + struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + struct isci_host *ihost = scic_to_ihost(scic); + + if (state != SCI_BASE_PHY_STATE_STOPPED) { + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + /* Create the SIGNATURE FIS Timeout timer for this phy */ + sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, + scic_sds_phy_sata_timeout); + + if (sci_phy->sata_timeout_timer) + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + + return SCI_SUCCESS; } /** @@ -1256,12 +1267,6 @@ static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_phy_default_start_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - static enum sci_status scic_sds_phy_default_stop_handler(struct scic_sds_phy *sci_phy) { @@ -1305,31 +1310,6 @@ scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) return default_phy_handler(sci_phy, __func__); } -/* - * This method takes the struct scic_sds_phy from a stopped state and - * attempts to start it. - The phy state machine is transitioned to the - * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS - */ -static enum sci_status -scic_sds_phy_stopped_state_start_handler(struct scic_sds_phy *sci_phy) -{ - struct isci_host *ihost; - struct scic_sds_controller *scic; - - scic = scic_sds_phy_get_controller(sci_phy), - ihost = scic_to_ihost(scic); - - /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, - scic_sds_phy_sata_timeout); - - if (sci_phy->sata_timeout_timer) - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - - return SCI_SUCCESS; -} - static enum sci_status scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) { @@ -1429,7 +1409,6 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sd static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1438,7 +1417,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STOPPED] = { - .start_handler = scic_sds_phy_stopped_state_start_handler, .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, @@ -1447,7 +1425,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STARTING] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1456,7 +1433,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1465,7 +1441,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1474,7 +1449,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1483,7 +1457,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1492,7 +1465,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1501,7 +1473,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1510,7 +1481,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1519,7 +1489,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1528,7 +1497,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1537,7 +1505,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1546,7 +1513,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_READY] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_ready_state_stop_handler, .reset_handler = scic_sds_phy_ready_state_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1555,7 +1521,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_RESETTING] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, @@ -1564,7 +1529,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_FINAL] = { - .start_handler = scic_sds_phy_default_start_handler, .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index bf0296463c80..9b7d54e64e8f 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -511,12 +511,6 @@ typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); struct scic_sds_phy_state_handler { - /** - * The start_handler specifies the method invoked when there is an - * attempt to start a phy. - */ - scic_sds_phy_handler_t start_handler; - /** * The stop_handler specifies the method invoked when there is an * attempt to stop a phy. -- cgit v1.2.3 From 931532364e7966f61683bdf40fa1698d6707f523 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 04:01:03 -0700 Subject: isci: unify phy stop handlers Merge all implementations in scic_sds_phy_stop(), and kill the state handler Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 79 ++++++++++++++----------------------------------- drivers/scsi/isci/phy.h | 6 ---- 2 files changed, 23 insertions(+), 62 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 7cae192a2a30..cf8f2e9f6b25 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -463,16 +463,31 @@ enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) return SCI_SUCCESS; } -/** - * This method will attempt to stop the phy object. - * @sci_phy: - * - * enum sci_status SCI_SUCCESS if the phy is going to stop SCI_INVALID_STATE - * if the phy is not in a valid state to stop - */ enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) { - return sci_phy->state_handlers->stop_handler(sci_phy); + enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + + switch (state) { + case SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN: + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: + case SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL: + case SCI_BASE_PHY_STATE_READY: + break; + default: + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STOPPED); + return SCI_SUCCESS; } /** @@ -611,23 +626,6 @@ static void scic_sds_phy_restart_starting_state( SCI_BASE_PHY_STATE_STARTING); } -/* **************************************************************************** - * SCIC SDS PHY general handlers - ************************************************************************** */ -static enum sci_status scic_sds_phy_starting_substate_general_stop_handler( - struct scic_sds_phy *phy) -{ - sci_base_state_machine_change_state(&phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); - - return SCI_SUCCESS; -} - -/* - * ***************************************************************************** - * * SCIC SDS PHY EVENT_HANDLERS - * ***************************************************************************** */ - /** * * @phy: This struct scic_sds_phy object which has received an event. @@ -1267,12 +1265,6 @@ static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_phy_default_stop_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - static enum sci_status scic_sds_phy_default_reset_handler(struct scic_sds_phy *sci_phy) { @@ -1316,15 +1308,6 @@ scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) return SCI_SUCCESS; } -static enum sci_status -scic_sds_phy_ready_state_stop_handler(struct scic_sds_phy *sci_phy) -{ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); - - return SCI_SUCCESS; -} - static enum sci_status scic_sds_phy_ready_state_reset_handler(struct scic_sds_phy *sci_phy) { @@ -1409,7 +1392,6 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sd static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { - .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1417,7 +1399,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STOPPED] = { - .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1425,7 +1406,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STARTING] = { - .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1433,7 +1413,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1441,7 +1420,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1449,7 +1427,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1457,7 +1434,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, @@ -1465,7 +1441,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1473,7 +1448,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1481,7 +1455,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1489,7 +1462,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1497,7 +1469,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, @@ -1505,7 +1476,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .stop_handler = scic_sds_phy_starting_substate_general_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1513,7 +1483,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_READY] = { - .stop_handler = scic_sds_phy_ready_state_stop_handler, .reset_handler = scic_sds_phy_ready_state_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1521,7 +1490,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_RESETTING] = { - .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, @@ -1529,7 +1497,6 @@ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[ .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_FINAL] = { - .stop_handler = scic_sds_phy_default_stop_handler, .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 9b7d54e64e8f..d829e15eed10 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -511,12 +511,6 @@ typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); struct scic_sds_phy_state_handler { - /** - * The stop_handler specifies the method invoked when there is an - * attempt to stop a phy. - */ - scic_sds_phy_handler_t stop_handler; - /** * The reset_handler specifies the method invoked when there is an * attempt to reset a phy. -- cgit v1.2.3 From 0cf36fa9f1197e669ac6f5efc51d0587bcc95e6e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 04:02:07 -0700 Subject: isci: unify phy reset handlers Unify the implementations in scic_sds_phy_reset(), and kill the state handler Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 53 +++++++++++-------------------------------------- drivers/scsi/isci/phy.h | 6 ------ 2 files changed, 12 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index cf8f2e9f6b25..b606e2f317d5 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -490,17 +490,19 @@ enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) return SCI_SUCCESS; } -/** - * This method will attempt to reset the phy. This request is only valid when - * the phy is in an ready state - * @sci_phy: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_reset( - struct scic_sds_phy *sci_phy) +enum sci_status scic_sds_phy_reset(struct scic_sds_phy *sci_phy) { - return sci_phy->state_handlers->reset_handler(sci_phy); + enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + + if (state != SCI_BASE_PHY_STATE_READY) { + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_RESETTING); + return SCI_SUCCESS; } /** @@ -1265,12 +1267,6 @@ static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_phy_default_reset_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - static enum sci_status scic_sds_phy_default_destroy_handler(struct scic_sds_phy *sci_phy) { @@ -1308,15 +1304,6 @@ scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) return SCI_SUCCESS; } -static enum sci_status -scic_sds_phy_ready_state_reset_handler(struct scic_sds_phy *sci_phy) -{ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_RESETTING); - - return SCI_SUCCESS; -} - /** * scic_sds_phy_ready_state_event_handler - * @phy: This is the struct scic_sds_phy object which has received the event. @@ -1392,112 +1379,96 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sd static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STOPPED] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STARTING] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_READY] = { - .reset_handler = scic_sds_phy_ready_state_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_ready_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_RESETTING] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_resetting_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_FINAL] = { - .reset_handler = scic_sds_phy_default_reset_handler, .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index d829e15eed10..56474333dfca 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -511,12 +511,6 @@ typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); struct scic_sds_phy_state_handler { - /** - * The reset_handler specifies the method invoked when there is an - * attempt to reset a phy. - */ - scic_sds_phy_handler_t reset_handler; - /** * The destruct_handler specifies the method invoked when attempting to * destruct a phy. -- cgit v1.2.3 From 35b317bec511b4a5f87a637bf78b6d1d635c617d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 04:10:41 -0700 Subject: isci: remove phy destruct handlers Unused infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 28 ---------------------------- drivers/scsi/isci/phy.h | 6 ------ 2 files changed, 34 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index b606e2f317d5..8beea40697da 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -1267,12 +1267,6 @@ static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_phy_default_destroy_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - static enum sci_status scic_sds_phy_default_frame_handler(struct scic_sds_phy *sci_phy, u32 frame_index) @@ -1298,12 +1292,6 @@ scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) return default_phy_handler(sci_phy, __func__); } -static enum sci_status -scic_sds_phy_stopped_state_destroy_handler(struct scic_sds_phy *sci_phy) -{ - return SCI_SUCCESS; -} - /** * scic_sds_phy_ready_state_event_handler - * @phy: This is the struct scic_sds_phy object which has received the event. @@ -1379,97 +1367,81 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sd static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STOPPED] = { - .destruct_handler = scic_sds_phy_stopped_state_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STARTING] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_READY] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_ready_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_RESETTING] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_resetting_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_FINAL] = { - .destruct_handler = scic_sds_phy_default_destroy_handler, .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 56474333dfca..24536d6eef81 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -511,12 +511,6 @@ typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); struct scic_sds_phy_state_handler { - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a phy. - */ - scic_sds_phy_handler_t destruct_handler; - /** * The state handler for unsolicited frames received from the SCU hardware. */ -- cgit v1.2.3 From c4441abc25a33ab259f01dce4b4d63721013f86d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 04:17:51 -0700 Subject: isci: unify phy frame handlers Unify the implementations in scic_sds_phy_frame_handler(), and kill the state handler Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 267 +++++++++++++++++------------------------------- drivers/scsi/isci/phy.h | 5 - 2 files changed, 93 insertions(+), 179 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 8beea40697da..433ea605f70b 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -519,18 +519,100 @@ enum sci_status scic_sds_phy_event_handler( return sci_phy->state_handlers->event_handler(sci_phy, event_code); } -/** - * This method will process the frame index received. - * @sci_phy: - * @frame_index: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_frame_handler( - struct scic_sds_phy *sci_phy, - u32 frame_index) +enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, + u32 frame_index) { - return sci_phy->state_handlers->frame_handler(sci_phy, frame_index); + enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + enum sci_status result; + + switch (state) { + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: { + u32 *frame_words; + struct sas_identify_frame iaf; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + result = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_words); + + if (result != SCI_SUCCESS) + return result; + + sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32)); + if (iaf.frame_type == 0) { + u32 state; + + memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf)); + if (iaf.smp_tport) { + /* We got the IAF for an expander PHY go to the final + * state since there are no power requirements for + * expander phys. + */ + state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; + } else { + /* We got the IAF we can now go to the await spinup + * semaphore state + */ + state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; + } + sci_base_state_machine_change_state(&sci_phy->state_machine, + state); + result = SCI_SUCCESS; + } else + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected frame id %x\n", + __func__, frame_index); + + scic_sds_controller_release_frame(scic, frame_index); + return result; + } + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: { + struct dev_to_host_fis *frame_header; + u32 *fis_frame_data; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + result = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_phy_get_controller(sci_phy)->uf_control), + frame_index, + (void **)&frame_header); + + if (result != SCI_SUCCESS) + return result; + + if ((frame_header->fis_type == FIS_REGD2H) && + !(frame_header->status & ATA_BUSY)) { + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&fis_frame_data); + + scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, + frame_header, + fis_frame_data); + + /* got IAF we can now go to the await spinup semaphore state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); + + result = SCI_SUCCESS; + } else + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected frame id %x\n", + __func__, frame_index); + + /* Regardless of the result we are done with this frame with it */ + scic_sds_controller_release_frame(scic, frame_index); + + return result; + } + default: + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + } /** @@ -1069,141 +1151,6 @@ static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handle return result; } - -/* - * ***************************************************************************** - * * SCIC SDS PHY FRAME_HANDLERS - * ***************************************************************************** */ - -/** - * - * @phy: This is struct scic_sds_phy object which is being requested to decode the - * frame data. - * @frame_index: This is the index of the unsolicited frame which was received - * for this phy. - * - * This method decodes the unsolicited frame when the struct scic_sds_phy is in the - * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Get the UF Header - If the UF - * is an IAF - Copy IAF data to local phy object IAF data buffer. - Change - * starting substate to wait power. - else - log warning message of unexpected - * unsolicted frame - release frame buffer enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler( - struct scic_sds_phy *sci_phy, u32 frame_index) -{ - enum sci_status result; - u32 *frame_words; - struct sas_identify_frame iaf; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(sci_phy)->uf_control), - frame_index, - (void **)&frame_words); - - if (result != SCI_SUCCESS) - return result; - - sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32)); - if (iaf.frame_type == 0) { - u32 state; - - memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf)); - if (iaf.smp_tport) { - /* We got the IAF for an expander PHY go to the final - * state since there are no power requirements for - * expander phys. - */ - state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; - } else { - /* We got the IAF we can now go to the await spinup - * semaphore state - */ - state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; - } - sci_base_state_machine_change_state( - &sci_phy->state_machine, - state); - result = SCI_SUCCESS; - } else - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected frame id %x\n", - __func__, - frame_index); - - scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), - frame_index); - - return result; -} - -/** - * - * @phy: This is struct scic_sds_phy object which is being requested to decode the - * frame data. - * @frame_index: This is the index of the unsolicited frame which was received - * for this phy. - * - * This method decodes the unsolicited frame when the struct scic_sds_phy is in the - * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Get the UF Header - If - * the UF is an SIGNATURE FIS - Copy IAF data to local phy object SIGNATURE FIS - * data buffer. - else - log warning message of unexpected unsolicted frame - - * release frame buffer enum sci_status SCI_SUCCESS Must decode the SIGNATURE FIS - * data - */ -static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handler( - struct scic_sds_phy *sci_phy, - u32 frame_index) -{ - enum sci_status result; - struct dev_to_host_fis *frame_header; - u32 *fis_frame_data; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(sci_phy)->uf_control), - frame_index, - (void **)&frame_header); - - if (result != SCI_SUCCESS) - return result; - - if ((frame_header->fis_type == FIS_REGD2H) && - !(frame_header->status & ATA_BUSY)) { - scic_sds_unsolicited_frame_control_get_buffer( - &(scic_sds_phy_get_controller(sci_phy)->uf_control), - frame_index, - (void **)&fis_frame_data); - - scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, - frame_header, - fis_frame_data); - - /* got IAF we can now go to the await spinup semaphore state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); - - result = SCI_SUCCESS; - } else - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected frame id %x\n", - __func__, - frame_index); - - /* Regardless of the result we are done with this frame with it */ - scic_sds_controller_release_frame(scic_sds_phy_get_controller(sci_phy), - frame_index); - - return result; -} - -/* - * ***************************************************************************** - * * SCIC SDS PHY POWER_HANDLERS - * ***************************************************************************** */ - /* * This method is called by the struct scic_sds_controller when the phy object is * granted power. - The notify enable spinups are turned on for this phy object @@ -1267,18 +1214,6 @@ static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_phy_default_frame_handler(struct scic_sds_phy *sci_phy, - u32 frame_index) -{ - struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - - default_phy_handler(sci_phy, __func__); - scic_sds_controller_release_frame(scic, frame_index); - - return SCI_FAILURE_INVALID_STATE; -} - static enum sci_status scic_sds_phy_default_event_handler(struct scic_sds_phy *sci_phy, u32 event_code) @@ -1367,82 +1302,66 @@ static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sd static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STOPPED] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STARTING] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .frame_handler = scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .frame_handler = scic_sds_phy_starting_substate_await_sig_fis_frame_handler, .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_READY] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_ready_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_RESETTING] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_resetting_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_FINAL] = { - .frame_handler = scic_sds_phy_default_frame_handler, .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler } diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 24536d6eef81..e7f4b71b1158 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -511,11 +511,6 @@ typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); struct scic_sds_phy_state_handler { - /** - * The state handler for unsolicited frames received from the SCU hardware. - */ - scic_sds_phy_frame_handler_t frame_handler; - /** * The state handler for events received from the SCU hardware. */ -- cgit v1.2.3 From 23506a69e2ee761824c266f6e2cd541a7287c2a5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 04:27:29 -0700 Subject: isci: unify phy event handlers Unify the implementations in scic_sds_phy_event_handler(), and kill the state handler Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 1021 ++++++++++++++++++----------------------------- drivers/scsi/isci/phy.h | 5 - 2 files changed, 384 insertions(+), 642 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 433ea605f70b..0ffb5d5a860e 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -505,116 +505,6 @@ enum sci_status scic_sds_phy_reset(struct scic_sds_phy *sci_phy) return SCI_SUCCESS; } -/** - * This method will process the event code received. - * @sci_phy: - * @event_code: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - return sci_phy->state_handlers->event_handler(sci_phy, event_code); -} - -enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, - u32 frame_index) -{ - enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; - struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; - enum sci_status result; - - switch (state) { - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: { - u32 *frame_words; - struct sas_identify_frame iaf; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - result = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, - frame_index, - (void **)&frame_words); - - if (result != SCI_SUCCESS) - return result; - - sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32)); - if (iaf.frame_type == 0) { - u32 state; - - memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf)); - if (iaf.smp_tport) { - /* We got the IAF for an expander PHY go to the final - * state since there are no power requirements for - * expander phys. - */ - state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; - } else { - /* We got the IAF we can now go to the await spinup - * semaphore state - */ - state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; - } - sci_base_state_machine_change_state(&sci_phy->state_machine, - state); - result = SCI_SUCCESS; - } else - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected frame id %x\n", - __func__, frame_index); - - scic_sds_controller_release_frame(scic, frame_index); - return result; - } - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: { - struct dev_to_host_fis *frame_header; - u32 *fis_frame_data; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(sci_phy)->uf_control), - frame_index, - (void **)&frame_header); - - if (result != SCI_SUCCESS) - return result; - - if ((frame_header->fis_type == FIS_REGD2H) && - !(frame_header->status & ATA_BUSY)) { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, - frame_index, - (void **)&fis_frame_data); - - scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, - frame_header, - fis_frame_data); - - /* got IAF we can now go to the await spinup semaphore state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); - - result = SCI_SUCCESS; - } else - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected frame id %x\n", - __func__, frame_index); - - /* Regardless of the result we are done with this frame with it */ - scic_sds_controller_release_frame(scic, frame_index); - - return result; - } - default: - dev_dbg(sciphy_to_dev(sci_phy), - "%s: in wrong state: %d\n", __func__, state); - return SCI_FAILURE_INVALID_STATE; - } - -} - /** * This method will give the phy permission to consume power * @sci_phy: @@ -702,455 +592,6 @@ static void scic_sds_phy_complete_link_training( next_state); } -static void scic_sds_phy_restart_starting_state( - struct scic_sds_phy *sci_phy) -{ - /* Re-enter the base state machine starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - - * decode the event - sas phy detected causes a state transition to the wait - * for speed event notification. - any other events log a warning message and - * set a failure status enum sci_status SCI_SUCCESS on any valid event notification - * SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SAS_PHY_DETECTED: - scic_sds_phy_start_sas_link_training(sci_phy); - sci_phy->is_in_link_training = true; - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - scic_sds_phy_start_sata_link_training(sci_phy); - sci_phy->is_in_link_training = true; - break; - - default: - dev_dbg(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - - * decode the event - sas phy detected returns us back to this state. - speed - * event detected causes a state transition to the wait for iaf. - identify - * timeout is an un-expected event and the state machine is restarted. - link - * failure events restart the starting state machine - any other events log a - * warning message and set a failure status enum sci_status SCI_SUCCESS on any valid - * event notification SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SAS_PHY_DETECTED: - /* - * Why is this being reported again by the controller? - * We would re-enter this state so just stay here */ - break; - - case SCU_EVENT_SAS_15: - case SCU_EVENT_SAS_15_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_1_5_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); - break; - - case SCU_EVENT_SAS_30: - case SCU_EVENT_SAS_30_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_3_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); - break; - - case SCU_EVENT_SAS_60: - case SCU_EVENT_SAS_60_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_6_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - /* - * We were doing SAS PHY link training and received a SATA PHY event - * continue OOB/SN as if this were a SATA PHY */ - scic_sds_phy_start_sata_link_training(sci_phy); - break; - - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - - * decode the event - sas phy detected event backs up the state machine to the - * await speed notification. - identify timeout is an un-expected event and the - * state machine is restarted. - link failure events restart the starting state - * machine - any other events log a warning message and set a failure status - * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any - * unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SAS_PHY_DETECTED: - /* Backup the state machine */ - scic_sds_phy_start_sas_link_training(sci_phy); - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - /* - * We were doing SAS PHY link training and received a SATA PHY event - * continue OOB/SN as if this were a SATA PHY */ - scic_sds_phy_start_sata_link_training(sci_phy); - break; - - case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: - case SCU_EVENT_LINK_FAILURE: - case SCU_EVENT_HARD_RESET_RECEIVED: - /* Start the oob/sn state machine over again */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER. - - * decode the event - link failure events restart the starting state machine - - * any other events log a warning message and set a failure status enum sci_status - * SCI_SUCCESS on a link failure event SCI_FAILURE on any unexpected event - * notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received unexpected " - "event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - - * decode the event - link failure events restart the starting state machine - - * sata spinup hold events are ignored since they are expected - any other - * events log a warning message and set a failure status enum sci_status SCI_SUCCESS - * on a link failure event SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - /* These events are received every 10ms and are expected while in this state */ - break; - - case SCU_EVENT_SAS_PHY_DETECTED: - /* - * There has been a change in the phy type before OOB/SN for the - * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * scic_sds_phy_starting_substate_await_sata_phy_event_handler - - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - - * decode the event - link failure events restart the starting state machine - - * sata spinup hold events are ignored since they are expected - sata phy - * detected event change to the wait speed event - any other events log a - * warning message and set a failure status enum sci_status SCI_SUCCESS on a link - * failure event SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handler( - struct scic_sds_phy *sci_phy, u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - case SCU_EVENT_SATA_SPINUP_HOLD: - /* These events might be received since we dont know how many may be in - * the completion queue while waiting for power - */ - break; - - case SCU_EVENT_SATA_PHY_DETECTED: - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; - - /* We have received the SATA PHY notification change state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); - break; - - case SCU_EVENT_SAS_PHY_DETECTED: - /* There has been a change in the phy type before OOB/SN for the - * SATA finished start down the SAS link traning path. - */ - scic_sds_phy_start_sas_link_training(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - * - decode the event - sata phy detected returns us back to this state. - - * speed event detected causes a state transition to the wait for signature. - - * link failure events restart the starting state machine - any other events - * log a warning message and set a failure status enum sci_status SCI_SUCCESS on any - * valid event notification SCI_FAILURE on any unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_handler( - struct scic_sds_phy *sci_phy, - u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SATA_PHY_DETECTED: - /* - * The hardware reports multiple SATA PHY detected events - * ignore the extras */ - break; - - case SCU_EVENT_SATA_15: - case SCU_EVENT_SATA_15_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_1_5_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); - break; - - case SCU_EVENT_SATA_30: - case SCU_EVENT_SATA_30_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_3_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); - break; - - case SCU_EVENT_SATA_60: - case SCU_EVENT_SATA_60_SSC: - scic_sds_phy_complete_link_training( - sci_phy, - SAS_LINK_RATE_6_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); - break; - - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - case SCU_EVENT_SAS_PHY_DETECTED: - /* - * There has been a change in the phy type before OOB/SN for the - * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - -/** - * scic_sds_phy_starting_substate_await_sig_fis_event_handler - - * @phy: This struct scic_sds_phy object which has received an event. - * @event_code: This is the event code which the phy object is to decode. - * - * This method is called when an event notification is received for the phy - * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - - * decode the event - sas phy detected event backs up the state machine to the - * await speed notification. - identify timeout is an un-expected event and the - * state machine is restarted. - link failure events restart the starting state - * machine - any other events log a warning message and set a failure status - * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any - * unexpected event notifation - */ -static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handler( - struct scic_sds_phy *sci_phy, u32 event_code) -{ - u32 result = SCI_SUCCESS; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_SATA_PHY_DETECTED: - /* Backup the state machine */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); - break; - - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - scic_sds_phy_restart_starting_state(sci_phy); - break; - - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: PHY starting substate machine received " - "unexpected event_code %x\n", - __func__, - event_code); - - result = SCI_FAILURE; - break; - } - - return result; -} - /* * This method is called by the struct scic_sds_controller when the phy object is * granted power. - The notify enable spinups are turned on for this phy object @@ -1214,155 +655,461 @@ static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_phy_default_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) -{ - return default_phy_handler(sci_phy, __func__); -} - static enum sci_status scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) { return default_phy_handler(sci_phy, __func__); } -/** - * scic_sds_phy_ready_state_event_handler - - * @phy: This is the struct scic_sds_phy object which has received the event. - * - * This method request the struct scic_sds_phy handle the received event. The only - * event that we are interested in while in the ready state is the link failure - * event. - decoded event is a link failure - transition the struct scic_sds_phy back - * to the SCI_BASE_PHY_STATE_STARTING state. - any other event received will - * report a warning message enum sci_status SCI_SUCCESS if the event received is a - * link failure SCI_FAILURE_INVALID_STATE for any other event received. - */ -static enum sci_status scic_sds_phy_ready_state_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) + +enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, + u32 event_code) { - enum sci_status result = SCI_FAILURE; + enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_LINK_FAILURE: - /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - result = SCI_SUCCESS; - break; + switch (state) { + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + scic_sds_phy_start_sas_link_training(sci_phy); + sci_phy->is_in_link_training = true; + break; + case SCU_EVENT_SATA_SPINUP_HOLD: + scic_sds_phy_start_sata_link_training(sci_phy); + sci_phy->is_in_link_training = true; + break; + default: + dev_dbg(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + return SCI_FAILURE; + } + return SCI_SUCCESS; + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * Why is this being reported again by the controller? + * We would re-enter this state so just stay here */ + break; + case SCU_EVENT_SAS_15: + case SCU_EVENT_SAS_15_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_1_5_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + break; + case SCU_EVENT_SAS_30: + case SCU_EVENT_SAS_30_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_3_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + break; + case SCU_EVENT_SAS_60: + case SCU_EVENT_SAS_60_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_6_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + break; + case SCU_EVENT_SATA_SPINUP_HOLD: + /* + * We were doing SAS PHY link training and received a SATA PHY event + * continue OOB/SN as if this were a SATA PHY */ + scic_sds_phy_start_sata_link_training(sci_phy); + break; + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, event_code); + + return SCI_FAILURE; + break; + } + return SCI_SUCCESS; + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SAS_PHY_DETECTED: + /* Backup the state machine */ + scic_sds_phy_start_sas_link_training(sci_phy); + break; + case SCU_EVENT_SATA_SPINUP_HOLD: + /* We were doing SAS PHY link training and received a + * SATA PHY event continue OOB/SN as if this were a + * SATA PHY + */ + scic_sds_phy_start_sata_link_training(sci_phy); + break; + case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: + case SCU_EVENT_LINK_FAILURE: + case SCU_EVENT_HARD_RESET_RECEIVED: + /* Start the oob/sn state machine over again */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, event_code); + return SCI_FAILURE; + } + return SCI_SUCCESS; + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received unexpected " + "event_code %x\n", + __func__, + event_code); + return SCI_FAILURE; + } + return SCI_SUCCESS; + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; + case SCU_EVENT_SATA_SPINUP_HOLD: + /* These events are received every 10ms and are + * expected while in this state + */ + break; + + case SCU_EVENT_SAS_PHY_DETECTED: + /* There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. + */ + scic_sds_phy_start_sas_link_training(sci_phy); + break; + + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, event_code); - case SCU_EVENT_BROADCAST_CHANGE: - /* Broadcast change received. Notify the port. */ - if (scic_sds_phy_get_port(sci_phy) != NULL) - scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); - else - sci_phy->bcn_received_while_port_unassigned = true; - break; + return SCI_FAILURE; + } + return SCI_SUCCESS; + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; + case SCU_EVENT_SATA_SPINUP_HOLD: + /* These events might be received since we dont know how many may be in + * the completion queue while waiting for power + */ + break; + case SCU_EVENT_SATA_PHY_DETECTED: + sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; + + /* We have received the SATA PHY notification change state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); + break; + case SCU_EVENT_SAS_PHY_DETECTED: + /* There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. + */ + scic_sds_phy_start_sas_link_training(sci_phy); + break; + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); - default: - dev_warn(sciphy_to_dev(sci_phy), - "%sP SCIC PHY 0x%p ready state machine received " - "unexpected event_code %x\n", - __func__, sci_phy, event_code); + return SCI_FAILURE;; + } + return SCI_SUCCESS; + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SATA_PHY_DETECTED: + /* + * The hardware reports multiple SATA PHY detected events + * ignore the extras */ + break; + case SCU_EVENT_SATA_15: + case SCU_EVENT_SATA_15_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_1_5_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + break; + case SCU_EVENT_SATA_30: + case SCU_EVENT_SATA_30_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_3_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + break; + case SCU_EVENT_SATA_60: + case SCU_EVENT_SATA_60_SSC: + scic_sds_phy_complete_link_training( + sci_phy, + SAS_LINK_RATE_6_0_GBPS, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + break; + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; + case SCU_EVENT_SAS_PHY_DETECTED: + /* + * There has been a change in the phy type before OOB/SN for the + * SATA finished start down the SAS link traning path. */ + scic_sds_phy_start_sas_link_training(sci_phy); + break; + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, event_code); - result = SCI_FAILURE_INVALID_STATE; - break; - } + return SCI_FAILURE; + } + + return SCI_SUCCESS; + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_SATA_PHY_DETECTED: + /* Backup the state machine */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); + break; + + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; - return result; + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected event_code %x\n", + __func__, + event_code); + + return SCI_FAILURE; + } + return SCI_SUCCESS; + case SCI_BASE_PHY_STATE_READY: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_LINK_FAILURE: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; + case SCU_EVENT_BROADCAST_CHANGE: + /* Broadcast change received. Notify the port. */ + if (scic_sds_phy_get_port(sci_phy) != NULL) + scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); + else + sci_phy->bcn_received_while_port_unassigned = true; + break; + default: + dev_warn(sciphy_to_dev(sci_phy), + "%sP SCIC PHY 0x%p ready state machine received " + "unexpected event_code %x\n", + __func__, sci_phy, event_code); + return SCI_FAILURE_INVALID_STATE; + } + return SCI_SUCCESS; + case SCI_BASE_PHY_STATE_RESETTING: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_HARD_RESET_TRANSMITTED: + /* Link failure change state back to the starting state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); + break; + default: + dev_warn(sciphy_to_dev(sci_phy), + "%s: SCIC PHY 0x%p resetting state machine received " + "unexpected event_code %x\n", + __func__, sci_phy, event_code); + + return SCI_FAILURE_INVALID_STATE; + break; + } + return SCI_SUCCESS; + default: + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } } -static enum sci_status scic_sds_phy_resetting_state_event_handler(struct scic_sds_phy *sci_phy, - u32 event_code) +enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, + u32 frame_index) { - enum sci_status result = SCI_FAILURE; + enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + enum sci_status result; - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_HARD_RESET_TRANSMITTED: - /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - result = SCI_SUCCESS; - break; + switch (state) { + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: { + u32 *frame_words; + struct sas_identify_frame iaf; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - default: - dev_warn(sciphy_to_dev(sci_phy), - "%s: SCIC PHY 0x%p resetting state machine received " - "unexpected event_code %x\n", - __func__, sci_phy, event_code); + result = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + frame_index, + (void **)&frame_words); - result = SCI_FAILURE_INVALID_STATE; - break; + if (result != SCI_SUCCESS) + return result; + + sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32)); + if (iaf.frame_type == 0) { + u32 state; + + memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf)); + if (iaf.smp_tport) { + /* We got the IAF for an expander PHY go to the final + * state since there are no power requirements for + * expander phys. + */ + state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; + } else { + /* We got the IAF we can now go to the await spinup + * semaphore state + */ + state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; + } + sci_base_state_machine_change_state(&sci_phy->state_machine, + state); + result = SCI_SUCCESS; + } else + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected frame id %x\n", + __func__, frame_index); + + scic_sds_controller_release_frame(scic, frame_index); + return result; } + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: { + struct dev_to_host_fis *frame_header; + u32 *fis_frame_data; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + result = scic_sds_unsolicited_frame_control_get_header( + &(scic_sds_phy_get_controller(sci_phy)->uf_control), + frame_index, + (void **)&frame_header); + + if (result != SCI_SUCCESS) + return result; - return result; + if ((frame_header->fis_type == FIS_REGD2H) && + !(frame_header->status & ATA_BUSY)) { + scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + frame_index, + (void **)&fis_frame_data); + + scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, + frame_header, + fis_frame_data); + + /* got IAF we can now go to the await spinup semaphore state */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); + + result = SCI_SUCCESS; + } else + dev_warn(sciphy_to_dev(sci_phy), + "%s: PHY starting substate machine received " + "unexpected frame id %x\n", + __func__, frame_index); + + /* Regardless of the result we are done with this frame with it */ + scic_sds_controller_release_frame(scic, frame_index); + + return result; + } + default: + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + } + + /* --------------------------------------------------------------------------- */ static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { [SCI_BASE_PHY_STATE_INITIAL] = { - .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STOPPED] = { - .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_STARTING] = { - .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .event_handler = scic_sds_phy_starting_substate_await_ossp_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .event_handler = scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .event_handler = scic_sds_phy_starting_substate_await_iaf_uf_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .event_handler = scic_sds_phy_starting_substate_await_sas_power_event_handler, .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .event_handler = scic_sds_phy_starting_substate_await_sata_power_event_handler, .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .event_handler = scic_sds_phy_starting_substate_await_sata_phy_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .event_handler = scic_sds_phy_starting_substate_await_sata_speed_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .event_handler = scic_sds_phy_starting_substate_await_sig_fis_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_READY] = { - .event_handler = scic_sds_phy_ready_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_RESETTING] = { - .event_handler = scic_sds_phy_resetting_state_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler }, [SCI_BASE_PHY_STATE_FINAL] = { - .event_handler = scic_sds_phy_default_event_handler, .consume_power_handler = scic_sds_phy_default_consume_power_handler } }; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index e7f4b71b1158..a95c74e58695 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -511,11 +511,6 @@ typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); struct scic_sds_phy_state_handler { - /** - * The state handler for events received from the SCU hardware. - */ - scic_sds_phy_event_handler_t event_handler; - /** * The state handler for staggered spinup. */ -- cgit v1.2.3 From 5b1d4af25186f5d23dae7a538d8472dacd9486c8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 04:51:41 -0700 Subject: isci: unify phy consume_power handlers Unify the implementations in scic_sds_phy_consume_power_handler(), and kill the state handler plus infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 574 +++++++----------------------------------------- drivers/scsi/isci/phy.h | 36 --- 2 files changed, 83 insertions(+), 527 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 0ffb5d5a860e..9a5ec375f767 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -505,16 +505,53 @@ enum sci_status scic_sds_phy_reset(struct scic_sds_phy *sci_phy) return SCI_SUCCESS; } -/** - * This method will give the phy permission to consume power - * @sci_phy: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_consume_power_handler( - struct scic_sds_phy *sci_phy) +enum sci_status scic_sds_phy_consume_power_handler(struct scic_sds_phy *sci_phy) { - return sci_phy->state_handlers->consume_power_handler(sci_phy); + enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + + switch (state) { + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: { + u32 enable_spinup; + + enable_spinup = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); + enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); + writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control); + + /* Change state to the final state this substate machine has run to completion */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); + + return SCI_SUCCESS; + } + case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: { + u32 scu_sas_pcfg_value; + + /* Release the spinup hold state and reset the OOB state machine */ + scu_sas_pcfg_value = + readl(&sci_phy->link_layer_registers->phy_configuration); + scu_sas_pcfg_value &= + ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); + + /* Now restart the OOB operation */ + scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); + scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); + writel(scu_sas_pcfg_value, + &sci_phy->link_layer_registers->phy_configuration); + + /* Change state to the final state this substate machine has run to completion */ + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); + + return SCI_SUCCESS; + } + default: + dev_dbg(sciphy_to_dev(sci_phy), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } } /* @@ -592,76 +629,6 @@ static void scic_sds_phy_complete_link_training( next_state); } -/* - * This method is called by the struct scic_sds_controller when the phy object is - * granted power. - The notify enable spinups are turned on for this phy object - * - The phy state machine is transitioned to the - * SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_power_handler( - struct scic_sds_phy *sci_phy) -{ - u32 enable_spinup; - - enable_spinup = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); - enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); - writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control); - - /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); - - return SCI_SUCCESS; -} - -/* - * This method is called by the struct scic_sds_controller when the phy object is - * granted power. - The phy state machine is transitioned to the - * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_power_handler( - struct scic_sds_phy *sci_phy) -{ - u32 scu_sas_pcfg_value; - - /* Release the spinup hold state and reset the OOB state machine */ - scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); - scu_sas_pcfg_value &= - ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); - scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); - - /* Now restart the OOB operation */ - scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); - writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); - - /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); - - return SCI_SUCCESS; -} - -static enum sci_status default_phy_handler(struct scic_sds_phy *sci_phy, - const char *func) -{ - dev_dbg(sciphy_to_dev(sci_phy), - "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&sci_phy->state_machine)); - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status -scic_sds_phy_default_consume_power_handler(struct scic_sds_phy *sci_phy) -{ - return default_phy_handler(sci_phy, __func__); -} - - enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, u32 event_code) { @@ -1059,287 +1026,71 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, } - - -/* --------------------------------------------------------------------------- */ - -static const struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[] = { - [SCI_BASE_PHY_STATE_INITIAL] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_STOPPED] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_STARTING] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { - .consume_power_handler = scic_sds_phy_starting_substate_await_sas_power_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { - .consume_power_handler = scic_sds_phy_starting_substate_await_sata_power_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_READY] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_RESETTING] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - }, - [SCI_BASE_PHY_STATE_FINAL] = { - .consume_power_handler = scic_sds_phy_default_consume_power_handler - } -}; - -/* - * **************************************************************************** - * * PHY STARTING SUBSTATE METHODS - * **************************************************************************** */ - -/** - * scic_sds_phy_starting_initial_substate_enter - - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL. - The initial state - * handlers are put in place for the struct scic_sds_phy object. - The state is - * changed to the wait phy type event notification. none - */ static void scic_sds_phy_starting_initial_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_base_state_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); - /* This is just an temporary state go off to the starting state */ sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ -static void scic_sds_phy_starting_await_ossp_en_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ -static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( - void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ -static void scic_sds_phy_starting_await_iaf_uf_substate_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Set the - * struct scic_sds_phy object state handlers for this state. - Add this phy object to - * the power control queue none - */ static void scic_sds_phy_starting_await_sas_power_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; + struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; - scic_sds_phy_set_base_state_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER - ); - - scic_sds_controller_power_control_queue_insert( - scic_sds_phy_get_controller(sci_phy), - sci_phy - ); + scic_sds_controller_power_control_queue_insert(scic, sci_phy); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Remove the - * struct scic_sds_phy object from the power control queue. none - */ static void scic_sds_phy_starting_await_sas_power_substate_exit(void *object) { struct scic_sds_phy *sci_phy = object; + struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_remove( - scic_sds_phy_get_controller(sci_phy), sci_phy - ); + scic_sds_controller_power_control_queue_remove(scic, sci_phy); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Set the - * struct scic_sds_phy object state handlers for this state. - Add this phy object to - * the power control queue none - */ static void scic_sds_phy_starting_await_sata_power_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; + struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; - scic_sds_phy_set_base_state_handlers( - sci_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER - ); - - scic_sds_controller_power_control_queue_insert( - scic_sds_phy_get_controller(sci_phy), - sci_phy - ); + scic_sds_controller_power_control_queue_insert(scic, sci_phy); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Remove the - * struct scic_sds_phy object from the power control queue. none - */ static void scic_sds_phy_starting_await_sata_power_substate_exit(void *object) { struct scic_sds_phy *sci_phy = object; + struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_remove( - scic_sds_phy_get_controller(sci_phy), - sci_phy - ); + scic_sds_controller_power_control_queue_remove(scic, sci_phy); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ static void scic_sds_phy_starting_await_sata_phy_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_base_state_handlers( - sci_phy, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); - isci_timer_start(sci_phy->sata_timeout_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy - * on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer - * that was started on entry to await sata phy event notification none - */ -static inline void scic_sds_phy_starting_await_sata_phy_substate_exit( - void *object) +static void scic_sds_phy_starting_await_sata_phy_substate_exit(void *object) { struct scic_sds_phy *sci_phy = object; isci_timer_stop(sci_phy->sata_timeout_timer); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - Set the - * struct scic_sds_phy object state handlers for this state. none - */ static void scic_sds_phy_starting_await_sata_speed_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_base_state_handlers( - sci_phy, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); - isci_timer_start(sci_phy->sata_timeout_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the - * struct scic_sds_phy on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer - * that was started on entry to await sata phy event notification none - */ -static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( +static void scic_sds_phy_starting_await_sata_speed_substate_exit( void *object) { struct scic_sds_phy *sci_phy = object; @@ -1347,30 +1098,12 @@ static inline void scic_sds_phy_starting_await_sata_speed_substate_exit( isci_timer_stop(sci_phy->sata_timeout_timer); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Set the - * struct scic_sds_phy object state handlers for this state. - * - Start the SIGNATURE FIS - * timeout timer none - */ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) { - bool continue_to_ready_state; struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_base_state_handlers( - sci_phy, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); - - continue_to_ready_state = scic_sds_port_link_detected( - sci_phy->owning_port, - sci_phy); + if (scic_sds_port_link_detected(sci_phy->owning_port, sci_phy)) { - if (continue_to_ready_state) { /* * Clear the PE suspend condition so we can actually * receive SIG FIS @@ -1385,39 +1118,17 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) sci_phy->is_in_link_training = false; } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the - * struct scic_sds_phy on exiting - * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Stop the SIGNATURE - * FIS timeout timer. none - */ -static inline void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( - void *object) +static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(void *object) { struct scic_sds_phy *sci_phy = object; isci_timer_stop(sci_phy->sata_timeout_timer); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. - Set the struct scic_sds_phy - * object state handlers for this state. - Change base state machine to the - * ready state. none - */ static void scic_sds_phy_starting_final_substate_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_base_state_handlers(sci_phy, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); - /* State machine has run to completion so exit out and change * the base state machine to the ready state */ @@ -1425,11 +1136,6 @@ static void scic_sds_phy_starting_final_substate_enter(void *object) SCI_BASE_PHY_STATE_READY); } -/* - * **************************************************************************** - * * PHY STATE PRIVATE METHODS - * **************************************************************************** */ - /** * * @sci_phy: This is the struct scic_sds_phy object to stop. @@ -1511,49 +1217,17 @@ static void scu_link_layer_tx_hard_reset( &sci_phy->link_layer_registers->phy_configuration); } -/* - * **************************************************************************** - * * PHY BASE STATE METHODS - * **************************************************************************** */ - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state - * handlers for the phy object base state machine initial state. none - */ -static void scic_sds_phy_initial_state_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_INITIAL); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This function will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state - * handlers for the phy object base state machine initial state. - The SCU - * hardware is requested to stop the protocol engine. none - */ static void scic_sds_phy_stopped_state_enter(void *object) { struct scic_sds_phy *sci_phy = object; - struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); + struct scic_sds_port *sci_port = sci_phy->owning_port; + struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); /* * @todo We need to get to the controller to place this PE in a * reset state */ - - scic_sds_phy_set_base_state_handlers(sci_phy, - SCI_BASE_PHY_STATE_STOPPED); - if (sci_phy->sata_timeout_timer != NULL) { isci_del_timer(ihost, sci_phy->sata_timeout_timer); @@ -1562,32 +1236,16 @@ static void scic_sds_phy_stopped_state_enter(void *object) scu_link_layer_stop_protocol_engine(sci_phy); - if (sci_phy->state_machine.previous_state_id != - SCI_BASE_PHY_STATE_INITIAL) - scic_sds_controller_link_down( - scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), - sci_phy); + if (sci_phy->state_machine.previous_state_id != SCI_BASE_PHY_STATE_INITIAL) + scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_STARTING. - This function sets the state - * handlers for the phy object base state machine starting state. - The SCU - * hardware is requested to start OOB/SN on this protocl engine. - The phy - * starting substate machine is started. - If the previous state was the ready - * state then the struct scic_sds_controller is informed that the phy has gone link - * down. none - */ static void scic_sds_phy_starting_state_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_STARTING); - scu_link_layer_stop_protocol_engine(sci_phy); scu_link_layer_start_oob(sci_phy); @@ -1595,50 +1253,25 @@ static void scic_sds_phy_starting_state_enter(void *object) sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; sci_phy->bcn_received_while_port_unassigned = false; - if (sci_phy->state_machine.previous_state_id - == SCI_BASE_PHY_STATE_READY) { - scic_sds_controller_link_down( - scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), - sci_phy - ); - } + if (sci_phy->state_machine.previous_state_id == SCI_BASE_PHY_STATE_READY) + scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy); sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_READY. - This function sets the state - * handlers for the phy object base state machine ready state. - The SCU - * hardware protocol engine is resumed. - The struct scic_sds_controller is informed - * that the phy object has gone link up. none - */ static void scic_sds_phy_ready_state_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_READY); + scic_sds_controller_link_up(scic_sds_phy_get_controller(sci_phy), + scic_sds_phy_get_port(sci_phy), + sci_phy); - scic_sds_controller_link_up( - scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), - sci_phy - ); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on exiting - * the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU hardware - * protocol engine represented by this struct scic_sds_phy object. none - */ static void scic_sds_phy_ready_state_exit(void *object) { struct scic_sds_phy *sci_phy = object; @@ -1646,62 +1279,29 @@ static void scic_sds_phy_ready_state_exit(void *object) scic_sds_phy_suspend(sci_phy); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_RESETTING. - This function sets the state - * handlers for the phy object base state machine resetting state. none - */ static void scic_sds_phy_resetting_state_enter(void *object) { struct scic_sds_phy *sci_phy = object; - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_RESETTING); - - /* - * The phy is being reset, therefore deactivate it from the port. - * In the resetting state we don't notify the user regarding - * link up and link down notifications. */ + /* The phy is being reset, therefore deactivate it from the port. In + * the resetting state we don't notify the user regarding link up and + * link down notifications + */ scic_sds_port_deactivate_phy(sci_phy->owning_port, sci_phy, false); if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { scu_link_layer_tx_hard_reset(sci_phy); } else { - /* - * The SCU does not need to have a discrete reset state so + /* The SCU does not need to have a discrete reset state so * just go back to the starting state. */ - sci_base_state_machine_change_state( - &sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); } } -/** - * - * @object: This is the object which is cast to a struct scic_sds_phy object. - * - * This method will perform the actions required by the struct scic_sds_phy on - * entering the SCI_BASE_PHY_STATE_FINAL. - This function sets the state - * handlers for the phy object base state machine final state. none - */ -static void scic_sds_phy_final_state_enter(void *object) -{ - struct scic_sds_phy *sci_phy = object; - - scic_sds_phy_set_base_state_handlers(sci_phy, SCI_BASE_PHY_STATE_FINAL); - - /* Nothing to do here */ -} - -/* --------------------------------------------------------------------------- */ - static const struct sci_base_state scic_sds_phy_state_table[] = { - [SCI_BASE_PHY_STATE_INITIAL] = { - .enter_state = scic_sds_phy_initial_state_enter, - }, + [SCI_BASE_PHY_STATE_INITIAL] = { }, [SCI_BASE_PHY_STATE_STOPPED] = { .enter_state = scic_sds_phy_stopped_state_enter, }, @@ -1711,15 +1311,9 @@ static const struct sci_base_state scic_sds_phy_state_table[] = { [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { .enter_state = scic_sds_phy_starting_initial_substate_enter, }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { - .enter_state = scic_sds_phy_starting_await_ossp_en_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { - .enter_state = scic_sds_phy_starting_await_sas_speed_en_substate_enter, - }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { - .enter_state = scic_sds_phy_starting_await_iaf_uf_substate_enter, - }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { }, + [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { }, [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, @@ -1750,9 +1344,7 @@ static const struct sci_base_state scic_sds_phy_state_table[] = { [SCI_BASE_PHY_STATE_RESETTING] = { .enter_state = scic_sds_phy_resetting_state_enter, }, - [SCI_BASE_PHY_STATE_FINAL] = { - .enter_state = scic_sds_phy_final_state_enter, - }, + [SCI_BASE_PHY_STATE_FINAL] = { }, }; void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index a95c74e58695..57708550a186 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -140,8 +140,6 @@ struct scic_sds_phy { */ void *sata_timeout_timer; - const struct scic_sds_phy_state_handler *state_handlers; - /** * This field is the pointer to the transport layer register for the SCU * hardware. @@ -504,20 +502,6 @@ enum scic_sds_phy_states { SCI_BASE_PHY_STATE_FINAL, }; - -typedef enum sci_status (*scic_sds_phy_handler_t)(struct scic_sds_phy *); -typedef enum sci_status (*scic_sds_phy_event_handler_t)(struct scic_sds_phy *, u32); -typedef enum sci_status (*scic_sds_phy_frame_handler_t)(struct scic_sds_phy *, u32); -typedef enum sci_status (*scic_sds_phy_power_handler_t)(struct scic_sds_phy *); - -struct scic_sds_phy_state_handler { - /** - * The state handler for staggered spinup. - */ - scic_sds_phy_power_handler_t consume_power_handler; - -}; - /** * scic_sds_phy_get_index() - * @@ -535,26 +519,6 @@ struct scic_sds_phy_state_handler { #define scic_sds_phy_get_controller(phy) \ (scic_sds_port_get_controller((phy)->owning_port)) -/** - * scic_sds_phy_set_state_handlers() - This macro sets the state handlers for - * this phy object - * - * - */ -#define scic_sds_phy_set_state_handlers(phy, handlers) \ - ((phy)->state_handlers = (handlers)) - -/** - * scic_sds_phy_set_base_state_handlers() - - * - * This macro set the base state handlers for the phy object. - */ -#define scic_sds_phy_set_base_state_handlers(phy, state_id) \ - scic_sds_phy_set_state_handlers(\ - (phy), \ - &scic_sds_phy_state_handler_table[(state_id)] \ - ) - void scic_sds_phy_construct( struct scic_sds_phy *this_phy, struct scic_sds_port *owning_port, -- cgit v1.2.3 From 4f20ef4f57aa52fd3356c143a8f3d2bd18dc61fc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 06:00:31 -0700 Subject: isci: clarify phy to port lookups While cleaning up the driver it is very tempting to convert scic_sds_get_* macros to their open coded equivalent. They are all just pointer dereferences *except* scic_sds_phy_get_port() which returns NULL if the phy is assigned to the dummy port. Clarify this by renaming it to phy_get_non_dummy_port(). Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 4 ++-- drivers/scsi/isci/phy.c | 10 +++++----- drivers/scsi/isci/phy.h | 3 +-- drivers/scsi/isci/port.c | 4 ++-- drivers/scsi/isci/port_config.c | 2 +- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 675eddd3963e..2ef1c592a16f 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -983,7 +983,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro sci_phy = &ihost->phys[index].sci; state = sci_phy->state_machine.current_state_id; - if (!scic_sds_phy_get_port(sci_phy)) + if (!phy_get_non_dummy_port(sci_phy)) continue; /* The controller start operation is complete iff: @@ -1014,7 +1014,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro sci_phy = &ihost->phys[scic->next_phy_to_start].sci; if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { - if (scic_sds_phy_get_port(sci_phy) == NULL) { + if (phy_get_non_dummy_port(sci_phy) == NULL) { scic->next_phy_to_start++; /* Caution recursion ahead be forwarned diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 9a5ec375f767..8bd1a85f621e 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -287,7 +287,7 @@ static void scic_sds_phy_sata_timeout(void *phy) * port (i.e. it's contained in the dummy port). !NULL All other * values indicate a handle/pointer to the port containing the phy. */ -struct scic_sds_port *scic_sds_phy_get_port( +struct scic_sds_port *phy_get_non_dummy_port( struct scic_sds_phy *sci_phy) { if (scic_sds_port_get_index(sci_phy->owning_port) == SCIC_SDS_DUMMY_PORT) @@ -893,7 +893,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, break; case SCU_EVENT_BROADCAST_CHANGE: /* Broadcast change received. Notify the port. */ - if (scic_sds_phy_get_port(sci_phy) != NULL) + if (phy_get_non_dummy_port(sci_phy) != NULL) scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); else sci_phy->bcn_received_while_port_unassigned = true; @@ -1238,7 +1238,7 @@ static void scic_sds_phy_stopped_state_enter(void *object) if (sci_phy->state_machine.previous_state_id != SCI_BASE_PHY_STATE_INITIAL) scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), + phy_get_non_dummy_port(sci_phy), sci_phy); } @@ -1255,7 +1255,7 @@ static void scic_sds_phy_starting_state_enter(void *object) if (sci_phy->state_machine.previous_state_id == SCI_BASE_PHY_STATE_READY) scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), + phy_get_non_dummy_port(sci_phy), sci_phy); sci_base_state_machine_change_state(&sci_phy->state_machine, @@ -1267,7 +1267,7 @@ static void scic_sds_phy_ready_state_enter(void *object) struct scic_sds_phy *sci_phy = object; scic_sds_controller_link_up(scic_sds_phy_get_controller(sci_phy), - scic_sds_phy_get_port(sci_phy), + phy_get_non_dummy_port(sci_phy), sci_phy); } diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 57708550a186..7694ec4d76b5 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -524,8 +524,7 @@ void scic_sds_phy_construct( struct scic_sds_port *owning_port, u8 phy_index); -struct scic_sds_port *scic_sds_phy_get_port( - struct scic_sds_phy *this_phy); +struct scic_sds_port *phy_get_non_dummy_port(struct scic_sds_phy *sci_phy); void scic_sds_phy_set_port( struct scic_sds_phy *this_phy, diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index dbff28396dd8..6d2633051adc 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -485,7 +485,7 @@ static enum sci_status scic_sds_port_set_phy( * not already have a phy assinged to the phy index. */ if ( (port->phy_table[phy->phy_index] == NULL) - && (scic_sds_phy_get_port(phy) == NULL) + && (phy_get_non_dummy_port(phy) == NULL) && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index) ) { /* @@ -516,7 +516,7 @@ static enum sci_status scic_sds_port_clear_phy( { /* Make sure that this phy is part of this port */ if (port->phy_table[phy->phy_index] == phy && - scic_sds_phy_get_port(phy) == port) { + phy_get_non_dummy_port(phy) == port) { struct scic_sds_controller *scic = port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index 028ffa370c90..ca76f493c30d 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -353,7 +353,7 @@ static void scic_sds_mpc_agent_timeout_handler(void *object) if (configure_phy_mask & (1 << index)) { port_agent->link_up_handler(scic, port_agent, - scic_sds_phy_get_port(sci_phy), + phy_get_non_dummy_port(sci_phy), sci_phy); } } -- cgit v1.2.3 From c777c26ca2a06164e1b8c8ccf4cd76cd645a9bbb Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Wed, 11 May 2011 23:52:16 +0000 Subject: isci: c99 port state handlers Name the table fields for consistancy and clarity. Signed-off-by: Piotr Sawicki Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 227 ++++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 121 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 6d2633051adc..e386066825b2 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1567,56 +1567,48 @@ static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds return default_port_handler(sci_port, __func__); } - - -static struct scic_sds_port_state_handler -scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = { - { - /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */ - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_ready_substate_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_ready_waiting_substate_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_ready_waiting_substate_start_io_handler, - scic_sds_port_ready_substate_complete_io_handler, +static struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[] = { + [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_ready_substate_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, + .remove_phy_handler = scic_sds_port_default_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_ready_waiting_substate_link_up_handler, + .link_down_handler = scic_sds_port_default_link_down_handler, + .start_io_handler = scic_sds_port_ready_waiting_substate_start_io_handler, + .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, - - { - /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */ - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_ready_operational_substate_reset_handler, - scic_sds_port_ready_substate_add_phy_handler, - scic_sds_port_ready_substate_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_ready_operational_substate_link_up_handler, - scic_sds_port_ready_operational_substate_link_down_handler, - scic_sds_port_ready_operational_substate_start_io_handler, - scic_sds_port_ready_substate_complete_io_handler, + [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_ready_substate_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, + .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, + .remove_phy_handler = scic_sds_port_ready_substate_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_ready_operational_substate_link_up_handler, + .link_down_handler = scic_sds_port_ready_operational_substate_link_down_handler, + .start_io_handler = scic_sds_port_ready_operational_substate_start_io_handler, + .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, - - { - /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */ - scic_sds_port_default_start_handler, - scic_sds_port_ready_substate_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_ready_configuring_substate_add_phy_handler, - scic_sds_port_ready_configuring_substate_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_ready_configuring_substate_complete_io_handler + [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_ready_substate_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_ready_configuring_substate_add_phy_handler, + .remove_phy_handler = scic_sds_port_ready_configuring_substate_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_default_link_up_handler, + .link_down_handler = scic_sds_port_default_link_down_handler, + .start_io_handler = scic_sds_port_default_start_io_handler, + .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler } }; @@ -2166,83 +2158,76 @@ static void scic_sds_port_reset_state_link_down_handler( scic_sds_port_deactivate_phy(port, phy, false); } -static struct scic_sds_port_state_handler -scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = -{ - /* SCI_BASE_PORT_STATE_STOPPED */ - { - scic_sds_port_stopped_state_start_handler, - scic_sds_port_stopped_state_stop_handler, - scic_sds_port_stopped_state_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_stopped_state_add_phy_handler, - scic_sds_port_stopped_state_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_default_complete_io_handler +static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = { + [SCI_BASE_PORT_STATE_STOPPED] = { + .start_handler = scic_sds_port_stopped_state_start_handler, + .stop_handler = scic_sds_port_stopped_state_stop_handler, + .destruct_handler = scic_sds_port_stopped_state_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_stopped_state_add_phy_handler, + .remove_phy_handler = scic_sds_port_stopped_state_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_default_link_up_handler, + .link_down_handler = scic_sds_port_default_link_down_handler, + .start_io_handler = scic_sds_port_default_start_io_handler, + .complete_io_handler = scic_sds_port_default_complete_io_handler }, - /* SCI_BASE_PORT_STATE_STOPPING */ - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_stopping_state_complete_io_handler + [SCI_BASE_PORT_STATE_STOPPING] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_default_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_default_add_phy_handler, + .remove_phy_handler = scic_sds_port_default_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_default_link_up_handler, + .link_down_handler = scic_sds_port_default_link_down_handler, + .start_io_handler = scic_sds_port_default_start_io_handler, + .complete_io_handler = scic_sds_port_stopping_state_complete_io_handler }, - /* SCI_BASE_PORT_STATE_READY */ - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_general_complete_io_handler + [SCI_BASE_PORT_STATE_READY] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_default_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_default_add_phy_handler, + .remove_phy_handler = scic_sds_port_default_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_default_link_up_handler, + .link_down_handler = scic_sds_port_default_link_down_handler, + .start_io_handler = scic_sds_port_default_start_io_handler, + .complete_io_handler = scic_sds_port_general_complete_io_handler }, - /* SCI_BASE_PORT_STATE_RESETTING */ - { - scic_sds_port_default_start_handler, - scic_sds_port_reset_state_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_reset_state_link_up_handler, - scic_sds_port_reset_state_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_general_complete_io_handler + [SCI_BASE_PORT_STATE_RESETTING] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_reset_state_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_default_add_phy_handler, + .remove_phy_handler = scic_sds_port_default_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_reset_state_link_up_handler, + .link_down_handler = scic_sds_port_reset_state_link_down_handler, + .start_io_handler = scic_sds_port_default_start_io_handler, + .complete_io_handler = scic_sds_port_general_complete_io_handler }, - /* SCI_BASE_PORT_STATE_FAILED */ - { - scic_sds_port_default_start_handler, - scic_sds_port_default_stop_handler, - scic_sds_port_default_destruct_handler, - scic_sds_port_default_reset_handler, - scic_sds_port_default_add_phy_handler, - scic_sds_port_default_remove_phy_handler, - scic_sds_port_default_frame_handler, - scic_sds_port_default_event_handler, - scic_sds_port_default_link_up_handler, - scic_sds_port_default_link_down_handler, - scic_sds_port_default_start_io_handler, - scic_sds_port_general_complete_io_handler + [SCI_BASE_PORT_STATE_FAILED] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_default_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_default_add_phy_handler, + .remove_phy_handler = scic_sds_port_default_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_default_link_up_handler, + .link_down_handler = scic_sds_port_default_link_down_handler, + .start_io_handler = scic_sds_port_default_start_io_handler, + .complete_io_handler = scic_sds_port_general_complete_io_handler } }; -- cgit v1.2.3 From e91f41ef809a2d1b8cdba52ac380aecd706c93dd Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Wed, 11 May 2011 23:52:21 +0000 Subject: isci: merge port ready substates into primary state machine This conversion was complicated by the fact that the ready state exit routine took unconditional action beyond just stopping the substate machine (like in previous conversions). In order to ensure identical behaviour every state transition needs to be instrumented to catch ready-->!ready transitions and execute scic_sds_port_invalidate_dummy_remote_node() Reported-by: Christoph Hellwig Signed-off-by: Piotr Sawicki [fix ready state exit handling] Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 409 ++++++++++++++++++++++------------------------- drivers/scsi/isci/port.h | 57 +++---- 2 files changed, 210 insertions(+), 256 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index e386066825b2..2ea3d0fe091d 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -61,6 +61,8 @@ #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) #define SCU_DUMMY_INDEX (0xFFFF) +static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[]; + static void isci_port_change_state(struct isci_port *iport, enum isci_status status) { unsigned long flags; @@ -856,6 +858,40 @@ static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, } } +static bool is_port_ready_state(enum scic_sds_port_states state) +{ + switch (state) { + case SCI_BASE_PORT_STATE_READY: + case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: + case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + return true; + default: + return false; + } +} + +/* flag dummy rnc hanling when exiting a ready state */ +static void port_state_machine_change(struct scic_sds_port *sci_port, + enum scic_sds_port_states state) +{ + struct sci_base_state_machine *sm = &sci_port->state_machine; + enum scic_sds_port_states old_state = sm->current_state_id; + + if (is_port_ready_state(old_state) && !is_port_ready_state(state)) + sci_port->ready_exit = true; + + sci_base_state_machine_change_state(sm, state); + sci_port->ready_exit = false; +} + +static void port_state_machine_stop(struct scic_sds_port *sci_port) +{ + sci_port->ready_exit = true; + sci_base_state_machine_stop(&sci_port->state_machine); + sci_port->ready_exit = false; +} + /** * scic_sds_port_general_link_up_handler - phy can be assigned to port? * @sci_port: scic_sds_port object for which has a phy that has gone link up. @@ -891,7 +927,7 @@ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING) - sci_base_state_machine_change_state(sm, SCI_BASE_PORT_STATE_READY); + port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_READY); } else scic_sds_port_invalid_link_up(sci_port, sci_phy); } @@ -1025,46 +1061,33 @@ static void scic_sds_port_timeout_handler(void *port) struct scic_sds_port *sci_port = port; u32 current_state; - current_state = sci_base_state_machine_get_state( - &sci_port->state_machine); + current_state = sci_base_state_machine_get_state(&sci_port->state_machine); if (current_state == SCI_BASE_PORT_STATE_RESETTING) { - /* - * if the port is still in the resetting state then the - * timeout fired before the reset completed. + /* if the port is still in the resetting state then the timeout + * fired before the reset completed. */ - sci_base_state_machine_change_state( - &sci_port->state_machine, - SCI_BASE_PORT_STATE_FAILED); + port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_FAILED); } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { - /* - * if the port is stopped then the start request failed - * In this case stay in the stopped state. + /* if the port is stopped then the start request failed In this + * case stay in the stopped state. */ dev_err(sciport_to_dev(sci_port), "%s: SCIC Port 0x%p failed to stop before tiemout.\n", __func__, sci_port); } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { - /* - * if the port is still stopping then the stop has not - * completed - */ - isci_port_stop_complete( - scic_sds_port_get_controller(sci_port), - sci_port, - SCI_FAILURE_TIMEOUT); + /* if the port is still stopping then the stop has not completed */ + isci_port_stop_complete(sci_port->owning_controller, + sci_port, + SCI_FAILURE_TIMEOUT); } else { - /* - * The port is in the ready state and we have a timer + /* The port is in the ready state and we have a timer * reporting a timeout this should not happen. */ dev_err(sciport_to_dev(sci_port), "%s: SCIC Port 0x%p is processing a timeout operation " - "in state %d.\n", - __func__, - sci_port, - current_state); + "in state %d.\n", __func__, sci_port, current_state); } } @@ -1160,14 +1183,9 @@ static void scic_port_enable_broadcast_change_notification(struct scic_sds_port * object. This function will transition the ready substate machine to its * final state. enum sci_status SCI_SUCCESS */ -static enum sci_status scic_sds_port_ready_substate_stop_handler( - struct scic_sds_port *port) +static enum sci_status scic_sds_port_ready_substate_stop_handler(struct scic_sds_port *sci_port) { - sci_base_state_machine_change_state( - &port->state_machine, - SCI_BASE_PORT_STATE_STOPPING - ); - + port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_STOPPING); return SCI_SUCCESS; } @@ -1186,48 +1204,40 @@ static enum sci_status scic_sds_port_ready_substate_complete_io_handler( return SCI_SUCCESS; } -static enum sci_status scic_sds_port_ready_substate_add_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) +static enum sci_status scic_sds_port_ready_substate_add_phy_handler(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) { enum sci_status status; - status = scic_sds_port_set_phy(port, phy); + status = scic_sds_port_set_phy(sci_port, sci_phy); - if (status == SCI_SUCCESS) { - scic_sds_port_general_link_up_handler(port, phy, true); - - port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + if (status != SCI_SUCCESS) + return status; - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); - } + scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); + sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + port_state_machine_change(sci_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); return status; } -static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) +static enum sci_status scic_sds_port_ready_substate_remove_phy_handler(struct scic_sds_port *port, + struct scic_sds_phy *phy) { enum sci_status status; status = scic_sds_port_clear_phy(port, phy); - if (status == SCI_SUCCESS) { - scic_sds_port_deactivate_phy(port, phy, true); + if (status != SCI_SUCCESS) + return status; - port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + scic_sds_port_deactivate_phy(port, phy, true); - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); - } + port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + port_state_machine_change(port, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); return status; } @@ -1255,10 +1265,8 @@ static void scic_sds_port_ready_waiting_substate_link_up_handler( * it and continue. */ scic_sds_port_activate_phy(sci_port, sci_phy, true); - sci_base_state_machine_change_state( - &sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL - ); + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); } /* @@ -1317,9 +1325,8 @@ sci_status scic_sds_port_ready_operational_substate_reset_handler( port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; - sci_base_state_machine_change_state( - &port->state_machine, - SCI_BASE_PORT_STATE_RESETTING); + port_state_machine_change(port, + SCI_BASE_PORT_STATE_RESETTING); } } @@ -1365,8 +1372,8 @@ static void scic_sds_port_ready_operational_substate_link_down_handler( * the port to the WAITING state until such time as a phy goes * link up. */ if (sci_port->active_phy_mask == 0) - sci_base_state_machine_change_state(&sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); } /* @@ -1406,10 +1413,8 @@ static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( /* * Re-enter the configuring state since this may be the last phy in * the port. */ - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); + port_state_machine_change(port, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); } return status; @@ -1427,17 +1432,15 @@ static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handl status = scic_sds_port_clear_phy(port, phy); - if (status == SCI_SUCCESS) { - scic_sds_port_deactivate_phy(port, phy, true); + if (status != SCI_SUCCESS) + return status; + scic_sds_port_deactivate_phy(port, phy, true); - /* - * Re-enter the configuring state since this may be the last phy in - * the port. */ - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING - ); - } + /* Re-enter the configuring state since this may be the last phy in + * the port + */ + port_state_machine_change(port, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); return status; } @@ -1460,10 +1463,8 @@ scic_sds_port_ready_configuring_substate_complete_io_handler( scic_sds_port_decrement_request_count(port); if (port->started_request_count == 0) { - sci_base_state_machine_change_state( - &port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL - ); + port_state_machine_change(port, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); } return SCI_SUCCESS; @@ -1567,61 +1568,6 @@ static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds return default_port_handler(sci_port, __func__); } -static struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[] = { - [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .start_handler = scic_sds_port_default_start_handler, - .stop_handler = scic_sds_port_ready_substate_stop_handler, - .destruct_handler = scic_sds_port_default_destruct_handler, - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, - .remove_phy_handler = scic_sds_port_default_remove_phy_handler, - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, - .link_up_handler = scic_sds_port_ready_waiting_substate_link_up_handler, - .link_down_handler = scic_sds_port_default_link_down_handler, - .start_io_handler = scic_sds_port_ready_waiting_substate_start_io_handler, - .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, - }, - [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .start_handler = scic_sds_port_default_start_handler, - .stop_handler = scic_sds_port_ready_substate_stop_handler, - .destruct_handler = scic_sds_port_default_destruct_handler, - .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, - .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, - .remove_phy_handler = scic_sds_port_ready_substate_remove_phy_handler, - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, - .link_up_handler = scic_sds_port_ready_operational_substate_link_up_handler, - .link_down_handler = scic_sds_port_ready_operational_substate_link_down_handler, - .start_io_handler = scic_sds_port_ready_operational_substate_start_io_handler, - .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, - }, - [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .start_handler = scic_sds_port_default_start_handler, - .stop_handler = scic_sds_port_ready_substate_stop_handler, - .destruct_handler = scic_sds_port_default_destruct_handler, - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_ready_configuring_substate_add_phy_handler, - .remove_phy_handler = scic_sds_port_ready_configuring_substate_remove_phy_handler, - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, - .link_up_handler = scic_sds_port_default_link_up_handler, - .link_down_handler = scic_sds_port_default_link_down_handler, - .start_io_handler = scic_sds_port_default_start_io_handler, - .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler - } -}; - -/** - * scic_sds_port_set_ready_state_handlers() - - * - * This macro sets the port ready substate handlers. - */ -#define scic_sds_port_set_ready_state_handlers(port, state_id) \ - scic_sds_port_set_state_handlers(\ - port, &scic_sds_port_ready_substate_handler_table[(state_id)] \ - ) - /* * ****************************************************************************** * * PORT STATE PRIVATE METHODS @@ -1729,7 +1675,7 @@ static void scic_sds_port_ready_substate_waiting_enter(void *object) { struct scic_sds_port *sci_port = object; - scic_sds_port_set_ready_state_handlers( + scic_sds_port_set_base_state_handlers( sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING ); @@ -1739,10 +1685,8 @@ static void scic_sds_port_ready_substate_waiting_enter(void *object) if (sci_port->active_phy_mask != 0) { /* At least one of the phys on the port is ready */ - sci_base_state_machine_change_state( - &sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL - ); + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); } } @@ -1763,7 +1707,7 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); - scic_sds_port_set_ready_state_handlers( + scic_sds_port_set_base_state_handlers( sci_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); @@ -1788,6 +1732,31 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) scic_sds_port_post_dummy_request(sci_port); } +static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + u8 phys_index = sci_port->physical_port_index; + union scu_remote_node_context *rnc; + u16 rni = sci_port->reserved_rni; + u32 command; + + rnc = &scic->remote_node_context_table[rni]; + + rnc->ssp.is_valid = false; + + /* ensure the preceding tc abort request has reached the + * controller and give it ample time to act before posting the rnc + * invalidate + */ + readl(&scic->smu_registers->interrupt_status); /* flush */ + udelay(10); + + command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | + phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; + + scic_sds_controller_post_request(scic, command); +} + /** * * @object: This is the object which is cast to a struct scic_sds_port object. @@ -1811,6 +1780,9 @@ static void scic_sds_port_ready_substate_operational_exit(void *object) scic_sds_port_abort_dummy_request(sci_port); isci_port_not_ready(ihost, iport); + + if (sci_port->ready_exit) + scic_sds_port_invalidate_dummy_remote_node(sci_port); } /* @@ -1833,20 +1805,18 @@ static void scic_sds_port_ready_substate_configuring_enter(void *object) struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); - scic_sds_port_set_ready_state_handlers( + scic_sds_port_set_base_state_handlers( sci_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); if (sci_port->active_phy_mask == 0) { isci_port_not_ready(ihost, iport); - sci_base_state_machine_change_state( - &sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); } else if (sci_port->started_request_count == 0) - sci_base_state_machine_change_state( - &sci_port->ready_substate_machine, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); } static void scic_sds_port_ready_substate_configuring_exit(void *object) @@ -1854,24 +1824,12 @@ static void scic_sds_port_ready_substate_configuring_exit(void *object) struct scic_sds_port *sci_port = object; scic_sds_port_suspend_port_task_scheduler(sci_port); + if (sci_port->ready_exit) + scic_sds_port_invalidate_dummy_remote_node(sci_port); } /* --------------------------------------------------------------------------- */ -static const struct sci_base_state scic_sds_port_ready_substate_table[] = { - [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .enter_state = scic_sds_port_ready_substate_waiting_enter, - }, - [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .enter_state = scic_sds_port_ready_substate_operational_enter, - .exit_state = scic_sds_port_ready_substate_operational_exit - }, - [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .enter_state = scic_sds_port_ready_substate_configuring_enter, - .exit_state = scic_sds_port_ready_substate_configuring_exit - }, -}; - /** * * @port: This is the struct scic_sds_port object on which the io request count will @@ -1970,9 +1928,8 @@ scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port) * silicon. */ if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { - sci_base_state_machine_change_state( - &sci_port->state_machine, - SCI_BASE_PORT_STATE_READY); + port_state_machine_change(sci_port, + SCI_BASE_PORT_STATE_READY); return SCI_SUCCESS; } else @@ -2003,10 +1960,9 @@ static enum sci_status scic_sds_port_stopped_state_stop_handler( * struct scic_sds_port can be destroyed. This function causes the port object to * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS */ -static enum sci_status scic_sds_port_stopped_state_destruct_handler( - struct scic_sds_port *port) +static enum sci_status scic_sds_port_stopped_state_destruct_handler(struct scic_sds_port *port) { - sci_base_state_machine_stop(&port->state_machine); + port_state_machine_stop(port); return SCI_SUCCESS; } @@ -2087,10 +2043,9 @@ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( { scic_sds_port_decrement_request_count(sci_port); - if (sci_port->started_request_count == 0) { - sci_base_state_machine_change_state(&sci_port->state_machine, - SCI_BASE_PORT_STATE_STOPPED); - } + if (sci_port->started_request_count == 0) + port_state_machine_change(sci_port, + SCI_BASE_PORT_STATE_STOPPED); return SCI_SUCCESS; } @@ -2110,10 +2065,8 @@ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( static enum sci_status scic_sds_port_reset_state_stop_handler( struct scic_sds_port *port) { - sci_base_state_machine_change_state( - &port->state_machine, - SCI_BASE_PORT_STATE_STOPPING - ); + port_state_machine_change(port, + SCI_BASE_PORT_STATE_STOPPING); return SCI_SUCCESS; } @@ -2201,6 +2154,48 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_general_complete_io_handler }, + [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_ready_substate_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, + .remove_phy_handler = scic_sds_port_default_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_ready_waiting_substate_link_up_handler, + .link_down_handler = scic_sds_port_default_link_down_handler, + .start_io_handler = scic_sds_port_ready_waiting_substate_start_io_handler, + .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, + }, + [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_ready_substate_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, + .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, + .remove_phy_handler = scic_sds_port_ready_substate_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_ready_operational_substate_link_up_handler, + .link_down_handler = scic_sds_port_ready_operational_substate_link_down_handler, + .start_io_handler = scic_sds_port_ready_operational_substate_start_io_handler, + .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, + }, + [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { + .start_handler = scic_sds_port_default_start_handler, + .stop_handler = scic_sds_port_ready_substate_stop_handler, + .destruct_handler = scic_sds_port_default_destruct_handler, + .reset_handler = scic_sds_port_default_reset_handler, + .add_phy_handler = scic_sds_port_ready_configuring_substate_add_phy_handler, + .remove_phy_handler = scic_sds_port_ready_configuring_substate_remove_phy_handler, + .frame_handler = scic_sds_port_default_frame_handler, + .event_handler = scic_sds_port_default_event_handler, + .link_up_handler = scic_sds_port_default_link_up_handler, + .link_down_handler = scic_sds_port_default_link_down_handler, + .start_io_handler = scic_sds_port_default_start_io_handler, + .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler + }, [SCI_BASE_PORT_STATE_RESETTING] = { .start_handler = scic_sds_port_default_start_handler, .stop_handler = scic_sds_port_reset_state_stop_handler, @@ -2299,31 +2294,6 @@ static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) scic_sds_controller_post_request(scic, command); } -static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - u8 phys_index = sci_port->physical_port_index; - union scu_remote_node_context *rnc; - u16 rni = sci_port->reserved_rni; - u32 command; - - rnc = &scic->remote_node_context_table[rni]; - - rnc->ssp.is_valid = false; - - /* ensure the preceding tc abort request has reached the - * controller and give it ample time to act before posting the rnc - * invalidate - */ - readl(&scic->smu_registers->interrupt_status); /* flush */ - udelay(10); - - command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | - phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - - scic_sds_controller_post_request(scic, command); -} - /* * ****************************************************************************** * * PORT STATE METHODS @@ -2404,15 +2374,8 @@ static void scic_sds_port_ready_state_enter(void *object) scic_sds_port_post_dummy_remote_node(sci_port); /* Start the ready substate machine */ - sci_base_state_machine_start(&sci_port->ready_substate_machine); -} - -static void scic_sds_port_ready_state_exit(void *object) -{ - struct scic_sds_port *sci_port = object; - - sci_base_state_machine_stop(&sci_port->ready_substate_machine); - scic_sds_port_invalidate_dummy_remote_node(sci_port); + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); } /** @@ -2516,7 +2479,17 @@ static const struct sci_base_state scic_sds_port_state_table[] = { }, [SCI_BASE_PORT_STATE_READY] = { .enter_state = scic_sds_port_ready_state_enter, - .exit_state = scic_sds_port_ready_state_exit + }, + [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { + .enter_state = scic_sds_port_ready_substate_waiting_enter, + }, + [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { + .enter_state = scic_sds_port_ready_substate_operational_enter, + .exit_state = scic_sds_port_ready_substate_operational_exit + }, + [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { + .enter_state = scic_sds_port_ready_substate_configuring_enter, + .exit_state = scic_sds_port_ready_substate_configuring_exit }, [SCI_BASE_PORT_STATE_RESETTING] = { .enter_state = scic_sds_port_resetting_state_enter, @@ -2537,14 +2510,10 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, sci_base_state_machine_start(&sci_port->state_machine); - sci_base_state_machine_construct(&sci_port->ready_substate_machine, - sci_port, - scic_sds_port_ready_substate_table, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); - sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; sci_port->physical_port_index = index; sci_port->active_phy_mask = 0; + sci_port->ready_exit = false; sci_port->owning_controller = scic; diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index ea41dcead3ae..e63c34d02b7d 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -81,12 +81,13 @@ enum isci_status { * The core port object provides the the abstraction for an SCU port. */ struct scic_sds_port { - /** * This field contains the information for the base port state machine. */ struct sci_base_state_machine state_machine; + bool ready_exit; + /** * This field is the port index that is reported to the SCI USER. * This allows the actual hardware physical port to change without @@ -150,11 +151,6 @@ struct scic_sds_port { */ struct scic_sds_port_state_handler *state_handlers; - /** - * This field is the ready substate machine for the port. - */ - struct sci_base_state_machine ready_substate_machine; - /* / Memory mapped hardware register space */ /** @@ -175,7 +171,6 @@ struct scic_sds_port { * This field is the VIIT register space for ths port object. */ struct scu_viit_entry __iomem *viit_registers; - }; @@ -228,35 +223,6 @@ struct scic_port_properties { u32 phy_mask; }; -/** - * enum SCIC_SDS_PORT_READY_SUBSTATES - - * - * This enumeration depicts all of the states for the core port ready substate - * machine. - */ -enum scic_sds_port_ready_substates { - /** - * The substate where the port is started and ready but has no - * active phys. - */ - SCIC_SDS_PORT_READY_SUBSTATE_WAITING, - - /** - * The substate where the port is started and ready and there is - * at least one phy operational. - */ - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, - - /** - * The substate where the port is started and there was an - * add/remove phy event. This state is only used in Automatic - * Port Configuration Mode (APC) - */ - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, - - SCIC_SDS_PORT_READY_MAX_SUBSTATES -}; - /** * enum scic_sds_port_states - This enumeration depicts all the states for the * common port state machine. @@ -286,6 +252,25 @@ enum scic_sds_port_states { */ SCI_BASE_PORT_STATE_READY, + /** + * The substate where the port is started and ready but has no + * active phys. + */ + SCIC_SDS_PORT_READY_SUBSTATE_WAITING, + + /** + * The substate where the port is started and ready and there is + * at least one phy operational. + */ + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, + + /** + * The substate where the port is started and there was an + * add/remove phy event. This state is only used in Automatic + * Port Configuration Mode (APC) + */ + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, + /** * This state indicates the port is in the process of performing a hard * reset. Thus, the user is unable to perform IO operations on this -- cgit v1.2.3 From d76f71d988ef48384593ad97ebc762d9257d96a8 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Wed, 11 May 2011 23:52:26 +0000 Subject: isci: remove port start handler remove the handler from the port state handler table and implement the logic directly in scic_sds_port_start(). Signed-off-by: Piotr Sawicki [remove a level of indirection] Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 2 +- drivers/scsi/isci/port.c | 180 ++++++++++++++++++++--------------------------- drivers/scsi/isci/port.h | 8 +-- 3 files changed, 80 insertions(+), 110 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 2ef1c592a16f..7abfb663ca94 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1108,7 +1108,7 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, for (index = 0; index < scic->logical_port_entries; index++) { struct scic_sds_port *sci_port = &ihost->ports[index].sci; - result = sci_port->state_handlers->start_handler(sci_port); + result = scic_sds_port_start(sci_port); if (result) return result; } diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 2ea3d0fe091d..64559e8e568d 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1479,12 +1479,6 @@ static enum sci_status default_port_handler(struct scic_sds_port *sci_port, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_port_default_start_handler(struct scic_sds_port *sci_port) -{ - return default_port_handler(sci_port, __func__); -} - static enum sci_status scic_sds_port_default_stop_handler(struct scic_sds_port *sci_port) { @@ -1853,95 +1847,6 @@ static enum sci_status scic_sds_port_general_complete_io_handler( return SCI_SUCCESS; } -/** - * scic_sds_port_stopped_state_start_handler() - stop a port from "started" - * - * @port: This is the struct scic_sds_port object which is cast into a - * struct scic_sds_port object. - * - * This function takes the struct scic_sds_port from a stopped state and - * attempts to start it. To start a port it must have no assiged devices and - * it must have at least one phy assigned to it. If those conditions are - * met then the port can transition to the ready state. - * enum sci_status - * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION - * This struct scic_sds_port object could not be started because the port - * configuration is not valid. - * SCI_SUCCESS - * the start request is successful and the struct scic_sds_port object - * has transitioned to the SCI_BASE_PORT_STATE_READY. - */ -static enum sci_status -scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port) -{ - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); - enum sci_status status = SCI_SUCCESS; - u32 phy_mask; - - if (sci_port->assigned_device_count > 0) { - /* - * @todo This is a start failure operation because - * there are still devices assigned to this port. - * There must be no devices assigned to a port on a - * start operation. - */ - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - - sci_port->timer_handle = - isci_timer_create(ihost, - sci_port, - scic_sds_port_timeout_handler); - - if (!sci_port->timer_handle) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - - if (sci_port->reserved_rni == SCU_DUMMY_INDEX) { - u16 rni = scic_sds_remote_node_table_allocate_remote_node( - &scic->available_remote_nodes, 1); - - if (rni != SCU_DUMMY_INDEX) - scic_sds_port_construct_dummy_rnc(sci_port, rni); - else - status = SCI_FAILURE_INSUFFICIENT_RESOURCES; - sci_port->reserved_rni = rni; - } - - if (sci_port->reserved_tci == SCU_DUMMY_INDEX) { - /* Allocate a TCI and remove the sequence nibble */ - u16 tci = scic_controller_allocate_io_tag(scic); - - if (tci != SCU_DUMMY_INDEX) - scic_sds_port_construct_dummy_task(sci_port, tci); - else - status = SCI_FAILURE_INSUFFICIENT_RESOURCES; - sci_port->reserved_tci = tci; - } - - if (status == SCI_SUCCESS) { - phy_mask = scic_sds_port_get_phys(sci_port); - - /* - * There are one or more phys assigned to this port. Make sure - * the port's phy mask is in fact legal and supported by the - * silicon. - */ - if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { - port_state_machine_change(sci_port, - SCI_BASE_PORT_STATE_READY); - - return SCI_SUCCESS; - } else - status = SCI_FAILURE; - } - - if (status != SCI_SUCCESS) - scic_sds_port_destroy_dummy_resources(sci_port); - - return status; -} - /* * This method takes the struct scic_sds_port that is in a stopped state and handles a * stop request. This function takes no action. enum sci_status SCI_SUCCESS the @@ -2111,9 +2016,85 @@ static void scic_sds_port_reset_state_link_down_handler( scic_sds_port_deactivate_phy(port, phy, false); } +enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) +{ + struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); + enum sci_status status = SCI_SUCCESS; + enum scic_sds_port_states state; + u32 phy_mask; + + state = sci_port->state_machine.current_state_id; + if (state != SCI_BASE_PORT_STATE_STOPPED) { + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + if (sci_port->assigned_device_count > 0) { + /* TODO This is a start failure operation because + * there are still devices assigned to this port. + * There must be no devices assigned to a port on a + * start operation. + */ + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + + sci_port->timer_handle = + isci_timer_create(ihost, + sci_port, + scic_sds_port_timeout_handler); + + if (!sci_port->timer_handle) + return SCI_FAILURE_INSUFFICIENT_RESOURCES; + + if (sci_port->reserved_rni == SCU_DUMMY_INDEX) { + u16 rni = scic_sds_remote_node_table_allocate_remote_node( + &scic->available_remote_nodes, 1); + + if (rni != SCU_DUMMY_INDEX) + scic_sds_port_construct_dummy_rnc(sci_port, rni); + else + status = SCI_FAILURE_INSUFFICIENT_RESOURCES; + sci_port->reserved_rni = rni; + } + + if (sci_port->reserved_tci == SCU_DUMMY_INDEX) { + /* Allocate a TCI and remove the sequence nibble */ + u16 tci = scic_controller_allocate_io_tag(scic); + + if (tci != SCU_DUMMY_INDEX) + scic_sds_port_construct_dummy_task(sci_port, tci); + else + status = SCI_FAILURE_INSUFFICIENT_RESOURCES; + sci_port->reserved_tci = tci; + } + + if (status == SCI_SUCCESS) { + phy_mask = scic_sds_port_get_phys(sci_port); + + /* + * There are one or more phys assigned to this port. Make sure + * the port's phy mask is in fact legal and supported by the + * silicon. + */ + if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { + port_state_machine_change(sci_port, + SCI_BASE_PORT_STATE_READY); + + return SCI_SUCCESS; + } + status = SCI_FAILURE; + } + + if (status != SCI_SUCCESS) + scic_sds_port_destroy_dummy_resources(sci_port); + + return status; +} + static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = { [SCI_BASE_PORT_STATE_STOPPED] = { - .start_handler = scic_sds_port_stopped_state_start_handler, .stop_handler = scic_sds_port_stopped_state_stop_handler, .destruct_handler = scic_sds_port_stopped_state_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, @@ -2127,7 +2108,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_default_complete_io_handler }, [SCI_BASE_PORT_STATE_STOPPING] = { - .start_handler = scic_sds_port_default_start_handler, .stop_handler = scic_sds_port_default_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, @@ -2141,7 +2121,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_stopping_state_complete_io_handler }, [SCI_BASE_PORT_STATE_READY] = { - .start_handler = scic_sds_port_default_start_handler, .stop_handler = scic_sds_port_default_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, @@ -2155,7 +2134,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .start_handler = scic_sds_port_default_start_handler, .stop_handler = scic_sds_port_ready_substate_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, @@ -2169,7 +2147,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .start_handler = scic_sds_port_default_start_handler, .stop_handler = scic_sds_port_ready_substate_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, @@ -2183,7 +2160,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .start_handler = scic_sds_port_default_start_handler, .stop_handler = scic_sds_port_ready_substate_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, @@ -2197,7 +2173,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler }, [SCI_BASE_PORT_STATE_RESETTING] = { - .start_handler = scic_sds_port_default_start_handler, .stop_handler = scic_sds_port_reset_state_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, @@ -2211,7 +2186,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCI_BASE_PORT_STATE_FAILED] = { - .start_handler = scic_sds_port_default_start_handler, .stop_handler = scic_sds_port_default_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index e63c34d02b7d..2ad205100f25 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -312,12 +312,6 @@ typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_po struct scic_sds_request *); struct scic_sds_port_state_handler { - /** - * The start_handler specifies the method invoked when a user - * attempts to start a port. - */ - scic_sds_port_handler_t start_handler; - /** * The stop_handler specifies the method invoked when a user * attempts to stop a port. @@ -417,6 +411,8 @@ enum sci_status scic_sds_port_initialize( void __iomem *port_configuration_regsiter, void __iomem *viit_registers); +enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port); + enum sci_status scic_sds_port_add_phy( struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy); -- cgit v1.2.3 From 8bc80d303063d9540493be623df1c9a8dee9ccb8 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Wed, 11 May 2011 23:52:31 +0000 Subject: isci: unify port stop handlers Implement the stop handlers directly in scic_sds_port_stop() Reported-by: Christoph Hellwig Signed-off-by: Piotr Sawicki Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 4 +-- drivers/scsi/isci/port.c | 75 ++++++++++++++---------------------------------- drivers/scsi/isci/port.h | 7 +---- 3 files changed, 24 insertions(+), 62 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 7abfb663ca94..a942384f2798 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1591,10 +1591,8 @@ static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller for (index = 0; index < scic->logical_port_entries; index++) { struct scic_sds_port *sci_port = &ihost->ports[index].sci; - scic_sds_port_handler_t stop; - stop = sci_port->state_handlers->stop_handler; - port_status = stop(sci_port); + port_status = scic_sds_port_stop(sci_port); if ((port_status != SCI_SUCCESS) && (port_status != SCI_FAILURE_INVALID_STATE)) { diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 64559e8e568d..62e9785acfb0 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1178,17 +1178,6 @@ static void scic_port_enable_broadcast_change_notification(struct scic_sds_port * * READY SUBSTATE HANDLERS * **************************************************************************** */ -/* - * This method is the general ready state stop handler for the struct scic_sds_port - * object. This function will transition the ready substate machine to its - * final state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_ready_substate_stop_handler(struct scic_sds_port *sci_port) -{ - port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_STOPPING); - return SCI_SUCCESS; -} - /* * This method is the general ready substate complete io handler for the * struct scic_sds_port object. This function decrments the outstanding request count @@ -1479,12 +1468,6 @@ static enum sci_status default_port_handler(struct scic_sds_port *sci_port, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_port_default_stop_handler(struct scic_sds_port *sci_port) -{ - return default_port_handler(sci_port, __func__); -} - static enum sci_status scic_sds_port_default_destruct_handler(struct scic_sds_port *sci_port) { @@ -1847,18 +1830,6 @@ static enum sci_status scic_sds_port_general_complete_io_handler( return SCI_SUCCESS; } -/* - * This method takes the struct scic_sds_port that is in a stopped state and handles a - * stop request. This function takes no action. enum sci_status SCI_SUCCESS the - * stop request is successful as the struct scic_sds_port object is already stopped. - */ -static enum sci_status scic_sds_port_stopped_state_stop_handler( - struct scic_sds_port *port) -{ - /* We are already stopped so there is nothing to do here */ - return SCI_SUCCESS; -} - /* * This method takes the struct scic_sds_port that is in a stopped state and handles * the destruct request. The stopped state is the only state in which the @@ -1960,22 +1931,6 @@ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( * * RESETTING STATE HANDLERS * **************************************************************************** */ -/** - * - * @port: This is the port object which is being requested to stop. - * - * This method will stop a failed port. This causes a transition to the - * stopping state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_reset_state_stop_handler( - struct scic_sds_port *port) -{ - port_state_machine_change(port, - SCI_BASE_PORT_STATE_STOPPING); - - return SCI_SUCCESS; -} - /* * This method will transition a failed port to its ready state. The port * failed because a hard reset request timed out but at some time later one or @@ -2093,9 +2048,30 @@ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) return status; } +enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port) +{ + enum scic_sds_port_states state; + + state = sci_port->state_machine.current_state_id; + switch (state) { + case SCI_BASE_PORT_STATE_STOPPED: + return SCI_SUCCESS; + case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: + case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + case SCI_BASE_PORT_STATE_RESETTING: + port_state_machine_change(sci_port, + SCI_BASE_PORT_STATE_STOPPING); + return SCI_SUCCESS; + default: + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } +} + static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = { [SCI_BASE_PORT_STATE_STOPPED] = { - .stop_handler = scic_sds_port_stopped_state_stop_handler, .destruct_handler = scic_sds_port_stopped_state_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_stopped_state_add_phy_handler, @@ -2108,7 +2084,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_default_complete_io_handler }, [SCI_BASE_PORT_STATE_STOPPING] = { - .stop_handler = scic_sds_port_default_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_default_add_phy_handler, @@ -2121,7 +2096,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_stopping_state_complete_io_handler }, [SCI_BASE_PORT_STATE_READY] = { - .stop_handler = scic_sds_port_default_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_default_add_phy_handler, @@ -2134,7 +2108,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .stop_handler = scic_sds_port_ready_substate_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, @@ -2147,7 +2120,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .stop_handler = scic_sds_port_ready_substate_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, @@ -2160,7 +2132,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .stop_handler = scic_sds_port_ready_substate_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_ready_configuring_substate_add_phy_handler, @@ -2173,7 +2144,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler }, [SCI_BASE_PORT_STATE_RESETTING] = { - .stop_handler = scic_sds_port_reset_state_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_default_add_phy_handler, @@ -2186,7 +2156,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCI_BASE_PORT_STATE_FAILED] = { - .stop_handler = scic_sds_port_default_stop_handler, .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_default_add_phy_handler, diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 2ad205100f25..843eb62a3090 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -312,12 +312,6 @@ typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_po struct scic_sds_request *); struct scic_sds_port_state_handler { - /** - * The stop_handler specifies the method invoked when a user - * attempts to stop a port. - */ - scic_sds_port_handler_t stop_handler; - /** * The destruct_handler specifies the method invoked when attempting to * destruct a port. @@ -412,6 +406,7 @@ enum sci_status scic_sds_port_initialize( void __iomem *viit_registers); enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port); +enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port); enum sci_status scic_sds_port_add_phy( struct scic_sds_port *sci_port, -- cgit v1.2.3 From e6ec5afde9794f50e60788bd10760fcd0d609252 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Wed, 11 May 2011 23:52:37 +0000 Subject: isci: remove port destruct handler The handler was never used. Signed-off-by: Piotr Sawicki Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 34 ---------------------------------- drivers/scsi/isci/port.h | 6 ------ 2 files changed, 40 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 62e9785acfb0..1a058a27ebc1 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -885,13 +885,6 @@ static void port_state_machine_change(struct scic_sds_port *sci_port, sci_port->ready_exit = false; } -static void port_state_machine_stop(struct scic_sds_port *sci_port) -{ - sci_port->ready_exit = true; - sci_base_state_machine_stop(&sci_port->state_machine); - sci_port->ready_exit = false; -} - /** * scic_sds_port_general_link_up_handler - phy can be assigned to port? * @sci_port: scic_sds_port object for which has a phy that has gone link up. @@ -1468,12 +1461,6 @@ static enum sci_status default_port_handler(struct scic_sds_port *sci_port, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_port_default_destruct_handler(struct scic_sds_port *sci_port) -{ - return default_port_handler(sci_port, __func__); -} - static enum sci_status scic_sds_port_default_reset_handler(struct scic_sds_port *sci_port, u32 timeout) @@ -1830,19 +1817,6 @@ static enum sci_status scic_sds_port_general_complete_io_handler( return SCI_SUCCESS; } -/* - * This method takes the struct scic_sds_port that is in a stopped state and handles - * the destruct request. The stopped state is the only state in which the - * struct scic_sds_port can be destroyed. This function causes the port object to - * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_stopped_state_destruct_handler(struct scic_sds_port *port) -{ - port_state_machine_stop(port); - - return SCI_SUCCESS; -} - /* * This method takes the struct scic_sds_port that is in a stopped state and handles * the add phy request. In MPC mode the only time a phy can be added to a port @@ -2072,7 +2046,6 @@ enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port) static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = { [SCI_BASE_PORT_STATE_STOPPED] = { - .destruct_handler = scic_sds_port_stopped_state_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_stopped_state_add_phy_handler, .remove_phy_handler = scic_sds_port_stopped_state_remove_phy_handler, @@ -2084,7 +2057,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_default_complete_io_handler }, [SCI_BASE_PORT_STATE_STOPPING] = { - .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_default_add_phy_handler, .remove_phy_handler = scic_sds_port_default_remove_phy_handler, @@ -2096,7 +2068,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_stopping_state_complete_io_handler }, [SCI_BASE_PORT_STATE_READY] = { - .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_default_add_phy_handler, .remove_phy_handler = scic_sds_port_default_remove_phy_handler, @@ -2108,7 +2079,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, .remove_phy_handler = scic_sds_port_default_remove_phy_handler, @@ -2120,7 +2090,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, .remove_phy_handler = scic_sds_port_ready_substate_remove_phy_handler, @@ -2132,7 +2101,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_ready_configuring_substate_add_phy_handler, .remove_phy_handler = scic_sds_port_ready_configuring_substate_remove_phy_handler, @@ -2144,7 +2112,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler }, [SCI_BASE_PORT_STATE_RESETTING] = { - .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_default_add_phy_handler, .remove_phy_handler = scic_sds_port_default_remove_phy_handler, @@ -2156,7 +2123,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCI_BASE_PORT_STATE_FAILED] = { - .destruct_handler = scic_sds_port_default_destruct_handler, .reset_handler = scic_sds_port_default_reset_handler, .add_phy_handler = scic_sds_port_default_add_phy_handler, .remove_phy_handler = scic_sds_port_default_remove_phy_handler, diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 843eb62a3090..70163710988c 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -312,12 +312,6 @@ typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_po struct scic_sds_request *); struct scic_sds_port_state_handler { - /** - * The destruct_handler specifies the method invoked when attempting to - * destruct a port. - */ - scic_sds_port_handler_t destruct_handler; - /** * The reset_handler specifies the method invoked when a user * attempts to hard reset a port. -- cgit v1.2.3 From bd6713b416bbfc7d7180114f7cc543b152cc1725 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Thu, 12 May 2011 19:10:03 +0000 Subject: isci: unify port reset, add_phy, and remove_phy handlers Unify the implementations and remove the state handlers. Reported-by: Christoph Hellwig Signed-off-by: Piotr Sawicki Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 471 ++++++++++++++++------------------------------- drivers/scsi/isci/port.h | 19 -- 2 files changed, 163 insertions(+), 327 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 1a058a27ebc1..5501e14c8d93 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -531,40 +531,6 @@ static enum sci_status scic_sds_port_clear_phy( return SCI_FAILURE; } -/** - * scic_sds_port_add_phy() - - * @sci_port: This parameter specifies the port in which the phy will be added. - * @sci_phy: This parameter is the phy which is to be added to the port. - * - * This method will add a PHY to the selected port. This method returns an - * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status - * is failre to add the phy to the port. - */ -enum sci_status scic_sds_port_add_phy( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - return sci_port->state_handlers->add_phy_handler( - sci_port, sci_phy); -} - - -/** - * scic_sds_port_remove_phy() - - * @sci_port: This parameter specifies the port in which the phy will be added. - * @sci_phy: This parameter is the phy which is to be added to the port. - * - * This method will remove the PHY from the selected PORT. This method returns - * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other - * status is failre to add the phy to the port. - */ -enum sci_status scic_sds_port_remove_phy( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - return sci_port->state_handlers->remove_phy_handler( - sci_port, sci_phy); -} /** * This method requests the SAS address for the supplied SAS port from the SCI @@ -745,23 +711,6 @@ enum sci_status scic_sds_port_initialize( return SCI_SUCCESS; } -/** - * scic_port_hard_reset() - perform port hard reset - * @port: a handle corresponding to the SAS port to be hard reset. - * @reset_timeout: This parameter specifies the number of milliseconds in which - * the port reset operation should complete. - * - * The SCI User callback in scic_user_callbacks_t will only be called once for - * each phy in the SAS Port at completion of the hard reset sequence. Return a - * status indicating whether the hard reset started successfully. SCI_SUCCESS - * This value is returned if the hard reset operation started successfully. - */ -static enum sci_status scic_port_hard_reset(struct scic_sds_port *port, - u32 reset_timeout) -{ - return port->state_handlers->reset_handler( - port, reset_timeout); -} /** * This method assigns the direct attached device ID for this port. @@ -1186,48 +1135,6 @@ static enum sci_status scic_sds_port_ready_substate_complete_io_handler( return SCI_SUCCESS; } -static enum sci_status scic_sds_port_ready_substate_add_phy_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - enum sci_status status; - - status = scic_sds_port_set_phy(sci_port, sci_phy); - - if (status != SCI_SUCCESS) - return status; - - scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); - sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; - port_state_machine_change(sci_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); - - return status; -} - - -static enum sci_status scic_sds_port_ready_substate_remove_phy_handler(struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - enum sci_status status; - - status = scic_sds_port_clear_phy(port, phy); - - if (status != SCI_SUCCESS) - return status; - - scic_sds_port_deactivate_phy(port, phy, true); - - port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; - - port_state_machine_change(port, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); - return status; -} - -/* - * **************************************************************************** - * * READY SUBSTATE WAITING HANDLERS - * **************************************************************************** */ - /** * * @sci_port: This is the struct scic_sds_port object that which has a phy that has @@ -1264,57 +1171,6 @@ static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( return SCI_FAILURE_INVALID_STATE; } -/* - * **************************************************************************** - * * READY SUBSTATE OPERATIONAL HANDLERS - * **************************************************************************** */ - -/* - * This method will casue the port to reset. enum sci_status SCI_SUCCESS - */ -static enum -sci_status scic_sds_port_ready_operational_substate_reset_handler( - struct scic_sds_port *port, - u32 timeout) -{ - enum sci_status status = SCI_FAILURE_INVALID_PHY; - u32 phy_index; - struct scic_sds_phy *selected_phy = NULL; - - - /* Select a phy on which we can send the hard reset request. */ - for (phy_index = 0; - (phy_index < SCI_MAX_PHYS) && (selected_phy == NULL); - phy_index++) { - selected_phy = port->phy_table[phy_index]; - - if ((selected_phy != NULL) && - !scic_sds_port_active_phy(port, selected_phy)) { - /* - * We found a phy but it is not ready select - * different phy - */ - selected_phy = NULL; - } - } - - /* If we have a phy then go ahead and start the reset procedure */ - if (selected_phy != NULL) { - status = scic_sds_phy_reset(selected_phy); - - if (status == SCI_SUCCESS) { - isci_timer_start(port->timer_handle, timeout); - port->not_ready_reason = - SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; - - port_state_machine_change(port, - SCI_BASE_PORT_STATE_RESETTING); - } - } - - return status; -} - /** * scic_sds_port_ready_operational_substate_link_up_handler() - * @sci_port: This is the struct scic_sds_port object that which has a phy that has @@ -1372,61 +1228,6 @@ static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler return SCI_SUCCESS; } -/* - * **************************************************************************** - * * READY SUBSTATE OPERATIONAL HANDLERS - * **************************************************************************** */ - -/* - * This is the default method for a port add phy request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - enum sci_status status; - - status = scic_sds_port_set_phy(port, phy); - - if (status == SCI_SUCCESS) { - scic_sds_port_general_link_up_handler(port, phy, true); - - /* - * Re-enter the configuring state since this may be the last phy in - * the port. */ - port_state_machine_change(port, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); - } - - return status; -} - -/* - * This is the default method for a port remove phy request. It will report a - * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - enum sci_status status; - - status = scic_sds_port_clear_phy(port, phy); - - if (status != SCI_SUCCESS) - return status; - scic_sds_port_deactivate_phy(port, phy, true); - - /* Re-enter the configuring state since this may be the last phy in - * the port - */ - port_state_machine_change(port, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); - - return status; -} - /** * scic_sds_port_ready_configuring_substate_complete_io_handler() - * @port: This is the port that is being requested to complete the io request. @@ -1461,27 +1262,6 @@ static enum sci_status default_port_handler(struct scic_sds_port *sci_port, return SCI_FAILURE_INVALID_STATE; } -static enum sci_status -scic_sds_port_default_reset_handler(struct scic_sds_port *sci_port, - u32 timeout) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status -scic_sds_port_default_add_phy_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *base_phy) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status -scic_sds_port_default_remove_phy_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *base_phy) -{ - return default_port_handler(sci_port, __func__); -} - /* * This is the default method for a port unsolicited frame request. It will * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even @@ -1817,70 +1597,6 @@ static enum sci_status scic_sds_port_general_complete_io_handler( return SCI_SUCCESS; } -/* - * This method takes the struct scic_sds_port that is in a stopped state and handles - * the add phy request. In MPC mode the only time a phy can be added to a port - * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status - * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not - * be added to the port. SCI_SUCCESS if the phy is added to the port. - */ -static enum sci_status scic_sds_port_stopped_state_add_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - struct sci_sas_address port_sas_address; - - /* Read the port assigned SAS Address if there is one */ - scic_sds_port_get_sas_address(port, &port_sas_address); - - if (port_sas_address.high != 0 && port_sas_address.low != 0) { - struct sci_sas_address phy_sas_address; - - /* - * Make sure that the PHY SAS Address matches the SAS Address - * for this port. */ - scic_sds_phy_get_sas_address(phy, &phy_sas_address); - - if ( - (port_sas_address.high != phy_sas_address.high) - || (port_sas_address.low != phy_sas_address.low) - ) { - return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; - } - } - - return scic_sds_port_set_phy(port, phy); -} - -/* - * This method takes the struct scic_sds_port that is in a stopped state and handles - * the remove phy request. In MPC mode the only time a phy can be removed from - * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status - * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not - * be added to the port. SCI_SUCCESS if the phy is added to the port. - */ -static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - return scic_sds_port_clear_phy(port, phy); -} - -/* - * **************************************************************************** - * * READY STATE HANDLERS - * **************************************************************************** */ - -/* - * **************************************************************************** - * * RESETTING STATE HANDLERS - * **************************************************************************** */ - -/* - * **************************************************************************** - * * STOPPING STATE HANDLERS - * **************************************************************************** */ - /* * This method takes the struct scic_sds_port that is in a stopping state and handles * the complete io request. Should the request count reach 0 then the port @@ -2044,11 +1760,171 @@ enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port) } } +static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 timeout) +{ + enum sci_status status = SCI_FAILURE_INVALID_PHY; + struct scic_sds_phy *selected_phy = NULL; + enum scic_sds_port_states state; + u32 phy_index; + + state = sci_port->state_machine.current_state_id; + if (state != SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL) { + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + /* Select a phy on which we can send the hard reset request. */ + for (phy_index = 0; phy_index < SCI_MAX_PHYS && !selected_phy; phy_index++) { + selected_phy = sci_port->phy_table[phy_index]; + if (selected_phy && + !scic_sds_port_active_phy(sci_port, selected_phy)) { + /* + * We found a phy but it is not ready select + * different phy + */ + selected_phy = NULL; + } + } + + /* If we have a phy then go ahead and start the reset procedure */ + if (!selected_phy) + return status; + status = scic_sds_phy_reset(selected_phy); + + if (status != SCI_SUCCESS) + return status; + + isci_timer_start(sci_port->timer_handle, timeout); + sci_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; + + port_state_machine_change(sci_port, + SCI_BASE_PORT_STATE_RESETTING); + return SCI_SUCCESS; +} + +/** + * scic_sds_port_add_phy() - + * @sci_port: This parameter specifies the port in which the phy will be added. + * @sci_phy: This parameter is the phy which is to be added to the port. + * + * This method will add a PHY to the selected port. This method returns an + * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other + * status is a failure to add the phy to the port. + */ +enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + enum sci_status status; + enum scic_sds_port_states state; + + state = sci_port->state_machine.current_state_id; + switch (state) { + case SCI_BASE_PORT_STATE_STOPPED: { + struct sci_sas_address port_sas_address; + + /* Read the port assigned SAS Address if there is one */ + scic_sds_port_get_sas_address(sci_port, &port_sas_address); + + if (port_sas_address.high != 0 && port_sas_address.low != 0) { + struct sci_sas_address phy_sas_address; + + /* Make sure that the PHY SAS Address matches the SAS Address + * for this port + */ + scic_sds_phy_get_sas_address(sci_phy, &phy_sas_address); + + if (port_sas_address.high != phy_sas_address.high || + port_sas_address.low != phy_sas_address.low) + return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; + } + return scic_sds_port_set_phy(sci_port, sci_phy); + } + case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: + case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + status = scic_sds_port_set_phy(sci_port, sci_phy); + + if (status != SCI_SUCCESS) + return status; + + scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); + sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + port_state_machine_change(sci_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + + return status; + case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + status = scic_sds_port_set_phy(sci_port, sci_phy); + + if (status != SCI_SUCCESS) + return status; + scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); + + /* Re-enter the configuring state since this may be the last phy in + * the port. + */ + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + return SCI_SUCCESS; + default: + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } +} + +/** + * scic_sds_port_remove_phy() - + * @sci_port: This parameter specifies the port in which the phy will be added. + * @sci_phy: This parameter is the phy which is to be added to the port. + * + * This method will remove the PHY from the selected PORT. This method returns + * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any + * other status is a failure to add the phy to the port. + */ +enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + enum sci_status status; + enum scic_sds_port_states state; + + state = sci_port->state_machine.current_state_id; + + switch (state) { + case SCI_BASE_PORT_STATE_STOPPED: + return scic_sds_port_clear_phy(sci_port, sci_phy); + case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + status = scic_sds_port_clear_phy(sci_port, sci_phy); + if (status != SCI_SUCCESS) + return status; + + scic_sds_port_deactivate_phy(sci_port, sci_phy, true); + sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + return SCI_SUCCESS; + case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + status = scic_sds_port_clear_phy(sci_port, sci_phy); + + if (status != SCI_SUCCESS) + return status; + scic_sds_port_deactivate_phy(sci_port, sci_phy, true); + + /* Re-enter the configuring state since this may be the last phy in + * the port + */ + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + + return SCI_SUCCESS; + default: + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } +} + static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = { [SCI_BASE_PORT_STATE_STOPPED] = { - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_stopped_state_add_phy_handler, - .remove_phy_handler = scic_sds_port_stopped_state_remove_phy_handler, .frame_handler = scic_sds_port_default_frame_handler, .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, @@ -2057,9 +1933,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_default_complete_io_handler }, [SCI_BASE_PORT_STATE_STOPPING] = { - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_default_add_phy_handler, - .remove_phy_handler = scic_sds_port_default_remove_phy_handler, .frame_handler = scic_sds_port_default_frame_handler, .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, @@ -2068,9 +1941,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_stopping_state_complete_io_handler }, [SCI_BASE_PORT_STATE_READY] = { - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_default_add_phy_handler, - .remove_phy_handler = scic_sds_port_default_remove_phy_handler, .frame_handler = scic_sds_port_default_frame_handler, .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, @@ -2079,9 +1949,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, - .remove_phy_handler = scic_sds_port_default_remove_phy_handler, .frame_handler = scic_sds_port_default_frame_handler, .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_ready_waiting_substate_link_up_handler, @@ -2090,9 +1957,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, - .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, - .remove_phy_handler = scic_sds_port_ready_substate_remove_phy_handler, .frame_handler = scic_sds_port_default_frame_handler, .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_ready_operational_substate_link_up_handler, @@ -2101,9 +1965,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_ready_configuring_substate_add_phy_handler, - .remove_phy_handler = scic_sds_port_ready_configuring_substate_remove_phy_handler, .frame_handler = scic_sds_port_default_frame_handler, .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, @@ -2112,9 +1973,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler }, [SCI_BASE_PORT_STATE_RESETTING] = { - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_default_add_phy_handler, - .remove_phy_handler = scic_sds_port_default_remove_phy_handler, .frame_handler = scic_sds_port_default_frame_handler, .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_reset_state_link_up_handler, @@ -2123,9 +1981,6 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCI_BASE_PORT_STATE_FAILED] = { - .reset_handler = scic_sds_port_default_reset_handler, - .add_phy_handler = scic_sds_port_default_add_phy_handler, - .remove_phy_handler = scic_sds_port_default_remove_phy_handler, .frame_handler = scic_sds_port_default_frame_handler, .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 70163710988c..326279a194ab 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -312,24 +312,6 @@ typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_po struct scic_sds_request *); struct scic_sds_port_state_handler { - /** - * The reset_handler specifies the method invoked when a user - * attempts to hard reset a port. - */ - scic_sds_port_reset_handler_t reset_handler; - - /** - * The add_phy_handler specifies the method invoked when a user - * attempts to add another phy into the port. - */ - scic_sds_port_phy_handler_t add_phy_handler; - - /** - * The remove_phy_handler specifies the method invoked when a user - * attempts to remove a phy from the port. - */ - scic_sds_port_phy_handler_t remove_phy_handler; - scic_sds_port_frame_handler_t frame_handler; scic_sds_port_event_handler_t event_handler; @@ -338,7 +320,6 @@ struct scic_sds_port_state_handler { scic_sds_port_io_request_handler_t start_io_handler; scic_sds_port_io_request_handler_t complete_io_handler; - }; /** -- cgit v1.2.3 From 13721e186fd31cd8475e635a89383853871fdbf1 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Thu, 12 May 2011 19:10:08 +0000 Subject: isci: remove port frame and event handlers Unused infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Piotr Sawicki Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 40 ---------------------------------------- drivers/scsi/isci/port.h | 3 --- 2 files changed, 43 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 5501e14c8d93..d58001cb0bcf 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1262,30 +1262,6 @@ static enum sci_status default_port_handler(struct scic_sds_port *sci_port, return SCI_FAILURE_INVALID_STATE; } -/* - * This is the default method for a port unsolicited frame request. It will - * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even - * possible to receive an unsolicited frame directed to a port object? It - * seems possible if we implementing virtual functions but until then? - */ -static enum sci_status -scic_sds_port_default_frame_handler(struct scic_sds_port *sci_port, - u32 frame_index) -{ - struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - - default_port_handler(sci_port, __func__); - scic_sds_controller_release_frame(scic, frame_index); - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_port_default_event_handler(struct scic_sds_port *sci_port, - u32 event_code) -{ - return default_port_handler(sci_port, __func__); -} - static void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy) { @@ -1925,64 +1901,48 @@ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = { [SCI_BASE_PORT_STATE_STOPPED] = { - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_default_complete_io_handler }, [SCI_BASE_PORT_STATE_STOPPING] = { - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_stopping_state_complete_io_handler }, [SCI_BASE_PORT_STATE_READY] = { - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_ready_waiting_substate_link_up_handler, .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_ready_waiting_substate_start_io_handler, .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_ready_operational_substate_link_up_handler, .link_down_handler = scic_sds_port_ready_operational_substate_link_down_handler, .start_io_handler = scic_sds_port_ready_operational_substate_start_io_handler, .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler }, [SCI_BASE_PORT_STATE_RESETTING] = { - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_reset_state_link_up_handler, .link_down_handler = scic_sds_port_reset_state_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCI_BASE_PORT_STATE_FAILED] = { - .frame_handler = scic_sds_port_default_frame_handler, - .event_handler = scic_sds_port_default_event_handler, .link_up_handler = scic_sds_port_default_link_up_handler, .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 326279a194ab..20f99263fa0a 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -312,9 +312,6 @@ typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_po struct scic_sds_request *); struct scic_sds_port_state_handler { - scic_sds_port_frame_handler_t frame_handler; - scic_sds_port_event_handler_t event_handler; - scic_sds_port_link_handler_t link_up_handler; scic_sds_port_link_handler_t link_down_handler; -- cgit v1.2.3 From 051266caaeb15719553c5316e3d43b533d3cd5a0 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Thu, 12 May 2011 19:10:14 +0000 Subject: isci: unify port link_up and link_down handlers Unify the handlers and kill the state handler implementations. Reported-by: Christoph Hellwig Signed-off-by: Piotr Sawicki Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 241 ++++++++++++++--------------------------------- drivers/scsi/isci/port.h | 14 +-- 2 files changed, 76 insertions(+), 179 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index d58001cb0bcf..61ba37da437d 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -928,36 +928,6 @@ bool scic_sds_port_link_detected( return true; } -/** - * This method is the entry point for the phy to inform the port that it is now - * in a ready state - * @sci_port: - * - * - */ -void scic_sds_port_link_up( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - sci_phy->is_in_link_training = false; - - sci_port->state_handlers->link_up_handler(sci_port, sci_phy); -} - -/** - * This method is the entry point for the phy to inform the port that it is no - * longer in a ready state - * @sci_port: - * - * - */ -void scic_sds_port_link_down( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - sci_port->state_handlers->link_down_handler(sci_port, sci_phy); -} - /** * This method is called to start an IO request on this port. * @sci_port: @@ -1135,29 +1105,6 @@ static enum sci_status scic_sds_port_ready_substate_complete_io_handler( return SCI_SUCCESS; } -/** - * - * @sci_port: This is the struct scic_sds_port object that which has a phy that has - * gone link up. - * @sci_phy: This is the struct scic_sds_phy object that has gone link up. - * - * This method is the ready waiting substate link up handler for the - * struct scic_sds_port object. This methos will report the link up condition for - * this port and will transition to the ready operational substate. none - */ -static void scic_sds_port_ready_waiting_substate_link_up_handler( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - /* - * Since this is the first phy going link up for the port we can just enable - * it and continue. */ - scic_sds_port_activate_phy(sci_port, sci_phy, true); - - port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); -} - /* * This method is the ready waiting substate start io handler for the * struct scic_sds_port object. The port object can not accept new requests so the @@ -1171,49 +1118,6 @@ static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( return SCI_FAILURE_INVALID_STATE; } -/** - * scic_sds_port_ready_operational_substate_link_up_handler() - - * @sci_port: This is the struct scic_sds_port object that which has a phy that has - * gone link up. - * @sci_phy: This is the struct scic_sds_phy object that has gone link up. - * - * This method is the ready operational substate link up handler for the - * struct scic_sds_port object. This function notifies the SCI User that the phy has - * gone link up. none - */ -static void scic_sds_port_ready_operational_substate_link_up_handler( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); -} - -/** - * scic_sds_port_ready_operational_substate_link_down_handler() - - * @sci_port: This is the struct scic_sds_port object that which has a phy that has - * gone link down. - * @sci_phy: This is the struct scic_sds_phy object that has gone link down. - * - * This method is the ready operational substate link down handler for the - * struct scic_sds_port object. This function notifies the SCI User that the phy has - * gone link down and if this is the last phy in the port the port will change - * state to the ready waiting substate. none - */ -static void scic_sds_port_ready_operational_substate_link_down_handler( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - scic_sds_port_deactivate_phy(sci_port, sci_phy, true); - - /* - * If there are no active phys left in the port, then transition - * the port to the WAITING state until such time as a phy goes - * link up. */ - if (sci_port->active_phy_mask == 0) - port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); -} - /* * This method is the ready operational substate start io handler for the * struct scic_sds_port object. This function incremetns the outstanding request @@ -1262,18 +1166,6 @@ static enum sci_status default_port_handler(struct scic_sds_port *sci_port, return SCI_FAILURE_INVALID_STATE; } -static void scic_sds_port_default_link_up_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - default_port_handler(sci_port, __func__); -} - -static void scic_sds_port_default_link_down_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - default_port_handler(sci_port, __func__); -} - static enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, struct scic_sds_request *sci_req) @@ -1592,51 +1484,6 @@ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( return SCI_SUCCESS; } -/* - * **************************************************************************** - * * RESETTING STATE HANDLERS - * **************************************************************************** */ - -/* - * This method will transition a failed port to its ready state. The port - * failed because a hard reset request timed out but at some time later one or - * more phys in the port became ready. enum sci_status SCI_SUCCESS - */ -static void scic_sds_port_reset_state_link_up_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - /* - * / @todo We should make sure that the phy that has gone link up is the same - * / one on which we sent the reset. It is possible that the phy on - * / which we sent the reset is not the one that has gone link up and we - * / want to make sure that phy being reset comes back. Consider the - * / case where a reset is sent but before the hardware processes the - * / reset it get a link up on the port because of a hot plug event. - * / because of the reset request this phy will go link down almost - * / immediately. */ - - /* - * In the resetting state we don't notify the user regarding - * link up and link down notifications. */ - scic_sds_port_general_link_up_handler(port, phy, false); -} - -/* - * This method process link down notifications that occur during a port reset - * operation. Link downs can occur during the reset operation. enum sci_status - * SCI_SUCCESS - */ -static void scic_sds_port_reset_state_link_down_handler( - struct scic_sds_port *port, - struct scic_sds_phy *phy) -{ - /* - * In the resetting state we don't notify the user regarding - * link up and link down notifications. */ - scic_sds_port_deactivate_phy(port, phy, false); -} - enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; @@ -1890,7 +1737,79 @@ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, */ port_state_machine_change(sci_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + return SCI_SUCCESS; + default: + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } +} +enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + enum scic_sds_port_states state; + + state = sci_port->state_machine.current_state_id; + switch (state) { + case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: + /* Since this is the first phy going link up for the port we + * can just enable it and continue + */ + scic_sds_port_activate_phy(sci_port, sci_phy, true); + + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); + return SCI_SUCCESS; + case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); + return SCI_SUCCESS; + case SCI_BASE_PORT_STATE_RESETTING: + /* TODO We should make sure that the phy that has gone + * link up is the same one on which we sent the reset. It is + * possible that the phy on which we sent the reset is not the + * one that has gone link up and we want to make sure that + * phy being reset comes back. Consider the case where a + * reset is sent but before the hardware processes the reset it + * get a link up on the port because of a hot plug event. + * because of the reset request this phy will go link down + * almost immediately. + */ + + /* In the resetting state we don't notify the user regarding + * link up and link down notifications. + */ + scic_sds_port_general_link_up_handler(sci_port, sci_phy, false); + return SCI_SUCCESS; + default: + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } +} + +enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + enum scic_sds_port_states state; + + state = sci_port->state_machine.current_state_id; + switch (state) { + case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + scic_sds_port_deactivate_phy(sci_port, sci_phy, true); + + /* If there are no active phys left in the port, then + * transition the port to the WAITING state until such time + * as a phy goes link up + */ + if (sci_port->active_phy_mask == 0) + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + return SCI_SUCCESS; + case SCI_BASE_PORT_STATE_RESETTING: + /* In the resetting state we don't notify the user regarding + * link up and link down notifications. */ + scic_sds_port_deactivate_phy(sci_port, sci_phy, false); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(sci_port), @@ -1901,50 +1820,34 @@ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = { [SCI_BASE_PORT_STATE_STOPPED] = { - .link_up_handler = scic_sds_port_default_link_up_handler, - .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_default_complete_io_handler }, [SCI_BASE_PORT_STATE_STOPPING] = { - .link_up_handler = scic_sds_port_default_link_up_handler, - .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_stopping_state_complete_io_handler }, [SCI_BASE_PORT_STATE_READY] = { - .link_up_handler = scic_sds_port_default_link_up_handler, - .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .link_up_handler = scic_sds_port_ready_waiting_substate_link_up_handler, - .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_ready_waiting_substate_start_io_handler, .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .link_up_handler = scic_sds_port_ready_operational_substate_link_up_handler, - .link_down_handler = scic_sds_port_ready_operational_substate_link_down_handler, .start_io_handler = scic_sds_port_ready_operational_substate_start_io_handler, .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, }, [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .link_up_handler = scic_sds_port_default_link_up_handler, - .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler }, [SCI_BASE_PORT_STATE_RESETTING] = { - .link_up_handler = scic_sds_port_reset_state_link_up_handler, - .link_down_handler = scic_sds_port_reset_state_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_general_complete_io_handler }, [SCI_BASE_PORT_STATE_FAILED] = { - .link_up_handler = scic_sds_port_default_link_up_handler, - .link_down_handler = scic_sds_port_default_link_down_handler, .start_io_handler = scic_sds_port_default_start_io_handler, .complete_io_handler = scic_sds_port_general_complete_io_handler } diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 20f99263fa0a..bbce0ec583a9 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -312,9 +312,6 @@ typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_po struct scic_sds_request *); struct scic_sds_port_state_handler { - scic_sds_port_link_handler_t link_up_handler; - scic_sds_port_link_handler_t link_down_handler; - scic_sds_port_io_request_handler_t start_io_handler; scic_sds_port_io_request_handler_t complete_io_handler; }; @@ -402,13 +399,10 @@ bool scic_sds_port_link_detected( struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy); -void scic_sds_port_link_up( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); - -void scic_sds_port_link_down( - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); +enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); +enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy); enum sci_status scic_sds_port_start_io( struct scic_sds_port *sci_port, -- cgit v1.2.3 From 6813820c7b892e1a5c2306808a5ccc8a27b7946d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 07:16:06 -0700 Subject: isci: unify port start_io and complete_io handlers Unify the handlers and kill the state handler infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 432 +++++++---------------------------------------- drivers/scsi/isci/port.h | 55 +----- 2 files changed, 59 insertions(+), 428 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 61ba37da437d..f43c1f6c9669 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -61,8 +61,6 @@ #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) #define SCU_DUMMY_INDEX (0xFFFF) -static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[]; - static void isci_port_change_state(struct isci_port *iport, enum isci_status status) { unsigned long flags; @@ -928,40 +926,6 @@ bool scic_sds_port_link_detected( return true; } -/** - * This method is called to start an IO request on this port. - * @sci_port: - * @sci_dev: - * @sci_req: - * - * enum sci_status - */ -enum sci_status scic_sds_port_start_io( - struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return sci_port->state_handlers->start_io_handler( - sci_port, sci_dev, sci_req); -} - -/** - * This method is called to complete an IO request to the port. - * @sci_port: - * @sci_dev: - * @sci_req: - * - * enum sci_status - */ -enum sci_status scic_sds_port_complete_io( - struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return sci_port->state_handlers->complete_io_handler( - sci_port, sci_dev, sci_req); -} - /** * This method is provided to timeout requests for port operations. Mostly its * for the port reset operation. @@ -1085,106 +1049,6 @@ static void scic_port_enable_broadcast_change_notification(struct scic_sds_port } } -/* - * **************************************************************************** - * * READY SUBSTATE HANDLERS - * **************************************************************************** */ - -/* - * This method is the general ready substate complete io handler for the - * struct scic_sds_port object. This function decrments the outstanding request count - * for this port object. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_ready_substate_complete_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - scic_sds_port_decrement_request_count(port); - - return SCI_SUCCESS; -} - -/* - * This method is the ready waiting substate start io handler for the - * struct scic_sds_port object. The port object can not accept new requests so the - * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE - */ -static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - return SCI_FAILURE_INVALID_STATE; -} - -/* - * This method is the ready operational substate start io handler for the - * struct scic_sds_port object. This function incremetns the outstanding request - * count for this port object. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - port->started_request_count++; - return SCI_SUCCESS; -} - -/** - * scic_sds_port_ready_configuring_substate_complete_io_handler() - - * @port: This is the port that is being requested to complete the io request. - * @device: This is the device on which the io is completing. - * - * This method will decrement the outstanding request count for this port. If - * the request count goes to 0 then the port can be reprogrammed with its new - * phy data. - */ -static enum sci_status -scic_sds_port_ready_configuring_substate_complete_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - scic_sds_port_decrement_request_count(port); - - if (port->started_request_count == 0) { - port_state_machine_change(port, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); - } - - return SCI_SUCCESS; -} - -static enum sci_status default_port_handler(struct scic_sds_port *sci_port, - const char *func) -{ - dev_warn(sciport_to_dev(sci_port), - "%s: in wrong state: %d\n", func, - sci_base_state_machine_get_state(&sci_port->state_machine)); - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_port_default_start_io_handler(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return default_port_handler(sci_port, __func__); -} - -static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds_port *sci_port, - struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) -{ - return default_port_handler(sci_port, __func__); -} - -/* - * ****************************************************************************** - * * PORT STATE PRIVATE METHODS - * ****************************************************************************** */ - /** * * @sci_port: This is the struct scic_sds_port object to suspend. @@ -1269,28 +1133,10 @@ scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) writel(pts_control_value, &port->port_task_scheduler_registers->control); } -/* - * ****************************************************************************** - * * PORT READY SUBSTATE METHODS - * ****************************************************************************** */ - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the - * port for any ready phys. If there is at least one phy in a ready state then - * the port transitions to the ready operational substate. none - */ static void scic_sds_port_ready_substate_waiting_enter(void *object) { struct scic_sds_port *sci_port = object; - scic_sds_port_set_base_state_handlers( - sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING - ); - scic_sds_port_suspend_port_task_scheduler(sci_port); sci_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; @@ -1302,15 +1148,6 @@ static void scic_sds_port_ready_substate_waiting_enter(void *object) } } -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This function will perform the actions required by the struct scic_sds_port - * on entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets - * the state handlers for the port object, notifies the SCI User that the port - * is ready, and resumes port operations. none - */ static void scic_sds_port_ready_substate_operational_enter(void *object) { u32 index; @@ -1319,10 +1156,6 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); - scic_sds_port_set_base_state_handlers( - sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); - isci_port_ready(ihost, iport); for (index = 0; index < SCI_MAX_PHYS; index++) { @@ -1397,19 +1230,6 @@ static void scic_sds_port_ready_substate_operational_exit(void *object) scic_sds_port_invalidate_dummy_remote_node(sci_port); } -/* - * ****************************************************************************** - * * PORT READY CONFIGURING METHODS - * ****************************************************************************** */ - -/** - * scic_sds_port_ready_substate_configuring_enter() - - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports - * the port not ready and suspends the port task scheduler. none - */ static void scic_sds_port_ready_substate_configuring_enter(void *object) { struct scic_sds_port *sci_port = object; @@ -1417,10 +1237,6 @@ static void scic_sds_port_ready_substate_configuring_enter(void *object) struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); - scic_sds_port_set_base_state_handlers( - sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); - if (sci_port->active_phy_mask == 0) { isci_port_not_ready(ihost, iport); @@ -1440,50 +1256,6 @@ static void scic_sds_port_ready_substate_configuring_exit(void *object) scic_sds_port_invalidate_dummy_remote_node(sci_port); } -/* --------------------------------------------------------------------------- */ - -/** - * - * @port: This is the struct scic_sds_port object on which the io request count will - * be decremented. - * @device: This is the struct scic_sds_remote_device object to which the io request - * is being directed. This parameter is not required to complete this - * operation. - * @io_request: This is the request that is being completed on this port - * object. This parameter is not required to complete this operation. - * - * This is a general complete io request handler for the struct scic_sds_port object. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_general_complete_io_handler( - struct scic_sds_port *port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - scic_sds_port_decrement_request_count(port); - - return SCI_SUCCESS; -} - -/* - * This method takes the struct scic_sds_port that is in a stopping state and handles - * the complete io request. Should the request count reach 0 then the port - * object will transition to the stopped state. enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_port_stopping_state_complete_io_handler( - struct scic_sds_port *sci_port, - struct scic_sds_remote_device *device, - struct scic_sds_request *io_request) -{ - scic_sds_port_decrement_request_count(sci_port); - - if (sci_port->started_request_count == 0) - port_state_machine_change(sci_port, - SCI_BASE_PORT_STATE_STOPPED); - - return SCI_SUCCESS; -} - enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; @@ -1818,45 +1590,62 @@ enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, } } -static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = { - [SCI_BASE_PORT_STATE_STOPPED] = { - .start_io_handler = scic_sds_port_default_start_io_handler, - .complete_io_handler = scic_sds_port_default_complete_io_handler - }, - [SCI_BASE_PORT_STATE_STOPPING] = { - .start_io_handler = scic_sds_port_default_start_io_handler, - .complete_io_handler = scic_sds_port_stopping_state_complete_io_handler - }, - [SCI_BASE_PORT_STATE_READY] = { - .start_io_handler = scic_sds_port_default_start_io_handler, - .complete_io_handler = scic_sds_port_general_complete_io_handler - }, - [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { - .start_io_handler = scic_sds_port_ready_waiting_substate_start_io_handler, - .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, - }, - [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { - .start_io_handler = scic_sds_port_ready_operational_substate_start_io_handler, - .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, - }, - [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { - .start_io_handler = scic_sds_port_default_start_io_handler, - .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler - }, - [SCI_BASE_PORT_STATE_RESETTING] = { - .start_io_handler = scic_sds_port_default_start_io_handler, - .complete_io_handler = scic_sds_port_general_complete_io_handler - }, - [SCI_BASE_PORT_STATE_FAILED] = { - .start_io_handler = scic_sds_port_default_start_io_handler, - .complete_io_handler = scic_sds_port_general_complete_io_handler +enum sci_status scic_sds_port_start_io(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + enum scic_sds_port_states state; + + state = sci_port->state_machine.current_state_id; + switch (state) { + case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: + return SCI_FAILURE_INVALID_STATE; + case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + sci_port->started_request_count++; + return SCI_SUCCESS; + default: + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; } -}; +} -/* - * ****************************************************************************** - * * PORT STATE PRIVATE METHODS - * ****************************************************************************** */ +enum sci_status scic_sds_port_complete_io(struct scic_sds_port *sci_port, + struct scic_sds_remote_device *sci_dev, + struct scic_sds_request *sci_req) +{ + enum scic_sds_port_states state; + + state = sci_port->state_machine.current_state_id; + switch (state) { + case SCI_BASE_PORT_STATE_STOPPED: + dev_warn(sciport_to_dev(sci_port), + "%s: in wrong state: %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + case SCI_BASE_PORT_STATE_STOPPING: + scic_sds_port_decrement_request_count(sci_port); + + if (sci_port->started_request_count == 0) + port_state_machine_change(sci_port, + SCI_BASE_PORT_STATE_STOPPED); + break; + case SCI_BASE_PORT_STATE_READY: + case SCI_BASE_PORT_STATE_RESETTING: + case SCI_BASE_PORT_STATE_FAILED: + case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: + case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + scic_sds_port_decrement_request_count(sci_port); + break; + case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + scic_sds_port_decrement_request_count(sci_port); + if (sci_port->started_request_count == 0) { + port_state_machine_change(sci_port, + SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); + } + break; + } + return SCI_SUCCESS; +} /** * @@ -1921,32 +1710,11 @@ static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) scic_sds_controller_post_request(scic, command); } -/* - * ****************************************************************************** - * * PORT STATE METHODS - * ****************************************************************************** */ - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped - * state handlers for the struct scic_sds_port object and disables the port task - * scheduler in the hardware. none - */ static void scic_sds_port_stopped_state_enter(void *object) { struct scic_sds_port *sci_port = object; - scic_sds_port_set_base_state_handlers( - sci_port, SCI_BASE_PORT_STATE_STOPPED - ); - - if ( - SCI_BASE_PORT_STATE_STOPPING - == sci_port->state_machine.previous_state_id - ) { + if (sci_port->state_machine.previous_state_id == SCI_BASE_PORT_STATE_STOPPING) { /* * If we enter this state becasuse of a request to stop * the port then we want to disable the hardwares port @@ -1955,14 +1723,6 @@ static void scic_sds_port_stopped_state_enter(void *object) } } -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware - * port task scheduler. none - */ static void scic_sds_port_stopped_state_exit(void *object) { struct scic_sds_port *sci_port = object; @@ -1971,15 +1731,6 @@ static void scic_sds_port_stopped_state_exit(void *object) scic_sds_port_enable_port_task_scheduler(sci_port); } -/** - * scic_sds_port_ready_state_enter - - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state - * handlers for the struct scic_sds_port object, reports the port object as - * not ready and starts the ready substate machine. none - */ static void scic_sds_port_ready_state_enter(void *object) { struct scic_sds_port *sci_port = object; @@ -1988,9 +1739,6 @@ static void scic_sds_port_ready_state_enter(void *object) struct isci_port *iport = sci_port_to_iport(sci_port); u32 prev_state; - /* Put the ready state handlers in place though they will not be there long */ - scic_sds_port_set_base_state_handlers(sci_port, SCI_BASE_PORT_STATE_READY); - prev_state = sci_port->state_machine.previous_state_id; if (prev_state == SCI_BASE_PORT_STATE_RESETTING) isci_port_hard_reset_complete(iport, SCI_SUCCESS); @@ -2005,66 +1753,14 @@ static void scic_sds_port_ready_state_enter(void *object) SCIC_SDS_PORT_READY_SUBSTATE_WAITING); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting - * state handlers for the struct scic_sds_port object. none - */ -static void scic_sds_port_resetting_state_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - - scic_sds_port_set_base_state_handlers( - sci_port, SCI_BASE_PORT_STATE_RESETTING - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This function will perform the actions required by the - * struct scic_sds_port on - * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none - */ -static inline void scic_sds_port_resetting_state_exit(void *object) +static void scic_sds_port_resetting_state_exit(void *object) { struct scic_sds_port *sci_port = object; isci_timer_stop(sci_port->timer_handle); } -/** - * - * @object: This is the void object which is cast to a - * struct scic_sds_port object. - * - * This method will perform the actions required by the struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping - * state handlers for the struct scic_sds_port object. none - */ -static void scic_sds_port_stopping_state_enter(void *object) -{ - struct scic_sds_port *sci_port = object; - - scic_sds_port_set_base_state_handlers( - sci_port, SCI_BASE_PORT_STATE_STOPPING - ); -} - -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This function will perform the actions required by the - * struct scic_sds_port on - * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none - */ -static inline void -scic_sds_port_stopping_state_exit(void *object) +static void scic_sds_port_stopping_state_exit(void *object) { struct scic_sds_port *sci_port = object; @@ -2073,23 +1769,11 @@ scic_sds_port_stopping_state_exit(void *object) scic_sds_port_destroy_dummy_resources(sci_port); } -/** - * - * @object: This is the object which is cast to a struct scic_sds_port object. - * - * This function will perform the actions required by the - * struct scic_sds_port on - * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping - * state handlers for the struct scic_sds_port object. none - */ static void scic_sds_port_failed_state_enter(void *object) { struct scic_sds_port *sci_port = object; struct isci_port *iport = sci_port_to_iport(sci_port); - scic_sds_port_set_base_state_handlers(sci_port, - SCI_BASE_PORT_STATE_FAILED); - isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); } @@ -2101,7 +1785,6 @@ static const struct sci_base_state scic_sds_port_state_table[] = { .exit_state = scic_sds_port_stopped_state_exit }, [SCI_BASE_PORT_STATE_STOPPING] = { - .enter_state = scic_sds_port_stopping_state_enter, .exit_state = scic_sds_port_stopping_state_exit }, [SCI_BASE_PORT_STATE_READY] = { @@ -2119,7 +1802,6 @@ static const struct sci_base_state scic_sds_port_state_table[] = { .exit_state = scic_sds_port_ready_substate_configuring_exit }, [SCI_BASE_PORT_STATE_RESETTING] = { - .enter_state = scic_sds_port_resetting_state_enter, .exit_state = scic_sds_port_resetting_state_exit }, [SCI_BASE_PORT_STATE_FAILED] = { diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index bbce0ec583a9..af540e5c03a0 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -144,15 +144,6 @@ struct scic_sds_port { */ void *timer_handle; - /** - * This field points to the current set of state handlers for this port - * object. These state handlers are assigned at each enter state of - * the state machine. - */ - struct scic_sds_port_state_handler *state_handlers; - - /* / Memory mapped hardware register space */ - /** * This field is the pointer to the port task scheduler registers * for the SCU hardware. @@ -286,34 +277,7 @@ enum scic_sds_port_states { */ SCI_BASE_PORT_STATE_FAILED, - SCI_BASE_PORT_MAX_STATES - -}; - -struct scic_sds_remote_device; -struct scic_sds_request; - -typedef enum sci_status (*scic_sds_port_handler_t)(struct scic_sds_port *); - -typedef enum sci_status (*scic_sds_port_phy_handler_t)(struct scic_sds_port *, - struct scic_sds_phy *); - -typedef enum sci_status (*scic_sds_port_reset_handler_t)(struct scic_sds_port *, - u32 timeout); - -typedef enum sci_status (*scic_sds_port_event_handler_t)(struct scic_sds_port *, u32); -typedef enum sci_status (*scic_sds_port_frame_handler_t)(struct scic_sds_port *, u32); - -typedef void (*scic_sds_port_link_handler_t)(struct scic_sds_port *, struct scic_sds_phy *); - -typedef enum sci_status (*scic_sds_port_io_request_handler_t)(struct scic_sds_port *, - struct scic_sds_remote_device *, - struct scic_sds_request *); - -struct scic_sds_port_state_handler { - scic_sds_port_io_request_handler_t start_io_handler; - scic_sds_port_io_request_handler_t complete_io_handler; }; /** @@ -324,23 +288,6 @@ struct scic_sds_port_state_handler { #define scic_sds_port_get_controller(this_port) \ ((this_port)->owning_controller) -/** - * scic_sds_port_set_base_state_handlers() - - * - * This macro will change the state handlers to those of the specified state id - */ -#define scic_sds_port_set_base_state_handlers(this_port, state_id) \ - scic_sds_port_set_state_handlers(\ - (this_port), &scic_sds_port_state_handler_table[(state_id)]) - -/** - * scic_sds_port_set_state_handlers() - - * - * Helper macro to set the port object state handlers - */ -#define scic_sds_port_set_state_handlers(this_port, handlers) \ - ((this_port)->state_handlers = (handlers)) - /** * scic_sds_port_get_index() - * @@ -404,6 +351,8 @@ enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy); +struct scic_sds_request; +struct scic_sds_remote_device; enum sci_status scic_sds_port_start_io( struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, -- cgit v1.2.3 From 338e386d12c2440e39c987d35fda403d319a79a0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 07:46:59 -0700 Subject: isci: unify rnc event handlers Unify rnc event handlers and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_node_context.c | 365 ++++++++++---------------------- drivers/scsi/isci/remote_node_context.h | 16 +- 2 files changed, 111 insertions(+), 270 deletions(-) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index aef258b959f8..9f2407f0f5a6 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -299,21 +299,6 @@ static enum sci_status scic_sds_remote_node_context_default_start_task_handler( return SCI_FAILURE; } -static enum sci_status scic_sds_remote_node_context_default_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to process " - "event 0x%x while in wrong state %d\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - /** * * @sci_rnc: The rnc for which the task request is targeted. @@ -383,41 +368,6 @@ static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler return SCI_FAILURE_INVALID_STATE; } -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_code(event_code)) { - case SCU_EVENT_POST_RNC_COMPLETE: - status = SCI_SUCCESS; - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE - ); - break; - - default: - status = SCI_FAILURE; - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to " - "process unexpected event 0x%x while in posting " - "state\n", - __func__, - sci_rnc, - event_code); - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler( struct scic_sds_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, @@ -430,110 +380,6 @@ static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_ return SCI_SUCCESS; } -static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { - status = SCI_SUCCESS; - - if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE - ); - } else { - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE - ); - } - } else { - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TYPE_RNC_SUSPEND_TX: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - /* - * We really dont care if the hardware is going to suspend - * the device since it's being invalidated anyway */ - dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p was " - "suspeneded by hardware while being " - "invalidated.\n", - __func__, - sci_rnc); - status = SCI_SUCCESS; - break; - - default: - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p " - "requested to process event 0x%x while " - "in state %d.\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state( - &sci_rnc->state_machine)); - status = SCI_FAILURE; - break; - } - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - - -static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) { - status = SCI_SUCCESS; - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE - ); - } else { - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TYPE_RNC_SUSPEND_TX: - case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - /* - * We really dont care if the hardware is going to suspend - * the device since it's being resumed anyway */ - dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p was " - "suspeneded by hardware while being resumed.\n", - __func__, - sci_rnc); - status = SCI_SUCCESS; - break; - - default: - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested " - "to process event 0x%x while in state %d.\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state( - &sci_rnc->state_machine)); - status = SCI_FAILURE; - break; - } - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - /** * * @sci_rnc: The remote node context object being suspended. @@ -582,53 +428,6 @@ static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler return SCI_SUCCESS; } - -static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TL_RNC_SUSPEND_TX: - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE - ); - - sci_rnc->suspension_code = scu_get_event_specifier(event_code); - status = SCI_SUCCESS; - break; - - case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE - ); - - sci_rnc->suspension_code = scu_get_event_specifier(event_code); - status = SCI_SUCCESS; - break; - - default: - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to " - "process event 0x%x while in state %d.\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state( - &sci_rnc->state_machine)); - - status = SCI_FAILURE; - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler( struct scic_sds_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, @@ -738,61 +537,13 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_start return SCI_SUCCESS; } -static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code) -{ - enum sci_status status; - - switch (scu_get_event_type(event_code)) { - case SCU_EVENT_TL_RNC_SUSPEND_TX: - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE - ); - - sci_rnc->suspension_code = scu_get_event_specifier(event_code); - status = SCI_SUCCESS; - break; - - case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE - ); - - sci_rnc->suspension_code = scu_get_event_specifier(event_code); - status = SCI_SUCCESS; - break; - - default: - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to " - "process event 0x%x while in state %d.\n", - __func__, - sci_rnc, - event_code, - sci_base_state_machine_get_state( - &sci_rnc->state_machine)); - - status = SCI_FAILURE; - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - -static struct scic_sds_remote_node_context_handlers -scic_sds_remote_node_context_state_handler_table[] = { +static struct scic_sds_remote_node_context_handlers scic_sds_remote_node_context_state_handler_table[] = { [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { .destruct_handler = scic_sds_remote_node_context_default_destruct_handler, .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, .resume_handler = scic_sds_remote_node_context_initial_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, - .event_handler = scic_sds_remote_node_context_default_event_handler }, [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, @@ -800,7 +551,6 @@ scic_sds_remote_node_context_state_handler_table[] = { .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, - .event_handler = scic_sds_remote_node_context_posting_state_event_handler }, [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { .destruct_handler = scic_sds_remote_node_context_invalidating_state_destruct_handler, @@ -808,7 +558,6 @@ scic_sds_remote_node_context_state_handler_table[] = { .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, - .event_handler = scic_sds_remote_node_context_invalidating_state_event_handler }, [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, @@ -816,7 +565,6 @@ scic_sds_remote_node_context_state_handler_table[] = { .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, - .event_handler = scic_sds_remote_node_context_resuming_state_event_handler }, [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, @@ -824,7 +572,6 @@ scic_sds_remote_node_context_state_handler_table[] = { .resume_handler = scic_sds_remote_node_context_default_resume_handler, .start_io_handler = scic_sds_remote_node_context_ready_state_start_io_handler, .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, - .event_handler = scic_sds_remote_node_context_ready_state_event_handler }, [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, @@ -832,7 +579,6 @@ scic_sds_remote_node_context_state_handler_table[] = { .resume_handler = scic_sds_remote_node_context_tx_suspended_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, - .event_handler = scic_sds_remote_node_context_default_event_handler }, [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, @@ -840,7 +586,6 @@ scic_sds_remote_node_context_state_handler_table[] = { .resume_handler = scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, - .event_handler = scic_sds_remote_node_context_default_event_handler }, [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, @@ -848,7 +593,6 @@ scic_sds_remote_node_context_state_handler_table[] = { .resume_handler = scic_sds_remote_node_context_await_suspension_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_await_suspension_state_start_task_handler, - .event_handler = scic_sds_remote_node_context_await_suspension_state_event_handler } }; @@ -1172,3 +916,110 @@ void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context sci_base_state_machine_start(&rnc->state_machine); } + +enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc, + u32 event_code) +{ + enum scis_sds_remote_node_context_states state; + + state = sci_rnc->state_machine.current_state_id; + switch (state) { + case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE: + switch (scu_get_event_code(event_code)) { + case SCU_EVENT_POST_RNC_COMPLETE: + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE); + break; + default: + goto out; + } + break; + case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE: + if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { + if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) + state = SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE; + else + state = SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE; + sci_base_state_machine_change_state(&sci_rnc->state_machine, + state); + } else { + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + /* We really dont care if the hardware is going to suspend + * the device since it's being invalidated anyway */ + dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p was " + "suspeneded by hardware while being " + "invalidated.\n", __func__, sci_rnc); + break; + default: + goto out; + } + } + break; + case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE: + if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) { + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE); + } else { + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TYPE_RNC_SUSPEND_TX: + case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: + /* We really dont care if the hardware is going to suspend + * the device since it's being resumed anyway */ + dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: SCIC Remote Node Context 0x%p was " + "suspeneded by hardware while being resumed.\n", + __func__, sci_rnc); + break; + default: + goto out; + } + } + break; + case SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE: + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TL_RNC_SUSPEND_TX: + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE); + sci_rnc->suspension_code = scu_get_event_specifier(event_code); + break; + case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE); + sci_rnc->suspension_code = scu_get_event_specifier(event_code); + break; + default: + goto out; + } + break; + case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE: + switch (scu_get_event_type(event_code)) { + case SCU_EVENT_TL_RNC_SUSPEND_TX: + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE); + sci_rnc->suspension_code = scu_get_event_specifier(event_code); + break; + case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE); + sci_rnc->suspension_code = scu_get_event_specifier(event_code); + break; + default: + goto out; + } + break; + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: invalid state %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + return SCI_SUCCESS; + + out: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: code: %#x state: %d\n", __func__, event_code, state); + return SCI_FAILURE; + +} diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index a763468fa74f..fb93f09d4df6 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -102,11 +102,6 @@ typedef enum sci_status (*scic_sds_remote_node_context_io_request)( struct scic_sds_request *sci_req ); -typedef enum sci_status (*scic_sds_remote_node_context_event_handler)( - struct scic_sds_remote_node_context *sci_rnc, - u32 event_code - ); - struct scic_sds_remote_node_context_handlers { /** * This handle is invoked to stop the RNC. The callback is invoked when after @@ -138,12 +133,6 @@ struct scic_sds_remote_node_context_handlers { * operation. */ scic_sds_remote_node_context_io_request start_task_handler; - - /** - * This handler is invoked where there is an RNC event that must be processed. - */ - scic_sds_remote_node_context_event_handler event_handler; - }; /** @@ -271,8 +260,9 @@ bool scic_sds_remote_node_context_is_ready( #define scic_sds_remote_node_context_get_remote_node_index(rcn) \ ((rnc)->remote_node_index) -#define scic_sds_remote_node_context_event_handler(rnc, event_code) \ - ((rnc)->state_handlers->event_handler(rnc, event_code)) + +enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc, + u32 event_code); #define scic_sds_remote_node_context_resume(rnc, callback, parameter) \ ((rnc)->state_handlers->resume_handler(rnc, callback, parameter)) -- cgit v1.2.3 From c845ae96bcb1625a093003248ffaf13b92a81ac2 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 08:26:56 -0700 Subject: isci: unify rnc destruct handlers Unify rnc destruct handlers and delete the state handler. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_node_context.c | 106 +++++++++++--------------------- drivers/scsi/isci/remote_node_context.h | 13 +--- 2 files changed, 39 insertions(+), 80 deletions(-) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 9f2407f0f5a6..769a3fc6ec4b 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -218,26 +218,6 @@ static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( return SCI_FAILURE_INVALID_STATE; } -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_default_destruct_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to stop while " - "in unexpected state %d\n", - __func__, - sci_rnc, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - /* - * We have decided that the destruct request on the remote node context can not fail - * since it is either in the initial/destroyed state or is can be destroyed. */ - return SCI_SUCCESS; -} - static enum sci_status scic_sds_remote_node_context_default_suspend_handler( struct scic_sds_remote_node_context *sci_rnc, u32 suspend_type, @@ -315,36 +295,6 @@ static enum sci_status scic_sds_remote_node_context_success_start_task_handler( return SCI_SUCCESS; } -/** - * - * @sci_rnc: - * @callback: - * @callback_parameter: - * - * This method handles destruct calls from the various state handlers. The - * remote node context can be requested to destroy from any state. If there was - * a user callback it is always replaced with the request to destroy user - * callback. enum sci_status - */ -static enum sci_status scic_sds_remote_node_context_general_destruct_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - scic_sds_remote_node_context_setup_to_destory( - sci_rnc, callback, callback_parameter - ); - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE - ); - - return SCI_SUCCESS; -} - -/* --------------------------------------------------------------------------- */ - static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler( struct scic_sds_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, @@ -368,18 +318,6 @@ static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler return SCI_FAILURE_INVALID_STATE; } -static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - scic_sds_remote_node_context_setup_to_destory( - sci_rnc, callback, callback_parameter - ); - - return SCI_SUCCESS; -} - /** * * @sci_rnc: The remote node context object being suspended. @@ -539,56 +477,48 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_start static struct scic_sds_remote_node_context_handlers scic_sds_remote_node_context_state_handler_table[] = { [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { - .destruct_handler = scic_sds_remote_node_context_default_destruct_handler, .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, .resume_handler = scic_sds_remote_node_context_initial_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { - .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { - .destruct_handler = scic_sds_remote_node_context_invalidating_state_destruct_handler, .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { - .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { - .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, .suspend_handler = scic_sds_remote_node_context_ready_state_suspend_handler, .resume_handler = scic_sds_remote_node_context_default_resume_handler, .start_io_handler = scic_sds_remote_node_context_ready_state_start_io_handler, .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { - .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, .resume_handler = scic_sds_remote_node_context_tx_suspended_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { - .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, .resume_handler = scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { - .destruct_handler = scic_sds_remote_node_context_general_destruct_handler, .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, .resume_handler = scic_sds_remote_node_context_await_suspension_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, @@ -1023,3 +953,39 @@ enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remot return SCI_FAILURE; } + +enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback cb_fn, + void *cb_p) +{ + enum scis_sds_remote_node_context_states state; + + state = sci_rnc->state_machine.current_state_id; + switch (state) { + case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE: + scic_sds_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); + return SCI_SUCCESS; + case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE: + scic_sds_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE); + return SCI_SUCCESS; + case SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: invalid state %d\n", __func__, state); + /* We have decided that the destruct request on the remote node context + * can not fail since it is either in the initial/destroyed state or is + * can be destroyed. + */ + return SCI_SUCCESS; + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: invalid state %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } +} diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index fb93f09d4df6..1cd323438292 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -103,12 +103,6 @@ typedef enum sci_status (*scic_sds_remote_node_context_io_request)( ); struct scic_sds_remote_node_context_handlers { - /** - * This handle is invoked to stop the RNC. The callback is invoked when after - * the hardware notification that the RNC has been invalidated. - */ - scic_sds_remote_node_context_operation destruct_handler; - /** * This handler is invoked when there is a request to suspend the RNC. The * callback is invoked after the hardware notification that the remote node is @@ -260,19 +254,18 @@ bool scic_sds_remote_node_context_is_ready( #define scic_sds_remote_node_context_get_remote_node_index(rcn) \ ((rnc)->remote_node_index) - enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc, u32 event_code); +enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback callback, + void *callback_parameter); #define scic_sds_remote_node_context_resume(rnc, callback, parameter) \ ((rnc)->state_handlers->resume_handler(rnc, callback, parameter)) #define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \ ((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter)) -#define scic_sds_remote_node_context_destruct(rnc, callback, parameter) \ - ((rnc)->state_handlers->destruct_handler(rnc, callback, parameter)) - #define scic_sds_remote_node_context_start_io(rnc, request) \ ((rnc)->state_handlers->start_io_handler(rnc, request)) -- cgit v1.2.3 From ed3efb7784cb0772558e9cc9440bd6c9a3139be4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 08:50:23 -0700 Subject: isci: unify rnc suspend/resume handlers Unify rnc suspend/resume handlers and delete the state handlers. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_node_context.c | 306 ++++++++++---------------------- drivers/scsi/isci/remote_node_context.h | 32 +--- 2 files changed, 104 insertions(+), 234 deletions(-) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 769a3fc6ec4b..095d61288c3b 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -195,60 +195,6 @@ static void scic_sds_remote_node_context_setup_to_destory( sci_rnc->user_cookie = callback_parameter; } -/** - * - * @sci_rnc: - * @callback: - * - * This method will continue to resume a remote node context. This is used in - * the states where a resume is requested while a resume is in progress. - */ -static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { - sci_rnc->user_callback = callback; - sci_rnc->user_cookie = callback_parameter; - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_remote_node_context_default_suspend_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 suspend_type, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to suspend " - "while in wrong state %d\n", - __func__, - sci_rnc, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - -static enum sci_status scic_sds_remote_node_context_default_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to resume " - "while in wrong state %d\n", - __func__, - sci_rnc, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE_INVALID_STATE; -} - static enum sci_status scic_sds_remote_node_context_default_start_io_handler( struct scic_sds_remote_node_context *sci_rnc, struct scic_sds_request *sci_req) @@ -295,61 +241,6 @@ static enum sci_status scic_sds_remote_node_context_success_start_task_handler( return SCI_SUCCESS; } -static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - if (sci_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - scic_sds_remote_node_context_setup_to_resume( - sci_rnc, callback, callback_parameter - ); - - scic_sds_remote_node_context_construct_buffer(sci_rnc); - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE - ); - - return SCI_SUCCESS; - } - - return SCI_FAILURE_INVALID_STATE; -} - -/** - * - * @sci_rnc: The remote node context object being suspended. - * @callback: The callback when the suspension is complete. - * @callback_parameter: The parameter that is to be passed into the callback. - * - * This method will handle the suspend requests from the ready state. - * SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( - struct scic_sds_remote_node_context *sci_rnc, - u32 suspend_type, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - sci_rnc->user_callback = callback; - sci_rnc->user_cookie = callback_parameter; - sci_rnc->suspension_code = suspend_type; - - if (suspend_type == SCI_SOFTWARE_SUSPENSION) { - scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), - SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); - } - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE - ); - - return SCI_SUCCESS; -} - /** * * @sci_rnc: The rnc for which the io request is targeted. @@ -366,39 +257,6 @@ static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler return SCI_SUCCESS; } -static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); - struct domain_device *dev = sci_dev_to_domain(sci_dev); - enum sci_status status = SCI_SUCCESS; - - scic_sds_remote_node_context_setup_to_resume(sci_rnc, callback, - callback_parameter); - - /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ - if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev)) - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); - else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { - if (sci_dev->is_direct_attached) { - /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); - } else { - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE); - } - } else - status = SCI_FAILURE; - - return status; -} - /** * * @sci_rnc: The remote node context which is to receive the task request. @@ -419,44 +277,6 @@ static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler return SCI_SUCCESS; } -/* --------------------------------------------------------------------------- */ - -static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - scic_sds_remote_node_context_setup_to_resume( - sci_rnc, callback, callback_parameter - ); - - sci_base_state_machine_change_state( - &sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE - ); - - return SCI_FAILURE_INVALID_STATE; -} - -/* --------------------------------------------------------------------------- */ - -/** - * - * - * - */ -static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter) -{ - scic_sds_remote_node_context_setup_to_resume( - sci_rnc, callback, callback_parameter - ); - - return SCI_SUCCESS; -} - /** * * @sci_rnc: The remote node context which is to receive the task request. @@ -477,50 +297,34 @@ static enum sci_status scic_sds_remote_node_context_await_suspension_state_start static struct scic_sds_remote_node_context_handlers scic_sds_remote_node_context_state_handler_table[] = { [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { - .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, - .resume_handler = scic_sds_remote_node_context_initial_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { - .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, - .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { - .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, - .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { - .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, - .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { - .suspend_handler = scic_sds_remote_node_context_ready_state_suspend_handler, - .resume_handler = scic_sds_remote_node_context_default_resume_handler, .start_io_handler = scic_sds_remote_node_context_ready_state_start_io_handler, .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { - .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, - .resume_handler = scic_sds_remote_node_context_tx_suspended_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { - .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, - .resume_handler = scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, }, [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { - .suspend_handler = scic_sds_remote_node_context_default_suspend_handler, - .resume_handler = scic_sds_remote_node_context_await_suspension_state_resume_handler, .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, .start_task_handler = scic_sds_remote_node_context_await_suspension_state_start_task_handler, } @@ -548,21 +352,11 @@ static void scic_sds_remote_node_context_notify_user( } } -/** - * - * - * This method will continue the remote node context state machine by - * requesting to resume the remote node context state machine from its current - * state. - */ -static void scic_sds_remote_node_context_continue_state_transitions( - struct scic_sds_remote_node_context *rnc) +static void scic_sds_remote_node_context_continue_state_transitions(struct scic_sds_remote_node_context *rnc) { - if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { - rnc->state_handlers->resume_handler( - rnc, rnc->user_callback, rnc->user_cookie - ); - } + if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) + scic_sds_remote_node_context_resume(rnc, rnc->user_callback, + rnc->user_cookie); } /** @@ -989,3 +783,95 @@ enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_nod return SCI_FAILURE_INVALID_STATE; } } + +enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node_context *sci_rnc, + u32 suspend_type, + scics_sds_remote_node_context_callback cb_fn, + void *cb_p) +{ + enum scis_sds_remote_node_context_states state; + + state = sci_rnc->state_machine.current_state_id; + if (state != SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: invalid state %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } + + sci_rnc->user_callback = cb_fn; + sci_rnc->user_cookie = cb_p; + sci_rnc->suspension_code = suspend_type; + + if (suspend_type == SCI_SOFTWARE_SUSPENSION) { + scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), + SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); + } + + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE); + return SCI_SUCCESS; +} + +enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback cb_fn, + void *cb_p) +{ + enum scis_sds_remote_node_context_states state; + + state = sci_rnc->state_machine.current_state_id; + switch (state) { + case SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE: + if (sci_rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) + return SCI_FAILURE_INVALID_STATE; + + scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); + scic_sds_remote_node_context_construct_buffer(sci_rnc); + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE); + return SCI_SUCCESS; + case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE: + if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) + return SCI_FAILURE_INVALID_STATE; + + sci_rnc->user_callback = cb_fn; + sci_rnc->user_cookie = cb_p; + return SCI_SUCCESS; + case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE: { + struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); + struct domain_device *dev = sci_dev_to_domain(sci_dev); + + scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); + + /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ + if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev)) + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); + else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { + if (sci_dev->is_direct_attached) { + /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); + } else { + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE); + } + } else + return SCI_FAILURE; + return SCI_SUCCESS; + } + case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE: + scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); + sci_base_state_machine_change_state(&sci_rnc->state_machine, + SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); + return SCI_FAILURE_INVALID_STATE; + case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE: + scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); + return SCI_SUCCESS; + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: invalid state %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } +} diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index 1cd323438292..68983748eba9 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -90,32 +90,12 @@ typedef enum sci_status (*scic_sds_remote_node_context_operation)( void *callback_parameter ); -typedef enum sci_status (*scic_sds_remote_node_context_suspend_operation)( - struct scic_sds_remote_node_context *sci_rnc, - u32 suspension_type, - scics_sds_remote_node_context_callback callback, - void *callback_parameter - ); - typedef enum sci_status (*scic_sds_remote_node_context_io_request)( struct scic_sds_remote_node_context *sci_rnc, struct scic_sds_request *sci_req ); struct scic_sds_remote_node_context_handlers { - /** - * This handler is invoked when there is a request to suspend the RNC. The - * callback is invoked after the hardware notification that the remote node is - * suspended. - */ - scic_sds_remote_node_context_suspend_operation suspend_handler; - - /** - * This handler is invoked when there is a request to resume the RNC. The - * callback is invoked when after the RNC has reached the ready state. - */ - scic_sds_remote_node_context_operation resume_handler; - /** * This handler is invoked when there is a request to start an io request * operation. @@ -260,11 +240,15 @@ enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remot enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, void *callback_parameter); -#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \ - ((rnc)->state_handlers->resume_handler(rnc, callback, parameter)) -#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \ - ((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter)) +enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node_context *sci_rnc, + u32 suspend_type, + scics_sds_remote_node_context_callback cb_fn, + void *cb_p); + +enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_context *sci_rnc, + scics_sds_remote_node_context_callback cb_fn, + void *cb_p); #define scic_sds_remote_node_context_start_io(rnc, request) \ ((rnc)->state_handlers->start_io_handler(rnc, request)) -- cgit v1.2.3 From f34d9e5d3f34f395a497a8747316b04ef3e865b1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 09:27:52 -0700 Subject: isci: unify rnc start{io|task} handlers Unify rnc start{io|task} handlers and delete the state handler infrastructure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_node_context.c | 306 +++++--------------------------- drivers/scsi/isci/remote_node_context.h | 40 +---- drivers/scsi/isci/state_machine.h | 8 - 3 files changed, 47 insertions(+), 307 deletions(-) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 095d61288c3b..82507bd228d4 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -176,15 +176,6 @@ static void scic_sds_remote_node_context_setup_to_resume( } } -/** - * - * @sci_rnc: - * @callback: - * @callback_parameter: - * - * This method will setup the remote node context object so it will transistion - * to its final state. none - */ static void scic_sds_remote_node_context_setup_to_destory( struct scic_sds_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, @@ -195,146 +186,6 @@ static void scic_sds_remote_node_context_setup_to_destory( sci_rnc->user_cookie = callback_parameter; } -static enum sci_status scic_sds_remote_node_context_default_start_io_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to start io " - "0x%p while in wrong state %d\n", - __func__, - sci_rnc, - sci_req, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; -} - -static enum sci_status scic_sds_remote_node_context_default_start_task_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), - "%s: SCIC Remote Node Context 0x%p requested to start " - "task 0x%p while in wrong state %d\n", - __func__, - sci_rnc, - sci_req, - sci_base_state_machine_get_state(&sci_rnc->state_machine)); - - return SCI_FAILURE; -} - -/** - * - * @sci_rnc: The rnc for which the task request is targeted. - * @sci_req: The request which is going to be started. - * - * This method determines if the task request can be started by the SCU - * hardware. When the RNC is in the ready state any task can be started. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_success_start_task_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - return SCI_SUCCESS; -} - -/** - * - * @sci_rnc: The rnc for which the io request is targeted. - * @sci_req: The request which is going to be started. - * - * This method determines if the io request can be started by the SCU hardware. - * When the RNC is in the ready state any io request can be started. enum sci_status - * SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - return SCI_SUCCESS; -} - -/** - * - * @sci_rnc: The remote node context which is to receive the task request. - * @sci_req: The task request to be transmitted to to the remote target - * device. - * - * This method will report a success or failure attempt to start a new task - * request to the hardware. Since all task requests are sent on the high - * priority queue they can be sent when the RCN is in a TX suspend state. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - scic_sds_remote_node_context_resume(sci_rnc, NULL, NULL); - - return SCI_SUCCESS; -} - -/** - * - * @sci_rnc: The remote node context which is to receive the task request. - * @sci_req: The task request to be transmitted to to the remote target - * device. - * - * This method will report a success or failure attempt to start a new task - * request to the hardware. Since all task requests are sent on the high - * priority queue they can be sent when the RCN is in a TX suspend state. - * enum sci_status SCI_SUCCESS - */ -static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) -{ - return SCI_SUCCESS; -} - -static struct scic_sds_remote_node_context_handlers scic_sds_remote_node_context_state_handler_table[] = { - [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { - .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, - .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { - .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, - .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { - .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, - .start_task_handler = scic_sds_remote_node_context_default_start_task_handler, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { - .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, - .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { - .start_io_handler = scic_sds_remote_node_context_ready_state_start_io_handler, - .start_task_handler = scic_sds_remote_node_context_success_start_task_handler, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { - .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, - .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { - .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, - .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler, - }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { - .start_io_handler = scic_sds_remote_node_context_default_start_io_handler, - .start_task_handler = scic_sds_remote_node_context_await_suspension_state_start_task_handler, - } -}; - -/* - * ***************************************************************************** - * * REMOTE NODE CONTEXT PRIVATE METHODS - * ***************************************************************************** */ - /** * * @@ -415,80 +266,34 @@ static void scic_sds_remote_node_context_invalidate_context_buffer( SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE); } -/* - * ***************************************************************************** - * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS - * ***************************************************************************** */ - -/** - * - * - * - */ static void scic_sds_remote_node_context_initial_state_enter(void *object) { struct scic_sds_remote_node_context *rnc = object; + struct sci_base_state_machine *sm = &rnc->state_machine; - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE - ); - - /* - * Check to see if we have gotten back to the initial state because someone - * requested to destroy the remote node context object. */ - if ( - rnc->state_machine.previous_state_id - == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE - ) { + /* Check to see if we have gotten back to the initial state because + * someone requested to destroy the remote node context object. + */ + if (sm->previous_state_id == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE) { rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - scic_sds_remote_node_context_notify_user(rnc); } } -/** - * - * - * - */ static void scic_sds_remote_node_context_posting_state_enter(void *object) { struct scic_sds_remote_node_context *sci_rnc = object; - SET_STATE_HANDLER( - sci_rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE - ); - scic_sds_remote_node_context_validate_context_buffer(sci_rnc); } -/** - * - * - * - */ static void scic_sds_remote_node_context_invalidating_state_enter(void *object) { struct scic_sds_remote_node_context *rnc = object; - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE - ); - scic_sds_remote_node_context_invalidate_context_buffer(rnc); } -/** - * - * - * - */ static void scic_sds_remote_node_context_resuming_state_enter(void *object) { struct scic_sds_remote_node_context *rnc = object; @@ -498,12 +303,6 @@ static void scic_sds_remote_node_context_resuming_state_enter(void *object) sci_dev = rnc_to_dev(rnc); dev = sci_dev_to_domain(sci_dev); - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE - ); - /* * For direct attached SATA devices we need to clear the TLCR * NCQ to TCi tag mapping on the phy and in cases where we @@ -518,84 +317,31 @@ static void scic_sds_remote_node_context_resuming_state_enter(void *object) scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); } -/** - * - * - * - */ static void scic_sds_remote_node_context_ready_state_enter(void *object) { struct scic_sds_remote_node_context *rnc = object; - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE - ); - rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - if (rnc->user_callback != NULL) { + if (rnc->user_callback) scic_sds_remote_node_context_notify_user(rnc); - } } -/** - * - * - * - */ static void scic_sds_remote_node_context_tx_suspended_state_enter(void *object) { struct scic_sds_remote_node_context *rnc = object; - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE - ); - scic_sds_remote_node_context_continue_state_transitions(rnc); } -/** - * - * - * - */ static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( void *object) { struct scic_sds_remote_node_context *rnc = object; - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE - ); - scic_sds_remote_node_context_continue_state_transitions(rnc); } -/** - * - * - * - */ -static void scic_sds_remote_node_context_await_suspension_state_enter( - void *object) -{ - struct scic_sds_remote_node_context *rnc = object; - - SET_STATE_HANDLER( - rnc, - scic_sds_remote_node_context_state_handler_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE - ); -} - -/* --------------------------------------------------------------------------- */ - static const struct sci_base_state scic_sds_remote_node_context_state_table[] = { [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { .enter_state = scic_sds_remote_node_context_initial_state_enter, @@ -618,9 +364,7 @@ static const struct sci_base_state scic_sds_remote_node_context_state_table[] = [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter, }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { - .enter_state = scic_sds_remote_node_context_await_suspension_state_enter, - }, + [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { }, }; void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, @@ -875,3 +619,39 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ return SCI_FAILURE_INVALID_STATE; } } + +enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) +{ + enum scis_sds_remote_node_context_states state; + + state = sci_rnc->state_machine.current_state_id; + if (state != SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: invalid state %d\n", __func__, state); + return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; + } + return SCI_SUCCESS; +} + +enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req) +{ + enum scis_sds_remote_node_context_states state; + + state = sci_rnc->state_machine.current_state_id; + switch (state) { + case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE: + return SCI_SUCCESS; + case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE: + case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE: + scic_sds_remote_node_context_resume(sci_rnc, NULL, NULL); + return SCI_SUCCESS; + default: + dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: invalid state %d\n", __func__, state); + return SCI_FAILURE_INVALID_STATE; + } +} diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index 68983748eba9..f53329f782c8 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -84,31 +84,6 @@ struct scic_sds_remote_node_context; typedef void (*scics_sds_remote_node_context_callback)(void *); -typedef enum sci_status (*scic_sds_remote_node_context_operation)( - struct scic_sds_remote_node_context *sci_rnc, - scics_sds_remote_node_context_callback callback, - void *callback_parameter - ); - -typedef enum sci_status (*scic_sds_remote_node_context_io_request)( - struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req - ); - -struct scic_sds_remote_node_context_handlers { - /** - * This handler is invoked when there is a request to start an io request - * operation. - */ - scic_sds_remote_node_context_io_request start_io_handler; - - /** - * This handler is invoked when there is a request to start a task request - * operation. - */ - scic_sds_remote_node_context_io_request start_task_handler; -}; - /** * This is the enumeration of the remote node context states. */ @@ -220,8 +195,6 @@ struct scic_sds_remote_node_context { * This field contains the data for the object's state machine. */ struct sci_base_state_machine state_machine; - - struct scic_sds_remote_node_context_handlers *state_handlers; }; void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, @@ -236,24 +209,19 @@ bool scic_sds_remote_node_context_is_ready( enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc, u32 event_code); - enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, void *callback_parameter); - enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node_context *sci_rnc, u32 suspend_type, scics_sds_remote_node_context_callback cb_fn, void *cb_p); - enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback cb_fn, void *cb_p); - -#define scic_sds_remote_node_context_start_io(rnc, request) \ - ((rnc)->state_handlers->start_io_handler(rnc, request)) - -#define scic_sds_remote_node_context_start_task(rnc, task) \ - ((rnc)->state_handlers->start_task_handler(rnc, task)) +enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req); +enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_node_context *sci_rnc, + struct scic_sds_request *sci_req); #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ diff --git a/drivers/scsi/isci/state_machine.h b/drivers/scsi/isci/state_machine.h index c29eb4271d05..60ef1cf5abf4 100644 --- a/drivers/scsi/isci/state_machine.h +++ b/drivers/scsi/isci/state_machine.h @@ -83,14 +83,6 @@ struct sci_base_state { }; -/** - * SET_STATE_HANDLER() - - * - * This macro simply provides simplified retrieval of an objects state handler. - */ -#define SET_STATE_HANDLER(object, table, state) \ - (object)->state_handlers = &(table)[(state)] - /** * struct sci_base_state_machine - This structure defines the fields common to * all state machines. -- cgit v1.2.3 From 9269e0e898594c65dee6b20d4ed48e33dbbd4eeb Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 May 2011 07:42:17 -0700 Subject: isci: add some type safety to the state machine interface Now that any given object type only has one state_machine we can use container_of() to get back to the given state machine owner. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 32 +++++++-------- drivers/scsi/isci/phy.c | 70 ++++++++++++++++----------------- drivers/scsi/isci/port.c | 45 +++++++++++---------- drivers/scsi/isci/remote_device.c | 65 ++++++++++++++---------------- drivers/scsi/isci/remote_node_context.c | 39 ++++++++---------- drivers/scsi/isci/request.c | 35 ++++++++--------- drivers/scsi/isci/state_machine.c | 13 +----- drivers/scsi/isci/state_machine.h | 43 +++++--------------- 8 files changed, 148 insertions(+), 194 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index a942384f2798..6cd7648197e1 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1404,17 +1404,17 @@ static void isci_user_parameters_get( u->max_number_concurrent_device_spin_up = max_concurr_spinup; } -static void scic_sds_controller_initial_state_enter(void *object) +static void scic_sds_controller_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = object; + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_RESET); } -static inline void scic_sds_controller_starting_state_exit(void *object) +static inline void scic_sds_controller_starting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = object; + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); isci_timer_stop(scic->timeout_timer); } @@ -1539,17 +1539,17 @@ static enum sci_status scic_controller_set_interrupt_coalescence( } -static void scic_sds_controller_ready_state_enter(void *object) +static void scic_sds_controller_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = object; + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); /* set the default interrupt coalescence number and timeout value. */ scic_controller_set_interrupt_coalescence(scic, 0x10, 250); } -static void scic_sds_controller_ready_state_exit(void *object) +static void scic_sds_controller_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = object; + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); /* disable interrupt coalescence. */ scic_controller_set_interrupt_coalescence(scic, 0, 0); @@ -1638,9 +1638,9 @@ static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controll return status; } -static void scic_sds_controller_stopping_state_enter(void *object) +static void scic_sds_controller_stopping_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = object; + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); /* Stop all of the components for this controller */ scic_sds_controller_stop_phys(scic); @@ -1648,9 +1648,9 @@ static void scic_sds_controller_stopping_state_enter(void *object) scic_sds_controller_stop_devices(scic); } -static void scic_sds_controller_stopping_state_exit(void *object) +static void scic_sds_controller_stopping_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = object; + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); isci_timer_stop(scic->timeout_timer); } @@ -1679,9 +1679,9 @@ static void scic_sds_controller_reset_hardware(struct scic_sds_controller *scic) writel(0, &scic->scu_registers->sdma.unsolicited_frame_get_pointer); } -static void scic_sds_controller_resetting_state_enter(void *object) +static void scic_sds_controller_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = object; + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); scic_sds_controller_reset_hardware(scic); sci_base_state_machine_change_state(&scic->state_machine, @@ -1785,8 +1785,8 @@ static enum sci_status scic_controller_construct(struct scic_sds_controller *sci u8 i; sci_base_state_machine_construct(&scic->state_machine, - scic, scic_sds_controller_state_table, - SCI_BASE_CONTROLLER_STATE_INITIAL); + scic_sds_controller_state_table, + SCI_BASE_CONTROLLER_STATE_INITIAL); sci_base_state_machine_start(&scic->state_machine); diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 8bd1a85f621e..f21e10e2888c 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -1026,81 +1026,80 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, } -static void scic_sds_phy_starting_initial_substate_enter(void *object) +static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); /* This is just an temporary state go off to the starting state */ sci_base_state_machine_change_state(&sci_phy->state_machine, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN); } -static void scic_sds_phy_starting_await_sas_power_substate_enter(void *object) +static void scic_sds_phy_starting_await_sas_power_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; scic_sds_controller_power_control_queue_insert(scic, sci_phy); } -static void scic_sds_phy_starting_await_sas_power_substate_exit(void *object) +static void scic_sds_phy_starting_await_sas_power_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; scic_sds_controller_power_control_queue_remove(scic, sci_phy); } -static void scic_sds_phy_starting_await_sata_power_substate_enter(void *object) +static void scic_sds_phy_starting_await_sata_power_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; scic_sds_controller_power_control_queue_insert(scic, sci_phy); } -static void scic_sds_phy_starting_await_sata_power_substate_exit(void *object) +static void scic_sds_phy_starting_await_sata_power_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; scic_sds_controller_power_control_queue_remove(scic, sci_phy); } -static void scic_sds_phy_starting_await_sata_phy_substate_enter(void *object) +static void scic_sds_phy_starting_await_sata_phy_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); isci_timer_start(sci_phy->sata_timeout_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } -static void scic_sds_phy_starting_await_sata_phy_substate_exit(void *object) +static void scic_sds_phy_starting_await_sata_phy_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); isci_timer_stop(sci_phy->sata_timeout_timer); } -static void scic_sds_phy_starting_await_sata_speed_substate_enter(void *object) +static void scic_sds_phy_starting_await_sata_speed_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); isci_timer_start(sci_phy->sata_timeout_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } -static void scic_sds_phy_starting_await_sata_speed_substate_exit( - void *object) +static void scic_sds_phy_starting_await_sata_speed_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); isci_timer_stop(sci_phy->sata_timeout_timer); } -static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) +static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); if (scic_sds_port_link_detected(sci_phy->owning_port, sci_phy)) { @@ -1118,16 +1117,16 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(void *object) sci_phy->is_in_link_training = false; } -static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(void *object) +static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); isci_timer_stop(sci_phy->sata_timeout_timer); } -static void scic_sds_phy_starting_final_substate_enter(void *object) +static void scic_sds_phy_starting_final_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); /* State machine has run to completion so exit out and change * the base state machine to the ready state @@ -1217,9 +1216,9 @@ static void scu_link_layer_tx_hard_reset( &sci_phy->link_layer_registers->phy_configuration); } -static void scic_sds_phy_stopped_state_enter(void *object) +static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); struct scic_sds_port *sci_port = sci_phy->owning_port; struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); @@ -1242,9 +1241,9 @@ static void scic_sds_phy_stopped_state_enter(void *object) sci_phy); } -static void scic_sds_phy_starting_state_enter(void *object) +static void scic_sds_phy_starting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); scu_link_layer_stop_protocol_engine(sci_phy); scu_link_layer_start_oob(sci_phy); @@ -1262,9 +1261,9 @@ static void scic_sds_phy_starting_state_enter(void *object) SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); } -static void scic_sds_phy_ready_state_enter(void *object) +static void scic_sds_phy_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); scic_sds_controller_link_up(scic_sds_phy_get_controller(sci_phy), phy_get_non_dummy_port(sci_phy), @@ -1272,16 +1271,16 @@ static void scic_sds_phy_ready_state_enter(void *object) } -static void scic_sds_phy_ready_state_exit(void *object) +static void scic_sds_phy_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); scic_sds_phy_suspend(sci_phy); } -static void scic_sds_phy_resetting_state_enter(void *object) +static void scic_sds_phy_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = object; + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); /* The phy is being reset, therefore deactivate it from the port. In * the resetting state we don't notify the user regarding link up and @@ -1351,7 +1350,6 @@ void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, struct scic_sds_port *owning_port, u8 phy_index) { sci_base_state_machine_construct(&sci_phy->state_machine, - sci_phy, scic_sds_phy_state_table, SCI_BASE_PHY_STATE_INITIAL); diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index f43c1f6c9669..3050415e228d 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1133,9 +1133,9 @@ scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) writel(pts_control_value, &port->port_task_scheduler_registers->control); } -static void scic_sds_port_ready_substate_waiting_enter(void *object) +static void scic_sds_port_ready_substate_waiting_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); scic_sds_port_suspend_port_task_scheduler(sci_port); @@ -1148,10 +1148,10 @@ static void scic_sds_port_ready_substate_waiting_enter(void *object) } } -static void scic_sds_port_ready_substate_operational_enter(void *object) +static void scic_sds_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) { u32 index; - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); @@ -1210,9 +1210,9 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports * the port not ready and suspends the port task scheduler. none */ -static void scic_sds_port_ready_substate_operational_exit(void *object) +static void scic_sds_port_ready_substate_operational_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); @@ -1230,9 +1230,9 @@ static void scic_sds_port_ready_substate_operational_exit(void *object) scic_sds_port_invalidate_dummy_remote_node(sci_port); } -static void scic_sds_port_ready_substate_configuring_enter(void *object) +static void scic_sds_port_ready_substate_configuring_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); @@ -1247,9 +1247,9 @@ static void scic_sds_port_ready_substate_configuring_enter(void *object) SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); } -static void scic_sds_port_ready_substate_configuring_exit(void *object) +static void scic_sds_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); scic_sds_port_suspend_port_task_scheduler(sci_port); if (sci_port->ready_exit) @@ -1710,9 +1710,9 @@ static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) scic_sds_controller_post_request(scic, command); } -static void scic_sds_port_stopped_state_enter(void *object) +static void scic_sds_port_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); if (sci_port->state_machine.previous_state_id == SCI_BASE_PORT_STATE_STOPPING) { /* @@ -1723,17 +1723,17 @@ static void scic_sds_port_stopped_state_enter(void *object) } } -static void scic_sds_port_stopped_state_exit(void *object) +static void scic_sds_port_stopped_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); /* Enable and suspend the port task scheduler */ scic_sds_port_enable_port_task_scheduler(sci_port); } -static void scic_sds_port_ready_state_enter(void *object) +static void scic_sds_port_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); @@ -1753,25 +1753,25 @@ static void scic_sds_port_ready_state_enter(void *object) SCIC_SDS_PORT_READY_SUBSTATE_WAITING); } -static void scic_sds_port_resetting_state_exit(void *object) +static void scic_sds_port_resetting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); isci_timer_stop(sci_port->timer_handle); } -static void scic_sds_port_stopping_state_exit(void *object) +static void scic_sds_port_stopping_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); isci_timer_stop(sci_port->timer_handle); scic_sds_port_destroy_dummy_resources(sci_port); } -static void scic_sds_port_failed_state_enter(void *object) +static void scic_sds_port_failed_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = object; + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); struct isci_port *iport = sci_port_to_iport(sci_port); isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); @@ -1813,7 +1813,6 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, struct scic_sds_controller *scic) { sci_base_state_machine_construct(&sci_port->state_machine, - sci_port, scic_sds_port_state_table, SCI_BASE_PORT_STATE_STOPPED); diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index b900e2c1b63e..68b63b04be19 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -807,9 +807,9 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl isci_remote_device_ready(scic_to_ihost(scic), idev); } -static void scic_sds_remote_device_initial_state_enter(void *object) +static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); /* Initial state is a transitional state to the stopped state */ sci_base_state_machine_change_state(&sci_dev->state_machine, @@ -904,9 +904,9 @@ static void isci_remote_device_stop_complete(struct isci_host *ihost, isci_remote_device_deconstruct(ihost, idev); } -static void scic_sds_remote_device_stopped_state_enter(void *object) +static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); u32 prev_state; @@ -921,9 +921,9 @@ static void scic_sds_remote_device_stopped_state_enter(void *object) scic_sds_controller_remote_device_stopped(scic, sci_dev); } -static void scic_sds_remote_device_starting_state_enter(void *object) +static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic_to_ihost(scic); struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); @@ -932,9 +932,9 @@ static void scic_sds_remote_device_starting_state_enter(void *object) SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); } -static void scic_sds_remote_device_ready_state_enter(void *object) +static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); struct domain_device *dev = idev->domain_dev; @@ -951,9 +951,9 @@ static void scic_sds_remote_device_ready_state_enter(void *object) isci_remote_device_ready(scic_to_ihost(scic), idev); } -static void scic_sds_remote_device_ready_state_exit(void *object) +static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); struct domain_device *dev = sci_dev_to_domain(sci_dev); if (dev->dev_type == SAS_END_DEV) { @@ -965,24 +965,24 @@ static void scic_sds_remote_device_ready_state_exit(void *object) } } -static void scic_sds_remote_device_resetting_state_enter(void *object) +static void scic_sds_remote_device_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); scic_sds_remote_node_context_suspend( &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); } -static void scic_sds_remote_device_resetting_state_exit(void *object) +static void scic_sds_remote_device_resetting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); } -static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *object) +static void scic_sds_stp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); sci_dev->working_request = NULL; if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { @@ -997,9 +997,9 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *object) } } -static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) +static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); BUG_ON(sci_dev->working_request == NULL); @@ -1008,9 +1008,9 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } -static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(void *object) +static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); @@ -1019,17 +1019,17 @@ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(void *obje sci_dev->not_ready_reason); } -static void scic_sds_smp_remote_device_ready_idle_substate_enter(void *object) +static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); isci_remote_device_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev)); } -static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) +static void scic_sds_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); BUG_ON(sci_dev->working_request == NULL); @@ -1038,9 +1038,9 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter(void *object) SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); } -static void scic_sds_smp_remote_device_ready_cmd_substate_exit(void *object) +static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = object; + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); sci_dev->working_request = NULL; } @@ -1102,16 +1102,11 @@ static void scic_remote_device_construct(struct scic_sds_port *sci_port, sci_dev->owning_port = sci_port; sci_dev->started_request_count = 0; - sci_base_state_machine_construct( - &sci_dev->state_machine, - sci_dev, - scic_sds_remote_device_state_table, - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL - ); + sci_base_state_machine_construct(&sci_dev->state_machine, + scic_sds_remote_device_state_table, + SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); - sci_base_state_machine_start( - &sci_dev->state_machine - ); + sci_base_state_machine_start(&sci_dev->state_machine); scic_sds_remote_node_context_construct(&sci_dev->rnc, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 82507bd228d4..e7fa5bac7d53 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -266,10 +266,9 @@ static void scic_sds_remote_node_context_invalidate_context_buffer( SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE); } -static void scic_sds_remote_node_context_initial_state_enter(void *object) +static void scic_sds_remote_node_context_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = object; - struct sci_base_state_machine *sm = &rnc->state_machine; + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); /* Check to see if we have gotten back to the initial state because * someone requested to destroy the remote node context object. @@ -280,23 +279,23 @@ static void scic_sds_remote_node_context_initial_state_enter(void *object) } } -static void scic_sds_remote_node_context_posting_state_enter(void *object) +static void scic_sds_remote_node_context_posting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *sci_rnc = object; + struct scic_sds_remote_node_context *sci_rnc = container_of(sm, typeof(*sci_rnc), state_machine); scic_sds_remote_node_context_validate_context_buffer(sci_rnc); } -static void scic_sds_remote_node_context_invalidating_state_enter(void *object) +static void scic_sds_remote_node_context_invalidating_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = object; + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); scic_sds_remote_node_context_invalidate_context_buffer(rnc); } -static void scic_sds_remote_node_context_resuming_state_enter(void *object) +static void scic_sds_remote_node_context_resuming_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = object; + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); struct scic_sds_remote_device *sci_dev; struct domain_device *dev; @@ -317,9 +316,9 @@ static void scic_sds_remote_node_context_resuming_state_enter(void *object) scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); } -static void scic_sds_remote_node_context_ready_state_enter(void *object) +static void scic_sds_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = object; + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; @@ -327,17 +326,16 @@ static void scic_sds_remote_node_context_ready_state_enter(void *object) scic_sds_remote_node_context_notify_user(rnc); } -static void scic_sds_remote_node_context_tx_suspended_state_enter(void *object) +static void scic_sds_remote_node_context_tx_suspended_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = object; + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); scic_sds_remote_node_context_continue_state_transitions(rnc); } -static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( - void *object) +static void scic_sds_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = object; + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); scic_sds_remote_node_context_continue_state_transitions(rnc); } @@ -375,12 +373,9 @@ void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context rnc->remote_node_index = remote_node_index; rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - sci_base_state_machine_construct( - &rnc->state_machine, - rnc, - scic_sds_remote_node_context_state_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE - ); + sci_base_state_machine_construct(&rnc->state_machine, + scic_sds_remote_node_context_state_table, + SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE); sci_base_state_machine_start(&rnc->state_machine); } diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c63064ede38d..063ef04080d5 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2900,10 +2900,9 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, isci_host_can_dequeue(isci_host, 1); } -static void scic_sds_request_started_state_enter(void *object) +static void scic_sds_request_started_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = object; - struct sci_base_state_machine *sm = &sci_req->state_machine; + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); struct isci_request *ireq = sci_req_to_ireq(sci_req); struct domain_device *dev = sci_dev_to_domain(sci_req->target_device); struct sas_task *task; @@ -2942,9 +2941,9 @@ static void scic_sds_request_started_state_enter(void *object) } } -static void scic_sds_request_completed_state_enter(void *object) +static void scic_sds_request_completed_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = object; + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); struct scic_sds_controller *scic = sci_req->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_request *ireq = sci_req_to_ireq(sci_req); @@ -2957,42 +2956,41 @@ static void scic_sds_request_completed_state_enter(void *object) isci_task_request_complete(ihost, ireq, sci_req->sci_status); } -static void scic_sds_request_aborting_state_enter(void *object) +static void scic_sds_request_aborting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = object; + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); /* Setting the abort bit in the Task Context is required by the silicon. */ sci_req->task_context_buffer->abort = 1; } -static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( - void *object) +static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = object; + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); scic_sds_remote_device_set_working_request(sci_req->target_device, sci_req); } -static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(void *object) +static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = object; + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); scic_sds_remote_device_set_working_request(sci_req->target_device, sci_req); } -static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(void *object) +static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = object; + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); scic_sds_remote_device_set_working_request(sci_req->target_device, sci_req); } -static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(void *object) +static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = object; + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); struct scu_task_context *task_context; struct host_to_dev_fis *h2d_fis; enum sci_status status; @@ -3052,8 +3050,9 @@ static void scic_sds_general_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, u16 io_tag, struct scic_sds_request *sci_req) { - sci_base_state_machine_construct(&sci_req->state_machine, sci_req, - scic_sds_request_state_table, SCI_BASE_REQUEST_STATE_INITIAL); + sci_base_state_machine_construct(&sci_req->state_machine, + scic_sds_request_state_table, + SCI_BASE_REQUEST_STATE_INITIAL); sci_base_state_machine_start(&sci_req->state_machine); sci_req->io_tag = io_tag; diff --git a/drivers/scsi/isci/state_machine.c b/drivers/scsi/isci/state_machine.c index 6057782af8c2..1bcd925e502f 100644 --- a/drivers/scsi/isci/state_machine.c +++ b/drivers/scsi/isci/state_machine.c @@ -68,7 +68,7 @@ static void sci_state_machine_exit_state(struct sci_base_state_machine *sm) sci_state_transition_t exit = sm->state_table[state].exit_state; if (exit) - exit(sm->state_machine_owner); + exit(sm); } static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) @@ -77,22 +77,15 @@ static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) sci_state_transition_t enter = sm->state_table[state].enter_state; if (enter) - enter(sm->state_machine_owner); + enter(sm); } -/* - * ****************************************************************************** - * * P R O T E C T E D M E T H O D S - * ****************************************************************************** */ - /** * This method will set the initial state and state table for the state * machine. The caller should follow this request with the initialize * request to cause the state machine to start. * @sm: This parameter provides the state machine object to be * constructed. - * @state_machine_owner: This parameter indicates the object that is owns the - * state machine being constructed. * @state_table: This parameter specifies the table of state objects that is * managed by this state machine. * @initial_state: This parameter specifies the value of the initial state for @@ -100,11 +93,9 @@ static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) * */ void sci_base_state_machine_construct(struct sci_base_state_machine *sm, - void *owner, const struct sci_base_state *state_table, u32 initial_state) { - sm->state_machine_owner = owner; sm->initial_state_id = initial_state; sm->previous_state_id = initial_state; sm->current_state_id = initial_state; diff --git a/drivers/scsi/isci/state_machine.h b/drivers/scsi/isci/state_machine.h index 60ef1cf5abf4..067ed9126bf2 100644 --- a/drivers/scsi/isci/state_machine.h +++ b/drivers/scsi/isci/state_machine.h @@ -58,9 +58,9 @@ #include +struct sci_base_state_machine; typedef void (*sci_base_state_handler_t)(void); - -typedef void (*sci_state_transition_t)(void *base_object); +typedef void (*sci_state_transition_t)(struct sci_base_state_machine *sm); /** * struct sci_base_state - The base state object abstracts the fields common to @@ -80,7 +80,6 @@ struct sci_base_state { * invoked when the state is exited. */ sci_state_transition_t exit_state; - }; /** @@ -95,13 +94,6 @@ struct sci_base_state_machine { */ const struct sci_base_state *state_table; - /** - * This field points to the object to which this state machine is - * associated. It serves as a cookie to be provided to the state - * enter/exit methods. - */ - void *state_machine_owner; - /** * This field simply indicates the state value for the state machine's * initial state. @@ -120,28 +112,13 @@ struct sci_base_state_machine { }; -/* - * ****************************************************************************** - * * P R O T E C T E D M E T H O D S - * ****************************************************************************** */ - -void sci_base_state_machine_construct( - struct sci_base_state_machine *this_state_machine, - void *state_machine_owner, - const struct sci_base_state *state_table, - u32 initial_state); - -void sci_base_state_machine_start( - struct sci_base_state_machine *this_state_machine); - -void sci_base_state_machine_stop( - struct sci_base_state_machine *this_state_machine); - -void sci_base_state_machine_change_state( - struct sci_base_state_machine *this_state_machine, - u32 next_state); - -u32 sci_base_state_machine_get_state( - struct sci_base_state_machine *this_state_machine); +void sci_base_state_machine_construct(struct sci_base_state_machine *sm, + const struct sci_base_state *state_table, + u32 initial_state); +void sci_base_state_machine_start(struct sci_base_state_machine *sm); +void sci_base_state_machine_stop(struct sci_base_state_machine *sm); +void sci_base_state_machine_change_state(struct sci_base_state_machine *sm, + u32 next_state); +u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm); #endif /* _SCI_BASE_STATE_MACHINE_H_ */ -- cgit v1.2.3 From 5553ba2be0f3e3741e1a885a33d2b89921f9fd48 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 19 May 2011 11:59:10 +0000 Subject: isci: replace isci_timer list with proper embedded timers Rather than preallocating a list of timers and doling them out at runtime, embed a struct timerlist in each object that needs one. A struct sci_timer interface is introduced to manage the timer cancellation semantics which currently need to guarantee the timer is cancelled while holding spin_lock(ihost->scic_lock). Since the timeout functions also need to acquire the lock it currently prevents the driver from using del_timer_sync() for runtime cancellations. del_timer_sync() is used however before the objects go out of scope. Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 7 +++++++ drivers/scsi/isci/isci.h | 33 +++++++++++++++++++++++++++++++++ drivers/scsi/isci/port.c | 39 ++++++++++++++++++--------------------- drivers/scsi/isci/port.h | 6 ++---- 4 files changed, 60 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 6cd7648197e1..a3269b6fa225 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1359,6 +1359,13 @@ void isci_host_deinit(struct isci_host *ihost) wait_for_stop(ihost); scic_controller_reset(&ihost->sci); + + /* Cancel any/all outstanding port timers */ + for (i = 0; i < ihost->sci.logical_port_entries; i++) { + struct scic_sds_port *sci_port = &ihost->ports[i].sci; + del_timer_sync(&sci_port->timer.timer); + } + isci_timer_list_destroy(ihost); } diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 69826eac97b5..2fe5557d8590 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -551,4 +551,37 @@ extern unsigned char max_concurr_spinup; irqreturn_t isci_msix_isr(int vec, void *data); irqreturn_t isci_intx_isr(int vec, void *data); irqreturn_t isci_error_isr(int vec, void *data); + +/* + * Each timer is associated with a cancellation flag that is set when + * del_timer() is called and checked in the timer callback function. This + * is needed since del_timer_sync() cannot be called with scic_lock held. + * For deinit however, del_timer_sync() is used without holding the lock. + */ +struct sci_timer { + struct timer_list timer; + bool cancel; +}; + +static inline +void sci_init_timer(struct sci_timer *tmr, void (*fn)(unsigned long)) +{ + tmr->timer.function = fn; + tmr->timer.data = (unsigned long) tmr; + tmr->cancel = 0; + init_timer(&tmr->timer); +} + +static inline void sci_mod_timer(struct sci_timer *tmr, unsigned long msec) +{ + tmr->cancel = 0; + mod_timer(&tmr->timer, jiffies + msecs_to_jiffies(msec)); +} + +static inline void sci_del_timer(struct sci_timer *tmr) +{ + tmr->cancel = 1; + del_timer(&tmr->timer); +} + #endif /* __ISCI_H__ */ diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 3050415e228d..3da9048b45b7 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -926,17 +926,19 @@ bool scic_sds_port_link_detected( return true; } -/** - * This method is provided to timeout requests for port operations. Mostly its - * for the port reset operation. - * - * - */ -static void scic_sds_port_timeout_handler(void *port) +static void port_timeout(unsigned long data) { - struct scic_sds_port *sci_port = port; + struct sci_timer *tmr = (struct sci_timer *)data; + struct scic_sds_port *sci_port = container_of(tmr, typeof(*sci_port), timer); + struct isci_host *ihost = scic_to_ihost(sci_port->owning_controller); + unsigned long flags; u32 current_state; + spin_lock_irqsave(&ihost->scic_lock, flags); + + if (tmr->cancel) + goto done; + current_state = sci_base_state_machine_get_state(&sci_port->state_machine); if (current_state == SCI_BASE_PORT_STATE_RESETTING) { @@ -965,6 +967,9 @@ static void scic_sds_port_timeout_handler(void *port) "%s: SCIC Port 0x%p is processing a timeout operation " "in state %d.\n", __func__, sci_port, current_state); } + +done: + spin_unlock_irqrestore(&ihost->scic_lock, flags); } /* --------------------------------------------------------------------------- */ @@ -1259,7 +1264,6 @@ static void scic_sds_port_ready_substate_configuring_exit(struct sci_base_state_ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); enum sci_status status = SCI_SUCCESS; enum scic_sds_port_states state; u32 phy_mask; @@ -1280,14 +1284,6 @@ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } - sci_port->timer_handle = - isci_timer_create(ihost, - sci_port, - scic_sds_port_timeout_handler); - - if (!sci_port->timer_handle) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - if (sci_port->reserved_rni == SCU_DUMMY_INDEX) { u16 rni = scic_sds_remote_node_table_allocate_remote_node( &scic->available_remote_nodes, 1); @@ -1390,7 +1386,7 @@ static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 if (status != SCI_SUCCESS) return status; - isci_timer_start(sci_port->timer_handle, timeout); + sci_mod_timer(&sci_port->timer, timeout); sci_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; port_state_machine_change(sci_port, @@ -1757,14 +1753,14 @@ static void scic_sds_port_resetting_state_exit(struct sci_base_state_machine *sm { struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); - isci_timer_stop(sci_port->timer_handle); + sci_del_timer(&sci_port->timer); } static void scic_sds_port_stopping_state_exit(struct sci_base_state_machine *sm) { struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); - isci_timer_stop(sci_port->timer_handle); + sci_del_timer(&sci_port->timer); scic_sds_port_destroy_dummy_resources(sci_port); } @@ -1831,7 +1827,8 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, sci_port->reserved_rni = SCU_DUMMY_INDEX; sci_port->reserved_tci = SCU_DUMMY_INDEX; - sci_port->timer_handle = NULL; + sci_init_timer(&sci_port->timer, port_timeout); + sci_port->port_task_scheduler_registers = NULL; for (index = 0; index < SCI_MAX_PHYS; index++) diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index af540e5c03a0..9a6912855fc1 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -139,10 +139,8 @@ struct scic_sds_port { */ struct scic_sds_controller *owning_controller; - /** - * This field contains the port start/stop timer handle. - */ - void *timer_handle; + /* timer used for port start/stop operations */ + struct sci_timer timer; /** * This field is the pointer to the port task scheduler registers -- cgit v1.2.3 From ac0eeb4f774261d1da21a68169f7ddd4f6c082fc Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 19 May 2011 20:00:51 -0700 Subject: isci: convert port config agent timer to sci_timer Signed-off-by: Edmund Nadolski [squashed collateral cleanups] Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 2 + drivers/scsi/isci/host.h | 11 +--- drivers/scsi/isci/port_config.c | 117 +++++++++++++++++----------------------- 3 files changed, 53 insertions(+), 77 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index a3269b6fa225..468357ffc771 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1366,6 +1366,8 @@ void isci_host_deinit(struct isci_host *ihost) del_timer_sync(&sci_port->timer.timer); } + del_timer_sync(&ihost->sci.port_agent.timer.timer); + isci_timer_list_destroy(ihost); } diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 784e1355e8ec..deb0ee031f27 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -122,7 +122,7 @@ struct scic_sds_port_configuration_agent { bool timer_pending; port_config_fn link_up_handler; port_config_fn link_down_handler; - void *timer; + struct sci_timer timer; }; /** @@ -568,15 +568,6 @@ static inline struct isci_host *scic_to_ihost(struct scic_sds_controller *scic) } \ } -/** - * scic_sds_controller_get_port_configuration_agent() - - * - * This is a helper macro to get the port configuration agent from the - * controller object. - */ -#define scic_sds_controller_get_port_configuration_agent(controller) \ - (&(controller)->port_agent) - /** * scic_sds_controller_get_protocol_engine_group() - * diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index ca76f493c30d..1cde7b9165f4 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -328,21 +328,25 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); } -/** - * - * - * This timer routine is used to allow the SCI User to rediscover or change - * device objects before a new series of link up notifications because a link - * down has allowed a better port configuration. - */ -static void scic_sds_mpc_agent_timeout_handler(void *object) +static void mpc_agent_timeout(unsigned long data) { u8 index; - struct scic_sds_controller *scic = object; - struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_port_configuration_agent *port_agent = &scic->port_agent; + struct sci_timer *tmr = (struct sci_timer *)data; + struct scic_sds_port_configuration_agent *port_agent; + struct scic_sds_controller *scic; + struct isci_host *ihost; + unsigned long flags; u16 configure_phy_mask; + port_agent = container_of(tmr, typeof(*port_agent), timer); + scic = container_of(port_agent, typeof(*scic), port_agent); + ihost = scic_to_ihost(scic); + + spin_lock_irqsave(&ihost->scic_lock, flags); + + if (tmr->cancel) + goto done; + port_agent->timer_pending = false; /* Find the mask of phys that are reported read but as yet unconfigured into a port */ @@ -357,6 +361,9 @@ static void scic_sds_mpc_agent_timeout_handler(void *object) sci_phy); } } + +done: + spin_unlock_irqrestore(&ihost->scic_lock, flags); } /** @@ -441,8 +448,8 @@ static void scic_sds_mpc_agent_link_down( !port_agent->timer_pending) { port_agent->timer_pending = true; - isci_timer_start(port_agent->timer, - SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT); + sci_mod_timer(&port_agent->timer, + SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT); } scic_sds_port_link_down(sci_port, sci_phy); @@ -498,31 +505,6 @@ static enum sci_status scic_sds_apc_agent_validate_phy_configuration( return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); } -/** - * - * @controller: This is the controller that to which the port agent is assigned. - * @port_agent: This is the port agent that is requesting the timer start - * operation. - * @phy: This is the phy that has caused the timer operation to be scheduled. - * - * This routine will restart the automatic port configuration timeout timer for - * the next time period. This could be caused by either a link down event or a - * link up event where we can not yet tell to which port a phy belongs. - */ -static inline void scic_sds_apc_agent_start_timer( - struct scic_sds_controller *scic, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_phy *sci_phy, - u32 timeout) -{ - if (port_agent->timer_pending) - isci_timer_stop(port_agent->timer); - - port_agent->timer_pending = true; - - isci_timer_start(port_agent->timer, timeout); -} - /** * * @controller: This is the controller object that receives the link up @@ -635,9 +617,17 @@ static void scic_sds_apc_agent_configure_ports( break; case SCIC_SDS_APC_START_TIMER: - scic_sds_apc_agent_start_timer( - controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION - ); + /* + * This can occur for either a link down event, or a link + * up event where we cannot yet tell the port to which a + * phy belongs. + */ + if (port_agent->timer_pending) + sci_del_timer(&port_agent->timer); + + port_agent->timer_pending = true; + sci_mod_timer(&port_agent->timer, + SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION); break; case SCIC_SDS_APC_SKIP_PHY: @@ -719,15 +709,24 @@ static void scic_sds_apc_agent_link_down( } /* configure the phys into ports when the timer fires */ -static void scic_sds_apc_agent_timeout_handler(void *object) +static void apc_agent_timeout(unsigned long data) { u32 index; + struct sci_timer *tmr = (struct sci_timer *)data; struct scic_sds_port_configuration_agent *port_agent; - struct scic_sds_controller *scic = object; - struct isci_host *ihost = scic_to_ihost(scic); + struct scic_sds_controller *scic; + struct isci_host *ihost; + unsigned long flags; u16 configure_phy_mask; - port_agent = scic_sds_controller_get_port_configuration_agent(scic); + port_agent = container_of(tmr, typeof(*port_agent), timer); + scic = container_of(port_agent, typeof(*scic), port_agent); + ihost = scic_to_ihost(scic); + + spin_lock_irqsave(&ihost->scic_lock, flags); + + if (tmr->cancel) + goto done; port_agent->timer_pending = false; @@ -743,6 +742,9 @@ static void scic_sds_apc_agent_timeout_handler(void *object) scic_sds_apc_agent_configure_ports(scic, port_agent, &ihost->phys[index].sci, false); } + +done: + spin_unlock_irqrestore(&ihost->scic_lock, flags); } /* @@ -769,7 +771,6 @@ void scic_sds_port_configuration_agent_construct( port_agent->link_down_handler = NULL; port_agent->timer_pending = false; - port_agent->timer = NULL; for (index = 0; index < SCI_MAX_PORTS; index++) { port_agent->phy_valid_port_range[index].min_index = 0; @@ -781,9 +782,8 @@ enum sci_status scic_sds_port_configuration_agent_initialize( struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent) { - enum sci_status status = SCI_SUCCESS; + enum sci_status status; enum scic_port_configuration_mode mode; - struct isci_host *ihost = scic_to_ihost(scic); mode = scic->oem_parameters.sds1.controller.mode_type; @@ -794,10 +794,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize( port_agent->link_up_handler = scic_sds_mpc_agent_link_up; port_agent->link_down_handler = scic_sds_mpc_agent_link_down; - port_agent->timer = isci_timer_create( - ihost, - scic, - scic_sds_mpc_agent_timeout_handler); + sci_init_timer(&port_agent->timer, mpc_agent_timeout); } else { status = scic_sds_apc_agent_validate_phy_configuration( scic, port_agent); @@ -805,21 +802,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize( port_agent->link_up_handler = scic_sds_apc_agent_link_up; port_agent->link_down_handler = scic_sds_apc_agent_link_down; - port_agent->timer = isci_timer_create( - ihost, - scic, - scic_sds_apc_agent_timeout_handler); - } - - /* Make sure we have actually gotten a timer */ - if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) { - dev_err(scic_to_dev(scic), - "%s: Controller 0x%p automatic port configuration " - "agent could not get timer.\n", - __func__, - scic); - - status = SCI_FAILURE; + sci_init_timer(&port_agent->timer, apc_agent_timeout); } return status; -- cgit v1.2.3 From a628d478570d71fb8751ad09b8017139c5056002 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 19 May 2011 11:59:36 +0000 Subject: isci: convert phy sata_timeout_timer to sci_timer Convert the sata_timeout_timer in the scic_sds_phy struct to use a struct sci_timer Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 6 +++++ drivers/scsi/isci/phy.c | 70 +++++++++++++++++------------------------------- drivers/scsi/isci/phy.h | 8 +++--- 3 files changed, 35 insertions(+), 49 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 468357ffc771..aa00cce37821 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1366,6 +1366,12 @@ void isci_host_deinit(struct isci_host *ihost) del_timer_sync(&sci_port->timer.timer); } + /* Cancel any/all outstanding phy timers */ + for (i = 0; i < SCI_MAX_PHYS; i++) { + struct scic_sds_phy *sci_phy = &ihost->phys[i].sci; + del_timer_sync(&sci_phy->sata_timer.timer); + } + del_timer_sync(&ihost->sci.port_agent.timer.timer); isci_timer_list_destroy(ihost); diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index f21e10e2888c..b663bbdd4e59 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -256,14 +256,17 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, return SCI_SUCCESS; } -/** - * This function will handle the sata SIGNATURE FIS timeout condition. It will - * restart the starting substate machine since we dont know what has actually - * happening. - */ -static void scic_sds_phy_sata_timeout(void *phy) +static void phy_sata_timeout(unsigned long data) { - struct scic_sds_phy *sci_phy = phy; + struct sci_timer *tmr = (struct sci_timer *)data; + struct scic_sds_phy *sci_phy = container_of(tmr, typeof(*sci_phy), sata_timer); + struct isci_host *ihost = scic_to_ihost(sci_phy->owning_port->owning_controller); + unsigned long flags; + + spin_lock_irqsave(&ihost->scic_lock, flags); + + if (tmr->cancel) + goto done; dev_dbg(sciphy_to_dev(sci_phy), "%s: SCIC SDS Phy 0x%p did not receive signature fis before " @@ -273,6 +276,8 @@ static void scic_sds_phy_sata_timeout(void *phy) sci_base_state_machine_change_state(&sci_phy->state_machine, SCI_BASE_PHY_STATE_STARTING); +done: + spin_unlock_irqrestore(&ihost->scic_lock, flags); } /** @@ -327,16 +332,6 @@ enum sci_status scic_sds_phy_initialize( struct scu_transport_layer_registers __iomem *transport_layer_registers, struct scu_link_layer_registers __iomem *link_layer_registers) { - struct scic_sds_controller *scic = scic_sds_phy_get_controller(sci_phy); - struct isci_host *ihost = scic_to_ihost(scic); - - /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = - isci_timer_create( - ihost, - sci_phy, - scic_sds_phy_sata_timeout); - /* Perfrom the initialization of the TL hardware */ scic_sds_phy_transport_layer_initialization( sci_phy, @@ -442,9 +437,7 @@ void scic_sds_phy_get_protocols(struct scic_sds_phy *sci_phy, enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) { - struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; - struct isci_host *ihost = scic_to_ihost(scic); if (state != SCI_BASE_PHY_STATE_STOPPED) { dev_dbg(sciphy_to_dev(sci_phy), @@ -452,14 +445,8 @@ enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) return SCI_FAILURE_INVALID_STATE; } - /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_phy->sata_timeout_timer = isci_timer_create(ihost, sci_phy, - scic_sds_phy_sata_timeout); - - if (sci_phy->sata_timeout_timer) - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); - + sci_base_state_machine_change_state(&sci_phy->state_machine, + SCI_BASE_PHY_STATE_STARTING); return SCI_SUCCESS; } @@ -1071,30 +1058,28 @@ static void scic_sds_phy_starting_await_sata_phy_substate_enter(struct sci_base_ { struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); - isci_timer_start(sci_phy->sata_timeout_timer, - SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); + sci_mod_timer(&sci_phy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } static void scic_sds_phy_starting_await_sata_phy_substate_exit(struct sci_base_state_machine *sm) { struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); - isci_timer_stop(sci_phy->sata_timeout_timer); + sci_del_timer(&sci_phy->sata_timer); } static void scic_sds_phy_starting_await_sata_speed_substate_enter(struct sci_base_state_machine *sm) { struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); - isci_timer_start(sci_phy->sata_timeout_timer, - SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); + sci_mod_timer(&sci_phy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } static void scic_sds_phy_starting_await_sata_speed_substate_exit(struct sci_base_state_machine *sm) { struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); - isci_timer_stop(sci_phy->sata_timeout_timer); + sci_del_timer(&sci_phy->sata_timer); } static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_base_state_machine *sm) @@ -1111,8 +1096,8 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_bas */ scic_sds_phy_resume(sci_phy); - isci_timer_start(sci_phy->sata_timeout_timer, - SCIC_SDS_SIGNATURE_FIS_TIMEOUT); + sci_mod_timer(&sci_phy->sata_timer, + SCIC_SDS_SIGNATURE_FIS_TIMEOUT); } else sci_phy->is_in_link_training = false; } @@ -1121,7 +1106,7 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(struct sci_base { struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); - isci_timer_stop(sci_phy->sata_timeout_timer); + sci_del_timer(&sci_phy->sata_timer); } static void scic_sds_phy_starting_final_substate_enter(struct sci_base_state_machine *sm) @@ -1219,19 +1204,12 @@ static void scu_link_layer_tx_hard_reset( static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm) { struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); - struct scic_sds_port *sci_port = sci_phy->owning_port; - struct scic_sds_controller *scic = sci_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); /* * @todo We need to get to the controller to place this PE in a * reset state */ - if (sci_phy->sata_timeout_timer != NULL) { - isci_del_timer(ihost, sci_phy->sata_timeout_timer); - - sci_phy->sata_timeout_timer = NULL; - } + sci_del_timer(&sci_phy->sata_timer); scu_link_layer_stop_protocol_engine(sci_phy); @@ -1362,7 +1340,9 @@ void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; sci_phy->link_layer_registers = NULL; sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; - sci_phy->sata_timeout_timer = NULL; + + /* Create the SIGNATURE FIS Timeout timer for this phy */ + sci_init_timer(&sci_phy->sata_timer, phy_sata_timeout); } void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index) diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 7694ec4d76b5..da3f0f1d56d4 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -134,11 +134,11 @@ struct scic_sds_phy { bool is_in_link_training; /** - * This field contains a reference to the timer utilized in detecting - * when a signature FIS timeout has occurred. The signature FIS is the - * first FIS sent by an attached SATA device after OOB/SN. + * Timer to detect when a signature FIS timeout has occurred. The + * signature FIS is the first FIS sent by an attached SATA device + * after OOB/SN. */ - void *sata_timeout_timer; + struct sci_timer sata_timer; /** * This field is the pointer to the transport layer register for the SCU -- cgit v1.2.3 From 0473661a125905240879456567e117ed8a58cf5d Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 19 May 2011 20:17:47 -0700 Subject: isci: convert power control timer to sci_timer Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 103 ++++++++++++++++++++++------------------------- drivers/scsi/isci/host.h | 5 +-- 2 files changed, 50 insertions(+), 58 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index aa00cce37821..7b497f2667b7 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1374,6 +1374,8 @@ void isci_host_deinit(struct isci_host *ihost) del_timer_sync(&ihost->sci.port_agent.timer.timer); + del_timer_sync(&ihost->sci.power_control.timer.timer); + isci_timer_list_destroy(ihost); } @@ -1935,67 +1937,55 @@ static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sd return SCI_SUCCESS; } -static void scic_sds_controller_power_control_timer_start(struct scic_sds_controller *scic) +static void power_control_timeout(unsigned long data) { - isci_timer_start(scic->power_control.timer, - SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); + struct sci_timer *tmr = (struct sci_timer *)data; + struct scic_sds_controller *scic = container_of(tmr, typeof(*scic), power_control.timer); + struct isci_host *ihost = scic_to_ihost(scic); + struct scic_sds_phy *sci_phy; + unsigned long flags; + u8 i; - scic->power_control.timer_started = true; -} + spin_lock_irqsave(&ihost->scic_lock, flags); -static void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic) -{ - if (scic->power_control.timer_started) { - isci_timer_stop(scic->power_control.timer); + if (tmr->cancel) + goto done; + + scic->power_control.phys_granted_power = 0; + + if (scic->power_control.phys_waiting == 0) { scic->power_control.timer_started = false; + goto done; } -} - -static void scic_sds_controller_power_control_timer_restart(struct scic_sds_controller *scic) -{ - scic_sds_controller_power_control_timer_stop(scic); - scic_sds_controller_power_control_timer_start(scic); -} -static void scic_sds_controller_power_control_timer_handler( - void *controller) -{ - struct scic_sds_controller *scic; + for (i = 0; i < SCI_MAX_PHYS; i++) { - scic = (struct scic_sds_controller *)controller; + if (scic->power_control.phys_waiting == 0) + break; - scic->power_control.phys_granted_power = 0; + sci_phy = scic->power_control.requesters[i]; + if (sci_phy == NULL) + continue; - if (scic->power_control.phys_waiting == 0) { - scic->power_control.timer_started = false; - } else { - struct scic_sds_phy *sci_phy = NULL; - u8 i; - - for (i = 0; - (i < SCI_MAX_PHYS) - && (scic->power_control.phys_waiting != 0); - i++) { - if (scic->power_control.requesters[i] != NULL) { - if (scic->power_control.phys_granted_power < - scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { - sci_phy = scic->power_control.requesters[i]; - scic->power_control.requesters[i] = NULL; - scic->power_control.phys_waiting--; - scic->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(sci_phy); - } else { - break; - } - } - } + if (scic->power_control.phys_granted_power >= + scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) + break; - /* - * It doesn't matter if the power list is empty, we need to start the - * timer in case another phy becomes ready. - */ - scic_sds_controller_power_control_timer_start(scic); + scic->power_control.requesters[i] = NULL; + scic->power_control.phys_waiting--; + scic->power_control.phys_granted_power++; + scic_sds_phy_consume_power_handler(sci_phy); } + + /* + * It doesn't matter if the power list is empty, we need to start the + * timer in case another phy becomes ready. + */ + sci_mod_timer(tmr, SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); + scic->power_control.timer_started = true; + +done: + spin_unlock_irqrestore(&ihost->scic_lock, flags); } /** @@ -2019,7 +2009,13 @@ void scic_sds_controller_power_control_queue_insert( * stop and start the power_control timer. When the timer fires, the * no_of_phys_granted_power will be set to 0 */ - scic_sds_controller_power_control_timer_restart(scic); + if (scic->power_control.timer_started) + sci_del_timer(&scic->power_control.timer); + + sci_mod_timer(&scic->power_control.timer, + SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); + scic->power_control.timer_started = true; + } else { /* Add the phy in the waiting list */ scic->power_control.requesters[sci_phy->phy_index] = sci_phy; @@ -2224,10 +2220,7 @@ static enum sci_status scic_controller_set_mode(struct scic_sds_controller *scic static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) { - struct isci_host *ihost = scic_to_ihost(scic); - scic->power_control.timer = isci_timer_create(ihost, - scic, - scic_sds_controller_power_control_timer_handler); + sci_init_timer(&scic->power_control.timer, power_control_timeout); memset(scic->power_control.requesters, 0, sizeof(scic->power_control.requesters)); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index deb0ee031f27..2be935fa6af2 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -83,10 +83,9 @@ struct scic_power_control { bool timer_started; /** - * This field is the handle to the driver timer object. This timer is used to - * control when the directed attached disks can consume power. + * Timer to control when the directed attached disks can consume power. */ - void *timer; + struct sci_timer timer; /** * This field is used to keep track of how many phys are put into the -- cgit v1.2.3 From 6cb5853d3e252015eaf72d3761491e3da959556d Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 19 May 2011 11:59:56 +0000 Subject: isci: convert scic_timeout_timer to sci_timer Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 59 ++++++++++++++++++++++++++++-------------------- drivers/scsi/isci/host.h | 5 ++-- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 7b497f2667b7..156b37563761 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1115,7 +1115,7 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, scic_sds_controller_start_next_phy(scic); - isci_timer_start(scic->timeout_timer, timeout); + sci_mod_timer(&scic->timer, timeout); sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_STARTING); @@ -1296,7 +1296,7 @@ static enum sci_status scic_controller_stop(struct scic_sds_controller *scic, return SCI_FAILURE_INVALID_STATE; } - isci_timer_start(scic->timeout_timer, timeout); + sci_mod_timer(&scic->timer, timeout); sci_base_state_machine_change_state(&scic->state_machine, SCI_BASE_CONTROLLER_STATE_STOPPING); return SCI_SUCCESS; @@ -1376,6 +1376,8 @@ void isci_host_deinit(struct isci_host *ihost) del_timer_sync(&ihost->sci.power_control.timer.timer); + del_timer_sync(&ihost->sci.timer.timer); + isci_timer_list_destroy(ihost); } @@ -1433,7 +1435,7 @@ static inline void scic_sds_controller_starting_state_exit(struct sci_base_state { struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); - isci_timer_stop(scic->timeout_timer); + sci_del_timer(&scic->timer); } #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853 @@ -1669,7 +1671,7 @@ static void scic_sds_controller_stopping_state_exit(struct sci_base_state_machin { struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); - isci_timer_stop(scic->timeout_timer); + sci_del_timer(&scic->timer); } @@ -1776,7 +1778,33 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co scic->user_parameters.sds1.no_outbound_task_timeout = 20; } +static void controller_timeout(unsigned long data) +{ + struct sci_timer *tmr = (struct sci_timer *)data; + struct scic_sds_controller *scic = container_of(tmr, typeof(*scic), timer); + struct isci_host *ihost = scic_to_ihost(scic); + struct sci_base_state_machine *sm = &scic->state_machine; + unsigned long flags; + + spin_lock_irqsave(&ihost->scic_lock, flags); + + if (tmr->cancel) + goto done; + + if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) + scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT); + else if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STOPPING) { + sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_FAILED); + isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); + } else /* / @todo Now what do we want to do in this case? */ + dev_err(scic_to_dev(scic), + "%s: Controller timer fired when controller was not " + "in a state being timed.\n", + __func__); +done: + spin_unlock_irqrestore(&ihost->scic_lock, flags); +} /** * scic_controller_construct() - This method will attempt to construct a @@ -1826,6 +1854,8 @@ static enum sci_status scic_controller_construct(struct scic_sds_controller *sci scic->invalid_phy_mask = 0; + sci_init_timer(&scic->timer, controller_timeout); + /* Set the default maximum values */ scic->completion_event_entries = SCU_EVENT_COUNT; scic->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; @@ -1901,24 +1931,6 @@ void scic_oem_parameters_get( memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms)); } -static void scic_sds_controller_timeout_handler(void *_scic) -{ - struct scic_sds_controller *scic = _scic; - struct isci_host *ihost = scic_to_ihost(scic); - struct sci_base_state_machine *sm = &scic->state_machine; - - if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) - scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT); - else if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STOPPING) { - sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_FAILED); - isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); - } else /* / @todo Now what do we want to do in this case? */ - dev_err(scic_to_dev(scic), - "%s: Controller timer fired when controller was not " - "in a state being timed.\n", - __func__); -} - static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic) { struct isci_host *ihost = scic_to_ihost(scic); @@ -2246,9 +2258,6 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); - scic->timeout_timer = isci_timer_create(ihost, scic, - scic_sds_controller_timeout_handler); - scic_sds_controller_initialize_phy_startup(scic); scic_sds_controller_initialize_power_control(scic); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 2be935fa6af2..80808661ce5c 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -137,10 +137,9 @@ struct scic_sds_controller { struct sci_base_state_machine state_machine; /** - * This field is the driver timer object handler used to time the controller - * object start and stop requests. + * Timer for controller start/stop operations. */ - void *timeout_timer; + struct sci_timer timer; /** * This field contains the user parameters to be utilized for this -- cgit v1.2.3 From bb3dbdf6c835a145e46119ed18a920a774694583 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 19 May 2011 20:26:02 -0700 Subject: isci: convert phy_startup_timer to sci_timer Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 70 ++++++++++++++++++++---------------------------- drivers/scsi/isci/host.h | 11 ++++---- 2 files changed, 34 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 156b37563761..e79f35d510c7 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -917,21 +917,6 @@ static void scic_sds_controller_transition_to_ready( } } -static void scic_sds_controller_phy_timer_stop(struct scic_sds_controller *scic) -{ - isci_timer_stop(scic->phy_startup_timer); - - scic->phy_startup_timer_pending = false; -} - -static void scic_sds_controller_phy_timer_start(struct scic_sds_controller *scic) -{ - isci_timer_start(scic->phy_startup_timer, - SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT); - - scic->phy_startup_timer_pending = true; -} - static bool is_phy_starting(struct scic_sds_phy *sci_phy) { enum scic_sds_phy_states state; @@ -1008,7 +993,8 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro * Inform the SCI Core user and transition to the READY state. */ if (is_controller_start_complete == true) { scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS); - scic_sds_controller_phy_timer_stop(scic); + sci_del_timer(&scic->phy_timer); + scic->phy_startup_timer_pending = false; } } else { sci_phy = &ihost->phys[scic->next_phy_to_start].sci; @@ -1033,7 +1019,9 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro status = scic_sds_phy_start(sci_phy); if (status == SCI_SUCCESS) { - scic_sds_controller_phy_timer_start(scic); + sci_mod_timer(&scic->phy_timer, + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT); + scic->phy_startup_timer_pending = true; } else { dev_warn(scic_to_dev(scic), "%s: Controller stop operation failed " @@ -1050,15 +1038,27 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro return status; } -static void scic_sds_controller_phy_startup_timeout_handler(void *_scic) +static void phy_startup_timeout(unsigned long data) { - struct scic_sds_controller *scic = _scic; + struct sci_timer *tmr = (struct sci_timer *)data; + struct scic_sds_controller *scic = container_of(tmr, typeof(*scic), phy_timer); + struct isci_host *ihost = scic_to_ihost(scic); + unsigned long flags; enum sci_status status; + spin_lock_irqsave(&ihost->scic_lock, flags); + + if (tmr->cancel) + goto done; + scic->phy_startup_timer_pending = false; - status = SCI_FAILURE; - while (status != SCI_SUCCESS) + + do { status = scic_sds_controller_start_next_phy(scic); + } while (status != SCI_SUCCESS); + +done: + spin_unlock_irqrestore(&ihost->scic_lock, flags); } static enum sci_status scic_controller_start(struct scic_sds_controller *scic, @@ -1378,6 +1378,8 @@ void isci_host_deinit(struct isci_host *ihost) del_timer_sync(&ihost->sci.timer.timer); + del_timer_sync(&ihost->sci.phy_timer.timer); + isci_timer_list_destroy(ihost); } @@ -1931,24 +1933,6 @@ void scic_oem_parameters_get( memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms)); } -static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic) -{ - struct isci_host *ihost = scic_to_ihost(scic); - - scic->phy_startup_timer = isci_timer_create(ihost, - scic, - scic_sds_controller_phy_startup_timeout_handler); - - if (scic->phy_startup_timer == NULL) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; - else { - scic->next_phy_to_start = 0; - scic->phy_startup_timer_pending = false; - } - - return SCI_SUCCESS; -} - static void power_control_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; @@ -2258,7 +2242,10 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); - scic_sds_controller_initialize_phy_startup(scic); + sci_init_timer(&scic->phy_timer, phy_startup_timeout); + + scic->next_phy_to_start = 0; + scic->phy_startup_timer_pending = false; scic_sds_controller_initialize_power_control(scic); @@ -2640,7 +2627,8 @@ void scic_sds_controller_link_up(struct scic_sds_controller *scic, { switch (scic->state_machine.current_state_id) { case SCI_BASE_CONTROLLER_STATE_STARTING: - scic_sds_controller_phy_timer_stop(scic); + sci_del_timer(&scic->phy_timer); + scic->phy_startup_timer_pending = false; scic->port_agent.link_up_handler(scic, &scic->port_agent, port, phy); scic_sds_controller_start_next_phy(scic); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 80808661ce5c..9fd47b42da05 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -271,15 +271,14 @@ struct scic_sds_controller { /* Phy Startup Data */ /** - * This field is the driver timer handle for controller phy request startup. - * On controller start the controller will start each PHY individually in - * order of phy index. + * Timer for controller phy request startup. On controller start the + * controller will start each PHY individually in order of phy index. */ - void *phy_startup_timer; + struct sci_timer phy_timer; /** - * This field is set when the phy_startup_timer is running and is cleared when - * the phy_startup_timer is stopped. + * This field is set when the phy_timer is running and is cleared when + * the phy_timer is stopped. */ bool phy_startup_timer_pending; -- cgit v1.2.3 From fd18388bc5820b3e7807302ac18e8e7de83c9f4c Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 19 May 2011 12:00:15 +0000 Subject: isci: Remove tmf timeout_timer Replace the timeout_timer in the isci_tmf with a call to wait_for_completion_timeout Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 105 +++++++++-------------------------------------- drivers/scsi/isci/task.h | 2 - 2 files changed, 20 insertions(+), 87 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 078e2ee4f4be..60b687b77d56 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -338,54 +338,6 @@ static enum sci_status isci_task_request_build( return status; } -/** - * isci_tmf_timeout_cb() - This function is called as a kernel callback when - * the timeout period for the TMF has expired. - * - * - */ -static void isci_tmf_timeout_cb(void *tmf_request_arg) -{ - struct isci_request *request = (struct isci_request *)tmf_request_arg; - struct isci_tmf *tmf = isci_request_access_tmf(request); - enum sci_status status; - - /* This task management request has timed-out. Terminate the request - * so that the request eventually completes to the requestor in the - * request completion callback path. - */ - /* Note - the timer callback function itself has provided spinlock - * exclusion from the start and completion paths. No need to take - * the request->isci_host->scic_lock here. - */ - - if (tmf->timeout_timer != NULL) { - /* Call the users callback, if any. */ - if (tmf->cb_state_func != NULL) - tmf->cb_state_func(isci_tmf_timed_out, tmf, - tmf->cb_data); - - /* Terminate the TMF transmit request. */ - status = scic_controller_terminate_request( - &request->isci_host->sci, - &request->isci_device->sci, - &request->sci); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: tmf_request = %p; tmf = %p; status = %d\n", - __func__, request, tmf, status); - } else - dev_dbg(&request->isci_host->pdev->dev, - "%s: timer already canceled! " - "tmf_request = %p; tmf = %p\n", - __func__, request, tmf); - - /* No need to unlock since the caller to this callback is doing it for - * us. - * request->isci_host->scic_lock - */ -} - /** * isci_task_execute_tmf() - This function builds and sends a task request, * then waits for the completion. @@ -410,6 +362,7 @@ int isci_task_execute_tmf( struct isci_request *request; int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; + unsigned long timeleft; /* sanity check, return TMF_RESP_FUNC_FAILED * if the device is not there and ready. @@ -443,17 +396,7 @@ int isci_task_execute_tmf( return TMF_RESP_FUNC_FAILED; } - /* Allocate the TMF timeout timer. */ spin_lock_irqsave(&isci_host->scic_lock, flags); - tmf->timeout_timer = isci_timer_create(isci_host, request, isci_tmf_timeout_cb); - - /* Start the timer. */ - if (tmf->timeout_timer) - isci_timer_start(tmf->timeout_timer, timeout_ms); - else - dev_warn(&isci_host->pdev->dev, - "%s: isci_timer_create failed!!!!\n", - __func__); /* start the TMF io. */ status = scic_controller_start_task( @@ -468,14 +411,13 @@ int isci_task_execute_tmf( __func__, status, request); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); goto cleanup_request; } - /* Call the users callback, if any. */ if (tmf->cb_state_func != NULL) tmf->cb_state_func(isci_tmf_started, tmf, tmf->cb_data); - /* Change the state of the TMF-bearing request to "started". */ isci_request_change_state(request, started); /* add the request to the remote device request list. */ @@ -484,7 +426,22 @@ int isci_task_execute_tmf( spin_unlock_irqrestore(&isci_host->scic_lock, flags); /* Wait for the TMF to complete, or a timeout. */ - wait_for_completion(&completion); + timeleft = wait_for_completion_timeout(&completion, + jiffies + msecs_to_jiffies(timeout_ms)); + + if (timeleft == 0) { + spin_lock_irqsave(&isci_host->scic_lock, flags); + + if (tmf->cb_state_func != NULL) + tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); + + status = scic_controller_terminate_request( + &request->isci_host->sci, + &request->isci_device->sci, + &request->sci); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + } isci_print_tmf(tmf); @@ -505,28 +462,12 @@ int isci_task_execute_tmf( request); if (request->io_request_completion != NULL) { - - /* The fact that this is non-NULL for a TMF request - * means there is a thread waiting for this TMF to - * finish. - */ + /* A thread is waiting for this TMF to finish. */ complete(request->io_request_completion); } - spin_lock_irqsave(&isci_host->scic_lock, flags); - cleanup_request: - - /* Clean up the timer if needed. */ - if (tmf->timeout_timer) { - isci_del_timer(isci_host, tmf->timeout_timer); - tmf->timeout_timer = NULL; - } - - spin_unlock_irqrestore(&isci_host->scic_lock, flags); - isci_request_free(isci_host, request); - return ret; } @@ -546,7 +487,7 @@ void isci_task_build_tmf( tmf->device = isci_device; tmf->tmf_code = code; - tmf->timeout_timer = NULL; + tmf->cb_state_func = tmf_sent_cb; tmf->cb_data = cb_data; } @@ -1442,12 +1383,6 @@ isci_task_request_complete(struct isci_host *ihost, sizeof(struct dev_to_host_fis)); } - /* Manage the timer if it is still running. */ - if (tmf->timeout_timer) { - isci_del_timer(ihost, tmf->timeout_timer); - tmf->timeout_timer = NULL; - } - /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index c59dc9620cf9..432b81aecd47 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -107,8 +107,6 @@ struct isci_tmf { enum isci_tmf_function_codes tmf_code; int status; - struct isci_timer *timeout_timer; - /* The optional callback function allows the user process to * track the TMF transmit / timeout conditions. */ -- cgit v1.2.3 From 8db02da52895285e99d7eb2fa825fd393e61d9c5 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 19 May 2011 12:00:22 +0000 Subject: isci: remove isci_timer interface Delete code which is no longer used. Signed-off-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 2 +- drivers/scsi/isci/host.c | 13 --- drivers/scsi/isci/host.h | 1 - drivers/scsi/isci/phy.c | 1 - drivers/scsi/isci/port.c | 1 - drivers/scsi/isci/port_config.c | 1 - drivers/scsi/isci/task.c | 1 - drivers/scsi/isci/timers.c | 245 ---------------------------------------- drivers/scsi/isci/timers.h | 88 --------------- 9 files changed, 1 insertion(+), 352 deletions(-) delete mode 100644 drivers/scsi/isci/timers.c delete mode 100644 drivers/scsi/isci/timers.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 86b0c88e91a6..ad58fe3acc72 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ - remote_device.o port.o timers.o \ + remote_device.o port.o \ host.o task.o probe_roms.o \ state_machine.o \ remote_node_context.o \ diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index e79f35d510c7..8801955be213 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -67,7 +67,6 @@ #include "scu_remote_node_context.h" #include "scu_task_context.h" #include "scu_unsolicited_frame.h" -#include "timers.h" #define SCU_CONTEXT_RAM_INIT_STALL_TIME 200 @@ -111,14 +110,6 @@ ) -#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3 -#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3 - -/** - * - * - * The number of milliseconds to wait for a phy to start. - */ #define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100 /** @@ -1379,8 +1370,6 @@ void isci_host_deinit(struct isci_host *ihost) del_timer_sync(&ihost->sci.timer.timer); del_timer_sync(&ihost->sci.phy_timer.timer); - - isci_timer_list_destroy(ihost); } static void __iomem *scu_base(struct isci_host *isci_host) @@ -2517,8 +2506,6 @@ int isci_host_init(struct isci_host *isci_host) union scic_user_parameters scic_user_params; struct isci_pci_info *pci_info = to_pci_info(isci_host->pdev); - isci_timer_list_construct(isci_host); - spin_lock_init(&isci_host->state_lock); spin_lock_init(&isci_host->scic_lock); spin_lock_init(&isci_host->queue_lock); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 9fd47b42da05..4ce39e1803ff 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -325,7 +325,6 @@ struct isci_host { union scic_oem_parameters oem_parameters; int id; /* unique within a given pci device */ - struct list_head timers; void *core_ctrl_memory; struct dma_pool *dma_pool; struct isci_phy phys[SCI_MAX_PHYS]; diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index b663bbdd4e59..fc196e389ffb 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -57,7 +57,6 @@ #include "host.h" #include "phy.h" #include "scu_event_codes.h" -#include "timers.h" #include "probe_roms.h" /* Maximum arbitration wait time in micro-seconds */ diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 3da9048b45b7..8d88ca21a51c 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -56,7 +56,6 @@ #include "isci.h" #include "port.h" #include "request.h" -#include "timers.h" #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) #define SCU_DUMMY_INDEX (0xFFFF) diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index 1cde7b9165f4..38401f644e18 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -54,7 +54,6 @@ */ #include "host.h" -#include "timers.h" #define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) #define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 60b687b77d56..93c75560a5c7 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -62,7 +62,6 @@ #include "request.h" #include "sata.h" #include "task.h" -#include "timers.h" /** * isci_task_refuse() - complete the request to the upper layer driver in diff --git a/drivers/scsi/isci/timers.c b/drivers/scsi/isci/timers.c deleted file mode 100644 index 007700e3eb6a..000000000000 --- a/drivers/scsi/isci/timers.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "isci.h" -#include "timers.h" -#include "host.h" - -/** - * isci_timer_list_construct() - This method contrucst the SCI Timer List - * object used by the SCI Module class. The construction process involves - * creating isci_timer objects and adding them to the SCI Timer List - * object's list member. The number of isci_timer objects is determined by - * the timer_list_size parameter. - * @ihost: container of the timer list - * - * This method returns an error code indicating sucess or failure. The user - * should check for possible memory allocation error return otherwise, a zero - * indicates success. - */ -int isci_timer_list_construct(struct isci_host *ihost) -{ - struct isci_timer *itimer; - int i, err = 0; - - INIT_LIST_HEAD(&ihost->timers); - for (i = 0; i < SCI_MAX_TIMER_COUNT; i++) { - itimer = devm_kzalloc(&ihost->pdev->dev, sizeof(*itimer), GFP_KERNEL); - - if (!itimer) { - err = -ENOMEM; - break; - } - init_timer(&itimer->timer); - itimer->used = 0; - itimer->stopped = 1; - list_add(&itimer->node, &ihost->timers); - } - - return err; -} - -/** - * isci_timer_list_destroy() - This method destroys the SCI Timer List object - * used by the SCI Module class. The destruction process involves freeing - * memory allocated for isci_timer objects on the SCI Timer List object's - * timers list_head member. If any isci_timer objects are mark as "in use", - * they are not freed and the function returns an error code of -EBUSY. - * @ihost: container of the list to be destroyed - */ -void isci_timer_list_destroy(struct isci_host *ihost) -{ - struct isci_timer *timer; - LIST_HEAD(list); - - spin_lock_irq(&ihost->scic_lock); - list_splice_init(&ihost->timers, &list); - spin_unlock_irq(&ihost->scic_lock); - - list_for_each_entry(timer, &list, node) - del_timer_sync(&timer->timer); -} - -/** - * This method pulls an isci_timer object off of the list for the SCI Timer - * List object specified, marks the isci_timer as "in use" and initializes - * it with user callback function and cookie data. The timer is not start at - * this time, just reserved for the user. - * @isci_timer_list: This parameter points to the SCI Timer List from which the - * timer is reserved. - * @cookie: This parameter specifies a piece of information that the user must - * retain. This cookie is to be supplied by the user anytime a timeout - * occurs for the created timer. - * @timer_callback: This parameter specifies the callback method to be invoked - * whenever the timer expires. - * - * This method returns a pointer to an isci_timer object reserved from the SCI - * Timer List. The pointer will be utilized for all further interactions - * relating to this timer. - */ - -static void timer_function(unsigned long data) -{ - - struct isci_timer *timer = (struct isci_timer *)data; - struct isci_host *isci_host = timer->isci_host; - unsigned long flags; - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_timer = %p\n", __func__, timer); - - if (isci_stopped == isci_host_get_state(isci_host)) { - timer->stopped = 1; - return; - } - - spin_lock_irqsave(&isci_host->scic_lock, flags); - - if (!timer->stopped) { - timer->stopped = 1; - timer->timer_callback(timer->cb_param); - } - - spin_unlock_irqrestore(&isci_host->scic_lock, flags); -} - - -struct isci_timer *isci_timer_create(struct isci_host *ihost, void *cb_param, - void (*timer_callback)(void *)) -{ - struct timer_list *timer; - struct isci_timer *isci_timer; - struct list_head *list = &ihost->timers; - - WARN_ONCE(!spin_is_locked(&ihost->scic_lock), - "%s: unlocked!\n", __func__); - - if (WARN_ONCE(list_empty(list), "%s: timer pool empty\n", __func__)) - return NULL; - - isci_timer = list_entry(list->next, struct isci_timer, node); - - isci_timer->used = 1; - isci_timer->stopped = 1; - /* FIXME: what!? we recycle the timer, rather than take it off - * the free list? - */ - list_move_tail(&isci_timer->node, list); - - timer = &isci_timer->timer; - timer->data = (unsigned long)isci_timer; - timer->function = timer_function; - isci_timer->cb_param = cb_param; - isci_timer->timer_callback = timer_callback; - isci_timer->isci_host = ihost; - - dev_dbg(&ihost->pdev->dev, - "%s: isci_timer = %p\n", __func__, isci_timer); - - return isci_timer; -} - -/* isci_del_timer() - This method frees the isci_timer, marking it "free to - * use", then places its back at the head of the timers list for the SCI - * Timer List object specified. - */ -void isci_del_timer(struct isci_host *ihost, struct isci_timer *isci_timer) -{ - struct list_head *list = &ihost->timers; - - WARN_ONCE(!spin_is_locked(&ihost->scic_lock), - "%s unlocked!\n", __func__); - - dev_dbg(&isci_timer->isci_host->pdev->dev, - "%s: isci_timer = %p\n", __func__, isci_timer); - - isci_timer->used = 0; - list_move(&isci_timer->node, list); - del_timer(&isci_timer->timer); - isci_timer->stopped = 1; -} - -/** - * isci_timer_start() - This method starts the specified isci_timer, with the - * specified timeout value. - * @isci_timer: This parameter specifies the timer to be started. - * @timeout: This parameter specifies the timeout, in milliseconds, after which - * the associated callback function will be called. - * - */ -void isci_timer_start(struct isci_timer *isci_timer, unsigned long tmo) -{ - struct timer_list *timer = &isci_timer->timer; - - dev_dbg(&isci_timer->isci_host->pdev->dev, - "%s: isci_timer = %p\n", __func__, isci_timer); - - isci_timer->stopped = 0; - mod_timer(timer, jiffies + msecs_to_jiffies(tmo)); -} - -/** - * isci_timer_stop() - This method stops the supplied isci_timer. - * @isci_timer: This parameter specifies the isci_timer to be stopped. - * - */ -void isci_timer_stop(struct isci_timer *isci_timer) -{ - dev_dbg(&isci_timer->isci_host->pdev->dev, - "%s: isci_timer = %p\n", __func__, isci_timer); - - isci_timer->stopped = 1; - del_timer(&isci_timer->timer); -} diff --git a/drivers/scsi/isci/timers.h b/drivers/scsi/isci/timers.h deleted file mode 100644 index 8d8a892ad7f2..000000000000 --- a/drivers/scsi/isci/timers.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if !defined(_SCI_TIMER_H_) -#define _SCI_TIMER_H_ - -#include -#include - -#define SCI_MAX_TIMER_COUNT 25 - -/** - * struct isci_timer - This class represents the timer object used by SCIC. It - * wraps the Linux timer_list object, and (TODO) should be removed in favor - * of a delayed-workqueue style interface with simpler locking - * - */ -struct isci_timer { - int used; - int stopped; - void *cb_param; - void (*timer_callback)(void *); - struct list_head node; - struct timer_list timer; - struct isci_host *isci_host; -}; - -int isci_timer_list_construct(struct isci_host *ihost); -void isci_timer_list_destroy(struct isci_host *ihost); -struct isci_timer *isci_timer_create(struct isci_host *ihost, void *cb_param, - void (*timer_callback)(void *)); -void isci_del_timer(struct isci_host *ihost, struct isci_timer *itimer); -void isci_timer_start(struct isci_timer *isci_timer, unsigned long timeout); -void isci_timer_stop(struct isci_timer *isci_timer); - -#endif /* !defined (_SCI_TIMER_H_) */ -- cgit v1.2.3 From 77d67385f7b4a630912fd567f104946be137f477 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 25 May 2011 02:21:57 +0000 Subject: isci: removing the kmalloc in smp request construct It doesn't look like there is any reason to do a kmalloc. We can do the byte swap in place and avoid the allocation. This allow us to remove a kmalloc and a memcpy. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 063ef04080d5..7c0928ed9e63 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -3187,7 +3187,7 @@ static enum sci_status isci_request_stp_request_construct( */ static void scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, - struct smp_req *smp_req) + ssize_t req_len) { dma_addr_t dma_addr; struct scic_sds_controller *scic; @@ -3197,7 +3197,7 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); /* byte swap the smp request. */ - sci_swab32_cpy(&sci_req->smp.cmd, smp_req, + sci_swab32_cpy(&sci_req->smp.cmd, &sci_req->smp.cmd, word_cnt); task_context = scic_sds_request_get_task_context(sci_req); @@ -3238,7 +3238,7 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, task_context->address_modifier = 0; /* 10h */ - task_context->ssp_command_iu_length = smp_req->req_len; + task_context->ssp_command_iu_length = req_len; /* 14h */ task_context->transfer_length_bytes = 0; @@ -3299,22 +3299,18 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, task_context->response_iu_lower = 0; } -static enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req) +static enum sci_status +scic_io_request_construct_smp(struct scic_sds_request *sci_req) { - struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); - - if (!smp_req) - return SCI_FAILURE_INSUFFICIENT_RESOURCES; + struct smp_req *smp_req = &sci_req->smp.cmd; sci_req->protocol = SCIC_SMP_PROTOCOL; - /* Construct the SMP SCU Task Context */ - memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req)); - /* * Look at the SMP requests' header fields; for certain SAS 1.x SMP * functions under SAS 2.0, a zero request length really indicates - * a non-zero default length. */ + * a non-zero default length. + */ if (smp_req->req_len == 0) { switch (smp_req->func) { case SMP_DISCOVER: @@ -3332,12 +3328,10 @@ static enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sc } } - scu_smp_request_construct_task_context(sci_req, smp_req); + scu_smp_request_construct_task_context(sci_req, smp_req->req_len); sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); - - kfree(smp_req); + SCI_BASE_REQUEST_STATE_CONSTRUCTED); return SCI_SUCCESS; } -- cgit v1.2.3 From bf482c6069b514b7fe57a048ae1b6f11cf3bb10c Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 25 May 2011 05:04:35 +0000 Subject: isci: Retrieve the EFI variable for OEM parameter We can call the EFI get_variable service routine directly to retrieve the EFI variable that holds the OEM parameters table. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/probe_roms.c | 73 +++++++++++++----------------------------- drivers/scsi/isci/probe_roms.h | 2 +- 2 files changed, 24 insertions(+), 51 deletions(-) diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 9bc173fa49e1..084fdc60548f 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -34,14 +34,8 @@ #include "task.h" #include "probe_roms.h" -struct efi_variable { - efi_char16_t VariableName[1024/sizeof(efi_char16_t)]; - efi_guid_t VendorGuid; - unsigned long DataSize; - __u8 Data[1024]; - efi_status_t Status; - __u32 Attributes; -} __attribute__((packed)); +static efi_char16_t isci_efivar_name[] = + {'R', 's', 't', 'S', 'c', 'u', 'O'}; struct isci_orom *isci_request_oprom(struct pci_dev *pdev) { @@ -169,62 +163,50 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw static struct efi *get_efi(void) { - #ifdef CONFIG_EFI +#ifdef CONFIG_EFI return &efi; - #else +#else return NULL; - #endif +#endif } struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) { - struct efi_variable *evar; efi_status_t status; - struct isci_orom *rom = NULL; + struct isci_orom *rom; struct isci_oem_hdr *oem_hdr; u8 *tmp, sum; int j; - size_t copy_len; + ssize_t data_len; + u8 *efi_data; + u32 efi_attrib = 0; - evar = devm_kzalloc(&pdev->dev, - sizeof(struct efi_variable), - GFP_KERNEL); - if (!evar) { + data_len = 1024; + efi_data = devm_kzalloc(&pdev->dev, data_len, GFP_KERNEL); + if (!efi_data) { dev_warn(&pdev->dev, - "Unable to allocate memory for EFI var\n"); + "Unable to allocate memory for EFI data\n"); return NULL; } - rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); - if (!rom) { - dev_warn(&pdev->dev, - "Unable to allocate memory for orom\n"); - return NULL; - } - - for (j = 0; j < strlen(ISCI_EFI_VAR_NAME) + 1; j++) - evar->VariableName[j] = ISCI_EFI_VAR_NAME[j]; - - evar->DataSize = 1024; - evar->VendorGuid = ISCI_EFI_VENDOR_GUID; - evar->Attributes = ISCI_EFI_ATTRIBUTES; + rom = (struct isci_orom *)(efi_data + sizeof(struct isci_oem_hdr)); if (get_efi()) - status = get_efi()->get_variable(evar->VariableName, - &evar->VendorGuid, - &evar->Attributes, - &evar->DataSize, - evar->Data); + status = get_efi()->get_variable(isci_efivar_name, + &ISCI_EFI_VENDOR_GUID, + &efi_attrib, + &data_len, + efi_data); else status = EFI_NOT_FOUND; if (status != EFI_SUCCESS) { dev_warn(&pdev->dev, - "Unable to obtain EFI variable for OEM parms\n"); + "Unable to obtain EFI var data for OEM parms\n"); return NULL; } - oem_hdr = (struct isci_oem_hdr *)evar->Data; + oem_hdr = (struct isci_oem_hdr *)efi_data; if (memcmp(oem_hdr->sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) != 0) { dev_warn(&pdev->dev, @@ -233,12 +215,8 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) } /* calculate checksum */ - tmp = (u8 *)oem_hdr; - for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++) - sum += *tmp; - - tmp = (u8 *)rom; - for (j = 0; j < sizeof(*rom); j++, tmp++) + tmp = (u8 *)efi_data; + for (j = 0, sum = 0; j < (sizeof(*oem_hdr) + sizeof(*rom)); j++, tmp++) sum += *tmp; if (sum != 0) { @@ -247,11 +225,6 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) return NULL; } - copy_len = min_t(u16, evar->DataSize, - min_t(u16, oem_hdr->len - sizeof(*oem_hdr), sizeof(*rom))); - - memcpy(rom, (char *)evar->Data + sizeof(*oem_hdr), copy_len); - if (memcmp(rom->hdr.signature, ISCI_ROM_SIG, ISCI_ROM_SIG_SIZE) != 0) { diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 7e3e6d7a0a47..95c8d91aab8d 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -58,6 +58,7 @@ #ifdef __KERNEL__ #include #include +#include #include "isci.h" #define SCIC_SDS_PARM_NO_SPEED 0 @@ -202,7 +203,6 @@ struct isci_oem_hdr { #define ISCI_EFI_VENDOR_GUID \ EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \ 0x1a, 0x04, 0xc6) -#define ISCI_EFI_ATTRIBUTES 0 #define ISCI_EFI_VAR_NAME "RstScuO" /* Allowed PORT configuration modes APC Automatic PORT configuration mode is -- cgit v1.2.3 From 8d2c65c09c9e0adc16070562e7944c1c3277f332 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 1 Jun 2011 09:03:08 +0000 Subject: isci: Removing unused variables compiler warnings Newer gcc's are better at identifying "set, but not used" variables. Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 8 -------- drivers/scsi/isci/task.c | 3 +-- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 7c0928ed9e63..31c9b2c34259 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -211,11 +211,9 @@ static void scu_ssp_reqeust_construct_task_context( struct scu_task_context *task_context) { dma_addr_t dma_addr; - struct scic_sds_controller *controller; struct scic_sds_remote_device *target_device; struct scic_sds_port *target_port; - controller = scic_sds_request_get_controller(sds_request); target_device = scic_sds_request_get_device(sds_request); target_port = scic_sds_request_get_port(sds_request); @@ -384,11 +382,9 @@ static void scu_sata_reqeust_construct_task_context( struct scu_task_context *task_context) { dma_addr_t dma_addr; - struct scic_sds_controller *controller; struct scic_sds_remote_device *target_device; struct scic_sds_port *target_port; - controller = scic_sds_request_get_controller(sci_req); target_device = scic_sds_request_get_device(sci_req); target_port = scic_sds_request_get_port(sci_req); @@ -677,12 +673,10 @@ enum sci_status scic_task_request_construct_ssp( static enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_request *sci_req) { enum sci_status status; - struct scic_sds_stp_request *stp_req; bool copy = false; struct isci_request *isci_request = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(isci_request); - stp_req = &sci_req->stp.req; sci_req->protocol = SCIC_STP_PROTOCOL; copy = (task->data_dir == DMA_NONE) ? false : true; @@ -3190,7 +3184,6 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, ssize_t req_len) { dma_addr_t dma_addr; - struct scic_sds_controller *scic; struct scic_sds_remote_device *sci_dev; struct scic_sds_port *sci_port; struct scu_task_context *task_context; @@ -3202,7 +3195,6 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, task_context = scic_sds_request_get_task_context(sci_req); - scic = scic_sds_request_get_controller(sci_req); sci_dev = scic_sds_request_get_device(sci_req); sci_port = scic_sds_request_get_port(sci_req); diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 93c75560a5c7..b54ef2b0fca1 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1358,7 +1358,6 @@ isci_task_request_complete(struct isci_host *ihost, enum sci_task_status completion_status) { struct isci_remote_device *idev = ireq->isci_device; - enum isci_request_status old_state; struct isci_tmf *tmf = isci_request_access_tmf(ireq); struct completion *tmf_complete; struct scic_sds_request *sci_req = &ireq->sci; @@ -1367,7 +1366,7 @@ isci_task_request_complete(struct isci_host *ihost, "%s: request = %p, status=%d\n", __func__, ireq, completion_status); - old_state = isci_request_change_state(ireq, completed); + isci_request_change_state(ireq, completed); tmf->status = completion_status; ireq->complete_in_target = true; -- cgit v1.2.3 From e301370ac553a9a0ac0d1d25e769b86cf60395b3 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 2 Jun 2011 00:10:43 +0000 Subject: isci: state machine cleanup This cleans up several areas of the state machine mechanism: o Rename sci_base_state_machine_change_state to sci_change_state o Remove sci_base_state_machine_get_state function o Rename 'state_machine' struct member to 'sm' in client structs o Shorten the name of request states o Shorten state machine state names as follows: SCI_BASE_CONTROLLER_STATE_xxx to SCIC_xxx SCI_BASE_PHY_STATE_xxx to SCI_PHY_xxx SCIC_SDS_PHY_STARTING_SUBSTATE_xxx to SCI_PHY_SUB_xxx SCI_BASE_PORT_STATE_xxx to SCI_PORT_xxx and SCIC_SDS_PORT_READY_SUBSTATE_xxx to SCI_PORT_SUB_xxx SCI_BASE_REMOTE_DEVICE_STATE_xxx to SCI_DEV_xxx SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_xxx to SCI_STP_DEV_xxx SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_xxx to SCI_SMP_DEV_xxx SCIC_SDS_REMOTE_NODE_CONTEXT_xxx_STATE to SCI_RNC_xxx Signed-off-by: Edmund Nadolski Signed-off-by: Dave Jiang Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 201 +++++------ drivers/scsi/isci/host.h | 25 +- drivers/scsi/isci/phy.c | 244 ++++++------- drivers/scsi/isci/phy.h | 34 +- drivers/scsi/isci/port.c | 186 +++++----- drivers/scsi/isci/port.h | 18 +- drivers/scsi/isci/port_config.c | 4 +- drivers/scsi/isci/remote_device.c | 349 ++++++++++--------- drivers/scsi/isci/remote_device.h | 34 +- drivers/scsi/isci/remote_node_context.c | 154 ++++----- drivers/scsi/isci/remote_node_context.h | 18 +- drivers/scsi/isci/request.c | 582 +++++++++++++++++--------------- drivers/scsi/isci/request.h | 357 ++++++++++---------- drivers/scsi/isci/state_machine.c | 26 +- drivers/scsi/isci/state_machine.h | 4 +- 15 files changed, 1076 insertions(+), 1160 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 8801955be213..81ee64c0a4b7 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -635,8 +635,7 @@ static void scic_sds_controller_error_handler(struct scic_sds_controller *scic) dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, interrupt_status); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_FAILED); + sci_change_state(&scic->sm, SCIC_FAILED); return; } @@ -895,14 +894,12 @@ static void scic_sds_controller_transition_to_ready( { struct isci_host *ihost = scic_to_ihost(scic); - if (scic->state_machine.current_state_id == - SCI_BASE_CONTROLLER_STATE_STARTING) { + if (scic->sm.current_state_id == SCIC_STARTING) { /* * We move into the ready state, because some of the phys/ports * may be up and operational. */ - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_READY); + sci_change_state(&scic->sm, SCIC_READY); isci_host_start_complete(ihost, status); } @@ -912,18 +909,18 @@ static bool is_phy_starting(struct scic_sds_phy *sci_phy) { enum scic_sds_phy_states state; - state = sci_phy->state_machine.current_state_id; + state = sci_phy->sm.current_state_id; switch (state) { - case SCI_BASE_PHY_STATE_STARTING: - case SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: - case SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL: + case SCI_PHY_STARTING: + case SCI_PHY_SUB_INITIAL: + case SCI_PHY_SUB_AWAIT_SAS_SPEED_EN: + case SCI_PHY_SUB_AWAIT_IAF_UF: + case SCI_PHY_SUB_AWAIT_SAS_POWER: + case SCI_PHY_SUB_AWAIT_SATA_POWER: + case SCI_PHY_SUB_AWAIT_SATA_PHY_EN: + case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN: + case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: + case SCI_PHY_SUB_FINAL: return true; default: return false; @@ -957,7 +954,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro for (index = 0; index < SCI_MAX_PHYS; index++) { sci_phy = &ihost->phys[index].sci; - state = sci_phy->state_machine.current_state_id; + state = sci_phy->sm.current_state_id; if (!phy_get_non_dummy_port(sci_phy)) continue; @@ -968,12 +965,9 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro * - have an indication of a connected device and it has * finished the link training process. */ - if ((sci_phy->is_in_link_training == false && - state == SCI_BASE_PHY_STATE_INITIAL) || - (sci_phy->is_in_link_training == false && - state == SCI_BASE_PHY_STATE_STOPPED) || - (sci_phy->is_in_link_training == true && - is_phy_starting(sci_phy))) { + if ((sci_phy->is_in_link_training == false && state == SCI_PHY_INITIAL) || + (sci_phy->is_in_link_training == false && state == SCI_PHY_STOPPED) || + (sci_phy->is_in_link_training == true && is_phy_starting(sci_phy))) { is_controller_start_complete = false; break; } @@ -1059,8 +1053,7 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, enum sci_status result; u16 index; - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_INITIALIZED) { + if (scic->sm.current_state_id != SCIC_INITIALIZED) { dev_warn(scic_to_dev(scic), "SCIC Controller start operation requested in " "invalid state\n"); @@ -1108,8 +1101,7 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, sci_mod_timer(&scic->timer, timeout); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_STARTING); + sci_change_state(&scic->sm, SCIC_STARTING); return SCI_SUCCESS; } @@ -1279,8 +1271,7 @@ static void isci_host_completion_routine(unsigned long data) static enum sci_status scic_controller_stop(struct scic_sds_controller *scic, u32 timeout) { - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { + if (scic->sm.current_state_id != SCIC_READY) { dev_warn(scic_to_dev(scic), "SCIC Controller stop operation requested in " "invalid state\n"); @@ -1288,8 +1279,7 @@ static enum sci_status scic_controller_stop(struct scic_sds_controller *scic, } sci_mod_timer(&scic->timer, timeout); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_STOPPING); + sci_change_state(&scic->sm, SCIC_STOPPING); return SCI_SUCCESS; } @@ -1307,17 +1297,16 @@ static enum sci_status scic_controller_stop(struct scic_sds_controller *scic, */ static enum sci_status scic_controller_reset(struct scic_sds_controller *scic) { - switch (scic->state_machine.current_state_id) { - case SCI_BASE_CONTROLLER_STATE_RESET: - case SCI_BASE_CONTROLLER_STATE_READY: - case SCI_BASE_CONTROLLER_STATE_STOPPED: - case SCI_BASE_CONTROLLER_STATE_FAILED: + switch (scic->sm.current_state_id) { + case SCIC_RESET: + case SCIC_READY: + case SCIC_STOPPED: + case SCIC_FAILED: /* * The reset operation is not a graceful cleanup, just * perform the state transition. */ - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_RESETTING); + sci_change_state(&scic->sm, SCIC_RESETTING); return SCI_SUCCESS; default: dev_warn(scic_to_dev(scic), @@ -1416,15 +1405,14 @@ static void isci_user_parameters_get( static void scic_sds_controller_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_RESET); + sci_change_state(&scic->sm, SCIC_RESET); } static inline void scic_sds_controller_starting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); sci_del_timer(&scic->timer); } @@ -1551,7 +1539,7 @@ static enum sci_status scic_controller_set_interrupt_coalescence( static void scic_sds_controller_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); /* set the default interrupt coalescence number and timeout value. */ scic_controller_set_interrupt_coalescence(scic, 0x10, 250); @@ -1559,7 +1547,7 @@ static void scic_sds_controller_ready_state_enter(struct sci_base_state_machine static void scic_sds_controller_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); /* disable interrupt coalescence. */ scic_controller_set_interrupt_coalescence(scic, 0, 0); @@ -1650,7 +1638,7 @@ static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controll static void scic_sds_controller_stopping_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); /* Stop all of the components for this controller */ scic_sds_controller_stop_phys(scic); @@ -1660,7 +1648,7 @@ static void scic_sds_controller_stopping_state_enter(struct sci_base_state_machi static void scic_sds_controller_stopping_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); sci_del_timer(&scic->timer); } @@ -1691,36 +1679,35 @@ static void scic_sds_controller_reset_hardware(struct scic_sds_controller *scic) static void scic_sds_controller_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), state_machine); + struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); scic_sds_controller_reset_hardware(scic); - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_RESET); + sci_change_state(&scic->sm, SCIC_RESET); } static const struct sci_base_state scic_sds_controller_state_table[] = { - [SCI_BASE_CONTROLLER_STATE_INITIAL] = { + [SCIC_INITIAL] = { .enter_state = scic_sds_controller_initial_state_enter, }, - [SCI_BASE_CONTROLLER_STATE_RESET] = {}, - [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {}, - [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {}, - [SCI_BASE_CONTROLLER_STATE_STARTING] = { + [SCIC_RESET] = {}, + [SCIC_INITIALIZING] = {}, + [SCIC_INITIALIZED] = {}, + [SCIC_STARTING] = { .exit_state = scic_sds_controller_starting_state_exit, }, - [SCI_BASE_CONTROLLER_STATE_READY] = { + [SCIC_READY] = { .enter_state = scic_sds_controller_ready_state_enter, .exit_state = scic_sds_controller_ready_state_exit, }, - [SCI_BASE_CONTROLLER_STATE_RESETTING] = { + [SCIC_RESETTING] = { .enter_state = scic_sds_controller_resetting_state_enter, }, - [SCI_BASE_CONTROLLER_STATE_STOPPING] = { + [SCIC_STOPPING] = { .enter_state = scic_sds_controller_stopping_state_enter, .exit_state = scic_sds_controller_stopping_state_exit, }, - [SCI_BASE_CONTROLLER_STATE_STOPPED] = {}, - [SCI_BASE_CONTROLLER_STATE_FAILED] = {} + [SCIC_STOPPED] = {}, + [SCIC_FAILED] = {} }; static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) @@ -1774,7 +1761,7 @@ static void controller_timeout(unsigned long data) struct sci_timer *tmr = (struct sci_timer *)data; struct scic_sds_controller *scic = container_of(tmr, typeof(*scic), timer); struct isci_host *ihost = scic_to_ihost(scic); - struct sci_base_state_machine *sm = &scic->state_machine; + struct sci_base_state_machine *sm = &scic->sm; unsigned long flags; spin_lock_irqsave(&ihost->scic_lock, flags); @@ -1782,10 +1769,10 @@ static void controller_timeout(unsigned long data) if (tmr->cancel) goto done; - if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING) + if (sm->current_state_id == SCIC_STARTING) scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT); - else if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STOPPING) { - sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_FAILED); + else if (sm->current_state_id == SCIC_STOPPING) { + sci_change_state(sm, SCIC_FAILED); isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); } else /* / @todo Now what do we want to do in this case? */ dev_err(scic_to_dev(scic), @@ -1820,11 +1807,11 @@ static enum sci_status scic_controller_construct(struct scic_sds_controller *sci struct isci_host *ihost = scic_to_ihost(scic); u8 i; - sci_base_state_machine_construct(&scic->state_machine, + sci_base_state_machine_construct(&scic->sm, scic_sds_controller_state_table, - SCI_BASE_CONTROLLER_STATE_INITIAL); + SCIC_INITIAL); - sci_base_state_machine_start(&scic->state_machine); + sci_base_state_machine_start(&scic->sm); scic->scu_registers = scu_base; scic->smu_registers = smu_base; @@ -1899,11 +1886,11 @@ int scic_oem_parameters_validate(struct scic_sds_oem_params *oem) static enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic, union scic_oem_parameters *scic_parms) { - u32 state = scic->state_machine.current_state_id; + u32 state = scic->sm.current_state_id; - if (state == SCI_BASE_CONTROLLER_STATE_RESET || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { + if (state == SCIC_RESET || + state == SCIC_INITIALIZING || + state == SCIC_INITIALIZED) { if (scic_oem_parameters_validate(&scic_parms->sds1)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; @@ -2168,10 +2155,8 @@ static enum sci_status scic_controller_set_mode(struct scic_sds_controller *scic { enum sci_status status = SCI_SUCCESS; - if ((scic->state_machine.current_state_id == - SCI_BASE_CONTROLLER_STATE_INITIALIZING) || - (scic->state_machine.current_state_id == - SCI_BASE_CONTROLLER_STATE_INITIALIZED)) { + if ((scic->sm.current_state_id == SCIC_INITIALIZING) || + (scic->sm.current_state_id == SCIC_INITIALIZED)) { switch (operating_mode) { case SCI_MODE_SPEED: scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; @@ -2216,20 +2201,19 @@ static void scic_sds_controller_initialize_power_control(struct scic_sds_control static enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) { - struct sci_base_state_machine *sm = &scic->state_machine; + struct sci_base_state_machine *sm = &scic->sm; enum sci_status result = SCI_SUCCESS; struct isci_host *ihost = scic_to_ihost(scic); u32 index, state; - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_RESET) { + if (scic->sm.current_state_id != SCIC_RESET) { dev_warn(scic_to_dev(scic), "SCIC Controller initialize operation requested " "in invalid state\n"); return SCI_FAILURE_INVALID_STATE; } - sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING); + sci_change_state(sm, SCIC_INITIALIZING); sci_init_timer(&scic->phy_timer, phy_startup_timeout); @@ -2374,10 +2358,10 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc /* Advance the controller state machine */ if (result == SCI_SUCCESS) - state = SCI_BASE_CONTROLLER_STATE_INITIALIZED; + state = SCIC_INITIALIZED; else - state = SCI_BASE_CONTROLLER_STATE_FAILED; - sci_base_state_machine_change_state(sm, state); + state = SCIC_FAILED; + sci_change_state(sm, state); return result; } @@ -2386,11 +2370,11 @@ static enum sci_status scic_user_parameters_set( struct scic_sds_controller *scic, union scic_user_parameters *scic_parms) { - u32 state = scic->state_machine.current_state_id; + u32 state = scic->sm.current_state_id; - if (state == SCI_BASE_CONTROLLER_STATE_RESET || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZING || - state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) { + if (state == SCIC_RESET || + state == SCIC_INITIALIZING || + state == SCIC_INITIALIZED) { u16 index; /* @@ -2612,15 +2596,15 @@ int isci_host_init(struct isci_host *isci_host) void scic_sds_controller_link_up(struct scic_sds_controller *scic, struct scic_sds_port *port, struct scic_sds_phy *phy) { - switch (scic->state_machine.current_state_id) { - case SCI_BASE_CONTROLLER_STATE_STARTING: + switch (scic->sm.current_state_id) { + case SCIC_STARTING: sci_del_timer(&scic->phy_timer); scic->phy_startup_timer_pending = false; scic->port_agent.link_up_handler(scic, &scic->port_agent, port, phy); scic_sds_controller_start_next_phy(scic); break; - case SCI_BASE_CONTROLLER_STATE_READY: + case SCIC_READY: scic->port_agent.link_up_handler(scic, &scic->port_agent, port, phy); break; @@ -2628,16 +2612,16 @@ void scic_sds_controller_link_up(struct scic_sds_controller *scic, dev_dbg(scic_to_dev(scic), "%s: SCIC Controller linkup event from phy %d in " "unexpected state %d\n", __func__, phy->phy_index, - scic->state_machine.current_state_id); + scic->sm.current_state_id); } } void scic_sds_controller_link_down(struct scic_sds_controller *scic, struct scic_sds_port *port, struct scic_sds_phy *phy) { - switch (scic->state_machine.current_state_id) { - case SCI_BASE_CONTROLLER_STATE_STARTING: - case SCI_BASE_CONTROLLER_STATE_READY: + switch (scic->sm.current_state_id) { + case SCIC_STARTING: + case SCIC_READY: scic->port_agent.link_down_handler(scic, &scic->port_agent, port, phy); break; @@ -2647,7 +2631,7 @@ void scic_sds_controller_link_down(struct scic_sds_controller *scic, "unexpected state %d\n", __func__, phy->phy_index, - scic->state_machine.current_state_id); + scic->sm.current_state_id); } } @@ -2663,8 +2647,7 @@ static bool scic_sds_controller_has_remote_devices_stopping( for (index = 0; index < controller->remote_node_entries; index++) { if ((controller->device_table[index] != NULL) && - (controller->device_table[index]->state_machine.current_state_id - == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING)) + (controller->device_table[index]->sm.current_state_id == SCI_DEV_STOPPING)) return true; } @@ -2678,19 +2661,17 @@ static bool scic_sds_controller_has_remote_devices_stopping( void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev) { - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_STOPPING) { + if (scic->sm.current_state_id != SCIC_STOPPING) { dev_dbg(scic_to_dev(scic), "SCIC Controller 0x%p remote device stopped event " "from device 0x%p in unexpected state %d\n", scic, sci_dev, - scic->state_machine.current_state_id); + scic->sm.current_state_id); return; } if (!scic_sds_controller_has_remote_devices_stopping(scic)) { - sci_base_state_machine_change_state(&scic->state_machine, - SCI_BASE_CONTROLLER_STATE_STOPPED); + sci_change_state(&scic->sm, SCIC_STOPPED); } } @@ -2948,8 +2929,7 @@ enum sci_status scic_controller_start_io( { enum sci_status status; - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { + if (scic->sm.current_state_id != SCIC_READY) { dev_warn(scic_to_dev(scic), "invalid state to start I/O"); return SCI_FAILURE_INVALID_STATE; } @@ -2986,8 +2966,7 @@ enum sci_status scic_controller_terminate_request( { enum sci_status status; - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { + if (scic->sm.current_state_id != SCIC_READY) { dev_warn(scic_to_dev(scic), "invalid state to terminate request\n"); return SCI_FAILURE_INVALID_STATE; @@ -3037,11 +3016,11 @@ enum sci_status scic_controller_complete_io( enum sci_status status; u16 index; - switch (scic->state_machine.current_state_id) { - case SCI_BASE_CONTROLLER_STATE_STOPPING: + switch (scic->sm.current_state_id) { + case SCIC_STOPPING: /* XXX: Implement this function */ return SCI_FAILURE; - case SCI_BASE_CONTROLLER_STATE_READY: + case SCIC_READY: status = scic_sds_remote_device_complete_io(scic, rdev, request); if (status != SCI_SUCCESS) return status; @@ -3060,8 +3039,7 @@ enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) { struct scic_sds_controller *scic = sci_req->owning_controller; - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { + if (scic->sm.current_state_id != SCIC_READY) { dev_warn(scic_to_dev(scic), "invalid state to continue I/O"); return SCI_FAILURE_INVALID_STATE; } @@ -3107,8 +3085,7 @@ enum sci_task_status scic_controller_start_task( { enum sci_status status; - if (scic->state_machine.current_state_id != - SCI_BASE_CONTROLLER_STATE_READY) { + if (scic->sm.current_state_id != SCIC_READY) { dev_warn(scic_to_dev(scic), "%s: SCIC Controller starting task from invalid " "state\n", diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 4ce39e1803ff..be09765ee1d5 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -134,7 +134,7 @@ struct scic_sds_controller { * This field contains the information for the base controller state * machine. */ - struct sci_base_state_machine state_machine; + struct sci_base_state_machine sm; /** * Timer for controller start/stop operations. @@ -359,7 +359,7 @@ enum scic_sds_controller_states { /** * Simply the initial state for the base controller state machine. */ - SCI_BASE_CONTROLLER_STATE_INITIAL = 0, + SCIC_INITIAL = 0, /** * This state indicates that the controller is reset. The memory for @@ -368,7 +368,7 @@ enum scic_sds_controller_states { * This state is entered from the INITIAL state. * This state is entered from the RESETTING state. */ - SCI_BASE_CONTROLLER_STATE_RESET, + SCIC_RESET, /** * This state is typically an action state that indicates the controller @@ -376,28 +376,28 @@ enum scic_sds_controller_states { * are permitted. * This state is entered from the RESET state. */ - SCI_BASE_CONTROLLER_STATE_INITIALIZING, + SCIC_INITIALIZING, /** * This state indicates that the controller has been successfully * initialized. In this state no new IO operations are permitted. * This state is entered from the INITIALIZING state. */ - SCI_BASE_CONTROLLER_STATE_INITIALIZED, + SCIC_INITIALIZED, /** * This state indicates the the controller is in the process of becoming * ready (i.e. starting). In this state no new IO operations are permitted. * This state is entered from the INITIALIZED state. */ - SCI_BASE_CONTROLLER_STATE_STARTING, + SCIC_STARTING, /** * This state indicates the controller is now ready. Thus, the user * is able to perform IO operations on the controller. * This state is entered from the STARTING state. */ - SCI_BASE_CONTROLLER_STATE_READY, + SCIC_READY, /** * This state is typically an action state that indicates the controller @@ -408,7 +408,7 @@ enum scic_sds_controller_states { * This state is entered from the FAILED state. * This state is entered from the STOPPED state. */ - SCI_BASE_CONTROLLER_STATE_RESETTING, + SCIC_RESETTING, /** * This state indicates that the controller is in the process of stopping. @@ -416,14 +416,14 @@ enum scic_sds_controller_states { * operations are allowed to complete. * This state is entered from the READY state. */ - SCI_BASE_CONTROLLER_STATE_STOPPING, + SCIC_STOPPING, /** * This state indicates that the controller has successfully been stopped. * In this state no new IO operations are permitted. * This state is entered from the STOPPING state. */ - SCI_BASE_CONTROLLER_STATE_STOPPED, + SCIC_STOPPED, /** * This state indicates that the controller could not successfully be @@ -433,10 +433,7 @@ enum scic_sds_controller_states { * This state is entered from the STOPPING state. * This state is entered from the RESETTING state. */ - SCI_BASE_CONTROLLER_STATE_FAILED, - - SCI_BASE_CONTROLLER_MAX_STATES - + SCIC_FAILED, }; diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index fc196e389ffb..9de21c719351 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -249,8 +249,7 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, writel(0x1F4, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout); /* We can exit the initial state to the stopped state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); + sci_change_state(&sci_phy->sm, SCI_PHY_STOPPED); return SCI_SUCCESS; } @@ -273,8 +272,7 @@ static void phy_sata_timeout(unsigned long data) __func__, sci_phy); - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } @@ -342,8 +340,7 @@ enum sci_status scic_sds_phy_initialize( /* * There is nothing that needs to be done in this state just * transition to the stopped state. */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); + sci_change_state(&sci_phy->sm, SCI_PHY_STOPPED); return SCI_SUCCESS; } @@ -436,34 +433,33 @@ void scic_sds_phy_get_protocols(struct scic_sds_phy *sci_phy, enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) { - enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + enum scic_sds_phy_states state = sci_phy->sm.current_state_id; - if (state != SCI_BASE_PHY_STATE_STOPPED) { + if (state != SCI_PHY_STOPPED) { dev_dbg(sciphy_to_dev(sci_phy), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); return SCI_SUCCESS; } enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) { - enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + enum scic_sds_phy_states state = sci_phy->sm.current_state_id; switch (state) { - case SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN: - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: - case SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL: - case SCI_BASE_PHY_STATE_READY: + case SCI_PHY_SUB_INITIAL: + case SCI_PHY_SUB_AWAIT_OSSP_EN: + case SCI_PHY_SUB_AWAIT_SAS_SPEED_EN: + case SCI_PHY_SUB_AWAIT_SAS_POWER: + case SCI_PHY_SUB_AWAIT_SATA_POWER: + case SCI_PHY_SUB_AWAIT_SATA_PHY_EN: + case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN: + case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: + case SCI_PHY_SUB_FINAL: + case SCI_PHY_READY: break; default: dev_dbg(sciphy_to_dev(sci_phy), @@ -471,32 +467,30 @@ enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) return SCI_FAILURE_INVALID_STATE; } - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STOPPED); + sci_change_state(&sci_phy->sm, SCI_PHY_STOPPED); return SCI_SUCCESS; } enum sci_status scic_sds_phy_reset(struct scic_sds_phy *sci_phy) { - enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + enum scic_sds_phy_states state = sci_phy->sm.current_state_id; - if (state != SCI_BASE_PHY_STATE_READY) { + if (state != SCI_PHY_READY) { dev_dbg(sciphy_to_dev(sci_phy), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_RESETTING); + sci_change_state(&sci_phy->sm, SCI_PHY_RESETTING); return SCI_SUCCESS; } enum sci_status scic_sds_phy_consume_power_handler(struct scic_sds_phy *sci_phy) { - enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + enum scic_sds_phy_states state = sci_phy->sm.current_state_id; switch (state) { - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: { + case SCI_PHY_SUB_AWAIT_SAS_POWER: { u32 enable_spinup; enable_spinup = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); @@ -504,12 +498,11 @@ enum sci_status scic_sds_phy_consume_power_handler(struct scic_sds_phy *sci_phy) writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control); /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_FINAL); return SCI_SUCCESS; } - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: { + case SCI_PHY_SUB_AWAIT_SATA_POWER: { u32 scu_sas_pcfg_value; /* Release the spinup hold state and reset the OOB state machine */ @@ -528,8 +521,7 @@ enum sci_status scic_sds_phy_consume_power_handler(struct scic_sds_phy *sci_phy) &sci_phy->link_layer_registers->phy_configuration); /* Change state to the final state this substate machine has run to completion */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SATA_PHY_EN); return SCI_SUCCESS; } @@ -566,10 +558,7 @@ static void scic_sds_phy_start_sas_link_training( writel(phy_control, &sci_phy->link_layer_registers->phy_configuration); - sci_base_state_machine_change_state( - &sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN - ); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SAS_SPEED_EN); sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; } @@ -585,10 +574,7 @@ static void scic_sds_phy_start_sas_link_training( static void scic_sds_phy_start_sata_link_training( struct scic_sds_phy *sci_phy) { - sci_base_state_machine_change_state( - &sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER - ); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SATA_POWER); sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; } @@ -611,17 +597,16 @@ static void scic_sds_phy_complete_link_training( { sci_phy->max_negotiated_speed = max_link_rate; - sci_base_state_machine_change_state(&sci_phy->state_machine, - next_state); + sci_change_state(&sci_phy->sm, next_state); } enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, u32 event_code) { - enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + enum scic_sds_phy_states state = sci_phy->sm.current_state_id; switch (state) { - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN: + case SCI_PHY_SUB_AWAIT_OSSP_EN: switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: scic_sds_phy_start_sas_link_training(sci_phy); @@ -640,7 +625,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE; } return SCI_SUCCESS; - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN: + case SCI_PHY_SUB_AWAIT_SAS_SPEED_EN: switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: /* @@ -652,21 +637,21 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, scic_sds_phy_complete_link_training( sci_phy, SAS_LINK_RATE_1_5_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + SCI_PHY_SUB_AWAIT_IAF_UF); break; case SCU_EVENT_SAS_30: case SCU_EVENT_SAS_30_SSC: scic_sds_phy_complete_link_training( sci_phy, SAS_LINK_RATE_3_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + SCI_PHY_SUB_AWAIT_IAF_UF); break; case SCU_EVENT_SAS_60: case SCU_EVENT_SAS_60_SSC: scic_sds_phy_complete_link_training( sci_phy, SAS_LINK_RATE_6_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF); + SCI_PHY_SUB_AWAIT_IAF_UF); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* @@ -676,8 +661,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; default: dev_warn(sciphy_to_dev(sci_phy), @@ -689,7 +673,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, break; } return SCI_SUCCESS; - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: + case SCI_PHY_SUB_AWAIT_IAF_UF: switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: /* Backup the state machine */ @@ -706,8 +690,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, case SCU_EVENT_LINK_FAILURE: case SCU_EVENT_HARD_RESET_RECEIVED: /* Start the oob/sn state machine over again */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; default: dev_warn(sciphy_to_dev(sci_phy), @@ -717,12 +700,11 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE; } return SCI_SUCCESS; - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: + case SCI_PHY_SUB_AWAIT_SAS_POWER: switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; default: dev_warn(sciphy_to_dev(sci_phy), @@ -733,12 +715,11 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE; } return SCI_SUCCESS; - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: + case SCI_PHY_SUB_AWAIT_SATA_POWER: switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* These events are received every 10ms and are @@ -762,12 +743,11 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE; } return SCI_SUCCESS; - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN: + case SCI_PHY_SUB_AWAIT_SATA_PHY_EN: switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* These events might be received since we dont know how many may be in @@ -778,8 +758,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; /* We have received the SATA PHY notification change state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN); break; case SCU_EVENT_SAS_PHY_DETECTED: /* There has been a change in the phy type before OOB/SN for the @@ -797,7 +776,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE;; } return SCI_SUCCESS; - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN: + case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN: switch (scu_get_event_code(event_code)) { case SCU_EVENT_SATA_PHY_DETECTED: /* @@ -809,26 +788,25 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, scic_sds_phy_complete_link_training( sci_phy, SAS_LINK_RATE_1_5_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_SATA_30: case SCU_EVENT_SATA_30_SSC: scic_sds_phy_complete_link_training( sci_phy, SAS_LINK_RATE_3_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_SATA_60: case SCU_EVENT_SATA_60_SSC: scic_sds_phy_complete_link_training( sci_phy, SAS_LINK_RATE_6_0_GBPS, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF); + SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; case SCU_EVENT_SAS_PHY_DETECTED: /* @@ -846,18 +824,16 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, } return SCI_SUCCESS; - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: + case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: switch (scu_get_event_code(event_code)) { case SCU_EVENT_SATA_PHY_DETECTED: /* Backup the state machine */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; default: @@ -870,12 +846,11 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE; } return SCI_SUCCESS; - case SCI_BASE_PHY_STATE_READY: + case SCI_PHY_READY: switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; case SCU_EVENT_BROADCAST_CHANGE: /* Broadcast change received. Notify the port. */ @@ -892,12 +867,11 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, return SCI_FAILURE_INVALID_STATE; } return SCI_SUCCESS; - case SCI_BASE_PHY_STATE_RESETTING: + case SCI_PHY_RESETTING: switch (scu_get_event_code(event_code)) { case SCU_EVENT_HARD_RESET_TRANSMITTED: /* Link failure change state back to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); break; default: dev_warn(sciphy_to_dev(sci_phy), @@ -919,12 +893,12 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, u32 frame_index) { - enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id; + enum scic_sds_phy_states state = sci_phy->sm.current_state_id; struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; enum sci_status result; switch (state) { - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: { + case SCI_PHY_SUB_AWAIT_IAF_UF: { u32 *frame_words; struct sas_identify_frame iaf; struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); @@ -946,15 +920,14 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, * state since there are no power requirements for * expander phys. */ - state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL; + state = SCI_PHY_SUB_FINAL; } else { /* We got the IAF we can now go to the await spinup * semaphore state */ - state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER; + state = SCI_PHY_SUB_AWAIT_SAS_POWER; } - sci_base_state_machine_change_state(&sci_phy->state_machine, - state); + sci_change_state(&sci_phy->sm, state); result = SCI_SUCCESS; } else dev_warn(sciphy_to_dev(sci_phy), @@ -965,7 +938,7 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, scic_sds_controller_release_frame(scic, frame_index); return result; } - case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: { + case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: { struct dev_to_host_fis *frame_header; u32 *fis_frame_data; struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); @@ -989,8 +962,7 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, fis_frame_data); /* got IAF we can now go to the await spinup semaphore state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_FINAL); result = SCI_SUCCESS; } else @@ -1014,16 +986,15 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); /* This is just an temporary state go off to the starting state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_OSSP_EN); } static void scic_sds_phy_starting_await_sas_power_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; scic_sds_controller_power_control_queue_insert(scic, sci_phy); @@ -1031,7 +1002,7 @@ static void scic_sds_phy_starting_await_sas_power_substate_enter(struct sci_base static void scic_sds_phy_starting_await_sas_power_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; scic_sds_controller_power_control_queue_remove(scic, sci_phy); @@ -1039,7 +1010,7 @@ static void scic_sds_phy_starting_await_sas_power_substate_exit(struct sci_base_ static void scic_sds_phy_starting_await_sata_power_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; scic_sds_controller_power_control_queue_insert(scic, sci_phy); @@ -1047,7 +1018,7 @@ static void scic_sds_phy_starting_await_sata_power_substate_enter(struct sci_bas static void scic_sds_phy_starting_await_sata_power_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; scic_sds_controller_power_control_queue_remove(scic, sci_phy); @@ -1055,35 +1026,35 @@ static void scic_sds_phy_starting_await_sata_power_substate_exit(struct sci_base static void scic_sds_phy_starting_await_sata_phy_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); sci_mod_timer(&sci_phy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } static void scic_sds_phy_starting_await_sata_phy_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); sci_del_timer(&sci_phy->sata_timer); } static void scic_sds_phy_starting_await_sata_speed_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); sci_mod_timer(&sci_phy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } static void scic_sds_phy_starting_await_sata_speed_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); sci_del_timer(&sci_phy->sata_timer); } static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); if (scic_sds_port_link_detected(sci_phy->owning_port, sci_phy)) { @@ -1103,20 +1074,19 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_bas static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); sci_del_timer(&sci_phy->sata_timer); } static void scic_sds_phy_starting_final_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); /* State machine has run to completion so exit out and change * the base state machine to the ready state */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_READY); + sci_change_state(&sci_phy->sm, SCI_PHY_READY); } /** @@ -1202,7 +1172,7 @@ static void scu_link_layer_tx_hard_reset( static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); /* * @todo We need to get to the controller to place this PE in a @@ -1212,7 +1182,7 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm) scu_link_layer_stop_protocol_engine(sci_phy); - if (sci_phy->state_machine.previous_state_id != SCI_BASE_PHY_STATE_INITIAL) + if (sci_phy->sm.previous_state_id != SCI_PHY_INITIAL) scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), phy_get_non_dummy_port(sci_phy), sci_phy); @@ -1220,7 +1190,7 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm) static void scic_sds_phy_starting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); scu_link_layer_stop_protocol_engine(sci_phy); scu_link_layer_start_oob(sci_phy); @@ -1229,18 +1199,17 @@ static void scic_sds_phy_starting_state_enter(struct sci_base_state_machine *sm) sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; sci_phy->bcn_received_while_port_unassigned = false; - if (sci_phy->state_machine.previous_state_id == SCI_BASE_PHY_STATE_READY) + if (sci_phy->sm.previous_state_id == SCI_PHY_READY) scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), phy_get_non_dummy_port(sci_phy), sci_phy); - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); + sci_change_state(&sci_phy->sm, SCI_PHY_SUB_INITIAL); } static void scic_sds_phy_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); scic_sds_controller_link_up(scic_sds_phy_get_controller(sci_phy), phy_get_non_dummy_port(sci_phy), @@ -1250,14 +1219,14 @@ static void scic_sds_phy_ready_state_enter(struct sci_base_state_machine *sm) static void scic_sds_phy_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); scic_sds_phy_suspend(sci_phy); } static void scic_sds_phy_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine); + struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); /* The phy is being reset, therefore deactivate it from the port. In * the resetting state we don't notify the user regarding link up and @@ -1271,66 +1240,65 @@ static void scic_sds_phy_resetting_state_enter(struct sci_base_state_machine *sm /* The SCU does not need to have a discrete reset state so * just go back to the starting state. */ - sci_base_state_machine_change_state(&sci_phy->state_machine, - SCI_BASE_PHY_STATE_STARTING); + sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); } } static const struct sci_base_state scic_sds_phy_state_table[] = { - [SCI_BASE_PHY_STATE_INITIAL] = { }, - [SCI_BASE_PHY_STATE_STOPPED] = { + [SCI_PHY_INITIAL] = { }, + [SCI_PHY_STOPPED] = { .enter_state = scic_sds_phy_stopped_state_enter, }, - [SCI_BASE_PHY_STATE_STARTING] = { + [SCI_PHY_STARTING] = { .enter_state = scic_sds_phy_starting_state_enter, }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { + [SCI_PHY_SUB_INITIAL] = { .enter_state = scic_sds_phy_starting_initial_substate_enter, }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { + [SCI_PHY_SUB_AWAIT_OSSP_EN] = { }, + [SCI_PHY_SUB_AWAIT_SAS_SPEED_EN] = { }, + [SCI_PHY_SUB_AWAIT_IAF_UF] = { }, + [SCI_PHY_SUB_AWAIT_SAS_POWER] = { .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { + [SCI_PHY_SUB_AWAIT_SATA_POWER] = { .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter, .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { + [SCI_PHY_SUB_AWAIT_SATA_PHY_EN] = { .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter, .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { + [SCI_PHY_SUB_AWAIT_SATA_SPEED_EN] = { .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter, .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { + [SCI_PHY_SUB_AWAIT_SIG_FIS_UF] = { .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter, .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit }, - [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { + [SCI_PHY_SUB_FINAL] = { .enter_state = scic_sds_phy_starting_final_substate_enter, }, - [SCI_BASE_PHY_STATE_READY] = { + [SCI_PHY_READY] = { .enter_state = scic_sds_phy_ready_state_enter, .exit_state = scic_sds_phy_ready_state_exit, }, - [SCI_BASE_PHY_STATE_RESETTING] = { + [SCI_PHY_RESETTING] = { .enter_state = scic_sds_phy_resetting_state_enter, }, - [SCI_BASE_PHY_STATE_FINAL] = { }, + [SCI_PHY_FINAL] = { }, }; void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, struct scic_sds_port *owning_port, u8 phy_index) { - sci_base_state_machine_construct(&sci_phy->state_machine, + sci_base_state_machine_construct(&sci_phy->sm, scic_sds_phy_state_table, - SCI_BASE_PHY_STATE_INITIAL); + SCI_PHY_INITIAL); - sci_base_state_machine_start(&sci_phy->state_machine); + sci_base_state_machine_start(&sci_phy->sm); /* Copy the rest of the input data to our locals */ sci_phy->owning_port = owning_port; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index da3f0f1d56d4..9d21d2754dbb 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -94,7 +94,7 @@ struct scic_sds_phy { /** * This field contains the information for the base phy state machine. */ - struct sci_base_state_machine state_machine; + struct sci_base_state_machine sm; /** * This field specifies the port object that owns/contains this phy. @@ -410,7 +410,7 @@ enum scic_sds_phy_states { /** * Simply the initial state for the base domain state machine. */ - SCI_BASE_PHY_STATE_INITIAL, + SCI_PHY_INITIAL, /** * This state indicates that the phy has successfully been stopped. @@ -420,7 +420,7 @@ enum scic_sds_phy_states { * This state is entered from the READY state. * This state is entered from the RESETTING state. */ - SCI_BASE_PHY_STATE_STOPPED, + SCI_PHY_STOPPED, /** * This state indicates that the phy is in the process of becomming @@ -429,57 +429,57 @@ enum scic_sds_phy_states { * This state is entered from the READY state. * This state is entered from the RESETTING state. */ - SCI_BASE_PHY_STATE_STARTING, + SCI_PHY_STARTING, /** * Initial state */ - SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL, + SCI_PHY_SUB_INITIAL, /** * Wait state for the hardware OSSP event type notification */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN, + SCI_PHY_SUB_AWAIT_OSSP_EN, /** * Wait state for the PHY speed notification */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN, + SCI_PHY_SUB_AWAIT_SAS_SPEED_EN, /** * Wait state for the IAF Unsolicited frame notification */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF, + SCI_PHY_SUB_AWAIT_IAF_UF, /** * Wait state for the request to consume power */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER, + SCI_PHY_SUB_AWAIT_SAS_POWER, /** * Wait state for request to consume power */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, + SCI_PHY_SUB_AWAIT_SATA_POWER, /** * Wait state for the SATA PHY notification */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, + SCI_PHY_SUB_AWAIT_SATA_PHY_EN, /** * Wait for the SATA PHY speed notification */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, + SCI_PHY_SUB_AWAIT_SATA_SPEED_EN, /** * Wait state for the SIGNATURE FIS unsolicited frame notification */ - SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, + SCI_PHY_SUB_AWAIT_SIG_FIS_UF, /** * Exit state for this state machine */ - SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL, + SCI_PHY_SUB_FINAL, /** * This state indicates the the phy is now ready. Thus, the user @@ -487,19 +487,19 @@ enum scic_sds_phy_states { * is currently part of a valid port. * This state is entered from the STARTING state. */ - SCI_BASE_PHY_STATE_READY, + SCI_PHY_READY, /** * This state indicates that the phy is in the process of being reset. * In this state no new IO operations are permitted on this phy. * This state is entered from the READY state. */ - SCI_BASE_PHY_STATE_RESETTING, + SCI_PHY_RESETTING, /** * Simply the final state for the base phy state machine. */ - SCI_BASE_PHY_STATE_FINAL, + SCI_PHY_FINAL, }; /** diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 8d88ca21a51c..6370b93bd6ae 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -807,10 +807,10 @@ static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, static bool is_port_ready_state(enum scic_sds_port_states state) { switch (state) { - case SCI_BASE_PORT_STATE_READY: - case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: - case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: - case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + case SCI_PORT_READY: + case SCI_PORT_SUB_WAITING: + case SCI_PORT_SUB_OPERATIONAL: + case SCI_PORT_SUB_CONFIGURING: return true; default: return false; @@ -821,13 +821,13 @@ static bool is_port_ready_state(enum scic_sds_port_states state) static void port_state_machine_change(struct scic_sds_port *sci_port, enum scic_sds_port_states state) { - struct sci_base_state_machine *sm = &sci_port->state_machine; + struct sci_base_state_machine *sm = &sci_port->sm; enum scic_sds_port_states old_state = sm->current_state_id; if (is_port_ready_state(old_state) && !is_port_ready_state(state)) sci_port->ready_exit = true; - sci_base_state_machine_change_state(sm, state); + sci_change_state(sm, state); sci_port->ready_exit = false; } @@ -862,11 +862,11 @@ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port if ((phy_sas_address.high == port_sas_address.high && phy_sas_address.low == port_sas_address.low) || sci_port->active_phy_mask == 0) { - struct sci_base_state_machine *sm = &sci_port->state_machine; + struct sci_base_state_machine *sm = &sci_port->sm; scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); - if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING) - port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_READY); + if (sm->current_state_id == SCI_PORT_RESETTING) + port_state_machine_change(sci_port, SCI_PORT_READY); } else scic_sds_port_invalid_link_up(sci_port, sci_phy); } @@ -938,14 +938,14 @@ static void port_timeout(unsigned long data) if (tmr->cancel) goto done; - current_state = sci_base_state_machine_get_state(&sci_port->state_machine); + current_state = sci_port->sm.current_state_id; - if (current_state == SCI_BASE_PORT_STATE_RESETTING) { + if (current_state == SCI_PORT_RESETTING) { /* if the port is still in the resetting state then the timeout * fired before the reset completed. */ - port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_FAILED); - } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { + port_state_machine_change(sci_port, SCI_PORT_FAILED); + } else if (current_state == SCI_PORT_STOPPED) { /* if the port is stopped then the start request failed In this * case stay in the stopped state. */ @@ -953,7 +953,7 @@ static void port_timeout(unsigned long data) "%s: SCIC Port 0x%p failed to stop before tiemout.\n", __func__, sci_port); - } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { + } else if (current_state == SCI_PORT_STOPPING) { /* if the port is still stopping then the stop has not completed */ isci_port_stop_complete(sci_port->owning_controller, sci_port, @@ -1139,7 +1139,7 @@ scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) static void scic_sds_port_ready_substate_waiting_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); scic_sds_port_suspend_port_task_scheduler(sci_port); @@ -1148,14 +1148,14 @@ static void scic_sds_port_ready_substate_waiting_enter(struct sci_base_state_mac if (sci_port->active_phy_mask != 0) { /* At least one of the phys on the port is ready */ port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); + SCI_PORT_SUB_OPERATIONAL); } } static void scic_sds_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) { u32 index; - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); @@ -1211,12 +1211,12 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci * @object: This is the object which is cast to a struct scic_sds_port object. * * This method will perform the actions required by the struct scic_sds_port on - * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports + * exiting the SCI_PORT_SUB_OPERATIONAL. This function reports * the port not ready and suspends the port task scheduler. none */ static void scic_sds_port_ready_substate_operational_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); @@ -1236,7 +1236,7 @@ static void scic_sds_port_ready_substate_operational_exit(struct sci_base_state_ static void scic_sds_port_ready_substate_configuring_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); @@ -1245,15 +1245,15 @@ static void scic_sds_port_ready_substate_configuring_enter(struct sci_base_state isci_port_not_ready(ihost, iport); port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + SCI_PORT_SUB_WAITING); } else if (sci_port->started_request_count == 0) port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); + SCI_PORT_SUB_OPERATIONAL); } static void scic_sds_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); scic_sds_port_suspend_port_task_scheduler(sci_port); if (sci_port->ready_exit) @@ -1267,8 +1267,8 @@ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) enum scic_sds_port_states state; u32 phy_mask; - state = sci_port->state_machine.current_state_id; - if (state != SCI_BASE_PORT_STATE_STOPPED) { + state = sci_port->sm.current_state_id; + if (state != SCI_PORT_STOPPED) { dev_warn(sciport_to_dev(sci_port), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; @@ -1315,7 +1315,7 @@ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) */ if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { port_state_machine_change(sci_port, - SCI_BASE_PORT_STATE_READY); + SCI_PORT_READY); return SCI_SUCCESS; } @@ -1332,16 +1332,16 @@ enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port) { enum scic_sds_port_states state; - state = sci_port->state_machine.current_state_id; + state = sci_port->sm.current_state_id; switch (state) { - case SCI_BASE_PORT_STATE_STOPPED: + case SCI_PORT_STOPPED: return SCI_SUCCESS; - case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: - case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: - case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: - case SCI_BASE_PORT_STATE_RESETTING: + case SCI_PORT_SUB_WAITING: + case SCI_PORT_SUB_OPERATIONAL: + case SCI_PORT_SUB_CONFIGURING: + case SCI_PORT_RESETTING: port_state_machine_change(sci_port, - SCI_BASE_PORT_STATE_STOPPING); + SCI_PORT_STOPPING); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(sci_port), @@ -1357,8 +1357,8 @@ static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 enum scic_sds_port_states state; u32 phy_index; - state = sci_port->state_machine.current_state_id; - if (state != SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL) { + state = sci_port->sm.current_state_id; + if (state != SCI_PORT_SUB_OPERATIONAL) { dev_warn(sciport_to_dev(sci_port), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; @@ -1389,7 +1389,7 @@ static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 sci_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; port_state_machine_change(sci_port, - SCI_BASE_PORT_STATE_RESETTING); + SCI_PORT_RESETTING); return SCI_SUCCESS; } @@ -1408,9 +1408,9 @@ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, enum sci_status status; enum scic_sds_port_states state; - state = sci_port->state_machine.current_state_id; + state = sci_port->sm.current_state_id; switch (state) { - case SCI_BASE_PORT_STATE_STOPPED: { + case SCI_PORT_STOPPED: { struct sci_sas_address port_sas_address; /* Read the port assigned SAS Address if there is one */ @@ -1430,8 +1430,8 @@ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, } return scic_sds_port_set_phy(sci_port, sci_phy); } - case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: - case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + case SCI_PORT_SUB_WAITING: + case SCI_PORT_SUB_OPERATIONAL: status = scic_sds_port_set_phy(sci_port, sci_phy); if (status != SCI_SUCCESS) @@ -1439,10 +1439,10 @@ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; - port_state_machine_change(sci_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + port_state_machine_change(sci_port, SCI_PORT_SUB_CONFIGURING); return status; - case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + case SCI_PORT_SUB_CONFIGURING: status = scic_sds_port_set_phy(sci_port, sci_phy); if (status != SCI_SUCCESS) @@ -1453,7 +1453,7 @@ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, * the port. */ port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(sci_port), @@ -1477,12 +1477,12 @@ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, enum sci_status status; enum scic_sds_port_states state; - state = sci_port->state_machine.current_state_id; + state = sci_port->sm.current_state_id; switch (state) { - case SCI_BASE_PORT_STATE_STOPPED: + case SCI_PORT_STOPPED: return scic_sds_port_clear_phy(sci_port, sci_phy); - case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + case SCI_PORT_SUB_OPERATIONAL: status = scic_sds_port_clear_phy(sci_port, sci_phy); if (status != SCI_SUCCESS) return status; @@ -1490,9 +1490,9 @@ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, scic_sds_port_deactivate_phy(sci_port, sci_phy, true); sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; - case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + case SCI_PORT_SUB_CONFIGURING: status = scic_sds_port_clear_phy(sci_port, sci_phy); if (status != SCI_SUCCESS) @@ -1503,7 +1503,7 @@ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, * the port */ port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); + SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(sci_port), @@ -1517,21 +1517,21 @@ enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, { enum scic_sds_port_states state; - state = sci_port->state_machine.current_state_id; + state = sci_port->sm.current_state_id; switch (state) { - case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: + case SCI_PORT_SUB_WAITING: /* Since this is the first phy going link up for the port we * can just enable it and continue */ scic_sds_port_activate_phy(sci_port, sci_phy, true); port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); + SCI_PORT_SUB_OPERATIONAL); return SCI_SUCCESS; - case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + case SCI_PORT_SUB_OPERATIONAL: scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); return SCI_SUCCESS; - case SCI_BASE_PORT_STATE_RESETTING: + case SCI_PORT_RESETTING: /* TODO We should make sure that the phy that has gone * link up is the same one on which we sent the reset. It is * possible that the phy on which we sent the reset is not the @@ -1560,9 +1560,9 @@ enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, { enum scic_sds_port_states state; - state = sci_port->state_machine.current_state_id; + state = sci_port->sm.current_state_id; switch (state) { - case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + case SCI_PORT_SUB_OPERATIONAL: scic_sds_port_deactivate_phy(sci_port, sci_phy, true); /* If there are no active phys left in the port, then @@ -1571,9 +1571,9 @@ enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, */ if (sci_port->active_phy_mask == 0) port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + SCI_PORT_SUB_WAITING); return SCI_SUCCESS; - case SCI_BASE_PORT_STATE_RESETTING: + case SCI_PORT_RESETTING: /* In the resetting state we don't notify the user regarding * link up and link down notifications. */ scic_sds_port_deactivate_phy(sci_port, sci_phy, false); @@ -1591,11 +1591,11 @@ enum sci_status scic_sds_port_start_io(struct scic_sds_port *sci_port, { enum scic_sds_port_states state; - state = sci_port->state_machine.current_state_id; + state = sci_port->sm.current_state_id; switch (state) { - case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: + case SCI_PORT_SUB_WAITING: return SCI_FAILURE_INVALID_STATE; - case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + case SCI_PORT_SUB_OPERATIONAL: sci_port->started_request_count++; return SCI_SUCCESS; default: @@ -1611,31 +1611,31 @@ enum sci_status scic_sds_port_complete_io(struct scic_sds_port *sci_port, { enum scic_sds_port_states state; - state = sci_port->state_machine.current_state_id; + state = sci_port->sm.current_state_id; switch (state) { - case SCI_BASE_PORT_STATE_STOPPED: + case SCI_PORT_STOPPED: dev_warn(sciport_to_dev(sci_port), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; - case SCI_BASE_PORT_STATE_STOPPING: + case SCI_PORT_STOPPING: scic_sds_port_decrement_request_count(sci_port); if (sci_port->started_request_count == 0) port_state_machine_change(sci_port, - SCI_BASE_PORT_STATE_STOPPED); + SCI_PORT_STOPPED); break; - case SCI_BASE_PORT_STATE_READY: - case SCI_BASE_PORT_STATE_RESETTING: - case SCI_BASE_PORT_STATE_FAILED: - case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: - case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: + case SCI_PORT_READY: + case SCI_PORT_RESETTING: + case SCI_PORT_FAILED: + case SCI_PORT_SUB_WAITING: + case SCI_PORT_SUB_OPERATIONAL: scic_sds_port_decrement_request_count(sci_port); break; - case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: + case SCI_PORT_SUB_CONFIGURING: scic_sds_port_decrement_request_count(sci_port); if (sci_port->started_request_count == 0) { port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); + SCI_PORT_SUB_OPERATIONAL); } break; } @@ -1707,9 +1707,9 @@ static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) static void scic_sds_port_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); - if (sci_port->state_machine.previous_state_id == SCI_BASE_PORT_STATE_STOPPING) { + if (sci_port->sm.previous_state_id == SCI_PORT_STOPPING) { /* * If we enter this state becasuse of a request to stop * the port then we want to disable the hardwares port @@ -1720,7 +1720,7 @@ static void scic_sds_port_stopped_state_enter(struct sci_base_state_machine *sm) static void scic_sds_port_stopped_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); /* Enable and suspend the port task scheduler */ scic_sds_port_enable_port_task_scheduler(sci_port); @@ -1728,14 +1728,14 @@ static void scic_sds_port_stopped_state_exit(struct sci_base_state_machine *sm) static void scic_sds_port_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_port *iport = sci_port_to_iport(sci_port); u32 prev_state; - prev_state = sci_port->state_machine.previous_state_id; - if (prev_state == SCI_BASE_PORT_STATE_RESETTING) + prev_state = sci_port->sm.previous_state_id; + if (prev_state == SCI_PORT_RESETTING) isci_port_hard_reset_complete(iport, SCI_SUCCESS); else isci_port_not_ready(ihost, iport); @@ -1745,19 +1745,19 @@ static void scic_sds_port_ready_state_enter(struct sci_base_state_machine *sm) /* Start the ready substate machine */ port_state_machine_change(sci_port, - SCIC_SDS_PORT_READY_SUBSTATE_WAITING); + SCI_PORT_SUB_WAITING); } static void scic_sds_port_resetting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); sci_del_timer(&sci_port->timer); } static void scic_sds_port_stopping_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); sci_del_timer(&sci_port->timer); @@ -1766,7 +1766,7 @@ static void scic_sds_port_stopping_state_exit(struct sci_base_state_machine *sm) static void scic_sds_port_failed_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), state_machine); + struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); struct isci_port *iport = sci_port_to_iport(sci_port); isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); @@ -1775,31 +1775,31 @@ static void scic_sds_port_failed_state_enter(struct sci_base_state_machine *sm) /* --------------------------------------------------------------------------- */ static const struct sci_base_state scic_sds_port_state_table[] = { - [SCI_BASE_PORT_STATE_STOPPED] = { + [SCI_PORT_STOPPED] = { .enter_state = scic_sds_port_stopped_state_enter, .exit_state = scic_sds_port_stopped_state_exit }, - [SCI_BASE_PORT_STATE_STOPPING] = { + [SCI_PORT_STOPPING] = { .exit_state = scic_sds_port_stopping_state_exit }, - [SCI_BASE_PORT_STATE_READY] = { + [SCI_PORT_READY] = { .enter_state = scic_sds_port_ready_state_enter, }, - [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { + [SCI_PORT_SUB_WAITING] = { .enter_state = scic_sds_port_ready_substate_waiting_enter, }, - [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { + [SCI_PORT_SUB_OPERATIONAL] = { .enter_state = scic_sds_port_ready_substate_operational_enter, .exit_state = scic_sds_port_ready_substate_operational_exit }, - [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { + [SCI_PORT_SUB_CONFIGURING] = { .enter_state = scic_sds_port_ready_substate_configuring_enter, .exit_state = scic_sds_port_ready_substate_configuring_exit }, - [SCI_BASE_PORT_STATE_RESETTING] = { + [SCI_PORT_RESETTING] = { .exit_state = scic_sds_port_resetting_state_exit }, - [SCI_BASE_PORT_STATE_FAILED] = { + [SCI_PORT_FAILED] = { .enter_state = scic_sds_port_failed_state_enter, } }; @@ -1807,11 +1807,11 @@ static const struct sci_base_state scic_sds_port_state_table[] = { void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, struct scic_sds_controller *scic) { - sci_base_state_machine_construct(&sci_port->state_machine, + sci_base_state_machine_construct(&sci_port->sm, scic_sds_port_state_table, - SCI_BASE_PORT_STATE_STOPPED); + SCI_PORT_STOPPED); - sci_base_state_machine_start(&sci_port->state_machine); + sci_base_state_machine_start(&sci_port->sm); sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; sci_port->physical_port_index = index; diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 9a6912855fc1..fee6d80df769 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -84,7 +84,7 @@ struct scic_sds_port { /** * This field contains the information for the base port state machine. */ - struct sci_base_state_machine state_machine; + struct sci_base_state_machine sm; bool ready_exit; @@ -224,7 +224,7 @@ enum scic_sds_port_states { * In this state no new IO operations are permitted. * This state is entered from the STOPPING state. */ - SCI_BASE_PORT_STATE_STOPPED, + SCI_PORT_STOPPED, /** * This state indicates that the port is in the process of stopping. @@ -232,33 +232,33 @@ enum scic_sds_port_states { * operations are allowed to complete. * This state is entered from the READY state. */ - SCI_BASE_PORT_STATE_STOPPING, + SCI_PORT_STOPPING, /** * This state indicates the port is now ready. Thus, the user is * able to perform IO operations on this port. * This state is entered from the STARTING state. */ - SCI_BASE_PORT_STATE_READY, + SCI_PORT_READY, /** * The substate where the port is started and ready but has no * active phys. */ - SCIC_SDS_PORT_READY_SUBSTATE_WAITING, + SCI_PORT_SUB_WAITING, /** * The substate where the port is started and ready and there is * at least one phy operational. */ - SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, + SCI_PORT_SUB_OPERATIONAL, /** * The substate where the port is started and there was an * add/remove phy event. This state is only used in Automatic * Port Configuration Mode (APC) */ - SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, + SCI_PORT_SUB_CONFIGURING, /** * This state indicates the port is in the process of performing a hard @@ -266,14 +266,14 @@ enum scic_sds_port_states { * port. * This state is entered from the READY state. */ - SCI_BASE_PORT_STATE_RESETTING, + SCI_PORT_RESETTING, /** * This state indicates the port has failed a reset request. This state * is entered when a port reset request times out. * This state is entered from the RESETTING state. */ - SCI_BASE_PORT_STATE_FAILED, + SCI_PORT_FAILED, }; diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index 38401f644e18..fcb8f030b7ae 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -661,13 +661,13 @@ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, scic_sds_apc_agent_configure_ports(scic, port_agent, sci_phy, true); } else { /* the phy is already the part of the port */ - u32 port_state = sci_port->state_machine.current_state_id; + u32 port_state = sci_port->sm.current_state_id; /* if the PORT'S state is resetting then the link up is from * port hard reset in this case, we need to tell the port * that link up is recieved */ - BUG_ON(port_state != SCI_BASE_PORT_STATE_RESETTING); + BUG_ON(port_state != SCI_PORT_RESETTING); port_agent->phy_ready_mask |= 1 << phy_index; scic_sds_port_link_up(sci_port, sci_phy); } diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 68b63b04be19..6c93f20f3dd3 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -126,8 +126,7 @@ static void rnc_destruct_done(void *_dev) struct scic_sds_remote_device *sci_dev = _dev; BUG_ON(sci_dev->started_request_count != 0); - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); + sci_change_state(&sci_dev->sm, SCI_DEV_STOPPED); } static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds_remote_device *sci_dev) @@ -154,20 +153,20 @@ static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev, u32 timeout) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; switch (state) { - case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: - case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: - case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + case SCI_DEV_INITIAL: + case SCI_DEV_FAILED: + case SCI_DEV_FINAL: default: dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: + case SCI_DEV_STOPPED: return SCI_SUCCESS; - case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: + case SCI_DEV_STARTING: /* device not started so there had better be no requests */ BUG_ON(sci_dev->started_request_count != 0); scic_sds_remote_node_context_destruct(&sci_dev->rnc, @@ -175,17 +174,17 @@ enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev, /* Transition to the stopping state and wait for the * remote node to complete being posted and invalidated. */ - sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); + sci_change_state(sm, SCI_DEV_STOPPING); return SCI_SUCCESS; - case SCI_BASE_REMOTE_DEVICE_STATE_READY: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); + case SCI_DEV_READY: + case SCI_STP_DEV_IDLE: + case SCI_STP_DEV_CMD: + case SCI_STP_DEV_NCQ: + case SCI_STP_DEV_NCQ_ERROR: + case SCI_STP_DEV_AWAIT_RESET: + case SCI_SMP_DEV_IDLE: + case SCI_SMP_DEV_CMD: + sci_change_state(sm, SCI_DEV_STOPPING); if (sci_dev->started_request_count == 0) { scic_sds_remote_node_context_destruct(&sci_dev->rnc, rnc_destruct_done, sci_dev); @@ -193,70 +192,70 @@ enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev, } else return scic_sds_remote_device_terminate_requests(sci_dev); break; - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: + case SCI_DEV_STOPPING: /* All requests should have been terminated, but if there is an * attempt to stop a device already in the stopping state, then * try again to terminate. */ return scic_sds_remote_device_terminate_requests(sci_dev); - case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: - sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); + case SCI_DEV_RESETTING: + sci_change_state(sm, SCI_DEV_STOPPING); return SCI_SUCCESS; } } enum sci_status scic_remote_device_reset(struct scic_sds_remote_device *sci_dev) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; switch (state) { - case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: - case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: - case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: - case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: - case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + case SCI_DEV_INITIAL: + case SCI_DEV_STOPPED: + case SCI_DEV_STARTING: + case SCI_SMP_DEV_IDLE: + case SCI_SMP_DEV_CMD: + case SCI_DEV_STOPPING: + case SCI_DEV_FAILED: + case SCI_DEV_RESETTING: + case SCI_DEV_FINAL: default: dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; - case SCI_BASE_REMOTE_DEVICE_STATE_READY: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: - sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_RESETTING); + case SCI_DEV_READY: + case SCI_STP_DEV_IDLE: + case SCI_STP_DEV_CMD: + case SCI_STP_DEV_NCQ: + case SCI_STP_DEV_NCQ_ERROR: + case SCI_STP_DEV_AWAIT_RESET: + sci_change_state(sm, SCI_DEV_RESETTING); return SCI_SUCCESS; } } enum sci_status scic_remote_device_reset_complete(struct scic_sds_remote_device *sci_dev) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - if (state != SCI_BASE_REMOTE_DEVICE_STATE_RESETTING) { + if (state != SCI_DEV_RESETTING) { dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_READY); + sci_change_state(sm, SCI_DEV_READY); return SCI_SUCCESS; } enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sci_dev, u32 suspend_type) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - if (state != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD) { + if (state != SCI_STP_DEV_CMD) { dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; @@ -269,30 +268,30 @@ enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sc enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_device *sci_dev, u32 frame_index) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; enum sci_status status; switch (state) { - case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: - case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + case SCI_DEV_INITIAL: + case SCI_DEV_STOPPED: + case SCI_DEV_STARTING: + case SCI_STP_DEV_IDLE: + case SCI_SMP_DEV_IDLE: + case SCI_DEV_FINAL: default: dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); /* Return the frame back to the controller */ scic_sds_controller_release_frame(scic, frame_index); return SCI_FAILURE_INVALID_STATE; - case SCI_BASE_REMOTE_DEVICE_STATE_READY: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: - case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: - case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: { + case SCI_DEV_READY: + case SCI_STP_DEV_NCQ_ERROR: + case SCI_STP_DEV_AWAIT_RESET: + case SCI_DEV_STOPPING: + case SCI_DEV_FAILED: + case SCI_DEV_RESETTING: { struct scic_sds_request *sci_req; struct ssp_frame_hdr hdr; void *frame_header; @@ -319,7 +318,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi } break; } - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: { + case SCI_STP_DEV_NCQ: { struct dev_to_host_fis *hdr; status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, @@ -333,7 +332,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; /* TODO Check sactive and complete associated IO if any. */ - sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + sci_change_state(sm, SCI_STP_DEV_NCQ_ERROR); } else if (hdr->fis_type == FIS_REGD2H && (hdr->status & ATA_ERR)) { /* @@ -341,16 +340,15 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi * Treat this like an SDB error FIS ready reason. */ sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); + sci_change_state(&sci_dev->sm, SCI_STP_DEV_NCQ_ERROR); } else status = SCI_FAILURE; scic_sds_controller_release_frame(scic, frame_index); break; } - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCI_STP_DEV_CMD: + case SCI_SMP_DEV_CMD: /* The device does not process any UF received from the hardware while * in this state. All unsolicited frames are forwarded to the io request * object. @@ -365,18 +363,18 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; switch (state) { - case SCI_BASE_REMOTE_DEVICE_STATE_READY: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCI_DEV_READY: + case SCI_STP_DEV_IDLE: + case SCI_STP_DEV_CMD: + case SCI_STP_DEV_NCQ: + case SCI_STP_DEV_NCQ_ERROR: + case SCI_STP_DEV_AWAIT_RESET: + case SCI_SMP_DEV_IDLE: + case SCI_SMP_DEV_CMD: return true; default: return false; @@ -386,7 +384,7 @@ static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev) enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_device *sci_dev, u32 event_code) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; enum sci_status status; @@ -429,7 +427,7 @@ enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_devi if (status != SCI_SUCCESS) return status; - if (state == SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE) { + if (state == SCI_STP_DEV_IDLE) { /* We pick up suspension events to handle specifically to this * state. We resume the RNC right away. @@ -459,26 +457,26 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic struct scic_sds_remote_device *sci_dev, struct scic_sds_request *sci_req) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_port *sci_port = sci_dev->owning_port; struct isci_request *ireq = sci_req_to_ireq(sci_req); enum sci_status status; switch (state) { - case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: - case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: - case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: - case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: - case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + case SCI_DEV_INITIAL: + case SCI_DEV_STOPPED: + case SCI_DEV_STARTING: + case SCI_STP_DEV_NCQ_ERROR: + case SCI_DEV_STOPPING: + case SCI_DEV_FAILED: + case SCI_DEV_RESETTING: + case SCI_DEV_FINAL: default: dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; - case SCI_BASE_REMOTE_DEVICE_STATE_READY: + case SCI_DEV_READY: /* attempt to start an io request for this device object. The remote * device object will issue the start request for the io and if * successful it will start the request for the port object then @@ -494,7 +492,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic status = scic_sds_request_start(sci_req); break; - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: { + case SCI_STP_DEV_IDLE: { /* handle the start io operation for a sata device that is in * the command idle state. - Evalute the type of IO request to * be started - If its an NCQ request change to NCQ substate - @@ -519,15 +517,15 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic break; if (task->ata_task.use_ncq) - new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ; + new_state = SCI_STP_DEV_NCQ; else { sci_dev->working_request = sci_req; - new_state = SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD; + new_state = SCI_STP_DEV_CMD; } - sci_base_state_machine_change_state(sm, new_state); + sci_change_state(sm, new_state); break; } - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: { + case SCI_STP_DEV_NCQ: { struct sas_task *task = isci_request_access_task(ireq); if (task->ata_task.use_ncq) { @@ -544,9 +542,9 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic return SCI_FAILURE_INVALID_STATE; break; } - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + case SCI_STP_DEV_AWAIT_RESET: return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: + case SCI_SMP_DEV_IDLE: status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); if (status != SCI_SUCCESS) return status; @@ -560,11 +558,10 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic break; sci_dev->working_request = sci_req; - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + sci_change_state(&sci_dev->sm, SCI_SMP_DEV_CMD); break; - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCI_STP_DEV_CMD: + case SCI_SMP_DEV_CMD: /* device is already handling a command it can not accept new commands * until this one is complete. */ @@ -597,31 +594,31 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s struct scic_sds_remote_device *sci_dev, struct scic_sds_request *sci_req) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_port *sci_port = sci_dev->owning_port; enum sci_status status; switch (state) { - case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: - case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: - case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + case SCI_DEV_INITIAL: + case SCI_DEV_STOPPED: + case SCI_DEV_STARTING: + case SCI_STP_DEV_IDLE: + case SCI_SMP_DEV_IDLE: + case SCI_DEV_FAILED: + case SCI_DEV_FINAL: default: dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; - case SCI_BASE_REMOTE_DEVICE_STATE_READY: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: - case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: + case SCI_DEV_READY: + case SCI_STP_DEV_AWAIT_RESET: + case SCI_DEV_RESETTING: status = common_complete_io(sci_port, sci_dev, sci_req); break; - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: + case SCI_STP_DEV_CMD: + case SCI_STP_DEV_NCQ: + case SCI_STP_DEV_NCQ_ERROR: status = common_complete_io(sci_port, sci_dev, sci_req); if (status != SCI_SUCCESS) break; @@ -632,17 +629,17 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s * can reach RNC state handler, these IOs will be completed by RNC with * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ - sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET); + sci_change_state(sm, SCI_STP_DEV_AWAIT_RESET); } else if (scic_sds_remote_device_get_request_count(sci_dev) == 0) - sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + sci_change_state(sm, SCI_STP_DEV_IDLE); break; - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: + case SCI_SMP_DEV_CMD: status = common_complete_io(sci_port, sci_dev, sci_req); if (status != SCI_SUCCESS) break; - sci_base_state_machine_change_state(sm, SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + sci_change_state(sm, SCI_SMP_DEV_IDLE); break; - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: + case SCI_DEV_STOPPING: status = common_complete_io(sci_port, sci_dev, sci_req); if (status != SCI_SUCCESS) break; @@ -676,30 +673,30 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc struct scic_sds_remote_device *sci_dev, struct scic_sds_request *sci_req) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_port *sci_port = sci_dev->owning_port; enum sci_status status; switch (state) { - case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED: - case SCI_BASE_REMOTE_DEVICE_STATE_STARTING: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING: - case SCI_BASE_REMOTE_DEVICE_STATE_FAILED: - case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: - case SCI_BASE_REMOTE_DEVICE_STATE_FINAL: + case SCI_DEV_INITIAL: + case SCI_DEV_STOPPED: + case SCI_DEV_STARTING: + case SCI_SMP_DEV_IDLE: + case SCI_SMP_DEV_CMD: + case SCI_DEV_STOPPING: + case SCI_DEV_FAILED: + case SCI_DEV_RESETTING: + case SCI_DEV_FINAL: default: dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR: - case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET: + case SCI_STP_DEV_IDLE: + case SCI_STP_DEV_CMD: + case SCI_STP_DEV_NCQ: + case SCI_STP_DEV_NCQ_ERROR: + case SCI_STP_DEV_AWAIT_RESET: status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); if (status != SCI_SUCCESS) return status; @@ -717,7 +714,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc * management request. */ sci_dev->working_request = sci_req; - sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); + sci_change_state(sm, SCI_STP_DEV_CMD); /* The remote node context must cleanup the TCi to NCQ mapping * table. The only way to do this correctly is to either write @@ -739,7 +736,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc * post TC when RNC gets resumed. */ return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; - case SCI_BASE_REMOTE_DEVICE_STATE_READY: + case SCI_DEV_READY: status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); if (status != SCI_SUCCESS) return status; @@ -790,8 +787,7 @@ static void remote_device_resume_done(void *_dev) return; /* go 'ready' if we are not already in a ready state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_READY); + sci_change_state(&sci_dev->sm, SCI_DEV_READY); } static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) @@ -803,17 +799,16 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl /* For NCQ operation we do not issue a isci_remote_device_not_ready(). * As a result, avoid sending the ready notification. */ - if (sci_dev->state_machine.previous_state_id != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) + if (sci_dev->sm.previous_state_id != SCI_STP_DEV_NCQ) isci_remote_device_ready(scic_to_ihost(scic), idev); } static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); /* Initial state is a transitional state to the stopped state */ - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); + sci_change_state(&sci_dev->sm, SCI_DEV_STOPPED); } /** @@ -831,11 +826,11 @@ static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_mac */ static enum sci_status scic_remote_device_destruct(struct scic_sds_remote_device *sci_dev) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_controller *scic; - if (state != SCI_BASE_REMOTE_DEVICE_STATE_STOPPED) { + if (state != SCI_DEV_STOPPED) { dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; @@ -845,7 +840,7 @@ static enum sci_status scic_remote_device_destruct(struct scic_sds_remote_device scic_sds_controller_free_remote_node_context(scic, sci_dev, sci_dev->rnc.remote_node_index); sci_dev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_FINAL); + sci_change_state(sm, SCI_DEV_FINAL); return SCI_SUCCESS; } @@ -906,7 +901,7 @@ static void isci_remote_device_stop_complete(struct isci_host *ihost, static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); u32 prev_state; @@ -914,8 +909,8 @@ static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_mac /* If we are entering from the stopping state let the SCI User know that * the stop operation has completed. */ - prev_state = sci_dev->state_machine.previous_state_id; - if (prev_state == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) + prev_state = sci_dev->sm.previous_state_id; + if (prev_state == SCI_DEV_STOPPING) isci_remote_device_stop_complete(scic_to_ihost(scic), idev); scic_sds_controller_remote_device_stopped(scic, sci_dev); @@ -923,7 +918,7 @@ static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_mac static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_host *ihost = scic_to_ihost(scic); struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); @@ -934,7 +929,7 @@ static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_ma static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); struct domain_device *dev = idev->domain_dev; @@ -942,18 +937,16 @@ static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machi scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + sci_change_state(&sci_dev->sm, SCI_STP_DEV_IDLE); } else if (dev_is_expander(dev)) { - sci_base_state_machine_change_state(&sci_dev->state_machine, - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); + sci_change_state(&sci_dev->sm, SCI_SMP_DEV_IDLE); } else isci_remote_device_ready(scic_to_ihost(scic), idev); } static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); struct domain_device *dev = sci_dev_to_domain(sci_dev); if (dev->dev_type == SAS_END_DEV) { @@ -967,7 +960,7 @@ static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machin static void scic_sds_remote_device_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); scic_sds_remote_node_context_suspend( &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); @@ -975,14 +968,14 @@ static void scic_sds_remote_device_resetting_state_enter(struct sci_base_state_m static void scic_sds_remote_device_resetting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); } static void scic_sds_stp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); sci_dev->working_request = NULL; if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { @@ -999,7 +992,7 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter(struct sci_base static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); BUG_ON(sci_dev->working_request == NULL); @@ -1010,7 +1003,7 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); @@ -1021,7 +1014,7 @@ static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); isci_remote_device_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev)); @@ -1029,7 +1022,7 @@ static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base static void scic_sds_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); BUG_ON(sci_dev->working_request == NULL); @@ -1040,50 +1033,50 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter(struct sci_base_ static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), state_machine); + struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); sci_dev->working_request = NULL; } static const struct sci_base_state scic_sds_remote_device_state_table[] = { - [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { + [SCI_DEV_INITIAL] = { .enter_state = scic_sds_remote_device_initial_state_enter, }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { + [SCI_DEV_STOPPED] = { .enter_state = scic_sds_remote_device_stopped_state_enter, }, - [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { + [SCI_DEV_STARTING] = { .enter_state = scic_sds_remote_device_starting_state_enter, }, - [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { + [SCI_DEV_READY] = { .enter_state = scic_sds_remote_device_ready_state_enter, .exit_state = scic_sds_remote_device_ready_state_exit }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + [SCI_STP_DEV_IDLE] = { .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + [SCI_STP_DEV_CMD] = { .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { + [SCI_STP_DEV_NCQ] = { }, + [SCI_STP_DEV_NCQ_ERROR] = { .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, }, - [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { }, - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { + [SCI_STP_DEV_AWAIT_RESET] = { }, + [SCI_SMP_DEV_IDLE] = { .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, }, - [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { + [SCI_SMP_DEV_CMD] = { .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, }, - [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { }, - [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { }, - [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { + [SCI_DEV_STOPPING] = { }, + [SCI_DEV_FAILED] = { }, + [SCI_DEV_RESETTING] = { .enter_state = scic_sds_remote_device_resetting_state_enter, .exit_state = scic_sds_remote_device_resetting_state_exit }, - [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { }, + [SCI_DEV_FINAL] = { }, }; /** @@ -1102,11 +1095,11 @@ static void scic_remote_device_construct(struct scic_sds_port *sci_port, sci_dev->owning_port = sci_port; sci_dev->started_request_count = 0; - sci_base_state_machine_construct(&sci_dev->state_machine, + sci_base_state_machine_construct(&sci_dev->sm, scic_sds_remote_device_state_table, - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); + SCI_DEV_INITIAL); - sci_base_state_machine_start(&sci_dev->state_machine); + sci_base_state_machine_start(&sci_dev->sm); scic_sds_remote_node_context_construct(&sci_dev->rnc, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); @@ -1224,11 +1217,11 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *sci_dev, u32 timeout) { - struct sci_base_state_machine *sm = &sci_dev->state_machine; + struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; enum sci_status status; - if (state != SCI_BASE_REMOTE_DEVICE_STATE_STOPPED) { + if (state != SCI_DEV_STOPPED) { dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; @@ -1240,7 +1233,7 @@ static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *s if (status != SCI_SUCCESS) return status; - sci_base_state_machine_change_state(sm, SCI_BASE_REMOTE_DEVICE_STATE_STARTING); + sci_change_state(sm, SCI_DEV_STARTING); return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index a118f5873f64..2b6a5bb7bd60 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -74,7 +74,7 @@ struct scic_sds_remote_device { * This field contains the information for the base remote device state * machine. */ - struct sci_base_state_machine state_machine; + struct sci_base_state_machine sm; /** * This field is the programmed device port width. This value is @@ -109,7 +109,7 @@ struct scic_sds_remote_device { /** * This field contains the stated request count for the remote device. The - * device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all + * device can not reach the SCI_DEV_STOPPED until all * requests are complete and the rnc_posted value is false. */ u32 started_request_count; @@ -213,7 +213,7 @@ enum scic_sds_remote_device_states { /** * Simply the initial state for the base remote device state machine. */ - SCI_BASE_REMOTE_DEVICE_STATE_INITIAL, + SCI_DEV_INITIAL, /** * This state indicates that the remote device has successfully been @@ -221,7 +221,7 @@ enum scic_sds_remote_device_states { * This state is entered from the INITIAL state. * This state is entered from the STOPPING state. */ - SCI_BASE_REMOTE_DEVICE_STATE_STOPPED, + SCI_DEV_STOPPED, /** * This state indicates the the remote device is in the process of @@ -229,34 +229,34 @@ enum scic_sds_remote_device_states { * are permitted. * This state is entered from the STOPPED state. */ - SCI_BASE_REMOTE_DEVICE_STATE_STARTING, + SCI_DEV_STARTING, /** * This state indicates the remote device is now ready. Thus, the user * is able to perform IO operations on the remote device. * This state is entered from the STARTING state. */ - SCI_BASE_REMOTE_DEVICE_STATE_READY, + SCI_DEV_READY, /** * This is the idle substate for the stp remote device. When there are no * active IO for the device it is is in this state. */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, + SCI_STP_DEV_IDLE, /** * This is the command state for for the STP remote device. This state is * entered when the device is processing a non-NCQ command. The device object * will fail any new start IO requests until this command is complete. */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD, + SCI_STP_DEV_CMD, /** * This is the NCQ state for the STP remote device. This state is entered * when the device is processing an NCQ reuqest. It will remain in this state * so long as there is one or more NCQ requests being processed. */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ, + SCI_STP_DEV_NCQ, /** * This is the NCQ error state for the STP remote device. This state is @@ -264,25 +264,25 @@ enum scic_sds_remote_device_states { * NCQ state. The device object will only accept a READ LOG command while in * this state. */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR, + SCI_STP_DEV_NCQ_ERROR, /** * This is the READY substate indicates the device is waiting for the RESET task * coming to be recovered from certain hardware specific error. */ - SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, + SCI_STP_DEV_AWAIT_RESET, /** * This is the ready operational substate for the remote device. This is the * normal operational state for a remote device. */ - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, + SCI_SMP_DEV_IDLE, /** * This is the suspended state for the remote device. This is the state that * the device is placed in when a RNC suspend is received by the SCU hardware. */ - SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, + SCI_SMP_DEV_CMD, /** * This state indicates that the remote device is in the process of @@ -291,7 +291,7 @@ enum scic_sds_remote_device_states { * This state is entered from the READY state. * This state is entered from the FAILED state. */ - SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, + SCI_DEV_STOPPING, /** * This state indicates that the remote device has failed. @@ -299,19 +299,19 @@ enum scic_sds_remote_device_states { * This state is entered from the INITIALIZING state. * This state is entered from the READY state. */ - SCI_BASE_REMOTE_DEVICE_STATE_FAILED, + SCI_DEV_FAILED, /** * This state indicates the device is being reset. * In this state no new IO operations are permitted. * This state is entered from the READY state. */ - SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, + SCI_DEV_RESETTING, /** * Simply the final state for the base remote device state machine. */ - SCI_BASE_REMOTE_DEVICE_STATE_FINAL, + SCI_DEV_FINAL, }; static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index e7fa5bac7d53..24b1d8acf7b8 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -84,9 +84,9 @@ bool scic_sds_remote_node_context_is_ready( struct scic_sds_remote_node_context *sci_rnc) { - u32 current_state = sci_base_state_machine_get_state(&sci_rnc->state_machine); + u32 current_state = sci_rnc->sm.current_state_id; - if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { + if (current_state == SCI_RNC_READY) { return true; } @@ -268,12 +268,12 @@ static void scic_sds_remote_node_context_invalidate_context_buffer( static void scic_sds_remote_node_context_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); /* Check to see if we have gotten back to the initial state because * someone requested to destroy the remote node context object. */ - if (sm->previous_state_id == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE) { + if (sm->previous_state_id == SCI_RNC_INVALIDATING) { rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; scic_sds_remote_node_context_notify_user(rnc); } @@ -281,21 +281,21 @@ static void scic_sds_remote_node_context_initial_state_enter(struct sci_base_sta static void scic_sds_remote_node_context_posting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *sci_rnc = container_of(sm, typeof(*sci_rnc), state_machine); + struct scic_sds_remote_node_context *sci_rnc = container_of(sm, typeof(*sci_rnc), sm); scic_sds_remote_node_context_validate_context_buffer(sci_rnc); } static void scic_sds_remote_node_context_invalidating_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); scic_sds_remote_node_context_invalidate_context_buffer(rnc); } static void scic_sds_remote_node_context_resuming_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); struct scic_sds_remote_device *sci_dev; struct domain_device *dev; @@ -318,7 +318,7 @@ static void scic_sds_remote_node_context_resuming_state_enter(struct sci_base_st static void scic_sds_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; @@ -328,41 +328,41 @@ static void scic_sds_remote_node_context_ready_state_enter(struct sci_base_state static void scic_sds_remote_node_context_tx_suspended_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); scic_sds_remote_node_context_continue_state_transitions(rnc); } static void scic_sds_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), state_machine); + struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); scic_sds_remote_node_context_continue_state_transitions(rnc); } static const struct sci_base_state scic_sds_remote_node_context_state_table[] = { - [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { + [SCI_RNC_INITIAL] = { .enter_state = scic_sds_remote_node_context_initial_state_enter, }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { + [SCI_RNC_POSTING] = { .enter_state = scic_sds_remote_node_context_posting_state_enter, }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { + [SCI_RNC_INVALIDATING] = { .enter_state = scic_sds_remote_node_context_invalidating_state_enter, }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { + [SCI_RNC_RESUMING] = { .enter_state = scic_sds_remote_node_context_resuming_state_enter, }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { + [SCI_RNC_READY] = { .enter_state = scic_sds_remote_node_context_ready_state_enter, }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { + [SCI_RNC_TX_SUSPENDED] = { .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter, }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { + [SCI_RNC_TX_RX_SUSPENDED] = { .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter, }, - [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { }, + [SCI_RNC_AWAIT_SUSPENSION] = { }, }; void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, @@ -373,11 +373,11 @@ void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context rnc->remote_node_index = remote_node_index; rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - sci_base_state_machine_construct(&rnc->state_machine, + sci_base_state_machine_construct(&rnc->sm, scic_sds_remote_node_context_state_table, - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE); + SCI_RNC_INITIAL); - sci_base_state_machine_start(&rnc->state_machine); + sci_base_state_machine_start(&rnc->sm); } enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc, @@ -385,26 +385,24 @@ enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remot { enum scis_sds_remote_node_context_states state; - state = sci_rnc->state_machine.current_state_id; + state = sci_rnc->sm.current_state_id; switch (state) { - case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE: + case SCI_RNC_POSTING: switch (scu_get_event_code(event_code)) { case SCU_EVENT_POST_RNC_COMPLETE: - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_READY); break; default: goto out; } break; - case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE: + case SCI_RNC_INVALIDATING: if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) - state = SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE; + state = SCI_RNC_INITIAL; else - state = SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE; - sci_base_state_machine_change_state(&sci_rnc->state_machine, - state); + state = SCI_RNC_POSTING; + sci_change_state(&sci_rnc->sm, state); } else { switch (scu_get_event_type(event_code)) { case SCU_EVENT_TYPE_RNC_SUSPEND_TX: @@ -421,10 +419,9 @@ enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remot } } break; - case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE: + case SCI_RNC_RESUMING: if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) { - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_READY); } else { switch (scu_get_event_type(event_code)) { case SCU_EVENT_TYPE_RNC_SUSPEND_TX: @@ -441,32 +438,28 @@ enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remot } } break; - case SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE: + case SCI_RNC_READY: switch (scu_get_event_type(event_code)) { case SCU_EVENT_TL_RNC_SUSPEND_TX: - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED); sci_rnc->suspension_code = scu_get_event_specifier(event_code); break; case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED); sci_rnc->suspension_code = scu_get_event_specifier(event_code); break; default: goto out; } break; - case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE: + case SCI_RNC_AWAIT_SUSPENSION: switch (scu_get_event_type(event_code)) { case SCU_EVENT_TL_RNC_SUSPEND_TX: - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED); sci_rnc->suspension_code = scu_get_event_specifier(event_code); break; case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED); sci_rnc->suspension_code = scu_get_event_specifier(event_code); break; default: @@ -493,22 +486,21 @@ enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_nod { enum scis_sds_remote_node_context_states state; - state = sci_rnc->state_machine.current_state_id; + state = sci_rnc->sm.current_state_id; switch (state) { - case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE: + case SCI_RNC_INVALIDATING: scic_sds_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); return SCI_SUCCESS; - case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE: + case SCI_RNC_POSTING: + case SCI_RNC_RESUMING: + case SCI_RNC_READY: + case SCI_RNC_TX_SUSPENDED: + case SCI_RNC_TX_RX_SUSPENDED: + case SCI_RNC_AWAIT_SUSPENSION: scic_sds_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING); return SCI_SUCCESS; - case SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE: + case SCI_RNC_INITIAL: dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %d\n", __func__, state); /* We have decided that the destruct request on the remote node context @@ -530,8 +522,8 @@ enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node { enum scis_sds_remote_node_context_states state; - state = sci_rnc->state_machine.current_state_id; - if (state != SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { + state = sci_rnc->sm.current_state_id; + if (state != SCI_RNC_READY) { dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; @@ -546,8 +538,7 @@ enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); } - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION); return SCI_SUCCESS; } @@ -557,27 +548,26 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ { enum scis_sds_remote_node_context_states state; - state = sci_rnc->state_machine.current_state_id; + state = sci_rnc->sm.current_state_id; switch (state) { - case SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE: + case SCI_RNC_INITIAL: if (sci_rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_STATE; scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); scic_sds_remote_node_context_construct_buffer(sci_rnc); - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_POSTING); return SCI_SUCCESS; - case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE: + case SCI_RNC_POSTING: + case SCI_RNC_INVALIDATING: + case SCI_RNC_RESUMING: if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) return SCI_FAILURE_INVALID_STATE; sci_rnc->user_callback = cb_fn; sci_rnc->user_cookie = cb_p; return SCI_SUCCESS; - case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE: { + case SCI_RNC_TX_SUSPENDED: { struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); struct domain_device *dev = sci_dev_to_domain(sci_dev); @@ -585,27 +575,23 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev)) - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { if (sci_dev->is_direct_attached) { /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); } else { - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING); } } else return SCI_FAILURE; return SCI_SUCCESS; } - case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE: + case SCI_RNC_TX_RX_SUSPENDED: scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); - sci_base_state_machine_change_state(&sci_rnc->state_machine, - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE); + sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); return SCI_FAILURE_INVALID_STATE; - case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE: + case SCI_RNC_AWAIT_SUSPENSION: scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); return SCI_SUCCESS; default: @@ -620,8 +606,8 @@ enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_nod { enum scis_sds_remote_node_context_states state; - state = sci_rnc->state_machine.current_state_id; - if (state != SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { + state = sci_rnc->sm.current_state_id; + if (state != SCI_RNC_READY) { dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %d\n", __func__, state); return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; @@ -634,14 +620,14 @@ enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_n { enum scis_sds_remote_node_context_states state; - state = sci_rnc->state_machine.current_state_id; + state = sci_rnc->sm.current_state_id; switch (state) { - case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE: + case SCI_RNC_RESUMING: + case SCI_RNC_READY: + case SCI_RNC_AWAIT_SUSPENSION: return SCI_SUCCESS; - case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE: - case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE: + case SCI_RNC_TX_SUSPENDED: + case SCI_RNC_TX_RX_SUSPENDED: scic_sds_remote_node_context_resume(sci_rnc, NULL, NULL); return SCI_SUCCESS; default: diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index f53329f782c8..e6c7248be3f6 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -92,45 +92,45 @@ enum scis_sds_remote_node_context_states { * This state is the initial state for a remote node context. On a resume * request the remote node context will transition to the posting state. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE, + SCI_RNC_INITIAL, /** * This is a transition state that posts the RNi to the hardware. Once the RNC * is posted the remote node context will be made ready. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE, + SCI_RNC_POSTING, /** * This is a transition state that will post an RNC invalidate to the * hardware. Once the invalidate is complete the remote node context will * transition to the posting state. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE, + SCI_RNC_INVALIDATING, /** * This is a transition state that will post an RNC resume to the hardare. * Once the event notification of resume complete is received the remote node * context will transition to the ready state. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE, + SCI_RNC_RESUMING, /** * This is the state that the remote node context must be in to accept io * request operations. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE, + SCI_RNC_READY, /** * This is the state that the remote node context transitions to when it gets * a TX suspend notification from the hardware. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE, + SCI_RNC_TX_SUSPENDED, /** * This is the state that the remote node context transitions to when it gets * a TX RX suspend notification from the hardware. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE, + SCI_RNC_TX_RX_SUSPENDED, /** * This state is a wait state for the remote node context that waits for a @@ -138,7 +138,7 @@ enum scis_sds_remote_node_context_states { * there is a request to supend the remote node context or when there is a TC * completion where the remote node will be suspended by the hardware. */ - SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE + SCI_RNC_AWAIT_SUSPENSION }; /** @@ -194,7 +194,7 @@ struct scic_sds_remote_node_context { /** * This field contains the data for the object's state machine. */ - struct sci_base_state_machine state_machine; + struct sci_base_state_machine sm; }; void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 31c9b2c34259..89f0ab925c27 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -649,8 +649,7 @@ static enum sci_status scic_io_request_construct_basic_ssp(struct scic_sds_reque scic_sds_io_request_build_ssp_command_iu(sci_req); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); return SCI_SUCCESS; } @@ -664,8 +663,7 @@ enum sci_status scic_task_request_construct_ssp( /* Fill in the SSP Task IU */ scic_sds_task_request_build_ssp_task_iu(sci_req); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); return SCI_SUCCESS; } @@ -687,8 +685,7 @@ static enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_requ copy); if (status == SCI_SUCCESS) - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); return status; } @@ -718,8 +715,7 @@ enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_re if (status != SCI_SUCCESS) return status; - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); return status; } @@ -761,8 +757,8 @@ enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) scic_sds_remote_device_get_sequence(sci_req->target_device)) return SCI_FAILURE; - state = sci_req->state_machine.current_state_id; - if (state != SCI_BASE_REQUEST_STATE_CONSTRUCTED) { + state = sci_req->sm.current_state_id; + if (state != SCI_REQ_CONSTRUCTED) { dev_warn(scic_to_dev(scic), "%s: SCIC IO Request requested to start while in wrong " "state %d\n", __func__, state); @@ -818,8 +814,7 @@ enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) sci_req->post_context |= scic_sds_io_tag_get_index(sci_req->io_tag); /* Everything is good go ahead and change state */ - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_STARTED); + sci_change_state(&sci_req->sm, SCI_REQ_STARTED); return SCI_SUCCESS; } @@ -832,52 +827,47 @@ scic_sds_io_request_terminate(struct scic_sds_request *sci_req) { enum sci_base_request_states state; - state = sci_req->state_machine.current_state_id; + state = sci_req->sm.current_state_id; switch (state) { - case SCI_BASE_REQUEST_STATE_CONSTRUCTED: + case SCI_REQ_CONSTRUCTED: scic_sds_request_set_status(sci_req, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; - case SCI_BASE_REQUEST_STATE_STARTED: - case SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION: - case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE: - case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION: - case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE: - case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE: - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); + case SCI_REQ_STARTED: + case SCI_REQ_TASK_WAIT_TC_COMP: + case SCI_REQ_SMP_WAIT_RESP: + case SCI_REQ_SMP_WAIT_TC_COMP: + case SCI_REQ_STP_UDMA_WAIT_TC_COMP: + case SCI_REQ_STP_UDMA_WAIT_D2H: + case SCI_REQ_STP_NON_DATA_WAIT_H2D: + case SCI_REQ_STP_NON_DATA_WAIT_D2H: + case SCI_REQ_STP_PIO_WAIT_H2D: + case SCI_REQ_STP_PIO_WAIT_FRAME: + case SCI_REQ_STP_PIO_DATA_IN: + case SCI_REQ_STP_PIO_DATA_OUT: + case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED: + case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG: + case SCI_REQ_STP_SOFT_RESET_WAIT_D2H: + sci_change_state(&sci_req->sm, SCI_REQ_ABORTING); return SCI_SUCCESS; - case SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE: - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_ABORTING); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + case SCI_REQ_TASK_WAIT_TC_RESP: + sci_change_state(&sci_req->sm, SCI_REQ_ABORTING); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; - case SCI_BASE_REQUEST_STATE_ABORTING: - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + case SCI_REQ_ABORTING: + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; - case SCI_BASE_REQUEST_STATE_COMPLETED: + case SCI_REQ_COMPLETED: default: dev_warn(scic_to_dev(sci_req->owning_controller), "%s: SCIC IO Request requested to abort while in wrong " "state %d\n", __func__, - sci_base_state_machine_get_state(&sci_req->state_machine)); + sci_req->sm.current_state_id); break; } @@ -889,8 +879,8 @@ enum sci_status scic_sds_request_complete(struct scic_sds_request *sci_req) enum sci_base_request_states state; struct scic_sds_controller *scic = sci_req->owning_controller; - state = sci_req->state_machine.current_state_id; - if (WARN_ONCE(state != SCI_BASE_REQUEST_STATE_COMPLETED, + state = sci_req->sm.current_state_id; + if (WARN_ONCE(state != SCI_REQ_COMPLETED, "isci: request completion from wrong state (%d)\n", state)) return SCI_FAILURE_INVALID_STATE; @@ -902,8 +892,7 @@ enum sci_status scic_sds_request_complete(struct scic_sds_request *sci_req) sci_req->saved_rx_frame_index); /* XXX can we just stop the machine and remove the 'final' state? */ - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_FINAL); + sci_change_state(&sci_req->sm, SCI_REQ_FINAL); return SCI_SUCCESS; } @@ -913,9 +902,9 @@ enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_r enum sci_base_request_states state; struct scic_sds_controller *scic = sci_req->owning_controller; - state = sci_req->state_machine.current_state_id; + state = sci_req->sm.current_state_id; - if (state != SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE) { + if (state != SCI_REQ_STP_PIO_DATA_IN) { dev_warn(scic_to_dev(scic), "%s: (%x) in wrong state %d\n", __func__, event_code, state); @@ -927,8 +916,7 @@ enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_r /* We are waiting for data and the SCU has R_ERR the data frame. * Go back to waiting for the D2H Register FIS */ - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); return SCI_SUCCESS; default: dev_err(scic_to_dev(scic), @@ -967,8 +955,9 @@ static void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) memcpy(resp_buf, ssp_response->resp_data, len); } -static enum sci_status request_started_state_tc_event(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +request_started_state_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { struct ssp_response_iu *resp_iu; u8 datapres; @@ -1110,13 +1099,13 @@ static enum sci_status request_started_state_tc_event(struct scic_sds_request *s */ /* In all cases we will treat this as the completion of the IO req. */ - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; } -static enum sci_status request_aborting_state_tc_event(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +request_aborting_state_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): @@ -1124,8 +1113,7 @@ static enum sci_status request_aborting_state_tc_event(struct scic_sds_request * scic_sds_request_set_status(sci_req, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; default: @@ -1146,8 +1134,7 @@ static enum sci_status ssp_task_request_await_tc_event(struct scic_sds_request * scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); + sci_change_state(&sci_req->sm, SCI_REQ_TASK_WAIT_TC_RESP); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): /* Currently, the decision is to simply allow the task request @@ -1160,27 +1147,28 @@ static enum sci_status ssp_task_request_await_tc_event(struct scic_sds_request * "ACK/NAK timeout\n", __func__, sci_req, completion_code); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); + sci_change_state(&sci_req->sm, SCI_REQ_TASK_WAIT_TC_RESP); break; default: - /* All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. + /* + * All other completion status cause the IO to be complete. + * If a NAK was received, then it is up to the user to retry + * the request. */ scic_sds_request_set_status(sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; } return SCI_SUCCESS; } -static enum sci_status smp_request_await_response_tc_event(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +smp_request_await_response_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): @@ -1191,8 +1179,7 @@ static enum sci_status smp_request_await_response_tc_event(struct scic_sds_reque scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): @@ -1209,8 +1196,7 @@ static enum sci_status smp_request_await_response_tc_event(struct scic_sds_reque scic_sds_request_set_status(sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; default: @@ -1221,24 +1207,23 @@ static enum sci_status smp_request_await_response_tc_event(struct scic_sds_reque SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; } return SCI_SUCCESS; } -static enum sci_status smp_request_await_tc_event(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +smp_request_await_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; default: /* All other completion status cause the IO to be @@ -1249,8 +1234,7 @@ static enum sci_status smp_request_await_tc_event(struct scic_sds_request *sci_r SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; } @@ -1311,16 +1295,16 @@ static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic return current_sgl; } -static enum sci_status stp_request_non_data_await_h2d_tc_event(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +stp_request_non_data_await_h2d_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_NON_DATA_WAIT_D2H); break; default: @@ -1332,8 +1316,7 @@ static enum sci_status stp_request_non_data_await_h2d_tc_event(struct scic_sds_r SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; } @@ -1509,17 +1492,19 @@ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( return status; } -static enum sci_status stp_request_pio_await_h2d_completion_tc_event(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +stp_request_pio_await_h2d_completion_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { enum sci_status status = SCI_SUCCESS; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_GOOD, + SCI_SUCCESS); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); break; default: @@ -1531,16 +1516,16 @@ static enum sci_status stp_request_pio_await_h2d_completion_tc_event(struct scic SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; } return status; } -static enum sci_status pio_data_out_tx_done_tc_event(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +pio_data_out_tx_done_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { enum sci_status status = SCI_SUCCESS; bool all_frames_transferred = false; @@ -1566,28 +1551,24 @@ static enum sci_status pio_data_out_tx_done_tc_event(struct scic_sds_request *sc /* all data transferred. */ if (all_frames_transferred) { /* - * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE + * Change the state to SCI_REQ_STP_PIO_DATA_IN * and wait for PIO_SETUP fis / or D2H REg fis. */ - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE - ); + sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); } break; + default: /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ + * All other completion status cause the IO to be complete. + * If a NAK was received, then it is up to the user to retry + * the request. + */ scic_sds_request_set_status( sci_req, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR - ); + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state( - &sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED - ); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; } @@ -1600,8 +1581,7 @@ static void scic_sds_stp_request_udma_complete_request( enum sci_status sci_status) { scic_sds_request_set_status(request, scu_status, sci_status); - sci_base_state_machine_change_state(&request->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&request->sm, SCI_REQ_COMPLETED); } static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct scic_sds_request *sci_req, @@ -1632,8 +1612,9 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct sc return status; } -enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index) +enum sci_status +scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index) { struct scic_sds_controller *scic = sci_req->owning_controller; struct scic_sds_stp_request *stp_req = &sci_req->stp.req; @@ -1641,9 +1622,9 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r enum sci_status status; ssize_t word_cnt; - state = sci_req->state_machine.current_state_id; + state = sci_req->sm.current_state_id; switch (state) { - case SCI_BASE_REQUEST_STATE_STARTED: { + case SCI_REQ_STARTED: { struct ssp_frame_hdr ssp_hdr; void *frame_header; @@ -1684,20 +1665,21 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r } /* - * In any case we are done with this frame buffer return it to the - * controller + * In any case we are done with this frame buffer return it to + * the controller */ scic_sds_controller_release_frame(scic, frame_index); return SCI_SUCCESS; } - case SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE: + + case SCI_REQ_TASK_WAIT_TC_RESP: scic_sds_io_request_copy_response(sci_req); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); scic_sds_controller_release_frame(scic,frame_index); return SCI_SUCCESS; - case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE: { + + case SCI_REQ_SMP_WAIT_RESP: { struct smp_resp *rsp_hdr = &sci_req->smp.rsp; void *frame_header; @@ -1725,32 +1707,40 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION); + sci_change_state(&sci_req->sm, SCI_REQ_SMP_WAIT_TC_COMP); } else { - /* This was not a response frame why did it get forwarded? */ + /* + * This was not a response frame why did it get + * forwarded? + */ dev_err(scic_to_dev(scic), - "%s: SCIC SMP Request 0x%p received unexpected frame " - "%d type 0x%02x\n", __func__, sci_req, - frame_index, rsp_hdr->frame_type); + "%s: SCIC SMP Request 0x%p received unexpected " + "frame %d type 0x%02x\n", + __func__, + sci_req, + frame_index, + rsp_hdr->frame_type); scic_sds_request_set_status(sci_req, SCU_TASK_DONE_SMP_FRM_TYPE_ERR, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); } scic_sds_controller_release_frame(scic, frame_index); return SCI_SUCCESS; } - case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE: - return scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); - case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE: + + case SCI_REQ_STP_UDMA_WAIT_TC_COMP: + return scic_sds_stp_request_udma_general_frame_handler(sci_req, + frame_index); + + case SCI_REQ_STP_UDMA_WAIT_D2H: /* Use the general frame handler to copy the resposne data */ - status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index); + status = scic_sds_stp_request_udma_general_frame_handler(sci_req, + frame_index); if (status != SCI_SUCCESS) return status; @@ -1758,8 +1748,10 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r scic_sds_stp_request_udma_complete_request(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); + return SCI_SUCCESS; - case SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE: { + + case SCI_REQ_STP_NON_DATA_WAIT_D2H: { struct dev_to_host_fis *frame_header; u32 *frame_buffer; @@ -1769,9 +1761,12 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r if (status != SCI_SUCCESS) { dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); + "%s: SCIC IO Request 0x%p could not get frame " + "header for frame index %d, status %x\n", + __func__, + stp_req, + frame_index, + status); return status; } @@ -1802,15 +1797,15 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r break; } - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame(scic, frame_index); return status; } - case SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE: { + + case SCI_REQ_STP_PIO_WAIT_FRAME: { struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); struct dev_to_host_fis *frame_header; @@ -1822,8 +1817,8 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r if (status != SCI_SUCCESS) { dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", + "%s: SCIC IO Request 0x%p could not get frame " + "header for frame index %d, status %x\n", __func__, stp_req, frame_index, status); return status; } @@ -1835,9 +1830,10 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r frame_index, (void **)&frame_buffer); - /* Get the data from the PIO Setup The SCU Hardware returns - * first word in the frame_header and the rest of the data is in - * the frame buffer so we need to back up one dword + /* Get the data from the PIO Setup The SCU Hardware + * returns first word in the frame_header and the rest + * of the data is in the frame buffer so we need to + * back up one dword */ /* transfer_count: first 16bits in the 4th dword */ @@ -1856,31 +1852,33 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r * request was PIO Data-in or Data out */ if (task->data_dir == DMA_FROM_DEVICE) { - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_DATA_IN); } else if (task->data_dir == DMA_TO_DEVICE) { /* Transmit data */ status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); if (status != SCI_SUCCESS) break; - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_DATA_OUT); } break; + case FIS_SETDEVBITS: - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); break; + case FIS_REGD2H: if (frame_header->status & ATA_BUSY) { - /* Now why is the drive sending a D2H Register FIS when - * it is still busy? Do nothing since we are still in - * the right state. + /* + * Now why is the drive sending a D2H Register + * FIS when it is still busy? Do nothing since + * we are still in the right state. */ dev_dbg(scic_to_dev(scic), "%s: SCIC PIO Request 0x%p received " "D2H Register FIS with BSY status " - "0x%x\n", __func__, stp_req, + "0x%x\n", + __func__, + stp_req, frame_header->status); break; } @@ -1897,9 +1895,9 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; + default: /* FIXME: what do we do here? */ break; @@ -1910,7 +1908,8 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r return status; } - case SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE: { + + case SCI_REQ_STP_PIO_DATA_IN: { struct dev_to_host_fis *frame_header; struct sata_fis_data *frame_buffer; @@ -1920,9 +1919,12 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r if (status != SCI_SUCCESS) { dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); + "%s: SCIC IO Request 0x%p could not get frame " + "header for frame index %d, status %x\n", + __func__, + stp_req, + frame_index, + status); return status; } @@ -1930,15 +1932,17 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r dev_err(scic_to_dev(scic), "%s: SCIC PIO Request 0x%p received frame %d " "with fis type 0x%02x when expecting a data " - "fis.\n", __func__, stp_req, frame_index, + "fis.\n", + __func__, + stp_req, + frame_index, frame_header->fis_type); scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); /* Frame is decoded return it to the controller */ scic_sds_controller_release_frame(scic, frame_index); @@ -1972,15 +1976,14 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); } else { - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); } return status; } - case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE: { + + case SCI_REQ_STP_SOFT_RESET_WAIT_D2H: { struct dev_to_host_fis *frame_header; u32 *frame_buffer; @@ -1989,9 +1992,12 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r (void **)&frame_header); if (status != SCI_SUCCESS) { dev_err(scic_to_dev(scic), - "%s: SCIC IO Request 0x%p could not get frame header " - "for frame index %d, status %x\n", - __func__, stp_req, frame_index, status); + "%s: SCIC IO Request 0x%p could not get frame " + "header for frame index %d, status %x\n", + __func__, + stp_req, + frame_index, + status); return status; } @@ -2010,35 +2016,43 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); break; + default: dev_warn(scic_to_dev(scic), "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", __func__, stp_req, + "violation occurred\n", + __func__, + stp_req, frame_index); - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + scic_sds_request_set_status(sci_req, + SCU_TASK_DONE_UNEXP_FIS, SCI_FAILURE_PROTOCOL_VIOLATION); break; } - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame(scic, frame_index); return status; } - case SCI_BASE_REQUEST_STATE_ABORTING: - /* TODO: Is it even possible to get an unsolicited frame in the + case SCI_REQ_ABORTING: + /* + * TODO: Is it even possible to get an unsolicited frame in the * aborting state? */ scic_sds_controller_release_frame(scic, frame_index); return SCI_SUCCESS; + default: dev_warn(scic_to_dev(scic), - "%s: SCIC IO Request given unexpected frame %x while in " - "state %d\n", __func__, frame_index, state); + "%s: SCIC IO Request given unexpected frame %x while " + "in state %d\n", + __func__, + frame_index, + state); scic_sds_controller_release_frame(scic, frame_index); return SCI_FAILURE_INVALID_STATE; @@ -2075,8 +2089,7 @@ static enum sci_status stp_request_udma_await_tc_event(struct scic_sds_request * * the device so we must change state to wait * for it */ - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_UDMA_WAIT_D2H); } break; @@ -2105,45 +2118,45 @@ static enum sci_status stp_request_udma_await_tc_event(struct scic_sds_request * return status; } -static enum sci_status stp_request_soft_reset_await_h2d_asserted_tc_event(struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +stp_request_soft_reset_await_h2d_asserted_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG); break; default: /* - * All other completion status cause the IO to be complete. If a NAK - * was received, then it is up to the user to retry the request. */ + * All other completion status cause the IO to be complete. + * If a NAK was received, then it is up to the user to retry + * the request. + */ scic_sds_request_set_status(sci_req, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + SCU_NORMALIZE_COMPLETION_STATUS(completion_code), + SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; } return SCI_SUCCESS; } -static enum sci_status stp_request_soft_reset_await_h2d_diagnostic_tc_event( - struct scic_sds_request *sci_req, - u32 completion_code) +static enum sci_status +stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct scic_sds_request *sci_req, + u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE); + sci_change_state(&sci_req->sm, SCI_REQ_STP_SOFT_RESET_WAIT_D2H); break; default: @@ -2155,8 +2168,7 @@ static enum sci_status stp_request_soft_reset_await_h2d_diagnostic_tc_event( SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_COMPLETED); + sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); break; } @@ -2164,42 +2176,64 @@ static enum sci_status stp_request_soft_reset_await_h2d_diagnostic_tc_event( } enum sci_status -scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, u32 completion_code) +scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, + u32 completion_code) { enum sci_base_request_states state; struct scic_sds_controller *scic = sci_req->owning_controller; - state = sci_req->state_machine.current_state_id; + state = sci_req->sm.current_state_id; switch (state) { - case SCI_BASE_REQUEST_STATE_STARTED: - return request_started_state_tc_event(sci_req, completion_code); - case SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION: - return ssp_task_request_await_tc_event(sci_req, completion_code); - case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE: - return smp_request_await_response_tc_event(sci_req, completion_code); - case SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION: - return smp_request_await_tc_event(sci_req, completion_code); - case SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE: - return stp_request_udma_await_tc_event(sci_req, completion_code); - case SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE: - return stp_request_non_data_await_h2d_tc_event(sci_req, completion_code); - case SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE: - return stp_request_pio_await_h2d_completion_tc_event(sci_req, completion_code); - case SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE: - return pio_data_out_tx_done_tc_event(sci_req, completion_code); - case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE: - return stp_request_soft_reset_await_h2d_asserted_tc_event(sci_req, completion_code); - case SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE: - return stp_request_soft_reset_await_h2d_diagnostic_tc_event(sci_req, completion_code); - case SCI_BASE_REQUEST_STATE_ABORTING: - return request_aborting_state_tc_event(sci_req, completion_code); - default: - dev_warn(scic_to_dev(scic), - "%s: SCIC IO Request given task completion notification %x " - "while in wrong state %d\n", __func__, completion_code, - state); - return SCI_FAILURE_INVALID_STATE; + case SCI_REQ_STARTED: + return request_started_state_tc_event(sci_req, completion_code); + + case SCI_REQ_TASK_WAIT_TC_COMP: + return ssp_task_request_await_tc_event(sci_req, + completion_code); + + case SCI_REQ_SMP_WAIT_RESP: + return smp_request_await_response_tc_event(sci_req, + completion_code); + + case SCI_REQ_SMP_WAIT_TC_COMP: + return smp_request_await_tc_event(sci_req, completion_code); + + case SCI_REQ_STP_UDMA_WAIT_TC_COMP: + return stp_request_udma_await_tc_event(sci_req, + completion_code); + + case SCI_REQ_STP_NON_DATA_WAIT_H2D: + return stp_request_non_data_await_h2d_tc_event(sci_req, + completion_code); + + case SCI_REQ_STP_PIO_WAIT_H2D: + return stp_request_pio_await_h2d_completion_tc_event(sci_req, + completion_code); + + case SCI_REQ_STP_PIO_DATA_OUT: + return pio_data_out_tx_done_tc_event(sci_req, completion_code); + + case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED: + return stp_request_soft_reset_await_h2d_asserted_tc_event(sci_req, + completion_code); + + case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG: + return stp_request_soft_reset_await_h2d_diagnostic_tc_event(sci_req, + completion_code); + + case SCI_REQ_ABORTING: + return request_aborting_state_tc_event(sci_req, + completion_code); + + default: + dev_warn(scic_to_dev(scic), + "%s: SCIC IO Request given task completion " + "notification %x while in wrong state %d\n", + __func__, + completion_code, + state); + return SCI_FAILURE_INVALID_STATE; } } @@ -2896,7 +2930,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, static void scic_sds_request_started_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); struct isci_request *ireq = sci_req_to_ireq(sci_req); struct domain_device *dev = sci_dev_to_domain(sci_req->target_device); struct sas_task *task; @@ -2910,34 +2944,31 @@ static void scic_sds_request_started_state_enter(struct sci_base_state_machine * * substates */ if (!task && dev->dev_type == SAS_END_DEV) { - sci_base_state_machine_change_state(sm, - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION); + sci_change_state(sm, SCI_REQ_TASK_WAIT_TC_COMP); } else if (!task && (isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high || isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) { - sci_base_state_machine_change_state(sm, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE); + sci_change_state(sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED); } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { - sci_base_state_machine_change_state(sm, - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE); + sci_change_state(sm, SCI_REQ_SMP_WAIT_RESP); } else if (task && sas_protocol_ata(task->task_proto) && !task->ata_task.use_ncq) { u32 state; if (task->data_dir == DMA_NONE) - state = SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE; + state = SCI_REQ_STP_NON_DATA_WAIT_H2D; else if (task->ata_task.dma_xfer) - state = SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE; + state = SCI_REQ_STP_UDMA_WAIT_TC_COMP; else /* PIO */ - state = SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE; + state = SCI_REQ_STP_PIO_WAIT_H2D; - sci_base_state_machine_change_state(sm, state); + sci_change_state(sm, state); } } static void scic_sds_request_completed_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); struct scic_sds_controller *scic = sci_req->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); struct isci_request *ireq = sci_req_to_ireq(sci_req); @@ -2952,7 +2983,7 @@ static void scic_sds_request_completed_state_enter(struct sci_base_state_machine static void scic_sds_request_aborting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); /* Setting the abort bit in the Task Context is required by the silicon. */ sci_req->task_context_buffer->abort = 1; @@ -2960,7 +2991,7 @@ static void scic_sds_request_aborting_state_enter(struct sci_base_state_machine static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); scic_sds_remote_device_set_working_request(sci_req->target_device, sci_req); @@ -2968,7 +2999,7 @@ static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(str static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); scic_sds_remote_device_set_working_request(sci_req->target_device, sci_req); @@ -2976,7 +3007,7 @@ static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(struct s static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); scic_sds_remote_device_set_working_request(sci_req->target_device, sci_req); @@ -2984,7 +3015,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completio static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), state_machine); + struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); struct scu_task_context *task_context; struct host_to_dev_fis *h2d_fis; enum sci_status status; @@ -3003,51 +3034,53 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet } static const struct sci_base_state scic_sds_request_state_table[] = { - [SCI_BASE_REQUEST_STATE_INITIAL] = { }, - [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { }, - [SCI_BASE_REQUEST_STATE_STARTED] = { + [SCI_REQ_INIT] = { }, + [SCI_REQ_CONSTRUCTED] = { }, + [SCI_REQ_STARTED] = { .enter_state = scic_sds_request_started_state_enter, }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { + [SCI_REQ_STP_NON_DATA_WAIT_H2D] = { .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, }, - [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { + [SCI_REQ_STP_NON_DATA_WAIT_D2H] = { }, + [SCI_REQ_STP_PIO_WAIT_H2D] = { .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { + [SCI_REQ_STP_PIO_WAIT_FRAME] = { }, + [SCI_REQ_STP_PIO_DATA_IN] = { }, + [SCI_REQ_STP_PIO_DATA_OUT] = { }, + [SCI_REQ_STP_UDMA_WAIT_TC_COMP] = { }, + [SCI_REQ_STP_UDMA_WAIT_D2H] = { }, + [SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED] = { .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { + [SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG] = { .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, }, - [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { }, - [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { }, - [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { }, - [SCI_BASE_REQUEST_STATE_COMPLETED] = { + [SCI_REQ_STP_SOFT_RESET_WAIT_D2H] = { }, + [SCI_REQ_TASK_WAIT_TC_COMP] = { }, + [SCI_REQ_TASK_WAIT_TC_RESP] = { }, + [SCI_REQ_SMP_WAIT_RESP] = { }, + [SCI_REQ_SMP_WAIT_TC_COMP] = { }, + [SCI_REQ_COMPLETED] = { .enter_state = scic_sds_request_completed_state_enter, }, - [SCI_BASE_REQUEST_STATE_ABORTING] = { + [SCI_REQ_ABORTING] = { .enter_state = scic_sds_request_aborting_state_enter, }, - [SCI_BASE_REQUEST_STATE_FINAL] = { }, + [SCI_REQ_FINAL] = { }, }; -static void scic_sds_general_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - u16 io_tag, struct scic_sds_request *sci_req) +static void +scic_sds_general_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, + struct scic_sds_request *sci_req) { - sci_base_state_machine_construct(&sci_req->state_machine, + sci_base_state_machine_construct(&sci_req->sm, scic_sds_request_state_table, - SCI_BASE_REQUEST_STATE_INITIAL); - sci_base_state_machine_start(&sci_req->state_machine); + SCI_REQ_INIT); + sci_base_state_machine_start(&sci_req->sm); sci_req->io_tag = io_tag; sci_req->owning_controller = scic; @@ -3322,8 +3355,7 @@ scic_io_request_construct_smp(struct scic_sds_request *sci_req) scu_smp_request_construct_task_context(sci_req, smp_req->req_len); - sci_base_state_machine_change_state(&sci_req->state_machine, - SCI_BASE_REQUEST_STATE_CONSTRUCTED); + sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 31d6d5717473..757cd99ae2ed 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -96,37 +96,42 @@ struct scic_sds_stp_request { u32 udma; struct scic_sds_stp_pio_request { - /** - * Total transfer for the entire PIO request recorded at request constuction - * time. + /* + * Total transfer for the entire PIO request recorded + * at request constuction time. * - * @todo Should we just decrement this value for each byte of data transitted - * or received to elemenate the current_transfer_bytes field? + * @todo Should we just decrement this value for each + * byte of data transitted or received to elemenate + * the current_transfer_bytes field? */ u32 total_transfer_bytes; - /** - * Total number of bytes received/transmitted in data frames since the start - * of the IO request. At the end of the IO request this should equal the + /* + * Total number of bytes received/transmitted in data + * frames since the start of the IO request. At the + * end of the IO request this should equal the * total_transfer_bytes. */ u32 current_transfer_bytes; - /** - * The number of bytes requested in the in the PIO setup. + /* + * The number of bytes requested in the in the PIO + * setup. */ u32 pio_transfer_bytes; - /** - * PIO Setup ending status value to tell us if we need to wait for another FIS - * or if the transfer is complete. On the receipt of a D2H FIS this will be + /* + * PIO Setup ending status value to tell us if we need + * to wait for another FIS or if the transfer is + * complete. On the receipt of a D2H FIS this will be * the status field of that FIS. */ u8 ending_status; - /** - * On receipt of a D2H FIS this will be the ending error field if the - * ending_status has the SATA_STATUS_ERR bit set. + /* + * On receipt of a D2H FIS this will be the ending + * error field if the ending_status has the + * SATA_STATUS_ERR bit set. */ u8 ending_error; @@ -138,8 +143,9 @@ struct scic_sds_stp_request { } pio; struct { - /** - * The number of bytes requested in the PIO setup before CDB data frame. + /* + * The number of bytes requested in the PIO setup + * before CDB data frame. */ u32 device_preferred_cdb_length; } packet; @@ -147,57 +153,59 @@ struct scic_sds_stp_request { }; struct scic_sds_request { - /** - * This field contains the information for the base request state machine. + /* + * This field contains the information for the base request state + * machine. */ - struct sci_base_state_machine state_machine; + struct sci_base_state_machine sm; - /** + /* * This field simply points to the controller to which this IO request * is associated. */ struct scic_sds_controller *owning_controller; - /** - * This field simply points to the remote device to which this IO request - * is associated. + /* + * This field simply points to the remote device to which this IO + * request is associated. */ struct scic_sds_remote_device *target_device; - /** + /* * This field is utilized to determine if the SCI user is managing * the IO tag for this request or if the core is managing it. */ bool was_tag_assigned_by_user; - /** + /* * This field indicates the IO tag for this request. The IO tag is * comprised of the task_index and a sequence count. The sequence count * is utilized to help identify tasks from one life to another. */ u16 io_tag; - /** + /* * This field specifies the protocol being utilized for this * IO request. */ enum sci_request_protocol protocol; - /** + /* * This field indicates the completion status taken from the SCUs - * completion code. It indicates the completion result for the SCU hardware. + * completion code. It indicates the completion result for the SCU + * hardware. */ u32 scu_status; - /** - * This field indicates the completion status returned to the SCI user. It - * indicates the users view of the io request completion. + /* + * This field indicates the completion status returned to the SCI user. + * It indicates the users view of the io request completion. */ u32 sci_status; - /** - * This field contains the value to be utilized when posting (e.g. Post_TC, - * Post_TC_Abort) this request to the silicon. + /* + * This field contains the value to be utilized when posting + * (e.g. Post_TC, * Post_TC_Abort) this request to the silicon. */ u32 post_context; @@ -208,26 +216,26 @@ struct scic_sds_request { #define SCU_SGL_SIZE ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) struct scu_sgl_element_pair sg_table[SCU_SGL_SIZE] __attribute__ ((aligned(32))); - /** + /* * This field indicates if this request is a task management request or * normal IO request. */ bool is_task_management_request; - /** - * This field is a pointer to the stored rx frame data. It is used in STP - * internal requests and SMP response frames. If this field is non-NULL the - * saved frame must be released on IO request completion. + /* + * This field is a pointer to the stored rx frame data. It is used in + * STP internal requests and SMP response frames. If this field is + * non-NULL the saved frame must be released on IO request completion. * * @todo In the future do we want to keep a list of RX frame buffers? */ u32 saved_rx_frame_index; - /** - * This field in the recorded device sequence for the io request. This is - * recorded during the build operation and is compared in the start - * operation. If the sequence is different then there was a change of - * devices from the build to start operations. + /* + * This field in the recorded device sequence for the io request. + * This is recorded during the build operation and is compared in the + * start operation. If the sequence is different then there was a + * change of devices from the build to start operations. */ u8 device_sequence; @@ -286,7 +294,7 @@ struct isci_request { dma_addr_t request_daddr; dma_addr_t zero_scatter_daddr; - unsigned int num_sg_entries; /* returned by pci_alloc_sg */ + unsigned int num_sg_entries; /* returned by pci_alloc_sg */ /** Note: "io_request_completion" is completed in two different ways * depending on whether this is a TMF or regular request. @@ -315,104 +323,105 @@ static inline struct isci_request *sci_req_to_ireq(struct scic_sds_request *sci_ * */ enum sci_base_request_states { - /** + /* * Simply the initial state for the base request state machine. */ - SCI_BASE_REQUEST_STATE_INITIAL, + SCI_REQ_INIT, - /** - * This state indicates that the request has been constructed. This state - * is entered from the INITIAL state. + /* + * This state indicates that the request has been constructed. + * This state is entered from the INITIAL state. */ - SCI_BASE_REQUEST_STATE_CONSTRUCTED, + SCI_REQ_CONSTRUCTED, - /** - * This state indicates that the request has been started. This state is - * entered from the CONSTRUCTED state. + /* + * This state indicates that the request has been started. This state + * is entered from the CONSTRUCTED state. */ - SCI_BASE_REQUEST_STATE_STARTED, + SCI_REQ_STARTED, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, + SCI_REQ_STP_UDMA_WAIT_TC_COMP, + SCI_REQ_STP_UDMA_WAIT_D2H, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, + SCI_REQ_STP_NON_DATA_WAIT_H2D, + SCI_REQ_STP_NON_DATA_WAIT_D2H, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, - SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, + SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED, + SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG, + SCI_REQ_STP_SOFT_RESET_WAIT_D2H, - /** - * While in this state the IO request object is waiting for the TC completion - * notification for the H2D Register FIS + /* + * While in this state the IO request object is waiting for the TC + * completion notification for the H2D Register FIS */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE, + SCI_REQ_STP_PIO_WAIT_H2D, - /** - * While in this state the IO request object is waiting for either a PIO Setup - * FIS or a D2H register FIS. The type of frame received is based on the - * result of the prior frame and line conditions. + /* + * While in this state the IO request object is waiting for either a + * PIO Setup FIS or a D2H register FIS. The type of frame received is + * based on the result of the prior frame and line conditions. */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE, + SCI_REQ_STP_PIO_WAIT_FRAME, - /** - * While in this state the IO request object is waiting for a DATA frame from - * the device. + /* + * While in this state the IO request object is waiting for a DATA + * frame from the device. */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE, + SCI_REQ_STP_PIO_DATA_IN, - /** - * While in this state the IO request object is waiting to transmit the next data - * frame to the device. + /* + * While in this state the IO request object is waiting to transmit + * the next data frame to the device. */ - SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, + SCI_REQ_STP_PIO_DATA_OUT, - /** + /* * The AWAIT_TC_COMPLETION sub-state indicates that the started raw * task management request is waiting for the transmission of the * initial frame (i.e. command, task, etc.). */ - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, + SCI_REQ_TASK_WAIT_TC_COMP, - /** + /* * This sub-state indicates that the started task management request * is waiting for the reception of an unsolicited frame * (i.e. response IU). */ - SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, + SCI_REQ_TASK_WAIT_TC_RESP, - /** + /* * This sub-state indicates that the started task management request * is waiting for the reception of an unsolicited frame * (i.e. response IU). */ - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, + SCI_REQ_SMP_WAIT_RESP, - /** - * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is - * waiting for the transmission of the initial frame (i.e. command, task, etc.). + /* + * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP + * request is waiting for the transmission of the initial frame + * (i.e. command, task, etc.). */ - SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, + SCI_REQ_SMP_WAIT_TC_COMP, - /** + /* * This state indicates that the request has completed. - * This state is entered from the STARTED state. This state is entered from - * the ABORTING state. + * This state is entered from the STARTED state. This state is entered + * from the ABORTING state. */ - SCI_BASE_REQUEST_STATE_COMPLETED, + SCI_REQ_COMPLETED, - /** + /* * This state indicates that the request is in the process of being * terminated/aborted. * This state is entered from the CONSTRUCTED state. * This state is entered from the STARTED state. */ - SCI_BASE_REQUEST_STATE_ABORTING, + SCI_REQ_ABORTING, - /** + /* * Simply the final state for the base request state machine. */ - SCI_BASE_REQUEST_STATE_FINAL, + SCI_REQ_FINAL, }; /** @@ -498,13 +507,18 @@ enum sci_base_request_states { enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); -enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, - u32 event_code); -enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, - u32 frame_index); -enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req); -extern enum sci_status scic_sds_request_complete(struct scic_sds_request *sci_req); -extern enum sci_status scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, u32 code); +enum sci_status +scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, + u32 event_code); +enum sci_status +scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, + u32 frame_index); +enum sci_status +scic_sds_task_request_terminate(struct scic_sds_request *sci_req); +extern enum sci_status +scic_sds_request_complete(struct scic_sds_request *sci_req); +extern enum sci_status +scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, u32 code); /* XXX open code in caller */ static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, @@ -523,8 +537,8 @@ static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, } /* XXX open code in caller */ -static inline dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sci_req, - void *virt_addr) +static inline dma_addr_t +scic_io_request_get_dma_addr(struct scic_sds_request *sci_req, void *virt_addr) { struct isci_request *ireq = sci_req_to_ireq(sci_req); @@ -543,9 +557,8 @@ static inline dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *s * * status of the object as a isci_request_status enum. */ -static inline -enum isci_request_status isci_request_get_state( - struct isci_request *isci_request) +static inline enum isci_request_status +isci_request_get_state(struct isci_request *isci_request) { BUG_ON(isci_request == NULL); @@ -566,9 +579,9 @@ enum isci_request_status isci_request_get_state( * @status: This Parameter is the new status of the object * */ -static inline enum isci_request_status isci_request_change_state( - struct isci_request *isci_request, - enum isci_request_status status) +static inline enum isci_request_status +isci_request_change_state(struct isci_request *isci_request, + enum isci_request_status status) { enum isci_request_status old_state; unsigned long flags; @@ -597,10 +610,10 @@ static inline enum isci_request_status isci_request_change_state( * * state previous to any change. */ -static inline enum isci_request_status isci_request_change_started_to_newstate( - struct isci_request *isci_request, - struct completion *completion_ptr, - enum isci_request_status newstate) +static inline enum isci_request_status +isci_request_change_started_to_newstate(struct isci_request *isci_request, + struct completion *completion_ptr, + enum isci_request_status newstate) { enum isci_request_status old_state; unsigned long flags; @@ -615,6 +628,7 @@ static inline enum isci_request_status isci_request_change_started_to_newstate( isci_request->io_request_completion = completion_ptr; isci_request->status = newstate; } + spin_unlock_irqrestore(&isci_request->state_lock, flags); dev_dbg(&isci_request->isci_host->pdev->dev, @@ -635,13 +649,13 @@ static inline enum isci_request_status isci_request_change_started_to_newstate( * * state previous to any change. */ -static inline enum isci_request_status isci_request_change_started_to_aborted( - struct isci_request *isci_request, - struct completion *completion_ptr) +static inline enum isci_request_status +isci_request_change_started_to_aborted(struct isci_request *isci_request, + struct completion *completion_ptr) { - return isci_request_change_started_to_newstate( - isci_request, completion_ptr, aborted - ); + return isci_request_change_started_to_newstate(isci_request, + completion_ptr, + aborted); } /** * isci_request_free() - This function frees the request object. @@ -649,62 +663,33 @@ static inline enum isci_request_status isci_request_change_started_to_aborted( * @isci_request: This parameter points to the isci_request object * */ -static inline void isci_request_free( - struct isci_host *isci_host, - struct isci_request *isci_request) +static inline void isci_request_free(struct isci_host *isci_host, + struct isci_request *isci_request) { if (!isci_request) return; /* release the dma memory if we fail. */ - dma_pool_free(isci_host->dma_pool, isci_request, + dma_pool_free(isci_host->dma_pool, + isci_request, isci_request->request_daddr); } +#define isci_request_access_task(req) ((req)->ttype_ptr.io_task_ptr) -/* #define ISCI_REQUEST_VALIDATE_ACCESS - */ - -#ifdef ISCI_REQUEST_VALIDATE_ACCESS - -static inline -struct sas_task *isci_request_access_task(struct isci_request *isci_request) -{ - BUG_ON(isci_request->ttype != io_task); - return isci_request->ttype_ptr.io_task_ptr; -} - -static inline -struct isci_tmf *isci_request_access_tmf(struct isci_request *isci_request) -{ - BUG_ON(isci_request->ttype != tmf_task); - return isci_request->ttype_ptr.tmf_task_ptr; -} - -#else /* not ISCI_REQUEST_VALIDATE_ACCESS */ - -#define isci_request_access_task(RequestPtr) \ - ((RequestPtr)->ttype_ptr.io_task_ptr) - -#define isci_request_access_tmf(RequestPtr) \ - ((RequestPtr)->ttype_ptr.tmf_task_ptr) - -#endif /* not ISCI_REQUEST_VALIDATE_ACCESS */ - +#define isci_request_access_tmf(req) ((req)->ttype_ptr.tmf_task_ptr) -int isci_request_alloc_tmf( - struct isci_host *isci_host, - struct isci_tmf *isci_tmf, - struct isci_request **isci_request, - struct isci_remote_device *isci_device, - gfp_t gfp_flags); +int isci_request_alloc_tmf(struct isci_host *isci_host, + struct isci_tmf *isci_tmf, + struct isci_request **isci_request, + struct isci_remote_device *isci_device, + gfp_t gfp_flags); -int isci_request_execute( - struct isci_host *isci_host, - struct sas_task *task, - struct isci_request **request, - gfp_t gfp_flags); +int isci_request_execute(struct isci_host *isci_host, + struct sas_task *task, + struct isci_request **request, + gfp_t gfp_flags); /** * isci_request_unmap_sgl() - This function unmaps the DMA address of a given @@ -713,9 +698,8 @@ int isci_request_execute( * @*pdev: This Parameter is the pci_device struct for the controller * */ -static inline void isci_request_unmap_sgl( - struct isci_request *request, - struct pci_dev *pdev) +static inline void +isci_request_unmap_sgl(struct isci_request *request, struct pci_dev *pdev) { struct sas_task *task = isci_request_access_task(request); @@ -758,9 +742,9 @@ static inline void isci_request_unmap_sgl( * * pointer to the next sge for specified request. */ -static inline void *isci_request_io_request_get_next_sge( - struct isci_request *request, - void *current_sge_address) +static inline void * +isci_request_io_request_get_next_sge(struct isci_request *request, + void *current_sge_address) { struct sas_task *task = isci_request_access_task(request); void *ret = NULL; @@ -791,15 +775,20 @@ static inline void *isci_request_io_request_get_next_sge( return ret; } -void isci_terminate_pending_requests(struct isci_host *isci_host, - struct isci_remote_device *isci_device, - enum isci_request_status new_request_state); -enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, - u16 io_tag, - struct scic_sds_request *sci_req); -enum sci_status scic_task_request_construct_ssp(struct scic_sds_request *sci_req); -enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req); -void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); +void +isci_terminate_pending_requests(struct isci_host *isci_host, + struct isci_remote_device *isci_device, + enum isci_request_status new_request_state); +enum sci_status +scic_task_request_construct(struct scic_sds_controller *scic, + struct scic_sds_remote_device *sci_dev, + u16 io_tag, + struct scic_sds_request *sci_req); +enum sci_status +scic_task_request_construct_ssp(struct scic_sds_request *sci_req); +enum sci_status +scic_task_request_construct_sata(struct scic_sds_request *sci_req); +void +scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); #endif /* !defined(_ISCI_REQUEST_H_) */ diff --git a/drivers/scsi/isci/state_machine.c b/drivers/scsi/isci/state_machine.c index 1bcd925e502f..8cfefb959f22 100644 --- a/drivers/scsi/isci/state_machine.c +++ b/drivers/scsi/isci/state_machine.c @@ -127,16 +127,7 @@ void sci_base_state_machine_stop( sci_state_machine_exit_state(sm); } -/** - * This method performs an update to the current state of the state machine. - * @sm: This parameter specifies the state machine for which - * the caller wishes to perform a state change. - * @next_state: This parameter specifies the new state for the state machine. - * - */ -void sci_base_state_machine_change_state( - struct sci_base_state_machine *sm, - u32 next_state) +void sci_change_state(struct sci_base_state_machine *sm, u32 next_state) { sci_state_machine_exit_state(sm); @@ -145,18 +136,3 @@ void sci_base_state_machine_change_state( sci_state_machine_enter_state(sm); } - -/** - * This method simply returns the current state of the state machine to the - * caller. - * @sm: This parameter specifies the state machine for which to - * retrieve the current state. - * - * This method returns a u32 value indicating the current state for the - * supplied state machine. - */ -u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm) -{ - return sm->current_state_id; -} - diff --git a/drivers/scsi/isci/state_machine.h b/drivers/scsi/isci/state_machine.h index 067ed9126bf2..6cb55a0adc54 100644 --- a/drivers/scsi/isci/state_machine.h +++ b/drivers/scsi/isci/state_machine.h @@ -117,8 +117,6 @@ void sci_base_state_machine_construct(struct sci_base_state_machine *sm, u32 initial_state); void sci_base_state_machine_start(struct sci_base_state_machine *sm); void sci_base_state_machine_stop(struct sci_base_state_machine *sm); -void sci_base_state_machine_change_state(struct sci_base_state_machine *sm, - u32 next_state); -u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm); +void sci_change_state(struct sci_base_state_machine *sm, u32 next_state); #endif /* _SCI_BASE_STATE_MACHINE_H_ */ -- cgit v1.2.3 From 12ef65444de9d387a383b9991960848bed5bbe74 Mon Sep 17 00:00:00 2001 From: Edmund Nadolski Date: Thu, 2 Jun 2011 00:10:50 +0000 Subject: isci: additional state machine cleanup Additional state machine cleanups: o Remove static functions sci_state_machine_exit_state() and sci_state_machine_enter_state() o Combines sci_base_state_machine_construct() and sci_base_state_machine_start() into a single function, sci_init_sm() o Remove sci_base_state_machine_stop() which is unused. o Kill state_machine.[ch] Signed-off-by: Edmund Nadolski [fixed too large to inline functions] Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 1 - drivers/scsi/isci/host.c | 39 +++++++-- drivers/scsi/isci/host.h | 2 +- drivers/scsi/isci/isci.h | 19 +++++ drivers/scsi/isci/phy.c | 6 +- drivers/scsi/isci/phy.h | 2 +- drivers/scsi/isci/port.c | 6 +- drivers/scsi/isci/remote_device.c | 6 +- drivers/scsi/isci/remote_node_context.c | 8 +- drivers/scsi/isci/remote_node_context.h | 2 +- drivers/scsi/isci/request.c | 5 +- drivers/scsi/isci/state_machine.c | 138 -------------------------------- drivers/scsi/isci/state_machine.h | 122 ---------------------------- 13 files changed, 62 insertions(+), 294 deletions(-) delete mode 100644 drivers/scsi/isci/state_machine.c delete mode 100644 drivers/scsi/isci/state_machine.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index ad58fe3acc72..42449701ad9e 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -2,7 +2,6 @@ obj-$(CONFIG_SCSI_ISCI) += isci.o isci-objs := init.o phy.o request.o sata.o \ remote_device.o port.o \ host.o task.o probe_roms.o \ - state_machine.o \ remote_node_context.o \ remote_node_table.o \ unsolicited_frame_control.o \ diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 81ee64c0a4b7..f502882a2e17 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -197,6 +197,39 @@ */ #define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000) +/* Init the state machine and call the state entry function (if any) */ +void sci_init_sm(struct sci_base_state_machine *sm, + const struct sci_base_state *state_table, u32 initial_state) +{ + sci_state_transition_t handler; + + sm->initial_state_id = initial_state; + sm->previous_state_id = initial_state; + sm->current_state_id = initial_state; + sm->state_table = state_table; + + handler = sm->state_table[initial_state].enter_state; + if (handler) + handler(sm); +} + +/* Call the state exit fn, update the current state, call the state entry fn */ +void sci_change_state(struct sci_base_state_machine *sm, u32 next_state) +{ + sci_state_transition_t handler; + + handler = sm->state_table[sm->current_state_id].exit_state; + if (handler) + handler(sm); + + sm->previous_state_id = sm->current_state_id; + sm->current_state_id = next_state; + + handler = sm->state_table[sm->current_state_id].enter_state; + if (handler) + handler(sm); +} + static bool scic_sds_controller_completion_queue_has_entries( struct scic_sds_controller *scic) { @@ -1807,11 +1840,7 @@ static enum sci_status scic_controller_construct(struct scic_sds_controller *sci struct isci_host *ihost = scic_to_ihost(scic); u8 i; - sci_base_state_machine_construct(&scic->sm, - scic_sds_controller_state_table, - SCIC_INITIAL); - - sci_base_state_machine_start(&scic->sm); + sci_init_sm(&scic->sm, scic_sds_controller_state_table, SCIC_INITIAL); scic->scu_registers = scu_base; scic->smu_registers = smu_base; diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index be09765ee1d5..4020cf7b6f2a 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -58,7 +58,7 @@ #include "remote_device.h" #include "phy.h" #include "pool.h" -#include "state_machine.h" +#include "isci.h" #include "remote_node_table.h" #include "registers.h" #include "scu_unsolicited_frame.h" diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 2fe5557d8590..80cfb45f8da1 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -57,6 +57,7 @@ #define __ISCI_H__ #include +#include #define DRV_NAME "isci" #define SCI_PCI_BAR_COUNT 2 @@ -584,4 +585,22 @@ static inline void sci_del_timer(struct sci_timer *tmr) del_timer(&tmr->timer); } +struct sci_base_state_machine { + const struct sci_base_state *state_table; + u32 initial_state_id; + u32 current_state_id; + u32 previous_state_id; +}; + +typedef void (*sci_state_transition_t)(struct sci_base_state_machine *sm); + +struct sci_base_state { + sci_state_transition_t enter_state; /* Called on state entry */ + sci_state_transition_t exit_state; /* Called on state exit */ +}; + +extern void sci_init_sm(struct sci_base_state_machine *sm, + const struct sci_base_state *state_table, + u32 initial_state); +extern void sci_change_state(struct sci_base_state_machine *sm, u32 next_state); #endif /* __ISCI_H__ */ diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 9de21c719351..784c9a71333a 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -1294,11 +1294,7 @@ static const struct sci_base_state scic_sds_phy_state_table[] = { void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, struct scic_sds_port *owning_port, u8 phy_index) { - sci_base_state_machine_construct(&sci_phy->sm, - scic_sds_phy_state_table, - SCI_PHY_INITIAL); - - sci_base_state_machine_start(&sci_phy->sm); + sci_init_sm(&sci_phy->sm, scic_sds_phy_state_table, SCI_PHY_INITIAL); /* Copy the rest of the input data to our locals */ sci_phy->owning_port = owning_port; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 9d21d2754dbb..97ebee16f4b3 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -57,7 +57,7 @@ #include #include -#include "state_machine.h" +#include "isci.h" #include "sas.h" /* This is the timeout value for the SATA phy to wait for a SIGNATURE FIS diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 6370b93bd6ae..74f06f3c0735 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1807,11 +1807,7 @@ static const struct sci_base_state scic_sds_port_state_table[] = { void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, struct scic_sds_controller *scic) { - sci_base_state_machine_construct(&sci_port->sm, - scic_sds_port_state_table, - SCI_PORT_STOPPED); - - sci_base_state_machine_start(&sci_port->sm); + sci_init_sm(&sci_port->sm, scic_sds_port_state_table, SCI_PORT_STOPPED); sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; sci_port->physical_port_index = index; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 6c93f20f3dd3..3b555dcbe569 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1095,11 +1095,7 @@ static void scic_remote_device_construct(struct scic_sds_port *sci_port, sci_dev->owning_port = sci_port; sci_dev->started_request_count = 0; - sci_base_state_machine_construct(&sci_dev->sm, - scic_sds_remote_device_state_table, - SCI_DEV_INITIAL); - - sci_base_state_machine_start(&sci_dev->sm); + sci_init_sm(&sci_dev->sm, scic_sds_remote_device_state_table, SCI_DEV_INITIAL); scic_sds_remote_node_context_construct(&sci_dev->rnc, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 24b1d8acf7b8..9e8967e19688 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -54,7 +54,7 @@ */ #include "host.h" -#include "state_machine.h" +#include "isci.h" #include "remote_device.h" #include "remote_node_context.h" #include "scu_event_codes.h" @@ -373,11 +373,7 @@ void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context rnc->remote_node_index = remote_node_index; rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - sci_base_state_machine_construct(&rnc->sm, - scic_sds_remote_node_context_state_table, - SCI_RNC_INITIAL); - - sci_base_state_machine_start(&rnc->sm); + sci_init_sm(&rnc->sm, scic_sds_remote_node_context_state_table, SCI_RNC_INITIAL); } enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc, diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index e6c7248be3f6..67a45b686a98 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -64,7 +64,7 @@ * */ -#include "state_machine.h" +#include "isci.h" /** * diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 89f0ab925c27..8bd1f7dbad37 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -3077,10 +3077,7 @@ scic_sds_general_request_construct(struct scic_sds_controller *scic, u16 io_tag, struct scic_sds_request *sci_req) { - sci_base_state_machine_construct(&sci_req->sm, - scic_sds_request_state_table, - SCI_REQ_INIT); - sci_base_state_machine_start(&sci_req->sm); + sci_init_sm(&sci_req->sm, scic_sds_request_state_table, SCI_REQ_INIT); sci_req->io_tag = io_tag; sci_req->owning_controller = scic; diff --git a/drivers/scsi/isci/state_machine.c b/drivers/scsi/isci/state_machine.c deleted file mode 100644 index 8cfefb959f22..000000000000 --- a/drivers/scsi/isci/state_machine.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains all of the functionality common to all state machine - * object implementations. - * - * - */ - -#include "state_machine.h" - -static void sci_state_machine_exit_state(struct sci_base_state_machine *sm) -{ - u32 state = sm->current_state_id; - sci_state_transition_t exit = sm->state_table[state].exit_state; - - if (exit) - exit(sm); -} - -static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) -{ - u32 state = sm->current_state_id; - sci_state_transition_t enter = sm->state_table[state].enter_state; - - if (enter) - enter(sm); -} - -/** - * This method will set the initial state and state table for the state - * machine. The caller should follow this request with the initialize - * request to cause the state machine to start. - * @sm: This parameter provides the state machine object to be - * constructed. - * @state_table: This parameter specifies the table of state objects that is - * managed by this state machine. - * @initial_state: This parameter specifies the value of the initial state for - * this state machine. - * - */ -void sci_base_state_machine_construct(struct sci_base_state_machine *sm, - const struct sci_base_state *state_table, - u32 initial_state) -{ - sm->initial_state_id = initial_state; - sm->previous_state_id = initial_state; - sm->current_state_id = initial_state; - sm->state_table = state_table; -} - -/** - * This method will cause the state machine to enter the initial state. - * @sm: This parameter specifies the state machine that is to - * be started. - * - * sci_base_state_machine_construct() for how to set the initial state none - */ -void sci_base_state_machine_start(struct sci_base_state_machine *sm) -{ - sm->current_state_id = sm->initial_state_id; - sci_state_machine_enter_state(sm); -} - -/** - * This method will cause the state machine to exit it's current state only. - * @sm: This parameter specifies the state machine that is to - * be stopped. - * - */ -void sci_base_state_machine_stop( - struct sci_base_state_machine *sm) -{ - sci_state_machine_exit_state(sm); -} - -void sci_change_state(struct sci_base_state_machine *sm, u32 next_state) -{ - sci_state_machine_exit_state(sm); - - sm->previous_state_id = sm->current_state_id; - sm->current_state_id = next_state; - - sci_state_machine_enter_state(sm); -} diff --git a/drivers/scsi/isci/state_machine.h b/drivers/scsi/isci/state_machine.h deleted file mode 100644 index 6cb55a0adc54..000000000000 --- a/drivers/scsi/isci/state_machine.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SCI_BASE_STATE_MACHINE_H_ -#define _SCI_BASE_STATE_MACHINE_H_ - -#include - -struct sci_base_state_machine; -typedef void (*sci_base_state_handler_t)(void); -typedef void (*sci_state_transition_t)(struct sci_base_state_machine *sm); - -/** - * struct sci_base_state - The base state object abstracts the fields common to - * all state objects defined in SCI. - * - * - */ -struct sci_base_state { - /** - * This field is a function pointer that defines the method to be - * invoked when the state is entered. - */ - sci_state_transition_t enter_state; - - /** - * This field is a function pointer that defines the method to be - * invoked when the state is exited. - */ - sci_state_transition_t exit_state; -}; - -/** - * struct sci_base_state_machine - This structure defines the fields common to - * all state machines. - * - * - */ -struct sci_base_state_machine { - /** - * This field points to the start of the state machine's state table. - */ - const struct sci_base_state *state_table; - - /** - * This field simply indicates the state value for the state machine's - * initial state. - */ - u32 initial_state_id; - - /** - * This field indicates the current state of the state machine. - */ - u32 current_state_id; - - /** - * This field indicates the previous state of the state machine. - */ - u32 previous_state_id; - -}; - -void sci_base_state_machine_construct(struct sci_base_state_machine *sm, - const struct sci_base_state *state_table, - u32 initial_state); -void sci_base_state_machine_start(struct sci_base_state_machine *sm); -void sci_base_state_machine_stop(struct sci_base_state_machine *sm); -void sci_change_state(struct sci_base_state_machine *sm, u32 next_state); - -#endif /* _SCI_BASE_STATE_MACHINE_H_ */ -- cgit v1.2.3 From dbb0743a58825d94f1b3fdfa90a8d61dfef88f7b Mon Sep 17 00:00:00 2001 From: Adam Gruchala Date: Wed, 1 Jun 2011 22:31:03 +0000 Subject: isci: Added support for C0 to SCU Driver C0 silicon updates the pci revision id and requires new AFE parameters for phy signal integrity. Support for previous silicon revisions is deprecated (it's also broken for the theoretical case of multiple controllers at different silicon revisions, all the more reason to get it removed as soon as possible) Signed-off-by: Adam Gruchala [fixed up deprecated silicon support] Signed-off-by: Dan Williams --- drivers/scsi/isci/firmware/create_fw.h | 8 +++---- drivers/scsi/isci/host.c | 40 +++++++++++++++++++++++++++++----- drivers/scsi/isci/host.h | 8 ++++++- drivers/scsi/isci/init.c | 32 +++++++++++++-------------- drivers/scsi/isci/probe_roms.c | 15 +++++++++++++ firmware/isci/isci_firmware.bin.ihex | 24 ++++++++++---------- 6 files changed, 88 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h index 9f9afbd97d69..5f298828d22e 100644 --- a/drivers/scsi/isci/firmware/create_fw.h +++ b/drivers/scsi/isci/firmware/create_fw.h @@ -65,10 +65,10 @@ static const int max_num_concurrent_dev_spin_up = 1; static const int enable_ssc; /* AFE_TX_AMP_CONTROL */ -static const unsigned int afe_tx_amp_control0 = 0x000e7c03; -static const unsigned int afe_tx_amp_control1 = 0x000e7c03; -static const unsigned int afe_tx_amp_control2 = 0x000e7c03; -static const unsigned int afe_tx_amp_control3 = 0x000e7c03; +static const unsigned int afe_tx_amp_control0 = 0x000bdd08; +static const unsigned int afe_tx_amp_control1 = 0x000ffc00; +static const unsigned int afe_tx_amp_control2 = 0x000b7c09; +static const unsigned int afe_tx_amp_control3 = 0x000afc6e; static const char blob_name[] = "isci_firmware.bin"; static const char sig[] = "ISCUOEMB"; diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index f502882a2e17..009c0ee83ed6 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -2070,13 +2070,13 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s writel(0x00005500, &scic->scu_registers->afe.afe_bias_control); else if (is_a2()) writel(0x00005A00, &scic->scu_registers->afe.afe_bias_control); - else if (is_b0()) + else if (is_b0() || is_c0()) writel(0x00005F00, &scic->scu_registers->afe.afe_bias_control); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable PLL */ - if (is_b0()) + if (is_b0() || is_c0()) writel(0x80040A08, &scic->scu_registers->afe.afe_pll_control0); else writel(0x80040908, &scic->scu_registers->afe.afe_pll_control0); @@ -2102,6 +2102,16 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s /* Configure transmitter SSC parameters */ writel(0x00030000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); + } else if (is_c0()) { + /* Configure transmitter SSC parameters */ + writel(0x0003000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); + udelay(AFE_REGISTER_WRITE_DELAY); + + /* + * All defaults, except the Receive Word Alignament/Comma Detect + * Enable....(0xe800) */ + writel(0x00004500, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + udelay(AFE_REGISTER_WRITE_DELAY); } else { /* * All defaults, except the Receive Word Alignament/Comma Detect @@ -2120,15 +2130,23 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); else if (is_a2()) writel(0x000003F0, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); - else { + else if (is_b0()) { /* Power down TX and RX (PWRDNTX and PWRDNRX) */ - writel(0x000003d7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000003D7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + udelay(AFE_REGISTER_WRITE_DELAY); + + /* + * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) + * & increase TX int & ext bias 20%....(0xe85c) */ + writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + } else { + writel(0x000001E7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); /* * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) * & increase TX int & ext bias 20%....(0xe85c) */ - writel(0x000003d4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000001E4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); } udelay(AFE_REGISTER_WRITE_DELAY); @@ -2149,12 +2167,22 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s writel(0x3F09983F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); else if (is_a2()) writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); - else { + else if (is_b0()) { writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); udelay(AFE_REGISTER_WRITE_DELAY); + /* Enable TX equalization (0xe824) */ + writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + } else { + writel(0x0140DF0F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control1); + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(0x3F6F103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + /* Enable TX equalization (0xe824) */ writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); } + udelay(AFE_REGISTER_WRITE_DELAY); writel(oem_phy->afe_tx_amp_control0, diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 4020cf7b6f2a..04698dd75ad6 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -675,6 +675,7 @@ enum { ISCI_SI_REVA0, ISCI_SI_REVA2, ISCI_SI_REVB0, + ISCI_SI_REVC0 }; extern int isci_si_rev; @@ -691,7 +692,12 @@ static inline bool is_a2(void) static inline bool is_b0(void) { - return isci_si_rev > ISCI_SI_REVA2; + return isci_si_rev == ISCI_SI_REVB0; +} + +static inline bool is_c0(void) +{ + return isci_si_rev > ISCI_SI_REVB0; } void scic_sds_controller_post_request(struct scic_sds_controller *scic, diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index bda701655b25..bbfb6e563207 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -437,27 +437,27 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) static void check_si_rev(struct pci_dev *pdev) { - if (num_controllers(pdev) > 1) + switch (pdev->revision) { + case 0: + case 1: + /* if the id is ambiguous don't update isci_si_rev */ + break; + case 3: + isci_si_rev = ISCI_SI_REVA2; + break; + case 4: isci_si_rev = ISCI_SI_REVB0; - else { - switch (pdev->revision) { - case 0: - case 1: - /* if the id is ambiguous don't update isci_si_rev */ - break; - case 3: - isci_si_rev = ISCI_SI_REVA2; - break; - default: - case 4: - isci_si_rev = ISCI_SI_REVB0; - break; - } + break; + default: + case 5: + isci_si_rev = ISCI_SI_REVC0; + break; } dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n", isci_si_rev == ISCI_SI_REVA0 ? "A0" : - isci_si_rev == ISCI_SI_REVA2 ? "A2" : "B0", pdev->revision); + isci_si_rev == ISCI_SI_REVA2 ? "A2" : + isci_si_rev == ISCI_SI_REVB0 ? "B0" : "C0", pdev->revision); } diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 084fdc60548f..bc52a6174070 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -136,6 +136,7 @@ enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw) { struct isci_orom *orom = NULL, *data; + int i, j; if (request_firmware(&fw, ISCI_FW_NAME, &pdev->dev) != 0) return NULL; @@ -155,6 +156,20 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw memcpy(orom, fw->data, fw->size); + /* + * deprecated: override default amp_control for pre-preproduction + * silicon revisions + */ + if (isci_si_rev <= ISCI_SI_REVB0) + goto out; + + for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++) + for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) { + orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03; + orom->ctrl[i].phys[j].afe_tx_amp_control1 = 0xe7c03; + orom->ctrl[i].phys[j].afe_tx_amp_control2 = 0xe7c03; + orom->ctrl[i].phys[j].afe_tx_amp_control3 = 0xe7c03; + } out: release_firmware(fw); diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex index 13a9655dfc93..2e6619570072 100644 --- a/firmware/isci/isci_firmware.bin.ihex +++ b/firmware/isci/isci_firmware.bin.ihex @@ -1,16 +1,16 @@ :10000000495343554F454D42E80018100002000087 :1000100000000000000000000101000000000000DE -:10002000FFFFCF5F01000000037C0E00037C0E0089 -:10003000037C0E00037C0E00FFFFCF5F0100000079 -:10004000037C0E00037C0E00037C0E00037C0E007C -:10005000FFFFCF5F01000000037C0E00037C0E0059 -:10006000037C0E00037C0E00FFFFCF5F0100000049 -:10007000037C0E00037C0E00037C0E00037C0E004C +:10002000FFFFCF5F0100000008DD0B0000FC0F00A8 +:10003000097C0B006EFC0A00FFFFCF5F010000008F +:1000400008DD0B0000FC0F00097C0B006EFC0A00B1 +:10005000FFFFCF5F0100000008DD0B0000FC0F0078 +:10006000097C0B006EFC0A00FFFFCF5F010000005F +:1000700008DD0B0000FC0F00097C0B006EFC0A0081 :100080000101000000000000FFFFCF5F0200000040 -:10009000037C0E00037C0E00037C0E00037C0E002C -:1000A000FFFFCF5F02000000037C0E00037C0E0008 -:1000B000037C0E00037C0E00FFFFCF5F02000000F8 -:1000C000037C0E00037C0E00037C0E00037C0E00FC -:1000D000FFFFCF5F02000000037C0E00037C0E00D8 -:0800E000037C0E00037C0E00FE +:1000900008DD0B0000FC0F00097C0B006EFC0A0061 +:1000A000FFFFCF5F0200000008DD0B0000FC0F0027 +:1000B000097C0B006EFC0A00FFFFCF5F020000000E +:1000C00008DD0B0000FC0F00097C0B006EFC0A0031 +:1000D000FFFFCF5F0200000008DD0B0000FC0F00F7 +:0800E000097C0B006EFC0A0014 :00000001FF -- cgit v1.2.3 From 7c78da3175177c905a75c54b5830029c778494ea Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 1 Jun 2011 16:00:01 -0700 Subject: isci: remove 'min memory' infrastructure The old 'core' had aspirations of running in severely memory constrained environments like bios option-rom, it's not needed for Linux and gets in the way of other cleanups (like unifying/reducing the number of structure members in scic_sds_controller/isci_host). This also fixes a theoretical bug in that the driver would blindly override the silicon advertised limits for number of ports, task contexts, and remote node contexts. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 305 ++++++++------------------ drivers/scsi/isci/host.h | 13 -- drivers/scsi/isci/isci.h | 90 +------- drivers/scsi/isci/request.h | 2 +- drivers/scsi/isci/unsolicited_frame_control.c | 186 ++++------------ drivers/scsi/isci/unsolicited_frame_control.h | 20 +- 6 files changed, 144 insertions(+), 472 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 009c0ee83ed6..41a7c5099dea 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -70,46 +70,24 @@ #define SCU_CONTEXT_RAM_INIT_STALL_TIME 200 -/** - * smu_dcc_get_max_ports() - - * - * This macro returns the maximum number of logical ports supported by the - * hardware. The caller passes in the value read from the device context - * capacity register and this macro will mash and shift the value appropriately. - */ -#define smu_dcc_get_max_ports(dcc_value) \ +#define smu_max_ports(dcc_value) \ (\ (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \ ) -/** - * smu_dcc_get_max_task_context() - - * - * This macro returns the maximum number of task contexts supported by the - * hardware. The caller passes in the value read from the device context - * capacity register and this macro will mash and shift the value appropriately. - */ -#define smu_dcc_get_max_task_context(dcc_value) \ +#define smu_max_task_contexts(dcc_value) \ (\ (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \ ) -/** - * smu_dcc_get_max_remote_node_context() - - * - * This macro returns the maximum number of remote node contexts supported by - * the hardware. The caller passes in the value read from the device context - * capacity register and this macro will mash and shift the value appropriately. - */ -#define smu_dcc_get_max_remote_node_context(dcc_value) \ +#define smu_max_rncs(dcc_value) \ (\ (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \ ) - #define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100 /** @@ -153,9 +131,8 @@ INCREMENT_QUEUE_GET(\ (index), \ (cycle), \ - (controller)->completion_queue_entries, \ - SMU_CQGR_CYCLE_BIT \ - ) + SCU_MAX_COMPLETION_QUEUE_ENTRIES, \ + SMU_CQGR_CYCLE_BIT) /** * INCREMENT_EVENT_QUEUE_GET() - @@ -167,7 +144,7 @@ INCREMENT_QUEUE_GET(\ (index), \ (cycle), \ - (controller)->completion_event_entries, \ + SCU_MAX_EVENTS, \ SMU_CQGR_EVENT_CYCLE_BIT \ ) @@ -843,10 +820,9 @@ static void scic_sds_controller_initialize_completion_queue(struct scic_sds_cont scic->completion_queue_get = 0; - completion_queue_control_value = ( - SMU_CQC_QUEUE_LIMIT_SET(scic->completion_queue_entries - 1) - | SMU_CQC_EVENT_LIMIT_SET(scic->completion_event_entries - 1) - ); + completion_queue_control_value = + (SMU_CQC_QUEUE_LIMIT_SET(SCU_MAX_COMPLETION_QUEUE_ENTRIES - 1) | + SMU_CQC_EVENT_LIMIT_SET(SCU_MAX_EVENTS - 1)); writel(completion_queue_control_value, &scic->smu_registers->completion_queue_control); @@ -873,7 +849,7 @@ static void scic_sds_controller_initialize_completion_queue(struct scic_sds_cont &scic->smu_registers->completion_queue_put); /* Initialize the cycle bit of the completion queue entries */ - for (index = 0; index < scic->completion_queue_entries; index++) { + for (index = 0; index < SCU_MAX_COMPLETION_QUEUE_ENTRIES; index++) { /* * If get.cycle_bit != completion_queue.cycle_bit * its not a valid completion queue entry @@ -890,8 +866,7 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue(struct scic_s /* Write the queue size */ frame_queue_control_value = - SCU_UFQC_GEN_VAL(QUEUE_SIZE, - scic->uf_control.address_table.count); + SCU_UFQC_GEN_VAL(QUEUE_SIZE, SCU_MAX_UNSOLICITED_FRAMES); writel(frame_queue_control_value, &scic->scu_registers->sdma.unsolicited_frame_queue_control); @@ -1863,15 +1838,6 @@ static enum sci_status scic_controller_construct(struct scic_sds_controller *sci sci_init_timer(&scic->timer, controller_timeout); - /* Set the default maximum values */ - scic->completion_event_entries = SCU_EVENT_COUNT; - scic->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; - scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; - scic->logical_port_entries = SCI_MAX_PORTS; - scic->task_context_entries = SCU_IO_REQUEST_COUNT; - scic->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT; - scic->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT; - /* Initialize the User and OEM parameters to default values. */ scic_sds_controller_set_default_config_parameters(scic); @@ -2207,44 +2173,6 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s udelay(AFE_REGISTER_WRITE_DELAY); } -static enum sci_status scic_controller_set_mode(struct scic_sds_controller *scic, - enum sci_controller_mode operating_mode) -{ - enum sci_status status = SCI_SUCCESS; - - if ((scic->sm.current_state_id == SCIC_INITIALIZING) || - (scic->sm.current_state_id == SCIC_INITIALIZED)) { - switch (operating_mode) { - case SCI_MODE_SPEED: - scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; - scic->task_context_entries = SCU_IO_REQUEST_COUNT; - scic->uf_control.buffers.count = - SCU_UNSOLICITED_FRAME_COUNT; - scic->completion_event_entries = SCU_EVENT_COUNT; - scic->completion_queue_entries = - SCU_COMPLETION_QUEUE_COUNT; - break; - - case SCI_MODE_SIZE: - scic->remote_node_entries = SCI_MIN_REMOTE_DEVICES; - scic->task_context_entries = SCI_MIN_IO_REQUESTS; - scic->uf_control.buffers.count = - SCU_MIN_UNSOLICITED_FRAMES; - scic->completion_event_entries = SCU_MIN_EVENTS; - scic->completion_queue_entries = - SCU_MIN_COMPLETION_QUEUE_ENTRIES; - break; - - default: - status = SCI_FAILURE_INVALID_PARAMETER_VALUE; - break; - } - } else - status = SCI_FAILURE_INVALID_STATE; - - return status; -} - static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) { sci_init_timer(&scic->power_control.timer, power_control_timeout); @@ -2259,9 +2187,9 @@ static void scic_sds_controller_initialize_power_control(struct scic_sds_control static enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) { struct sci_base_state_machine *sm = &scic->sm; - enum sci_status result = SCI_SUCCESS; struct isci_host *ihost = scic_to_ihost(scic); - u32 index, state; + enum sci_status result = SCI_FAILURE; + unsigned long i, state, val; if (scic->sm.current_state_id != SCIC_RESET) { dev_warn(scic_to_dev(scic), @@ -2286,133 +2214,81 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc * / presently they seem to be wrong. */ scic_sds_controller_afe_initialization(scic); - if (result == SCI_SUCCESS) { - u32 status; - u32 terminate_loop; - - /* Take the hardware out of reset */ - writel(0, &scic->smu_registers->soft_reset_control); - /* - * / @todo Provide meaningfull error code for hardware failure - * result = SCI_FAILURE_CONTROLLER_HARDWARE; */ - result = SCI_FAILURE; - terminate_loop = 100; - - while (terminate_loop-- && (result != SCI_SUCCESS)) { - /* Loop until the hardware reports success */ - udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME); - status = readl(&scic->smu_registers->control_status); - - if ((status & SCU_RAM_INIT_COMPLETED) == - SCU_RAM_INIT_COMPLETED) - result = SCI_SUCCESS; - } - } - - if (result == SCI_SUCCESS) { - u32 max_supported_ports; - u32 max_supported_devices; - u32 max_supported_io_requests; - u32 device_context_capacity; + /* Take the hardware out of reset */ + writel(0, &scic->smu_registers->soft_reset_control); - /* - * Determine what are the actaul device capacities that the - * hardware will support */ - device_context_capacity = - readl(&scic->smu_registers->device_context_capacity); - - - max_supported_ports = smu_dcc_get_max_ports(device_context_capacity); - max_supported_devices = smu_dcc_get_max_remote_node_context(device_context_capacity); - max_supported_io_requests = smu_dcc_get_max_task_context(device_context_capacity); + /* + * / @todo Provide meaningfull error code for hardware failure + * result = SCI_FAILURE_CONTROLLER_HARDWARE; */ + for (i = 100; i >= 1; i--) { + u32 status; - /* - * Make all PEs that are unassigned match up with the - * logical ports - */ - for (index = 0; index < max_supported_ports; index++) { - struct scu_port_task_scheduler_group_registers __iomem - *ptsg = &scic->scu_registers->peg0.ptsg; + /* Loop until the hardware reports success */ + udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME); + status = readl(&scic->smu_registers->control_status); - writel(index, &ptsg->protocol_engine[index]); - } + if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) + break; + } + if (i == 0) + goto out; - /* Record the smaller of the two capacity values */ - scic->logical_port_entries = - min(max_supported_ports, scic->logical_port_entries); + /* + * Determine what are the actaul device capacities that the + * hardware will support */ + val = readl(&scic->smu_registers->device_context_capacity); - scic->task_context_entries = - min(max_supported_io_requests, - scic->task_context_entries); + /* Record the smaller of the two capacity values */ + scic->logical_port_entries = min(smu_max_ports(val), SCI_MAX_PORTS); + scic->task_context_entries = min(smu_max_task_contexts(val), SCI_MAX_IO_REQUESTS); + scic->remote_node_entries = min(smu_max_rncs(val), SCI_MAX_REMOTE_DEVICES); - scic->remote_node_entries = - min(max_supported_devices, scic->remote_node_entries); + /* + * Make all PEs that are unassigned match up with the + * logical ports + */ + for (i = 0; i < scic->logical_port_entries; i++) { + struct scu_port_task_scheduler_group_registers __iomem + *ptsg = &scic->scu_registers->peg0.ptsg; - /* - * Now that we have the correct hardware reported minimum values - * build the MDL for the controller. Default to a performance - * configuration. - */ - scic_controller_set_mode(scic, SCI_MODE_SPEED); + writel(i, &ptsg->protocol_engine[i]); } /* Initialize hardware PCI Relaxed ordering in DMA engines */ - if (result == SCI_SUCCESS) { - u32 dma_configuration; - - /* Configure the payload DMA */ - dma_configuration = - readl(&scic->scu_registers->sdma.pdma_configuration); - dma_configuration |= - SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - writel(dma_configuration, - &scic->scu_registers->sdma.pdma_configuration); - - /* Configure the control DMA */ - dma_configuration = - readl(&scic->scu_registers->sdma.cdma_configuration); - dma_configuration |= - SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - writel(dma_configuration, - &scic->scu_registers->sdma.cdma_configuration); - } + val = readl(&scic->scu_registers->sdma.pdma_configuration); + val |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); + writel(val, &scic->scu_registers->sdma.pdma_configuration); + + val = readl(&scic->scu_registers->sdma.cdma_configuration); + val |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); + writel(val, &scic->scu_registers->sdma.cdma_configuration); /* * Initialize the PHYs before the PORTs because the PHY registers * are accessed during the port initialization. */ - if (result == SCI_SUCCESS) { - /* Initialize the phys */ - for (index = 0; - (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS); - index++) { - result = scic_sds_phy_initialize( - &ihost->phys[index].sci, - &scic->scu_registers->peg0.pe[index].tl, - &scic->scu_registers->peg0.pe[index].ll); - } + for (i = 0; i < SCI_MAX_PHYS; i++) { + result = scic_sds_phy_initialize(&ihost->phys[i].sci, + &scic->scu_registers->peg0.pe[i].tl, + &scic->scu_registers->peg0.pe[i].ll); + if (result != SCI_SUCCESS) + goto out; } - if (result == SCI_SUCCESS) { - /* Initialize the logical ports */ - for (index = 0; - (index < scic->logical_port_entries) && - (result == SCI_SUCCESS); - index++) { - result = scic_sds_port_initialize( - &ihost->ports[index].sci, - &scic->scu_registers->peg0.ptsg.port[index], - &scic->scu_registers->peg0.ptsg.protocol_engine, - &scic->scu_registers->peg0.viit[index]); - } + for (i = 0; i < scic->logical_port_entries; i++) { + result = scic_sds_port_initialize(&ihost->ports[i].sci, + &scic->scu_registers->peg0.ptsg.port[i], + &scic->scu_registers->peg0.ptsg.protocol_engine, + &scic->scu_registers->peg0.viit[i]); + + if (result != SCI_SUCCESS) + goto out; } - if (result == SCI_SUCCESS) - result = scic_sds_port_configuration_agent_initialize( - scic, - &scic->port_agent); + result = scic_sds_port_configuration_agent_initialize(scic, &scic->port_agent); + out: /* Advance the controller state machine */ if (result == SCI_SUCCESS) state = SCIC_INITIALIZED; @@ -2480,47 +2356,38 @@ static enum sci_status scic_user_parameters_set( static int scic_controller_mem_init(struct scic_sds_controller *scic) { struct device *dev = scic_to_dev(scic); - dma_addr_t dma_handle; - enum sci_status result; + dma_addr_t dma; + size_t size; + int err; - scic->completion_queue = dmam_alloc_coherent(dev, - scic->completion_queue_entries * sizeof(u32), - &dma_handle, GFP_KERNEL); + size = SCU_MAX_COMPLETION_QUEUE_ENTRIES * sizeof(u32); + scic->completion_queue = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); if (!scic->completion_queue) return -ENOMEM; - writel(lower_32_bits(dma_handle), - &scic->smu_registers->completion_queue_lower); - writel(upper_32_bits(dma_handle), - &scic->smu_registers->completion_queue_upper); + writel(lower_32_bits(dma), &scic->smu_registers->completion_queue_lower); + writel(upper_32_bits(dma), &scic->smu_registers->completion_queue_upper); - scic->remote_node_context_table = dmam_alloc_coherent(dev, - scic->remote_node_entries * - sizeof(union scu_remote_node_context), - &dma_handle, GFP_KERNEL); + size = scic->remote_node_entries * sizeof(union scu_remote_node_context); + scic->remote_node_context_table = dmam_alloc_coherent(dev, size, &dma, + GFP_KERNEL); if (!scic->remote_node_context_table) return -ENOMEM; - writel(lower_32_bits(dma_handle), - &scic->smu_registers->remote_node_context_lower); - writel(upper_32_bits(dma_handle), - &scic->smu_registers->remote_node_context_upper); + writel(lower_32_bits(dma), &scic->smu_registers->remote_node_context_lower); + writel(upper_32_bits(dma), &scic->smu_registers->remote_node_context_upper); - scic->task_context_table = dmam_alloc_coherent(dev, - scic->task_context_entries * - sizeof(struct scu_task_context), - &dma_handle, GFP_KERNEL); + size = scic->task_context_entries * sizeof(struct scu_task_context), + scic->task_context_table = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); if (!scic->task_context_table) return -ENOMEM; - writel(lower_32_bits(dma_handle), - &scic->smu_registers->host_task_table_lower); - writel(upper_32_bits(dma_handle), - &scic->smu_registers->host_task_table_upper); + writel(lower_32_bits(dma), &scic->smu_registers->host_task_table_lower); + writel(upper_32_bits(dma), &scic->smu_registers->host_task_table_upper); - result = scic_sds_unsolicited_frame_control_construct(scic); - if (result) - return result; + err = scic_sds_unsolicited_frame_control_construct(scic); + if (err) + return err; /* * Inform the silicon as to the location of the UF headers and diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 04698dd75ad6..740350043d89 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -239,18 +239,6 @@ struct scic_sds_controller { */ u32 logical_port_entries; - /** - * This field is the minimum number of hardware supported completion queue - * entries and the software requested completion queue entries. - */ - u32 completion_queue_entries; - - /** - * This field is the minimum number of hardware supported event entries and - * the software requested event entries. - */ - u32 completion_event_entries; - /** * This field is the minimum number of devices supported by the hardware and * the number of devices requested by the software. @@ -325,7 +313,6 @@ struct isci_host { union scic_oem_parameters oem_parameters; int id; /* unique within a given pci device */ - void *core_ctrl_memory; struct dma_pool *dma_pool; struct isci_phy phys[SCI_MAX_PHYS]; struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 80cfb45f8da1..714ed926171b 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -78,39 +78,16 @@ enum sci_controller_mode { SCI_MODE_SIZE /* deprecated */ }; -#define SCI_MAX_PHYS (4) +#define SCI_MAX_PHYS (4UL) #define SCI_MAX_PORTS SCI_MAX_PHYS -#define SCI_MIN_SMP_PHYS (38) #define SCI_MAX_SMP_PHYS (384) /* not silicon constrained */ -#define SCI_MAX_REMOTE_DEVICES (256) -#define SCI_MIN_REMOTE_DEVICES (16) -#define SCI_MAX_IO_REQUESTS (256) -#define SCI_MIN_IO_REQUESTS (1) +#define SCI_MAX_REMOTE_DEVICES (256UL) +#define SCI_MAX_IO_REQUESTS (256UL) #define SCI_MAX_MSIX_MESSAGES (2) #define SCI_MAX_SCATTER_GATHER_ELEMENTS 130 /* not silicon constrained */ -#define SCI_MIN_SCATTER_GATHER_ELEMENTS 1 #define SCI_MAX_CONTROLLERS 2 #define SCI_MAX_DOMAINS SCI_MAX_PORTS -/* 2 indicates the maximum number of UFs that can occur for a given IO request. - * The hardware handles reception of additional unsolicited frames while all - * UFs are in use, by holding off the transmitting device. This number could - * be theoretically reduced to 1, but 2 provides for more reliable operation. - * During SATA PIO operation, it is possible under some conditions for there to - * be 3 separate FISes received, back to back to back (PIO Setup, Data, D2H - * Register). It is unlikely to have all 3 pending all at once without some of - * them already being processed. - */ -#define SCU_MIN_UNSOLICITED_FRAMES (1) -#define SCU_MIN_CRITICAL_NOTIFICATIONS (24) -#define SCU_MIN_EVENTS (4) -#define SCU_MIN_COMPLETION_QUEUE_SCRATCH (2) -#define SCU_MIN_COMPLETION_QUEUE_ENTRIES (SCU_MIN_CRITICAL_NOTIFICATIONS \ - + SCU_MIN_EVENTS \ - + SCU_MIN_UNSOLICITED_FRAMES \ - + SCI_MIN_IO_REQUESTS \ - + SCU_MIN_COMPLETION_QUEUE_SCRATCH) - #define SCU_MAX_CRITICAL_NOTIFICATIONS (384) #define SCU_MAX_EVENTS (128) #define SCU_MAX_UNSOLICITED_FRAMES (128) @@ -121,51 +98,6 @@ enum sci_controller_mode { + SCI_MAX_IO_REQUESTS \ + SCU_MAX_COMPLETION_QUEUE_SCRATCH) -#if !defined(ENABLE_MINIMUM_MEMORY_MODE) -#define SCU_UNSOLICITED_FRAME_COUNT SCU_MAX_UNSOLICITED_FRAMES -#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MAX_CRITICAL_NOTIFICATIONS -#define SCU_EVENT_COUNT SCU_MAX_EVENTS -#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MAX_COMPLETION_QUEUE_SCRATCH -#define SCU_IO_REQUEST_COUNT SCI_MAX_IO_REQUESTS -#define SCU_IO_REQUEST_SGE_COUNT SCI_MAX_SCATTER_GATHER_ELEMENTS -#define SCU_COMPLETION_QUEUE_COUNT SCU_MAX_COMPLETION_QUEUE_ENTRIES -#else -#define SCU_UNSOLICITED_FRAME_COUNT SCU_MIN_UNSOLICITED_FRAMES -#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MIN_CRITICAL_NOTIFICATIONS -#define SCU_EVENT_COUNT SCU_MIN_EVENTS -#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MIN_COMPLETION_QUEUE_SCRATCH -#define SCU_IO_REQUEST_COUNT SCI_MIN_IO_REQUESTS -#define SCU_IO_REQUEST_SGE_COUNT SCI_MIN_SCATTER_GATHER_ELEMENTS -#define SCU_COMPLETION_QUEUE_COUNT SCU_MIN_COMPLETION_QUEUE_ENTRIES -#endif /* !defined(ENABLE_MINIMUM_MEMORY_OPERATION) */ - -/** - * - * - * The SCU_COMPLETION_QUEUE_COUNT constant indicates the size of the completion - * queue into which the hardware DMAs 32-bit quantas (completion entries). - */ - -/** - * - * - * This queue must be programmed to a power of 2 size (e.g. 32, 64, 1024, etc.). - */ -#if (SCU_COMPLETION_QUEUE_COUNT != 16) && \ - (SCU_COMPLETION_QUEUE_COUNT != 32) && \ - (SCU_COMPLETION_QUEUE_COUNT != 64) && \ - (SCU_COMPLETION_QUEUE_COUNT != 128) && \ - (SCU_COMPLETION_QUEUE_COUNT != 256) && \ - (SCU_COMPLETION_QUEUE_COUNT != 512) && \ - (SCU_COMPLETION_QUEUE_COUNT != 1024) -#error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2." -#endif - -#if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES -#error "Invalid configuration of unsolicited frame constants" -#endif /* SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES */ - -#define SCU_MIN_UF_TABLE_ENTRIES (8) #define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096) #define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024) #define SCU_INVALID_FRAME_INDEX (0xFFFF) @@ -173,14 +105,14 @@ enum sci_controller_mode { #define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF) #define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH (0x00FFFFFF) -/* - * Determine the size of the unsolicited frame array including - * unused buffers. */ -#if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES -#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES -#else -#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES -#endif /* SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES */ +static inline void check_sizes(void) +{ + BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_EVENTS); + BUILD_BUG_ON(SCU_MAX_UNSOLICITED_FRAMES <= 8); + BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_UNSOLICITED_FRAMES); + BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_COMPLETION_QUEUE_ENTRIES); + BUILD_BUG_ON(SCU_MAX_UNSOLICITED_FRAMES > SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES); +} /** * enum sci_status - This is the general return status enumeration for non-IO, diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 757cd99ae2ed..547c35cbe459 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -213,7 +213,7 @@ struct scic_sds_request { struct scu_task_context tc ____cacheline_aligned; /* could be larger with sg chaining */ - #define SCU_SGL_SIZE ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) + #define SCU_SGL_SIZE ((SCI_MAX_SCATTER_GATHER_ELEMENTS + 1) / 2) struct scu_sgl_element_pair sg_table[SCU_SGL_SIZE] __attribute__ ((aligned(32))); /* diff --git a/drivers/scsi/isci/unsolicited_frame_control.c b/drivers/scsi/isci/unsolicited_frame_control.c index 12e676346386..d89570700ffd 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.c +++ b/drivers/scsi/isci/unsolicited_frame_control.c @@ -57,120 +57,30 @@ #include "unsolicited_frame_control.h" #include "registers.h" -/** - * This method will program the unsolicited frames (UFs) into the UF address - * table and construct the UF frame structure being modeled in the core. It - * will handle the case where some of the UFs are not being used and thus - * should have entries programmed to zero in the address table. - * @uf_control: This parameter specifies the unsolicted frame control object - * for which to construct the unsolicited frames objects. - * @uf_buffer_phys_address: This parameter specifies the physical address for - * the first unsolicited frame buffer. - * @uf_buffer_virt_address: This parameter specifies the virtual address for - * the first unsolicited frame buffer. - * @unused_uf_header_entries: This parameter specifies the number of unused UF - * headers. This value can be non-zero when there are a non-power of 2 - * number of unsolicited frames being supported. - * @used_uf_header_entries: This parameter specifies the number of actually - * utilized UF headers. - * - */ -static void scic_sds_unsolicited_frame_control_construct_frames( - struct scic_sds_unsolicited_frame_control *uf_control, - dma_addr_t uf_buffer_phys_address, - void *uf_buffer_virt_address, - u32 unused_uf_header_entries, - u32 used_uf_header_entries) -{ - u32 index; - struct scic_sds_unsolicited_frame *uf; - - /* - * Program the unused buffers into the UF address table and the - * controller's array of UFs. - */ - for (index = 0; index < unused_uf_header_entries; index++) { - uf = &uf_control->buffers.array[index]; - - uf->buffer = NULL; - uf_control->address_table.array[index] = 0; - uf->header = &uf_control->headers.array[index]; - uf->state = UNSOLICITED_FRAME_EMPTY; - } - - /* - * Program the actual used UF buffers into the UF address table and - * the controller's array of UFs. - */ - for (index = unused_uf_header_entries; - index < unused_uf_header_entries + used_uf_header_entries; - index++) { - uf = &uf_control->buffers.array[index]; - - uf_control->address_table.array[index] = uf_buffer_phys_address; - - uf->buffer = uf_buffer_virt_address; - uf->header = &uf_control->headers.array[index]; - uf->state = UNSOLICITED_FRAME_EMPTY; - - /* - * Increment the address of the physical and virtual memory - * pointers. Everything is aligned on 1k boundary with an - * increment of 1k. - */ - uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; - uf_buffer_phys_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; - } -} - int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic) { struct scic_sds_unsolicited_frame_control *uf_control = &scic->uf_control; - u32 unused_uf_header_entries; - u32 used_uf_header_entries; - u32 used_uf_buffer_bytes; - u32 unused_uf_header_bytes; - u32 used_uf_header_bytes; - dma_addr_t uf_buffer_phys_address; - void *uf_buffer_virt_address; + struct scic_sds_unsolicited_frame *uf; + u32 buf_len, header_len, i; + dma_addr_t dma; size_t size; - - /* - * The UF buffer address table size must be programmed to a power - * of 2. Find the first power of 2 that is equal to or greater then - * the number of unsolicited frame buffers to be utilized. - */ - uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES; - while (uf_control->address_table.count < uf_control->buffers.count && - uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES) - uf_control->address_table.count <<= 1; + void *virt; /* * Prepare all of the memory sizes for the UF headers, UF address * table, and UF buffers themselves. */ - used_uf_buffer_bytes = uf_control->buffers.count - * SCU_UNSOLICITED_FRAME_BUFFER_SIZE; - unused_uf_header_entries = uf_control->address_table.count - - uf_control->buffers.count; - used_uf_header_entries = uf_control->buffers.count; - unused_uf_header_bytes = unused_uf_header_entries - * sizeof(struct scu_unsolicited_frame_header); - used_uf_header_bytes = used_uf_header_entries - * sizeof(struct scu_unsolicited_frame_header); - - size = used_uf_buffer_bytes + used_uf_header_bytes + - uf_control->address_table.count * sizeof(dma_addr_t); - + buf_len = SCU_MAX_UNSOLICITED_FRAMES * SCU_UNSOLICITED_FRAME_BUFFER_SIZE; + header_len = SCU_MAX_UNSOLICITED_FRAMES * sizeof(struct scu_unsolicited_frame_header); + size = buf_len + header_len + SCU_MAX_UNSOLICITED_FRAMES * sizeof(dma_addr_t); /* * The Unsolicited Frame buffers are set at the start of the UF * memory descriptor entry. The headers and address table will be * placed after the buffers. */ - uf_buffer_virt_address = dmam_alloc_coherent(scic_to_dev(scic), size, - &uf_buffer_phys_address, GFP_KERNEL); - if (!uf_buffer_virt_address) + virt = dmam_alloc_coherent(scic_to_dev(scic), size, &dma, GFP_KERNEL); + if (!virt) return -ENOMEM; /* @@ -183,15 +93,8 @@ int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *sci * headers, since we program the UF address table pointers to * NULL. */ - uf_control->headers.physical_address = - uf_buffer_phys_address + - used_uf_buffer_bytes - - unused_uf_header_bytes; - - uf_control->headers.array = - uf_buffer_virt_address + - used_uf_buffer_bytes - - unused_uf_header_bytes; + uf_control->headers.physical_address = dma + buf_len; + uf_control->headers.array = virt + buf_len; /* * Program the location of the UF address table into the SCU. @@ -200,16 +103,8 @@ int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *sci * byte boundary already due to above programming headers being on a * 64-bit boundary and headers are on a 64-bytes in size. */ - uf_control->address_table.physical_address = - uf_buffer_phys_address + - used_uf_buffer_bytes + - used_uf_header_bytes; - - uf_control->address_table.array = - uf_buffer_virt_address + - used_uf_buffer_bytes + - used_uf_header_bytes; - + uf_control->address_table.physical_address = dma + buf_len + header_len; + uf_control->address_table.array = virt + buf_len + header_len; uf_control->get = 0; /* @@ -220,16 +115,26 @@ int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *sci * - Aligned on a 1KB boundary. */ /* - * If the user provided less then the maximum amount of memory, - * then be sure that we programm the first entries in the UF - * address table to NULL. */ - scic_sds_unsolicited_frame_control_construct_frames( - uf_control, - uf_buffer_phys_address, - uf_buffer_virt_address, - unused_uf_header_entries, - used_uf_header_entries - ); + * Program the actual used UF buffers into the UF address table and + * the controller's array of UFs. + */ + for (i = 0; i < SCU_MAX_UNSOLICITED_FRAMES; i++) { + uf = &uf_control->buffers.array[i]; + + uf_control->address_table.array[i] = dma; + + uf->buffer = virt; + uf->header = &uf_control->headers.array[i]; + uf->state = UNSOLICITED_FRAME_EMPTY; + + /* + * Increment the address of the physical and virtual memory + * pointers. Everything is aligned on 1k boundary with an + * increment of 1k. + */ + virt += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; + dma += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; + } return 0; } @@ -247,7 +152,7 @@ enum sci_status scic_sds_unsolicited_frame_control_get_header( u32 frame_index, void **frame_header) { - if (frame_index < uf_control->address_table.count) { + if (frame_index < SCU_MAX_UNSOLICITED_FRAMES) { /* * Skip the first word in the frame since this is a controll word used * by the hardware. */ @@ -272,7 +177,7 @@ enum sci_status scic_sds_unsolicited_frame_control_get_buffer( u32 frame_index, void **frame_buffer) { - if (frame_index < uf_control->address_table.count) { + if (frame_index < SCU_MAX_UNSOLICITED_FRAMES) { *frame_buffer = uf_control->buffers.array[frame_index].buffer; return SCI_SUCCESS; @@ -298,26 +203,24 @@ bool scic_sds_unsolicited_frame_control_release_frame( u32 frame_get; u32 frame_cycle; - frame_get = uf_control->get & (uf_control->address_table.count - 1); - frame_cycle = uf_control->get & uf_control->address_table.count; + frame_get = uf_control->get & (SCU_MAX_UNSOLICITED_FRAMES - 1); + frame_cycle = uf_control->get & SCU_MAX_UNSOLICITED_FRAMES; /* * In the event there are NULL entries in the UF table, we need to * advance the get pointer in order to find out if this frame should * be released (i.e. update the get pointer). */ - while (((lower_32_bits(uf_control->address_table.array[frame_get]) - == 0) && - (upper_32_bits(uf_control->address_table.array[frame_get]) - == 0)) && - (frame_get < uf_control->address_table.count)) + while (lower_32_bits(uf_control->address_table.array[frame_get]) == 0 && + upper_32_bits(uf_control->address_table.array[frame_get]) == 0 && + frame_get < SCU_MAX_UNSOLICITED_FRAMES) frame_get++; /* * The table has a NULL entry as it's last element. This is * illegal. */ - BUG_ON(frame_get >= uf_control->address_table.count); + BUG_ON(frame_get >= SCU_MAX_UNSOLICITED_FRAMES); - if (frame_index < uf_control->address_table.count) { + if (frame_index < SCU_MAX_UNSOLICITED_FRAMES) { uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED; /* @@ -333,9 +236,8 @@ bool scic_sds_unsolicited_frame_control_release_frame( INCREMENT_QUEUE_GET( frame_get, frame_cycle, - uf_control->address_table.count - 1, - uf_control->address_table.count - ); + SCU_MAX_UNSOLICITED_FRAMES - 1, + SCU_MAX_UNSOLICITED_FRAMES); } uf_control->get = diff --git a/drivers/scsi/isci/unsolicited_frame_control.h b/drivers/scsi/isci/unsolicited_frame_control.h index 0d8ca8c4770f..2954904f025a 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.h +++ b/drivers/scsi/isci/unsolicited_frame_control.h @@ -144,25 +144,18 @@ struct scic_sds_uf_header_array { */ struct scic_sds_uf_buffer_array { /** - * This field is the minimum number of unsolicited frames supported by the - * hardware and the number of unsolicited frames requested by the software. - */ - u32 count; - - /** - * This field is the SCIC_UNSOLICITED_FRAME data its used to manage + * This field is the unsolicited frame data its used to manage * the data for the unsolicited frame requests. It also represents * the virtual address location that corresponds to the * physical_address field. */ - struct scic_sds_unsolicited_frame array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE]; + struct scic_sds_unsolicited_frame array[SCU_MAX_UNSOLICITED_FRAMES]; /** * This field specifies the physical address location for the UF * buffer array. */ dma_addr_t physical_address; - }; /** @@ -173,15 +166,6 @@ struct scic_sds_uf_buffer_array { * 1KB buffers into which the silicon will DMA unsolicited frames. */ struct scic_sds_uf_address_table_array { - /** - * This field specifies the actual programmed size of the - * unsolicited frame buffer address table. The size of the table - * can be larger than the actual number of UF buffers, but it must - * be a power of 2 and the last entry in the table is not allowed - * to be NULL. - */ - u32 count; - /** * This field represents a virtual pointer that refers to the * starting address of the UF address table. -- cgit v1.2.3 From ff717ab05f0c33f93514eccea6dfe1a15983e1d1 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Mon, 20 Jun 2011 14:08:51 -0700 Subject: isci: Move the reset delay after the remote node resumption. Delay after bringing up the RNC to allow for resumption latency. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index b54ef2b0fca1..69f17b98e4fa 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1433,15 +1433,17 @@ static int isci_reset_device(struct domain_device *dev, int hard_reset) isci_device_clear_reset_pending(ihost, idev); rc = sas_phy_reset(phy, hard_reset); - msleep(2000); /* just like mvsas */ /* Terminate in-progress I/O now. */ isci_remote_device_nuke_requests(ihost, idev); + /* Since all pending TCs have been cleaned, resume the RNC. */ spin_lock_irqsave(&ihost->scic_lock, flags); status = scic_remote_device_reset_complete(&idev->sci); spin_unlock_irqrestore(&ihost->scic_lock, flags); + msleep(2000); /* just like mvsas */ + if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, "%s: scic_remote_device_reset_complete(%p) " -- cgit v1.2.3 From 61aaff49e20fdb700f1300a49962bc76effc77fc Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Tue, 21 Jun 2011 12:16:33 -0700 Subject: isci: filter broadcast change notifications during SMP phy resets When resetting a sata device in the domain we have seen occasions where libsas prematurely marks a device gone in the time it takes for the device to re-establish the link. This plays badly with software raid arrays. Other libsas drivers have non-uniform delays in their reset handlers to try to cover this condition, but not sufficient to close the hole. Given that a sata device can take many seconds to recover we filter bcns and poll for the device reattach state before notifying libsas that the port needs the domain to be rediscovered. Once this has been proven out at the lldd level we can think about uplevelling this feature to a common implementation in libsas. Signed-off-by: Jeff Skirvin [ use kzalloc instead of kmem_cache ] Signed-off-by: Dave Jiang [ use eventq and time macros ] Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 115 +++++++++++++-------- drivers/scsi/isci/port.h | 5 + drivers/scsi/isci/task.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 338 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 74f06f3c0735..2946eee8e702 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -152,6 +152,71 @@ static enum sci_status scic_port_get_properties(struct scic_sds_port *port, return SCI_SUCCESS; } +static void scic_port_bcn_enable(struct scic_sds_port *sci_port) +{ + struct scic_sds_phy *sci_phy; + u32 val; + int i; + + for (i = 0; i < ARRAY_SIZE(sci_port->phy_table); i++) { + sci_phy = sci_port->phy_table[i]; + if (!sci_phy) + continue; + val = readl(&sci_phy->link_layer_registers->link_layer_control); + /* clear the bit by writing 1. */ + writel(val, &sci_phy->link_layer_registers->link_layer_control); + } +} + +/* called under scic_lock to stabilize phy:port associations */ +void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport) +{ + int i; + + clear_bit(IPORT_BCN_BLOCKED, &iport->flags); + wake_up(&ihost->eventq); + + if (!test_and_clear_bit(IPORT_BCN_PENDING, &iport->flags)) + return; + + for (i = 0; i < ARRAY_SIZE(iport->sci.phy_table); i++) { + struct scic_sds_phy *sci_phy = iport->sci.phy_table[i]; + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + + if (!sci_phy) + continue; + + ihost->sas_ha.notify_port_event(&iphy->sas_phy, + PORTE_BROADCAST_RCVD); + break; + } +} + +void isci_port_bc_change_received(struct isci_host *ihost, + struct scic_sds_port *sci_port, + struct scic_sds_phy *sci_phy) +{ + struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + struct isci_port *iport = iphy->isci_port; + + if (iport && test_bit(IPORT_BCN_BLOCKED, &iport->flags)) { + dev_dbg(&ihost->pdev->dev, + "%s: disabled BCN; isci_phy = %p, sas_phy = %p\n", + __func__, iphy, &iphy->sas_phy); + set_bit(IPORT_BCN_PENDING, &iport->flags); + atomic_inc(&iport->event); + wake_up(&ihost->eventq); + } else { + dev_dbg(&ihost->pdev->dev, + "%s: isci_phy = %p, sas_phy = %p\n", + __func__, iphy, &iphy->sas_phy); + + ihost->sas_ha.notify_port_event(&iphy->sas_phy, + PORTE_BROADCAST_RCVD); + } + scic_port_bcn_enable(sci_port); +} + static void isci_port_link_up(struct isci_host *isci_host, struct scic_sds_port *port, struct scic_sds_phy *phy) @@ -240,13 +305,15 @@ static void isci_port_link_down(struct isci_host *isci_host, if (isci_port) { /* check to see if this is the last phy on this port. */ - if (isci_phy->sas_phy.port - && isci_phy->sas_phy.port->num_phys == 1) { - - /* change the state for all devices on this port. - * The next task sent to this device will be returned - * as SAS_TASK_UNDELIVERED, and the scsi mid layer - * will remove the target + if (isci_phy->sas_phy.port && + isci_phy->sas_phy.port->num_phys == 1) { + atomic_inc(&isci_port->event); + isci_port_bcn_enable(isci_host, isci_port); + + /* change the state for all devices on this port. The + * next task sent to this device will be returned as + * SAS_TASK_UNDELIVERED, and the scsi mid layer will + * remove the target */ list_for_each_entry(isci_device, &isci_port->remote_dev_list, @@ -1033,26 +1100,6 @@ enum sas_linkrate scic_sds_port_get_max_allowed_speed( return max_allowed_speed; } -static void scic_port_enable_broadcast_change_notification(struct scic_sds_port *port) -{ - struct scic_sds_phy *phy; - u32 register_value; - u8 index; - - /* Loop through all of the phys to enable BCN. */ - for (index = 0; index < SCI_MAX_PHYS; index++) { - phy = port->phy_table[index]; - if (phy != NULL) { - register_value = - readl(&phy->link_layer_registers->link_layer_control); - - /* clear the bit by writing 1. */ - writel(register_value, - &phy->link_layer_registers->link_layer_control); - } - } -} - /** * * @sci_port: This is the struct scic_sds_port object to suspend. @@ -1838,6 +1885,7 @@ void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index) init_completion(&iport->start_complete); iport->isci_host = ihost; isci_port_change_state(iport, isci_freed); + atomic_set(&iport->event, 0); } /** @@ -1852,19 +1900,6 @@ enum isci_status isci_port_get_state( return isci_port->status; } -static void isci_port_bc_change_received(struct isci_host *ihost, - struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) -{ - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - - dev_dbg(&ihost->pdev->dev, "%s: iphy = %p, sas_phy = %p\n", - __func__, iphy, &iphy->sas_phy); - - ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); - scic_port_enable_broadcast_change_notification(sci_port); -} - void scic_sds_port_broadcast_change_received( struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy) diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index fee6d80df769..45c01f80bf83 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -173,6 +173,10 @@ struct scic_sds_port { */ struct isci_port { enum isci_status status; + #define IPORT_BCN_BLOCKED 0 + #define IPORT_BCN_PENDING 1 + unsigned long flags; + atomic_t event; struct isci_host *isci_host; struct asd_sas_port sas_port; struct list_head remote_dev_list; @@ -334,6 +338,7 @@ void scic_sds_port_setup_transports( struct scic_sds_port *sci_port, u32 device_id); +void isci_port_bcn_enable(struct isci_host *, struct isci_port *); void scic_sds_port_deactivate_phy( struct scic_sds_port *sci_port, diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 69f17b98e4fa..709c08171743 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -56,6 +56,7 @@ #include #include #include "sas.h" +#include #include "remote_device.h" #include "remote_node_context.h" #include "isci.h" @@ -1397,11 +1398,250 @@ isci_task_request_complete(struct isci_host *ihost, complete(tmf_complete); } +static void isci_smp_task_timedout(unsigned long _task) +{ + struct sas_task *task = (void *) _task; + unsigned long flags; + + spin_lock_irqsave(&task->task_state_lock, flags); + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) + task->task_state_flags |= SAS_TASK_STATE_ABORTED; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + complete(&task->completion); +} + +static void isci_smp_task_done(struct sas_task *task) +{ + if (!del_timer(&task->timer)) + return; + complete(&task->completion); +} + +static struct sas_task *isci_alloc_task(void) +{ + struct sas_task *task = kzalloc(sizeof(*task), GFP_KERNEL); + + if (task) { + INIT_LIST_HEAD(&task->list); + spin_lock_init(&task->task_state_lock); + task->task_state_flags = SAS_TASK_STATE_PENDING; + init_timer(&task->timer); + init_completion(&task->completion); + } + + return task; +} + +static void isci_free_task(struct isci_host *ihost, struct sas_task *task) +{ + if (task) { + BUG_ON(!list_empty(&task->list)); + kfree(task); + } +} + +static int isci_smp_execute_task(struct isci_host *ihost, + struct domain_device *dev, void *req, + int req_size, void *resp, int resp_size) +{ + int res, retry; + struct sas_task *task = NULL; + + for (retry = 0; retry < 3; retry++) { + task = isci_alloc_task(); + if (!task) + return -ENOMEM; + + task->dev = dev; + task->task_proto = dev->tproto; + sg_init_one(&task->smp_task.smp_req, req, req_size); + sg_init_one(&task->smp_task.smp_resp, resp, resp_size); + + task->task_done = isci_smp_task_done; + + task->timer.data = (unsigned long) task; + task->timer.function = isci_smp_task_timedout; + task->timer.expires = jiffies + 10*HZ; + add_timer(&task->timer); + + res = isci_task_execute_task(task, 1, GFP_KERNEL); + + if (res) { + del_timer(&task->timer); + dev_err(&ihost->pdev->dev, + "%s: executing SMP task failed:%d\n", + __func__, res); + goto ex_err; + } + + wait_for_completion(&task->completion); + res = -ECOMM; + if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { + dev_err(&ihost->pdev->dev, + "%s: smp task timed out or aborted\n", + __func__); + isci_task_abort_task(task); + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { + dev_err(&ihost->pdev->dev, + "%s: SMP task aborted and not done\n", + __func__); + goto ex_err; + } + } + if (task->task_status.resp == SAS_TASK_COMPLETE && + task->task_status.stat == SAM_STAT_GOOD) { + res = 0; + break; + } + if (task->task_status.resp == SAS_TASK_COMPLETE && + task->task_status.stat == SAS_DATA_UNDERRUN) { + /* no error, but return the number of bytes of + * underrun */ + res = task->task_status.residual; + break; + } + if (task->task_status.resp == SAS_TASK_COMPLETE && + task->task_status.stat == SAS_DATA_OVERRUN) { + res = -EMSGSIZE; + break; + } else { + dev_err(&ihost->pdev->dev, + "%s: task to dev %016llx response: 0x%x " + "status 0x%x\n", __func__, + SAS_ADDR(dev->sas_addr), + task->task_status.resp, + task->task_status.stat); + isci_free_task(ihost, task); + task = NULL; + } + } +ex_err: + BUG_ON(retry == 3 && task != NULL); + isci_free_task(ihost, task); + return res; +} + +#define DISCOVER_REQ_SIZE 16 +#define DISCOVER_RESP_SIZE 56 + +int isci_smp_get_phy_attached_dev_type(struct isci_host *ihost, + struct domain_device *dev, + int phy_id, int *adt) +{ + struct smp_resp *disc_resp; + u8 *disc_req; + int res; + + disc_resp = kzalloc(DISCOVER_RESP_SIZE, GFP_KERNEL); + if (!disc_resp) + return -ENOMEM; + + disc_req = kzalloc(DISCOVER_REQ_SIZE, GFP_KERNEL); + if (disc_req) { + disc_req[0] = SMP_REQUEST; + disc_req[1] = SMP_DISCOVER; + disc_req[9] = phy_id; + } else { + kfree(disc_resp); + return -ENOMEM; + } + res = isci_smp_execute_task(ihost, dev, disc_req, DISCOVER_REQ_SIZE, + disc_resp, DISCOVER_RESP_SIZE); + if (!res) { + if (disc_resp->result != SMP_RESP_FUNC_ACC) + res = disc_resp->result; + else + *adt = disc_resp->disc.attached_dev_type; + } + kfree(disc_req); + kfree(disc_resp); + + return res; +} + +static void isci_wait_for_smp_phy_reset(struct isci_remote_device *idev, int phy_num) +{ + struct domain_device *dev = idev->domain_dev; + struct isci_port *iport = idev->isci_port; + struct isci_host *ihost = iport->isci_host; + int res, iteration = 0, attached_device_type; + #define STP_WAIT_MSECS 25000 + unsigned long tmo = msecs_to_jiffies(STP_WAIT_MSECS); + unsigned long deadline = jiffies + tmo; + enum { + SMP_PHYWAIT_PHYDOWN, + SMP_PHYWAIT_PHYUP, + SMP_PHYWAIT_DONE + } phy_state = SMP_PHYWAIT_PHYDOWN; + + /* While there is time, wait for the phy to go away and come back */ + while (time_is_after_jiffies(deadline) && phy_state != SMP_PHYWAIT_DONE) { + int event = atomic_read(&iport->event); + + ++iteration; + + tmo = wait_event_timeout(ihost->eventq, + event != atomic_read(&iport->event) || + !test_bit(IPORT_BCN_BLOCKED, &iport->flags), + tmo); + /* link down, stop polling */ + if (!test_bit(IPORT_BCN_BLOCKED, &iport->flags)) + break; + + dev_dbg(&ihost->pdev->dev, + "%s: iport %p, iteration %d," + " phase %d: time_remaining %lu, bcns = %d\n", + __func__, iport, iteration, phy_state, + tmo, test_bit(IPORT_BCN_PENDING, &iport->flags)); + + res = isci_smp_get_phy_attached_dev_type(ihost, dev, phy_num, + &attached_device_type); + tmo = deadline - jiffies; + + if (res) { + dev_warn(&ihost->pdev->dev, + "%s: iteration %d, phase %d:" + " SMP error=%d, time_remaining=%lu\n", + __func__, iteration, phy_state, res, tmo); + break; + } + dev_dbg(&ihost->pdev->dev, + "%s: iport %p, iteration %d," + " phase %d: time_remaining %lu, bcns = %d, " + "attdevtype = %x\n", + __func__, iport, iteration, phy_state, + tmo, test_bit(IPORT_BCN_PENDING, &iport->flags), + attached_device_type); + + switch (phy_state) { + case SMP_PHYWAIT_PHYDOWN: + /* Has the device gone away? */ + if (!attached_device_type) + phy_state = SMP_PHYWAIT_PHYUP; + + break; + + case SMP_PHYWAIT_PHYUP: + /* Has the device come back? */ + if (attached_device_type) + phy_state = SMP_PHYWAIT_DONE; + break; + + case SMP_PHYWAIT_DONE: + break; + } + + } + dev_dbg(&ihost->pdev->dev, "%s: done\n", __func__); +} + static int isci_reset_device(struct domain_device *dev, int hard_reset) { struct isci_remote_device *idev = dev->lldd_dev; struct sas_phy *phy = sas_find_local_phy(dev); struct isci_host *ihost = dev_to_ihost(dev); + struct isci_port *iport = idev->isci_port; enum sci_status status; unsigned long flags; int rc; @@ -1432,6 +1672,10 @@ static int isci_reset_device(struct domain_device *dev, int hard_reset) /* Make sure all pending requests are able to be fully terminated. */ isci_device_clear_reset_pending(ihost, idev); + /* If this is a device on an expander, disable BCN processing. */ + if (!scsi_is_sas_phy_local(phy)) + set_bit(IPORT_BCN_BLOCKED, &iport->flags); + rc = sas_phy_reset(phy, hard_reset); /* Terminate in-progress I/O now. */ @@ -1442,7 +1686,20 @@ static int isci_reset_device(struct domain_device *dev, int hard_reset) status = scic_remote_device_reset_complete(&idev->sci); spin_unlock_irqrestore(&ihost->scic_lock, flags); - msleep(2000); /* just like mvsas */ + /* If this is a device on an expander, bring the phy back up. */ + if (!scsi_is_sas_phy_local(phy)) { + /* A phy reset will cause the device to go away then reappear. + * Since libsas will take action on incoming BCNs (eg. remove + * a device going through an SMP phy-control driven reset), + * we need to wait until the phy comes back up before letting + * discovery proceed in libsas. + */ + isci_wait_for_smp_phy_reset(idev, phy->number); + + spin_lock_irqsave(&ihost->scic_lock, flags); + isci_port_bcn_enable(ihost, idev->isci_port); + spin_unlock_irqrestore(&ihost->scic_lock, flags); + } if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, -- cgit v1.2.3 From cde76fbf1f27551a08860227765ae8d5026ac0d9 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Mon, 20 Jun 2011 14:09:06 -0700 Subject: isci: Add decode for SMP request retry error condition There are situations with slow expanders in which a first attempt to execute an SMP request will fail with a timeout. Immediate subsequent retries will generally succeed. This change makes sure SMP I/O failures are immediately failed to libsas so that retries happen with no discovery process timeout delay. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 35 +++++++++++++++++++++++++++++++---- drivers/scsi/isci/task.h | 27 +++++++++++++++++++++------ 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 8bd1f7dbad37..3a891d32c331 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2508,9 +2508,16 @@ static void isci_request_handle_controller_specific_errors( /* Task in the target is not done. */ *response_ptr = SAS_TASK_UNDELIVERED; *status_ptr = SAM_STAT_TASK_ABORTED; - request->complete_in_target = false; - *complete_to_host_ptr = isci_perform_error_io_completion; + if (task->task_proto == SAS_PROTOCOL_SMP) { + request->complete_in_target = true; + + *complete_to_host_ptr = isci_perform_normal_io_completion; + } else { + request->complete_in_target = false; + + *complete_to_host_ptr = isci_perform_error_io_completion; + } break; } } @@ -2882,6 +2889,21 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, request->complete_in_target = false; break; + case SCI_FAILURE_RETRY_REQUIRED: + + /* Fail the I/O so it can be retried. */ + response = SAS_TASK_UNDELIVERED; + if ((isci_device->status == isci_stopping) || + (isci_device->status == isci_stopped)) + status = SAS_DEVICE_UNKNOWN; + else + status = SAS_ABORTED_TASK; + + complete_to_host = isci_perform_normal_io_completion; + request->complete_in_target = true; + break; + + default: /* Catch any otherwise unhandled error codes here. */ dev_warn(&isci_host->pdev->dev, @@ -2901,8 +2923,13 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, else status = SAS_ABORTED_TASK; - complete_to_host = isci_perform_error_io_completion; - request->complete_in_target = false; + if (SAS_PROTOCOL_SMP == task->task_proto) { + request->complete_in_target = true; + complete_to_host = isci_perform_normal_io_completion; + } else { + request->complete_in_target = false; + complete_to_host = isci_perform_error_io_completion; + } break; } break; diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index 432b81aecd47..c8dd075d2be2 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -301,6 +301,27 @@ isci_task_set_completion_status( task->task_status.stat = status; switch (task_notification_selection) { + + case isci_perform_error_io_completion: + + if (task->task_proto == SAS_PROTOCOL_SMP) { + /* There is no error escalation in the SMP case. + * Convert to a normal completion to avoid the + * timeout in the discovery path and to let the + * next action take place quickly. + */ + task_notification_selection + = isci_perform_normal_io_completion; + + /* Fall through to the normal case... */ + } else { + /* Use sas_task_abort */ + /* Leave SAS_TASK_STATE_DONE clear + * Leave SAS_TASK_AT_INITIATOR set. + */ + break; + } + case isci_perform_aborted_io_completion: /* This path can occur with task-managed requests as well as * requests terminated because of LUN or device resets. @@ -313,12 +334,6 @@ isci_task_set_completion_status( default: WARN_ONCE(1, "unknown task_notification_selection: %d\n", task_notification_selection); - /* Fall through to the error case... */ - case isci_perform_error_io_completion: - /* Use sas_task_abort */ - /* Leave SAS_TASK_STATE_DONE clear - * Leave SAS_TASK_AT_INITIATOR set. - */ break; } -- cgit v1.2.3 From f53a3a32c1e799e27f63bff7b42b4c36749e5e6f Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Mon, 20 Jun 2011 14:09:11 -0700 Subject: isci: Requests that do not start must be set to "complete" Requests that fail at start because of a reset pending condition must be set to complete in order to allow for later cleanup. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 3a891d32c331..5879e5f308e6 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -3678,18 +3678,19 @@ int isci_request_execute( * Update it's status and add it to the list in the * remote device object. */ - isci_request_change_state(request, started); list_add(&request->dev_node, &isci_device->reqs_in_process); if (status == SCI_SUCCESS) { /* Save the tag for possible task mgmt later. */ request->io_tag = request->sci.io_tag; + isci_request_change_state(request, started); } else { /* The request did not really start in the * hardware, so clear the request handle * here so no terminations will be done. */ request->terminated = true; + isci_request_change_state(request, completed); } spin_unlock_irqrestore(&isci_host->scic_lock, flags); -- cgit v1.2.3 From 77c852f312243192b1f2ce7fc56d678784786692 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Mon, 20 Jun 2011 14:09:16 -0700 Subject: isci: Handle timed-out request terminations correctly In the situation where a termination of an I/O times-out, make sure that the linkage from the request to the task is severed completely. Also make sure that the selection of tasks to terminate occurs under scic_lock. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 9 ++ drivers/scsi/isci/task.c | 358 +++++++++++++++++++++----------------------- 2 files changed, 181 insertions(+), 186 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 5879e5f308e6..433565c2b343 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2741,6 +2741,15 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, spin_unlock(&request->state_lock); break; + case dead: + /* This was a terminated request that timed-out during the + * termination process. There is no task to complete to + * libsas. + */ + complete_to_host = isci_perform_normal_io_completion; + spin_unlock(&request->state_lock); + break; + default: /* The request is done from an SCU HW perspective. */ diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 709c08171743..573cf1c9e81d 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -567,31 +567,33 @@ static enum isci_request_status isci_task_validate_request_to_abort( return old_state; } +/** +* isci_request_cleanup_completed_loiterer() - This function will take care of +* the final cleanup on any request which has been explicitly terminated. +* @isci_host: This parameter specifies the ISCI host object +* @isci_device: This is the device to which the request is pending. +* @isci_request: This parameter specifies the terminated request object. +* @task: This parameter is the libsas I/O request. +*/ static void isci_request_cleanup_completed_loiterer( - struct isci_host *isci_host, + struct isci_host *isci_host, struct isci_remote_device *isci_device, - struct isci_request *isci_request) + struct isci_request *isci_request, + struct sas_task *task) { - struct sas_task *task; - unsigned long flags; - - task = (isci_request->ttype == io_task) - ? isci_request_access_task(isci_request) - : NULL; + unsigned long flags; dev_dbg(&isci_host->pdev->dev, "%s: isci_device=%p, request=%p, task=%p\n", __func__, isci_device, isci_request, task); - spin_lock_irqsave(&isci_host->scic_lock, flags); - list_del_init(&isci_request->dev_node); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); - if (task != NULL) { spin_lock_irqsave(&task->task_state_lock, flags); task->lldd_task = NULL; + task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; + isci_set_task_doneflags(task); /* If this task is not in the abort path, call task_done. */ @@ -602,61 +604,16 @@ static void isci_request_cleanup_completed_loiterer( } else spin_unlock_irqrestore(&task->task_state_lock, flags); } - isci_request_free(isci_host, isci_request); -} - -/** -* @isci_termination_timed_out(): this function will deal with a request for -* which the wait for termination has timed-out. -* -* @isci_host This SCU. -* @isci_request The I/O request being terminated. -*/ -static void -isci_termination_timed_out( - struct isci_host * host, - struct isci_request * request - ) -{ - unsigned long state_flags; - - dev_warn(&host->pdev->dev, - "%s: host = %p; request = %p\n", - __func__, host, request); - /* At this point, the request to terminate - * has timed out. The best we can do is to - * have the request die a silent death - * if it ever completes. - */ - spin_lock_irqsave(&request->state_lock, state_flags); - - if (request->status == started) { - - /* Set the request state to "dead", - * and clear the task pointer so that an actual - * completion event callback doesn't do - * anything. - */ - request->status = dead; - - /* Clear the timeout completion event pointer.*/ - request->io_request_completion = NULL; - - if (request->ttype == io_task) { - - /* Break links with the sas_task. */ - if (request->ttype_ptr.io_task_ptr != NULL) { + if (isci_request != NULL) { + spin_lock_irqsave(&isci_host->scic_lock, flags); + list_del_init(&isci_request->dev_node); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); - request->ttype_ptr.io_task_ptr->lldd_task = NULL; - request->ttype_ptr.io_task_ptr = NULL; - } - } + isci_request_free(isci_host, isci_request); } - spin_unlock_irqrestore(&request->state_lock, state_flags); } - /** * isci_terminate_request_core() - This function will terminate the given * request, and wait for it to complete. This function must only be called @@ -666,7 +623,6 @@ isci_termination_timed_out( * @isci_device: The target. * @isci_request: The I/O request to be terminated. * - * */ static void isci_terminate_request_core( struct isci_host *isci_host, @@ -677,9 +633,10 @@ static void isci_terminate_request_core( bool was_terminated = false; bool needs_cleanup_handling = false; enum isci_request_status request_status; - unsigned long flags; - unsigned long timeout_remaining; - + unsigned long flags; + unsigned long termination_completed = 1; + struct completion *io_request_completion; + struct sas_task *task; dev_dbg(&isci_host->pdev->dev, "%s: device = %p; request = %p\n", @@ -687,6 +644,12 @@ static void isci_terminate_request_core( spin_lock_irqsave(&isci_host->scic_lock, flags); + io_request_completion = isci_request->io_request_completion; + + task = (isci_request->ttype == io_task) + ? isci_request_access_task(isci_request) + : NULL; + /* Note that we are not going to control * the target to abort the request. */ @@ -715,119 +678,112 @@ static void isci_terminate_request_core( dev_err(&isci_host->pdev->dev, "%s: scic_controller_terminate_request" " returned = 0x%x\n", - __func__, - status); - /* Clear the completion pointer from the request. */ + __func__, status); + isci_request->io_request_completion = NULL; } else { if (was_terminated) { dev_dbg(&isci_host->pdev->dev, - "%s: before completion wait (%p)\n", - __func__, - isci_request->io_request_completion); + "%s: before completion wait (%p/%p)\n", + __func__, isci_request, io_request_completion); /* Wait here for the request to complete. */ - #define TERMINATION_TIMEOUT_MSEC 50 - timeout_remaining + #define TERMINATION_TIMEOUT_MSEC 500 + termination_completed = wait_for_completion_timeout( - isci_request->io_request_completion, + io_request_completion, msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC)); - if (!timeout_remaining) { + if (!termination_completed) { + + /* The request to terminate has timed out. */ + spin_lock_irqsave(&isci_host->scic_lock, + flags); + + /* Check for state changes. */ + if (!isci_request->terminated) { + + /* The best we can do is to have the + * request die a silent death if it + * ever really completes. + * + * Set the request state to "dead", + * and clear the task pointer so that + * an actual completion event callback + * doesn't do anything. + */ + isci_request->status = dead; + isci_request->io_request_completion + = NULL; + + if (isci_request->ttype == io_task) { + + /* Break links with the + * sas_task. + */ + isci_request->ttype_ptr.io_task_ptr + = NULL; + } + } else + termination_completed = 1; + + spin_unlock_irqrestore(&isci_host->scic_lock, + flags); - isci_termination_timed_out(isci_host, - isci_request); + if (!termination_completed) { - dev_err(&isci_host->pdev->dev, - "%s: *** Timeout waiting for " - "termination(%p/%p)\n", - __func__, - isci_request->io_request_completion, - isci_request); + dev_err(&isci_host->pdev->dev, + "%s: *** Timeout waiting for " + "termination(%p/%p)\n", + __func__, io_request_completion, + isci_request); - } else + /* The request can no longer be referenced + * safely since it may go away if the + * termination every really does complete. + */ + isci_request = NULL; + } + } + if (termination_completed) dev_dbg(&isci_host->pdev->dev, - "%s: after completion wait (%p)\n", - __func__, - isci_request->io_request_completion); + "%s: after completion wait (%p/%p)\n", + __func__, isci_request, io_request_completion); } - /* Clear the completion pointer from the request. */ - isci_request->io_request_completion = NULL; - /* Peek at the status of the request. This will tell - * us if there was special handling on the request such that it - * needs to be detached and freed here. - */ - spin_lock_irqsave(&isci_request->state_lock, flags); - request_status = isci_request_get_state(isci_request); - - if ((isci_request->ttype == io_task) /* TMFs are in their own thread */ - && ((request_status == aborted) - || (request_status == aborting) - || (request_status == terminating) - || (request_status == completed) - || (request_status == dead) - ) - ) { - - /* The completion routine won't free a request in - * the aborted/aborting/etc. states, so we do - * it here. - */ - needs_cleanup_handling = true; - } - spin_unlock_irqrestore(&isci_request->state_lock, flags); - - if (needs_cleanup_handling) - isci_request_cleanup_completed_loiterer( - isci_host, isci_device, isci_request - ); - } -} + if (termination_completed) { -static void isci_terminate_request( - struct isci_host *isci_host, - struct isci_remote_device *isci_device, - struct isci_request *isci_request, - enum isci_request_status new_request_state) -{ - enum isci_request_status old_state; - DECLARE_COMPLETION_ONSTACK(request_completion); + isci_request->io_request_completion = NULL; - /* Change state to "new_request_state" if it is currently "started" */ - old_state = isci_request_change_started_to_newstate( - isci_request, - &request_completion, - new_request_state - ); + /* Peek at the status of the request. This will tell + * us if there was special handling on the request such that it + * needs to be detached and freed here. + */ + spin_lock_irqsave(&isci_request->state_lock, flags); + request_status = isci_request_get_state(isci_request); + + if ((isci_request->ttype == io_task) /* TMFs are in their own thread */ + && ((request_status == aborted) + || (request_status == aborting) + || (request_status == terminating) + || (request_status == completed) + || (request_status == dead) + ) + ) { + + /* The completion routine won't free a request in + * the aborted/aborting/etc. states, so we do + * it here. + */ + needs_cleanup_handling = true; + } + spin_unlock_irqrestore(&isci_request->state_lock, flags); - if ((old_state == started) || - (old_state == completed) || - (old_state == aborting)) { - - /* If the old_state is started: - * This request was not already being aborted. If it had been, - * then the aborting I/O (ie. the TMF request) would not be in - * the aborting state, and thus would be terminated here. Note - * that since the TMF completion's call to the kernel function - * "complete()" does not happen until the pending I/O request - * terminate fully completes, we do not have to implement a - * special wait here for already aborting requests - the - * termination of the TMF request will force the request - * to finish it's already started terminate. - * - * If old_state == completed: - * This request completed from the SCU hardware perspective - * and now just needs cleaning up in terms of freeing the - * request and potentially calling up to libsas. - * - * If old_state == aborting: - * This request has already gone through a TMF timeout, but may - * not have been terminated; needs cleaning up at least. - */ - isci_terminate_request_core(isci_host, isci_device, - isci_request); + } + if (needs_cleanup_handling) + isci_request_cleanup_completed_loiterer( + isci_host, isci_device, isci_request, task); } } @@ -850,9 +806,8 @@ void isci_terminate_pending_requests( struct isci_request *request; struct isci_request *next_request; unsigned long flags; - struct list_head aborted_request_list; - - INIT_LIST_HEAD(&aborted_request_list); + enum isci_request_status old_state; + DECLARE_COMPLETION_ONSTACK(request_completion); dev_dbg(&isci_host->pdev->dev, "%s: isci_device = %p (new request state = %d)\n", @@ -860,31 +815,62 @@ void isci_terminate_pending_requests( spin_lock_irqsave(&isci_host->scic_lock, flags); - /* Move all of the pending requests off of the device list. */ - list_splice_init(&isci_device->reqs_in_process, - &aborted_request_list); - - spin_unlock_irqrestore(&isci_host->scic_lock, flags); - - /* Iterate through the now-local list. */ + /* Iterate through the list. */ list_for_each_entry_safe(request, next_request, - &aborted_request_list, dev_node) { + &isci_device->reqs_in_process, dev_node) { - dev_warn(&isci_host->pdev->dev, - "%s: isci_device=%p request=%p; task=%p\n", - __func__, - isci_device, request, - ((request->ttype == io_task) - ? isci_request_access_task(request) - : NULL)); + init_completion(&request_completion); - /* Mark all still pending I/O with the selected next - * state, terminate and free it. + /* Change state to "new_request_state" if it is currently + * "started". */ - isci_terminate_request(isci_host, isci_device, - request, new_request_state - ); + old_state = isci_request_change_started_to_newstate( + request, + &request_completion, + new_request_state); + + spin_unlock_irqrestore(&isci_host->scic_lock, flags); + + if ((old_state == started) || + (old_state == completed) || + (old_state == aborting)) { + + dev_warn(&isci_host->pdev->dev, + "%s: isci_device=%p request=%p; task=%p " + "old_state=%d\n", + __func__, + isci_device, request, + ((request->ttype == io_task) + ? isci_request_access_task(request) + : NULL), + old_state); + + /* If the old_state is started: + * This request was not already being aborted. If it had been, + * then the aborting I/O (ie. the TMF request) would not be in + * the aborting state, and thus would be terminated here. Note + * that since the TMF completion's call to the kernel function + * "complete()" does not happen until the pending I/O request + * terminate fully completes, we do not have to implement a + * special wait here for already aborting requests - the + * termination of the TMF request will force the request + * to finish it's already started terminate. + * + * If old_state == completed: + * This request completed from the SCU hardware perspective + * and now just needs cleaning up in terms of freeing the + * request and potentially calling up to libsas. + * + * If old_state == aborting: + * This request has already gone through a TMF timeout, but may + * not have been terminated; needs cleaning up at least. + */ + isci_terminate_request_core(isci_host, isci_device, + request); + } + spin_lock_irqsave(&isci_host->scic_lock, flags); } + spin_unlock_irqrestore(&isci_host->scic_lock, flags); } /** @@ -1257,9 +1243,9 @@ int isci_task_abort_task(struct sas_task *task) if (ret == TMF_RESP_FUNC_COMPLETE) { old_request->complete_in_target = true; - /* Clean up the request on our side, and wait for the aborted I/O to - * complete. - */ + /* Clean up the request on our side, and wait for the aborted + * I/O to complete. + */ isci_terminate_request_core(isci_host, isci_device, old_request); } -- cgit v1.2.3 From 980d3aeb3828b0fdf2a0b2e893d238130b014575 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 20 Jun 2011 15:11:22 -0700 Subject: isci: fix isci_terminate_pending() list management Walk through the list of pending requests being careful to consider that multiple requests can be terminated when the lock is dropped (i.e. invalidating the 'next' reference established by list_for_each_entry_safe). Also noticed that all callers to isci_terminate_pending_requests() specifying terminating, so just drop the parameter. Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 2 +- drivers/scsi/isci/request.h | 5 +- drivers/scsi/isci/task.c | 131 +++++++++++++++++++------------------- 3 files changed, 67 insertions(+), 71 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 3b555dcbe569..45592ad33c3b 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1272,7 +1272,7 @@ void isci_remote_device_nuke_requests(struct isci_host *ihost, struct isci_remot "%s: idev = %p\n", __func__, idev); /* Cleanup all requests pending for this device. */ - isci_terminate_pending_requests(ihost, idev, terminating); + isci_terminate_pending_requests(ihost, idev); dev_dbg(&ihost->pdev->dev, "%s: idev = %p, done\n", __func__, idev); diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 547c35cbe459..ac9368c5a6b5 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -776,9 +776,8 @@ isci_request_io_request_get_next_sge(struct isci_request *request, } void -isci_terminate_pending_requests(struct isci_host *isci_host, - struct isci_remote_device *isci_device, - enum isci_request_status new_request_state); +isci_terminate_pending_requests(struct isci_host *ihost, + struct isci_remote_device *idev); enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 573cf1c9e81d..01032dc2c116 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -796,81 +796,79 @@ static void isci_terminate_request_core( * @isci_host: This parameter specifies SCU. * @isci_device: This parameter specifies the target. * - * */ -void isci_terminate_pending_requests( - struct isci_host *isci_host, - struct isci_remote_device *isci_device, - enum isci_request_status new_request_state) +void isci_terminate_pending_requests(struct isci_host *ihost, + struct isci_remote_device *idev) { - struct isci_request *request; - struct isci_request *next_request; - unsigned long flags; + struct completion request_completion; enum isci_request_status old_state; - DECLARE_COMPLETION_ONSTACK(request_completion); - - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p (new request state = %d)\n", - __func__, isci_device, new_request_state); + unsigned long flags; + LIST_HEAD(list); - spin_lock_irqsave(&isci_host->scic_lock, flags); + spin_lock_irqsave(&ihost->scic_lock, flags); + list_splice_init(&idev->reqs_in_process, &list); - /* Iterate through the list. */ - list_for_each_entry_safe(request, next_request, - &isci_device->reqs_in_process, dev_node) { + /* assumes that isci_terminate_request_core deletes from the list */ + while (!list_empty(&list)) { + struct isci_request *ireq = list_entry(list.next, typeof(*ireq), dev_node); - init_completion(&request_completion); + /* Change state to "terminating" if it is currently + * "started". + */ + old_state = isci_request_change_started_to_newstate(ireq, + &request_completion, + terminating); + switch (old_state) { + case started: + case completed: + case aborting: + break; + default: + /* termination in progress, or otherwise dispositioned. + * We know the request was on 'list' so should be safe + * to move it back to reqs_in_process + */ + list_move(&ireq->dev_node, &idev->reqs_in_process); + ireq = NULL; + break; + } - /* Change state to "new_request_state" if it is currently - * "started". - */ - old_state = isci_request_change_started_to_newstate( - request, - &request_completion, - new_request_state); + if (!ireq) + continue; + spin_unlock_irqrestore(&ihost->scic_lock, flags); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + init_completion(&request_completion); - if ((old_state == started) || - (old_state == completed) || - (old_state == aborting)) { - - dev_warn(&isci_host->pdev->dev, - "%s: isci_device=%p request=%p; task=%p " - "old_state=%d\n", - __func__, - isci_device, request, - ((request->ttype == io_task) - ? isci_request_access_task(request) - : NULL), - old_state); - - /* If the old_state is started: - * This request was not already being aborted. If it had been, - * then the aborting I/O (ie. the TMF request) would not be in - * the aborting state, and thus would be terminated here. Note - * that since the TMF completion's call to the kernel function - * "complete()" does not happen until the pending I/O request - * terminate fully completes, we do not have to implement a - * special wait here for already aborting requests - the - * termination of the TMF request will force the request - * to finish it's already started terminate. - * - * If old_state == completed: - * This request completed from the SCU hardware perspective - * and now just needs cleaning up in terms of freeing the - * request and potentially calling up to libsas. - * - * If old_state == aborting: - * This request has already gone through a TMF timeout, but may - * not have been terminated; needs cleaning up at least. - */ - isci_terminate_request_core(isci_host, isci_device, - request); - } - spin_lock_irqsave(&isci_host->scic_lock, flags); + dev_dbg(&ihost->pdev->dev, + "%s: idev=%p request=%p; task=%p old_state=%d\n", + __func__, idev, ireq, + ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL, + old_state); + + /* If the old_state is started: + * This request was not already being aborted. If it had been, + * then the aborting I/O (ie. the TMF request) would not be in + * the aborting state, and thus would be terminated here. Note + * that since the TMF completion's call to the kernel function + * "complete()" does not happen until the pending I/O request + * terminate fully completes, we do not have to implement a + * special wait here for already aborting requests - the + * termination of the TMF request will force the request + * to finish it's already started terminate. + * + * If old_state == completed: + * This request completed from the SCU hardware perspective + * and now just needs cleaning up in terms of freeing the + * request and potentially calling up to libsas. + * + * If old_state == aborting: + * This request has already gone through a TMF timeout, but may + * not have been terminated; needs cleaning up at least. + */ + isci_terminate_request_core(ihost, idev, ireq); + spin_lock_irqsave(&ihost->scic_lock, flags); } - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); } /** @@ -965,8 +963,7 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) if (ret == TMF_RESP_FUNC_COMPLETE) /* Terminate all I/O now. */ isci_terminate_pending_requests(isci_host, - isci_device, - terminating); + isci_device); return ret; } -- cgit v1.2.3 From fd53660120b5eda06539225de56755dc389a4e64 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Mon, 20 Jun 2011 14:09:22 -0700 Subject: isci: Explicitly decode remote node ready and suspended states The remote node context should only signal a device reset condition in a suspended state. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_node_context.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 9e8967e19688..b6774bcdabd8 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -603,12 +603,23 @@ enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_nod enum scis_sds_remote_node_context_states state; state = sci_rnc->sm.current_state_id; - if (state != SCI_RNC_READY) { + + switch (state) { + case SCI_RNC_READY: + return SCI_SUCCESS; + case SCI_RNC_TX_SUSPENDED: + case SCI_RNC_TX_RX_SUSPENDED: + case SCI_RNC_AWAIT_SUSPENSION: dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %d\n", __func__, state); return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; + default: + break; } - return SCI_SUCCESS; + dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), + "%s: requested to start IO while still resuming, %d\n", + __func__, state); + return SCI_FAILURE_INVALID_STATE; } enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_node_context *sci_rnc, -- cgit v1.2.3 From fd0527ab15bfd96f04b084b1b2550f80cf151b60 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Mon, 20 Jun 2011 14:09:26 -0700 Subject: isci: Hard reset failure will link reset all phys in the port In the case where the hard reset process fails, each link in the port is put through a link reset sequence. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 2946eee8e702..e540281ebd49 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1916,7 +1916,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor { unsigned long flags; enum sci_status status; - int ret = TMF_RESP_FUNC_COMPLETE; + int idx, ret = TMF_RESP_FUNC_COMPLETE; dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n", __func__, iport); @@ -1953,14 +1953,26 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor * the same as link failures on all phys in the port. */ if (ret != TMF_RESP_FUNC_COMPLETE) { + dev_err(&ihost->pdev->dev, "%s: iport = %p; hard reset failed " - "(0x%x) - sending link down to libsas for phy %p\n", - __func__, iport, iport->hard_reset_status, iphy); + "(0x%x) - driving explicit link fail for all phys\n", + __func__, iport, iport->hard_reset_status); - isci_port_link_down(ihost, iphy, iport); - } + /* Down all phys in the port. */ + spin_lock_irqsave(&ihost->scic_lock, flags); + for (idx = 0; idx < SCI_MAX_PHYS; ++idx) { + + if (iport->sci.phy_table[idx] != NULL) { + scic_sds_phy_stop( + iport->sci.phy_table[idx]); + scic_sds_phy_start( + iport->sci.phy_table[idx]); + } + } + spin_unlock_irqrestore(&ihost->scic_lock, flags); + } return ret; } -- cgit v1.2.3 From 9b917987fd16d0687afe550a02f68099419f5d43 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Mon, 20 Jun 2011 14:09:31 -0700 Subject: isci: Disable link layer hang detection Some targets exceed the hang detect timer. Use the OS timeout to catch hung tasks. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 784c9a71333a..93a401dfbd30 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -242,11 +242,8 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, &sci_phy->link_layer_registers->maximum_arbitration_wait_timer_timeout); } - /* - * Set the link layer hang detection to 500ms (0x1F4) from its default - * value of 128ms. Max value is 511 ms. - */ - writel(0x1F4, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout); + /* Disable link layer hang detection, rely on the OS timeout for I/O timeouts. */ + writel(0, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout); /* We can exit the initial state to the stopped state */ sci_change_state(&sci_phy->sm, SCI_PHY_STOPPED); -- cgit v1.2.3 From ac668c69709c7d927015c5cf3d9e87bf4eaaf57d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 7 Jun 2011 18:50:55 -0700 Subject: isci: cleanup/optimize pool implementation The circ_buf macros are ~6% faster, as measured by perf, because they take advantage of power-of-two math assumptions i.e. no test and branch for rollover. Their semantics are clearer than the hidden side effects in pool.h (like sci_pool_get() which hides an assignment). Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 75 ++++++++++++------ drivers/scsi/isci/host.h | 12 +-- drivers/scsi/isci/isci.h | 1 + drivers/scsi/isci/pool.h | 199 ----------------------------------------------- 4 files changed, 56 insertions(+), 231 deletions(-) delete mode 100644 drivers/scsi/isci/pool.h diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 41a7c5099dea..343655bd1a6a 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -52,6 +52,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include "host.h" @@ -1054,6 +1055,33 @@ done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } +static void isci_tci_free(struct isci_host *ihost, u16 tci) +{ + u16 tail = ihost->tci_tail & (SCI_MAX_IO_REQUESTS-1); + + ihost->tci_pool[tail] = tci; + ihost->tci_tail = tail + 1; +} + +static u16 isci_tci_alloc(struct isci_host *ihost) +{ + u16 head = ihost->tci_head & (SCI_MAX_IO_REQUESTS-1); + u16 tci = ihost->tci_pool[head]; + + ihost->tci_head = head + 1; + return tci; +} + +static u16 isci_tci_active(struct isci_host *ihost) +{ + return CIRC_CNT(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); +} + +static u16 isci_tci_space(struct isci_host *ihost) +{ + return CIRC_SPACE(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); +} + static enum sci_status scic_controller_start(struct scic_sds_controller *scic, u32 timeout) { @@ -1069,9 +1097,11 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, } /* Build the TCi free pool */ - sci_pool_initialize(scic->tci_pool); + BUILD_BUG_ON(SCI_MAX_IO_REQUESTS > 1 << sizeof(ihost->tci_pool[0]) * 8); + ihost->tci_head = 0; + ihost->tci_tail = 0; for (index = 0; index < scic->task_context_entries; index++) - sci_pool_put(scic->tci_pool, index); + isci_tci_free(ihost, index); /* Build the RNi free pool */ scic_sds_remote_node_table_initialize( @@ -3063,18 +3093,17 @@ enum sci_task_status scic_controller_start_task( * currently available tags to be allocated. All return other values indicate a * legitimate tag. */ -u16 scic_controller_allocate_io_tag( - struct scic_sds_controller *scic) +u16 scic_controller_allocate_io_tag(struct scic_sds_controller *scic) { - u16 task_context; - u16 sequence_count; - - if (!sci_pool_empty(scic->tci_pool)) { - sci_pool_get(scic->tci_pool, task_context); + struct isci_host *ihost = scic_to_ihost(scic); + u16 tci; + u16 seq; - sequence_count = scic->io_request_sequence[task_context]; + if (isci_tci_space(ihost)) { + tci = isci_tci_alloc(ihost); + seq = scic->io_request_sequence[tci]; - return scic_sds_io_tag_construct(sequence_count, task_context); + return scic_sds_io_tag_construct(seq, tci); } return SCI_CONTROLLER_INVALID_IO_TAG; @@ -3105,10 +3134,10 @@ u16 scic_controller_allocate_io_tag( * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag * is not a valid IO tag value. */ -enum sci_status scic_controller_free_io_tag( - struct scic_sds_controller *scic, - u16 io_tag) +enum sci_status scic_controller_free_io_tag(struct scic_sds_controller *scic, + u16 io_tag) { + struct isci_host *ihost = scic_to_ihost(scic); u16 sequence; u16 index; @@ -3117,18 +3146,16 @@ enum sci_status scic_controller_free_io_tag( sequence = scic_sds_io_tag_get_sequence(io_tag); index = scic_sds_io_tag_get_index(io_tag); - if (!sci_pool_full(scic->tci_pool)) { - if (sequence == scic->io_request_sequence[index]) { - scic_sds_io_sequence_increment( - scic->io_request_sequence[index]); + /* prevent tail from passing head */ + if (isci_tci_active(ihost) == 0) + return SCI_FAILURE_INVALID_IO_TAG; - sci_pool_put(scic->tci_pool, index); + if (sequence == scic->io_request_sequence[index]) { + scic_sds_io_sequence_increment(scic->io_request_sequence[index]); - return SCI_SUCCESS; - } - } + isci_tci_free(ihost, index); + return SCI_SUCCESS; + } return SCI_FAILURE_INVALID_IO_TAG; } - - diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 740350043d89..c61a9fa130b7 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -57,7 +57,6 @@ #include "remote_device.h" #include "phy.h" -#include "pool.h" #include "isci.h" #include "remote_node_table.h" #include "registers.h" @@ -179,11 +178,6 @@ struct scic_sds_controller { */ struct scic_remote_node_table available_remote_nodes; - /** - * This field is the TCi pool used to manage the task context index. - */ - SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS); - /** * This filed is the struct scic_power_control data used to controll when direct * attached devices can consume power. @@ -310,6 +304,10 @@ struct scic_sds_controller { struct isci_host { struct scic_sds_controller sci; + u16 tci_head; + u16 tci_tail; + u16 tci_pool[SCI_MAX_IO_REQUESTS]; + union scic_oem_parameters oem_parameters; int id; /* unique within a given pci device */ @@ -423,8 +421,6 @@ enum scic_sds_controller_states { SCIC_FAILED, }; - - /** * struct isci_pci_info - This class represents the pci function containing the * controllers. Depending on PCI SKU, there could be up to 2 controllers in diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 714ed926171b..84ba533ca51e 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -112,6 +112,7 @@ static inline void check_sizes(void) BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_UNSOLICITED_FRAMES); BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_COMPLETION_QUEUE_ENTRIES); BUILD_BUG_ON(SCU_MAX_UNSOLICITED_FRAMES > SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES); + BUILD_BUG_ON_NOT_POWER_OF_2(SCI_MAX_IO_REQUESTS); } /** diff --git a/drivers/scsi/isci/pool.h b/drivers/scsi/isci/pool.h deleted file mode 100644 index 016ec832f74f..000000000000 --- a/drivers/scsi/isci/pool.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This file contains the interface to the pool class. This class allows two - * different two different priority tasks to insert and remove items from - * the free pool. The user of the pool is expected to evaluate the pool - * condition empty before a get operation and pool condition full before a - * put operation. Methods Provided: - sci_pool_create() - - * sci_pool_initialize() - sci_pool_empty() - sci_pool_full() - - * sci_pool_get() - sci_pool_put() - * - * - */ - -#ifndef _SCI_POOL_H_ -#define _SCI_POOL_H_ - -/** - * SCI_POOL_INCREMENT() - - * - * Private operation for the pool - */ -#define SCI_POOL_INCREMENT(pool, index) \ - (((index) + 1) == (pool).size ? 0 : (index) + 1) - -/** - * SCI_POOL_CREATE() - - * - * This creates a pool structure of pool_name. The members in the pool are of - * type with number of elements equal to size. - */ -#define SCI_POOL_CREATE(pool_name, type, pool_size) \ - struct \ - { \ - u32 size; \ - u32 get; \ - u32 put; \ - type array[(pool_size) + 1]; \ - } pool_name - - -/** - * sci_pool_empty() - - * - * This macro evaluates the pool and returns true if the pool is empty. If the - * pool is empty the user should not perform any get operation on the pool. - */ -#define sci_pool_empty(pool) \ - ((pool).get == (pool).put) - -/** - * sci_pool_full() - - * - * This macro evaluates the pool and returns true if the pool is full. If the - * pool is full the user should not perform any put operation. - */ -#define sci_pool_full(pool) \ - (SCI_POOL_INCREMENT(pool, (pool).put) == (pool).get) - -/** - * sci_pool_size() - - * - * This macro returns the size of the pool created. The internal size of the - * pool is actually 1 larger then necessary in order to ensure get and put - * pointers can be written simultaneously by different users. As a result, - * this macro subtracts 1 from the internal size - */ -#define sci_pool_size(pool) \ - ((pool).size - 1) - -/** - * sci_pool_count() - - * - * This macro indicates the number of elements currently contained in the pool. - */ -#define sci_pool_count(pool) \ - (\ - sci_pool_empty((pool)) \ - ? 0 \ - : (\ - sci_pool_full((pool)) \ - ? sci_pool_size((pool)) \ - : (\ - (pool).get > (pool).put \ - ? ((pool).size - (pool).get + (pool).put) \ - : ((pool).put - (pool).get) \ - ) \ - ) \ - ) - -/** - * sci_pool_initialize() - - * - * This macro initializes the pool to an empty condition. - */ -#define sci_pool_initialize(pool) \ - { \ - (pool).size = (sizeof((pool).array) / sizeof((pool).array[0])); \ - (pool).get = 0; \ - (pool).put = 0; \ - } - -/** - * sci_pool_get() - - * - * This macro will get the next free element from the pool. This should only be - * called if the pool is not empty. - */ -#define sci_pool_get(pool, my_value) \ - { \ - (my_value) = (pool).array[(pool).get]; \ - (pool).get = SCI_POOL_INCREMENT((pool), (pool).get); \ - } - -/** - * sci_pool_put() - - * - * This macro will put the value into the pool. This should only be called if - * the pool is not full. - */ -#define sci_pool_put(pool, value) \ - { \ - (pool).array[(pool).put] = (value); \ - (pool).put = SCI_POOL_INCREMENT((pool), (pool).put); \ - } - -/** - * sci_pool_erase() - - * - * This macro will search the pool and remove any elements in the pool matching - * the supplied value. This method can only be utilized on pools - */ -#define sci_pool_erase(pool, type, value) \ - { \ - type tmp_value; \ - u32 index; \ - u32 element_count = sci_pool_count((pool)); \ - \ - for (index = 0; index < element_count; index++) { \ - sci_pool_get((pool), tmp_value); \ - if (tmp_value != (value)) \ - sci_pool_put((pool), tmp_value); \ - } \ - } - -#endif /* _SCI_POOL_H_ */ -- cgit v1.2.3 From dd047c8e2bca22856050dbe0378a37cf44eecc97 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 9 Jun 2011 11:06:58 -0700 Subject: isci: cleanup tag macros A tag is a 16 bit number where the upper four bits is a sequence number and the remainder is the task context index (tci). Sanitize the macro names and shave 256-bytes out of scic_sds_controller by reducing the size of io_request_sequence. scic_sds_io_tag_construct --> ISCI_TAG scic_sds_io_tag_get_sequence --> ISCI_TAG_SEQ scic_sds_io_tag_get_index() --> ISCI_TAG_TCI scic_sds_io_sequence_increment() [delete / open code] Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 88 +++++++++++++++++---------------------------- drivers/scsi/isci/host.h | 47 ++++-------------------- drivers/scsi/isci/isci.h | 2 ++ drivers/scsi/isci/port.c | 17 +++------ drivers/scsi/isci/request.c | 12 +++---- 5 files changed, 52 insertions(+), 114 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 343655bd1a6a..3c7042b8bc0e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -284,23 +284,16 @@ static void scic_sds_controller_task_completion(struct scic_sds_controller *scic u32 completion_entry) { u32 index; - struct scic_sds_request *io_request; + struct scic_sds_request *sci_req; index = SCU_GET_COMPLETION_INDEX(completion_entry); - io_request = scic->io_request_table[index]; + sci_req = scic->io_request_table[index]; /* Make sure that we really want to process this IO request */ - if ( - (io_request != NULL) - && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) - && ( - scic_sds_io_tag_get_sequence(io_request->io_tag) - == scic->io_request_sequence[index] - ) - ) { + if (sci_req && sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && + ISCI_TAG_SEQ(sci_req->io_tag) == scic->io_request_sequence[index]) /* Yep this is a valid io request pass it along to the io request handler */ - scic_sds_io_request_tc_completion(io_request, completion_entry); - } + scic_sds_io_request_tc_completion(sci_req, completion_entry); } static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic, @@ -2682,37 +2675,28 @@ void scic_sds_controller_copy_task_context( sci_req->task_context_buffer = task_context_buffer; } -/** - * This method returns the task context buffer for the given io tag. - * @scic: - * @io_tag: - * - * struct scu_task_context* - */ -struct scu_task_context *scic_sds_controller_get_task_context_buffer( - struct scic_sds_controller *scic, - u16 io_tag - ) { - u16 task_index = scic_sds_io_tag_get_index(io_tag); +struct scu_task_context *scic_sds_controller_get_task_context_buffer(struct scic_sds_controller *scic, + u16 io_tag) +{ + u16 tci = ISCI_TAG_TCI(io_tag); - if (task_index < scic->task_context_entries) { - return &scic->task_context_table[task_index]; + if (tci < scic->task_context_entries) { + return &scic->task_context_table[tci]; } return NULL; } -struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, - u16 io_tag) +struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 io_tag) { u16 task_index; u16 task_sequence; - task_index = scic_sds_io_tag_get_index(io_tag); + task_index = ISCI_TAG_TCI(io_tag); - if (task_index < scic->task_context_entries) { + if (task_index < scic->task_context_entries) { if (scic->io_request_table[task_index] != NULL) { - task_sequence = scic_sds_io_tag_get_sequence(io_tag); + task_sequence = ISCI_TAG_SEQ(io_tag); if (task_sequence == scic->io_request_sequence[task_index]) { return scic->io_request_table[task_index]; @@ -2875,11 +2859,10 @@ void scic_sds_controller_release_frame( * successfully started the IO request. SCI_SUCCESS if the IO request was * successfully started. Determine the failure situations and return values. */ -enum sci_status scic_controller_start_io( - struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, - struct scic_sds_request *req, - u16 io_tag) +enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, + struct scic_sds_remote_device *rdev, + struct scic_sds_request *req, + u16 io_tag) { enum sci_status status; @@ -2892,7 +2875,7 @@ enum sci_status scic_controller_start_io( if (status != SCI_SUCCESS) return status; - scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; + scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); return SCI_SUCCESS; } @@ -2979,7 +2962,7 @@ enum sci_status scic_controller_complete_io( if (status != SCI_SUCCESS) return status; - index = scic_sds_io_tag_get_index(request->io_tag); + index = ISCI_TAG_TCI(request->io_tag); scic->io_request_table[index] = NULL; return SCI_SUCCESS; default: @@ -2998,7 +2981,7 @@ enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) return SCI_FAILURE_INVALID_STATE; } - scic->io_request_table[scic_sds_io_tag_get_index(sci_req->io_tag)] = sci_req; + scic->io_request_table[ISCI_TAG_TCI(sci_req->io_tag)] = sci_req; scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req)); return SCI_SUCCESS; } @@ -3050,7 +3033,7 @@ enum sci_task_status scic_controller_start_task( status = scic_sds_remote_device_start_task(scic, rdev, req); switch (status) { case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: - scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; + scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; /* * We will let framework know this task request started successfully, @@ -3059,7 +3042,7 @@ enum sci_task_status scic_controller_start_task( */ return SCI_SUCCESS; case SCI_SUCCESS: - scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req; + scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); @@ -3096,14 +3079,12 @@ enum sci_task_status scic_controller_start_task( u16 scic_controller_allocate_io_tag(struct scic_sds_controller *scic) { struct isci_host *ihost = scic_to_ihost(scic); - u16 tci; - u16 seq; if (isci_tci_space(ihost)) { - tci = isci_tci_alloc(ihost); - seq = scic->io_request_sequence[tci]; + u16 tci = isci_tci_alloc(ihost); + u8 seq = scic->io_request_sequence[tci]; - return scic_sds_io_tag_construct(seq, tci); + return ISCI_TAG(seq, tci); } return SCI_CONTROLLER_INVALID_IO_TAG; @@ -3138,22 +3119,17 @@ enum sci_status scic_controller_free_io_tag(struct scic_sds_controller *scic, u16 io_tag) { struct isci_host *ihost = scic_to_ihost(scic); - u16 sequence; - u16 index; - - BUG_ON(io_tag == SCI_CONTROLLER_INVALID_IO_TAG); - - sequence = scic_sds_io_tag_get_sequence(io_tag); - index = scic_sds_io_tag_get_index(io_tag); + u16 tci = ISCI_TAG_TCI(io_tag); + u16 seq = ISCI_TAG_SEQ(io_tag); /* prevent tail from passing head */ if (isci_tci_active(ihost) == 0) return SCI_FAILURE_INVALID_IO_TAG; - if (sequence == scic->io_request_sequence[index]) { - scic_sds_io_sequence_increment(scic->io_request_sequence[index]); + if (seq == scic->io_request_sequence[tci]) { + scic->io_request_sequence[tci] = (seq+1) & (SCI_MAX_SEQ-1); - isci_tci_free(ihost, index); + isci_tci_free(ihost, ISCI_TAG_TCI(io_tag)); return SCI_SUCCESS; } diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index c61a9fa130b7..7d17ab80f1a9 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -184,13 +184,8 @@ struct scic_sds_controller { */ struct scic_power_control power_control; - /** - * This field is the array of sequence values for the IO Tag fields. Even - * though only 4 bits of the field is used for the sequence the sequence is 16 - * bits in size so the sequence can be bitwise or'd with the TCi to build the - * IO Tag value. - */ - u16 io_request_sequence[SCI_MAX_IO_REQUESTS]; + /* sequence number per tci */ + u8 io_request_sequence[SCI_MAX_IO_REQUESTS]; /** * This field in the array of sequence values for the RNi. These are used @@ -552,40 +547,12 @@ static inline struct isci_host *scic_to_ihost(struct scic_sds_controller *scic) */ #define scic_sds_controller_get_protocol_engine_group(controller) 0 -/** - * scic_sds_io_tag_construct() - - * - * This macro constructs an IO tag from the sequence and index values. - */ -#define scic_sds_io_tag_construct(sequence, task_index) \ - ((sequence) << 12 | (task_index)) - -/** - * scic_sds_io_tag_get_sequence() - - * - * This macro returns the IO sequence from the IO tag value. - */ -#define scic_sds_io_tag_get_sequence(io_tag) \ - (((io_tag) & 0xF000) >> 12) - -/** - * scic_sds_io_tag_get_index() - - * - * This macro returns the TCi from the io tag value - */ -#define scic_sds_io_tag_get_index(io_tag) \ - ((io_tag) & 0x0FFF) +/* see scic_controller_io_tag_allocate|free for how seq and tci are built */ +#define ISCI_TAG(seq, tci) (((u16) (seq)) << 12 | tci) -/** - * scic_sds_io_sequence_increment() - - * - * This is a helper macro to increment the io sequence count. We may find in - * the future that it will be faster to store the sequence count in such a way - * as we dont perform the shift operation to build io tag values so therefore - * need a way to incrment them correctly - */ -#define scic_sds_io_sequence_increment(value) \ - ((value) = (((value) + 1) & 0x000F)) +/* these are returned by the hardware, so sanitize them */ +#define ISCI_TAG_SEQ(tag) (((tag) >> 12) & (SCI_MAX_SEQ-1)) +#define ISCI_TAG_TCI(tag) ((tag) & (SCI_MAX_IO_REQUESTS-1)) /* expander attached sata devices require 3 rnc slots */ static inline int scic_sds_remote_device_node_count(struct scic_sds_remote_device *sci_dev) diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 84ba533ca51e..81bade421b96 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -83,6 +83,7 @@ enum sci_controller_mode { #define SCI_MAX_SMP_PHYS (384) /* not silicon constrained */ #define SCI_MAX_REMOTE_DEVICES (256UL) #define SCI_MAX_IO_REQUESTS (256UL) +#define SCI_MAX_SEQ (16) #define SCI_MAX_MSIX_MESSAGES (2) #define SCI_MAX_SCATTER_GATHER_ELEMENTS 130 /* not silicon constrained */ #define SCI_MAX_CONTROLLERS 2 @@ -113,6 +114,7 @@ static inline void check_sizes(void) BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_COMPLETION_QUEUE_ENTRIES); BUILD_BUG_ON(SCU_MAX_UNSOLICITED_FRAMES > SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES); BUILD_BUG_ON_NOT_POWER_OF_2(SCI_MAX_IO_REQUESTS); + BUILD_BUG_ON_NOT_POWER_OF_2(SCI_MAX_SEQ); } /** diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index e540281ebd49..fb66e30da075 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -689,23 +689,16 @@ static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u1 rnc->ssp.arbitration_wait_time = 0; } -/** - * scic_sds_port_construct_dummy_task() - create dummy task for si workaround - * @sci_port The logical port on which we need to create the - * remote node context. - * context. - * @tci The remote node index for this remote node context. - * - * This routine will construct a dummy task context data structure. This +/* + * construct a dummy task context data structure. This * structure will be posted to the hardwre to work around a scheduler error * in the hardware. - * */ -static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tci) +static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tag) { struct scu_task_context *task_context; - task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tci); + task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tag); memset(task_context, 0, sizeof(struct scu_task_context)); @@ -716,7 +709,7 @@ static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u task_context->protocol_engine_index = 0; task_context->logical_port_index = sci_port->physical_port_index; task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; - task_context->task_index = scic_sds_io_tag_get_index(tci); + task_context->task_index = ISCI_TAG_TCI(tag); task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 433565c2b343..9d7531ad9a74 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -258,7 +258,7 @@ static void scu_ssp_reqeust_construct_task_context( SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | (scic_sds_port_get_index(target_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sds_request->io_tag)); + ISCI_TAG_TCI(sds_request->io_tag)); } else { /* * Build the task context now since we have already read @@ -433,7 +433,7 @@ static void scu_sata_reqeust_construct_task_context( SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | (scic_sds_port_get_index(target_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sci_req->io_tag)); + ISCI_TAG_TCI(sci_req->io_tag)); } else { /* * Build the task context now since we have already read @@ -741,7 +741,7 @@ static u32 sci_req_tx_bytes(struct scic_sds_request *sci_req) */ ret_val = readl(scu_reg_base + (SCU_TASK_CONTEXT_SRAM + offsetof(struct scu_task_context, type.ssp.data_offset)) + - ((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(sci_req->io_tag))); + ((sizeof(struct scu_task_context)) * ISCI_TAG_TCI(sci_req->io_tag))); } return ret_val; @@ -777,7 +777,7 @@ enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) if (sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { task_context = sci_req->task_context_buffer; - task_context->task_index = scic_sds_io_tag_get_index(sci_req->io_tag); + task_context->task_index = ISCI_TAG_TCI(sci_req->io_tag); switch (task_context->protocol_type) { case SCU_TASK_CONTEXT_PROTOCOL_SMP: @@ -811,7 +811,7 @@ enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) scic_sds_controller_copy_task_context(scic, sci_req); /* Add to the post_context the io tag value */ - sci_req->post_context |= scic_sds_io_tag_get_index(sci_req->io_tag); + sci_req->post_context |= ISCI_TAG_TCI(sci_req->io_tag); /* Everything is good go ahead and change state */ sci_change_state(&sci_req->sm, SCI_REQ_STARTED); @@ -3325,7 +3325,7 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | (scic_sds_port_get_index(sci_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - scic_sds_io_tag_get_index(sci_req->io_tag)); + ISCI_TAG_TCI(sci_req->io_tag)); } else { /* * Build the task context now since we have already read -- cgit v1.2.3 From 994a9303d33f8238d57f58c26067b6d4ac9af222 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 9 Jun 2011 16:04:28 -0700 Subject: isci: cleanup/optimize queue increment macros Every single i/o or event completion incurs a test and branch to see if the cycle bit changed. For power-of-2 queue sizes the cycle bit can be read directly from the rollover of the queue pointer. Likely premature optimization, but the hidden if() and hidden assignments / side-effects in the macros were already asking to be cleaned up. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 56 ++++++-------------------- drivers/scsi/isci/host.h | 16 -------- drivers/scsi/isci/isci.h | 4 +- drivers/scsi/isci/unsolicited_frame_control.c | 58 +++++++++++++-------------- 4 files changed, 44 insertions(+), 90 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 3c7042b8bc0e..ae9edae1d245 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -122,34 +122,6 @@ >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \ ) -/** - * INCREMENT_COMPLETION_QUEUE_GET() - - * - * This macro will increment the controllers completion queue index value and - * possibly toggle the cycle bit if the completion queue index wraps back to 0. - */ -#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \ - INCREMENT_QUEUE_GET(\ - (index), \ - (cycle), \ - SCU_MAX_COMPLETION_QUEUE_ENTRIES, \ - SMU_CQGR_CYCLE_BIT) - -/** - * INCREMENT_EVENT_QUEUE_GET() - - * - * This macro will increment the controllers event queue index value and - * possibly toggle the event cycle bit if the event queue index wraps back to 0. - */ -#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \ - INCREMENT_QUEUE_GET(\ - (index), \ - (cycle), \ - SCU_MAX_EVENTS, \ - SMU_CQGR_EVENT_CYCLE_BIT \ - ) - - /** * NORMALIZE_GET_POINTER() - * @@ -528,15 +500,13 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci } } - - static void scic_sds_controller_process_completions(struct scic_sds_controller *scic) { u32 completion_count = 0; u32 completion_entry; u32 get_index; u32 get_cycle; - u32 event_index; + u32 event_get; u32 event_cycle; dev_dbg(scic_to_dev(scic), @@ -548,7 +518,7 @@ static void scic_sds_controller_process_completions(struct scic_sds_controller * get_index = NORMALIZE_GET_POINTER(scic->completion_queue_get); get_cycle = SMU_CQGR_CYCLE_BIT & scic->completion_queue_get; - event_index = NORMALIZE_EVENT_POINTER(scic->completion_queue_get); + event_get = NORMALIZE_EVENT_POINTER(scic->completion_queue_get); event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & scic->completion_queue_get; while ( @@ -558,7 +528,11 @@ static void scic_sds_controller_process_completions(struct scic_sds_controller * completion_count++; completion_entry = scic->completion_queue[get_index]; - INCREMENT_COMPLETION_QUEUE_GET(scic, get_index, get_cycle); + + /* increment the get pointer and check for rollover to toggle the cycle bit */ + get_cycle ^= ((get_index+1) & SCU_MAX_COMPLETION_QUEUE_ENTRIES) << + (SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT - SCU_MAX_COMPLETION_QUEUE_SHIFT); + get_index = (get_index+1) & (SCU_MAX_COMPLETION_QUEUE_ENTRIES-1); dev_dbg(scic_to_dev(scic), "%s: completion queue entry:0x%08x\n", @@ -579,18 +553,14 @@ static void scic_sds_controller_process_completions(struct scic_sds_controller * break; case SCU_COMPLETION_TYPE_EVENT: - INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle); - scic_sds_controller_event_completion(scic, completion_entry); - break; + case SCU_COMPLETION_TYPE_NOTIFY: { + event_cycle ^= ((event_get+1) & SCU_MAX_EVENTS) << + (SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT - SCU_MAX_EVENTS_SHIFT); + event_get = (event_get+1) & (SCU_MAX_EVENTS-1); - case SCU_COMPLETION_TYPE_NOTIFY: - /* - * Presently we do the same thing with a notify event that we do with the - * other event codes. */ - INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle); scic_sds_controller_event_completion(scic, completion_entry); break; - + } default: dev_warn(scic_to_dev(scic), "%s: SCIC Controller received unknown " @@ -607,7 +577,7 @@ static void scic_sds_controller_process_completions(struct scic_sds_controller * SMU_CQGR_GEN_BIT(ENABLE) | SMU_CQGR_GEN_BIT(EVENT_ENABLE) | event_cycle | - SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) | + SMU_CQGR_GEN_VAL(EVENT_POINTER, event_get) | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 7d17ab80f1a9..94fd54dc9f01 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -523,22 +523,6 @@ static inline struct isci_host *scic_to_ihost(struct scic_sds_controller *scic) return ihost; } -/** - * INCREMENT_QUEUE_GET() - - * - * This macro will increment the specified index to and if the index wraps to 0 - * it will toggel the cycle bit. - */ -#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \ - { \ - if ((index) + 1 == entry_count) { \ - (index) = 0; \ - (cycle) = (cycle) ^ (bit_toggle); \ - } else { \ - index = index + 1; \ - } \ - } - /** * scic_sds_controller_get_protocol_engine_group() - * diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 81bade421b96..207328369edd 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -90,7 +90,8 @@ enum sci_controller_mode { #define SCI_MAX_DOMAINS SCI_MAX_PORTS #define SCU_MAX_CRITICAL_NOTIFICATIONS (384) -#define SCU_MAX_EVENTS (128) +#define SCU_MAX_EVENTS_SHIFT (7) +#define SCU_MAX_EVENTS (1 << SCU_MAX_EVENTS_SHIFT) #define SCU_MAX_UNSOLICITED_FRAMES (128) #define SCU_MAX_COMPLETION_QUEUE_SCRATCH (128) #define SCU_MAX_COMPLETION_QUEUE_ENTRIES (SCU_MAX_CRITICAL_NOTIFICATIONS \ @@ -98,6 +99,7 @@ enum sci_controller_mode { + SCU_MAX_UNSOLICITED_FRAMES \ + SCI_MAX_IO_REQUESTS \ + SCU_MAX_COMPLETION_QUEUE_SCRATCH) +#define SCU_MAX_COMPLETION_QUEUE_SHIFT (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES)) #define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096) #define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024) diff --git a/drivers/scsi/isci/unsolicited_frame_control.c b/drivers/scsi/isci/unsolicited_frame_control.c index d89570700ffd..680582d8cde5 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.c +++ b/drivers/scsi/isci/unsolicited_frame_control.c @@ -209,7 +209,8 @@ bool scic_sds_unsolicited_frame_control_release_frame( /* * In the event there are NULL entries in the UF table, we need to * advance the get pointer in order to find out if this frame should - * be released (i.e. update the get pointer). */ + * be released (i.e. update the get pointer) + */ while (lower_32_bits(uf_control->address_table.array[frame_get]) == 0 && upper_32_bits(uf_control->address_table.array[frame_get]) == 0 && frame_get < SCU_MAX_UNSOLICITED_FRAMES) @@ -217,40 +218,37 @@ bool scic_sds_unsolicited_frame_control_release_frame( /* * The table has a NULL entry as it's last element. This is - * illegal. */ + * illegal. + */ BUG_ON(frame_get >= SCU_MAX_UNSOLICITED_FRAMES); + if (frame_index >= SCU_MAX_UNSOLICITED_FRAMES) + return false; - if (frame_index < SCU_MAX_UNSOLICITED_FRAMES) { - uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED; + uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED; + if (frame_get != frame_index) { /* - * The frame index is equal to the current get pointer so we - * can now free up all of the frame entries that */ - if (frame_get == frame_index) { - while ( - uf_control->buffers.array[frame_get].state - == UNSOLICITED_FRAME_RELEASED - ) { - uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY; - - INCREMENT_QUEUE_GET( - frame_get, - frame_cycle, - SCU_MAX_UNSOLICITED_FRAMES - 1, - SCU_MAX_UNSOLICITED_FRAMES); - } - - uf_control->get = - (SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get); + * Frames remain in use until we advance the get pointer + * so there is nothing we can do here + */ + return false; + } - return true; - } else { - /* - * Frames remain in use until we advance the get pointer - * so there is nothing we can do here */ - } + /* + * The frame index is equal to the current get pointer so we + * can now free up all of the frame entries that + */ + while (uf_control->buffers.array[frame_get].state == UNSOLICITED_FRAME_RELEASED) { + uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY; + + if (frame_get+1 == SCU_MAX_UNSOLICITED_FRAMES-1) { + frame_cycle ^= SCU_MAX_UNSOLICITED_FRAMES; + frame_get = 0; + } else + frame_get++; } - return false; -} + uf_control->get = SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get; + return true; +} -- cgit v1.2.3 From 0d0cf14c9bd2943ed5afd15df459f564d85eacde Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 13 Jun 2011 00:51:30 -0700 Subject: isci: cleanup request allocation Rather than return an error code and update a pointer that was passed by reference just return the request object directly (or null if allocation failed). Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 197 +++++++++++++++----------------------------- drivers/scsi/isci/request.h | 11 +-- drivers/scsi/isci/task.c | 136 +++++++++++------------------- 3 files changed, 121 insertions(+), 223 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 9d7531ad9a74..f0813d076c50 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -3510,172 +3510,110 @@ static enum sci_status isci_io_request_build( return SCI_SUCCESS; } -/** - * isci_request_alloc_core() - This function gets the request object from the - * isci_host dma cache. - * @isci_host: This parameter specifies the ISCI host object - * @isci_request: This parameter will contain the pointer to the new - * isci_request object. - * @isci_device: This parameter is the pointer to the isci remote device object - * that is the destination for this request. - * @gfp_flags: This parameter specifies the os allocation flags. - * - * SCI_SUCCESS on successfull completion, or specific failure code. - */ -static int isci_request_alloc_core( - struct isci_host *isci_host, - struct isci_request **isci_request, - struct isci_remote_device *isci_device, - gfp_t gfp_flags) +static struct isci_request *isci_request_alloc_core(struct isci_host *ihost, + struct isci_remote_device *idev, + gfp_t gfp_flags) { - int ret = 0; dma_addr_t handle; - struct isci_request *request; - + struct isci_request *ireq; - /* get pointer to dma memory. This actually points - * to both the isci_remote_device object and the - * sci object. The isci object is at the beginning - * of the memory allocated here. - */ - request = dma_pool_alloc(isci_host->dma_pool, gfp_flags, &handle); - if (!request) { - dev_warn(&isci_host->pdev->dev, + ireq = dma_pool_alloc(ihost->dma_pool, gfp_flags, &handle); + if (!ireq) { + dev_warn(&ihost->pdev->dev, "%s: dma_pool_alloc returned NULL\n", __func__); - return -ENOMEM; + return NULL; } /* initialize the request object. */ - spin_lock_init(&request->state_lock); - request->request_daddr = handle; - request->isci_host = isci_host; - request->isci_device = isci_device; - request->io_request_completion = NULL; - request->terminated = false; + spin_lock_init(&ireq->state_lock); + ireq->request_daddr = handle; + ireq->isci_host = ihost; + ireq->isci_device = idev; + ireq->io_request_completion = NULL; + ireq->terminated = false; - request->num_sg_entries = 0; + ireq->num_sg_entries = 0; - request->complete_in_target = false; + ireq->complete_in_target = false; - INIT_LIST_HEAD(&request->completed_node); - INIT_LIST_HEAD(&request->dev_node); + INIT_LIST_HEAD(&ireq->completed_node); + INIT_LIST_HEAD(&ireq->dev_node); - *isci_request = request; - isci_request_change_state(request, allocated); + isci_request_change_state(ireq, allocated); - return ret; + return ireq; } -static int isci_request_alloc_io( - struct isci_host *isci_host, - struct sas_task *task, - struct isci_request **isci_request, - struct isci_remote_device *isci_device, - gfp_t gfp_flags) +static struct isci_request *isci_request_alloc_io(struct isci_host *ihost, + struct sas_task *task, + struct isci_remote_device *idev, + gfp_t gfp_flags) { - int retval = isci_request_alloc_core(isci_host, isci_request, - isci_device, gfp_flags); - - if (!retval) { - (*isci_request)->ttype_ptr.io_task_ptr = task; - (*isci_request)->ttype = io_task; + struct isci_request *ireq; - task->lldd_task = *isci_request; + ireq = isci_request_alloc_core(ihost, idev, gfp_flags); + if (ireq) { + ireq->ttype_ptr.io_task_ptr = task; + ireq->ttype = io_task; + task->lldd_task = ireq; } - return retval; + return ireq; } -/** - * isci_request_alloc_tmf() - This function gets the request object from the - * isci_host dma cache and initializes the relevant fields as a sas_task. - * @isci_host: This parameter specifies the ISCI host object - * @sas_task: This parameter is the task struct from the upper layer driver. - * @isci_request: This parameter will contain the pointer to the new - * isci_request object. - * @isci_device: This parameter is the pointer to the isci remote device object - * that is the destination for this request. - * @gfp_flags: This parameter specifies the os allocation flags. - * - * SCI_SUCCESS on successfull completion, or specific failure code. - */ -int isci_request_alloc_tmf( - struct isci_host *isci_host, - struct isci_tmf *isci_tmf, - struct isci_request **isci_request, - struct isci_remote_device *isci_device, - gfp_t gfp_flags) +struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, + struct isci_tmf *isci_tmf, + struct isci_remote_device *idev, + gfp_t gfp_flags) { - int retval = isci_request_alloc_core(isci_host, isci_request, - isci_device, gfp_flags); - - if (!retval) { + struct isci_request *ireq; - (*isci_request)->ttype_ptr.tmf_task_ptr = isci_tmf; - (*isci_request)->ttype = tmf_task; + ireq = isci_request_alloc_core(ihost, idev, gfp_flags); + if (ireq) { + ireq->ttype_ptr.tmf_task_ptr = isci_tmf; + ireq->ttype = tmf_task; } - return retval; + return ireq; } -/** - * isci_request_execute() - This function allocates the isci_request object, - * all fills in some common fields. - * @isci_host: This parameter specifies the ISCI host object - * @sas_task: This parameter is the task struct from the upper layer driver. - * @isci_request: This parameter will contain the pointer to the new - * isci_request object. - * @gfp_flags: This parameter specifies the os allocation flags. - * - * SCI_SUCCESS on successfull completion, or specific failure code. - */ -int isci_request_execute( - struct isci_host *isci_host, - struct sas_task *task, - struct isci_request **isci_request, - gfp_t gfp_flags) +int isci_request_execute(struct isci_host *ihost, struct sas_task *task, + gfp_t gfp_flags) { - int ret = 0; - struct scic_sds_remote_device *sci_device; enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - struct isci_remote_device *isci_device; - struct isci_request *request; + struct scic_sds_remote_device *sci_dev; + struct isci_remote_device *idev; + struct isci_request *ireq; unsigned long flags; + int ret = 0; - isci_device = task->dev->lldd_dev; - sci_device = &isci_device->sci; + idev = task->dev->lldd_dev; + sci_dev = &idev->sci; /* do common allocation and init of request object. */ - ret = isci_request_alloc_io( - isci_host, - task, - &request, - isci_device, - gfp_flags - ); - - if (ret) + ireq = isci_request_alloc_io(ihost, task, idev, gfp_flags); + if (!ireq) goto out; - status = isci_io_request_build(isci_host, request, isci_device); + status = isci_io_request_build(ihost, ireq, idev); if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: request_construct failed - status = 0x%x\n", __func__, status); goto out; } - spin_lock_irqsave(&isci_host->scic_lock, flags); + spin_lock_irqsave(&ihost->scic_lock, flags); /* send the request, let the core assign the IO TAG. */ - status = scic_controller_start_io(&isci_host->sci, sci_device, - &request->sci, + status = scic_controller_start_io(&ihost->sci, sci_dev, + &ireq->sci, SCI_CONTROLLER_INVALID_IO_TAG); if (status != SCI_SUCCESS && status != SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: failed request start (0x%x)\n", __func__, status); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); goto out; } @@ -3687,21 +3625,21 @@ int isci_request_execute( * Update it's status and add it to the list in the * remote device object. */ - list_add(&request->dev_node, &isci_device->reqs_in_process); + list_add(&ireq->dev_node, &idev->reqs_in_process); if (status == SCI_SUCCESS) { /* Save the tag for possible task mgmt later. */ - request->io_tag = request->sci.io_tag; - isci_request_change_state(request, started); + ireq->io_tag = ireq->sci.io_tag; + isci_request_change_state(ireq, started); } else { /* The request did not really start in the * hardware, so clear the request handle * here so no terminations will be done. */ - request->terminated = true; - isci_request_change_state(request, completed); + ireq->terminated = true; + isci_request_change_state(ireq, completed); } - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); if (status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { @@ -3716,7 +3654,7 @@ int isci_request_execute( /* Cause this task to be scheduled in the SCSI error * handler thread. */ - isci_execpath_callback(isci_host, task, + isci_execpath_callback(ihost, task, sas_task_abort); /* Change the status, since we are holding @@ -3729,11 +3667,10 @@ int isci_request_execute( out: if (status != SCI_SUCCESS) { /* release dma memory on failure. */ - isci_request_free(isci_host, request); - request = NULL; + isci_request_free(ihost, ireq); + ireq = NULL; ret = SCI_FAILURE; } - *isci_request = request; return ret; } diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index ac9368c5a6b5..8de2542f081f 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -679,16 +679,13 @@ static inline void isci_request_free(struct isci_host *isci_host, #define isci_request_access_tmf(req) ((req)->ttype_ptr.tmf_task_ptr) -int isci_request_alloc_tmf(struct isci_host *isci_host, - struct isci_tmf *isci_tmf, - struct isci_request **isci_request, - struct isci_remote_device *isci_device, - gfp_t gfp_flags); - +struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, + struct isci_tmf *isci_tmf, + struct isci_remote_device *idev, + gfp_t gfp_flags); int isci_request_execute(struct isci_host *isci_host, struct sas_task *task, - struct isci_request **request, gfp_t gfp_flags); /** diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 01032dc2c116..ded81cd1a781 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -146,7 +146,6 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) { struct isci_host *ihost = dev_to_ihost(task->dev); - struct isci_request *request = NULL; struct isci_remote_device *device; unsigned long flags; int ret; @@ -226,8 +225,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) spin_unlock_irqrestore(&task->task_state_lock, flags); /* build and send the request. */ - status = isci_request_execute(ihost, task, &request, - gfp_flags); + status = isci_request_execute(ihost, task, gfp_flags); if (status != SCI_SUCCESS) { @@ -254,54 +252,34 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) return 0; } - - -/** - * isci_task_request_build() - This function builds the task request object. - * @isci_host: This parameter specifies the ISCI host object - * @request: This parameter points to the isci_request object allocated in the - * request construct function. - * @tmf: This parameter is the task management struct to be built - * - * SCI_SUCCESS on successfull completion, or specific failure code. - */ -static enum sci_status isci_task_request_build( - struct isci_host *isci_host, - struct isci_request **isci_request, - struct isci_tmf *isci_tmf) +static struct isci_request *isci_task_request_build(struct isci_host *ihost, + struct isci_tmf *isci_tmf) { - struct scic_sds_remote_device *sci_device; + struct scic_sds_remote_device *sci_dev; enum sci_status status = SCI_FAILURE; - struct isci_request *request = NULL; - struct isci_remote_device *isci_device; + struct isci_request *ireq = NULL; + struct isci_remote_device *idev; struct domain_device *dev; - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: isci_tmf = %p\n", __func__, isci_tmf); - isci_device = isci_tmf->device; - sci_device = &isci_device->sci; - dev = isci_device->domain_dev; + idev = isci_tmf->device; + sci_dev = &idev->sci; + dev = idev->domain_dev; /* do common allocation and init of request object. */ - status = isci_request_alloc_tmf( - isci_host, - isci_tmf, - &request, - isci_device, - GFP_ATOMIC - ); - - if (status != SCI_SUCCESS) - goto out; + ireq = isci_request_alloc_tmf(ihost, isci_tmf, idev, GFP_ATOMIC); + if (!ireq) + return NULL; /* let the core do it's construct. */ - status = scic_task_request_construct(&isci_host->sci, sci_device, + status = scic_task_request_construct(&ihost->sci, sci_dev, SCI_CONTROLLER_INVALID_IO_TAG, - &request->sci); + &ireq->sci); if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: scic_task_request_construct failed - " "status = 0x%x\n", __func__, @@ -312,30 +290,23 @@ static enum sci_status isci_task_request_build( /* XXX convert to get this from task->tproto like other drivers */ if (dev->dev_type == SAS_END_DEV) { isci_tmf->proto = SAS_PROTOCOL_SSP; - status = scic_task_request_construct_ssp(&request->sci); + status = scic_task_request_construct_ssp(&ireq->sci); if (status != SCI_SUCCESS) goto errout; } if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { isci_tmf->proto = SAS_PROTOCOL_SATA; - status = isci_sata_management_task_request_build(request); + status = isci_sata_management_task_request_build(ireq); if (status != SCI_SUCCESS) goto errout; } - - goto out; - + return ireq; errout: - - /* release the dma memory if we fail. */ - isci_request_free(isci_host, request); - request = NULL; - - out: - *isci_request = request; - return status; + isci_request_free(ihost, ireq); + ireq = NULL; + return ireq; } /** @@ -350,16 +321,14 @@ static enum sci_status isci_task_request_build( * TMF_RESP_FUNC_COMPLETE on successful completion of the TMF (this includes * error conditions reported in the IU status), or TMF_RESP_FUNC_FAILED. */ -int isci_task_execute_tmf( - struct isci_host *isci_host, - struct isci_tmf *tmf, - unsigned long timeout_ms) +int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, + unsigned long timeout_ms) { DECLARE_COMPLETION_ONSTACK(completion); enum sci_task_status status = SCI_TASK_FAILURE; struct scic_sds_remote_device *sci_device; struct isci_remote_device *isci_device = tmf->device; - struct isci_request *request; + struct isci_request *ireq; int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; unsigned long timeleft; @@ -368,13 +337,13 @@ int isci_task_execute_tmf( * if the device is not there and ready. */ if (!isci_device || isci_device->status != isci_ready_for_io) { - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: isci_device = %p not ready (%d)\n", __func__, isci_device, isci_device->status); return TMF_RESP_FUNC_FAILED; } else - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: isci_device = %p\n", __func__, isci_device); @@ -383,64 +352,59 @@ int isci_task_execute_tmf( /* Assign the pointer to the TMF's completion kernel wait structure. */ tmf->complete = &completion; - isci_task_request_build( - isci_host, - &request, - tmf - ); - - if (!request) { - dev_warn(&isci_host->pdev->dev, + ireq = isci_task_request_build(ihost, tmf); + if (!ireq) { + dev_warn(&ihost->pdev->dev, "%s: isci_task_request_build failed\n", __func__); return TMF_RESP_FUNC_FAILED; } - spin_lock_irqsave(&isci_host->scic_lock, flags); + spin_lock_irqsave(&ihost->scic_lock, flags); /* start the TMF io. */ status = scic_controller_start_task( - &isci_host->sci, + &ihost->sci, sci_device, - &request->sci, + &ireq->sci, SCI_CONTROLLER_INVALID_IO_TAG); if (status != SCI_TASK_SUCCESS) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: start_io failed - status = 0x%x, request = %p\n", __func__, status, - request); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + ireq); + spin_unlock_irqrestore(&ihost->scic_lock, flags); goto cleanup_request; } if (tmf->cb_state_func != NULL) tmf->cb_state_func(isci_tmf_started, tmf, tmf->cb_data); - isci_request_change_state(request, started); + isci_request_change_state(ireq, started); /* add the request to the remote device request list. */ - list_add(&request->dev_node, &isci_device->reqs_in_process); + list_add(&ireq->dev_node, &isci_device->reqs_in_process); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Wait for the TMF to complete, or a timeout. */ timeleft = wait_for_completion_timeout(&completion, jiffies + msecs_to_jiffies(timeout_ms)); if (timeleft == 0) { - spin_lock_irqsave(&isci_host->scic_lock, flags); + spin_lock_irqsave(&ihost->scic_lock, flags); if (tmf->cb_state_func != NULL) tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); status = scic_controller_terminate_request( - &request->isci_host->sci, - &request->isci_device->sci, - &request->sci); + &ireq->isci_host->sci, + &ireq->isci_device->sci, + &ireq->sci); - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); } isci_print_tmf(tmf); @@ -448,7 +412,7 @@ int isci_task_execute_tmf( if (tmf->status == SCI_SUCCESS) ret = TMF_RESP_FUNC_COMPLETE; else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) { - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: tmf.status == " "SCI_FAILURE_IO_RESPONSE_VALID\n", __func__); @@ -456,18 +420,18 @@ int isci_task_execute_tmf( } /* Else - leave the default "failed" status alone. */ - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: completed request = %p\n", __func__, - request); + ireq); - if (request->io_request_completion != NULL) { + if (ireq->io_request_completion != NULL) { /* A thread is waiting for this TMF to finish. */ - complete(request->io_request_completion); + complete(ireq->io_request_completion); } cleanup_request: - isci_request_free(isci_host, request); + isci_request_free(ihost, ireq); return ret; } -- cgit v1.2.3 From 360b03ed178a4fe3971b0a098d8feeb53333481b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 15 Jun 2011 11:11:03 -0700 Subject: isci: fix ssp response iu buffer size in isci_tmf In isci_task_request_complete() we save the response/sense data from the command. Make sure isci_tmf has enough space to hold the full response. [ it does not look like we actually use this data, and response_data_len/sense_data_len should be specifying the byte count, in any event do the simple fix first so we don't corrupt memory ] Reported-by: Adam Gruchala Tested-by: Edmund Nadolski Signed-off-by: Dan Williams --- drivers/scsi/isci/task.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index c8dd075d2be2..d574a18956d7 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -100,7 +100,8 @@ struct isci_tmf { union { struct ssp_response_iu resp_iu; struct dev_to_host_fis d2h_fis; - } resp; + u8 rsp_buf[SSP_RESP_IU_MAX_SIZE]; + } resp; unsigned char lun[8]; u16 io_tag; struct isci_remote_device *device; -- cgit v1.2.3 From 209fae14fabfd48525e5630bebbbd4ca15090c60 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 13 Jun 2011 17:39:44 -0700 Subject: isci: atomic device lookup and reference counting We have unsafe references to remote devices that are notified to disappear at lldd_dev_gone. In order to clean this up we need a single canonical source for device lookups and stable references once a lookup succeeds. Towards that end guarantee that domain_device.lldd_dev is NULL as soon as we start the process of stopping a device. Any code path that wants to safely lookup a remote device must do so through task->dev->lldd_dev (isci_lookup_device()). For in-flight references outside of scic_lock we need reference counting to ensure that the device is not recycled before we are done with it. Simplify device back references to just scic_sds_request.target_device which is now the only permissible internal reference that is maintained relative to the reference count. There were two occasions where we wanted new i/o's to be treated as SAS_TASK_UNDELIVERED but where the domain_dev->lldd_dev link is still intact. Introduce a 'gone' flag to prevent i/o while waiting for libsas to take action on the port down event. One 'core' leftover is that we currently call scic_remote_device_destruct() from isci_remote_device_deconstruct() which is called when the 'core' says the device is stopped. It would be more natural for the final put to trigger isci_remote_device_deconstruct() but this implementation is deferred as it requires other changes. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 4 +- drivers/scsi/isci/port.c | 3 +- drivers/scsi/isci/remote_device.c | 80 ++++++------- drivers/scsi/isci/remote_device.h | 23 ++++ drivers/scsi/isci/request.c | 60 ++++------ drivers/scsi/isci/request.h | 7 +- drivers/scsi/isci/sata.c | 7 +- drivers/scsi/isci/task.c | 231 +++++++++++++++----------------------- drivers/scsi/isci/task.h | 9 +- 9 files changed, 187 insertions(+), 237 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index ae9edae1d245..40f35fad244b 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1327,8 +1327,8 @@ void isci_host_deinit(struct isci_host *ihost) struct isci_remote_device *idev, *d; list_for_each_entry_safe(idev, d, &iport->remote_dev_list, node) { - isci_remote_device_change_state(idev, isci_stopping); - isci_remote_device_stop(ihost, idev); + if (test_bit(IDEV_ALLOCATED, &idev->flags)) + isci_remote_device_stop(ihost, idev); } } diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index fb66e30da075..5f4a4e3954db 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -321,8 +321,7 @@ static void isci_port_link_down(struct isci_host *isci_host, dev_dbg(&isci_host->pdev->dev, "%s: isci_device = %p\n", __func__, isci_device); - isci_remote_device_change_state(isci_device, - isci_stopping); + set_bit(IDEV_GONE, &isci_device->flags); } } isci_port_change_state(isci_port, isci_stopping); diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 45592ad33c3b..ab5f9868e4ef 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -94,7 +94,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, "%s: isci_device = %p\n", __func__, idev); if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) - isci_remote_device_change_state(idev, isci_stopping); + set_bit(IDEV_GONE, &idev->flags); else /* device ready is actually a "not ready for io" state. */ isci_remote_device_change_state(idev, isci_ready); @@ -449,8 +449,10 @@ static void scic_sds_remote_device_start_request(struct scic_sds_remote_device * /* cleanup requests that failed after starting on the port */ if (status != SCI_SUCCESS) scic_sds_port_complete_io(sci_port, sci_dev, sci_req); - else + else { + kref_get(&sci_dev_to_idev(sci_dev)->kref); scic_sds_remote_device_increment_request_count(sci_dev); + } } enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic, @@ -656,6 +658,8 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " "could not complete\n", __func__, sci_port, sci_dev, sci_req, status); + else + isci_put_device(sci_dev_to_idev(sci_dev)); return status; } @@ -860,23 +864,11 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ * here should go through isci_remote_device_nuke_requests. * If we hit this condition, we will need a way to complete * io requests in process */ - while (!list_empty(&idev->reqs_in_process)) { - - dev_err(&ihost->pdev->dev, - "%s: ** request list not empty! **\n", __func__); - BUG(); - } + BUG_ON(!list_empty(&idev->reqs_in_process)); scic_remote_device_destruct(&idev->sci); - idev->domain_dev->lldd_dev = NULL; - idev->domain_dev = NULL; - idev->isci_port = NULL; list_del_init(&idev->node); - - clear_bit(IDEV_START_PENDING, &idev->flags); - clear_bit(IDEV_STOP_PENDING, &idev->flags); - clear_bit(IDEV_EH, &idev->flags); - wake_up(&ihost->eventq); + isci_put_device(idev); } /** @@ -1314,6 +1306,22 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) return idev; } +void isci_remote_device_release(struct kref *kref) +{ + struct isci_remote_device *idev = container_of(kref, typeof(*idev), kref); + struct isci_host *ihost = idev->isci_port->isci_host; + + idev->domain_dev = NULL; + idev->isci_port = NULL; + clear_bit(IDEV_START_PENDING, &idev->flags); + clear_bit(IDEV_STOP_PENDING, &idev->flags); + clear_bit(IDEV_GONE, &idev->flags); + clear_bit(IDEV_EH, &idev->flags); + smp_mb__before_clear_bit(); + clear_bit(IDEV_ALLOCATED, &idev->flags); + wake_up(&ihost->eventq); +} + /** * isci_remote_device_stop() - This function is called internally to stop the * remote device. @@ -1330,7 +1338,11 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem dev_dbg(&ihost->pdev->dev, "%s: isci_device = %p\n", __func__, idev); + spin_lock_irqsave(&ihost->scic_lock, flags); + idev->domain_dev->lldd_dev = NULL; /* disable new lookups */ + set_bit(IDEV_GONE, &idev->flags); isci_remote_device_change_state(idev, isci_stopping); + spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Kill all outstanding requests. */ isci_remote_device_nuke_requests(ihost, idev); @@ -1342,14 +1354,10 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Wait for the stop complete callback. */ - if (status == SCI_SUCCESS) { + if (WARN_ONCE(status != SCI_SUCCESS, "failed to stop device\n")) + /* nothing to wait for */; + else wait_for_device_stop(ihost, idev); - clear_bit(IDEV_ALLOCATED, &idev->flags); - } - - dev_dbg(&ihost->pdev->dev, - "%s: idev = %p - after completion wait\n", - __func__, idev); return status; } @@ -1416,39 +1424,33 @@ int isci_remote_device_found(struct domain_device *domain_dev) if (!isci_device) return -ENODEV; + kref_init(&isci_device->kref); INIT_LIST_HEAD(&isci_device->node); - domain_dev->lldd_dev = isci_device; + + spin_lock_irq(&isci_host->scic_lock); isci_device->domain_dev = domain_dev; isci_device->isci_port = isci_port; isci_remote_device_change_state(isci_device, isci_starting); - - - spin_lock_irq(&isci_host->scic_lock); list_add_tail(&isci_device->node, &isci_port->remote_dev_list); set_bit(IDEV_START_PENDING, &isci_device->flags); status = isci_remote_device_construct(isci_port, isci_device); - spin_unlock_irq(&isci_host->scic_lock); dev_dbg(&isci_host->pdev->dev, "%s: isci_device = %p\n", __func__, isci_device); - if (status != SCI_SUCCESS) { - - spin_lock_irq(&isci_host->scic_lock); - isci_remote_device_deconstruct( - isci_host, - isci_device - ); - spin_unlock_irq(&isci_host->scic_lock); - return -ENODEV; - } + if (status == SCI_SUCCESS) { + /* device came up, advertise it to the world */ + domain_dev->lldd_dev = isci_device; + } else + isci_put_device(isci_device); + spin_unlock_irq(&isci_host->scic_lock); /* wait for the device ready callback. */ wait_for_device_start(isci_host, isci_device); - return 0; + return status == SCI_SUCCESS ? 0 : -ENODEV; } /** * isci_device_is_reset_pending() - This function will check if there is any diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 2b6a5bb7bd60..05842b5f1e3b 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -56,6 +56,7 @@ #ifndef _ISCI_REMOTE_DEVICE_H_ #define _ISCI_REMOTE_DEVICE_H_ #include +#include #include "scu_remote_node_context.h" #include "remote_node_context.h" #include "port.h" @@ -134,7 +135,9 @@ struct isci_remote_device { #define IDEV_STOP_PENDING 1 #define IDEV_ALLOCATED 2 #define IDEV_EH 3 + #define IDEV_GONE 4 unsigned long flags; + struct kref kref; struct isci_port *isci_port; struct domain_device *domain_dev; struct list_head node; @@ -145,6 +148,26 @@ struct isci_remote_device { #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 +/* device reference routines must be called under scic_lock */ +static inline struct isci_remote_device *isci_lookup_device(struct domain_device *dev) +{ + struct isci_remote_device *idev = dev->lldd_dev; + + if (idev && !test_bit(IDEV_GONE, &idev->flags)) { + kref_get(&idev->kref); + return idev; + } + + return NULL; +} + +void isci_remote_device_release(struct kref *kref); +static inline void isci_put_device(struct isci_remote_device *idev) +{ + if (idev) + kref_put(&idev->kref, isci_remote_device_release); +} + enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev); void isci_remote_device_nuke_requests(struct isci_host *ihost, diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index f0813d076c50..fd6314abeb0b 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2313,7 +2313,7 @@ static void isci_request_set_open_reject_status( * none. */ static void isci_request_handle_controller_specific_errors( - struct isci_remote_device *isci_device, + struct isci_remote_device *idev, struct isci_request *request, struct sas_task *task, enum service_response *response_ptr, @@ -2353,8 +2353,7 @@ static void isci_request_handle_controller_specific_errors( * that we ignore the quiesce state, since we are * concerned about the actual device state. */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) + if (!idev) *status_ptr = SAS_DEVICE_UNKNOWN; else *status_ptr = SAS_ABORTED_TASK; @@ -2367,8 +2366,7 @@ static void isci_request_handle_controller_specific_errors( /* Task in the target is not done. */ *response_ptr = SAS_TASK_UNDELIVERED; - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) + if (!idev) *status_ptr = SAS_DEVICE_UNKNOWN; else *status_ptr = SAM_STAT_TASK_ABORTED; @@ -2399,8 +2397,7 @@ static void isci_request_handle_controller_specific_errors( * that we ignore the quiesce state, since we are * concerned about the actual device state. */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) + if (!idev) *status_ptr = SAS_DEVICE_UNKNOWN; else *status_ptr = SAS_ABORTED_TASK; @@ -2629,7 +2626,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, struct ssp_response_iu *resp_iu; void *resp_buf; unsigned long task_flags; - struct isci_remote_device *isci_device = request->isci_device; + struct isci_remote_device *idev = isci_lookup_device(task->dev); enum service_response response = SAS_TASK_UNDELIVERED; enum exec_status status = SAS_ABORTED_TASK; enum isci_request_status request_status; @@ -2672,9 +2669,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * that we ignore the quiesce state, since we are * concerned about the actual device state. */ - if ((isci_device->status == isci_stopping) - || (isci_device->status == isci_stopped) - ) + if (!idev) status = SAS_DEVICE_UNKNOWN; else status = SAS_ABORTED_TASK; @@ -2697,8 +2692,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, request->complete_in_target = true; response = SAS_TASK_UNDELIVERED; - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) + if (!idev) /* The device has been /is being stopped. Note that * we ignore the quiesce state, since we are * concerned about the actual device state. @@ -2728,8 +2722,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * that we ignore the quiesce state, since we are * concerned about the actual device state. */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) + if (!idev) status = SAS_DEVICE_UNKNOWN; else status = SAS_ABORTED_TASK; @@ -2861,8 +2854,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * that we ignore the quiesce state, since we are * concerned about the actual device state. */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) + if (!idev) status = SAS_DEVICE_UNKNOWN; else status = SAS_ABORTED_TASK; @@ -2873,7 +2865,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, case SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR: isci_request_handle_controller_specific_errors( - isci_device, request, task, &response, &status, + idev, request, task, &response, &status, &complete_to_host); break; @@ -2902,8 +2894,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, /* Fail the I/O so it can be retried. */ response = SAS_TASK_UNDELIVERED; - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) + if (!idev) status = SAS_DEVICE_UNKNOWN; else status = SAS_ABORTED_TASK; @@ -2926,8 +2917,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * that we ignore the quiesce state, since we are * concerned about the actual device state. */ - if ((isci_device->status == isci_stopping) || - (isci_device->status == isci_stopped)) + if (!idev) status = SAS_DEVICE_UNKNOWN; else status = SAS_ABORTED_TASK; @@ -2953,8 +2943,10 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, /* complete the io request to the core. */ scic_controller_complete_io(&isci_host->sci, - &isci_device->sci, + request->sci.target_device, &request->sci); + isci_put_device(idev); + /* set terminated handle so it cannot be completed or * terminated again, and to cause any calls into abort * task to recognize the already completed case. @@ -3511,7 +3503,6 @@ static enum sci_status isci_io_request_build( } static struct isci_request *isci_request_alloc_core(struct isci_host *ihost, - struct isci_remote_device *idev, gfp_t gfp_flags) { dma_addr_t handle; @@ -3528,7 +3519,6 @@ static struct isci_request *isci_request_alloc_core(struct isci_host *ihost, spin_lock_init(&ireq->state_lock); ireq->request_daddr = handle; ireq->isci_host = ihost; - ireq->isci_device = idev; ireq->io_request_completion = NULL; ireq->terminated = false; @@ -3546,12 +3536,11 @@ static struct isci_request *isci_request_alloc_core(struct isci_host *ihost, static struct isci_request *isci_request_alloc_io(struct isci_host *ihost, struct sas_task *task, - struct isci_remote_device *idev, gfp_t gfp_flags) { struct isci_request *ireq; - ireq = isci_request_alloc_core(ihost, idev, gfp_flags); + ireq = isci_request_alloc_core(ihost, gfp_flags); if (ireq) { ireq->ttype_ptr.io_task_ptr = task; ireq->ttype = io_task; @@ -3562,12 +3551,11 @@ static struct isci_request *isci_request_alloc_io(struct isci_host *ihost, struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, struct isci_tmf *isci_tmf, - struct isci_remote_device *idev, gfp_t gfp_flags) { struct isci_request *ireq; - ireq = isci_request_alloc_core(ihost, idev, gfp_flags); + ireq = isci_request_alloc_core(ihost, gfp_flags); if (ireq) { ireq->ttype_ptr.tmf_task_ptr = isci_tmf; ireq->ttype = tmf_task; @@ -3575,21 +3563,16 @@ struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, return ireq; } -int isci_request_execute(struct isci_host *ihost, struct sas_task *task, - gfp_t gfp_flags) +int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, + struct sas_task *task, gfp_t gfp_flags) { enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; - struct scic_sds_remote_device *sci_dev; - struct isci_remote_device *idev; struct isci_request *ireq; unsigned long flags; int ret = 0; - idev = task->dev->lldd_dev; - sci_dev = &idev->sci; - /* do common allocation and init of request object. */ - ireq = isci_request_alloc_io(ihost, task, idev, gfp_flags); + ireq = isci_request_alloc_io(ihost, task, gfp_flags); if (!ireq) goto out; @@ -3605,8 +3588,7 @@ int isci_request_execute(struct isci_host *ihost, struct sas_task *task, spin_lock_irqsave(&ihost->scic_lock, flags); /* send the request, let the core assign the IO TAG. */ - status = scic_controller_start_io(&ihost->sci, sci_dev, - &ireq->sci, + status = scic_controller_start_io(&ihost->sci, &idev->sci, &ireq->sci, SCI_CONTROLLER_INVALID_IO_TAG); if (status != SCI_SUCCESS && status != SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 8de2542f081f..9bb7c36257f3 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -285,7 +285,6 @@ struct isci_request { struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */ } ttype_ptr; struct isci_host *isci_host; - struct isci_remote_device *isci_device; /* For use in the requests_to_{complete|abort} lists: */ struct list_head completed_node; /* For use in the reqs_in_process list: */ @@ -681,12 +680,10 @@ static inline void isci_request_free(struct isci_host *isci_host, struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, struct isci_tmf *isci_tmf, - struct isci_remote_device *idev, gfp_t gfp_flags); -int isci_request_execute(struct isci_host *isci_host, - struct sas_task *task, - gfp_t gfp_flags); +int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, + struct sas_task *task, gfp_t gfp_flags); /** * isci_request_unmap_sgl() - This function unmaps the DMA address of a given diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index b9b9271d4736..e7ce46924465 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -213,11 +213,10 @@ int isci_task_send_lu_reset_sata( /* Send the soft reset to the target */ #define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */ - isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_high, - NULL, NULL - ); + isci_task_build_tmf(&tmf, isci_tmf_sata_srst_high, NULL, NULL); - ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS); + ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, + ISCI_SRST_TIMEOUT_MS); if (ret != TMF_RESP_FUNC_COMPLETE) { dev_warn(&isci_host->pdev->dev, diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index ded81cd1a781..dd5e9de1ffb5 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -146,7 +146,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) { struct isci_host *ihost = dev_to_ihost(task->dev); - struct isci_remote_device *device; + struct isci_remote_device *idev; unsigned long flags; int ret; enum sci_status status; @@ -166,11 +166,12 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) dev_dbg(&ihost->pdev->dev, "task = %p, num = %d; dev = %p; cmd = %p\n", task, num, task->dev, task->uldd_task); + spin_lock_irqsave(&ihost->scic_lock, flags); + idev = isci_lookup_device(task->dev); + spin_unlock_irqrestore(&ihost->scic_lock, flags); - device = task->dev->lldd_dev; - - if (device) - device_status = device->status; + if (idev) + device_status = idev->status; else device_status = isci_freed; @@ -188,7 +189,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) __func__, task, isci_host_get_state(ihost), - device, + idev, device_status); if (device_status == isci_ready) { @@ -225,7 +226,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) spin_unlock_irqrestore(&task->task_state_lock, flags); /* build and send the request. */ - status = isci_request_execute(ihost, task, gfp_flags); + status = isci_request_execute(ihost, idev, task, gfp_flags); if (status != SCI_SUCCESS) { @@ -248,33 +249,31 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) } } } + isci_put_device(idev); } return 0; } static struct isci_request *isci_task_request_build(struct isci_host *ihost, + struct isci_remote_device *idev, struct isci_tmf *isci_tmf) { - struct scic_sds_remote_device *sci_dev; enum sci_status status = SCI_FAILURE; struct isci_request *ireq = NULL; - struct isci_remote_device *idev; struct domain_device *dev; dev_dbg(&ihost->pdev->dev, "%s: isci_tmf = %p\n", __func__, isci_tmf); - idev = isci_tmf->device; - sci_dev = &idev->sci; dev = idev->domain_dev; /* do common allocation and init of request object. */ - ireq = isci_request_alloc_tmf(ihost, isci_tmf, idev, GFP_ATOMIC); + ireq = isci_request_alloc_tmf(ihost, isci_tmf, GFP_ATOMIC); if (!ireq) return NULL; /* let the core do it's construct. */ - status = scic_task_request_construct(&ihost->sci, sci_dev, + status = scic_task_request_construct(&ihost->sci, &idev->sci, SCI_CONTROLLER_INVALID_IO_TAG, &ireq->sci); @@ -309,25 +308,13 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, return ireq; } -/** - * isci_task_execute_tmf() - This function builds and sends a task request, - * then waits for the completion. - * @isci_host: This parameter specifies the ISCI host object - * @tmf: This parameter is the pointer to the task management structure for - * this request. - * @timeout_ms: This parameter specifies the timeout period for the task - * management request. - * - * TMF_RESP_FUNC_COMPLETE on successful completion of the TMF (this includes - * error conditions reported in the IU status), or TMF_RESP_FUNC_FAILED. - */ -int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, - unsigned long timeout_ms) +int isci_task_execute_tmf(struct isci_host *ihost, + struct isci_remote_device *isci_device, + struct isci_tmf *tmf, unsigned long timeout_ms) { DECLARE_COMPLETION_ONSTACK(completion); enum sci_task_status status = SCI_TASK_FAILURE; struct scic_sds_remote_device *sci_device; - struct isci_remote_device *isci_device = tmf->device; struct isci_request *ireq; int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; @@ -352,7 +339,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, /* Assign the pointer to the TMF's completion kernel wait structure. */ tmf->complete = &completion; - ireq = isci_task_request_build(ihost, tmf); + ireq = isci_task_request_build(ihost, isci_device, tmf); if (!ireq) { dev_warn(&ihost->pdev->dev, "%s: isci_task_request_build failed\n", @@ -399,10 +386,9 @@ int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, if (tmf->cb_state_func != NULL) tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); - status = scic_controller_terminate_request( - &ireq->isci_host->sci, - &ireq->isci_device->sci, - &ireq->sci); + status = scic_controller_terminate_request(&ihost->sci, + &isci_device->sci, + &ireq->sci); spin_unlock_irqrestore(&ihost->scic_lock, flags); } @@ -437,65 +423,32 @@ int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, void isci_task_build_tmf( struct isci_tmf *tmf, - struct isci_remote_device *isci_device, enum isci_tmf_function_codes code, void (*tmf_sent_cb)(enum isci_tmf_cb_state, struct isci_tmf *, void *), void *cb_data) { - dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, - "%s: isci_device = %p\n", __func__, isci_device); - memset(tmf, 0, sizeof(*tmf)); - tmf->device = isci_device; tmf->tmf_code = code; - tmf->cb_state_func = tmf_sent_cb; tmf->cb_data = cb_data; } static void isci_task_build_abort_task_tmf( struct isci_tmf *tmf, - struct isci_remote_device *isci_device, enum isci_tmf_function_codes code, void (*tmf_sent_cb)(enum isci_tmf_cb_state, struct isci_tmf *, void *), struct isci_request *old_request) { - isci_task_build_tmf(tmf, isci_device, code, tmf_sent_cb, + isci_task_build_tmf(tmf, code, tmf_sent_cb, (void *)old_request); tmf->io_tag = old_request->io_tag; } -static struct isci_request *isci_task_get_request_from_task( - struct sas_task *task, - struct isci_remote_device **isci_device) -{ - - struct isci_request *request = NULL; - unsigned long flags; - - spin_lock_irqsave(&task->task_state_lock, flags); - - request = task->lldd_task; - - /* If task is already done, the request isn't valid */ - if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && - (task->task_state_flags & SAS_TASK_AT_INITIATOR) && - (request != NULL)) { - - if (isci_device != NULL) - *isci_device = request->isci_device; - } - - spin_unlock_irqrestore(&task->task_state_lock, flags); - - return request; -} - /** * isci_task_validate_request_to_abort() - This function checks the given I/O * against the "started" state. If the request is still "started", it's @@ -858,11 +811,10 @@ static int isci_task_send_lu_reset_sas( * value is "TMF_RESP_FUNC_COMPLETE", or the request timed-out (or * was otherwise unable to be executed ("TMF_RESP_FUNC_FAILED"). */ - isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_lun_reset, NULL, - NULL); + isci_task_build_tmf(&tmf, isci_tmf_ssp_lun_reset, NULL, NULL); #define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */ - ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_LU_RESET_TIMEOUT_MS); + ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, ISCI_LU_RESET_TIMEOUT_MS); if (ret == TMF_RESP_FUNC_COMPLETE) dev_dbg(&isci_host->pdev->dev, @@ -888,33 +840,33 @@ static int isci_task_send_lu_reset_sas( int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) { struct isci_host *isci_host = dev_to_ihost(domain_device); - struct isci_remote_device *isci_device = NULL; + struct isci_remote_device *isci_device; + unsigned long flags; int ret; - bool device_stopping = false; - isci_device = domain_device->lldd_dev; + spin_lock_irqsave(&isci_host->scic_lock, flags); + isci_device = isci_lookup_device(domain_device); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); dev_dbg(&isci_host->pdev->dev, "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", __func__, domain_device, isci_host, isci_device); - if (isci_device != NULL) { - device_stopping = (isci_device->status == isci_stopping) - || (isci_device->status == isci_stopped); + if (isci_device) set_bit(IDEV_EH, &isci_device->flags); - } /* If there is a device reset pending on any request in the * device's list, fail this LUN reset request in order to * escalate to the device reset. */ - if (!isci_device || device_stopping || + if (!isci_device || isci_device_is_reset_pending(isci_host, isci_device)) { dev_warn(&isci_host->pdev->dev, "%s: No dev (%p), or " "RESET PENDING: domain_device=%p\n", __func__, isci_device, domain_device); - return TMF_RESP_FUNC_FAILED; + ret = TMF_RESP_FUNC_FAILED; + goto out; } /* Send the task management part of the reset. */ @@ -929,6 +881,8 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) isci_terminate_pending_requests(isci_host, isci_device); + out: + isci_put_device(isci_device); return ret; } @@ -1023,60 +977,54 @@ int isci_task_abort_task(struct sas_task *task) int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; bool any_dev_reset = false; - bool device_stopping; /* Get the isci_request reference from the task. Note that * this check does not depend on the pending request list * in the device, because tasks driving resets may land here * after completion in the core. */ - old_request = isci_task_get_request_from_task(task, &isci_device); + spin_lock_irqsave(&isci_host->scic_lock, flags); + spin_lock(&task->task_state_lock); + + old_request = task->lldd_task; + + /* If task is already done, the request isn't valid */ + if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && + (task->task_state_flags & SAS_TASK_AT_INITIATOR) && + old_request) + isci_device = isci_lookup_device(task->dev); + + spin_unlock(&task->task_state_lock); + spin_unlock_irqrestore(&isci_host->scic_lock, flags); dev_dbg(&isci_host->pdev->dev, "%s: task = %p\n", __func__, task); - /* Check if the device has been / is currently being removed. - * If so, no task management will be done, and the I/O will - * be terminated. - */ - device_stopping = (isci_device->status == isci_stopping) - || (isci_device->status == isci_stopped); + if (!isci_device || !old_request) + goto out; - /* XXX need to fix device lookup lifetime (needs to be done - * under scic_lock, among other things...), but for now assume - * the device is available like the above code - */ set_bit(IDEV_EH, &isci_device->flags); /* This version of the driver will fail abort requests for * SATA/STP. Failing the abort request this way will cause the * SCSI error handler thread to escalate to LUN reset */ - if (sas_protocol_ata(task->task_proto) && !device_stopping) { + if (sas_protocol_ata(task->task_proto)) { dev_warn(&isci_host->pdev->dev, " task %p is for a STP/SATA device;" " returning TMF_RESP_FUNC_FAILED\n" " to cause a LUN reset...\n", task); - return TMF_RESP_FUNC_FAILED; + goto out; } dev_dbg(&isci_host->pdev->dev, "%s: old_request == %p\n", __func__, old_request); - if (!device_stopping) - any_dev_reset = isci_device_is_reset_pending(isci_host,isci_device); + any_dev_reset = isci_device_is_reset_pending(isci_host,isci_device); spin_lock_irqsave(&task->task_state_lock, flags); - /* Don't do resets to stopping devices. */ - if (device_stopping) { - - task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; - any_dev_reset = false; - - } else /* See if there is a pending device reset for this device. */ - any_dev_reset = any_dev_reset - || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET); + any_dev_reset = any_dev_reset || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET); /* If the extraction of the request reference from the task * failed, then the request has been completed (or if there is a @@ -1130,8 +1078,7 @@ int isci_task_abort_task(struct sas_task *task) "%s: abort task not needed for %p\n", __func__, task); } - - return ret; + goto out; } else spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -1158,11 +1105,10 @@ int isci_task_abort_task(struct sas_task *task) "%s: device = %p; old_request %p already being aborted\n", __func__, isci_device, old_request); - - return TMF_RESP_FUNC_COMPLETE; + ret = TMF_RESP_FUNC_COMPLETE; + goto out; } if ((task->task_proto == SAS_PROTOCOL_SMP) - || device_stopping || old_request->complete_in_target ) { @@ -1170,10 +1116,9 @@ int isci_task_abort_task(struct sas_task *task) dev_dbg(&isci_host->pdev->dev, "%s: SMP request (%d)" - " or device is stopping (%d)" " or complete_in_target (%d), thus no TMF\n", __func__, (task->task_proto == SAS_PROTOCOL_SMP), - device_stopping, old_request->complete_in_target); + old_request->complete_in_target); /* Set the state on the task. */ isci_task_all_done(task); @@ -1185,15 +1130,14 @@ int isci_task_abort_task(struct sas_task *task) */ } else { /* Fill in the tmf stucture */ - isci_task_build_abort_task_tmf(&tmf, isci_device, - isci_tmf_ssp_task_abort, + isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort, isci_abort_task_process_cb, old_request); spin_unlock_irqrestore(&isci_host->scic_lock, flags); #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */ - ret = isci_task_execute_tmf(isci_host, &tmf, + ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, ISCI_ABORT_TASK_TIMEOUT_MS); if (ret != TMF_RESP_FUNC_COMPLETE) @@ -1212,6 +1156,8 @@ int isci_task_abort_task(struct sas_task *task) /* Make sure we do not leave a reference to aborted_io_completion */ old_request->io_request_completion = NULL; + out: + isci_put_device(isci_device); return ret; } @@ -1305,7 +1251,6 @@ isci_task_request_complete(struct isci_host *ihost, struct isci_request *ireq, enum sci_task_status completion_status) { - struct isci_remote_device *idev = ireq->isci_device; struct isci_tmf *tmf = isci_request_access_tmf(ireq); struct completion *tmf_complete; struct scic_sds_request *sci_req = &ireq->sci; @@ -1332,7 +1277,7 @@ isci_task_request_complete(struct isci_host *ihost, /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; - scic_controller_complete_io(&ihost->sci, &idev->sci, &ireq->sci); + scic_controller_complete_io(&ihost->sci, ireq->sci.target_device, &ireq->sci); /* set the 'terminated' flag handle to make sure it cannot be terminated * or completed again. */ @@ -1583,11 +1528,10 @@ static void isci_wait_for_smp_phy_reset(struct isci_remote_device *idev, int phy dev_dbg(&ihost->pdev->dev, "%s: done\n", __func__); } -static int isci_reset_device(struct domain_device *dev, int hard_reset) +static int isci_reset_device(struct isci_host *ihost, + struct isci_remote_device *idev, int hard_reset) { - struct isci_remote_device *idev = dev->lldd_dev; - struct sas_phy *phy = sas_find_local_phy(dev); - struct isci_host *ihost = dev_to_ihost(dev); + struct sas_phy *phy = sas_find_local_phy(idev->domain_dev); struct isci_port *iport = idev->isci_port; enum sci_status status; unsigned long flags; @@ -1595,14 +1539,6 @@ static int isci_reset_device(struct domain_device *dev, int hard_reset) dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); - if (!idev) { - dev_warn(&ihost->pdev->dev, - "%s: idev is GONE!\n", - __func__); - - return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */ - } - spin_lock_irqsave(&ihost->scic_lock, flags); status = scic_remote_device_reset(&idev->sci); if (status != SCI_SUCCESS) { @@ -1662,35 +1598,50 @@ static int isci_reset_device(struct domain_device *dev, int hard_reset) int isci_task_I_T_nexus_reset(struct domain_device *dev) { struct isci_host *ihost = dev_to_ihost(dev); - int ret = TMF_RESP_FUNC_FAILED, hard_reset = 1; struct isci_remote_device *idev; + int ret, hard_reset = 1; unsigned long flags; - /* XXX mvsas is not protecting against ->lldd_dev_gone(), are we - * being too paranoid, or is mvsas busted?! - */ spin_lock_irqsave(&ihost->scic_lock, flags); - idev = dev->lldd_dev; - if (!idev || !test_bit(IDEV_EH, &idev->flags)) - ret = TMF_RESP_FUNC_COMPLETE; + idev = isci_lookup_device(dev); spin_unlock_irqrestore(&ihost->scic_lock, flags); - if (ret == TMF_RESP_FUNC_COMPLETE) - return ret; + if (!idev || !test_bit(IDEV_EH, &idev->flags)) { + ret = TMF_RESP_FUNC_COMPLETE; + goto out; + } if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) hard_reset = 0; - return isci_reset_device(dev, hard_reset); + ret = isci_reset_device(ihost, idev, hard_reset); + out: + isci_put_device(idev); + return ret; } int isci_bus_reset_handler(struct scsi_cmnd *cmd) { struct domain_device *dev = sdev_to_domain_dev(cmd->device); - int hard_reset = 1; + struct isci_host *ihost = dev_to_ihost(dev); + struct isci_remote_device *idev; + int ret, hard_reset = 1; + unsigned long flags; if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) hard_reset = 0; - return isci_reset_device(dev, hard_reset); + spin_lock_irqsave(&ihost->scic_lock, flags); + idev = isci_lookup_device(dev); + spin_unlock_irqrestore(&ihost->scic_lock, flags); + + if (!idev) { + ret = TMF_RESP_FUNC_COMPLETE; + goto out; + } + + ret = isci_reset_device(ihost, idev, hard_reset); + out: + isci_put_device(idev); + return ret; } diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index d574a18956d7..42019de23805 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -213,18 +213,15 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd); void isci_task_build_tmf( struct isci_tmf *tmf, - struct isci_remote_device *isci_device, enum isci_tmf_function_codes code, void (*tmf_sent_cb)(enum isci_tmf_cb_state, struct isci_tmf *, void *), void *cb_data); - -int isci_task_execute_tmf( - struct isci_host *isci_host, - struct isci_tmf *tmf, - unsigned long timeout_ms); +int isci_task_execute_tmf(struct isci_host *isci_host, + struct isci_remote_device *idev, + struct isci_tmf *tmf, unsigned long timeout_ms); /** * enum isci_completion_selection - This enum defines the possible actions to -- cgit v1.2.3 From f2088267514b39af1a94409168101527769a911c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 16 Jun 2011 11:26:12 -0700 Subject: isci: kill isci_remote_device_change_state() Now that "stopping/stopped" are one in the same and signalled by a NULL device pointer the rest of the device status infrastructure can be removed (->status and ->state_lock). The "not ready for i/o state" is replaced with a state flag, and is evaluated under scic_lock so that we don't see transients from taking the device reference to submitting the i/o. This also fixes a potential leakage of can_queue slots in the rare case that SAS_TASK_ABORTED is set at submission. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 1 - drivers/scsi/isci/remote_device.c | 50 +++------------------------- drivers/scsi/isci/remote_device.h | 5 +-- drivers/scsi/isci/task.c | 68 +++++++++++++-------------------------- 4 files changed, 27 insertions(+), 97 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 40f35fad244b..b08455f0d350 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -2504,7 +2504,6 @@ int isci_host_init(struct isci_host *isci_host) INIT_LIST_HEAD(&idev->reqs_in_process); INIT_LIST_HEAD(&idev->node); - spin_lock_init(&idev->state_lock); } return 0; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index ab5f9868e4ef..c2e5c05be0cb 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -61,24 +61,6 @@ #include "scu_event_codes.h" #include "task.h" -/** - * isci_remote_device_change_state() - This function gets the status of the - * remote_device object. - * @isci_device: This parameter points to the isci_remote_device object - * - * status of the object as a isci_status enum. - */ -void isci_remote_device_change_state( - struct isci_remote_device *isci_device, - enum isci_status status) -{ - unsigned long flags; - - spin_lock_irqsave(&isci_device->state_lock, flags); - isci_device->status = status; - spin_unlock_irqrestore(&isci_device->state_lock, flags); -} - /** * isci_remote_device_not_ready() - This function is called by the scic when * the remote device is not ready. We mark the isci device as ready (not @@ -96,8 +78,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) set_bit(IDEV_GONE, &idev->flags); else - /* device ready is actually a "not ready for io" state. */ - isci_remote_device_change_state(idev, isci_ready); + clear_bit(IDEV_IO_READY, &idev->flags); } /** @@ -113,7 +94,7 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote dev_dbg(&ihost->pdev->dev, "%s: idev = %p\n", __func__, idev); - isci_remote_device_change_state(idev, isci_ready_for_io); + set_bit(IDEV_IO_READY, &idev->flags); if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags)) wake_up(&ihost->eventq); } @@ -871,26 +852,6 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ isci_put_device(idev); } -/** - * isci_remote_device_stop_complete() - This function is called by the scic - * when the remote device stop has completed. We mark the isci device as not - * ready and remove the isci remote device. - * @ihost: This parameter specifies the isci host object. - * @idev: This parameter specifies the remote device. - * @status: This parameter specifies status of the completion. - * - */ -static void isci_remote_device_stop_complete(struct isci_host *ihost, - struct isci_remote_device *idev) -{ - dev_dbg(&ihost->pdev->dev, "%s: complete idev = %p\n", __func__, idev); - - isci_remote_device_change_state(idev, isci_stopped); - - /* after stop, we can tear down resources. */ - isci_remote_device_deconstruct(ihost, idev); -} - static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) { struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); @@ -903,7 +864,7 @@ static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_mac */ prev_state = sci_dev->sm.previous_state_id; if (prev_state == SCI_DEV_STOPPING) - isci_remote_device_stop_complete(scic_to_ihost(scic), idev); + isci_remote_device_deconstruct(scic_to_ihost(scic), idev); scic_sds_controller_remote_device_stopped(scic, sci_dev); } @@ -1301,8 +1262,6 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) if (WARN_ONCE(!list_empty(&idev->node), "found non-idle remote device\n")) return NULL; - isci_remote_device_change_state(idev, isci_freed); - return idev; } @@ -1315,6 +1274,7 @@ void isci_remote_device_release(struct kref *kref) idev->isci_port = NULL; clear_bit(IDEV_START_PENDING, &idev->flags); clear_bit(IDEV_STOP_PENDING, &idev->flags); + clear_bit(IDEV_IO_READY, &idev->flags); clear_bit(IDEV_GONE, &idev->flags); clear_bit(IDEV_EH, &idev->flags); smp_mb__before_clear_bit(); @@ -1341,7 +1301,6 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem spin_lock_irqsave(&ihost->scic_lock, flags); idev->domain_dev->lldd_dev = NULL; /* disable new lookups */ set_bit(IDEV_GONE, &idev->flags); - isci_remote_device_change_state(idev, isci_stopping); spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Kill all outstanding requests. */ @@ -1430,7 +1389,6 @@ int isci_remote_device_found(struct domain_device *domain_dev) spin_lock_irq(&isci_host->scic_lock); isci_device->domain_dev = domain_dev; isci_device->isci_port = isci_port; - isci_remote_device_change_state(isci_device, isci_starting); list_add_tail(&isci_device->node, &isci_port->remote_dev_list); set_bit(IDEV_START_PENDING, &isci_device->flags); diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 05842b5f1e3b..33f011447312 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -130,19 +130,18 @@ struct scic_sds_remote_device { }; struct isci_remote_device { - enum isci_status status; #define IDEV_START_PENDING 0 #define IDEV_STOP_PENDING 1 #define IDEV_ALLOCATED 2 #define IDEV_EH 3 #define IDEV_GONE 4 + #define IDEV_IO_READY 5 unsigned long flags; struct kref kref; struct isci_port *isci_port; struct domain_device *domain_dev; struct list_head node; struct list_head reqs_in_process; - spinlock_t state_lock; struct scic_sds_remote_device sci; }; @@ -178,8 +177,6 @@ bool isci_device_is_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev); void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev); -void isci_remote_device_change_state(struct isci_remote_device *idev, - enum isci_status status); /** * scic_remote_device_stop() - This method will stop both transmission and * reception of link activity for the supplied remote device. This method diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index dd5e9de1ffb5..c313bc16c218 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -147,10 +147,10 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) { struct isci_host *ihost = dev_to_ihost(task->dev); struct isci_remote_device *idev; + enum sci_status status; unsigned long flags; + bool io_ready; int ret; - enum sci_status status; - enum isci_status device_status; dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num); @@ -163,64 +163,40 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) } for_each_sas_task(num, task) { - dev_dbg(&ihost->pdev->dev, - "task = %p, num = %d; dev = %p; cmd = %p\n", - task, num, task->dev, task->uldd_task); spin_lock_irqsave(&ihost->scic_lock, flags); idev = isci_lookup_device(task->dev); + io_ready = idev ? test_bit(IDEV_IO_READY, &idev->flags) : 0; spin_unlock_irqrestore(&ihost->scic_lock, flags); - if (idev) - device_status = idev->status; - else - device_status = isci_freed; - - /* From this point onward, any process that needs to guarantee - * that there is no kernel I/O being started will have to wait - * for the quiesce spinlock. - */ - - if (device_status != isci_ready_for_io) { + dev_dbg(&ihost->pdev->dev, + "task: %p, num: %d dev: %p idev: %p:%#lx cmd = %p\n", + task, num, task->dev, idev, idev ? idev->flags : 0, + task->uldd_task); - /* Forces a retry from scsi mid layer. */ - dev_dbg(&ihost->pdev->dev, - "%s: task %p: isci_host->status = %d, " - "device = %p; device_status = 0x%x\n\n", - __func__, - task, - isci_host_get_state(ihost), - idev, - device_status); - - if (device_status == isci_ready) { - /* Indicate QUEUE_FULL so that the scsi midlayer - * retries. - */ - isci_task_refuse(ihost, task, - SAS_TASK_COMPLETE, - SAS_QUEUE_FULL); - } else { - /* Else, the device is going down. */ - isci_task_refuse(ihost, task, - SAS_TASK_UNDELIVERED, - SAS_DEVICE_UNKNOWN); - } + if (!idev) { + isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED, + SAS_DEVICE_UNKNOWN); + isci_host_can_dequeue(ihost, 1); + } else if (!io_ready) { + /* Indicate QUEUE_FULL so that the scsi midlayer + * retries. + */ + isci_task_refuse(ihost, task, SAS_TASK_COMPLETE, + SAS_QUEUE_FULL); isci_host_can_dequeue(ihost, 1); } else { /* There is a device and it's ready for I/O. */ spin_lock_irqsave(&task->task_state_lock, flags); if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { - + /* The I/O was aborted. */ spin_unlock_irqrestore(&task->task_state_lock, flags); isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED, SAM_STAT_TASK_ABORTED); - - /* The I/O was aborted. */ - + isci_host_can_dequeue(ihost, 1); } else { task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -323,11 +299,11 @@ int isci_task_execute_tmf(struct isci_host *ihost, /* sanity check, return TMF_RESP_FUNC_FAILED * if the device is not there and ready. */ - if (!isci_device || isci_device->status != isci_ready_for_io) { + if (!isci_device || !test_bit(IDEV_IO_READY, &isci_device->flags)) { dev_dbg(&ihost->pdev->dev, - "%s: isci_device = %p not ready (%d)\n", + "%s: isci_device = %p not ready (%#lx)\n", __func__, - isci_device, isci_device->status); + isci_device, isci_device ? isci_device->flags : 0); return TMF_RESP_FUNC_FAILED; } else dev_dbg(&ihost->pdev->dev, -- cgit v1.2.3 From ff60639dc9a461883db9192d2da0674a00339f12 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 17 Jun 2011 13:34:43 -0700 Subject: isci: kill device_sequence Now that we have upleveled device reassignment protection to the isci_remote_device reference count we no longer need this level of self-defense. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.h | 9 --------- drivers/scsi/isci/remote_device.c | 2 -- drivers/scsi/isci/remote_device.h | 11 ----------- drivers/scsi/isci/request.c | 5 ----- drivers/scsi/isci/request.h | 9 --------- 5 files changed, 36 deletions(-) diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 94fd54dc9f01..a54397e1bf16 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -187,15 +187,6 @@ struct scic_sds_controller { /* sequence number per tci */ u8 io_request_sequence[SCI_MAX_IO_REQUESTS]; - /** - * This field in the array of sequence values for the RNi. These are used - * to control io request build to io request start operations. The sequence - * value is recorded into an io request when it is built and is checked on - * the io request start operation to make sure that there was not a device - * hot plug between the build and start operation. - */ - u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES]; - /** * This field is a pointer to the memory allocated by the driver for the task * context table. This data is shared between the hardware and software. diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index c2e5c05be0cb..9f45c2ba7307 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -887,8 +887,6 @@ static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machi struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); struct domain_device *dev = idev->domain_dev; - scic->remote_device_sequence[sci_dev->rnc.remote_node_index]++; - if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { sci_change_state(&sci_dev->sm, SCI_STP_DEV_IDLE); } else if (dev_is_expander(dev)) { diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 33f011447312..cde595078f6d 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -410,17 +410,6 @@ static inline bool dev_is_expander(struct domain_device *dev) #define scic_sds_remote_device_get_port(sci_dev) \ ((sci_dev)->owning_port) -/** - * scic_sds_remote_device_get_sequence() - - * - * This macro returns the remote device sequence value - */ -#define scic_sds_remote_device_get_sequence(sci_dev) \ - (\ - scic_sds_remote_device_get_controller(sci_dev)-> \ - remote_device_sequence[(sci_dev)->rnc.remote_node_index] \ - ) - /** * scic_sds_remote_device_get_controller_peg() - * diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index fd6314abeb0b..ebe160c83f91 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -753,10 +753,6 @@ enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) struct scu_task_context *task_context; enum sci_base_request_states state; - if (sci_req->device_sequence != - scic_sds_remote_device_get_sequence(sci_req->target_device)) - return SCI_FAILURE; - state = sci_req->sm.current_state_id; if (state != SCI_REQ_CONSTRUCTED) { dev_warn(scic_to_dev(scic), @@ -3112,7 +3108,6 @@ scic_sds_general_request_construct(struct scic_sds_controller *scic, sci_req->target_device = sci_dev; sci_req->protocol = SCIC_NO_PROTOCOL; sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; - sci_req->device_sequence = scic_sds_remote_device_get_sequence(sci_dev); sci_req->sci_status = SCI_SUCCESS; sci_req->scu_status = 0; diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 9bb7c36257f3..a91d1d6060ce 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -231,14 +231,6 @@ struct scic_sds_request { */ u32 saved_rx_frame_index; - /* - * This field in the recorded device sequence for the io request. - * This is recorded during the build operation and is compared in the - * start operation. If the sequence is different then there was a - * change of devices from the build to start operations. - */ - u8 device_sequence; - union { struct { union { @@ -262,7 +254,6 @@ struct scic_sds_request { struct dev_to_host_fis rsp; } stp; }; - }; static inline struct scic_sds_request *to_sci_req(struct scic_sds_stp_request *stp_req) -- cgit v1.2.3 From 5edc33480c1c363ab361a881f2957b9fba5185cf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 16 Jun 2011 17:20:35 -0700 Subject: isci: fix smp response frame overrun Due to a typo we currently copy way too much when copying over the response data, but since a request is likely backed by a full page allocation we don't corrupt live data. Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index ebe160c83f91..f4fbca7b1fa3 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1694,7 +1694,7 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, frame_index, &smp_resp); - word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) / + word_cnt = (sizeof(struct smp_resp) - SMP_RESP_HDR_SZ) / sizeof(u32); sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, -- cgit v1.2.3 From ddcc7e347a891937be65358b43f40b7f81185f8f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 17 Jun 2011 10:40:43 -0700 Subject: isci: fix dma_unmap_sg usage One bug and a cleanup: 1/ Fix cases where we were unmapping invalid addresses (smp requests were being unmapped) [ 604.662770] ------------[ cut here ]------------ [ 604.668026] WARNING: at lib/dma-debug.c:800 check_unmap+0x418/0x740() [ 604.675315] Hardware name: SandyBridge Platform [ 604.680465] isci 0000:03:00.0: DMA-API: device driver tries to free an invalid DMA memory address 2/ The unmap routine is too large to be an inline function, and isci_request_io_request_get_next_sge is unused. Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 17 ++++++++- drivers/scsi/isci/request.h | 91 +-------------------------------------------- 2 files changed, 18 insertions(+), 90 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index f4fbca7b1fa3..395084955150 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2930,7 +2930,22 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, break; } - isci_request_unmap_sgl(request, isci_host->pdev); + switch (task->task_proto) { + case SAS_PROTOCOL_SSP: + if (task->data_dir == DMA_NONE) + break; + if (task->num_scatter == 0) + /* 0 indicates a single dma address */ + dma_unmap_single(&isci_host->pdev->dev, + request->zero_scatter_daddr, + task->total_xfer_len, task->data_dir); + else /* unmap the sgl dma addresses */ + dma_unmap_sg(&isci_host->pdev->dev, task->scatter, + request->num_sg_entries, task->data_dir); + break; + default: + break; + } /* Put the completed request on the correct list */ isci_task_save_for_upper_layer_completion(isci_host, request, response, diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index a91d1d6060ce..324fb7b3ab42 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -672,97 +672,10 @@ static inline void isci_request_free(struct isci_host *isci_host, struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, struct isci_tmf *isci_tmf, gfp_t gfp_flags); - int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, struct sas_task *task, gfp_t gfp_flags); - -/** - * isci_request_unmap_sgl() - This function unmaps the DMA address of a given - * sgl - * @request: This parameter points to the isci_request object - * @*pdev: This Parameter is the pci_device struct for the controller - * - */ -static inline void -isci_request_unmap_sgl(struct isci_request *request, struct pci_dev *pdev) -{ - struct sas_task *task = isci_request_access_task(request); - - dev_dbg(&request->isci_host->pdev->dev, - "%s: request = %p, task = %p,\n" - "task->data_dir = %d, is_sata = %d\n ", - __func__, - request, - task, - task->data_dir, - sas_protocol_ata(task->task_proto)); - - if ((task->data_dir != PCI_DMA_NONE) && - !sas_protocol_ata(task->task_proto)) { - if (task->num_scatter == 0) - /* 0 indicates a single dma address */ - dma_unmap_single( - &pdev->dev, - request->zero_scatter_daddr, - task->total_xfer_len, - task->data_dir - ); - - else /* unmap the sgl dma addresses */ - dma_unmap_sg( - &pdev->dev, - task->scatter, - request->num_sg_entries, - task->data_dir - ); - } -} - -/** - * isci_request_io_request_get_next_sge() - This function is called by the sci - * core to retrieve the next sge for a given request. - * @request: This parameter is the isci_request object. - * @current_sge_address: This parameter is the last sge retrieved by the sci - * core for this request. - * - * pointer to the next sge for specified request. - */ -static inline void * -isci_request_io_request_get_next_sge(struct isci_request *request, - void *current_sge_address) -{ - struct sas_task *task = isci_request_access_task(request); - void *ret = NULL; - - dev_dbg(&request->isci_host->pdev->dev, - "%s: request = %p, " - "current_sge_address = %p, " - "num_scatter = %d\n", - __func__, - request, - current_sge_address, - task->num_scatter); - - if (!current_sge_address) /* First time through.. */ - ret = task->scatter; /* always task->scatter */ - else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */ - ret = NULL; /* there is only one element. */ - else - ret = sg_next(current_sge_address); /* sg_next returns NULL - * for the last element - */ - - dev_dbg(&request->isci_host->pdev->dev, - "%s: next sge address = %p\n", - __func__, - ret); - - return ret; -} - -void -isci_terminate_pending_requests(struct isci_host *ihost, - struct isci_remote_device *idev); +void isci_terminate_pending_requests(struct isci_host *ihost, + struct isci_remote_device *idev); enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, -- cgit v1.2.3 From e9bf709564e90abea25ca7aeae8c3de5cc6468d7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 16 Jun 2011 16:59:56 -0700 Subject: isci: fix support for arbitrarily large smp requests Instead of duplicating the smp request buffer reuse the one provided by libsas. This future proofs the driver to support arbitrarily large smp requests, and shrinks the request structure size by ~700 bytes. Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 138 ++++++++++++++++++++------------------------ drivers/scsi/isci/request.h | 1 - drivers/scsi/isci/sas.h | 11 +--- 3 files changed, 65 insertions(+), 85 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 395084955150..1043fed2a40a 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2943,6 +2943,20 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, dma_unmap_sg(&isci_host->pdev->dev, task->scatter, request->num_sg_entries, task->data_dir); break; + case SAS_PROTOCOL_SMP: { + struct scatterlist *sg = &task->smp_task.smp_req; + struct smp_req *smp_req; + void *kaddr; + + dma_unmap_sg(&isci_host->pdev->dev, sg, 1, DMA_TO_DEVICE); + + /* need to swab it back in case the command buffer is re-used */ + kaddr = kmap_atomic(sg_page(sg), KM_IRQ0); + smp_req = kaddr + sg->offset; + sci_swab32_cpy(smp_req, smp_req, sg->length / sizeof(u32)); + kunmap_atomic(kaddr, KM_IRQ0); + break; + } default: break; } @@ -3160,7 +3174,7 @@ scic_io_request_construct(struct scic_sds_controller *scic, else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); else if (dev_is_expander(dev)) - memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); + /* pass */; else return SCI_FAILURE_UNSUPPORTED_PROTOCOL; @@ -3236,30 +3250,54 @@ static enum sci_status isci_request_stp_request_construct( return status; } -/* - * This function will fill in the SCU Task Context for a SMP request. The - * following important settings are utilized: -# task_type == - * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type - * (i.e. non-raw frame) is being utilized to perform task management. -# - * control_frame == 1. This ensures that the proper endianess is set so - * that the bytes are transmitted in the right order for a smp request frame. - * @sci_req: This parameter specifies the smp request object being - * constructed. - * - */ -static void -scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, - ssize_t req_len) +static enum sci_status +scic_io_request_construct_smp(struct device *dev, + struct scic_sds_request *sci_req, + struct sas_task *task) { - dma_addr_t dma_addr; + struct scatterlist *sg = &task->smp_task.smp_req; struct scic_sds_remote_device *sci_dev; - struct scic_sds_port *sci_port; struct scu_task_context *task_context; - ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); + struct scic_sds_port *sci_port; + struct smp_req *smp_req; + void *kaddr; + u8 req_len; + u32 cmd; + + kaddr = kmap_atomic(sg_page(sg), KM_IRQ0); + smp_req = kaddr + sg->offset; + /* + * Look at the SMP requests' header fields; for certain SAS 1.x SMP + * functions under SAS 2.0, a zero request length really indicates + * a non-zero default length. + */ + if (smp_req->req_len == 0) { + switch (smp_req->func) { + case SMP_DISCOVER: + case SMP_REPORT_PHY_ERR_LOG: + case SMP_REPORT_PHY_SATA: + case SMP_REPORT_ROUTE_INFO: + smp_req->req_len = 2; + break; + case SMP_CONF_ROUTE_INFO: + case SMP_PHY_CONTROL: + case SMP_PHY_TEST_FUNCTION: + smp_req->req_len = 9; + break; + /* Default - zero is a valid default for 2.0. */ + } + } + req_len = smp_req->req_len; + sci_swab32_cpy(smp_req, smp_req, sg->length / sizeof(u32)); + cmd = *(u32 *) smp_req; + kunmap_atomic(kaddr, KM_IRQ0); + + if (!dma_map_sg(dev, sg, 1, DMA_TO_DEVICE)) + return SCI_FAILURE; + + sci_req->protocol = SCIC_SMP_PROTOCOL; /* byte swap the smp request. */ - sci_swab32_cpy(&sci_req->smp.cmd, &sci_req->smp.cmd, - word_cnt); task_context = scic_sds_request_get_task_context(sci_req); @@ -3307,7 +3345,7 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, * 18h ~ 30h, protocol specific * since commandIU has been build by framework at this point, we just * copy the frist DWord from command IU to this location. */ - memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); + memcpy(&task_context->type.smp, &cmd, sizeof(u32)); /* * 40h @@ -3347,48 +3385,12 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, * Copy the physical address for the command buffer to the SCU Task * Context command buffer should not contain command header. */ - dma_addr = scic_io_request_get_dma_addr(sci_req, - ((char *) &sci_req->smp.cmd) + - sizeof(u32)); - - task_context->command_iu_upper = upper_32_bits(dma_addr); - task_context->command_iu_lower = lower_32_bits(dma_addr); + task_context->command_iu_upper = upper_32_bits(sg_dma_address(sg)); + task_context->command_iu_lower = lower_32_bits(sg_dma_address(sg) + sizeof(u32)); /* SMP response comes as UF, so no need to set response IU address. */ task_context->response_iu_upper = 0; task_context->response_iu_lower = 0; -} - -static enum sci_status -scic_io_request_construct_smp(struct scic_sds_request *sci_req) -{ - struct smp_req *smp_req = &sci_req->smp.cmd; - - sci_req->protocol = SCIC_SMP_PROTOCOL; - - /* - * Look at the SMP requests' header fields; for certain SAS 1.x SMP - * functions under SAS 2.0, a zero request length really indicates - * a non-zero default length. - */ - if (smp_req->req_len == 0) { - switch (smp_req->func) { - case SMP_DISCOVER: - case SMP_REPORT_PHY_ERR_LOG: - case SMP_REPORT_PHY_SATA: - case SMP_REPORT_ROUTE_INFO: - smp_req->req_len = 2; - break; - case SMP_CONF_ROUTE_INFO: - case SMP_PHY_CONTROL: - case SMP_PHY_TEST_FUNCTION: - smp_req->req_len = 9; - break; - /* Default - zero is a valid default for 2.0. */ - } - } - - scu_smp_request_construct_task_context(sci_req, smp_req->req_len); sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); @@ -3404,24 +3406,12 @@ scic_io_request_construct_smp(struct scic_sds_request *sci_req) */ static enum sci_status isci_smp_request_build(struct isci_request *ireq) { - enum sci_status status = SCI_FAILURE; struct sas_task *task = isci_request_access_task(ireq); + struct device *dev = &ireq->isci_host->pdev->dev; struct scic_sds_request *sci_req = &ireq->sci; + enum sci_status status = SCI_FAILURE; - dev_dbg(&ireq->isci_host->pdev->dev, - "%s: request = %p\n", __func__, ireq); - - dev_dbg(&ireq->isci_host->pdev->dev, - "%s: smp_req len = %d\n", - __func__, - task->smp_task.smp_req.length); - - /* copy the smp_command to the address; */ - sg_copy_to_buffer(&task->smp_task.smp_req, 1, - &sci_req->smp.cmd, - sizeof(struct smp_req)); - - status = scic_io_request_construct_smp(sci_req); + status = scic_io_request_construct_smp(dev, sci_req, task); if (status != SCI_SUCCESS) dev_warn(&ireq->isci_host->pdev->dev, "%s: failed with status = %d\n", diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 324fb7b3ab42..7c8b59a7c02c 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -244,7 +244,6 @@ struct scic_sds_request { } ssp; struct { - struct smp_req cmd; struct smp_resp rsp; } smp; diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index 822a8dbd19ca..462b15174d3f 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h @@ -190,8 +190,6 @@ struct smp_req_phycntl { u8 _r_h[3]; /* bytes 37-39 */ } __packed; -#define SMP_REQ_VENDOR_SPECIFIC_MAX_LEN 1016 - /* * struct smp_req - This structure simply unionizes the existing request * structures into a common request type. @@ -203,14 +201,7 @@ struct smp_req { u8 func; /* byte 1 */ u8 alloc_resp_len; /* byte 2 */ u8 req_len; /* byte 3 */ - - union { /* bytes 4-N */ - u32 smp_req_gen; - struct smp_req_phy_id phy_id; - struct smp_req_phycntl phy_cntl; - struct smp_req_conf_rtinfo conf_rt_info; - u8 vendor[SMP_REQ_VENDOR_SPECIFIC_MAX_LEN]; - }; + u8 req_data[0]; } __packed; #define SMP_RESP_HDR_SZ 4 -- cgit v1.2.3 From 086a0dabc5bf154e13604a6d71e2d051207f9718 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 21 Jun 2011 16:23:03 -0700 Subject: isci: fix isci_task_execute_tmf completion 1/ fix the timeout for wait_for_completion_timeout 2/ In the tmf timeout case we need to wait for our termination callback 3/ Once the request is successfully started it will be freed according to the normal lifetime for requests. Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c313bc16c218..0835a2c2dc71 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -339,7 +339,8 @@ int isci_task_execute_tmf(struct isci_host *ihost, status, ireq); spin_unlock_irqrestore(&ihost->scic_lock, flags); - goto cleanup_request; + isci_request_free(ihost, ireq); + return ret; } if (tmf->cb_state_func != NULL) @@ -354,7 +355,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, /* Wait for the TMF to complete, or a timeout. */ timeleft = wait_for_completion_timeout(&completion, - jiffies + msecs_to_jiffies(timeout_ms)); + msecs_to_jiffies(timeout_ms)); if (timeleft == 0) { spin_lock_irqsave(&ihost->scic_lock, flags); @@ -362,11 +363,13 @@ int isci_task_execute_tmf(struct isci_host *ihost, if (tmf->cb_state_func != NULL) tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); - status = scic_controller_terminate_request(&ihost->sci, - &isci_device->sci, - &ireq->sci); + scic_controller_terminate_request(&ihost->sci, + &isci_device->sci, + &ireq->sci); spin_unlock_irqrestore(&ihost->scic_lock, flags); + + wait_for_completion(tmf->complete); } isci_print_tmf(tmf); @@ -387,13 +390,6 @@ int isci_task_execute_tmf(struct isci_host *ihost, __func__, ireq); - if (ireq->io_request_completion != NULL) { - /* A thread is waiting for this TMF to finish. */ - complete(ireq->io_request_completion); - } - - cleanup_request: - isci_request_free(ihost, ireq); return ret; } -- cgit v1.2.3 From 7cafbf1bd56be44038148bb8f733ea6e6a6a2d53 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Tue, 21 Jun 2011 22:03:13 +0000 Subject: isci: possible buffer overflow in isci_parse_oem_parameters fixed scu_index is a parameter of isci_parse_eom_parameters and is an index in controller table. There is a check: scu_index > SCI_MAX_CONTROLLERS which is insufficient and should be: scu_index >= SCI_MAX_CONTROLLERS. scu_index is used as an index in the table which size is SCI_MAX_CONTROLLERS. Signed-off-by: Maciej Patelczyk Signed-off-by: Dan Williams --- drivers/scsi/isci/probe_roms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index bc52a6174070..99b13c191877 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -125,7 +125,7 @@ enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, struct isci_orom *orom, int scu_index) { /* check for valid inputs */ - if (scu_index < 0 || scu_index > SCI_MAX_CONTROLLERS || + if (scu_index < 0 || scu_index >= SCI_MAX_CONTROLLERS || scu_index > orom->hdr.num_elements || !oem_params) return -EINVAL; -- cgit v1.2.3 From 4cffe13e0dfd00f90c86b0153c751dab61a1bf1d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 23 Jun 2011 23:44:52 -0700 Subject: isci: fix frame received locking Updates to the frame_rcvd before need to be atomic with respect to when they are evaluated by libsas. Signed-off-by: Dan Williams --- drivers/scsi/isci/phy.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 93a401dfbd30..c01d76210aa2 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -893,6 +893,7 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, enum scic_sds_phy_states state = sci_phy->sm.current_state_id; struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; enum sci_status result; + unsigned long flags; switch (state) { case SCI_PHY_SUB_AWAIT_IAF_UF: { @@ -911,7 +912,9 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, if (iaf.frame_type == 0) { u32 state; + spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags); memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf)); + spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags); if (iaf.smp_tport) { /* We got the IAF for an expander PHY go to the final * state since there are no power requirements for @@ -954,9 +957,11 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, frame_index, (void **)&fis_frame_data); + spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags); scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, frame_header, fis_frame_data); + spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags); /* got IAF we can now go to the await spinup semaphore state */ sci_change_state(&sci_phy->sm, SCI_PHY_SUB_FINAL); -- cgit v1.2.3 From 9274f45ea551421cd3bf329de9dd8d1e6208285a Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 23 Jun 2011 17:09:02 -0700 Subject: isci: Terminate dev requests on FIS err bit rx in NCQ When the remote device transitions to a not-ready state because of an NCQ error condition, all outstanding requests to that device are terminated and completed to libsas on the normal path. The device then waits for a READ LOG EXT command to issue on the task management path. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 27 +++++++++++++++++++++++++-- drivers/scsi/isci/remote_device.h | 1 + drivers/scsi/isci/request.c | 27 ++++++++++++++++++++++++--- drivers/scsi/isci/request.h | 9 +++++++++ drivers/scsi/isci/task.c | 16 ++++++++++++++-- 5 files changed, 73 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 9f45c2ba7307..c5ce0f0f3645 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -68,17 +68,39 @@ * @isci_host: This parameter specifies the isci host object. * @isci_device: This parameter specifies the remote device * + * scic_lock is held on entrance to this function. */ static void isci_remote_device_not_ready(struct isci_host *ihost, struct isci_remote_device *idev, u32 reason) { + struct isci_request * ireq; + dev_dbg(&ihost->pdev->dev, "%s: isci_device = %p\n", __func__, idev); - if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) + switch (reason) { + case SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED: set_bit(IDEV_GONE, &idev->flags); - else + break; + case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED: + set_bit(IDEV_IO_NCQERROR, &idev->flags); + + /* Kill all outstanding requests for the device. */ + list_for_each_entry(ireq, &idev->reqs_in_process, dev_node) { + + dev_dbg(&ihost->pdev->dev, + "%s: isci_device = %p request = %p\n", + __func__, idev, ireq); + + scic_controller_terminate_request(&ihost->sci, + &idev->sci, + &ireq->sci); + } + /* Fall through into the default case... */ + default: clear_bit(IDEV_IO_READY, &idev->flags); + break; + } } /** @@ -94,6 +116,7 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote dev_dbg(&ihost->pdev->dev, "%s: idev = %p\n", __func__, idev); + clear_bit(IDEV_IO_NCQERROR, &idev->flags); set_bit(IDEV_IO_READY, &idev->flags); if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags)) wake_up(&ihost->eventq); diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index cde595078f6d..0d9e37fe734f 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -136,6 +136,7 @@ struct isci_remote_device { #define IDEV_EH 3 #define IDEV_GONE 4 #define IDEV_IO_READY 5 + #define IDEV_IO_NCQERROR 6 unsigned long flags; struct kref kref; struct isci_port *isci_port; diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 1043fed2a40a..08a7340b33bf 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -3587,9 +3587,30 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide spin_lock_irqsave(&ihost->scic_lock, flags); - /* send the request, let the core assign the IO TAG. */ - status = scic_controller_start_io(&ihost->sci, &idev->sci, &ireq->sci, - SCI_CONTROLLER_INVALID_IO_TAG); + if (test_bit(IDEV_IO_NCQERROR, &idev->flags)) { + + if (isci_task_is_ncq_recovery(task)) { + + /* The device is in an NCQ recovery state. Issue the + * request on the task side. Note that it will + * complete on the I/O request side because the + * request was built that way (ie. + * ireq->is_task_management_request is false). + */ + status = scic_controller_start_task(&ihost->sci, + &idev->sci, + &ireq->sci, + SCI_CONTROLLER_INVALID_IO_TAG); + } else { + status = SCI_FAILURE; + } + } else { + + /* send the request, let the core assign the IO TAG. */ + status = scic_controller_start_io(&ihost->sci, &idev->sci, + &ireq->sci, + SCI_CONTROLLER_INVALID_IO_TAG); + } if (status != SCI_SUCCESS && status != SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { dev_warn(&ihost->pdev->dev, diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 7c8b59a7c02c..9130f22a63b8 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -687,4 +687,13 @@ scic_task_request_construct_sata(struct scic_sds_request *sci_req); void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); + +static inline int isci_task_is_ncq_recovery(struct sas_task *task) +{ + return (sas_protocol_ata(task->task_proto) && + task->ata_task.fis.command == ATA_CMD_READ_LOG_EXT && + task->ata_task.fis.lbal == ATA_LOG_SATA_NCQ); + +} + #endif /* !defined(_ISCI_REQUEST_H_) */ diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 0835a2c2dc71..157e9978183a 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -133,6 +133,15 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, for (; num > 0; num--,\ task = list_entry(task->list.next, struct sas_task, list)) + +static inline int isci_device_io_ready(struct isci_remote_device *idev, + struct sas_task *task) +{ + return idev ? test_bit(IDEV_IO_READY, &idev->flags) || + (test_bit(IDEV_IO_NCQERROR, &idev->flags) && + isci_task_is_ncq_recovery(task)) + : 0; +} /** * isci_task_execute_task() - This function is one of the SAS Domain Template * functions. This function is called by libsas to send a task down to @@ -165,7 +174,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) for_each_sas_task(num, task) { spin_lock_irqsave(&ihost->scic_lock, flags); idev = isci_lookup_device(task->dev); - io_ready = idev ? test_bit(IDEV_IO_READY, &idev->flags) : 0; + io_ready = isci_device_io_ready(idev, task); spin_unlock_irqrestore(&ihost->scic_lock, flags); dev_dbg(&ihost->pdev->dev, @@ -178,6 +187,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) SAS_DEVICE_UNKNOWN); isci_host_can_dequeue(ihost, 1); } else if (!io_ready) { + /* Indicate QUEUE_FULL so that the scsi midlayer * retries. */ @@ -299,7 +309,9 @@ int isci_task_execute_tmf(struct isci_host *ihost, /* sanity check, return TMF_RESP_FUNC_FAILED * if the device is not there and ready. */ - if (!isci_device || !test_bit(IDEV_IO_READY, &isci_device->flags)) { + if (!isci_device || + (!test_bit(IDEV_IO_READY, &isci_device->flags) && + !test_bit(IDEV_IO_NCQERROR, &isci_device->flags))) { dev_dbg(&ihost->pdev->dev, "%s: isci_device = %p not ready (%#lx)\n", __func__, -- cgit v1.2.3 From 312e0c2455c18716cf640d4336dcb1e9e5053818 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 28 Jun 2011 13:47:09 -0700 Subject: isci: unify can_queue tracking on the tci_pool, uplevel tag assignment The tci_pool tracks our outstanding command slots which are also the 'index' portion of our tags. Grabbing the tag early in ->lldd_execute_task let's us drop the isci_host_can_queue() and ->was_tag_assigned_by_user infrastructure. ->was_tag_assigned_by_user required the task context to be duplicated in request-local buffer. With the tci established early we can build the task_context directly into its final location and skip a memcpy. With the task context buffer at a known address at request construction we have the opportunity/obligation to also fix sgl handling. This rework feels like it belongs in another patch but the sgl handling and task_context are too intertwined. 1/ fix the 'ab' pair embedded in the task context to point to the 'cd' pair in the task context (previously we were prematurely linking to the staging buffer). 2/ fix the broken iteration of pio sgls that assumes all sgls are relative to the request, and does a dangerous looking reverse lookup of physical address to virtual address. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 265 ++++++------------------- drivers/scsi/isci/host.h | 55 +----- drivers/scsi/isci/port.c | 61 +++--- drivers/scsi/isci/port.h | 2 +- drivers/scsi/isci/request.c | 469 +++++++++++++++----------------------------- drivers/scsi/isci/request.h | 58 +----- drivers/scsi/isci/task.c | 80 ++++---- 7 files changed, 303 insertions(+), 687 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index b08455f0d350..c99fab53dd0c 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1018,33 +1018,11 @@ done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } -static void isci_tci_free(struct isci_host *ihost, u16 tci) -{ - u16 tail = ihost->tci_tail & (SCI_MAX_IO_REQUESTS-1); - - ihost->tci_pool[tail] = tci; - ihost->tci_tail = tail + 1; -} - -static u16 isci_tci_alloc(struct isci_host *ihost) -{ - u16 head = ihost->tci_head & (SCI_MAX_IO_REQUESTS-1); - u16 tci = ihost->tci_pool[head]; - - ihost->tci_head = head + 1; - return tci; -} - static u16 isci_tci_active(struct isci_host *ihost) { return CIRC_CNT(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); } -static u16 isci_tci_space(struct isci_host *ihost) -{ - return CIRC_SPACE(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); -} - static enum sci_status scic_controller_start(struct scic_sds_controller *scic, u32 timeout) { @@ -1205,6 +1183,11 @@ static void isci_host_completion_routine(unsigned long data) task->task_done(task); } } + + spin_lock_irq(&isci_host->scic_lock); + isci_free_tag(isci_host, request->sci.io_tag); + spin_unlock_irq(&isci_host->scic_lock); + /* Free the request object. */ isci_request_free(isci_host, request); } @@ -1242,6 +1225,7 @@ static void isci_host_completion_routine(unsigned long data) * of pending requests. */ list_del_init(&request->dev_node); + isci_free_tag(isci_host, request->sci.io_tag); spin_unlock_irq(&isci_host->scic_lock); /* Free the request object. */ @@ -2375,6 +2359,7 @@ static int scic_controller_mem_init(struct scic_sds_controller *scic) if (!scic->task_context_table) return -ENOMEM; + scic->task_context_dma = dma; writel(lower_32_bits(dma), &scic->smu_registers->host_task_table_lower); writel(upper_32_bits(dma), &scic->smu_registers->host_task_table_upper); @@ -2409,11 +2394,9 @@ int isci_host_init(struct isci_host *isci_host) spin_lock_init(&isci_host->state_lock); spin_lock_init(&isci_host->scic_lock); - spin_lock_init(&isci_host->queue_lock); init_waitqueue_head(&isci_host->eventq); isci_host_change_state(isci_host, isci_starting); - isci_host->can_queue = ISCI_CAN_QUEUE_VAL; status = scic_controller_construct(&isci_host->sci, scu_base(isci_host), smu_base(isci_host)); @@ -2611,51 +2594,6 @@ void scic_sds_controller_post_request( writel(request, &scic->smu_registers->post_context_port); } -/** - * This method will copy the soft copy of the task context into the physical - * memory accessible by the controller. - * @scic: This parameter specifies the controller for which to copy - * the task context. - * @sci_req: This parameter specifies the request for which the task - * context is being copied. - * - * After this call is made the SCIC_SDS_IO_REQUEST object will always point to - * the physical memory version of the task context. Thus, all subsequent - * updates to the task context are performed in the TC table (i.e. DMAable - * memory). none - */ -void scic_sds_controller_copy_task_context( - struct scic_sds_controller *scic, - struct scic_sds_request *sci_req) -{ - struct scu_task_context *task_context_buffer; - - task_context_buffer = scic_sds_controller_get_task_context_buffer( - scic, sci_req->io_tag); - - memcpy(task_context_buffer, - sci_req->task_context_buffer, - offsetof(struct scu_task_context, sgl_snapshot_ac)); - - /* - * Now that the soft copy of the TC has been copied into the TC - * table accessible by the silicon. Thus, any further changes to - * the TC (e.g. TC termination) occur in the appropriate location. */ - sci_req->task_context_buffer = task_context_buffer; -} - -struct scu_task_context *scic_sds_controller_get_task_context_buffer(struct scic_sds_controller *scic, - u16 io_tag) -{ - u16 tci = ISCI_TAG_TCI(io_tag); - - if (tci < scic->task_context_entries) { - return &scic->task_context_table[tci]; - } - - return NULL; -} - struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 io_tag) { u16 task_index; @@ -2801,6 +2739,60 @@ void scic_sds_controller_release_frame( &scic->scu_registers->sdma.unsolicited_frame_get_pointer); } +void isci_tci_free(struct isci_host *ihost, u16 tci) +{ + u16 tail = ihost->tci_tail & (SCI_MAX_IO_REQUESTS-1); + + ihost->tci_pool[tail] = tci; + ihost->tci_tail = tail + 1; +} + +static u16 isci_tci_alloc(struct isci_host *ihost) +{ + u16 head = ihost->tci_head & (SCI_MAX_IO_REQUESTS-1); + u16 tci = ihost->tci_pool[head]; + + ihost->tci_head = head + 1; + return tci; +} + +static u16 isci_tci_space(struct isci_host *ihost) +{ + return CIRC_SPACE(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); +} + +u16 isci_alloc_tag(struct isci_host *ihost) +{ + if (isci_tci_space(ihost)) { + u16 tci = isci_tci_alloc(ihost); + u8 seq = ihost->sci.io_request_sequence[tci]; + + return ISCI_TAG(seq, tci); + } + + return SCI_CONTROLLER_INVALID_IO_TAG; +} + +enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag) +{ + struct scic_sds_controller *scic = &ihost->sci; + u16 tci = ISCI_TAG_TCI(io_tag); + u16 seq = ISCI_TAG_SEQ(io_tag); + + /* prevent tail from passing head */ + if (isci_tci_active(ihost) == 0) + return SCI_FAILURE_INVALID_IO_TAG; + + if (seq == scic->io_request_sequence[tci]) { + scic->io_request_sequence[tci] = (seq+1) & (SCI_MAX_SEQ-1); + + isci_tci_free(ihost, tci); + + return SCI_SUCCESS; + } + return SCI_FAILURE_INVALID_IO_TAG; +} + /** * scic_controller_start_io() - This method is called by the SCI user to * send/start an IO request. If the method invocation is successful, then @@ -2811,27 +2803,11 @@ void scic_sds_controller_release_frame( * IO request. * @io_request: the handle to the io request object to start. * @io_tag: This parameter specifies a previously allocated IO tag that the - * user desires to be utilized for this request. This parameter is optional. - * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value - * for this parameter. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a - * result, it is expected the user will have set the NCQ tag field in the host - * to device register FIS prior to calling this method. There is also a - * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking - * the scic_controller_start_io() method. scic_controller_allocate_tag() for - * more information on allocating a tag. Indicate if the controller - * successfully started the IO request. SCI_SUCCESS if the IO request was - * successfully started. Determine the failure situations and return values. + * user desires to be utilized for this request. */ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, struct scic_sds_remote_device *rdev, - struct scic_sds_request *req, - u16 io_tag) + struct scic_sds_request *req) { enum sci_status status; @@ -2902,17 +2878,6 @@ enum sci_status scic_controller_terminate_request( * @remote_device: The handle to the remote device object for which to complete * the IO request. * @io_request: the handle to the io request object to complete. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI - * Core user, using the scic_controller_allocate_io_tag() method, then it is - * the responsibility of the caller to invoke the scic_controller_free_io_tag() - * method to free the tag (i.e. this method will not free the IO tag). Indicate - * if the controller successfully completed the IO request. SCI_SUCCESS if the - * completion process was successful. */ enum sci_status scic_controller_complete_io( struct scic_sds_controller *scic, @@ -2963,31 +2928,11 @@ enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) * @remote_device: the handle to the remote device object for which to start * the task management request. * @task_request: the handle to the task request object to start. - * @io_tag: This parameter specifies a previously allocated IO tag that the - * user desires to be utilized for this request. Note this not the io_tag - * of the request being managed. It is to be utilized for the task request - * itself. This parameter is optional. The user is allowed to supply - * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - The user must synchronize this task with completion - * queue processing. If they are not synchronized then it is possible for the - * io requests that are being managed by the task request can complete before - * starting the task request. scic_controller_allocate_tag() for more - * information on allocating a tag. Indicate if the controller successfully - * started the IO request. SCI_TASK_SUCCESS if the task request was - * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is - * returned if there is/are task(s) outstanding that require termination or - * completion before this request can succeed. */ enum sci_task_status scic_controller_start_task( struct scic_sds_controller *scic, struct scic_sds_remote_device *rdev, - struct scic_sds_request *req, - u16 task_tag) + struct scic_sds_request *req) { enum sci_status status; @@ -3022,85 +2967,3 @@ enum sci_task_status scic_controller_start_task( return status; } - -/** - * scic_controller_allocate_io_tag() - This method will allocate a tag from the - * pool of free IO tags. Direct allocation of IO tags by the SCI Core user - * is optional. The scic_controller_start_io() method will allocate an IO - * tag if this method is not utilized and the tag is not supplied to the IO - * construct routine. Direct allocation of IO tags may provide additional - * performance improvements in environments capable of supporting this usage - * model. Additionally, direct allocation of IO tags also provides - * additional flexibility to the SCI Core user. Specifically, the user may - * retain IO tags across the lives of multiple IO requests. - * @controller: the handle to the controller object for which to allocate the - * tag. - * - * IO tags are a protected resource. It is incumbent upon the SCI Core user to - * ensure that each of the methods that may allocate or free available IO tags - * are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). An unsigned integer representing an available IO tag. - * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no - * currently available tags to be allocated. All return other values indicate a - * legitimate tag. - */ -u16 scic_controller_allocate_io_tag(struct scic_sds_controller *scic) -{ - struct isci_host *ihost = scic_to_ihost(scic); - - if (isci_tci_space(ihost)) { - u16 tci = isci_tci_alloc(ihost); - u8 seq = scic->io_request_sequence[tci]; - - return ISCI_TAG(seq, tci); - } - - return SCI_CONTROLLER_INVALID_IO_TAG; -} - -/** - * scic_controller_free_io_tag() - This method will free an IO tag to the pool - * of free IO tags. This method provides the SCI Core user more flexibility - * with regards to IO tags. The user may desire to keep an IO tag after an - * IO request has completed, because they plan on re-using the tag for a - * subsequent IO request. This method is only legal if the tag was - * allocated via scic_controller_allocate_io_tag(). - * @controller: This parameter specifies the handle to the controller object - * for which to free/return the tag. - * @io_tag: This parameter represents the tag to be freed to the pool of - * available tags. - * - * - IO tags are a protected resource. It is incumbent upon the SCI Core user - * to ensure that each of the methods that may allocate or free available IO - * tags are handled in a mutually exclusive manner. This method is one of said - * methods requiring proper critical code section protection (e.g. semaphore, - * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI - * Core user, using the scic_controller_allocate_io_tag() method, then it is - * the responsibility of the caller to invoke this method to free the tag. This - * method returns an indication of whether the tag was successfully put back - * (freed) to the pool of available tags. SCI_SUCCESS This return value - * indicates the tag was successfully placed into the pool of available IO - * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag - * is not a valid IO tag value. - */ -enum sci_status scic_controller_free_io_tag(struct scic_sds_controller *scic, - u16 io_tag) -{ - struct isci_host *ihost = scic_to_ihost(scic); - u16 tci = ISCI_TAG_TCI(io_tag); - u16 seq = ISCI_TAG_SEQ(io_tag); - - /* prevent tail from passing head */ - if (isci_tci_active(ihost) == 0) - return SCI_FAILURE_INVALID_IO_TAG; - - if (seq == scic->io_request_sequence[tci]) { - scic->io_request_sequence[tci] = (seq+1) & (SCI_MAX_SEQ-1); - - isci_tci_free(ihost, ISCI_TAG_TCI(io_tag)); - - return SCI_SUCCESS; - } - return SCI_FAILURE_INVALID_IO_TAG; -} diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index a54397e1bf16..d8164f5d7988 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -192,6 +192,7 @@ struct scic_sds_controller { * context table. This data is shared between the hardware and software. */ struct scu_task_context *task_context_table; + dma_addr_t task_context_dma; /** * This field is a pointer to the memory allocated by the driver for the @@ -302,12 +303,8 @@ struct isci_host { struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ struct sas_ha_struct sas_ha; - int can_queue; - spinlock_t queue_lock; spinlock_t state_lock; - struct pci_dev *pdev; - enum isci_status status; #define IHOST_START_PENDING 0 #define IHOST_STOP_PENDING 1 @@ -451,36 +448,6 @@ static inline void isci_host_change_state(struct isci_host *isci_host, } -static inline int isci_host_can_queue(struct isci_host *isci_host, int num) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&isci_host->queue_lock, flags); - if ((isci_host->can_queue - num) < 0) { - dev_dbg(&isci_host->pdev->dev, - "%s: isci_host->can_queue = %d\n", - __func__, - isci_host->can_queue); - ret = -SAS_QUEUE_FULL; - - } else - isci_host->can_queue -= num; - - spin_unlock_irqrestore(&isci_host->queue_lock, flags); - - return ret; -} - -static inline void isci_host_can_dequeue(struct isci_host *isci_host, int num) -{ - unsigned long flags; - - spin_lock_irqsave(&isci_host->queue_lock, flags); - isci_host->can_queue += num; - spin_unlock_irqrestore(&isci_host->queue_lock, flags); -} - static inline void wait_for_start(struct isci_host *ihost) { wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags)); @@ -646,10 +613,6 @@ union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffe struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 io_tag); -struct scu_task_context *scic_sds_controller_get_task_context_buffer( - struct scic_sds_controller *scic, - u16 io_tag); - void scic_sds_controller_power_control_queue_insert( struct scic_sds_controller *scic, struct scic_sds_phy *sci_phy); @@ -681,6 +644,9 @@ void scic_sds_controller_register_setup(struct scic_sds_controller *scic); enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req); int isci_host_scan_finished(struct Scsi_Host *, unsigned long); void isci_host_scan_start(struct Scsi_Host *); +u16 isci_alloc_tag(struct isci_host *ihost); +enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag); +void isci_tci_free(struct isci_host *ihost, u16 tci); int isci_host_init(struct isci_host *); @@ -708,14 +674,12 @@ void scic_controller_disable_interrupts( enum sci_status scic_controller_start_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, - struct scic_sds_request *io_request, - u16 io_tag); + struct scic_sds_request *io_request); enum sci_task_status scic_controller_start_task( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, - struct scic_sds_request *task_request, - u16 io_tag); + struct scic_sds_request *task_request); enum sci_status scic_controller_terminate_request( struct scic_sds_controller *scic, @@ -727,13 +691,6 @@ enum sci_status scic_controller_complete_io( struct scic_sds_remote_device *remote_device, struct scic_sds_request *io_request); -u16 scic_controller_allocate_io_tag( - struct scic_sds_controller *scic); - -enum sci_status scic_controller_free_io_tag( - struct scic_sds_controller *scic, - u16 io_tag); - void scic_sds_port_configuration_agent_construct( struct scic_sds_port_configuration_agent *port_agent); diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 5f4a4e3954db..0e84e29335dd 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -695,35 +695,21 @@ static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u1 */ static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tag) { + struct scic_sds_controller *scic = sci_port->owning_controller; struct scu_task_context *task_context; - task_context = scic_sds_controller_get_task_context_buffer(sci_port->owning_controller, tag); - + task_context = &scic->task_context_table[ISCI_TAG_TCI(tag)]; memset(task_context, 0, sizeof(struct scu_task_context)); - task_context->abort = 0; - task_context->priority = 0; task_context->initiator_request = 1; task_context->connection_rate = 1; - task_context->protocol_engine_index = 0; task_context->logical_port_index = sci_port->physical_port_index; task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; task_context->task_index = ISCI_TAG_TCI(tag); task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; - task_context->remote_node_index = sci_port->reserved_rni; - task_context->command_code = 0; - - task_context->link_layer_control = 0; task_context->do_not_dma_ssp_good_response = 1; - task_context->strict_ordering = 0; - task_context->control_frame = 0; - task_context->timeout_enable = 0; - task_context->block_guard_enable = 0; - - task_context->address_modifier = 0; - task_context->task_phase = 0x01; } @@ -731,15 +717,15 @@ static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port { struct scic_sds_controller *scic = sci_port->owning_controller; - if (sci_port->reserved_tci != SCU_DUMMY_INDEX) - scic_controller_free_io_tag(scic, sci_port->reserved_tci); + if (sci_port->reserved_tag != SCI_CONTROLLER_INVALID_IO_TAG) + isci_free_tag(scic_to_ihost(scic), sci_port->reserved_tag); if (sci_port->reserved_rni != SCU_DUMMY_INDEX) scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes, 1, sci_port->reserved_rni); sci_port->reserved_rni = SCU_DUMMY_INDEX; - sci_port->reserved_tci = SCU_DUMMY_INDEX; + sci_port->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; } /** @@ -1119,18 +1105,17 @@ scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port) */ static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) { - u32 command; - struct scu_task_context *task_context; struct scic_sds_controller *scic = sci_port->owning_controller; - u16 tci = sci_port->reserved_tci; - - task_context = scic_sds_controller_get_task_context_buffer(scic, tci); + u16 tag = sci_port->reserved_tag; + struct scu_task_context *tc; + u32 command; - task_context->abort = 0; + tc = &scic->task_context_table[ISCI_TAG_TCI(tag)]; + tc->abort = 0; command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | - tci; + ISCI_TAG_TCI(tag); scic_sds_controller_post_request(scic, command); } @@ -1145,17 +1130,16 @@ static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) { struct scic_sds_controller *scic = sci_port->owning_controller; - u16 tci = sci_port->reserved_tci; + u16 tag = sci_port->reserved_tag; struct scu_task_context *tc; u32 command; - tc = scic_sds_controller_get_task_context_buffer(scic, tci); - + tc = &scic->task_context_table[ISCI_TAG_TCI(tag)]; tc->abort = 1; command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT | sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | - tci; + ISCI_TAG_TCI(tag); scic_sds_controller_post_request(scic, command); } @@ -1333,15 +1317,16 @@ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) sci_port->reserved_rni = rni; } - if (sci_port->reserved_tci == SCU_DUMMY_INDEX) { - /* Allocate a TCI and remove the sequence nibble */ - u16 tci = scic_controller_allocate_io_tag(scic); + if (sci_port->reserved_tag == SCI_CONTROLLER_INVALID_IO_TAG) { + struct isci_host *ihost = scic_to_ihost(scic); + u16 tag; - if (tci != SCU_DUMMY_INDEX) - scic_sds_port_construct_dummy_task(sci_port, tci); - else + tag = isci_alloc_tag(ihost); + if (tag == SCI_CONTROLLER_INVALID_IO_TAG) status = SCI_FAILURE_INSUFFICIENT_RESOURCES; - sci_port->reserved_tci = tci; + else + scic_sds_port_construct_dummy_task(sci_port, tag); + sci_port->reserved_tag = tag; } if (status == SCI_SUCCESS) { @@ -1859,7 +1844,7 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, sci_port->assigned_device_count = 0; sci_port->reserved_rni = SCU_DUMMY_INDEX; - sci_port->reserved_tci = SCU_DUMMY_INDEX; + sci_port->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; sci_init_timer(&sci_port->timer, port_timeout); diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 45c01f80bf83..a44e541914f5 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -108,7 +108,7 @@ struct scic_sds_port { u8 active_phy_mask; u16 reserved_rni; - u16 reserved_tci; + u16 reserved_tag; /** * This field contains the count of the io requests started on this port diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 08a7340b33bf..55859d5331b1 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -61,42 +61,50 @@ #include "scu_event_codes.h" #include "sas.h" -/** - * This method returns the sgl element pair for the specificed sgl_pair index. - * @sci_req: This parameter specifies the IO request for which to retrieve - * the Scatter-Gather List element pair. - * @sgl_pair_index: This parameter specifies the index into the SGL element - * pair to be retrieved. - * - * This method returns a pointer to an struct scu_sgl_element_pair. - */ -static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( - struct scic_sds_request *sci_req, - u32 sgl_pair_index - ) { - struct scu_task_context *task_context; +static struct scu_sgl_element_pair *to_sgl_element_pair(struct scic_sds_request *sci_req, + int idx) +{ + if (idx == 0) + return &sci_req->tc->sgl_pair_ab; + else if (idx == 1) + return &sci_req->tc->sgl_pair_cd; + else if (idx < 0) + return NULL; + else + return &sci_req->sg_table[idx - 2]; +} - task_context = (struct scu_task_context *)sci_req->task_context_buffer; +static dma_addr_t to_sgl_element_pair_dma(struct scic_sds_controller *scic, + struct scic_sds_request *sci_req, u32 idx) +{ + u32 offset; - if (sgl_pair_index == 0) { - return &task_context->sgl_pair_ab; - } else if (sgl_pair_index == 1) { - return &task_context->sgl_pair_cd; + if (idx == 0) { + offset = (void *) &sci_req->tc->sgl_pair_ab - + (void *) &scic->task_context_table[0]; + return scic->task_context_dma + offset; + } else if (idx == 1) { + offset = (void *) &sci_req->tc->sgl_pair_cd - + (void *) &scic->task_context_table[0]; + return scic->task_context_dma + offset; } - return &sci_req->sg_table[sgl_pair_index - 2]; + return scic_io_request_get_dma_addr(sci_req, &sci_req->sg_table[idx - 2]); +} + +static void init_sgl_element(struct scu_sgl_element *e, struct scatterlist *sg) +{ + e->length = sg_dma_len(sg); + e->address_upper = upper_32_bits(sg_dma_address(sg)); + e->address_lower = lower_32_bits(sg_dma_address(sg)); + e->address_modifier = 0; } -/** - * This function will build the SGL list for an IO request. - * @sci_req: This parameter specifies the IO request for which to build - * the Scatter-Gather List. - * - */ static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) { struct isci_request *isci_request = sci_req_to_ireq(sds_request); struct isci_host *isci_host = isci_request->isci_host; + struct scic_sds_controller *scic = &isci_host->sci; struct sas_task *task = isci_request_access_task(isci_request); struct scatterlist *sg = NULL; dma_addr_t dma_addr; @@ -108,25 +116,19 @@ static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) sg = task->scatter; while (sg) { - scu_sg = scic_sds_request_get_sgl_element_pair( - sds_request, - sg_idx); - - SCU_SGL_COPY(scu_sg->A, sg); - + scu_sg = to_sgl_element_pair(sds_request, sg_idx); + init_sgl_element(&scu_sg->A, sg); sg = sg_next(sg); - if (sg) { - SCU_SGL_COPY(scu_sg->B, sg); + init_sgl_element(&scu_sg->B, sg); sg = sg_next(sg); } else - SCU_SGL_ZERO(scu_sg->B); + memset(&scu_sg->B, 0, sizeof(scu_sg->B)); if (prev_sg) { - dma_addr = - scic_io_request_get_dma_addr( - sds_request, - scu_sg); + dma_addr = to_sgl_element_pair_dma(scic, + sds_request, + sg_idx); prev_sg->next_pair_upper = upper_32_bits(dma_addr); @@ -138,8 +140,7 @@ static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) sg_idx++; } } else { /* handle when no sg */ - scu_sg = scic_sds_request_get_sgl_element_pair(sds_request, - sg_idx); + scu_sg = to_sgl_element_pair(sds_request, sg_idx); dma_addr = dma_map_single(&isci_host->pdev->dev, task->scatter, @@ -246,35 +247,12 @@ static void scu_ssp_reqeust_construct_task_context( /* task_context->type.ssp.tag = sci_req->io_tag; */ task_context->task_phase = 0x01; - if (sds_request->was_tag_assigned_by_user) { - /* - * Build the task context now since we have already read - * the data - */ - sds_request->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(sds_request->io_tag)); - } else { - /* - * Build the task context now since we have already read - * the data - * - * I/O tag index is not assigned because we have to wait - * until we get a TCi - */ - sds_request->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - owning_controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); - } + sds_request->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group(controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + ISCI_TAG_TCI(sds_request->io_tag)); /* * Copy the physical address for the command buffer to the @@ -302,14 +280,11 @@ static void scu_ssp_reqeust_construct_task_context( * @sci_req: * */ -static void scu_ssp_io_request_construct_task_context( - struct scic_sds_request *sci_req, - enum dma_data_direction dir, - u32 len) +static void scu_ssp_io_request_construct_task_context(struct scic_sds_request *sci_req, + enum dma_data_direction dir, + u32 len) { - struct scu_task_context *task_context; - - task_context = scic_sds_request_get_task_context(sci_req); + struct scu_task_context *task_context = sci_req->tc; scu_ssp_reqeust_construct_task_context(sci_req, task_context); @@ -347,12 +322,9 @@ static void scu_ssp_io_request_construct_task_context( * constructed. * */ -static void scu_ssp_task_request_construct_task_context( - struct scic_sds_request *sci_req) +static void scu_ssp_task_request_construct_task_context(struct scic_sds_request *sci_req) { - struct scu_task_context *task_context; - - task_context = scic_sds_request_get_task_context(sci_req); + struct scu_task_context *task_context = sci_req->tc; scu_ssp_reqeust_construct_task_context(sci_req, task_context); @@ -421,35 +393,12 @@ static void scu_sata_reqeust_construct_task_context( /* Set the first word of the H2D REG FIS */ task_context->type.words[0] = *(u32 *)&sci_req->stp.cmd; - if (sci_req->was_tag_assigned_by_user) { - /* - * Build the task context now since we have already read - * the data - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(sci_req->io_tag)); - } else { - /* - * Build the task context now since we have already read - * the data. - * I/O tag index is not assigned because we have to wait - * until we get a TCi. - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group( - controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); - } - + sci_req->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group(controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(target_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + ISCI_TAG_TCI(sci_req->io_tag)); /* * Copy the physical address for the command buffer to the SCU Task * Context. We must offset the command buffer by 4 bytes because the @@ -467,22 +416,9 @@ static void scu_sata_reqeust_construct_task_context( task_context->response_iu_lower = 0; } - - -/** - * scu_stp_raw_request_construct_task_context - - * @sci_req: This parameter specifies the STP request object for which to - * construct a RAW command frame task context. - * @task_context: This parameter specifies the SCU specific task context buffer - * to construct. - * - * This method performs the operations common to all SATA/STP requests - * utilizing the raw frame method. none - */ -static void scu_stp_raw_request_construct_task_context(struct scic_sds_stp_request *stp_req, - struct scu_task_context *task_context) +static void scu_stp_raw_request_construct_task_context(struct scic_sds_request *sci_req) { - struct scic_sds_request *sci_req = to_sci_req(stp_req); + struct scu_task_context *task_context = sci_req->tc; scu_sata_reqeust_construct_task_context(sci_req, task_context); @@ -500,8 +436,7 @@ scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, struct scic_sds_stp_request *stp_req = &sci_req->stp.req; struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; - scu_stp_raw_request_construct_task_context(stp_req, - sci_req->task_context_buffer); + scu_stp_raw_request_construct_task_context(sci_req); pio->current_transfer_bytes = 0; pio->ending_error = 0; @@ -512,13 +447,10 @@ scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, if (copy_rx_frame) { scic_sds_request_build_sgl(sci_req); - /* Since the IO request copy of the TC contains the same data as - * the actual TC this pointer is vaild for either. - */ - pio->request_current.sgl_pair = &sci_req->task_context_buffer->sgl_pair_ab; + pio->request_current.sgl_index = 0; } else { /* The user does not want the data copied to the SGL buffer location */ - pio->request_current.sgl_pair = NULL; + pio->request_current.sgl_index = -1; } return SCI_SUCCESS; @@ -541,7 +473,7 @@ static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sc u32 len, enum dma_data_direction dir) { - struct scu_task_context *task_context = sci_req->task_context_buffer; + struct scu_task_context *task_context = sci_req->tc; /* Build the STP task context structure */ scu_sata_reqeust_construct_task_context(sci_req, task_context); @@ -587,8 +519,7 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, if (tmf->tmf_code == isci_tmf_sata_srst_high || tmf->tmf_code == isci_tmf_sata_srst_low) { - scu_stp_raw_request_construct_task_context(&sci_req->stp.req, - sci_req->task_context_buffer); + scu_stp_raw_request_construct_task_context(sci_req); return SCI_SUCCESS; } else { dev_err(scic_to_dev(sci_req->owning_controller), @@ -611,8 +542,7 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, /* non data */ if (task->data_dir == DMA_NONE) { - scu_stp_raw_request_construct_task_context(&sci_req->stp.req, - sci_req->task_context_buffer); + scu_stp_raw_request_construct_task_context(sci_req); return SCI_SUCCESS; } @@ -701,8 +631,7 @@ enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_re if (tmf->tmf_code == isci_tmf_sata_srst_high || tmf->tmf_code == isci_tmf_sata_srst_low) { - scu_stp_raw_request_construct_task_context(&sci_req->stp.req, - sci_req->task_context_buffer); + scu_stp_raw_request_construct_task_context(sci_req); } else { dev_err(scic_to_dev(sci_req->owning_controller), "%s: Request 0x%p received un-handled SAT " @@ -749,9 +678,9 @@ static u32 sci_req_tx_bytes(struct scic_sds_request *sci_req) enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) { - struct scic_sds_controller *scic = sci_req->owning_controller; - struct scu_task_context *task_context; enum sci_base_request_states state; + struct scu_task_context *tc = sci_req->tc; + struct scic_sds_controller *scic = sci_req->owning_controller; state = sci_req->sm.current_state_id; if (state != SCI_REQ_CONSTRUCTED) { @@ -761,61 +690,39 @@ enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) return SCI_FAILURE_INVALID_STATE; } - /* if necessary, allocate a TCi for the io request object and then will, - * if necessary, copy the constructed TC data into the actual TC buffer. - * If everything is successful the post context field is updated with - * the TCi so the controller can post the request to the hardware. - */ - if (sci_req->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) - sci_req->io_tag = scic_controller_allocate_io_tag(scic); - - /* Record the IO Tag in the request */ - if (sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { - task_context = sci_req->task_context_buffer; - - task_context->task_index = ISCI_TAG_TCI(sci_req->io_tag); - - switch (task_context->protocol_type) { - case SCU_TASK_CONTEXT_PROTOCOL_SMP: - case SCU_TASK_CONTEXT_PROTOCOL_SSP: - /* SSP/SMP Frame */ - task_context->type.ssp.tag = sci_req->io_tag; - task_context->type.ssp.target_port_transfer_tag = - 0xFFFF; - break; + tc->task_index = ISCI_TAG_TCI(sci_req->io_tag); - case SCU_TASK_CONTEXT_PROTOCOL_STP: - /* STP/SATA Frame - * task_context->type.stp.ncq_tag = sci_req->ncq_tag; - */ - break; - - case SCU_TASK_CONTEXT_PROTOCOL_NONE: - /* / @todo When do we set no protocol type? */ - break; + switch (tc->protocol_type) { + case SCU_TASK_CONTEXT_PROTOCOL_SMP: + case SCU_TASK_CONTEXT_PROTOCOL_SSP: + /* SSP/SMP Frame */ + tc->type.ssp.tag = sci_req->io_tag; + tc->type.ssp.target_port_transfer_tag = 0xFFFF; + break; - default: - /* This should never happen since we build the IO - * requests */ - break; - } + case SCU_TASK_CONTEXT_PROTOCOL_STP: + /* STP/SATA Frame + * tc->type.stp.ncq_tag = sci_req->ncq_tag; + */ + break; - /* - * Check to see if we need to copy the task context buffer - * or have been building into the task context buffer */ - if (sci_req->was_tag_assigned_by_user == false) - scic_sds_controller_copy_task_context(scic, sci_req); + case SCU_TASK_CONTEXT_PROTOCOL_NONE: + /* / @todo When do we set no protocol type? */ + break; - /* Add to the post_context the io tag value */ - sci_req->post_context |= ISCI_TAG_TCI(sci_req->io_tag); + default: + /* This should never happen since we build the IO + * requests */ + break; + } - /* Everything is good go ahead and change state */ - sci_change_state(&sci_req->sm, SCI_REQ_STARTED); + /* Add to the post_context the io tag value */ + sci_req->post_context |= ISCI_TAG_TCI(sci_req->io_tag); - return SCI_SUCCESS; - } + /* Everything is good go ahead and change state */ + sci_change_state(&sci_req->sm, SCI_REQ_STARTED); - return SCI_FAILURE_INSUFFICIENT_RESOURCES; + return SCI_SUCCESS; } enum sci_status @@ -880,9 +787,6 @@ enum sci_status scic_sds_request_complete(struct scic_sds_request *sci_req) "isci: request completion from wrong state (%d)\n", state)) return SCI_FAILURE_INVALID_STATE; - if (!sci_req->was_tag_assigned_by_user) - scic_controller_free_io_tag(scic, sci_req->io_tag); - if (sci_req->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) scic_sds_controller_release_frame(scic, sci_req->saved_rx_frame_index); @@ -1244,51 +1148,40 @@ void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *req, * @note This could be made to return an error to the user if the user * attempts to set the NCQ tag in the wrong state. */ - req->task_context_buffer->type.stp.ncq_tag = ncq_tag; + req->tc->type.stp.ncq_tag = ncq_tag; } -/** - * - * @sci_req: - * - * Get the next SGL element from the request. - Check on which SGL element pair - * we are working - if working on SLG pair element A - advance to element B - - * else - check to see if there are more SGL element pairs for this IO request - * - if there are more SGL element pairs - advance to the next pair and return - * element A struct scu_sgl_element* - */ -static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req) +static struct scu_sgl_element *pio_sgl_next(struct scic_sds_stp_request *stp_req) { - struct scu_sgl_element *current_sgl; + struct scu_sgl_element *sgl; + struct scu_sgl_element_pair *sgl_pair; struct scic_sds_request *sci_req = to_sci_req(stp_req); struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current; - if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - if (pio_sgl->sgl_pair->B.address_lower == 0 && - pio_sgl->sgl_pair->B.address_upper == 0) { - current_sgl = NULL; + sgl_pair = to_sgl_element_pair(sci_req, pio_sgl->sgl_index); + if (!sgl_pair) + sgl = NULL; + else if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + if (sgl_pair->B.address_lower == 0 && + sgl_pair->B.address_upper == 0) { + sgl = NULL; } else { pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B; - current_sgl = &pio_sgl->sgl_pair->B; + sgl = &sgl_pair->B; } } else { - if (pio_sgl->sgl_pair->next_pair_lower == 0 && - pio_sgl->sgl_pair->next_pair_upper == 0) { - current_sgl = NULL; + if (sgl_pair->next_pair_lower == 0 && + sgl_pair->next_pair_upper == 0) { + sgl = NULL; } else { - u64 phys_addr; - - phys_addr = pio_sgl->sgl_pair->next_pair_upper; - phys_addr <<= 32; - phys_addr |= pio_sgl->sgl_pair->next_pair_lower; - - pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr); + pio_sgl->sgl_index++; pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A; - current_sgl = &pio_sgl->sgl_pair->A; + sgl_pair = to_sgl_element_pair(sci_req, pio_sgl->sgl_index); + sgl = &sgl_pair->A; } } - return current_sgl; + return sgl; } static enum sci_status @@ -1328,21 +1221,19 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( struct scic_sds_request *sci_req, u32 length) { - struct scic_sds_controller *scic = sci_req->owning_controller; struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scu_task_context *task_context; + struct scu_task_context *task_context = sci_req->tc; + struct scu_sgl_element_pair *sgl_pair; struct scu_sgl_element *current_sgl; /* Recycle the TC and reconstruct it for sending out DATA FIS containing * for the data from current_sgl+offset for the input length */ - task_context = scic_sds_controller_get_task_context_buffer(scic, - sci_req->io_tag); - + sgl_pair = to_sgl_element_pair(sci_req, stp_req->type.pio.request_current.sgl_index); if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) - current_sgl = &stp_req->type.pio.request_current.sgl_pair->A; + current_sgl = &sgl_pair->A; else - current_sgl = &stp_req->type.pio.request_current.sgl_pair->B; + current_sgl = &sgl_pair->B; /* update the TC */ task_context->command_iu_upper = current_sgl->address_upper; @@ -1362,18 +1253,21 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct sc u32 remaining_bytes_in_current_sgl = 0; enum sci_status status = SCI_SUCCESS; struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct scu_sgl_element_pair *sgl_pair; sgl_offset = stp_req->type.pio.request_current.sgl_offset; + sgl_pair = to_sgl_element_pair(sci_req, stp_req->type.pio.request_current.sgl_index); + if (WARN_ONCE(!sgl_pair, "%s: null sgl element", __func__)) + return SCI_FAILURE; if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A); - remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->A.length - sgl_offset; + current_sgl = &sgl_pair->A; + remaining_bytes_in_current_sgl = sgl_pair->A.length - sgl_offset; } else { - current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B); - remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->B.length - sgl_offset; + current_sgl = &sgl_pair->B; + remaining_bytes_in_current_sgl = sgl_pair->B.length - sgl_offset; } - if (stp_req->type.pio.pio_transfer_bytes > 0) { if (stp_req->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ @@ -1382,7 +1276,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct sc stp_req->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; /* update the current sgl, sgl_offset and save for future */ - current_sgl = scic_sds_stp_request_pio_get_next_sgl(stp_req); + current_sgl = pio_sgl_next(stp_req); sgl_offset = 0; } } else if (stp_req->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { @@ -1945,7 +1839,7 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, return status; } - if (stp_req->type.pio.request_current.sgl_pair == NULL) { + if (stp_req->type.pio.request_current.sgl_index < 0) { sci_req->saved_rx_frame_index = frame_index; stp_req->type.pio.pio_transfer_bytes = 0; } else { @@ -2977,8 +2871,6 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * task to recognize the already completed case. */ request->terminated = true; - - isci_host_can_dequeue(isci_host, 1); } static void scic_sds_request_started_state_enter(struct sci_base_state_machine *sm) @@ -3039,7 +2931,7 @@ static void scic_sds_request_aborting_state_enter(struct sci_base_state_machine struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); /* Setting the abort bit in the Task Context is required by the silicon. */ - sci_req->task_context_buffer->abort = 1; + sci_req->tc->abort = 1; } static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(struct sci_base_state_machine *sm) @@ -3069,7 +2961,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completio static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(struct sci_base_state_machine *sm) { struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); - struct scu_task_context *task_context; + struct scu_task_context *tc = sci_req->tc; struct host_to_dev_fis *h2d_fis; enum sci_status status; @@ -3078,9 +2970,7 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet h2d_fis->control = 0; /* Clear the TC control bit */ - task_context = scic_sds_controller_get_task_context_buffer( - sci_req->owning_controller, sci_req->io_tag); - task_context->control_frame = 0; + tc->control_frame = 0; status = scic_controller_continue_io(sci_req); WARN_ONCE(status != SCI_SUCCESS, "isci: continue io failure\n"); @@ -3141,18 +3031,10 @@ scic_sds_general_request_construct(struct scic_sds_controller *scic, sci_req->sci_status = SCI_SUCCESS; sci_req->scu_status = 0; sci_req->post_context = 0xFFFFFFFF; + sci_req->tc = &scic->task_context_table[ISCI_TAG_TCI(io_tag)]; sci_req->is_task_management_request = false; - - if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { - sci_req->was_tag_assigned_by_user = false; - sci_req->task_context_buffer = &sci_req->tc; - } else { - sci_req->was_tag_assigned_by_user = true; - - sci_req->task_context_buffer = - scic_sds_controller_get_task_context_buffer(scic, io_tag); - } + WARN_ONCE(io_tag == SCI_CONTROLLER_INVALID_IO_TAG, "straggling invalid tag usage\n"); } static enum sci_status @@ -3178,8 +3060,7 @@ scic_io_request_construct(struct scic_sds_controller *scic, else return SCI_FAILURE_UNSUPPORTED_PROTOCOL; - memset(sci_req->task_context_buffer, 0, - offsetof(struct scu_task_context, sgl_pair_ab)); + memset(sci_req->tc, 0, offsetof(struct scu_task_context, sgl_pair_ab)); return status; } @@ -3197,7 +3078,7 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { sci_req->is_task_management_request = true; - memset(sci_req->task_context_buffer, 0, sizeof(struct scu_task_context)); + memset(sci_req->tc, 0, sizeof(struct scu_task_context)); } else status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; @@ -3299,7 +3180,7 @@ scic_io_request_construct_smp(struct device *dev, /* byte swap the smp request. */ - task_context = scic_sds_request_get_task_context(sci_req); + task_context = sci_req->tc; sci_dev = scic_sds_request_get_device(sci_req); sci_port = scic_sds_request_get_port(sci_req); @@ -3354,33 +3235,12 @@ scic_io_request_construct_smp(struct device *dev, */ task_context->task_phase = 0; - if (sci_req->was_tag_assigned_by_user) { - /* - * Build the task context now since we have already read - * the data - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(scic) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(sci_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(sci_req->io_tag)); - } else { - /* - * Build the task context now since we have already read - * the data. - * I/O tag index is not assigned because we have to wait - * until we get a TCi. - */ - sci_req->post_context = - (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(scic) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(sci_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT)); - } - + sci_req->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + (scic_sds_controller_get_protocol_engine_group(scic) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(sci_port) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + ISCI_TAG_TCI(sci_req->io_tag)); /* * Copy the physical address for the command buffer to the SCU Task * Context command buffer should not contain command header. @@ -3431,10 +3291,10 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) * * SCI_SUCCESS on successfull completion, or specific failure code. */ -static enum sci_status isci_io_request_build( - struct isci_host *isci_host, - struct isci_request *request, - struct isci_remote_device *isci_device) +static enum sci_status isci_io_request_build(struct isci_host *isci_host, + struct isci_request *request, + struct isci_remote_device *isci_device, + u16 tag) { enum sci_status status = SCI_SUCCESS; struct sas_task *task = isci_request_access_task(request); @@ -3471,8 +3331,7 @@ static enum sci_status isci_io_request_build( * we will let the core allocate the IO tag. */ status = scic_io_request_construct(&isci_host->sci, sci_device, - SCI_CONTROLLER_INVALID_IO_TAG, - &request->sci); + tag, &request->sci); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -3564,7 +3423,7 @@ struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, } int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, - struct sas_task *task, gfp_t gfp_flags) + struct sas_task *task, u16 tag, gfp_t gfp_flags) { enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; struct isci_request *ireq; @@ -3576,7 +3435,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide if (!ireq) goto out; - status = isci_io_request_build(ihost, ireq, idev); + status = isci_io_request_build(ihost, ireq, idev, tag); if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, "%s: request_construct failed - status = 0x%x\n", @@ -3599,18 +3458,16 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide */ status = scic_controller_start_task(&ihost->sci, &idev->sci, - &ireq->sci, - SCI_CONTROLLER_INVALID_IO_TAG); + &ireq->sci); } else { status = SCI_FAILURE; } } else { - /* send the request, let the core assign the IO TAG. */ status = scic_controller_start_io(&ihost->sci, &idev->sci, - &ireq->sci, - SCI_CONTROLLER_INVALID_IO_TAG); + &ireq->sci); } + if (status != SCI_SUCCESS && status != SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { dev_warn(&ihost->pdev->dev, @@ -3647,23 +3504,23 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide if (status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { /* Signal libsas that we need the SCSI error - * handler thread to work on this I/O and that - * we want a device reset. - */ + * handler thread to work on this I/O and that + * we want a device reset. + */ spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; spin_unlock_irqrestore(&task->task_state_lock, flags); /* Cause this task to be scheduled in the SCSI error - * handler thread. - */ + * handler thread. + */ isci_execpath_callback(ihost, task, sas_task_abort); /* Change the status, since we are holding - * the I/O until it is managed by the SCSI - * error handler. - */ + * the I/O until it is managed by the SCSI + * error handler. + */ status = SCI_SUCCESS; } diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 9130f22a63b8..8c77c4cbe04a 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -136,7 +136,7 @@ struct scic_sds_stp_request { u8 ending_error; struct scic_sds_request_pio_sgl { - struct scu_sgl_element_pair *sgl_pair; + int sgl_index; u8 sgl_set; u32 sgl_offset; } request_current; @@ -171,12 +171,6 @@ struct scic_sds_request { */ struct scic_sds_remote_device *target_device; - /* - * This field is utilized to determine if the SCI user is managing - * the IO tag for this request or if the core is managing it. - */ - bool was_tag_assigned_by_user; - /* * This field indicates the IO tag for this request. The IO tag is * comprised of the task_index and a sequence count. The sequence count @@ -209,8 +203,7 @@ struct scic_sds_request { */ u32 post_context; - struct scu_task_context *task_context_buffer; - struct scu_task_context tc ____cacheline_aligned; + struct scu_task_context *tc; /* could be larger with sg chaining */ #define SCU_SGL_SIZE ((SCI_MAX_SCATTER_GATHER_ELEMENTS + 1) / 2) @@ -465,35 +458,6 @@ enum sci_base_request_states { (request)->sci_status = (sci_status_code); \ } -/** - * SCU_SGL_ZERO() - - * - * This macro zeros the hardware SGL element data - */ -#define SCU_SGL_ZERO(scu_sge) \ - { \ - (scu_sge).length = 0; \ - (scu_sge).address_lower = 0; \ - (scu_sge).address_upper = 0; \ - (scu_sge).address_modifier = 0; \ - } - -/** - * SCU_SGL_COPY() - - * - * This macro copys the SGL Element data from the host os to the hardware SGL - * elment data - */ -#define SCU_SGL_COPY(scu_sge, os_sge) \ - { \ - (scu_sge).length = sg_dma_len(sg); \ - (scu_sge).address_upper = \ - upper_32_bits(sg_dma_address(sg)); \ - (scu_sge).address_lower = \ - lower_32_bits(sg_dma_address(sg)); \ - (scu_sge).address_modifier = 0; \ - } - enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); enum sci_status @@ -509,22 +473,6 @@ scic_sds_request_complete(struct scic_sds_request *sci_req); extern enum sci_status scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, u32 code); -/* XXX open code in caller */ -static inline void *scic_request_get_virt_addr(struct scic_sds_request *sci_req, - dma_addr_t phys_addr) -{ - struct isci_request *ireq = sci_req_to_ireq(sci_req); - dma_addr_t offset; - - BUG_ON(phys_addr < ireq->request_daddr); - - offset = phys_addr - ireq->request_daddr; - - BUG_ON(offset >= sizeof(*ireq)); - - return (char *)ireq + offset; -} - /* XXX open code in caller */ static inline dma_addr_t scic_io_request_get_dma_addr(struct scic_sds_request *sci_req, void *virt_addr) @@ -672,7 +620,7 @@ struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, struct isci_tmf *isci_tmf, gfp_t gfp_flags); int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, - struct sas_task *task, gfp_t gfp_flags); + struct sas_task *task, u16 tag, gfp_t gfp_flags); void isci_terminate_pending_requests(struct isci_host *ihost, struct isci_remote_device *idev); enum sci_status diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 157e9978183a..22f6fe171111 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -63,6 +63,7 @@ #include "request.h" #include "sata.h" #include "task.h" +#include "host.h" /** * isci_task_refuse() - complete the request to the upper layer driver in @@ -156,25 +157,19 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) { struct isci_host *ihost = dev_to_ihost(task->dev); struct isci_remote_device *idev; - enum sci_status status; unsigned long flags; bool io_ready; - int ret; + u16 tag; dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num); - /* Check if we have room for more tasks */ - ret = isci_host_can_queue(ihost, num); - - if (ret) { - dev_warn(&ihost->pdev->dev, "%s: queue full\n", __func__); - return ret; - } - for_each_sas_task(num, task) { + enum sci_status status = SCI_FAILURE; + spin_lock_irqsave(&ihost->scic_lock, flags); idev = isci_lookup_device(task->dev); io_ready = isci_device_io_ready(idev, task); + tag = isci_alloc_tag(ihost); spin_unlock_irqrestore(&ihost->scic_lock, flags); dev_dbg(&ihost->pdev->dev, @@ -185,15 +180,12 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) if (!idev) { isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED, SAS_DEVICE_UNKNOWN); - isci_host_can_dequeue(ihost, 1); - } else if (!io_ready) { - + } else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) { /* Indicate QUEUE_FULL so that the scsi midlayer * retries. */ isci_task_refuse(ihost, task, SAS_TASK_COMPLETE, SAS_QUEUE_FULL); - isci_host_can_dequeue(ihost, 1); } else { /* There is a device and it's ready for I/O. */ spin_lock_irqsave(&task->task_state_lock, flags); @@ -206,13 +198,12 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED, SAM_STAT_TASK_ABORTED); - isci_host_can_dequeue(ihost, 1); } else { task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock_irqrestore(&task->task_state_lock, flags); /* build and send the request. */ - status = isci_request_execute(ihost, idev, task, gfp_flags); + status = isci_request_execute(ihost, idev, task, tag, gfp_flags); if (status != SCI_SUCCESS) { @@ -231,10 +222,17 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) isci_task_refuse(ihost, task, SAS_TASK_COMPLETE, SAS_QUEUE_FULL); - isci_host_can_dequeue(ihost, 1); } } } + if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) { + spin_lock_irqsave(&ihost->scic_lock, flags); + /* command never hit the device, so just free + * the tci and skip the sequence increment + */ + isci_tci_free(ihost, ISCI_TAG_TCI(tag)); + spin_unlock_irqrestore(&ihost->scic_lock, flags); + } isci_put_device(idev); } return 0; @@ -242,7 +240,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) static struct isci_request *isci_task_request_build(struct isci_host *ihost, struct isci_remote_device *idev, - struct isci_tmf *isci_tmf) + u16 tag, struct isci_tmf *isci_tmf) { enum sci_status status = SCI_FAILURE; struct isci_request *ireq = NULL; @@ -259,8 +257,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, return NULL; /* let the core do it's construct. */ - status = scic_task_request_construct(&ihost->sci, &idev->sci, - SCI_CONTROLLER_INVALID_IO_TAG, + status = scic_task_request_construct(&ihost->sci, &idev->sci, tag, &ireq->sci); if (status != SCI_SUCCESS) { @@ -290,8 +287,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, return ireq; errout: isci_request_free(ihost, ireq); - ireq = NULL; - return ireq; + return NULL; } int isci_task_execute_tmf(struct isci_host *ihost, @@ -305,6 +301,14 @@ int isci_task_execute_tmf(struct isci_host *ihost, int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; unsigned long timeleft; + u16 tag; + + spin_lock_irqsave(&ihost->scic_lock, flags); + tag = isci_alloc_tag(ihost); + spin_unlock_irqrestore(&ihost->scic_lock, flags); + + if (tag == SCI_CONTROLLER_INVALID_IO_TAG) + return ret; /* sanity check, return TMF_RESP_FUNC_FAILED * if the device is not there and ready. @@ -316,7 +320,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, "%s: isci_device = %p not ready (%#lx)\n", __func__, isci_device, isci_device ? isci_device->flags : 0); - return TMF_RESP_FUNC_FAILED; + goto err_tci; } else dev_dbg(&ihost->pdev->dev, "%s: isci_device = %p\n", @@ -327,22 +331,16 @@ int isci_task_execute_tmf(struct isci_host *ihost, /* Assign the pointer to the TMF's completion kernel wait structure. */ tmf->complete = &completion; - ireq = isci_task_request_build(ihost, isci_device, tmf); - if (!ireq) { - dev_warn(&ihost->pdev->dev, - "%s: isci_task_request_build failed\n", - __func__); - return TMF_RESP_FUNC_FAILED; - } + ireq = isci_task_request_build(ihost, isci_device, tag, tmf); + if (!ireq) + goto err_tci; spin_lock_irqsave(&ihost->scic_lock, flags); /* start the TMF io. */ - status = scic_controller_start_task( - &ihost->sci, - sci_device, - &ireq->sci, - SCI_CONTROLLER_INVALID_IO_TAG); + status = scic_controller_start_task(&ihost->sci, + sci_device, + &ireq->sci); if (status != SCI_TASK_SUCCESS) { dev_warn(&ihost->pdev->dev, @@ -351,8 +349,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, status, ireq); spin_unlock_irqrestore(&ihost->scic_lock, flags); - isci_request_free(ihost, ireq); - return ret; + goto err_ireq; } if (tmf->cb_state_func != NULL) @@ -403,6 +400,15 @@ int isci_task_execute_tmf(struct isci_host *ihost, ireq); return ret; + + err_ireq: + isci_request_free(ihost, ireq); + err_tci: + spin_lock_irqsave(&ihost->scic_lock, flags); + isci_tci_free(ihost, ISCI_TAG_TCI(tag)); + spin_unlock_irqrestore(&ihost->scic_lock, flags); + + return ret; } void isci_task_build_tmf( -- cgit v1.2.3 From 38d8879baeb61b6946052739e7c03fa79b3a57f0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 23 Jun 2011 14:33:48 -0700 Subject: isci: combine request flags Combine three bools into one unsigned long 'flags'. Doesn't increase the request size due to packing. (to do: optimize the structure layout). Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 48 ++++++++++++++++++++------------------------- drivers/scsi/isci/request.h | 12 ++++-------- drivers/scsi/isci/task.c | 23 +++++++++++----------- 3 files changed, 36 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 55859d5331b1..27376ba22483 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2183,7 +2183,7 @@ static void isci_request_set_open_reject_status( enum sas_open_rej_reason open_rej_reason) { /* Task in the target is done. */ - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); *response_ptr = SAS_TASK_UNDELIVERED; *status_ptr = SAS_OPEN_REJECT; *complete_to_host_ptr = isci_perform_normal_io_completion; @@ -2248,7 +2248,7 @@ static void isci_request_handle_controller_specific_errors( else *status_ptr = SAS_ABORTED_TASK; - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); *complete_to_host_ptr = isci_perform_normal_io_completion; @@ -2261,7 +2261,7 @@ static void isci_request_handle_controller_specific_errors( else *status_ptr = SAM_STAT_TASK_ABORTED; - request->complete_in_target = false; + clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); *complete_to_host_ptr = isci_perform_error_io_completion; @@ -2292,7 +2292,7 @@ static void isci_request_handle_controller_specific_errors( else *status_ptr = SAS_ABORTED_TASK; - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); *complete_to_host_ptr = isci_perform_normal_io_completion; break; @@ -2397,11 +2397,11 @@ static void isci_request_handle_controller_specific_errors( *status_ptr = SAM_STAT_TASK_ABORTED; if (task->task_proto == SAS_PROTOCOL_SMP) { - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); *complete_to_host_ptr = isci_perform_normal_io_completion; } else { - request->complete_in_target = false; + clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); *complete_to_host_ptr = isci_perform_error_io_completion; } @@ -2552,7 +2552,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * * The target is still there (since the TMF was successful). */ - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); response = SAS_TASK_COMPLETE; /* See if the device has been/is being stopped. Note @@ -2579,7 +2579,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * Aborting also means an external thread is explicitly managing * this request, so that we do not complete it up the stack. */ - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); response = SAS_TASK_UNDELIVERED; if (!idev) @@ -2605,7 +2605,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * the device (reset, tear down, etc.), and the I/O needs * to be completed up the stack. */ - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); response = SAS_TASK_UNDELIVERED; /* See if the device has been/is being stopped. Note @@ -2675,7 +2675,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, /* use the task status set in the task struct by the * isci_request_process_response_iu call. */ - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); response = task->task_status.resp; status = task->task_status.stat; break; @@ -2685,7 +2685,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, response = SAS_TASK_COMPLETE; status = SAM_STAT_GOOD; - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); if (task->task_proto == SAS_PROTOCOL_SMP) { void *rsp = &request->sci.smp.rsp; @@ -2737,7 +2737,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, /* The request was terminated explicitly. No handling * is needed in the SCSI error handler path. */ - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); response = SAS_TASK_UNDELIVERED; /* See if the device has been/is being stopped. Note @@ -2777,7 +2777,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, status = SAM_STAT_TASK_ABORTED; complete_to_host = isci_perform_error_io_completion; - request->complete_in_target = false; + clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); break; case SCI_FAILURE_RETRY_REQUIRED: @@ -2790,7 +2790,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, status = SAS_ABORTED_TASK; complete_to_host = isci_perform_normal_io_completion; - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); break; @@ -2813,10 +2813,10 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, status = SAS_ABORTED_TASK; if (SAS_PROTOCOL_SMP == task->task_proto) { - request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); complete_to_host = isci_perform_normal_io_completion; } else { - request->complete_in_target = false; + clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); complete_to_host = isci_perform_error_io_completion; } break; @@ -2870,7 +2870,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * terminated again, and to cause any calls into abort * task to recognize the already completed case. */ - request->terminated = true; + set_bit(IREQ_TERMINATED, &request->flags); } static void scic_sds_request_started_state_enter(struct sci_base_state_machine *sm) @@ -2919,7 +2919,7 @@ static void scic_sds_request_completed_state_enter(struct sci_base_state_machine struct isci_request *ireq = sci_req_to_ireq(sci_req); /* Tell the SCI_USER that the IO request is complete */ - if (sci_req->is_task_management_request == false) + if (!test_bit(IREQ_TMF, &ireq->flags)) isci_request_io_request_complete(ihost, ireq, sci_req->sci_status); else @@ -3032,8 +3032,6 @@ scic_sds_general_request_construct(struct scic_sds_controller *scic, sci_req->scu_status = 0; sci_req->post_context = 0xFFFFFFFF; sci_req->tc = &scic->task_context_table[ISCI_TAG_TCI(io_tag)]; - - sci_req->is_task_management_request = false; WARN_ONCE(io_tag == SCI_CONTROLLER_INVALID_IO_TAG, "straggling invalid tag usage\n"); } @@ -3077,7 +3075,7 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { - sci_req->is_task_management_request = true; + set_bit(IREQ_TMF, &sci_req_to_ireq(sci_req)->flags); memset(sci_req->tc, 0, sizeof(struct scu_task_context)); } else status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; @@ -3379,12 +3377,8 @@ static struct isci_request *isci_request_alloc_core(struct isci_host *ihost, ireq->request_daddr = handle; ireq->isci_host = ihost; ireq->io_request_completion = NULL; - ireq->terminated = false; - + ireq->flags = 0; ireq->num_sg_entries = 0; - - ireq->complete_in_target = false; - INIT_LIST_HEAD(&ireq->completed_node); INIT_LIST_HEAD(&ireq->dev_node); @@ -3496,7 +3490,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide * hardware, so clear the request handle * here so no terminations will be done. */ - ireq->terminated = true; + set_bit(IREQ_TERMINATED, &ireq->flags); isci_request_change_state(ireq, completed); } spin_unlock_irqrestore(&ihost->scic_lock, flags); diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 8c77c4cbe04a..f440e421ea0e 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -209,12 +209,6 @@ struct scic_sds_request { #define SCU_SGL_SIZE ((SCI_MAX_SCATTER_GATHER_ELEMENTS + 1) / 2) struct scu_sgl_element_pair sg_table[SCU_SGL_SIZE] __attribute__ ((aligned(32))); - /* - * This field indicates if this request is a task management request or - * normal IO request. - */ - bool is_task_management_request; - /* * This field is a pointer to the stored rx frame data. It is used in * STP internal requests and SMP response frames. If this field is @@ -260,8 +254,10 @@ struct isci_request { enum isci_request_status status; enum task_type ttype; unsigned short io_tag; - bool complete_in_target; - bool terminated; + #define IREQ_COMPLETE_IN_TARGET 0 + #define IREQ_TERMINATED 1 + #define IREQ_TMF 2 + unsigned long flags; union ttype_ptr_union { struct sas_task *io_task_ptr; /* When ttype==io_task */ diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 22f6fe171111..d1a46710f4a7 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -558,15 +558,15 @@ static void isci_terminate_request_core( : NULL; /* Note that we are not going to control - * the target to abort the request. - */ - isci_request->complete_in_target = true; + * the target to abort the request. + */ + set_bit(IREQ_COMPLETE_IN_TARGET, &isci_request->flags); /* Make sure the request wasn't just sitting around signalling * device condition (if the request handle is NULL, then the * request completed but needed additional handling here). */ - if (!isci_request->terminated) { + if (!test_bit(IREQ_TERMINATED, &isci_request->flags)) { was_terminated = true; needs_cleanup_handling = true; status = scic_controller_terminate_request( @@ -609,7 +609,7 @@ static void isci_terminate_request_core( flags); /* Check for state changes. */ - if (!isci_request->terminated) { + if (!test_bit(IREQ_TERMINATED, &isci_request->flags)) { /* The best we can do is to have the * request die a silent death if it @@ -1098,9 +1098,8 @@ int isci_task_abort_task(struct sas_task *task) ret = TMF_RESP_FUNC_COMPLETE; goto out; } - if ((task->task_proto == SAS_PROTOCOL_SMP) - || old_request->complete_in_target - ) { + if (task->task_proto == SAS_PROTOCOL_SMP || + test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) { spin_unlock_irqrestore(&isci_host->scic_lock, flags); @@ -1108,7 +1107,7 @@ int isci_task_abort_task(struct sas_task *task) "%s: SMP request (%d)" " or complete_in_target (%d), thus no TMF\n", __func__, (task->task_proto == SAS_PROTOCOL_SMP), - old_request->complete_in_target); + test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)); /* Set the state on the task. */ isci_task_all_done(task); @@ -1136,7 +1135,7 @@ int isci_task_abort_task(struct sas_task *task) __func__); } if (ret == TMF_RESP_FUNC_COMPLETE) { - old_request->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags); /* Clean up the request on our side, and wait for the aborted * I/O to complete. @@ -1252,7 +1251,7 @@ isci_task_request_complete(struct isci_host *ihost, isci_request_change_state(ireq, completed); tmf->status = completion_status; - ireq->complete_in_target = true; + set_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags); if (tmf->proto == SAS_PROTOCOL_SSP) { memcpy(&tmf->resp.resp_iu, @@ -1271,7 +1270,7 @@ isci_task_request_complete(struct isci_host *ihost, /* set the 'terminated' flag handle to make sure it cannot be terminated * or completed again. */ - ireq->terminated = true;; + set_bit(IREQ_TERMINATED, &ireq->flags); isci_request_change_state(ireq, unallocated); list_del_init(&ireq->dev_node); -- cgit v1.2.3 From db0562509800a2d4cb5cb14a66413c30484f165c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 17 Jun 2011 14:18:39 -0700 Subject: isci: preallocate requests the dma_pool interface is optimized for object_size << page_size which is not the case with isci_request objects and the dma_pool routines show up in the top of the profile. The old io_request_table which tracked whether tci slots were in-flight or not is replaced with an IREQ_ACTIVE flag per request. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 70 ++++++++++++++++-------------- drivers/scsi/isci/host.h | 11 +---- drivers/scsi/isci/remote_device.c | 9 ++-- drivers/scsi/isci/request.c | 89 ++++++++++++--------------------------- drivers/scsi/isci/request.h | 26 +++--------- drivers/scsi/isci/task.c | 19 +++------ 6 files changed, 85 insertions(+), 139 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index c99fab53dd0c..0884ae3253e5 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -255,14 +255,14 @@ static bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) static void scic_sds_controller_task_completion(struct scic_sds_controller *scic, u32 completion_entry) { - u32 index; - struct scic_sds_request *sci_req; - - index = SCU_GET_COMPLETION_INDEX(completion_entry); - sci_req = scic->io_request_table[index]; + u32 index = SCU_GET_COMPLETION_INDEX(completion_entry); + struct isci_host *ihost = scic_to_ihost(scic); + struct isci_request *ireq = ihost->reqs[index]; + struct scic_sds_request *sci_req = &ireq->sci; /* Make sure that we really want to process this IO request */ - if (sci_req && sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && + if (test_bit(IREQ_ACTIVE, &ireq->flags) && + sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && ISCI_TAG_SEQ(sci_req->io_tag) == scic->io_request_sequence[index]) /* Yep this is a valid io request pass it along to the io request handler */ scic_sds_io_request_tc_completion(sci_req, completion_entry); @@ -280,7 +280,7 @@ static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic switch (scu_get_command_request_type(completion_entry)) { case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: - io_request = scic->io_request_table[index]; + io_request = &scic_to_ihost(scic)->reqs[index]->sci; dev_warn(scic_to_dev(scic), "%s: SCIC SDS Completion type SDMA %x for io request " "%p\n", @@ -418,7 +418,7 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci break; case SCU_EVENT_TYPE_TRANSPORT_ERROR: - io_request = scic->io_request_table[index]; + io_request = &ihost->reqs[index]->sci; scic_sds_io_request_event_handler(io_request, completion_entry); break; @@ -426,7 +426,7 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci switch (scu_get_event_specifier(completion_entry)) { case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: - io_request = scic->io_request_table[index]; + io_request = &ihost->reqs[index]->sci; if (io_request != NULL) scic_sds_io_request_event_handler(io_request, completion_entry); else @@ -1187,9 +1187,6 @@ static void isci_host_completion_routine(unsigned long data) spin_lock_irq(&isci_host->scic_lock); isci_free_tag(isci_host, request->sci.io_tag); spin_unlock_irq(&isci_host->scic_lock); - - /* Free the request object. */ - isci_request_free(isci_host, request); } list_for_each_entry_safe(request, next_request, &errored_request_list, completed_node) { @@ -1227,9 +1224,6 @@ static void isci_host_completion_routine(unsigned long data) list_del_init(&request->dev_node); isci_free_tag(isci_host, request->sci.io_tag); spin_unlock_irq(&isci_host->scic_lock); - - /* Free the request object. */ - isci_request_free(isci_host, request); } } @@ -2469,13 +2463,6 @@ int isci_host_init(struct isci_host *isci_host) if (err) return err; - isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev, - sizeof(struct isci_request), - SLAB_HWCACHE_ALIGN, 0); - - if (!isci_host->dma_pool) - return -ENOMEM; - for (i = 0; i < SCI_MAX_PORTS; i++) isci_port_init(&isci_host->ports[i], isci_host, i); @@ -2489,6 +2476,25 @@ int isci_host_init(struct isci_host *isci_host) INIT_LIST_HEAD(&idev->node); } + for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) { + struct isci_request *ireq; + dma_addr_t dma; + + ireq = dmam_alloc_coherent(&isci_host->pdev->dev, + sizeof(struct isci_request), &dma, + GFP_KERNEL); + if (!ireq) + return -ENOMEM; + + ireq->sci.tc = &isci_host->sci.task_context_table[i]; + ireq->sci.owning_controller = &isci_host->sci; + spin_lock_init(&ireq->state_lock); + ireq->request_daddr = dma; + ireq->isci_host = isci_host; + + isci_host->reqs[i] = ireq; + } + return 0; } @@ -2602,12 +2608,13 @@ struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, u task_index = ISCI_TAG_TCI(io_tag); if (task_index < scic->task_context_entries) { - if (scic->io_request_table[task_index] != NULL) { + struct isci_request *ireq = scic_to_ihost(scic)->reqs[task_index]; + + if (test_bit(IREQ_ACTIVE, &ireq->flags)) { task_sequence = ISCI_TAG_SEQ(io_tag); - if (task_sequence == scic->io_request_sequence[task_index]) { - return scic->io_request_table[task_index]; - } + if (task_sequence == scic->io_request_sequence[task_index]) + return &ireq->sci; } } @@ -2820,7 +2827,7 @@ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, if (status != SCI_SUCCESS) return status; - scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; + set_bit(IREQ_ACTIVE, &sci_req_to_ireq(req)->flags); scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); return SCI_SUCCESS; } @@ -2897,7 +2904,7 @@ enum sci_status scic_controller_complete_io( return status; index = ISCI_TAG_TCI(request->io_tag); - scic->io_request_table[index] = NULL; + clear_bit(IREQ_ACTIVE, &sci_req_to_ireq(request)->flags); return SCI_SUCCESS; default: dev_warn(scic_to_dev(scic), "invalid state to complete I/O"); @@ -2915,7 +2922,7 @@ enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) return SCI_FAILURE_INVALID_STATE; } - scic->io_request_table[ISCI_TAG_TCI(sci_req->io_tag)] = sci_req; + set_bit(IREQ_ACTIVE, &sci_req_to_ireq(sci_req)->flags); scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req)); return SCI_SUCCESS; } @@ -2934,6 +2941,7 @@ enum sci_task_status scic_controller_start_task( struct scic_sds_remote_device *rdev, struct scic_sds_request *req) { + struct isci_request *ireq = sci_req_to_ireq(req); enum sci_status status; if (scic->sm.current_state_id != SCIC_READY) { @@ -2947,7 +2955,7 @@ enum sci_task_status scic_controller_start_task( status = scic_sds_remote_device_start_task(scic, rdev, req); switch (status) { case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: - scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; + set_bit(IREQ_ACTIVE, &ireq->flags); /* * We will let framework know this task request started successfully, @@ -2956,7 +2964,7 @@ enum sci_task_status scic_controller_start_task( */ return SCI_SUCCESS; case SCI_SUCCESS: - scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; + set_bit(IREQ_ACTIVE, &ireq->flags); scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index d8164f5d7988..446fade19b3a 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -165,14 +165,6 @@ struct scic_sds_controller { */ struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; - /** - * This field is the array of IO request objects that are currently active for - * this controller object. This table is used as a fast lookup of the io - * request object that need to handle completion queue notifications. The - * table is TCi based. - */ - struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS]; - /** * This field is the free RNi data structure */ @@ -298,7 +290,6 @@ struct isci_host { union scic_oem_parameters oem_parameters; int id; /* unique within a given pci device */ - struct dma_pool *dma_pool; struct isci_phy phys[SCI_MAX_PHYS]; struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ struct sas_ha_struct sas_ha; @@ -315,7 +306,7 @@ struct isci_host { struct list_head requests_to_complete; struct list_head requests_to_errorback; spinlock_t scic_lock; - + struct isci_request *reqs[SCI_MAX_IO_REQUESTS]; struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES]; }; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index c5ce0f0f3645..5a86bb1e96df 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -136,16 +136,19 @@ static void rnc_destruct_done(void *_dev) static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds_remote_device *sci_dev) { struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + struct isci_host *ihost = scic_to_ihost(scic); u32 i, request_count = sci_dev->started_request_count; enum sci_status status = SCI_SUCCESS; for (i = 0; i < SCI_MAX_IO_REQUESTS && i < request_count; i++) { - struct scic_sds_request *sci_req; + struct isci_request *ireq = ihost->reqs[i]; + struct scic_sds_request *sci_req = &ireq->sci; enum sci_status s; - sci_req = scic->io_request_table[i]; - if (!sci_req || sci_req->target_device != sci_dev) + if (!test_bit(IREQ_ACTIVE, &ireq->flags) || + sci_req->target_device != sci_dev) continue; + s = scic_controller_terminate_request(scic, sci_dev, sci_req); if (s != SCI_SUCCESS) status = s; diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 27376ba22483..3c7ed4e61b4a 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -3017,13 +3017,10 @@ static const struct sci_base_state scic_sds_request_state_table[] = { static void scic_sds_general_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - u16 io_tag, struct scic_sds_request *sci_req) { sci_init_sm(&sci_req->sm, scic_sds_request_state_table, SCI_REQ_INIT); - sci_req->io_tag = io_tag; - sci_req->owning_controller = scic; sci_req->target_device = sci_dev; sci_req->protocol = SCIC_NO_PROTOCOL; sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; @@ -3031,20 +3028,18 @@ scic_sds_general_request_construct(struct scic_sds_controller *scic, sci_req->sci_status = SCI_SUCCESS; sci_req->scu_status = 0; sci_req->post_context = 0xFFFFFFFF; - sci_req->tc = &scic->task_context_table[ISCI_TAG_TCI(io_tag)]; - WARN_ONCE(io_tag == SCI_CONTROLLER_INVALID_IO_TAG, "straggling invalid tag usage\n"); } static enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - u16 io_tag, struct scic_sds_request *sci_req) + struct scic_sds_request *sci_req) { struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); + scic_sds_general_request_construct(scic, sci_dev, sci_req); if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; @@ -3071,7 +3066,7 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); + scic_sds_general_request_construct(scic, sci_dev, sci_req); if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { @@ -3291,8 +3286,7 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) */ static enum sci_status isci_io_request_build(struct isci_host *isci_host, struct isci_request *request, - struct isci_remote_device *isci_device, - u16 tag) + struct isci_remote_device *isci_device) { enum sci_status status = SCI_SUCCESS; struct sas_task *task = isci_request_access_task(request); @@ -3325,11 +3319,8 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, return SCI_FAILURE_INSUFFICIENT_RESOURCES; } - /* build the common request object. For now, - * we will let the core allocate the IO tag. - */ status = scic_io_request_construct(&isci_host->sci, sci_device, - tag, &request->sci); + &request->sci); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -3359,65 +3350,51 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, return SCI_SUCCESS; } -static struct isci_request *isci_request_alloc_core(struct isci_host *ihost, - gfp_t gfp_flags) +static struct isci_request *isci_request_from_tag(struct isci_host *ihost, u16 tag) { - dma_addr_t handle; struct isci_request *ireq; - ireq = dma_pool_alloc(ihost->dma_pool, gfp_flags, &handle); - if (!ireq) { - dev_warn(&ihost->pdev->dev, - "%s: dma_pool_alloc returned NULL\n", __func__); - return NULL; - } - - /* initialize the request object. */ - spin_lock_init(&ireq->state_lock); - ireq->request_daddr = handle; - ireq->isci_host = ihost; + ireq = ihost->reqs[ISCI_TAG_TCI(tag)]; + ireq->sci.io_tag = tag; ireq->io_request_completion = NULL; ireq->flags = 0; ireq->num_sg_entries = 0; INIT_LIST_HEAD(&ireq->completed_node); INIT_LIST_HEAD(&ireq->dev_node); - isci_request_change_state(ireq, allocated); return ireq; } -static struct isci_request *isci_request_alloc_io(struct isci_host *ihost, - struct sas_task *task, - gfp_t gfp_flags) +static struct isci_request *isci_io_request_from_tag(struct isci_host *ihost, + struct sas_task *task, + u16 tag) { struct isci_request *ireq; - ireq = isci_request_alloc_core(ihost, gfp_flags); - if (ireq) { - ireq->ttype_ptr.io_task_ptr = task; - ireq->ttype = io_task; - task->lldd_task = ireq; - } + ireq = isci_request_from_tag(ihost, tag); + ireq->ttype_ptr.io_task_ptr = task; + ireq->ttype = io_task; + task->lldd_task = ireq; + return ireq; } -struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, - struct isci_tmf *isci_tmf, - gfp_t gfp_flags) +struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost, + struct isci_tmf *isci_tmf, + u16 tag) { struct isci_request *ireq; - ireq = isci_request_alloc_core(ihost, gfp_flags); - if (ireq) { - ireq->ttype_ptr.tmf_task_ptr = isci_tmf; - ireq->ttype = tmf_task; - } + ireq = isci_request_from_tag(ihost, tag); + ireq->ttype_ptr.tmf_task_ptr = isci_tmf; + ireq->ttype = tmf_task; + return ireq; } int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, - struct sas_task *task, u16 tag, gfp_t gfp_flags) + struct sas_task *task, u16 tag) { enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; struct isci_request *ireq; @@ -3425,17 +3402,15 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide int ret = 0; /* do common allocation and init of request object. */ - ireq = isci_request_alloc_io(ihost, task, gfp_flags); - if (!ireq) - goto out; + ireq = isci_io_request_from_tag(ihost, task, tag); - status = isci_io_request_build(ihost, ireq, idev, tag); + status = isci_io_request_build(ihost, ireq, idev); if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, "%s: request_construct failed - status = 0x%x\n", __func__, status); - goto out; + return status; } spin_lock_irqsave(&ihost->scic_lock, flags); @@ -3468,7 +3443,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide "%s: failed request start (0x%x)\n", __func__, status); spin_unlock_irqrestore(&ihost->scic_lock, flags); - goto out; + return status; } /* Either I/O started OK, or the core has signaled that @@ -3518,13 +3493,5 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide status = SCI_SUCCESS; } - out: - if (status != SCI_SUCCESS) { - /* release dma memory on failure. */ - isci_request_free(ihost, ireq); - ireq = NULL; - ret = SCI_FAILURE; - } - return ret; } diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index f440e421ea0e..7628decbd535 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -257,6 +257,7 @@ struct isci_request { #define IREQ_COMPLETE_IN_TARGET 0 #define IREQ_TERMINATED 1 #define IREQ_TMF 2 + #define IREQ_ACTIVE 3 unsigned long flags; union ttype_ptr_union { @@ -590,33 +591,16 @@ isci_request_change_started_to_aborted(struct isci_request *isci_request, completion_ptr, aborted); } -/** - * isci_request_free() - This function frees the request object. - * @isci_host: This parameter specifies the ISCI host object - * @isci_request: This parameter points to the isci_request object - * - */ -static inline void isci_request_free(struct isci_host *isci_host, - struct isci_request *isci_request) -{ - if (!isci_request) - return; - - /* release the dma memory if we fail. */ - dma_pool_free(isci_host->dma_pool, - isci_request, - isci_request->request_daddr); -} #define isci_request_access_task(req) ((req)->ttype_ptr.io_task_ptr) #define isci_request_access_tmf(req) ((req)->ttype_ptr.tmf_task_ptr) -struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, - struct isci_tmf *isci_tmf, - gfp_t gfp_flags); +struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost, + struct isci_tmf *isci_tmf, + u16 tag); int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, - struct sas_task *task, u16 tag, gfp_t gfp_flags); + struct sas_task *task, u16 tag); void isci_terminate_pending_requests(struct isci_host *ihost, struct isci_remote_device *idev); enum sci_status diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index d1a46710f4a7..d2dba8354899 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -203,7 +203,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) spin_unlock_irqrestore(&task->task_state_lock, flags); /* build and send the request. */ - status = isci_request_execute(ihost, idev, task, tag, gfp_flags); + status = isci_request_execute(ihost, idev, task, tag); if (status != SCI_SUCCESS) { @@ -252,7 +252,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, dev = idev->domain_dev; /* do common allocation and init of request object. */ - ireq = isci_request_alloc_tmf(ihost, isci_tmf, GFP_ATOMIC); + ireq = isci_tmf_request_from_tag(ihost, isci_tmf, tag); if (!ireq) return NULL; @@ -266,7 +266,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, "status = 0x%x\n", __func__, status); - goto errout; + return NULL; } /* XXX convert to get this from task->tproto like other drivers */ @@ -274,7 +274,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, isci_tmf->proto = SAS_PROTOCOL_SSP; status = scic_task_request_construct_ssp(&ireq->sci); if (status != SCI_SUCCESS) - goto errout; + return NULL; } if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { @@ -282,12 +282,9 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, status = isci_sata_management_task_request_build(ireq); if (status != SCI_SUCCESS) - goto errout; + return NULL; } return ireq; - errout: - isci_request_free(ihost, ireq); - return NULL; } int isci_task_execute_tmf(struct isci_host *ihost, @@ -349,7 +346,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, status, ireq); spin_unlock_irqrestore(&ihost->scic_lock, flags); - goto err_ireq; + goto err_tci; } if (tmf->cb_state_func != NULL) @@ -401,8 +398,6 @@ int isci_task_execute_tmf(struct isci_host *ihost, return ret; - err_ireq: - isci_request_free(ihost, ireq); err_tci: spin_lock_irqsave(&ihost->scic_lock, flags); isci_tci_free(ihost, ISCI_TAG_TCI(tag)); @@ -516,8 +511,6 @@ static void isci_request_cleanup_completed_loiterer( spin_lock_irqsave(&isci_host->scic_lock, flags); list_del_init(&isci_request->dev_node); spin_unlock_irqrestore(&isci_host->scic_lock, flags); - - isci_request_free(isci_host, isci_request); } } -- cgit v1.2.3 From ba7cb22342a66505a831bb7e4541fef90e0193c9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 27 Jun 2011 11:56:41 -0700 Subject: isci: rename / clean up scic_sds_stp_request * Rename scic_sds_stp_request to isci_stp_request * Remove the unused fields and union indirection Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 147 ++++++++++++++++++++------------------------ drivers/scsi/isci/request.h | 84 +++++++------------------ 2 files changed, 89 insertions(+), 142 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 3c7ed4e61b4a..8520626b02fa 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -433,24 +433,20 @@ static enum sci_status scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, bool copy_rx_frame) { - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; - struct scic_sds_stp_pio_request *pio = &stp_req->type.pio; + struct isci_stp_request *stp_req = &sci_req->stp.req; scu_stp_raw_request_construct_task_context(sci_req); - pio->current_transfer_bytes = 0; - pio->ending_error = 0; - pio->ending_status = 0; - - pio->request_current.sgl_offset = 0; - pio->request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; + stp_req->status = 0; + stp_req->sgl.offset = 0; + stp_req->sgl.set = SCU_SGL_ELEMENT_PAIR_A; if (copy_rx_frame) { scic_sds_request_build_sgl(sci_req); - pio->request_current.sgl_index = 0; + stp_req->sgl.index = 0; } else { /* The user does not want the data copied to the SGL buffer location */ - pio->request_current.sgl_index = -1; + stp_req->sgl.index = -1; } return SCI_SUCCESS; @@ -1151,22 +1147,22 @@ void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *req, req->tc->type.stp.ncq_tag = ncq_tag; } -static struct scu_sgl_element *pio_sgl_next(struct scic_sds_stp_request *stp_req) +static struct scu_sgl_element *pio_sgl_next(struct isci_stp_request *stp_req) { struct scu_sgl_element *sgl; struct scu_sgl_element_pair *sgl_pair; struct scic_sds_request *sci_req = to_sci_req(stp_req); - struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current; + struct isci_stp_pio_sgl *pio_sgl = &stp_req->sgl; - sgl_pair = to_sgl_element_pair(sci_req, pio_sgl->sgl_index); + sgl_pair = to_sgl_element_pair(sci_req, pio_sgl->index); if (!sgl_pair) sgl = NULL; - else if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) { + else if (pio_sgl->set == SCU_SGL_ELEMENT_PAIR_A) { if (sgl_pair->B.address_lower == 0 && sgl_pair->B.address_upper == 0) { sgl = NULL; } else { - pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B; + pio_sgl->set = SCU_SGL_ELEMENT_PAIR_B; sgl = &sgl_pair->B; } } else { @@ -1174,9 +1170,9 @@ static struct scu_sgl_element *pio_sgl_next(struct scic_sds_stp_request *stp_req sgl_pair->next_pair_upper == 0) { sgl = NULL; } else { - pio_sgl->sgl_index++; - pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A; - sgl_pair = to_sgl_element_pair(sci_req, pio_sgl->sgl_index); + pio_sgl->index++; + pio_sgl->set = SCU_SGL_ELEMENT_PAIR_A; + sgl_pair = to_sgl_element_pair(sci_req, pio_sgl->index); sgl = &sgl_pair->A; } } @@ -1221,7 +1217,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( struct scic_sds_request *sci_req, u32 length) { - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct isci_stp_request *stp_req = &sci_req->stp.req; struct scu_task_context *task_context = sci_req->tc; struct scu_sgl_element_pair *sgl_pair; struct scu_sgl_element *current_sgl; @@ -1229,8 +1225,8 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( /* Recycle the TC and reconstruct it for sending out DATA FIS containing * for the data from current_sgl+offset for the input length */ - sgl_pair = to_sgl_element_pair(sci_req, stp_req->type.pio.request_current.sgl_index); - if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) + sgl_pair = to_sgl_element_pair(sci_req, stp_req->sgl.index); + if (stp_req->sgl.set == SCU_SGL_ELEMENT_PAIR_A) current_sgl = &sgl_pair->A; else current_sgl = &sgl_pair->B; @@ -1247,54 +1243,48 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct scic_sds_request *sci_req) { - - struct scu_sgl_element *current_sgl; - u32 sgl_offset; - u32 remaining_bytes_in_current_sgl = 0; - enum sci_status status = SCI_SUCCESS; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct isci_stp_request *stp_req = &sci_req->stp.req; struct scu_sgl_element_pair *sgl_pair; + struct scu_sgl_element *sgl; + enum sci_status status; + u32 offset; + u32 len = 0; - sgl_offset = stp_req->type.pio.request_current.sgl_offset; - sgl_pair = to_sgl_element_pair(sci_req, stp_req->type.pio.request_current.sgl_index); + offset = stp_req->sgl.offset; + sgl_pair = to_sgl_element_pair(sci_req, stp_req->sgl.index); if (WARN_ONCE(!sgl_pair, "%s: null sgl element", __func__)) return SCI_FAILURE; - if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { - current_sgl = &sgl_pair->A; - remaining_bytes_in_current_sgl = sgl_pair->A.length - sgl_offset; + if (stp_req->sgl.set == SCU_SGL_ELEMENT_PAIR_A) { + sgl = &sgl_pair->A; + len = sgl_pair->A.length - offset; } else { - current_sgl = &sgl_pair->B; - remaining_bytes_in_current_sgl = sgl_pair->B.length - sgl_offset; + sgl = &sgl_pair->B; + len = sgl_pair->B.length - offset; } - if (stp_req->type.pio.pio_transfer_bytes > 0) { - if (stp_req->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { - /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ - status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, remaining_bytes_in_current_sgl); - if (status == SCI_SUCCESS) { - stp_req->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; - - /* update the current sgl, sgl_offset and save for future */ - current_sgl = pio_sgl_next(stp_req); - sgl_offset = 0; - } - } else if (stp_req->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { - /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */ - scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->type.pio.pio_transfer_bytes); + if (stp_req->pio_len == 0) + return SCI_SUCCESS; - if (status == SCI_SUCCESS) { - /* Sgl offset will be adjusted and saved for future */ - sgl_offset += stp_req->type.pio.pio_transfer_bytes; - current_sgl->address_lower += stp_req->type.pio.pio_transfer_bytes; - stp_req->type.pio.pio_transfer_bytes = 0; - } - } + if (stp_req->pio_len >= len) { + status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, len); + if (status != SCI_SUCCESS) + return status; + stp_req->pio_len -= len; + + /* update the current sgl, offset and save for future */ + sgl = pio_sgl_next(stp_req); + offset = 0; + } else if (stp_req->pio_len < len) { + scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->pio_len); + + /* Sgl offset will be adjusted and saved for future */ + offset += stp_req->pio_len; + sgl->address_lower += stp_req->pio_len; + stp_req->pio_len = 0; } - if (status == SCI_SUCCESS) { - stp_req->type.pio.request_current.sgl_offset = sgl_offset; - } + stp_req->sgl.offset = offset; return status; } @@ -1309,7 +1299,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct sc * specified data region. enum sci_status */ static enum sci_status -scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req, +scic_sds_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req, u8 *data_buf, u32 len) { struct scic_sds_request *sci_req; @@ -1356,7 +1346,7 @@ scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *s * Copy the data buffer to the io request data region. enum sci_status */ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( - struct scic_sds_stp_request *sci_req, + struct isci_stp_request *stp_req, u8 *data_buffer) { enum sci_status status; @@ -1364,19 +1354,19 @@ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( /* * If there is less than 1K remaining in the transfer request * copy just the data for the transfer */ - if (sci_req->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { + if (stp_req->pio_len < SCU_MAX_FRAME_BUFFER_SIZE) { status = scic_sds_stp_request_pio_data_in_copy_data_buffer( - sci_req, data_buffer, sci_req->type.pio.pio_transfer_bytes); + stp_req, data_buffer, stp_req->pio_len); if (status == SCI_SUCCESS) - sci_req->type.pio.pio_transfer_bytes = 0; + stp_req->pio_len = 0; } else { /* We are transfering the whole frame so copy */ status = scic_sds_stp_request_pio_data_in_copy_data_buffer( - sci_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); + stp_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); if (status == SCI_SUCCESS) - sci_req->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; + stp_req->pio_len -= SCU_MAX_FRAME_BUFFER_SIZE; } return status; @@ -1419,18 +1409,18 @@ pio_data_out_tx_done_tc_event(struct scic_sds_request *sci_req, { enum sci_status status = SCI_SUCCESS; bool all_frames_transferred = false; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct isci_stp_request *stp_req = &sci_req->stp.req; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): /* Transmit data */ - if (stp_req->type.pio.pio_transfer_bytes != 0) { + if (stp_req->pio_len != 0) { status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); if (status == SCI_SUCCESS) { - if (stp_req->type.pio.pio_transfer_bytes == 0) + if (stp_req->pio_len == 0) all_frames_transferred = true; } - } else if (stp_req->type.pio.pio_transfer_bytes == 0) { + } else if (stp_req->pio_len == 0) { /* * this will happen if the all data is written at the * first time after the pio setup fis is received @@ -1507,7 +1497,7 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, u32 frame_index) { struct scic_sds_controller *scic = sci_req->owning_controller; - struct scic_sds_stp_request *stp_req = &sci_req->stp.req; + struct isci_stp_request *stp_req = &sci_req->stp.req; enum sci_base_request_states state; enum sci_status status; ssize_t word_cnt; @@ -1727,16 +1717,16 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, */ /* transfer_count: first 16bits in the 4th dword */ - stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff; + stp_req->pio_len = frame_buffer[3] & 0xffff; - /* ending_status: 4th byte in the 3rd dword */ - stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff; + /* status: 4th byte in the 3rd dword */ + stp_req->status = (frame_buffer[2] >> 24) & 0xff; scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, frame_header, frame_buffer); - sci_req->stp.rsp.status = stp_req->type.pio.ending_status; + sci_req->stp.rsp.status = stp_req->status; /* The next state is dependent on whether the * request was PIO Data-in or Data out @@ -1839,9 +1829,9 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, return status; } - if (stp_req->type.pio.request_current.sgl_index < 0) { + if (stp_req->sgl.index < 0) { sci_req->saved_rx_frame_index = frame_index; - stp_req->type.pio.pio_transfer_bytes = 0; + stp_req->pio_len = 0; } else { scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, frame_index, @@ -1857,11 +1847,10 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, /* Check for the end of the transfer, are there more * bytes remaining for this data transfer */ - if (status != SCI_SUCCESS || - stp_req->type.pio.pio_transfer_bytes != 0) + if (status != SCI_SUCCESS || stp_req->pio_len != 0) return status; - if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) { + if ((stp_req->status & ATA_BUSY) == 0) { scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 7628decbd535..7fd98531d1f2 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -89,67 +89,25 @@ enum sci_request_protocol { SCIC_STP_PROTOCOL }; /* XXX remove me, use sas_task.{dev|task_proto} instead */; -struct scic_sds_stp_request { - union { - u32 ncq; - - u32 udma; - - struct scic_sds_stp_pio_request { - /* - * Total transfer for the entire PIO request recorded - * at request constuction time. - * - * @todo Should we just decrement this value for each - * byte of data transitted or received to elemenate - * the current_transfer_bytes field? - */ - u32 total_transfer_bytes; - - /* - * Total number of bytes received/transmitted in data - * frames since the start of the IO request. At the - * end of the IO request this should equal the - * total_transfer_bytes. - */ - u32 current_transfer_bytes; - - /* - * The number of bytes requested in the in the PIO - * setup. - */ - u32 pio_transfer_bytes; - - /* - * PIO Setup ending status value to tell us if we need - * to wait for another FIS or if the transfer is - * complete. On the receipt of a D2H FIS this will be - * the status field of that FIS. - */ - u8 ending_status; - - /* - * On receipt of a D2H FIS this will be the ending - * error field if the ending_status has the - * SATA_STATUS_ERR bit set. - */ - u8 ending_error; - - struct scic_sds_request_pio_sgl { - int sgl_index; - u8 sgl_set; - u32 sgl_offset; - } request_current; - } pio; - - struct { - /* - * The number of bytes requested in the PIO setup - * before CDB data frame. - */ - u32 device_preferred_cdb_length; - } packet; - } type; +/** + * isci_stp_request - extra request infrastructure to handle pio/atapi protocol + * @pio_len - number of bytes requested at PIO setup + * @status - pio setup ending status value to tell us if we need + * to wait for another fis or if the transfer is complete. Upon + * receipt of a d2h fis this will be the status field of that fis. + * @sgl - track pio transfer progress as we iterate through the sgl + * @device_cdb_len - atapi device advertises it's transfer constraints at setup + */ +struct isci_stp_request { + u32 pio_len; + u8 status; + + struct isci_stp_pio_sgl { + int index; + u8 set; + u32 offset; + } sgl; + u32 device_cdb_len; }; struct scic_sds_request { @@ -235,14 +193,14 @@ struct scic_sds_request { } smp; struct { - struct scic_sds_stp_request req; + struct isci_stp_request req; struct host_to_dev_fis cmd; struct dev_to_host_fis rsp; } stp; }; }; -static inline struct scic_sds_request *to_sci_req(struct scic_sds_stp_request *stp_req) +static inline struct scic_sds_request *to_sci_req(struct isci_stp_request *stp_req) { struct scic_sds_request *sci_req; -- cgit v1.2.3 From 5076a1a97e2fa61c847a5fdd4b1991faf7716da6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 27 Jun 2011 14:57:03 -0700 Subject: isci: unify isci_request and scic_sds_request They are one in the same object so remove the distinction. The near duplicate fields (owning_controller, and isci_host) will be cleaned up after the scic_sds_contoller isci_host unification. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 98 ++--- drivers/scsi/isci/host.h | 16 +- drivers/scsi/isci/phy.c | 2 +- drivers/scsi/isci/port.c | 4 +- drivers/scsi/isci/port.h | 6 +- drivers/scsi/isci/remote_device.c | 92 +++-- drivers/scsi/isci/remote_device.h | 8 +- drivers/scsi/isci/remote_node_context.c | 4 +- drivers/scsi/isci/remote_node_context.h | 6 +- drivers/scsi/isci/request.c | 683 ++++++++++++++++---------------- drivers/scsi/isci/request.h | 184 +++------ drivers/scsi/isci/sata.c | 9 +- drivers/scsi/isci/task.c | 17 +- 13 files changed, 514 insertions(+), 615 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 0884ae3253e5..d91cd6d82747 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -258,21 +258,20 @@ static void scic_sds_controller_task_completion(struct scic_sds_controller *scic u32 index = SCU_GET_COMPLETION_INDEX(completion_entry); struct isci_host *ihost = scic_to_ihost(scic); struct isci_request *ireq = ihost->reqs[index]; - struct scic_sds_request *sci_req = &ireq->sci; /* Make sure that we really want to process this IO request */ if (test_bit(IREQ_ACTIVE, &ireq->flags) && - sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && - ISCI_TAG_SEQ(sci_req->io_tag) == scic->io_request_sequence[index]) + ireq->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && + ISCI_TAG_SEQ(ireq->io_tag) == scic->io_request_sequence[index]) /* Yep this is a valid io request pass it along to the io request handler */ - scic_sds_io_request_tc_completion(sci_req, completion_entry); + scic_sds_io_request_tc_completion(ireq, completion_entry); } static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic, u32 completion_entry) { u32 index; - struct scic_sds_request *io_request; + struct isci_request *ireq; struct scic_sds_remote_device *device; index = SCU_GET_COMPLETION_INDEX(completion_entry); @@ -280,41 +279,27 @@ static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic switch (scu_get_command_request_type(completion_entry)) { case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: - io_request = &scic_to_ihost(scic)->reqs[index]->sci; - dev_warn(scic_to_dev(scic), - "%s: SCIC SDS Completion type SDMA %x for io request " - "%p\n", - __func__, - completion_entry, - io_request); + ireq = scic_to_ihost(scic)->reqs[index]; + dev_warn(scic_to_dev(scic), "%s: %x for io request %p\n", + __func__, completion_entry, ireq); /* @todo For a post TC operation we need to fail the IO * request */ break; - case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: device = scic->device_table[index]; - dev_warn(scic_to_dev(scic), - "%s: SCIC SDS Completion type SDMA %x for remote " - "device %p\n", - __func__, - completion_entry, - device); + dev_warn(scic_to_dev(scic), "%s: %x for device %p\n", + __func__, completion_entry, device); /* @todo For a port RNC operation we need to fail the * device */ break; - default: - dev_warn(scic_to_dev(scic), - "%s: SCIC SDS Completion unknown SDMA completion " - "type %x\n", - __func__, - completion_entry); + dev_warn(scic_to_dev(scic), "%s: unknown completion type %x\n", + __func__, completion_entry); break; - } } @@ -385,8 +370,8 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci u32 completion_entry) { struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_request *io_request; struct scic_sds_remote_device *device; + struct isci_request *ireq; struct scic_sds_phy *phy; u32 index; @@ -418,17 +403,17 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci break; case SCU_EVENT_TYPE_TRANSPORT_ERROR: - io_request = &ihost->reqs[index]->sci; - scic_sds_io_request_event_handler(io_request, completion_entry); + ireq = ihost->reqs[index]; + scic_sds_io_request_event_handler(ireq, completion_entry); break; case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: switch (scu_get_event_specifier(completion_entry)) { case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: - io_request = &ihost->reqs[index]->sci; - if (io_request != NULL) - scic_sds_io_request_event_handler(io_request, completion_entry); + ireq = ihost->reqs[index]; + if (ireq != NULL) + scic_sds_io_request_event_handler(ireq, completion_entry); else dev_warn(scic_to_dev(scic), "%s: SCIC Controller 0x%p received " @@ -1185,7 +1170,7 @@ static void isci_host_completion_routine(unsigned long data) } spin_lock_irq(&isci_host->scic_lock); - isci_free_tag(isci_host, request->sci.io_tag); + isci_free_tag(isci_host, request->io_tag); spin_unlock_irq(&isci_host->scic_lock); } list_for_each_entry_safe(request, next_request, &errored_request_list, @@ -1222,7 +1207,7 @@ static void isci_host_completion_routine(unsigned long data) * of pending requests. */ list_del_init(&request->dev_node); - isci_free_tag(isci_host, request->sci.io_tag); + isci_free_tag(isci_host, request->io_tag); spin_unlock_irq(&isci_host->scic_lock); } } @@ -2486,8 +2471,8 @@ int isci_host_init(struct isci_host *isci_host) if (!ireq) return -ENOMEM; - ireq->sci.tc = &isci_host->sci.task_context_table[i]; - ireq->sci.owning_controller = &isci_host->sci; + ireq->tc = &isci_host->sci.task_context_table[i]; + ireq->owning_controller = &isci_host->sci; spin_lock_init(&ireq->state_lock); ireq->request_daddr = dma; ireq->isci_host = isci_host; @@ -2600,7 +2585,7 @@ void scic_sds_controller_post_request( writel(request, &scic->smu_registers->post_context_port); } -struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 io_tag) +struct isci_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 io_tag) { u16 task_index; u16 task_sequence; @@ -2614,7 +2599,7 @@ struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, u task_sequence = ISCI_TAG_SEQ(io_tag); if (task_sequence == scic->io_request_sequence[task_index]) - return &ireq->sci; + return ireq; } } @@ -2814,7 +2799,7 @@ enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag) */ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, struct scic_sds_remote_device *rdev, - struct scic_sds_request *req) + struct isci_request *ireq) { enum sci_status status; @@ -2823,12 +2808,12 @@ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, return SCI_FAILURE_INVALID_STATE; } - status = scic_sds_remote_device_start_io(scic, rdev, req); + status = scic_sds_remote_device_start_io(scic, rdev, ireq); if (status != SCI_SUCCESS) return status; - set_bit(IREQ_ACTIVE, &sci_req_to_ireq(req)->flags); - scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); + set_bit(IREQ_ACTIVE, &ireq->flags); + scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(ireq)); return SCI_SUCCESS; } @@ -2851,7 +2836,7 @@ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, enum sci_status scic_controller_terminate_request( struct scic_sds_controller *scic, struct scic_sds_remote_device *rdev, - struct scic_sds_request *req) + struct isci_request *ireq) { enum sci_status status; @@ -2861,7 +2846,7 @@ enum sci_status scic_controller_terminate_request( return SCI_FAILURE_INVALID_STATE; } - status = scic_sds_io_request_terminate(req); + status = scic_sds_io_request_terminate(ireq); if (status != SCI_SUCCESS) return status; @@ -2870,7 +2855,7 @@ enum sci_status scic_controller_terminate_request( * request sub-type. */ scic_sds_controller_post_request(scic, - scic_sds_request_get_post_context(req) | + scic_sds_request_get_post_context(ireq) | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); return SCI_SUCCESS; } @@ -2889,7 +2874,7 @@ enum sci_status scic_controller_terminate_request( enum sci_status scic_controller_complete_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *rdev, - struct scic_sds_request *request) + struct isci_request *ireq) { enum sci_status status; u16 index; @@ -2899,12 +2884,12 @@ enum sci_status scic_controller_complete_io( /* XXX: Implement this function */ return SCI_FAILURE; case SCIC_READY: - status = scic_sds_remote_device_complete_io(scic, rdev, request); + status = scic_sds_remote_device_complete_io(scic, rdev, ireq); if (status != SCI_SUCCESS) return status; - index = ISCI_TAG_TCI(request->io_tag); - clear_bit(IREQ_ACTIVE, &sci_req_to_ireq(request)->flags); + index = ISCI_TAG_TCI(ireq->io_tag); + clear_bit(IREQ_ACTIVE, &ireq->flags); return SCI_SUCCESS; default: dev_warn(scic_to_dev(scic), "invalid state to complete I/O"); @@ -2913,17 +2898,17 @@ enum sci_status scic_controller_complete_io( } -enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) +enum sci_status scic_controller_continue_io(struct isci_request *ireq) { - struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_controller *scic = ireq->owning_controller; if (scic->sm.current_state_id != SCIC_READY) { dev_warn(scic_to_dev(scic), "invalid state to continue I/O"); return SCI_FAILURE_INVALID_STATE; } - set_bit(IREQ_ACTIVE, &sci_req_to_ireq(sci_req)->flags); - scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req)); + set_bit(IREQ_ACTIVE, &ireq->flags); + scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(ireq)); return SCI_SUCCESS; } @@ -2939,9 +2924,8 @@ enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) enum sci_task_status scic_controller_start_task( struct scic_sds_controller *scic, struct scic_sds_remote_device *rdev, - struct scic_sds_request *req) + struct isci_request *ireq) { - struct isci_request *ireq = sci_req_to_ireq(req); enum sci_status status; if (scic->sm.current_state_id != SCIC_READY) { @@ -2952,7 +2936,7 @@ enum sci_task_status scic_controller_start_task( return SCI_TASK_FAILURE_INVALID_STATE; } - status = scic_sds_remote_device_start_task(scic, rdev, req); + status = scic_sds_remote_device_start_task(scic, rdev, ireq); switch (status) { case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: set_bit(IREQ_ACTIVE, &ireq->flags); @@ -2967,7 +2951,7 @@ enum sci_task_status scic_controller_start_task( set_bit(IREQ_ACTIVE, &ireq->flags); scic_sds_controller_post_request(scic, - scic_sds_request_get_post_context(req)); + scic_sds_request_get_post_context(ireq)); break; default: break; diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 446fade19b3a..0b26d25c19a9 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -64,7 +64,7 @@ #include "unsolicited_frame_control.h" #include "probe_roms.h" -struct scic_sds_request; +struct isci_request; struct scu_task_context; @@ -601,7 +601,7 @@ union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffe struct scic_sds_controller *scic, u16 node_id); -struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, +struct isci_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 io_tag); void scic_sds_controller_power_control_queue_insert( @@ -628,11 +628,11 @@ void scic_sds_controller_remote_device_stopped( void scic_sds_controller_copy_task_context( struct scic_sds_controller *scic, - struct scic_sds_request *this_request); + struct isci_request *ireq); void scic_sds_controller_register_setup(struct scic_sds_controller *scic); -enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req); +enum sci_status scic_controller_continue_io(struct isci_request *ireq); int isci_host_scan_finished(struct Scsi_Host *, unsigned long); void isci_host_scan_start(struct Scsi_Host *); u16 isci_alloc_tag(struct isci_host *ihost); @@ -665,22 +665,22 @@ void scic_controller_disable_interrupts( enum sci_status scic_controller_start_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, - struct scic_sds_request *io_request); + struct isci_request *ireq); enum sci_task_status scic_controller_start_task( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, - struct scic_sds_request *task_request); + struct isci_request *ireq); enum sci_status scic_controller_terminate_request( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, - struct scic_sds_request *request); + struct isci_request *ireq); enum sci_status scic_controller_complete_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, - struct scic_sds_request *io_request); + struct isci_request *ireq); void scic_sds_port_configuration_agent_construct( struct scic_sds_port_configuration_agent *port_agent); diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index c01d76210aa2..98d93aeea75d 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -983,7 +983,7 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - + } static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_state_machine *sm) diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 0e84e29335dd..bd091549b4f7 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1611,7 +1611,7 @@ enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, enum sci_status scic_sds_port_start_io(struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { enum scic_sds_port_states state; @@ -1631,7 +1631,7 @@ enum sci_status scic_sds_port_start_io(struct scic_sds_port *sci_port, enum sci_status scic_sds_port_complete_io(struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { enum scic_sds_port_states state; diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index a44e541914f5..668f3a14cd70 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -354,17 +354,17 @@ enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, struct scic_sds_phy *sci_phy); -struct scic_sds_request; +struct isci_request; struct scic_sds_remote_device; enum sci_status scic_sds_port_start_io( struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req); + struct isci_request *ireq); enum sci_status scic_sds_port_complete_io( struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req); + struct isci_request *ireq); enum sas_linkrate scic_sds_port_get_max_allowed_speed( struct scic_sds_port *sci_port); diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 5a86bb1e96df..c7cb0c54df57 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -94,7 +94,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, scic_controller_terminate_request(&ihost->sci, &idev->sci, - &ireq->sci); + ireq); } /* Fall through into the default case... */ default: @@ -142,14 +142,13 @@ static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds for (i = 0; i < SCI_MAX_IO_REQUESTS && i < request_count; i++) { struct isci_request *ireq = ihost->reqs[i]; - struct scic_sds_request *sci_req = &ireq->sci; enum sci_status s; if (!test_bit(IREQ_ACTIVE, &ireq->flags) || - sci_req->target_device != sci_dev) + ireq->target_device != sci_dev) continue; - s = scic_controller_terminate_request(scic, sci_dev, sci_req); + s = scic_controller_terminate_request(scic, sci_dev, ireq); if (s != SCI_SUCCESS) status = s; } @@ -299,7 +298,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi case SCI_DEV_STOPPING: case SCI_DEV_FAILED: case SCI_DEV_RESETTING: { - struct scic_sds_request *sci_req; + struct isci_request *ireq; struct ssp_frame_hdr hdr; void *frame_header; ssize_t word_cnt; @@ -313,10 +312,10 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi word_cnt = sizeof(hdr) / sizeof(u32); sci_swab32_cpy(&hdr, frame_header, word_cnt); - sci_req = scic_request_by_tag(scic, be16_to_cpu(hdr.tag)); - if (sci_req && sci_req->target_device == sci_dev) { + ireq = scic_request_by_tag(scic, be16_to_cpu(hdr.tag)); + if (ireq && ireq->target_device == sci_dev) { /* The IO request is now in charge of releasing the frame */ - status = scic_sds_io_request_frame_handler(sci_req, frame_index); + status = scic_sds_io_request_frame_handler(ireq, frame_index); } else { /* We could not map this tag to a valid IO * request Just toss the frame and continue @@ -448,14 +447,14 @@ enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_devi } static void scic_sds_remote_device_start_request(struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req, + struct isci_request *ireq, enum sci_status status) { struct scic_sds_port *sci_port = sci_dev->owning_port; /* cleanup requests that failed after starting on the port */ if (status != SCI_SUCCESS) - scic_sds_port_complete_io(sci_port, sci_dev, sci_req); + scic_sds_port_complete_io(sci_port, sci_dev, ireq); else { kref_get(&sci_dev_to_idev(sci_dev)->kref); scic_sds_remote_device_increment_request_count(sci_dev); @@ -464,12 +463,11 @@ static void scic_sds_remote_device_start_request(struct scic_sds_remote_device * enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_port *sci_port = sci_dev->owning_port; - struct isci_request *ireq = sci_req_to_ireq(sci_req); enum sci_status status; switch (state) { @@ -491,15 +489,15 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic * successful it will start the request for the port object then * increment its own request count. */ - status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + status = scic_sds_port_start_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(sci_req); + status = scic_sds_request_start(ireq); break; case SCI_STP_DEV_IDLE: { /* handle the start io operation for a sata device that is in @@ -513,22 +511,22 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic enum scic_sds_remote_device_states new_state; struct sas_task *task = isci_request_access_task(ireq); - status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + status = scic_sds_port_start_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(sci_req); + status = scic_sds_request_start(ireq); if (status != SCI_SUCCESS) break; if (task->ata_task.use_ncq) new_state = SCI_STP_DEV_NCQ; else { - sci_dev->working_request = sci_req; + sci_dev->working_request = ireq; new_state = SCI_STP_DEV_CMD; } sci_change_state(sm, new_state); @@ -538,15 +536,15 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic struct sas_task *task = isci_request_access_task(ireq); if (task->ata_task.use_ncq) { - status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + status = scic_sds_port_start_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(sci_req); + status = scic_sds_request_start(ireq); } else return SCI_FAILURE_INVALID_STATE; break; @@ -554,19 +552,19 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic case SCI_STP_DEV_AWAIT_RESET: return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; case SCI_SMP_DEV_IDLE: - status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + status = scic_sds_port_start_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req); + status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(sci_req); + status = scic_sds_request_start(ireq); if (status != SCI_SUCCESS) break; - sci_dev->working_request = sci_req; + sci_dev->working_request = ireq; sci_change_state(&sci_dev->sm, SCI_SMP_DEV_CMD); break; case SCI_STP_DEV_CMD: @@ -577,21 +575,21 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic return SCI_FAILURE_INVALID_STATE; } - scic_sds_remote_device_start_request(sci_dev, sci_req, status); + scic_sds_remote_device_start_request(sci_dev, ireq, status); return status; } static enum sci_status common_complete_io(struct scic_sds_port *sci_port, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { enum sci_status status; - status = scic_sds_request_complete(sci_req); + status = scic_sds_request_complete(ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_port_complete_io(sci_port, sci_dev, sci_req); + status = scic_sds_port_complete_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) return status; @@ -601,7 +599,7 @@ static enum sci_status common_complete_io(struct scic_sds_port *sci_port, enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; @@ -623,16 +621,16 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s case SCI_DEV_READY: case SCI_STP_DEV_AWAIT_RESET: case SCI_DEV_RESETTING: - status = common_complete_io(sci_port, sci_dev, sci_req); + status = common_complete_io(sci_port, sci_dev, ireq); break; case SCI_STP_DEV_CMD: case SCI_STP_DEV_NCQ: case SCI_STP_DEV_NCQ_ERROR: - status = common_complete_io(sci_port, sci_dev, sci_req); + status = common_complete_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) break; - if (sci_req->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { + if (ireq->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { /* This request causes hardware error, device needs to be Lun Reset. * So here we force the state machine to IDLE state so the rest IOs * can reach RNC state handler, these IOs will be completed by RNC with @@ -643,13 +641,13 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s sci_change_state(sm, SCI_STP_DEV_IDLE); break; case SCI_SMP_DEV_CMD: - status = common_complete_io(sci_port, sci_dev, sci_req); + status = common_complete_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) break; sci_change_state(sm, SCI_SMP_DEV_IDLE); break; case SCI_DEV_STOPPING: - status = common_complete_io(sci_port, sci_dev, sci_req); + status = common_complete_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) break; @@ -664,7 +662,7 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s dev_err(scirdev_to_dev(sci_dev), "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " "could not complete\n", __func__, sci_port, - sci_dev, sci_req, status); + sci_dev, ireq, status); else isci_put_device(sci_dev_to_idev(sci_dev)); @@ -682,7 +680,7 @@ static void scic_sds_remote_device_continue_request(void *dev) enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; @@ -708,15 +706,15 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc case SCI_STP_DEV_NCQ: case SCI_STP_DEV_NCQ_ERROR: case SCI_STP_DEV_AWAIT_RESET: - status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + status = scic_sds_port_start_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, sci_req); + status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, ireq); if (status != SCI_SUCCESS) goto out; - status = scic_sds_request_start(sci_req); + status = scic_sds_request_start(ireq); if (status != SCI_SUCCESS) goto out; @@ -724,7 +722,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc * replace the request that probably resulted in the task * management request. */ - sci_dev->working_request = sci_req; + sci_dev->working_request = ireq; sci_change_state(sm, SCI_STP_DEV_CMD); /* The remote node context must cleanup the TCi to NCQ mapping @@ -741,25 +739,25 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc sci_dev); out: - scic_sds_remote_device_start_request(sci_dev, sci_req, status); + scic_sds_remote_device_start_request(sci_dev, ireq, status); /* We need to let the controller start request handler know that * it can't post TC yet. We will provide a callback function to * post TC when RNC gets resumed. */ return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; case SCI_DEV_READY: - status = scic_sds_port_start_io(sci_port, sci_dev, sci_req); + status = scic_sds_port_start_io(sci_port, sci_dev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, sci_req); + status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(sci_req); + status = scic_sds_request_start(ireq); break; } - scic_sds_remote_device_start_request(sci_dev, sci_req, status); + scic_sds_remote_device_start_request(sci_dev, ireq, status); return status; } diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 0d9e37fe734f..6ac5dfb7d1db 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -120,7 +120,7 @@ struct scic_sds_remote_device { * used only for SATA requests since the unsolicited frames we get from the * hardware have no Tag value to look up the io request object. */ - struct scic_sds_request *working_request; + struct isci_request *working_request; /** * This field contains the reason for the remote device going not_ready. It is @@ -466,17 +466,17 @@ enum sci_status scic_sds_remote_device_event_handler( enum sci_status scic_sds_remote_device_start_io( struct scic_sds_controller *controller, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request); + struct isci_request *ireq); enum sci_status scic_sds_remote_device_start_task( struct scic_sds_controller *controller, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request); + struct isci_request *ireq); enum sci_status scic_sds_remote_device_complete_io( struct scic_sds_controller *controller, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *io_request); + struct isci_request *ireq); enum sci_status scic_sds_remote_device_suspend( struct scic_sds_remote_device *sci_dev, diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index b6774bcdabd8..1b51fe55314d 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -598,7 +598,7 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ } enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { enum scis_sds_remote_node_context_states state; @@ -623,7 +623,7 @@ enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_nod } enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { enum scis_sds_remote_node_context_states state; diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index 67a45b686a98..35e6ae616903 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -78,7 +78,7 @@ #define SCU_HARDWARE_SUSPENSION (0) #define SCI_SOFTWARE_SUSPENSION (1) -struct scic_sds_request; +struct isci_request; struct scic_sds_remote_device; struct scic_sds_remote_node_context; @@ -220,8 +220,8 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ scics_sds_remote_node_context_callback cb_fn, void *cb_p); enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req); + struct isci_request *ireq); enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_node_context *sci_rnc, - struct scic_sds_request *sci_req); + struct isci_request *ireq); #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 8520626b02fa..c544bc79ce17 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -61,35 +61,35 @@ #include "scu_event_codes.h" #include "sas.h" -static struct scu_sgl_element_pair *to_sgl_element_pair(struct scic_sds_request *sci_req, +static struct scu_sgl_element_pair *to_sgl_element_pair(struct isci_request *ireq, int idx) { if (idx == 0) - return &sci_req->tc->sgl_pair_ab; + return &ireq->tc->sgl_pair_ab; else if (idx == 1) - return &sci_req->tc->sgl_pair_cd; + return &ireq->tc->sgl_pair_cd; else if (idx < 0) return NULL; else - return &sci_req->sg_table[idx - 2]; + return &ireq->sg_table[idx - 2]; } static dma_addr_t to_sgl_element_pair_dma(struct scic_sds_controller *scic, - struct scic_sds_request *sci_req, u32 idx) + struct isci_request *ireq, u32 idx) { u32 offset; if (idx == 0) { - offset = (void *) &sci_req->tc->sgl_pair_ab - + offset = (void *) &ireq->tc->sgl_pair_ab - (void *) &scic->task_context_table[0]; return scic->task_context_dma + offset; } else if (idx == 1) { - offset = (void *) &sci_req->tc->sgl_pair_cd - + offset = (void *) &ireq->tc->sgl_pair_cd - (void *) &scic->task_context_table[0]; return scic->task_context_dma + offset; } - return scic_io_request_get_dma_addr(sci_req, &sci_req->sg_table[idx - 2]); + return scic_io_request_get_dma_addr(ireq, &ireq->sg_table[idx - 2]); } static void init_sgl_element(struct scu_sgl_element *e, struct scatterlist *sg) @@ -100,12 +100,11 @@ static void init_sgl_element(struct scu_sgl_element *e, struct scatterlist *sg) e->address_modifier = 0; } -static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) +static void scic_sds_request_build_sgl(struct isci_request *ireq) { - struct isci_request *isci_request = sci_req_to_ireq(sds_request); - struct isci_host *isci_host = isci_request->isci_host; + struct isci_host *isci_host = ireq->isci_host; struct scic_sds_controller *scic = &isci_host->sci; - struct sas_task *task = isci_request_access_task(isci_request); + struct sas_task *task = isci_request_access_task(ireq); struct scatterlist *sg = NULL; dma_addr_t dma_addr; u32 sg_idx = 0; @@ -116,7 +115,7 @@ static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) sg = task->scatter; while (sg) { - scu_sg = to_sgl_element_pair(sds_request, sg_idx); + scu_sg = to_sgl_element_pair(ireq, sg_idx); init_sgl_element(&scu_sg->A, sg); sg = sg_next(sg); if (sg) { @@ -127,7 +126,7 @@ static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) if (prev_sg) { dma_addr = to_sgl_element_pair_dma(scic, - sds_request, + ireq, sg_idx); prev_sg->next_pair_upper = @@ -140,14 +139,14 @@ static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) sg_idx++; } } else { /* handle when no sg */ - scu_sg = to_sgl_element_pair(sds_request, sg_idx); + scu_sg = to_sgl_element_pair(ireq, sg_idx); dma_addr = dma_map_single(&isci_host->pdev->dev, task->scatter, task->total_xfer_len, task->data_dir); - isci_request->zero_scatter_daddr = dma_addr; + ireq->zero_scatter_daddr = dma_addr; scu_sg->A.length = task->total_xfer_len; scu_sg->A.address_upper = upper_32_bits(dma_addr); @@ -160,13 +159,12 @@ static void scic_sds_request_build_sgl(struct scic_sds_request *sds_request) } } -static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sci_req) +static void scic_sds_io_request_build_ssp_command_iu(struct isci_request *ireq) { struct ssp_cmd_iu *cmd_iu; - struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); - cmd_iu = &sci_req->ssp.cmd; + cmd_iu = &ireq->ssp.cmd; memcpy(cmd_iu->LUN, task->ssp_task.LUN, 8); cmd_iu->add_cdb_len = 0; @@ -181,14 +179,13 @@ static void scic_sds_io_request_build_ssp_command_iu(struct scic_sds_request *sc sizeof(task->ssp_task.cdb) / sizeof(u32)); } -static void scic_sds_task_request_build_ssp_task_iu(struct scic_sds_request *sci_req) +static void scic_sds_task_request_build_ssp_task_iu(struct isci_request *ireq) { struct ssp_task_iu *task_iu; - struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - task_iu = &sci_req->ssp.tmf; + task_iu = &ireq->ssp.tmf; memset(task_iu, 0, sizeof(struct ssp_task_iu)); @@ -208,15 +205,15 @@ static void scic_sds_task_request_build_ssp_task_iu(struct scic_sds_request *sci * */ static void scu_ssp_reqeust_construct_task_context( - struct scic_sds_request *sds_request, + struct isci_request *ireq, struct scu_task_context *task_context) { dma_addr_t dma_addr; struct scic_sds_remote_device *target_device; struct scic_sds_port *target_port; - target_device = scic_sds_request_get_device(sds_request); - target_port = scic_sds_request_get_port(sds_request); + target_device = scic_sds_request_get_device(ireq); + target_port = scic_sds_request_get_port(ireq); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -232,7 +229,7 @@ static void scu_ssp_reqeust_construct_task_context( task_context->context_type = SCU_TASK_CONTEXT_TYPE; task_context->remote_node_index = - scic_sds_remote_device_get_index(sds_request->target_device); + scic_sds_remote_device_get_index(ireq->target_device); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -244,22 +241,21 @@ static void scu_ssp_reqeust_construct_task_context( task_context->address_modifier = 0; - /* task_context->type.ssp.tag = sci_req->io_tag; */ + /* task_context->type.ssp.tag = ireq->io_tag; */ task_context->task_phase = 0x01; - sds_request->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | (scic_sds_controller_get_protocol_engine_group(controller) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | (scic_sds_port_get_index(target_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(sds_request->io_tag)); + ISCI_TAG_TCI(ireq->io_tag)); /* * Copy the physical address for the command buffer to the * SCU Task Context */ - dma_addr = scic_io_request_get_dma_addr(sds_request, - &sds_request->ssp.cmd); + dma_addr = scic_io_request_get_dma_addr(ireq, &ireq->ssp.cmd); task_context->command_iu_upper = upper_32_bits(dma_addr); task_context->command_iu_lower = lower_32_bits(dma_addr); @@ -268,8 +264,7 @@ static void scu_ssp_reqeust_construct_task_context( * Copy the physical address for the response buffer to the * SCU Task Context */ - dma_addr = scic_io_request_get_dma_addr(sds_request, - &sds_request->ssp.rsp); + dma_addr = scic_io_request_get_dma_addr(ireq, &ireq->ssp.rsp); task_context->response_iu_upper = upper_32_bits(dma_addr); task_context->response_iu_lower = lower_32_bits(dma_addr); @@ -280,13 +275,13 @@ static void scu_ssp_reqeust_construct_task_context( * @sci_req: * */ -static void scu_ssp_io_request_construct_task_context(struct scic_sds_request *sci_req, +static void scu_ssp_io_request_construct_task_context(struct isci_request *ireq, enum dma_data_direction dir, u32 len) { - struct scu_task_context *task_context = sci_req->tc; + struct scu_task_context *task_context = ireq->tc; - scu_ssp_reqeust_construct_task_context(sci_req, task_context); + scu_ssp_reqeust_construct_task_context(ireq, task_context); task_context->ssp_command_iu_length = sizeof(struct ssp_cmd_iu) / sizeof(u32); @@ -306,7 +301,7 @@ static void scu_ssp_io_request_construct_task_context(struct scic_sds_request *s task_context->transfer_length_bytes = len; if (task_context->transfer_length_bytes > 0) - scic_sds_request_build_sgl(sci_req); + scic_sds_request_build_sgl(ireq); } /** @@ -322,11 +317,11 @@ static void scu_ssp_io_request_construct_task_context(struct scic_sds_request *s * constructed. * */ -static void scu_ssp_task_request_construct_task_context(struct scic_sds_request *sci_req) +static void scu_ssp_task_request_construct_task_context(struct isci_request *ireq) { - struct scu_task_context *task_context = sci_req->tc; + struct scu_task_context *task_context = ireq->tc; - scu_ssp_reqeust_construct_task_context(sci_req, task_context); + scu_ssp_reqeust_construct_task_context(ireq, task_context); task_context->control_frame = 1; task_context->priority = SCU_TASK_PRIORITY_HIGH; @@ -350,15 +345,15 @@ static void scu_ssp_task_request_construct_task_context(struct scic_sds_request * determine what is common for SSP/SMP/STP task context structures. */ static void scu_sata_reqeust_construct_task_context( - struct scic_sds_request *sci_req, + struct isci_request *ireq, struct scu_task_context *task_context) { dma_addr_t dma_addr; struct scic_sds_remote_device *target_device; struct scic_sds_port *target_port; - target_device = scic_sds_request_get_device(sci_req); - target_port = scic_sds_request_get_port(sci_req); + target_device = scic_sds_request_get_device(ireq); + target_port = scic_sds_request_get_port(ireq); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -374,7 +369,7 @@ static void scu_sata_reqeust_construct_task_context( task_context->context_type = SCU_TASK_CONTEXT_TYPE; task_context->remote_node_index = - scic_sds_remote_device_get_index(sci_req->target_device); + scic_sds_remote_device_get_index(ireq->target_device); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -391,21 +386,21 @@ static void scu_sata_reqeust_construct_task_context( (sizeof(struct host_to_dev_fis) - sizeof(u32)) / sizeof(u32); /* Set the first word of the H2D REG FIS */ - task_context->type.words[0] = *(u32 *)&sci_req->stp.cmd; + task_context->type.words[0] = *(u32 *)&ireq->stp.cmd; - sci_req->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | (scic_sds_controller_get_protocol_engine_group(controller) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | (scic_sds_port_get_index(target_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(sci_req->io_tag)); + ISCI_TAG_TCI(ireq->io_tag)); /* * Copy the physical address for the command buffer to the SCU Task * Context. We must offset the command buffer by 4 bytes because the * first 4 bytes are transfered in the body of the TC. */ - dma_addr = scic_io_request_get_dma_addr(sci_req, - ((char *) &sci_req->stp.cmd) + + dma_addr = scic_io_request_get_dma_addr(ireq, + ((char *) &ireq->stp.cmd) + sizeof(u32)); task_context->command_iu_upper = upper_32_bits(dma_addr); @@ -416,11 +411,11 @@ static void scu_sata_reqeust_construct_task_context( task_context->response_iu_lower = 0; } -static void scu_stp_raw_request_construct_task_context(struct scic_sds_request *sci_req) +static void scu_stp_raw_request_construct_task_context(struct isci_request *ireq) { - struct scu_task_context *task_context = sci_req->tc; + struct scu_task_context *task_context = ireq->tc; - scu_sata_reqeust_construct_task_context(sci_req, task_context); + scu_sata_reqeust_construct_task_context(ireq, task_context); task_context->control_frame = 0; task_context->priority = SCU_TASK_PRIORITY_NORMAL; @@ -429,20 +424,19 @@ static void scu_stp_raw_request_construct_task_context(struct scic_sds_request * task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32); } -static enum sci_status -scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, - bool copy_rx_frame) +static enum sci_status scic_sds_stp_pio_request_construct(struct isci_request *ireq, + bool copy_rx_frame) { - struct isci_stp_request *stp_req = &sci_req->stp.req; + struct isci_stp_request *stp_req = &ireq->stp.req; - scu_stp_raw_request_construct_task_context(sci_req); + scu_stp_raw_request_construct_task_context(ireq); stp_req->status = 0; stp_req->sgl.offset = 0; stp_req->sgl.set = SCU_SGL_ELEMENT_PAIR_A; if (copy_rx_frame) { - scic_sds_request_build_sgl(sci_req); + scic_sds_request_build_sgl(ireq); stp_req->sgl.index = 0; } else { /* The user does not want the data copied to the SGL buffer location */ @@ -464,18 +458,18 @@ scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req, * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method * returns an indication as to whether the construction was successful. */ -static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sci_req, +static void scic_sds_stp_optimized_request_construct(struct isci_request *ireq, u8 optimized_task_type, u32 len, enum dma_data_direction dir) { - struct scu_task_context *task_context = sci_req->tc; + struct scu_task_context *task_context = ireq->tc; /* Build the STP task context structure */ - scu_sata_reqeust_construct_task_context(sci_req, task_context); + scu_sata_reqeust_construct_task_context(ireq, task_context); /* Copy over the SGL elements */ - scic_sds_request_build_sgl(sci_req); + scic_sds_request_build_sgl(ireq); /* Copy over the number of bytes to be transfered */ task_context->transfer_length_bytes = len; @@ -500,13 +494,12 @@ static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sc static enum sci_status -scic_io_request_construct_sata(struct scic_sds_request *sci_req, +scic_io_request_construct_sata(struct isci_request *ireq, u32 len, enum dma_data_direction dir, bool copy) { enum sci_status status = SCI_SUCCESS; - struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); /* check for management protocols */ @@ -515,20 +508,20 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, if (tmf->tmf_code == isci_tmf_sata_srst_high || tmf->tmf_code == isci_tmf_sata_srst_low) { - scu_stp_raw_request_construct_task_context(sci_req); + scu_stp_raw_request_construct_task_context(ireq); return SCI_SUCCESS; } else { - dev_err(scic_to_dev(sci_req->owning_controller), + dev_err(scic_to_dev(ireq->owning_controller), "%s: Request 0x%p received un-handled SAT " "management protocol 0x%x.\n", - __func__, sci_req, tmf->tmf_code); + __func__, ireq, tmf->tmf_code); return SCI_FAILURE; } } if (!sas_protocol_ata(task->task_proto)) { - dev_err(scic_to_dev(sci_req->owning_controller), + dev_err(scic_to_dev(ireq->owning_controller), "%s: Non-ATA protocol in SATA path: 0x%x\n", __func__, task->task_proto); @@ -538,13 +531,13 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, /* non data */ if (task->data_dir == DMA_NONE) { - scu_stp_raw_request_construct_task_context(sci_req); + scu_stp_raw_request_construct_task_context(ireq); return SCI_SUCCESS; } /* NCQ */ if (task->ata_task.use_ncq) { - scic_sds_stp_optimized_request_construct(sci_req, + scic_sds_stp_optimized_request_construct(ireq, SCU_TASK_TYPE_FPDMAQ_READ, len, dir); return SCI_SUCCESS; @@ -552,74 +545,71 @@ scic_io_request_construct_sata(struct scic_sds_request *sci_req, /* DMA */ if (task->ata_task.dma_xfer) { - scic_sds_stp_optimized_request_construct(sci_req, + scic_sds_stp_optimized_request_construct(ireq, SCU_TASK_TYPE_DMA_IN, len, dir); return SCI_SUCCESS; } else /* PIO */ - return scic_sds_stp_pio_request_construct(sci_req, copy); + return scic_sds_stp_pio_request_construct(ireq, copy); return status; } -static enum sci_status scic_io_request_construct_basic_ssp(struct scic_sds_request *sci_req) +static enum sci_status scic_io_request_construct_basic_ssp(struct isci_request *ireq) { - struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); - sci_req->protocol = SCIC_SSP_PROTOCOL; + ireq->protocol = SCIC_SSP_PROTOCOL; - scu_ssp_io_request_construct_task_context(sci_req, + scu_ssp_io_request_construct_task_context(ireq, task->data_dir, task->total_xfer_len); - scic_sds_io_request_build_ssp_command_iu(sci_req); + scic_sds_io_request_build_ssp_command_iu(ireq); - sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); + sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED); return SCI_SUCCESS; } enum sci_status scic_task_request_construct_ssp( - struct scic_sds_request *sci_req) + struct isci_request *ireq) { /* Construct the SSP Task SCU Task Context */ - scu_ssp_task_request_construct_task_context(sci_req); + scu_ssp_task_request_construct_task_context(ireq); /* Fill in the SSP Task IU */ - scic_sds_task_request_build_ssp_task_iu(sci_req); + scic_sds_task_request_build_ssp_task_iu(ireq); - sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); + sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED); return SCI_SUCCESS; } -static enum sci_status scic_io_request_construct_basic_sata(struct scic_sds_request *sci_req) +static enum sci_status scic_io_request_construct_basic_sata(struct isci_request *ireq) { enum sci_status status; bool copy = false; - struct isci_request *isci_request = sci_req_to_ireq(sci_req); - struct sas_task *task = isci_request_access_task(isci_request); + struct sas_task *task = isci_request_access_task(ireq); - sci_req->protocol = SCIC_STP_PROTOCOL; + ireq->protocol = SCIC_STP_PROTOCOL; copy = (task->data_dir == DMA_NONE) ? false : true; - status = scic_io_request_construct_sata(sci_req, + status = scic_io_request_construct_sata(ireq, task->total_xfer_len, task->data_dir, copy); if (status == SCI_SUCCESS) - sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); + sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED); return status; } -enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_req) +enum sci_status scic_task_request_construct_sata(struct isci_request *ireq) { enum sci_status status = SCI_SUCCESS; - struct isci_request *ireq = sci_req_to_ireq(sci_req); /* check for management protocols */ if (ireq->ttype == tmf_task) { @@ -627,12 +617,12 @@ enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_re if (tmf->tmf_code == isci_tmf_sata_srst_high || tmf->tmf_code == isci_tmf_sata_srst_low) { - scu_stp_raw_request_construct_task_context(sci_req); + scu_stp_raw_request_construct_task_context(ireq); } else { - dev_err(scic_to_dev(sci_req->owning_controller), + dev_err(scic_to_dev(ireq->owning_controller), "%s: Request 0x%p received un-handled SAT " "Protocol 0x%x.\n", - __func__, sci_req, tmf->tmf_code); + __func__, ireq, tmf->tmf_code); return SCI_FAILURE; } @@ -640,7 +630,7 @@ enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_re if (status != SCI_SUCCESS) return status; - sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); + sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED); return status; } @@ -650,9 +640,9 @@ enum sci_status scic_task_request_construct_sata(struct scic_sds_request *sci_re * @sci_req: request that was terminated early */ #define SCU_TASK_CONTEXT_SRAM 0x200000 -static u32 sci_req_tx_bytes(struct scic_sds_request *sci_req) +static u32 sci_req_tx_bytes(struct isci_request *ireq) { - struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_controller *scic = ireq->owning_controller; u32 ret_val = 0; if (readl(&scic->smu_registers->address_modifier) == 0) { @@ -666,19 +656,19 @@ static u32 sci_req_tx_bytes(struct scic_sds_request *sci_req) */ ret_val = readl(scu_reg_base + (SCU_TASK_CONTEXT_SRAM + offsetof(struct scu_task_context, type.ssp.data_offset)) + - ((sizeof(struct scu_task_context)) * ISCI_TAG_TCI(sci_req->io_tag))); + ((sizeof(struct scu_task_context)) * ISCI_TAG_TCI(ireq->io_tag))); } return ret_val; } -enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) +enum sci_status scic_sds_request_start(struct isci_request *ireq) { enum sci_base_request_states state; - struct scu_task_context *tc = sci_req->tc; - struct scic_sds_controller *scic = sci_req->owning_controller; + struct scu_task_context *tc = ireq->tc; + struct scic_sds_controller *scic = ireq->owning_controller; - state = sci_req->sm.current_state_id; + state = ireq->sm.current_state_id; if (state != SCI_REQ_CONSTRUCTED) { dev_warn(scic_to_dev(scic), "%s: SCIC IO Request requested to start while in wrong " @@ -686,19 +676,19 @@ enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) return SCI_FAILURE_INVALID_STATE; } - tc->task_index = ISCI_TAG_TCI(sci_req->io_tag); + tc->task_index = ISCI_TAG_TCI(ireq->io_tag); switch (tc->protocol_type) { case SCU_TASK_CONTEXT_PROTOCOL_SMP: case SCU_TASK_CONTEXT_PROTOCOL_SSP: /* SSP/SMP Frame */ - tc->type.ssp.tag = sci_req->io_tag; + tc->type.ssp.tag = ireq->io_tag; tc->type.ssp.target_port_transfer_tag = 0xFFFF; break; case SCU_TASK_CONTEXT_PROTOCOL_STP: /* STP/SATA Frame - * tc->type.stp.ncq_tag = sci_req->ncq_tag; + * tc->type.stp.ncq_tag = ireq->ncq_tag; */ break; @@ -713,28 +703,28 @@ enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req) } /* Add to the post_context the io tag value */ - sci_req->post_context |= ISCI_TAG_TCI(sci_req->io_tag); + ireq->post_context |= ISCI_TAG_TCI(ireq->io_tag); /* Everything is good go ahead and change state */ - sci_change_state(&sci_req->sm, SCI_REQ_STARTED); + sci_change_state(&ireq->sm, SCI_REQ_STARTED); return SCI_SUCCESS; } enum sci_status -scic_sds_io_request_terminate(struct scic_sds_request *sci_req) +scic_sds_io_request_terminate(struct isci_request *ireq) { enum sci_base_request_states state; - state = sci_req->sm.current_state_id; + state = ireq->sm.current_state_id; switch (state) { case SCI_REQ_CONSTRUCTED: - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; case SCI_REQ_STARTED: case SCI_REQ_TASK_WAIT_TC_COMP: @@ -751,54 +741,54 @@ scic_sds_io_request_terminate(struct scic_sds_request *sci_req) case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED: case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG: case SCI_REQ_STP_SOFT_RESET_WAIT_D2H: - sci_change_state(&sci_req->sm, SCI_REQ_ABORTING); + sci_change_state(&ireq->sm, SCI_REQ_ABORTING); return SCI_SUCCESS; case SCI_REQ_TASK_WAIT_TC_RESP: - sci_change_state(&sci_req->sm, SCI_REQ_ABORTING); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_ABORTING); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; case SCI_REQ_ABORTING: - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; case SCI_REQ_COMPLETED: default: - dev_warn(scic_to_dev(sci_req->owning_controller), + dev_warn(scic_to_dev(ireq->owning_controller), "%s: SCIC IO Request requested to abort while in wrong " "state %d\n", __func__, - sci_req->sm.current_state_id); + ireq->sm.current_state_id); break; } return SCI_FAILURE_INVALID_STATE; } -enum sci_status scic_sds_request_complete(struct scic_sds_request *sci_req) +enum sci_status scic_sds_request_complete(struct isci_request *ireq) { enum sci_base_request_states state; - struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_controller *scic = ireq->owning_controller; - state = sci_req->sm.current_state_id; + state = ireq->sm.current_state_id; if (WARN_ONCE(state != SCI_REQ_COMPLETED, "isci: request completion from wrong state (%d)\n", state)) return SCI_FAILURE_INVALID_STATE; - if (sci_req->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) + if (ireq->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) scic_sds_controller_release_frame(scic, - sci_req->saved_rx_frame_index); + ireq->saved_rx_frame_index); /* XXX can we just stop the machine and remove the 'final' state? */ - sci_change_state(&sci_req->sm, SCI_REQ_FINAL); + sci_change_state(&ireq->sm, SCI_REQ_FINAL); return SCI_SUCCESS; } -enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, +enum sci_status scic_sds_io_request_event_handler(struct isci_request *ireq, u32 event_code) { enum sci_base_request_states state; - struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_controller *scic = ireq->owning_controller; - state = sci_req->sm.current_state_id; + state = ireq->sm.current_state_id; if (state != SCI_REQ_STP_PIO_DATA_IN) { dev_warn(scic_to_dev(scic), "%s: (%x) in wrong state %d\n", @@ -812,7 +802,7 @@ enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_r /* We are waiting for data and the SCU has R_ERR the data frame. * Go back to waiting for the D2H Register FIS */ - sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); + sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_WAIT_FRAME); return SCI_SUCCESS; default: dev_err(scic_to_dev(scic), @@ -832,15 +822,14 @@ enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_r * @sci_req: This parameter specifies the request object for which to copy * the response data. */ -static void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) +static void scic_sds_io_request_copy_response(struct isci_request *ireq) { void *resp_buf; u32 len; struct ssp_response_iu *ssp_response; - struct isci_request *ireq = sci_req_to_ireq(sci_req); struct isci_tmf *isci_tmf = isci_request_access_tmf(ireq); - ssp_response = &sci_req->ssp.rsp; + ssp_response = &ireq->ssp.rsp; resp_buf = &isci_tmf->resp.resp_iu; @@ -852,7 +841,7 @@ static void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) } static enum sci_status -request_started_state_tc_event(struct scic_sds_request *sci_req, +request_started_state_tc_event(struct isci_request *ireq, u32 completion_code) { struct ssp_response_iu *resp_iu; @@ -863,7 +852,7 @@ request_started_state_tc_event(struct scic_sds_request *sci_req, */ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; @@ -875,19 +864,19 @@ request_started_state_tc_event(struct scic_sds_request *sci_req, * truly a failed request or a good request that just got * completed early. */ - struct ssp_response_iu *resp = &sci_req->ssp.rsp; + struct ssp_response_iu *resp = &ireq->ssp.rsp; ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - sci_swab32_cpy(&sci_req->ssp.rsp, - &sci_req->ssp.rsp, + sci_swab32_cpy(&ireq->ssp.rsp, + &ireq->ssp.rsp, word_cnt); if (resp->status == 0) { - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY); } else { - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); } @@ -896,11 +885,11 @@ request_started_state_tc_event(struct scic_sds_request *sci_req, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): { ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - sci_swab32_cpy(&sci_req->ssp.rsp, - &sci_req->ssp.rsp, + sci_swab32_cpy(&ireq->ssp.rsp, + &ireq->ssp.rsp, word_cnt); - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); break; @@ -911,15 +900,15 @@ request_started_state_tc_event(struct scic_sds_request *sci_req, * guaranteed to be received before this completion status is * posted? */ - resp_iu = &sci_req->ssp.rsp; + resp_iu = &ireq->ssp.rsp; datapres = resp_iu->datapres; if (datapres == 1 || datapres == 2) { - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); } else - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; @@ -935,13 +924,13 @@ request_started_state_tc_event(struct scic_sds_request *sci_req, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): - if (sci_req->protocol == SCIC_STP_PROTOCOL) { - scic_sds_request_set_status(sci_req, + if (ireq->protocol == SCIC_STP_PROTOCOL) { + scic_sds_request_set_status(ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); } else { - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -959,7 +948,7 @@ request_started_state_tc_event(struct scic_sds_request *sci_req, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); @@ -983,7 +972,7 @@ request_started_state_tc_event(struct scic_sds_request *sci_req, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): default: scic_sds_request_set_status( - sci_req, + ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -995,21 +984,21 @@ request_started_state_tc_event(struct scic_sds_request *sci_req, */ /* In all cases we will treat this as the completion of the IO req. */ - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; } static enum sci_status -request_aborting_state_tc_event(struct scic_sds_request *sci_req, +request_aborting_state_tc_event(struct isci_request *ireq, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_TASK_ABORT, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; default: @@ -1022,15 +1011,15 @@ request_aborting_state_tc_event(struct scic_sds_request *sci_req, return SCI_SUCCESS; } -static enum sci_status ssp_task_request_await_tc_event(struct scic_sds_request *sci_req, +static enum sci_status ssp_task_request_await_tc_event(struct isci_request *ireq, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_change_state(&sci_req->sm, SCI_REQ_TASK_WAIT_TC_RESP); + sci_change_state(&ireq->sm, SCI_REQ_TASK_WAIT_TC_RESP); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): /* Currently, the decision is to simply allow the task request @@ -1038,12 +1027,12 @@ static enum sci_status ssp_task_request_await_tc_event(struct scic_sds_request * * There is a potential for receiving multiple task responses if * we decide to send the task IU again. */ - dev_warn(scic_to_dev(sci_req->owning_controller), + dev_warn(scic_to_dev(ireq->owning_controller), "%s: TaskRequest:0x%p CompletionCode:%x - " - "ACK/NAK timeout\n", __func__, sci_req, + "ACK/NAK timeout\n", __func__, ireq, completion_code); - sci_change_state(&sci_req->sm, SCI_REQ_TASK_WAIT_TC_RESP); + sci_change_state(&ireq->sm, SCI_REQ_TASK_WAIT_TC_RESP); break; default: /* @@ -1051,11 +1040,11 @@ static enum sci_status ssp_task_request_await_tc_event(struct scic_sds_request * * If a NAK was received, then it is up to the user to retry * the request. */ - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1063,7 +1052,7 @@ static enum sci_status ssp_task_request_await_tc_event(struct scic_sds_request * } static enum sci_status -smp_request_await_response_tc_event(struct scic_sds_request *sci_req, +smp_request_await_response_tc_event(struct isci_request *ireq, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { @@ -1072,10 +1061,10 @@ smp_request_await_response_tc_event(struct scic_sds_request *sci_req, * unexpected. but if the TC has success status, we * complete the IO anyway. */ - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): @@ -1089,21 +1078,21 @@ smp_request_await_response_tc_event(struct scic_sds_request *sci_req, * these SMP_XXX_XX_ERR status. For these type of error, * we ask scic user to retry the request. */ - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; default: /* All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request */ - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1111,50 +1100,50 @@ smp_request_await_response_tc_event(struct scic_sds_request *sci_req, } static enum sci_status -smp_request_await_tc_event(struct scic_sds_request *sci_req, +smp_request_await_tc_event(struct isci_request *ireq, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; default: /* All other completion status cause the IO to be * complete. If a NAK was received, then it is up to * the user to retry the request. */ - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } return SCI_SUCCESS; } -void scic_stp_io_request_set_ncq_tag(struct scic_sds_request *req, +void scic_stp_io_request_set_ncq_tag(struct isci_request *ireq, u16 ncq_tag) { /** * @note This could be made to return an error to the user if the user * attempts to set the NCQ tag in the wrong state. */ - req->tc->type.stp.ncq_tag = ncq_tag; + ireq->tc->type.stp.ncq_tag = ncq_tag; } static struct scu_sgl_element *pio_sgl_next(struct isci_stp_request *stp_req) { struct scu_sgl_element *sgl; struct scu_sgl_element_pair *sgl_pair; - struct scic_sds_request *sci_req = to_sci_req(stp_req); + struct isci_request *ireq = to_ireq(stp_req); struct isci_stp_pio_sgl *pio_sgl = &stp_req->sgl; - sgl_pair = to_sgl_element_pair(sci_req, pio_sgl->index); + sgl_pair = to_sgl_element_pair(ireq, pio_sgl->index); if (!sgl_pair) sgl = NULL; else if (pio_sgl->set == SCU_SGL_ELEMENT_PAIR_A) { @@ -1172,7 +1161,7 @@ static struct scu_sgl_element *pio_sgl_next(struct isci_stp_request *stp_req) } else { pio_sgl->index++; pio_sgl->set = SCU_SGL_ELEMENT_PAIR_A; - sgl_pair = to_sgl_element_pair(sci_req, pio_sgl->index); + sgl_pair = to_sgl_element_pair(ireq, pio_sgl->index); sgl = &sgl_pair->A; } } @@ -1181,15 +1170,15 @@ static struct scu_sgl_element *pio_sgl_next(struct isci_stp_request *stp_req) } static enum sci_status -stp_request_non_data_await_h2d_tc_event(struct scic_sds_request *sci_req, +stp_request_non_data_await_h2d_tc_event(struct isci_request *ireq, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_change_state(&sci_req->sm, SCI_REQ_STP_NON_DATA_WAIT_D2H); + sci_change_state(&ireq->sm, SCI_REQ_STP_NON_DATA_WAIT_D2H); break; default: @@ -1197,11 +1186,11 @@ stp_request_non_data_await_h2d_tc_event(struct scic_sds_request *sci_req, * complete. If a NAK was received, then it is up to * the user to retry the request. */ - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1214,18 +1203,18 @@ stp_request_non_data_await_h2d_tc_event(struct scic_sds_request *sci_req, * parameter length. current sgl and offset is alreay stored in the IO request */ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( - struct scic_sds_request *sci_req, + struct isci_request *ireq, u32 length) { - struct isci_stp_request *stp_req = &sci_req->stp.req; - struct scu_task_context *task_context = sci_req->tc; + struct isci_stp_request *stp_req = &ireq->stp.req; + struct scu_task_context *task_context = ireq->tc; struct scu_sgl_element_pair *sgl_pair; struct scu_sgl_element *current_sgl; /* Recycle the TC and reconstruct it for sending out DATA FIS containing * for the data from current_sgl+offset for the input length */ - sgl_pair = to_sgl_element_pair(sci_req, stp_req->sgl.index); + sgl_pair = to_sgl_element_pair(ireq, stp_req->sgl.index); if (stp_req->sgl.set == SCU_SGL_ELEMENT_PAIR_A) current_sgl = &sgl_pair->A; else @@ -1238,12 +1227,12 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( task_context->type.stp.fis_type = FIS_DATA; /* send the new TC out. */ - return scic_controller_continue_io(sci_req); + return scic_controller_continue_io(ireq); } -static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct scic_sds_request *sci_req) +static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct isci_request *ireq) { - struct isci_stp_request *stp_req = &sci_req->stp.req; + struct isci_stp_request *stp_req = &ireq->stp.req; struct scu_sgl_element_pair *sgl_pair; struct scu_sgl_element *sgl; enum sci_status status; @@ -1251,7 +1240,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct sc u32 len = 0; offset = stp_req->sgl.offset; - sgl_pair = to_sgl_element_pair(sci_req, stp_req->sgl.index); + sgl_pair = to_sgl_element_pair(ireq, stp_req->sgl.index); if (WARN_ONCE(!sgl_pair, "%s: null sgl element", __func__)) return SCI_FAILURE; @@ -1267,7 +1256,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct sc return SCI_SUCCESS; if (stp_req->pio_len >= len) { - status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, len); + status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(ireq, len); if (status != SCI_SUCCESS) return status; stp_req->pio_len -= len; @@ -1276,7 +1265,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct sc sgl = pio_sgl_next(stp_req); offset = 0; } else if (stp_req->pio_len < len) { - scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->pio_len); + scic_sds_stp_request_pio_data_out_trasmit_data_frame(ireq, stp_req->pio_len); /* Sgl offset will be adjusted and saved for future */ offset += stp_req->pio_len; @@ -1302,7 +1291,6 @@ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req, u8 *data_buf, u32 len) { - struct scic_sds_request *sci_req; struct isci_request *ireq; u8 *src_addr; int copy_len; @@ -1311,8 +1299,7 @@ scic_sds_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_r void *kaddr; int total_len = len; - sci_req = to_sci_req(stp_req); - ireq = sci_req_to_ireq(sci_req); + ireq = to_ireq(stp_req); task = isci_request_access_task(ireq); src_addr = data_buf; @@ -1373,18 +1360,18 @@ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( } static enum sci_status -stp_request_pio_await_h2d_completion_tc_event(struct scic_sds_request *sci_req, +stp_request_pio_await_h2d_completion_tc_event(struct isci_request *ireq, u32 completion_code) { enum sci_status status = SCI_SUCCESS; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); + sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_WAIT_FRAME); break; default: @@ -1392,11 +1379,11 @@ stp_request_pio_await_h2d_completion_tc_event(struct scic_sds_request *sci_req, * complete. If a NAK was received, then it is up to * the user to retry the request. */ - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1404,18 +1391,18 @@ stp_request_pio_await_h2d_completion_tc_event(struct scic_sds_request *sci_req, } static enum sci_status -pio_data_out_tx_done_tc_event(struct scic_sds_request *sci_req, +pio_data_out_tx_done_tc_event(struct isci_request *ireq, u32 completion_code) { enum sci_status status = SCI_SUCCESS; bool all_frames_transferred = false; - struct isci_stp_request *stp_req = &sci_req->stp.req; + struct isci_stp_request *stp_req = &ireq->stp.req; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): /* Transmit data */ if (stp_req->pio_len != 0) { - status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); + status = scic_sds_stp_request_pio_data_out_transmit_data(ireq); if (status == SCI_SUCCESS) { if (stp_req->pio_len == 0) all_frames_transferred = true; @@ -1433,7 +1420,7 @@ pio_data_out_tx_done_tc_event(struct scic_sds_request *sci_req, /* * Change the state to SCI_REQ_STP_PIO_DATA_IN * and wait for PIO_SETUP fis / or D2H REg fis. */ - sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); + sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_WAIT_FRAME); } break; @@ -1444,11 +1431,11 @@ pio_data_out_tx_done_tc_event(struct scic_sds_request *sci_req, * the request. */ scic_sds_request_set_status( - sci_req, + ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1456,18 +1443,18 @@ pio_data_out_tx_done_tc_event(struct scic_sds_request *sci_req, } static void scic_sds_stp_request_udma_complete_request( - struct scic_sds_request *request, + struct isci_request *ireq, u32 scu_status, enum sci_status sci_status) { - scic_sds_request_set_status(request, scu_status, sci_status); - sci_change_state(&request->sm, SCI_REQ_COMPLETED); + scic_sds_request_set_status(ireq, scu_status, sci_status); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } -static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct scic_sds_request *sci_req, +static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct isci_request *ireq, u32 frame_index) { - struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_controller *scic = ireq->owning_controller; struct dev_to_host_fis *frame_header; enum sci_status status; u32 *frame_buffer; @@ -1482,7 +1469,7 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct sc frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + scic_sds_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); } @@ -1493,16 +1480,16 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct sc } enum sci_status -scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, +scic_sds_io_request_frame_handler(struct isci_request *ireq, u32 frame_index) { - struct scic_sds_controller *scic = sci_req->owning_controller; - struct isci_stp_request *stp_req = &sci_req->stp.req; + struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_stp_request *stp_req = &ireq->stp.req; enum sci_base_request_states state; enum sci_status status; ssize_t word_cnt; - state = sci_req->sm.current_state_id; + state = ireq->sm.current_state_id; switch (state) { case SCI_REQ_STARTED: { struct ssp_frame_hdr ssp_hdr; @@ -1523,24 +1510,24 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, frame_index, (void **)&resp_iu); - sci_swab32_cpy(&sci_req->ssp.rsp, resp_iu, word_cnt); + sci_swab32_cpy(&ireq->ssp.rsp, resp_iu, word_cnt); - resp_iu = &sci_req->ssp.rsp; + resp_iu = &ireq->ssp.rsp; if (resp_iu->datapres == 0x01 || resp_iu->datapres == 0x02) { - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); } else - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); } else { /* not a response frame, why did it get forwarded? */ dev_err(scic_to_dev(scic), "%s: SCIC IO Request 0x%p received unexpected " - "frame %d type 0x%02x\n", __func__, sci_req, + "frame %d type 0x%02x\n", __func__, ireq, frame_index, ssp_hdr.frame_type); } @@ -1554,13 +1541,13 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, } case SCI_REQ_TASK_WAIT_TC_RESP: - scic_sds_io_request_copy_response(sci_req); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + scic_sds_io_request_copy_response(ireq); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); scic_sds_controller_release_frame(scic,frame_index); return SCI_SUCCESS; case SCI_REQ_SMP_WAIT_RESP: { - struct smp_resp *rsp_hdr = &sci_req->smp.rsp; + struct smp_resp *rsp_hdr = &ireq->smp.rsp; void *frame_header; scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, @@ -1584,10 +1571,10 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, smp_resp, word_cnt); - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_change_state(&sci_req->sm, SCI_REQ_SMP_WAIT_TC_COMP); + sci_change_state(&ireq->sm, SCI_REQ_SMP_WAIT_TC_COMP); } else { /* * This was not a response frame why did it get @@ -1597,15 +1584,15 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, "%s: SCIC SMP Request 0x%p received unexpected " "frame %d type 0x%02x\n", __func__, - sci_req, + ireq, frame_index, rsp_hdr->frame_type); - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_SMP_FRM_TYPE_ERR, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } scic_sds_controller_release_frame(scic, frame_index); @@ -1614,18 +1601,18 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, } case SCI_REQ_STP_UDMA_WAIT_TC_COMP: - return scic_sds_stp_request_udma_general_frame_handler(sci_req, + return scic_sds_stp_request_udma_general_frame_handler(ireq, frame_index); case SCI_REQ_STP_UDMA_WAIT_D2H: /* Use the general frame handler to copy the resposne data */ - status = scic_sds_stp_request_udma_general_frame_handler(sci_req, + status = scic_sds_stp_request_udma_general_frame_handler(ireq, frame_index); if (status != SCI_SUCCESS) return status; - scic_sds_stp_request_udma_complete_request(sci_req, + scic_sds_stp_request_udma_complete_request(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); @@ -1657,12 +1644,12 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + scic_sds_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); /* The command has completed with error */ - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); break; @@ -1672,12 +1659,12 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, "violation occurred\n", __func__, stp_req, frame_index); - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_UNEXP_FIS, SCI_FAILURE_PROTOCOL_VIOLATION); break; } - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame(scic, frame_index); @@ -1686,7 +1673,6 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, } case SCI_REQ_STP_PIO_WAIT_FRAME: { - struct isci_request *ireq = sci_req_to_ireq(sci_req); struct sas_task *task = isci_request_access_task(ireq); struct dev_to_host_fis *frame_header; u32 *frame_buffer; @@ -1722,28 +1708,28 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, /* status: 4th byte in the 3rd dword */ stp_req->status = (frame_buffer[2] >> 24) & 0xff; - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + scic_sds_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); - sci_req->stp.rsp.status = stp_req->status; + ireq->stp.rsp.status = stp_req->status; /* The next state is dependent on whether the * request was PIO Data-in or Data out */ if (task->data_dir == DMA_FROM_DEVICE) { - sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_DATA_IN); + sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_DATA_IN); } else if (task->data_dir == DMA_TO_DEVICE) { /* Transmit data */ - status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req); + status = scic_sds_stp_request_pio_data_out_transmit_data(ireq); if (status != SCI_SUCCESS) break; - sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_DATA_OUT); + sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_DATA_OUT); } break; case FIS_SETDEVBITS: - sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); + sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_WAIT_FRAME); break; case FIS_REGD2H: @@ -1767,15 +1753,15 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&sci_req->stp.req, + scic_sds_controller_copy_sata_response(&ireq->stp.req, frame_header, frame_buffer); - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; default: @@ -1818,11 +1804,11 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, frame_index, frame_header->fis_type); - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame is decoded return it to the controller */ scic_sds_controller_release_frame(scic, frame_index); @@ -1830,7 +1816,7 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, } if (stp_req->sgl.index < 0) { - sci_req->saved_rx_frame_index = frame_index; + ireq->saved_rx_frame_index = frame_index; stp_req->pio_len = 0; } else { scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, @@ -1851,13 +1837,13 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, return status; if ((stp_req->status & ATA_BUSY) == 0) { - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } else { - sci_change_state(&sci_req->sm, SCI_REQ_STP_PIO_WAIT_FRAME); + sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_WAIT_FRAME); } return status; } @@ -1886,12 +1872,12 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&sci_req->stp.rsp, + scic_sds_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); /* The command has completed with error */ - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); break; @@ -1904,13 +1890,13 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, stp_req, frame_index); - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_UNEXP_FIS, SCI_FAILURE_PROTOCOL_VIOLATION); break; } - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame has been decoded return it to the controller */ scic_sds_controller_release_frame(scic, frame_index); @@ -1938,14 +1924,14 @@ scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, } } -static enum sci_status stp_request_udma_await_tc_event(struct scic_sds_request *sci_req, +static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq, u32 completion_code) { enum sci_status status = SCI_SUCCESS; switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_stp_request_udma_complete_request(sci_req, + scic_sds_stp_request_udma_complete_request(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; @@ -1955,11 +1941,11 @@ static enum sci_status stp_request_udma_await_tc_event(struct scic_sds_request * * Register FIS was received before we got the TC * completion. */ - if (sci_req->stp.rsp.fis_type == FIS_REGD2H) { - scic_sds_remote_device_suspend(sci_req->target_device, + if (ireq->stp.rsp.fis_type == FIS_REGD2H) { + scic_sds_remote_device_suspend(ireq->target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); - scic_sds_stp_request_udma_complete_request(sci_req, + scic_sds_stp_request_udma_complete_request(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); } else { @@ -1968,7 +1954,7 @@ static enum sci_status stp_request_udma_await_tc_event(struct scic_sds_request * * the device so we must change state to wait * for it */ - sci_change_state(&sci_req->sm, SCI_REQ_STP_UDMA_WAIT_D2H); + sci_change_state(&ireq->sm, SCI_REQ_STP_UDMA_WAIT_D2H); } break; @@ -1983,12 +1969,12 @@ static enum sci_status stp_request_udma_await_tc_event(struct scic_sds_request * case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): - scic_sds_remote_device_suspend(sci_req->target_device, + scic_sds_remote_device_suspend(ireq->target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); /* Fall through to the default case */ default: /* All other completion status cause the IO to be complete. */ - scic_sds_stp_request_udma_complete_request(sci_req, + scic_sds_stp_request_udma_complete_request(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); break; @@ -1998,15 +1984,15 @@ static enum sci_status stp_request_udma_await_tc_event(struct scic_sds_request * } static enum sci_status -stp_request_soft_reset_await_h2d_asserted_tc_event(struct scic_sds_request *sci_req, +stp_request_soft_reset_await_h2d_asserted_tc_event(struct isci_request *ireq, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_change_state(&sci_req->sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG); + sci_change_state(&ireq->sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG); break; default: @@ -2015,11 +2001,11 @@ stp_request_soft_reset_await_h2d_asserted_tc_event(struct scic_sds_request *sci_ * If a NAK was received, then it is up to the user to retry * the request. */ - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -2027,15 +2013,15 @@ stp_request_soft_reset_await_h2d_asserted_tc_event(struct scic_sds_request *sci_ } static enum sci_status -stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct scic_sds_request *sci_req, +stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq, u32 completion_code) { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, + scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); - sci_change_state(&sci_req->sm, SCI_REQ_STP_SOFT_RESET_WAIT_D2H); + sci_change_state(&ireq->sm, SCI_REQ_STP_SOFT_RESET_WAIT_D2H); break; default: @@ -2043,11 +2029,11 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct scic_sds_request *sc * a NAK was received, then it is up to the user to retry the * request. */ - scic_sds_request_set_status(sci_req, + scic_sds_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - sci_change_state(&sci_req->sm, SCI_REQ_COMPLETED); + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -2055,54 +2041,54 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct scic_sds_request *sc } enum sci_status -scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, +scic_sds_io_request_tc_completion(struct isci_request *ireq, u32 completion_code) { enum sci_base_request_states state; - struct scic_sds_controller *scic = sci_req->owning_controller; + struct scic_sds_controller *scic = ireq->owning_controller; - state = sci_req->sm.current_state_id; + state = ireq->sm.current_state_id; switch (state) { case SCI_REQ_STARTED: - return request_started_state_tc_event(sci_req, completion_code); + return request_started_state_tc_event(ireq, completion_code); case SCI_REQ_TASK_WAIT_TC_COMP: - return ssp_task_request_await_tc_event(sci_req, + return ssp_task_request_await_tc_event(ireq, completion_code); case SCI_REQ_SMP_WAIT_RESP: - return smp_request_await_response_tc_event(sci_req, + return smp_request_await_response_tc_event(ireq, completion_code); case SCI_REQ_SMP_WAIT_TC_COMP: - return smp_request_await_tc_event(sci_req, completion_code); + return smp_request_await_tc_event(ireq, completion_code); case SCI_REQ_STP_UDMA_WAIT_TC_COMP: - return stp_request_udma_await_tc_event(sci_req, + return stp_request_udma_await_tc_event(ireq, completion_code); case SCI_REQ_STP_NON_DATA_WAIT_H2D: - return stp_request_non_data_await_h2d_tc_event(sci_req, + return stp_request_non_data_await_h2d_tc_event(ireq, completion_code); case SCI_REQ_STP_PIO_WAIT_H2D: - return stp_request_pio_await_h2d_completion_tc_event(sci_req, + return stp_request_pio_await_h2d_completion_tc_event(ireq, completion_code); case SCI_REQ_STP_PIO_DATA_OUT: - return pio_data_out_tx_done_tc_event(sci_req, completion_code); + return pio_data_out_tx_done_tc_event(ireq, completion_code); case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED: - return stp_request_soft_reset_await_h2d_asserted_tc_event(sci_req, + return stp_request_soft_reset_await_h2d_asserted_tc_event(ireq, completion_code); case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG: - return stp_request_soft_reset_await_h2d_diagnostic_tc_event(sci_req, + return stp_request_soft_reset_await_h2d_diagnostic_tc_event(ireq, completion_code); case SCI_REQ_ABORTING: - return request_aborting_state_tc_event(sci_req, + return request_aborting_state_tc_event(ireq, completion_code); default: @@ -2201,7 +2187,7 @@ static void isci_request_handle_controller_specific_errors( { unsigned int cstatus; - cstatus = request->sci.scu_status; + cstatus = request->scu_status; dev_dbg(&request->isci_host->pdev->dev, "%s: %p SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR " @@ -2640,13 +2626,13 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, task); if (sas_protocol_ata(task->task_proto)) { - resp_buf = &request->sci.stp.rsp; + resp_buf = &request->stp.rsp; isci_request_process_stp_response(task, resp_buf); } else if (SAS_PROTOCOL_SSP == task->task_proto) { /* crack the iu response buffer. */ - resp_iu = &request->sci.ssp.rsp; + resp_iu = &request->ssp.rsp; isci_request_process_response_iu(task, resp_iu, &isci_host->pdev->dev); @@ -2677,7 +2663,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); if (task->task_proto == SAS_PROTOCOL_SMP) { - void *rsp = &request->sci.smp.rsp; + void *rsp = &request->smp.rsp; dev_dbg(&isci_host->pdev->dev, "%s: SMP protocol completion\n", @@ -2693,7 +2679,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, * There is a possibility that less data than * the maximum was transferred. */ - u32 transferred_length = sci_req_tx_bytes(&request->sci); + u32 transferred_length = sci_req_tx_bytes(request); task->task_status.residual = task->total_xfer_len - transferred_length; @@ -2851,8 +2837,8 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, /* complete the io request to the core. */ scic_controller_complete_io(&isci_host->sci, - request->sci.target_device, - &request->sci); + request->target_device, + request); isci_put_device(idev); /* set terminated handle so it cannot be completed or @@ -2864,9 +2850,8 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, static void scic_sds_request_started_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); - struct isci_request *ireq = sci_req_to_ireq(sci_req); - struct domain_device *dev = sci_dev_to_domain(sci_req->target_device); + struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); + struct domain_device *dev = sci_dev_to_domain(ireq->target_device); struct sas_task *task; /* XXX as hch said always creating an internal sas_task for tmf @@ -2902,66 +2887,65 @@ static void scic_sds_request_started_state_enter(struct sci_base_state_machine * static void scic_sds_request_completed_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); - struct scic_sds_controller *scic = sci_req->owning_controller; + struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); + struct scic_sds_controller *scic = ireq->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_request *ireq = sci_req_to_ireq(sci_req); /* Tell the SCI_USER that the IO request is complete */ if (!test_bit(IREQ_TMF, &ireq->flags)) isci_request_io_request_complete(ihost, ireq, - sci_req->sci_status); + ireq->sci_status); else - isci_task_request_complete(ihost, ireq, sci_req->sci_status); + isci_task_request_complete(ihost, ireq, ireq->sci_status); } static void scic_sds_request_aborting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); + struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); /* Setting the abort bit in the Task Context is required by the silicon. */ - sci_req->tc->abort = 1; + ireq->tc->abort = 1; } static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); + struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - scic_sds_remote_device_set_working_request(sci_req->target_device, - sci_req); + scic_sds_remote_device_set_working_request(ireq->target_device, + ireq); } static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); + struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - scic_sds_remote_device_set_working_request(sci_req->target_device, - sci_req); + scic_sds_remote_device_set_working_request(ireq->target_device, + ireq); } static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); + struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - scic_sds_remote_device_set_working_request(sci_req->target_device, - sci_req); + scic_sds_remote_device_set_working_request(ireq->target_device, + ireq); } static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(struct sci_base_state_machine *sm) { - struct scic_sds_request *sci_req = container_of(sm, typeof(*sci_req), sm); - struct scu_task_context *tc = sci_req->tc; + struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); + struct scu_task_context *tc = ireq->tc; struct host_to_dev_fis *h2d_fis; enum sci_status status; /* Clear the SRST bit */ - h2d_fis = &sci_req->stp.cmd; + h2d_fis = &ireq->stp.cmd; h2d_fis->control = 0; /* Clear the TC control bit */ tc->control_frame = 0; - status = scic_controller_continue_io(sci_req); + status = scic_controller_continue_io(ireq); WARN_ONCE(status != SCI_SUCCESS, "isci: continue io failure\n"); } @@ -3006,29 +2990,29 @@ static const struct sci_base_state scic_sds_request_state_table[] = { static void scic_sds_general_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { - sci_init_sm(&sci_req->sm, scic_sds_request_state_table, SCI_REQ_INIT); + sci_init_sm(&ireq->sm, scic_sds_request_state_table, SCI_REQ_INIT); - sci_req->target_device = sci_dev; - sci_req->protocol = SCIC_NO_PROTOCOL; - sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; + ireq->target_device = sci_dev; + ireq->protocol = SCIC_NO_PROTOCOL; + ireq->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; - sci_req->sci_status = SCI_SUCCESS; - sci_req->scu_status = 0; - sci_req->post_context = 0xFFFFFFFF; + ireq->sci_status = SCI_SUCCESS; + ireq->scu_status = 0; + ireq->post_context = 0xFFFFFFFF; } static enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - struct scic_sds_request *sci_req) + struct isci_request *ireq) { struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, sci_req); + scic_sds_general_request_construct(scic, sci_dev, ireq); if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; @@ -3036,31 +3020,31 @@ scic_io_request_construct(struct scic_sds_controller *scic, if (dev->dev_type == SAS_END_DEV) /* pass */; else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) - memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); + memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd)); else if (dev_is_expander(dev)) /* pass */; else return SCI_FAILURE_UNSUPPORTED_PROTOCOL; - memset(sci_req->tc, 0, offsetof(struct scu_task_context, sgl_pair_ab)); + memset(ireq->tc, 0, offsetof(struct scu_task_context, sgl_pair_ab)); return status; } enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, - u16 io_tag, struct scic_sds_request *sci_req) + u16 io_tag, struct isci_request *ireq) { struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, sci_req); + scic_sds_general_request_construct(scic, sci_dev, ireq); if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { - set_bit(IREQ_TMF, &sci_req_to_ireq(sci_req)->flags); - memset(sci_req->tc, 0, sizeof(struct scu_task_context)); + set_bit(IREQ_TMF, &ireq->flags); + memset(ireq->tc, 0, sizeof(struct scu_task_context)); } else status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; @@ -3076,7 +3060,7 @@ static enum sci_status isci_request_ssp_request_construct( "%s: request = %p\n", __func__, request); - status = scic_io_request_construct_basic_ssp(&request->sci); + status = scic_io_request_construct_basic_ssp(request); return status; } @@ -3097,7 +3081,7 @@ static enum sci_status isci_request_stp_request_construct( */ register_fis = isci_sata_task_to_fis_copy(task); - status = scic_io_request_construct_basic_sata(&request->sci); + status = scic_io_request_construct_basic_sata(request); /* Set the ncq tag in the fis, from the queue * command in the task. @@ -3115,7 +3099,7 @@ static enum sci_status isci_request_stp_request_construct( static enum sci_status scic_io_request_construct_smp(struct device *dev, - struct scic_sds_request *sci_req, + struct isci_request *ireq, struct sas_task *task) { struct scatterlist *sg = &task->smp_task.smp_req; @@ -3158,14 +3142,14 @@ scic_io_request_construct_smp(struct device *dev, if (!dma_map_sg(dev, sg, 1, DMA_TO_DEVICE)) return SCI_FAILURE; - sci_req->protocol = SCIC_SMP_PROTOCOL; + ireq->protocol = SCIC_SMP_PROTOCOL; /* byte swap the smp request. */ - task_context = sci_req->tc; + task_context = ireq->tc; - sci_dev = scic_sds_request_get_device(sci_req); - sci_port = scic_sds_request_get_port(sci_req); + sci_dev = scic_sds_request_get_device(ireq); + sci_port = scic_sds_request_get_port(ireq); /* * Fill in the TC with the its required data @@ -3217,12 +3201,12 @@ scic_io_request_construct_smp(struct device *dev, */ task_context->task_phase = 0; - sci_req->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | + ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | (scic_sds_controller_get_protocol_engine_group(scic) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | (scic_sds_port_get_index(sci_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(sci_req->io_tag)); + ISCI_TAG_TCI(ireq->io_tag)); /* * Copy the physical address for the command buffer to the SCU Task * Context command buffer should not contain command header. @@ -3234,7 +3218,7 @@ scic_io_request_construct_smp(struct device *dev, task_context->response_iu_upper = 0; task_context->response_iu_lower = 0; - sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); + sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED); return SCI_SUCCESS; } @@ -3250,10 +3234,9 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) { struct sas_task *task = isci_request_access_task(ireq); struct device *dev = &ireq->isci_host->pdev->dev; - struct scic_sds_request *sci_req = &ireq->sci; enum sci_status status = SCI_FAILURE; - status = scic_io_request_construct_smp(dev, sci_req, task); + status = scic_io_request_construct_smp(dev, ireq, task); if (status != SCI_SUCCESS) dev_warn(&ireq->isci_host->pdev->dev, "%s: failed with status = %d\n", @@ -3309,7 +3292,7 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, } status = scic_io_request_construct(&isci_host->sci, sci_device, - &request->sci); + request); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -3344,7 +3327,7 @@ static struct isci_request *isci_request_from_tag(struct isci_host *ihost, u16 t struct isci_request *ireq; ireq = ihost->reqs[ISCI_TAG_TCI(tag)]; - ireq->sci.io_tag = tag; + ireq->io_tag = tag; ireq->io_request_completion = NULL; ireq->flags = 0; ireq->num_sg_entries = 0; @@ -3416,14 +3399,14 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide */ status = scic_controller_start_task(&ihost->sci, &idev->sci, - &ireq->sci); + ireq); } else { status = SCI_FAILURE; } } else { /* send the request, let the core assign the IO TAG. */ status = scic_controller_start_io(&ihost->sci, &idev->sci, - &ireq->sci); + ireq); } if (status != SCI_SUCCESS && @@ -3446,8 +3429,6 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide list_add(&ireq->dev_node, &idev->reqs_in_process); if (status == SCI_SUCCESS) { - /* Save the tag for possible task mgmt later. */ - ireq->io_tag = ireq->sci.io_tag; isci_request_change_state(ireq, started); } else { /* The request did not really start in the diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 7fd98531d1f2..68d8a27357eb 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -93,7 +93,7 @@ enum sci_request_protocol { * isci_stp_request - extra request infrastructure to handle pio/atapi protocol * @pio_len - number of bytes requested at PIO setup * @status - pio setup ending status value to tell us if we need - * to wait for another fis or if the transfer is complete. Upon + * to wait for another fis or if the transfer is complete. Upon * receipt of a d2h fis this will be the status field of that fis. * @sgl - track pio transfer progress as we iterate through the sgl * @device_cdb_len - atapi device advertises it's transfer constraints at setup @@ -110,69 +110,55 @@ struct isci_stp_request { u32 device_cdb_len; }; -struct scic_sds_request { - /* - * This field contains the information for the base request state - * machine. +struct isci_request { + enum isci_request_status status; + #define IREQ_COMPLETE_IN_TARGET 0 + #define IREQ_TERMINATED 1 + #define IREQ_TMF 2 + #define IREQ_ACTIVE 3 + unsigned long flags; + /* XXX kill ttype and ttype_ptr, allocate full sas_task */ + enum task_type ttype; + union ttype_ptr_union { + struct sas_task *io_task_ptr; /* When ttype==io_task */ + struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */ + } ttype_ptr; + struct isci_host *isci_host; + /* For use in the requests_to_{complete|abort} lists: */ + struct list_head completed_node; + /* For use in the reqs_in_process list: */ + struct list_head dev_node; + spinlock_t state_lock; + dma_addr_t request_daddr; + dma_addr_t zero_scatter_daddr; + unsigned int num_sg_entries; + /* Note: "io_request_completion" is completed in two different ways + * depending on whether this is a TMF or regular request. + * - TMF requests are completed in the thread that started them; + * - regular requests are completed in the request completion callback + * function. + * This difference in operation allows the aborter of a TMF request + * to be sure that once the TMF request completes, the I/O that the + * TMF was aborting is guaranteed to have completed. + * + * XXX kill io_request_completion */ + struct completion *io_request_completion; struct sci_base_state_machine sm; - - /* - * This field simply points to the controller to which this IO request - * is associated. - */ struct scic_sds_controller *owning_controller; - - /* - * This field simply points to the remote device to which this IO - * request is associated. - */ struct scic_sds_remote_device *target_device; - - /* - * This field indicates the IO tag for this request. The IO tag is - * comprised of the task_index and a sequence count. The sequence count - * is utilized to help identify tasks from one life to another. - */ u16 io_tag; - - /* - * This field specifies the protocol being utilized for this - * IO request. - */ enum sci_request_protocol protocol; - - /* - * This field indicates the completion status taken from the SCUs - * completion code. It indicates the completion result for the SCU - * hardware. - */ - u32 scu_status; - - /* - * This field indicates the completion status returned to the SCI user. - * It indicates the users view of the io request completion. - */ - u32 sci_status; - - /* - * This field contains the value to be utilized when posting - * (e.g. Post_TC, * Post_TC_Abort) this request to the silicon. - */ + u32 scu_status; /* hardware result */ + u32 sci_status; /* upper layer disposition */ u32 post_context; - struct scu_task_context *tc; - /* could be larger with sg chaining */ #define SCU_SGL_SIZE ((SCI_MAX_SCATTER_GATHER_ELEMENTS + 1) / 2) struct scu_sgl_element_pair sg_table[SCU_SGL_SIZE] __attribute__ ((aligned(32))); - - /* - * This field is a pointer to the stored rx frame data. It is used in + /* This field is a pointer to the stored rx frame data. It is used in * STP internal requests and SMP response frames. If this field is * non-NULL the saved frame must be released on IO request completion. - * - * @todo In the future do we want to keep a list of RX frame buffers? */ u32 saved_rx_frame_index; @@ -187,11 +173,9 @@ struct scic_sds_request { u8 rsp_buf[SSP_RESP_IU_MAX_SIZE]; }; } ssp; - struct { struct smp_resp rsp; } smp; - struct { struct isci_stp_request req; struct host_to_dev_fis cmd; @@ -200,56 +184,11 @@ struct scic_sds_request { }; }; -static inline struct scic_sds_request *to_sci_req(struct isci_stp_request *stp_req) -{ - struct scic_sds_request *sci_req; - - sci_req = container_of(stp_req, typeof(*sci_req), stp.req); - return sci_req; -} - -struct isci_request { - enum isci_request_status status; - enum task_type ttype; - unsigned short io_tag; - #define IREQ_COMPLETE_IN_TARGET 0 - #define IREQ_TERMINATED 1 - #define IREQ_TMF 2 - #define IREQ_ACTIVE 3 - unsigned long flags; - - union ttype_ptr_union { - struct sas_task *io_task_ptr; /* When ttype==io_task */ - struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */ - } ttype_ptr; - struct isci_host *isci_host; - /* For use in the requests_to_{complete|abort} lists: */ - struct list_head completed_node; - /* For use in the reqs_in_process list: */ - struct list_head dev_node; - spinlock_t state_lock; - dma_addr_t request_daddr; - dma_addr_t zero_scatter_daddr; - - unsigned int num_sg_entries; /* returned by pci_alloc_sg */ - - /** Note: "io_request_completion" is completed in two different ways - * depending on whether this is a TMF or regular request. - * - TMF requests are completed in the thread that started them; - * - regular requests are completed in the request completion callback - * function. - * This difference in operation allows the aborter of a TMF request - * to be sure that once the TMF request completes, the I/O that the - * TMF was aborting is guaranteed to have completed. - */ - struct completion *io_request_completion; - struct scic_sds_request sci; -}; - -static inline struct isci_request *sci_req_to_ireq(struct scic_sds_request *sci_req) +static inline struct isci_request *to_ireq(struct isci_stp_request *stp_req) { - struct isci_request *ireq = container_of(sci_req, typeof(*ireq), sci); + struct isci_request *ireq; + ireq = container_of(stp_req, typeof(*ireq), stp.req); return ireq; } @@ -366,32 +305,32 @@ enum sci_base_request_states { * * This macro will return the controller for this io request object */ -#define scic_sds_request_get_controller(sci_req) \ - ((sci_req)->owning_controller) +#define scic_sds_request_get_controller(ireq) \ + ((ireq)->owning_controller) /** * scic_sds_request_get_device() - * * This macro will return the device for this io request object */ -#define scic_sds_request_get_device(sci_req) \ - ((sci_req)->target_device) +#define scic_sds_request_get_device(ireq) \ + ((ireq)->target_device) /** * scic_sds_request_get_port() - * * This macro will return the port for this io request object */ -#define scic_sds_request_get_port(sci_req) \ - scic_sds_remote_device_get_port(scic_sds_request_get_device(sci_req)) +#define scic_sds_request_get_port(ireq) \ + scic_sds_remote_device_get_port(scic_sds_request_get_device(ireq)) /** * scic_sds_request_get_post_context() - * * This macro returns the constructed post context result for the io request. */ -#define scic_sds_request_get_post_context(sci_req) \ - ((sci_req)->post_context) +#define scic_sds_request_get_post_context(ireq) \ + ((ireq)->post_context) /** * scic_sds_request_get_task_context() - @@ -413,26 +352,25 @@ enum sci_base_request_states { (request)->sci_status = (sci_status_code); \ } -enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); -enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); +enum sci_status scic_sds_request_start(struct isci_request *ireq); +enum sci_status scic_sds_io_request_terminate(struct isci_request *ireq); enum sci_status -scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, +scic_sds_io_request_event_handler(struct isci_request *ireq, u32 event_code); enum sci_status -scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, +scic_sds_io_request_frame_handler(struct isci_request *ireq, u32 frame_index); enum sci_status -scic_sds_task_request_terminate(struct scic_sds_request *sci_req); +scic_sds_task_request_terminate(struct isci_request *ireq); extern enum sci_status -scic_sds_request_complete(struct scic_sds_request *sci_req); +scic_sds_request_complete(struct isci_request *ireq); extern enum sci_status -scic_sds_io_request_tc_completion(struct scic_sds_request *sci_req, u32 code); +scic_sds_io_request_tc_completion(struct isci_request *ireq, u32 code); /* XXX open code in caller */ static inline dma_addr_t -scic_io_request_get_dma_addr(struct scic_sds_request *sci_req, void *virt_addr) +scic_io_request_get_dma_addr(struct isci_request *ireq, void *virt_addr) { - struct isci_request *ireq = sci_req_to_ireq(sci_req); char *requested_addr = (char *)virt_addr; char *base_addr = (char *)ireq; @@ -565,14 +503,14 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, struct scic_sds_remote_device *sci_dev, u16 io_tag, - struct scic_sds_request *sci_req); + struct isci_request *ireq); enum sci_status -scic_task_request_construct_ssp(struct scic_sds_request *sci_req); +scic_task_request_construct_ssp(struct isci_request *ireq); enum sci_status -scic_task_request_construct_sata(struct scic_sds_request *sci_req); +scic_task_request_construct_sata(struct isci_request *ireq); void -scic_stp_io_request_set_ncq_tag(struct scic_sds_request *sci_req, u16 ncq_tag); -void scic_sds_smp_request_copy_response(struct scic_sds_request *sci_req); +scic_stp_io_request_set_ncq_tag(struct isci_request *ireq, u16 ncq_tag); +void scic_sds_smp_request_copy_response(struct isci_request *ireq); static inline int isci_task_is_ncq_recovery(struct sas_task *task) { diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index e7ce46924465..87d8cc1a6e39 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -70,7 +70,7 @@ struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task) { struct isci_request *ireq = task->lldd_task; - struct host_to_dev_fis *fis = &ireq->sci.stp.cmd; + struct host_to_dev_fis *fis = &ireq->stp.cmd; memcpy(fis, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); @@ -116,7 +116,7 @@ void isci_sata_set_ncq_tag( struct isci_request *request = task->lldd_task; register_fis->sector_count = qc->tag << 3; - scic_stp_io_request_set_ncq_tag(&request->sci, qc->tag); + scic_stp_io_request_set_ncq_tag(request, qc->tag); } /** @@ -154,7 +154,6 @@ void isci_request_process_stp_response(struct sas_task *task, enum sci_status isci_sata_management_task_request_build(struct isci_request *ireq) { - struct scic_sds_request *sci_req = &ireq->sci; struct isci_tmf *isci_tmf; enum sci_status status; @@ -167,7 +166,7 @@ enum sci_status isci_sata_management_task_request_build(struct isci_request *ire case isci_tmf_sata_srst_high: case isci_tmf_sata_srst_low: { - struct host_to_dev_fis *fis = &sci_req->stp.cmd; + struct host_to_dev_fis *fis = &ireq->stp.cmd; memset(fis, 0, sizeof(*fis)); @@ -188,7 +187,7 @@ enum sci_status isci_sata_management_task_request_build(struct isci_request *ire /* core builds the protocol specific request * based on the h2d fis. */ - status = scic_task_request_construct_sata(&ireq->sci); + status = scic_task_request_construct_sata(ireq); return status; } diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index d2dba8354899..700708c82678 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -258,7 +258,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, /* let the core do it's construct. */ status = scic_task_request_construct(&ihost->sci, &idev->sci, tag, - &ireq->sci); + ireq); if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, @@ -272,7 +272,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, /* XXX convert to get this from task->tproto like other drivers */ if (dev->dev_type == SAS_END_DEV) { isci_tmf->proto = SAS_PROTOCOL_SSP; - status = scic_task_request_construct_ssp(&ireq->sci); + status = scic_task_request_construct_ssp(ireq); if (status != SCI_SUCCESS) return NULL; } @@ -337,7 +337,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, /* start the TMF io. */ status = scic_controller_start_task(&ihost->sci, sci_device, - &ireq->sci); + ireq); if (status != SCI_TASK_SUCCESS) { dev_warn(&ihost->pdev->dev, @@ -371,7 +371,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, scic_controller_terminate_request(&ihost->sci, &isci_device->sci, - &ireq->sci); + ireq); spin_unlock_irqrestore(&ihost->scic_lock, flags); @@ -565,7 +565,7 @@ static void isci_terminate_request_core( status = scic_controller_terminate_request( &isci_host->sci, &isci_device->sci, - &isci_request->sci); + isci_request); } spin_unlock_irqrestore(&isci_host->scic_lock, flags); @@ -1235,7 +1235,6 @@ isci_task_request_complete(struct isci_host *ihost, { struct isci_tmf *tmf = isci_request_access_tmf(ireq); struct completion *tmf_complete; - struct scic_sds_request *sci_req = &ireq->sci; dev_dbg(&ihost->pdev->dev, "%s: request = %p, status=%d\n", @@ -1248,18 +1247,18 @@ isci_task_request_complete(struct isci_host *ihost, if (tmf->proto == SAS_PROTOCOL_SSP) { memcpy(&tmf->resp.resp_iu, - &sci_req->ssp.rsp, + &ireq->ssp.rsp, SSP_RESP_IU_MAX_SIZE); } else if (tmf->proto == SAS_PROTOCOL_SATA) { memcpy(&tmf->resp.d2h_fis, - &sci_req->stp.rsp, + &ireq->stp.rsp, sizeof(struct dev_to_host_fis)); } /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; - scic_controller_complete_io(&ihost->sci, ireq->sci.target_device, &ireq->sci); + scic_controller_complete_io(&ihost->sci, ireq->target_device, ireq); /* set the 'terminated' flag handle to make sure it cannot be terminated * or completed again. */ -- cgit v1.2.3 From 852809559e4680ba4768262a6c3d21454fcd460e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 28 Jun 2011 15:05:53 -0700 Subject: isci: unify isci_phy and scic_sds_phy They are one in the same object so remove the distinction. The near duplicate fields (owning_port, and isci_port) will be cleaned up after the scic_sds_port isci_port unification. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 92 ++++---- drivers/scsi/isci/host.h | 17 +- drivers/scsi/isci/phy.c | 479 +++++++++++++++++++------------------- drivers/scsi/isci/phy.h | 112 ++------- drivers/scsi/isci/port.c | 299 ++++++++++-------------- drivers/scsi/isci/port.h | 16 +- drivers/scsi/isci/port_config.c | 135 +++++------ drivers/scsi/isci/remote_device.c | 2 +- 8 files changed, 500 insertions(+), 652 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index d91cd6d82747..c5c2733a5197 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -311,7 +311,7 @@ static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *sc struct isci_host *ihost = scic_to_ihost(scic); struct scu_unsolicited_frame_header *frame_header; - struct scic_sds_phy *phy; + struct isci_phy *iphy; struct scic_sds_remote_device *device; enum sci_status result = SCI_FAILURE; @@ -332,8 +332,8 @@ static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *sc if (frame_header->is_address_frame) { index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &ihost->phys[index].sci; - result = scic_sds_phy_frame_handler(phy, frame_index); + iphy = &ihost->phys[index]; + result = scic_sds_phy_frame_handler(iphy, frame_index); } else { index = SCU_GET_COMPLETION_INDEX(completion_entry); @@ -344,8 +344,8 @@ static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *sc * device that has not yet been created. In either case forwared * the frame to the PE and let it take care of the frame data. */ index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &ihost->phys[index].sci; - result = scic_sds_phy_frame_handler(phy, frame_index); + iphy = &ihost->phys[index]; + result = scic_sds_phy_frame_handler(iphy, frame_index); } else { if (index < scic->remote_node_entries) device = scic->device_table[index]; @@ -372,7 +372,7 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci struct isci_host *ihost = scic_to_ihost(scic); struct scic_sds_remote_device *device; struct isci_request *ireq; - struct scic_sds_phy *phy; + struct isci_phy *iphy; u32 index; index = SCU_GET_COMPLETION_INDEX(completion_entry); @@ -452,8 +452,8 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci * we get the event notification. This is a type 4 event. */ case SCU_EVENT_TYPE_OSSP_EVENT: index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); - phy = &ihost->phys[index].sci; - scic_sds_phy_event_handler(phy, completion_entry); + iphy = &ihost->phys[index]; + scic_sds_phy_event_handler(iphy, completion_entry); break; case SCU_EVENT_TYPE_RNC_SUSPEND_TX: @@ -862,11 +862,11 @@ static void scic_sds_controller_transition_to_ready( } } -static bool is_phy_starting(struct scic_sds_phy *sci_phy) +static bool is_phy_starting(struct isci_phy *iphy) { enum scic_sds_phy_states state; - state = sci_phy->sm.current_state_id; + state = iphy->sm.current_state_id; switch (state) { case SCI_PHY_STARTING: case SCI_PHY_SUB_INITIAL: @@ -896,7 +896,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro { struct isci_host *ihost = scic_to_ihost(scic); struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; - struct scic_sds_phy *sci_phy; + struct isci_phy *iphy; enum sci_status status; status = SCI_SUCCESS; @@ -910,10 +910,10 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro u8 index; for (index = 0; index < SCI_MAX_PHYS; index++) { - sci_phy = &ihost->phys[index].sci; - state = sci_phy->sm.current_state_id; + iphy = &ihost->phys[index]; + state = iphy->sm.current_state_id; - if (!phy_get_non_dummy_port(sci_phy)) + if (!phy_get_non_dummy_port(iphy)) continue; /* The controller start operation is complete iff: @@ -922,9 +922,9 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro * - have an indication of a connected device and it has * finished the link training process. */ - if ((sci_phy->is_in_link_training == false && state == SCI_PHY_INITIAL) || - (sci_phy->is_in_link_training == false && state == SCI_PHY_STOPPED) || - (sci_phy->is_in_link_training == true && is_phy_starting(sci_phy))) { + if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) || + (iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) || + (iphy->is_in_link_training == true && is_phy_starting(iphy))) { is_controller_start_complete = false; break; } @@ -939,10 +939,10 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro scic->phy_startup_timer_pending = false; } } else { - sci_phy = &ihost->phys[scic->next_phy_to_start].sci; + iphy = &ihost->phys[scic->next_phy_to_start]; if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { - if (phy_get_non_dummy_port(sci_phy) == NULL) { + if (phy_get_non_dummy_port(iphy) == NULL) { scic->next_phy_to_start++; /* Caution recursion ahead be forwarned @@ -958,7 +958,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro } } - status = scic_sds_phy_start(sci_phy); + status = scic_sds_phy_start(iphy); if (status == SCI_SUCCESS) { sci_mod_timer(&scic->phy_timer, @@ -970,7 +970,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro "to stop phy %d because of status " "%d.\n", __func__, - ihost->phys[scic->next_phy_to_start].sci.phy_index, + ihost->phys[scic->next_phy_to_start].phy_index, status); } @@ -1312,8 +1312,8 @@ void isci_host_deinit(struct isci_host *ihost) /* Cancel any/all outstanding phy timers */ for (i = 0; i < SCI_MAX_PHYS; i++) { - struct scic_sds_phy *sci_phy = &ihost->phys[i].sci; - del_timer_sync(&sci_phy->sata_timer.timer); + struct isci_phy *iphy = &ihost->phys[i]; + del_timer_sync(&iphy->sata_timer.timer); } del_timer_sync(&ihost->sci.port_agent.timer.timer); @@ -1527,7 +1527,7 @@ static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller status = SCI_SUCCESS; for (index = 0; index < SCI_MAX_PHYS; index++) { - phy_status = scic_sds_phy_stop(&ihost->phys[index].sci); + phy_status = scic_sds_phy_stop(&ihost->phys[index]); if (phy_status != SCI_SUCCESS && phy_status != SCI_FAILURE_INVALID_STATE) { @@ -1537,7 +1537,7 @@ static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller "%s: Controller stop operation failed to stop " "phy %d because of status %d.\n", __func__, - ihost->phys[index].sci.phy_index, phy_status); + ihost->phys[index].phy_index, phy_status); } } @@ -1786,7 +1786,7 @@ static enum sci_status scic_controller_construct(struct scic_sds_controller *sci /* Construct the phys for this controller */ for (i = 0; i < SCI_MAX_PHYS; i++) { /* Add all the PHYs to the dummy port */ - scic_sds_phy_construct(&ihost->phys[i].sci, + scic_sds_phy_construct(&ihost->phys[i], &ihost->ports[SCI_MAX_PORTS].sci, i); } @@ -1865,7 +1865,7 @@ static void power_control_timeout(unsigned long data) struct sci_timer *tmr = (struct sci_timer *)data; struct scic_sds_controller *scic = container_of(tmr, typeof(*scic), power_control.timer); struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_phy *sci_phy; + struct isci_phy *iphy; unsigned long flags; u8 i; @@ -1886,8 +1886,8 @@ static void power_control_timeout(unsigned long data) if (scic->power_control.phys_waiting == 0) break; - sci_phy = scic->power_control.requesters[i]; - if (sci_phy == NULL) + iphy = scic->power_control.requesters[i]; + if (iphy == NULL) continue; if (scic->power_control.phys_granted_power >= @@ -1897,7 +1897,7 @@ static void power_control_timeout(unsigned long data) scic->power_control.requesters[i] = NULL; scic->power_control.phys_waiting--; scic->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(sci_phy); + scic_sds_phy_consume_power_handler(iphy); } /* @@ -1919,14 +1919,14 @@ done: */ void scic_sds_controller_power_control_queue_insert( struct scic_sds_controller *scic, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { - BUG_ON(sci_phy == NULL); + BUG_ON(iphy == NULL); if (scic->power_control.phys_granted_power < scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { scic->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(sci_phy); + scic_sds_phy_consume_power_handler(iphy); /* * stop and start the power_control timer. When the timer fires, the @@ -1941,7 +1941,7 @@ void scic_sds_controller_power_control_queue_insert( } else { /* Add the phy in the waiting list */ - scic->power_control.requesters[sci_phy->phy_index] = sci_phy; + scic->power_control.requesters[iphy->phy_index] = iphy; scic->power_control.phys_waiting++; } } @@ -1954,15 +1954,15 @@ void scic_sds_controller_power_control_queue_insert( */ void scic_sds_controller_power_control_queue_remove( struct scic_sds_controller *scic, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { - BUG_ON(sci_phy == NULL); + BUG_ON(iphy == NULL); - if (scic->power_control.requesters[sci_phy->phy_index] != NULL) { + if (scic->power_control.requesters[iphy->phy_index] != NULL) { scic->power_control.phys_waiting--; } - scic->power_control.requesters[sci_phy->phy_index] = NULL; + scic->power_control.requesters[iphy->phy_index] = NULL; } #define AFE_REGISTER_WRITE_DELAY 10 @@ -2225,7 +2225,7 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc * are accessed during the port initialization. */ for (i = 0; i < SCI_MAX_PHYS; i++) { - result = scic_sds_phy_initialize(&ihost->phys[i].sci, + result = scic_sds_phy_initialize(&ihost->phys[i], &scic->scu_registers->peg0.pe[i].tl, &scic->scu_registers->peg0.pe[i].ll); if (result != SCI_SUCCESS) @@ -2484,43 +2484,43 @@ int isci_host_init(struct isci_host *isci_host) } void scic_sds_controller_link_up(struct scic_sds_controller *scic, - struct scic_sds_port *port, struct scic_sds_phy *phy) + struct scic_sds_port *port, struct isci_phy *iphy) { switch (scic->sm.current_state_id) { case SCIC_STARTING: sci_del_timer(&scic->phy_timer); scic->phy_startup_timer_pending = false; scic->port_agent.link_up_handler(scic, &scic->port_agent, - port, phy); + port, iphy); scic_sds_controller_start_next_phy(scic); break; case SCIC_READY: scic->port_agent.link_up_handler(scic, &scic->port_agent, - port, phy); + port, iphy); break; default: dev_dbg(scic_to_dev(scic), "%s: SCIC Controller linkup event from phy %d in " - "unexpected state %d\n", __func__, phy->phy_index, + "unexpected state %d\n", __func__, iphy->phy_index, scic->sm.current_state_id); } } void scic_sds_controller_link_down(struct scic_sds_controller *scic, - struct scic_sds_port *port, struct scic_sds_phy *phy) + struct scic_sds_port *port, struct isci_phy *iphy) { switch (scic->sm.current_state_id) { case SCIC_STARTING: case SCIC_READY: scic->port_agent.link_down_handler(scic, &scic->port_agent, - port, phy); + port, iphy); break; default: dev_dbg(scic_to_dev(scic), "%s: SCIC Controller linkdown event from phy %d in " "unexpected state %d\n", __func__, - phy->phy_index, + iphy->phy_index, scic->sm.current_state_id); } } diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 0b26d25c19a9..1edd13535c24 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -101,14 +101,14 @@ struct scic_power_control { * This field is an array of phys that we are waiting on. The phys are direct * mapped into requesters via struct scic_sds_phy.phy_index */ - struct scic_sds_phy *requesters[SCI_MAX_PHYS]; + struct isci_phy *requesters[SCI_MAX_PHYS]; }; struct scic_sds_port_configuration_agent; typedef void (*port_config_fn)(struct scic_sds_controller *, struct scic_sds_port_configuration_agent *, - struct scic_sds_port *, struct scic_sds_phy *); + struct scic_sds_port *, struct isci_phy *); struct scic_sds_port_configuration_agent { u16 phy_configured_mask; @@ -523,9 +523,8 @@ static inline struct device *scic_to_dev(struct scic_sds_controller *scic) return &scic_to_ihost(scic)->pdev->dev; } -static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) +static inline struct device *sciphy_to_dev(struct isci_phy *iphy) { - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host) return NULL; @@ -606,21 +605,21 @@ struct isci_request *scic_request_by_tag(struct scic_sds_controller *scic, void scic_sds_controller_power_control_queue_insert( struct scic_sds_controller *scic, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); void scic_sds_controller_power_control_queue_remove( struct scic_sds_controller *scic, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); void scic_sds_controller_link_up( struct scic_sds_controller *scic, struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); void scic_sds_controller_link_down( struct scic_sds_controller *scic, struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); void scic_sds_controller_remote_device_stopped( struct scic_sds_controller *scic, @@ -651,7 +650,7 @@ void isci_host_deinit( void isci_host_port_link_up( struct isci_host *, struct scic_sds_port *, - struct scic_sds_phy *); + struct isci_phy *); int isci_host_dev_found(struct domain_device *); void isci_host_remote_device_start_complete( diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 98d93aeea75d..0e60fb7bc1ab 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -62,9 +62,9 @@ /* Maximum arbitration wait time in micro-seconds */ #define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) -enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy) +enum sas_linkrate sci_phy_linkrate(struct isci_phy *iphy) { - return sci_phy->max_negotiated_speed; + return iphy->max_negotiated_speed; } /* @@ -80,23 +80,23 @@ enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy) * enum sci_status */ static enum sci_status scic_sds_phy_transport_layer_initialization( - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, struct scu_transport_layer_registers __iomem *transport_layer_registers) { u32 tl_control; - sci_phy->transport_layer_registers = transport_layer_registers; + iphy->transport_layer_registers = transport_layer_registers; writel(SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX, - &sci_phy->transport_layer_registers->stp_rni); + &iphy->transport_layer_registers->stp_rni); /* * Hardware team recommends that we enable the STP prefetch for all * transports */ - tl_control = readl(&sci_phy->transport_layer_registers->control); + tl_control = readl(&iphy->transport_layer_registers->control); tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); - writel(tl_control, &sci_phy->transport_layer_registers->control); + writel(tl_control, &iphy->transport_layer_registers->control); return SCI_SUCCESS; } @@ -109,12 +109,12 @@ static enum sci_status scic_sds_phy_transport_layer_initialization( * enum sci_status */ static enum sci_status -scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, +scic_sds_phy_link_layer_initialization(struct isci_phy *iphy, struct scu_link_layer_registers __iomem *link_layer_registers) { struct scic_sds_controller *scic = - sci_phy->owning_port->owning_controller; - int phy_idx = sci_phy->phy_index; + iphy->owning_port->owning_controller; + int phy_idx = iphy->phy_index; struct sci_phy_user_params *phy_user = &scic->user_parameters.sds1.phys[phy_idx]; struct sci_phy_oem_params *phy_oem = @@ -126,7 +126,7 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, u32 llctl, link_rate; u32 clksm_value = 0; - sci_phy->link_layer_registers = link_layer_registers; + iphy->link_layer_registers = link_layer_registers; /* Set our IDENTIFY frame data */ #define SCI_END_DEVICE 0x01 @@ -136,32 +136,32 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE), - &sci_phy->link_layer_registers->transmit_identification); + &iphy->link_layer_registers->transmit_identification); /* Write the device SAS Address */ writel(0xFEDCBA98, - &sci_phy->link_layer_registers->sas_device_name_high); - writel(phy_idx, &sci_phy->link_layer_registers->sas_device_name_low); + &iphy->link_layer_registers->sas_device_name_high); + writel(phy_idx, &iphy->link_layer_registers->sas_device_name_low); /* Write the source SAS Address */ writel(phy_oem->sas_address.high, - &sci_phy->link_layer_registers->source_sas_address_high); + &iphy->link_layer_registers->source_sas_address_high); writel(phy_oem->sas_address.low, - &sci_phy->link_layer_registers->source_sas_address_low); + &iphy->link_layer_registers->source_sas_address_low); /* Clear and Set the PHY Identifier */ - writel(0, &sci_phy->link_layer_registers->identify_frame_phy_id); + writel(0, &iphy->link_layer_registers->identify_frame_phy_id); writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), - &sci_phy->link_layer_registers->identify_frame_phy_id); + &iphy->link_layer_registers->identify_frame_phy_id); /* Change the initial state of the phy configuration register */ phy_configuration = - readl(&sci_phy->link_layer_registers->phy_configuration); + readl(&iphy->link_layer_registers->phy_configuration); /* Hold OOB state machine in reset */ phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); writel(phy_configuration, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); /* Configure the SNW capabilities */ phy_cap.all = 0; @@ -191,14 +191,14 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, if ((parity_count % 2) != 0) phy_cap.parity = 1; - writel(phy_cap.all, &sci_phy->link_layer_registers->phy_capabilities); + writel(phy_cap.all, &iphy->link_layer_registers->phy_capabilities); /* Set the enable spinup period but disable the ability to send * notify enable spinup */ writel(SCU_ENSPINUP_GEN_VAL(COUNT, phy_user->notify_enable_spin_up_insertion_frequency), - &sci_phy->link_layer_registers->notify_enable_spinup_control); + &iphy->link_layer_registers->notify_enable_spinup_control); /* Write the ALIGN Insertion Ferequency for connected phy and * inpendent of connected state @@ -209,11 +209,11 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL, phy_user->align_insertion_frequency); - writel(clksm_value, &sci_phy->link_layer_registers->clock_skew_management); + writel(clksm_value, &iphy->link_layer_registers->clock_skew_management); /* @todo Provide a way to write this register correctly */ writel(0x02108421, - &sci_phy->link_layer_registers->afe_lookup_table_control); + &iphy->link_layer_registers->afe_lookup_table_control); llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, (u8)scic->user_parameters.sds1.no_outbound_task_timeout); @@ -230,7 +230,7 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, break; } llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate); - writel(llctl, &sci_phy->link_layer_registers->link_layer_control); + writel(llctl, &iphy->link_layer_registers->link_layer_control); if (is_a0() || is_a2()) { /* Program the max ARB time for the PHY to 700us so we inter-operate with @@ -239,14 +239,14 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, * generate the break. */ writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME, - &sci_phy->link_layer_registers->maximum_arbitration_wait_timer_timeout); + &iphy->link_layer_registers->maximum_arbitration_wait_timer_timeout); } /* Disable link layer hang detection, rely on the OS timeout for I/O timeouts. */ - writel(0, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout); + writel(0, &iphy->link_layer_registers->link_layer_hang_detection_timeout); /* We can exit the initial state to the stopped state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STOPPED); + sci_change_state(&iphy->sm, SCI_PHY_STOPPED); return SCI_SUCCESS; } @@ -254,8 +254,8 @@ scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy, static void phy_sata_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; - struct scic_sds_phy *sci_phy = container_of(tmr, typeof(*sci_phy), sata_timer); - struct isci_host *ihost = scic_to_ihost(sci_phy->owning_port->owning_controller); + struct isci_phy *iphy = container_of(tmr, typeof(*iphy), sata_timer); + struct isci_host *ihost = scic_to_ihost(iphy->owning_port->owning_controller); unsigned long flags; spin_lock_irqsave(&ihost->scic_lock, flags); @@ -263,13 +263,13 @@ static void phy_sata_timeout(unsigned long data) if (tmr->cancel) goto done; - dev_dbg(sciphy_to_dev(sci_phy), + dev_dbg(sciphy_to_dev(iphy), "%s: SCIC SDS Phy 0x%p did not receive signature fis before " "timeout.\n", __func__, - sci_phy); + iphy); - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } @@ -287,30 +287,30 @@ done: * values indicate a handle/pointer to the port containing the phy. */ struct scic_sds_port *phy_get_non_dummy_port( - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { - if (scic_sds_port_get_index(sci_phy->owning_port) == SCIC_SDS_DUMMY_PORT) + if (scic_sds_port_get_index(iphy->owning_port) == SCIC_SDS_DUMMY_PORT) return NULL; - return sci_phy->owning_port; + return iphy->owning_port; } /** * This method will assign a port to the phy object. - * @out]: sci_phy This parameter specifies the phy for which to assign a port + * @out]: iphy This parameter specifies the phy for which to assign a port * object. * * */ void scic_sds_phy_set_port( - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, struct scic_sds_port *sci_port) { - sci_phy->owning_port = sci_port; + iphy->owning_port = sci_port; - if (sci_phy->bcn_received_while_port_unassigned) { - sci_phy->bcn_received_while_port_unassigned = false; - scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); + if (iphy->bcn_received_while_port_unassigned) { + iphy->bcn_received_while_port_unassigned = false; + scic_sds_port_broadcast_change_received(iphy->owning_port, iphy); } } @@ -322,22 +322,22 @@ void scic_sds_phy_set_port( * enum sci_status */ enum sci_status scic_sds_phy_initialize( - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, struct scu_transport_layer_registers __iomem *transport_layer_registers, struct scu_link_layer_registers __iomem *link_layer_registers) { /* Perfrom the initialization of the TL hardware */ scic_sds_phy_transport_layer_initialization( - sci_phy, + iphy, transport_layer_registers); /* Perofrm the initialization of the PE hardware */ - scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers); + scic_sds_phy_link_layer_initialization(iphy, link_layer_registers); /* * There is nothing that needs to be done in this state just * transition to the stopped state. */ - sci_change_state(&sci_phy->sm, SCI_PHY_STOPPED); + sci_change_state(&iphy->sm, SCI_PHY_STOPPED); return SCI_SUCCESS; } @@ -345,27 +345,27 @@ enum sci_status scic_sds_phy_initialize( /** * This method assigns the direct attached device ID for this phy. * - * @sci_phy The phy for which the direct attached device id is to + * @iphy The phy for which the direct attached device id is to * be assigned. * @device_id The direct attached device ID to assign to the phy. * This will either be the RNi for the device or an invalid RNi if there * is no current device assigned to the phy. */ void scic_sds_phy_setup_transport( - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, u32 device_id) { u32 tl_control; - writel(device_id, &sci_phy->transport_layer_registers->stp_rni); + writel(device_id, &iphy->transport_layer_registers->stp_rni); /* * The read should guarantee that the first write gets posted * before the next write */ - tl_control = readl(&sci_phy->transport_layer_registers->control); + tl_control = readl(&iphy->transport_layer_registers->control); tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); - writel(tl_control, &sci_phy->transport_layer_registers->control); + writel(tl_control, &iphy->transport_layer_registers->control); } /** @@ -376,75 +376,74 @@ void scic_sds_phy_setup_transport( * hardware protocol engine. none */ static void scic_sds_phy_suspend( - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { u32 scu_sas_pcfg_value; scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); + readl(&iphy->link_layer_registers->phy_configuration); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); scic_sds_phy_setup_transport( - sci_phy, + iphy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); } -void scic_sds_phy_resume(struct scic_sds_phy *sci_phy) +void scic_sds_phy_resume(struct isci_phy *iphy) { u32 scu_sas_pcfg_value; scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); + readl(&iphy->link_layer_registers->phy_configuration); scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); } -void scic_sds_phy_get_sas_address(struct scic_sds_phy *sci_phy, +void scic_sds_phy_get_sas_address(struct isci_phy *iphy, struct sci_sas_address *sas_address) { - sas_address->high = readl(&sci_phy->link_layer_registers->source_sas_address_high); - sas_address->low = readl(&sci_phy->link_layer_registers->source_sas_address_low); + sas_address->high = readl(&iphy->link_layer_registers->source_sas_address_high); + sas_address->low = readl(&iphy->link_layer_registers->source_sas_address_low); } -void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy, +void scic_sds_phy_get_attached_sas_address(struct isci_phy *iphy, struct sci_sas_address *sas_address) { struct sas_identify_frame *iaf; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); iaf = &iphy->frame_rcvd.iaf; memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); } -void scic_sds_phy_get_protocols(struct scic_sds_phy *sci_phy, +void scic_sds_phy_get_protocols(struct isci_phy *iphy, struct scic_phy_proto *protocols) { protocols->all = - (u16)(readl(&sci_phy-> + (u16)(readl(&iphy-> link_layer_registers->transmit_identification) & 0x0000FFFF); } -enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy) +enum sci_status scic_sds_phy_start(struct isci_phy *iphy) { - enum scic_sds_phy_states state = sci_phy->sm.current_state_id; + enum scic_sds_phy_states state = iphy->sm.current_state_id; if (state != SCI_PHY_STOPPED) { - dev_dbg(sciphy_to_dev(sci_phy), + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); return SCI_SUCCESS; } -enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) +enum sci_status scic_sds_phy_stop(struct isci_phy *iphy) { - enum scic_sds_phy_states state = sci_phy->sm.current_state_id; + enum scic_sds_phy_states state = iphy->sm.current_state_id; switch (state) { case SCI_PHY_SUB_INITIAL: @@ -459,43 +458,43 @@ enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy) case SCI_PHY_READY: break; default: - dev_dbg(sciphy_to_dev(sci_phy), + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - sci_change_state(&sci_phy->sm, SCI_PHY_STOPPED); + sci_change_state(&iphy->sm, SCI_PHY_STOPPED); return SCI_SUCCESS; } -enum sci_status scic_sds_phy_reset(struct scic_sds_phy *sci_phy) +enum sci_status scic_sds_phy_reset(struct isci_phy *iphy) { - enum scic_sds_phy_states state = sci_phy->sm.current_state_id; + enum scic_sds_phy_states state = iphy->sm.current_state_id; if (state != SCI_PHY_READY) { - dev_dbg(sciphy_to_dev(sci_phy), + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - sci_change_state(&sci_phy->sm, SCI_PHY_RESETTING); + sci_change_state(&iphy->sm, SCI_PHY_RESETTING); return SCI_SUCCESS; } -enum sci_status scic_sds_phy_consume_power_handler(struct scic_sds_phy *sci_phy) +enum sci_status scic_sds_phy_consume_power_handler(struct isci_phy *iphy) { - enum scic_sds_phy_states state = sci_phy->sm.current_state_id; + enum scic_sds_phy_states state = iphy->sm.current_state_id; switch (state) { case SCI_PHY_SUB_AWAIT_SAS_POWER: { u32 enable_spinup; - enable_spinup = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); + enable_spinup = readl(&iphy->link_layer_registers->notify_enable_spinup_control); enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); - writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control); + writel(enable_spinup, &iphy->link_layer_registers->notify_enable_spinup_control); /* Change state to the final state this substate machine has run to completion */ - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_FINAL); + sci_change_state(&iphy->sm, SCI_PHY_SUB_FINAL); return SCI_SUCCESS; } @@ -504,26 +503,26 @@ enum sci_status scic_sds_phy_consume_power_handler(struct scic_sds_phy *sci_phy) /* Release the spinup hold state and reset the OOB state machine */ scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); + readl(&iphy->link_layer_registers->phy_configuration); scu_sas_pcfg_value &= ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); /* Now restart the OOB operation */ scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); /* Change state to the final state this substate machine has run to completion */ - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SATA_PHY_EN); + sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_PHY_EN); return SCI_SUCCESS; } default: - dev_dbg(sciphy_to_dev(sci_phy), + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } @@ -545,19 +544,19 @@ enum sci_status scic_sds_phy_consume_power_handler(struct scic_sds_phy *sci_phy) * none */ static void scic_sds_phy_start_sas_link_training( - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { u32 phy_control; phy_control = - readl(&sci_phy->link_layer_registers->phy_configuration); + readl(&iphy->link_layer_registers->phy_configuration); phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); writel(phy_control, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SAS_SPEED_EN); + sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SAS_SPEED_EN); - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; + iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; } /** @@ -569,11 +568,11 @@ static void scic_sds_phy_start_sas_link_training( * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none */ static void scic_sds_phy_start_sata_link_training( - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SATA_POWER); + sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_POWER); - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; + iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; } /** @@ -588,33 +587,33 @@ static void scic_sds_phy_start_sata_link_training( * */ static void scic_sds_phy_complete_link_training( - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, enum sas_linkrate max_link_rate, u32 next_state) { - sci_phy->max_negotiated_speed = max_link_rate; + iphy->max_negotiated_speed = max_link_rate; - sci_change_state(&sci_phy->sm, next_state); + sci_change_state(&iphy->sm, next_state); } -enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, +enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, u32 event_code) { - enum scic_sds_phy_states state = sci_phy->sm.current_state_id; + enum scic_sds_phy_states state = iphy->sm.current_state_id; switch (state) { case SCI_PHY_SUB_AWAIT_OSSP_EN: switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: - scic_sds_phy_start_sas_link_training(sci_phy); - sci_phy->is_in_link_training = true; + scic_sds_phy_start_sas_link_training(iphy); + iphy->is_in_link_training = true; break; case SCU_EVENT_SATA_SPINUP_HOLD: - scic_sds_phy_start_sata_link_training(sci_phy); - sci_phy->is_in_link_training = true; + scic_sds_phy_start_sata_link_training(iphy); + iphy->is_in_link_training = true; break; default: - dev_dbg(sciphy_to_dev(sci_phy), + dev_dbg(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -632,21 +631,21 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, case SCU_EVENT_SAS_15: case SCU_EVENT_SAS_15_SSC: scic_sds_phy_complete_link_training( - sci_phy, + iphy, SAS_LINK_RATE_1_5_GBPS, SCI_PHY_SUB_AWAIT_IAF_UF); break; case SCU_EVENT_SAS_30: case SCU_EVENT_SAS_30_SSC: scic_sds_phy_complete_link_training( - sci_phy, + iphy, SAS_LINK_RATE_3_0_GBPS, SCI_PHY_SUB_AWAIT_IAF_UF); break; case SCU_EVENT_SAS_60: case SCU_EVENT_SAS_60_SSC: scic_sds_phy_complete_link_training( - sci_phy, + iphy, SAS_LINK_RATE_6_0_GBPS, SCI_PHY_SUB_AWAIT_IAF_UF); break; @@ -654,14 +653,14 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, /* * We were doing SAS PHY link training and received a SATA PHY event * continue OOB/SN as if this were a SATA PHY */ - scic_sds_phy_start_sata_link_training(sci_phy); + scic_sds_phy_start_sata_link_training(iphy); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, event_code); @@ -674,23 +673,23 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: /* Backup the state machine */ - scic_sds_phy_start_sas_link_training(sci_phy); + scic_sds_phy_start_sas_link_training(iphy); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* We were doing SAS PHY link training and received a * SATA PHY event continue OOB/SN as if this were a * SATA PHY */ - scic_sds_phy_start_sata_link_training(sci_phy); + scic_sds_phy_start_sata_link_training(iphy); break; case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: case SCU_EVENT_LINK_FAILURE: case SCU_EVENT_HARD_RESET_RECEIVED: /* Start the oob/sn state machine over again */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, event_code); @@ -701,10 +700,10 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received unexpected " "event_code %x\n", __func__, @@ -716,7 +715,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* These events are received every 10ms and are @@ -728,11 +727,11 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, /* There has been a change in the phy type before OOB/SN for the * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(sci_phy); + scic_sds_phy_start_sas_link_training(iphy); break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, event_code); @@ -744,7 +743,7 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* These events might be received since we dont know how many may be in @@ -752,19 +751,19 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, */ break; case SCU_EVENT_SATA_PHY_DETECTED: - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; + iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; /* We have received the SATA PHY notification change state */ - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN); + sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN); break; case SCU_EVENT_SAS_PHY_DETECTED: /* There has been a change in the phy type before OOB/SN for the * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(sci_phy); + scic_sds_phy_start_sas_link_training(iphy); break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -783,36 +782,36 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, case SCU_EVENT_SATA_15: case SCU_EVENT_SATA_15_SSC: scic_sds_phy_complete_link_training( - sci_phy, + iphy, SAS_LINK_RATE_1_5_GBPS, SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_SATA_30: case SCU_EVENT_SATA_30_SSC: scic_sds_phy_complete_link_training( - sci_phy, + iphy, SAS_LINK_RATE_3_0_GBPS, SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_SATA_60: case SCU_EVENT_SATA_60_SSC: scic_sds_phy_complete_link_training( - sci_phy, + iphy, SAS_LINK_RATE_6_0_GBPS, SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; case SCU_EVENT_SAS_PHY_DETECTED: /* * There has been a change in the phy type before OOB/SN for the * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(sci_phy); + scic_sds_phy_start_sas_link_training(iphy); break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, event_code); @@ -825,16 +824,16 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, switch (scu_get_event_code(event_code)) { case SCU_EVENT_SATA_PHY_DETECTED: /* Backup the state machine */ - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN); + sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected event_code %x\n", __func__, @@ -847,20 +846,20 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, switch (scu_get_event_code(event_code)) { case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; case SCU_EVENT_BROADCAST_CHANGE: /* Broadcast change received. Notify the port. */ - if (phy_get_non_dummy_port(sci_phy) != NULL) - scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy); + if (phy_get_non_dummy_port(iphy) != NULL) + scic_sds_port_broadcast_change_received(iphy->owning_port, iphy); else - sci_phy->bcn_received_while_port_unassigned = true; + iphy->bcn_received_while_port_unassigned = true; break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%sP SCIC PHY 0x%p ready state machine received " "unexpected event_code %x\n", - __func__, sci_phy, event_code); + __func__, iphy, event_code); return SCI_FAILURE_INVALID_STATE; } return SCI_SUCCESS; @@ -868,30 +867,30 @@ enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy, switch (scu_get_event_code(event_code)) { case SCU_EVENT_HARD_RESET_TRANSMITTED: /* Link failure change state back to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); break; default: - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: SCIC PHY 0x%p resetting state machine received " "unexpected event_code %x\n", - __func__, sci_phy, event_code); + __func__, iphy, event_code); return SCI_FAILURE_INVALID_STATE; break; } return SCI_SUCCESS; default: - dev_dbg(sciphy_to_dev(sci_phy), + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } } -enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, +enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, u32 frame_index) { - enum scic_sds_phy_states state = sci_phy->sm.current_state_id; - struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + enum scic_sds_phy_states state = iphy->sm.current_state_id; + struct scic_sds_controller *scic = iphy->owning_port->owning_controller; enum sci_status result; unsigned long flags; @@ -899,7 +898,6 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, case SCI_PHY_SUB_AWAIT_IAF_UF: { u32 *frame_words; struct sas_identify_frame iaf; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); result = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, frame_index, @@ -927,10 +925,10 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, */ state = SCI_PHY_SUB_AWAIT_SAS_POWER; } - sci_change_state(&sci_phy->sm, state); + sci_change_state(&iphy->sm, state); result = SCI_SUCCESS; } else - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected frame id %x\n", __func__, frame_index); @@ -941,10 +939,9 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: { struct dev_to_host_fis *frame_header; u32 *fis_frame_data; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(sci_phy)->uf_control), + &(scic_sds_phy_get_controller(iphy)->uf_control), frame_index, (void **)&frame_header); @@ -964,11 +961,11 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags); /* got IAF we can now go to the await spinup semaphore state */ - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_FINAL); + sci_change_state(&iphy->sm, SCI_PHY_SUB_FINAL); result = SCI_SUCCESS; } else - dev_warn(sciphy_to_dev(sci_phy), + dev_warn(sciphy_to_dev(iphy), "%s: PHY starting substate machine received " "unexpected frame id %x\n", __func__, frame_index); @@ -979,7 +976,7 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, return result; } default: - dev_dbg(sciphy_to_dev(sci_phy), + dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } @@ -988,77 +985,77 @@ enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy, static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); /* This is just an temporary state go off to the starting state */ - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_AWAIT_OSSP_EN); + sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_OSSP_EN); } static void scic_sds_phy_starting_await_sas_power_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); - struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); + struct scic_sds_controller *scic = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_insert(scic, sci_phy); + scic_sds_controller_power_control_queue_insert(scic, iphy); } static void scic_sds_phy_starting_await_sas_power_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); - struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); + struct scic_sds_controller *scic = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_remove(scic, sci_phy); + scic_sds_controller_power_control_queue_remove(scic, iphy); } static void scic_sds_phy_starting_await_sata_power_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); - struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); + struct scic_sds_controller *scic = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_insert(scic, sci_phy); + scic_sds_controller_power_control_queue_insert(scic, iphy); } static void scic_sds_phy_starting_await_sata_power_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); - struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller; + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); + struct scic_sds_controller *scic = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_remove(scic, sci_phy); + scic_sds_controller_power_control_queue_remove(scic, iphy); } static void scic_sds_phy_starting_await_sata_phy_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - sci_mod_timer(&sci_phy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); + sci_mod_timer(&iphy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } static void scic_sds_phy_starting_await_sata_phy_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - sci_del_timer(&sci_phy->sata_timer); + sci_del_timer(&iphy->sata_timer); } static void scic_sds_phy_starting_await_sata_speed_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - sci_mod_timer(&sci_phy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); + sci_mod_timer(&iphy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } static void scic_sds_phy_starting_await_sata_speed_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - sci_del_timer(&sci_phy->sata_timer); + sci_del_timer(&iphy->sata_timer); } static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - if (scic_sds_port_link_detected(sci_phy->owning_port, sci_phy)) { + if (scic_sds_port_link_detected(iphy->owning_port, iphy)) { /* * Clear the PE suspend condition so we can actually @@ -1066,79 +1063,79 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_bas * The hardware will not respond to the XRDY until the PE * suspend condition is cleared. */ - scic_sds_phy_resume(sci_phy); + scic_sds_phy_resume(iphy); - sci_mod_timer(&sci_phy->sata_timer, + sci_mod_timer(&iphy->sata_timer, SCIC_SDS_SIGNATURE_FIS_TIMEOUT); } else - sci_phy->is_in_link_training = false; + iphy->is_in_link_training = false; } static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - sci_del_timer(&sci_phy->sata_timer); + sci_del_timer(&iphy->sata_timer); } static void scic_sds_phy_starting_final_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); /* State machine has run to completion so exit out and change * the base state machine to the ready state */ - sci_change_state(&sci_phy->sm, SCI_PHY_READY); + sci_change_state(&iphy->sm, SCI_PHY_READY); } /** * - * @sci_phy: This is the struct scic_sds_phy object to stop. + * @sci_phy: This is the struct isci_phy object to stop. * - * This method will stop the struct scic_sds_phy object. This does not reset the + * This method will stop the struct isci_phy object. This does not reset the * protocol engine it just suspends it and places it in a state where it will * not cause the end device to power up. none */ static void scu_link_layer_stop_protocol_engine( - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { u32 scu_sas_pcfg_value; u32 enable_spinup_value; /* Suspend the protocol engine and place it in a sata spinup hold state */ scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); + readl(&iphy->link_layer_registers->phy_configuration); scu_sas_pcfg_value |= (SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD)); writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); /* Disable the notify enable spinup primitives */ - enable_spinup_value = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control); + enable_spinup_value = readl(&iphy->link_layer_registers->notify_enable_spinup_control); enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE); - writel(enable_spinup_value, &sci_phy->link_layer_registers->notify_enable_spinup_control); + writel(enable_spinup_value, &iphy->link_layer_registers->notify_enable_spinup_control); } /** * * - * This method will start the OOB/SN state machine for this struct scic_sds_phy object. + * This method will start the OOB/SN state machine for this struct isci_phy object. */ static void scu_link_layer_start_oob( - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { u32 scu_sas_pcfg_value; scu_sas_pcfg_value = - readl(&sci_phy->link_layer_registers->phy_configuration); + readl(&iphy->link_layer_registers->phy_configuration); scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); scu_sas_pcfg_value &= ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); writel(scu_sas_pcfg_value, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); } /** @@ -1150,7 +1147,7 @@ static void scu_link_layer_start_oob( * hard reset bit set. */ static void scu_link_layer_tx_hard_reset( - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { u32 phy_configuration_value; @@ -1158,91 +1155,91 @@ static void scu_link_layer_tx_hard_reset( * SAS Phys must wait for the HARD_RESET_TX event notification to transition * to the starting state. */ phy_configuration_value = - readl(&sci_phy->link_layer_registers->phy_configuration); + readl(&iphy->link_layer_registers->phy_configuration); phy_configuration_value |= (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); writel(phy_configuration_value, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); /* Now take the OOB state machine out of reset */ phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); writel(phy_configuration_value, - &sci_phy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); } static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); /* * @todo We need to get to the controller to place this PE in a * reset state */ - sci_del_timer(&sci_phy->sata_timer); + sci_del_timer(&iphy->sata_timer); - scu_link_layer_stop_protocol_engine(sci_phy); + scu_link_layer_stop_protocol_engine(iphy); - if (sci_phy->sm.previous_state_id != SCI_PHY_INITIAL) - scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), - phy_get_non_dummy_port(sci_phy), - sci_phy); + if (iphy->sm.previous_state_id != SCI_PHY_INITIAL) + scic_sds_controller_link_down(scic_sds_phy_get_controller(iphy), + phy_get_non_dummy_port(iphy), + iphy); } static void scic_sds_phy_starting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - scu_link_layer_stop_protocol_engine(sci_phy); - scu_link_layer_start_oob(sci_phy); + scu_link_layer_stop_protocol_engine(iphy); + scu_link_layer_start_oob(iphy); /* We don't know what kind of phy we are going to be just yet */ - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; - sci_phy->bcn_received_while_port_unassigned = false; + iphy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; + iphy->bcn_received_while_port_unassigned = false; - if (sci_phy->sm.previous_state_id == SCI_PHY_READY) - scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy), - phy_get_non_dummy_port(sci_phy), - sci_phy); + if (iphy->sm.previous_state_id == SCI_PHY_READY) + scic_sds_controller_link_down(scic_sds_phy_get_controller(iphy), + phy_get_non_dummy_port(iphy), + iphy); - sci_change_state(&sci_phy->sm, SCI_PHY_SUB_INITIAL); + sci_change_state(&iphy->sm, SCI_PHY_SUB_INITIAL); } static void scic_sds_phy_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - scic_sds_controller_link_up(scic_sds_phy_get_controller(sci_phy), - phy_get_non_dummy_port(sci_phy), - sci_phy); + scic_sds_controller_link_up(scic_sds_phy_get_controller(iphy), + phy_get_non_dummy_port(iphy), + iphy); } static void scic_sds_phy_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - scic_sds_phy_suspend(sci_phy); + scic_sds_phy_suspend(iphy); } static void scic_sds_phy_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), sm); + struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); /* The phy is being reset, therefore deactivate it from the port. In * the resetting state we don't notify the user regarding link up and * link down notifications */ - scic_sds_port_deactivate_phy(sci_phy->owning_port, sci_phy, false); + scic_sds_port_deactivate_phy(iphy->owning_port, iphy, false); - if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { - scu_link_layer_tx_hard_reset(sci_phy); + if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + scu_link_layer_tx_hard_reset(iphy); } else { /* The SCU does not need to have a discrete reset state so * just go back to the starting state. */ - sci_change_state(&sci_phy->sm, SCI_PHY_STARTING); + sci_change_state(&iphy->sm, SCI_PHY_STARTING); } } @@ -1293,21 +1290,21 @@ static const struct sci_base_state scic_sds_phy_state_table[] = { [SCI_PHY_FINAL] = { }, }; -void scic_sds_phy_construct(struct scic_sds_phy *sci_phy, +void scic_sds_phy_construct(struct isci_phy *iphy, struct scic_sds_port *owning_port, u8 phy_index) { - sci_init_sm(&sci_phy->sm, scic_sds_phy_state_table, SCI_PHY_INITIAL); + sci_init_sm(&iphy->sm, scic_sds_phy_state_table, SCI_PHY_INITIAL); /* Copy the rest of the input data to our locals */ - sci_phy->owning_port = owning_port; - sci_phy->phy_index = phy_index; - sci_phy->bcn_received_while_port_unassigned = false; - sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; - sci_phy->link_layer_registers = NULL; - sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; + iphy->owning_port = owning_port; + iphy->phy_index = phy_index; + iphy->bcn_received_while_port_unassigned = false; + iphy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; + iphy->link_layer_registers = NULL; + iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; /* Create the SIGNATURE FIS Timeout timer for this phy */ - sci_init_timer(&sci_phy->sata_timer, phy_sata_timeout); + sci_init_timer(&iphy->sata_timer, phy_sata_timeout); } void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index) @@ -1368,14 +1365,14 @@ int isci_phy_control(struct asd_sas_phy *sas_phy, switch (func) { case PHY_FUNC_DISABLE: spin_lock_irqsave(&ihost->scic_lock, flags); - scic_sds_phy_stop(&iphy->sci); + scic_sds_phy_stop(iphy); spin_unlock_irqrestore(&ihost->scic_lock, flags); break; case PHY_FUNC_LINK_RESET: spin_lock_irqsave(&ihost->scic_lock, flags); - scic_sds_phy_stop(&iphy->sci); - scic_sds_phy_start(&iphy->sci); + scic_sds_phy_stop(iphy); + scic_sds_phy_start(iphy); spin_unlock_irqrestore(&ihost->scic_lock, flags); break; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 97ebee16f4b3..345fbeacb5cf 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -84,102 +84,40 @@ enum scic_sds_phy_protocol { }; /** - * struct scic_sds_phy - This structure contains or references all of the data - * necessary to represent the core phy object and SCU harware protocol - * engine. - * - * + * isci_phy - hba local phy infrastructure + * @sm: + * @protocol: attached device protocol + * @phy_index: physical index relative to the controller (0-3) + * @bcn_received_while_port_unassigned: bcn to report after port association + * @sata_timer: timeout SATA signature FIS arrival */ -struct scic_sds_phy { - /** - * This field contains the information for the base phy state machine. - */ +struct isci_phy { struct sci_base_state_machine sm; - - /** - * This field specifies the port object that owns/contains this phy. - */ struct scic_sds_port *owning_port; - - /** - * This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s, - * or 6.0 Gb/s operation. - */ enum sas_linkrate max_negotiated_speed; - - /** - * This member specifies the protocol being utilized on this phy. This - * field contains a legitamite value once the PHY has link trained with - * a remote phy. - */ enum scic_sds_phy_protocol protocol; - - /** - * This field specifies the index with which this phy is associated (0-3). - */ u8 phy_index; - - /** - * This member indicates if this particular PHY has received a BCN while - * it had no port assignement. This BCN will be reported once the phy is - * assigned to a port. - */ bool bcn_received_while_port_unassigned; - - /** - * This field indicates if this PHY is currently in the process of - * link training (i.e. it has started OOB, but has yet to perform - * IAF exchange/Signature FIS reception). - */ bool is_in_link_training; - - /** - * Timer to detect when a signature FIS timeout has occurred. The - * signature FIS is the first FIS sent by an attached SATA device - * after OOB/SN. - */ - struct sci_timer sata_timer; - - /** - * This field is the pointer to the transport layer register for the SCU - * hardware. - */ + struct sci_timer sata_timer; struct scu_transport_layer_registers __iomem *transport_layer_registers; - - /** - * This field points to the link layer register set within the SCU. - */ struct scu_link_layer_registers __iomem *link_layer_registers; - -}; - - -struct isci_phy { - struct scic_sds_phy sci; struct asd_sas_phy sas_phy; struct isci_port *isci_port; u8 sas_addr[SAS_ADDR_SIZE]; - union { struct sas_identify_frame iaf; struct dev_to_host_fis fis; } frame_rcvd; }; -static inline struct isci_phy *to_isci_phy(struct asd_sas_phy *sas_phy) +static inline struct isci_phy *to_iphy(struct asd_sas_phy *sas_phy) { struct isci_phy *iphy = container_of(sas_phy, typeof(*iphy), sas_phy); return iphy; } -static inline struct isci_phy *sci_phy_to_iphy(struct scic_sds_phy *sci_phy) -{ - struct isci_phy *iphy = container_of(sci_phy, typeof(*iphy), sci); - - return iphy; -} - struct scic_phy_cap { union { struct { @@ -520,61 +458,61 @@ enum scic_sds_phy_states { (scic_sds_port_get_controller((phy)->owning_port)) void scic_sds_phy_construct( - struct scic_sds_phy *this_phy, + struct isci_phy *iphy, struct scic_sds_port *owning_port, u8 phy_index); -struct scic_sds_port *phy_get_non_dummy_port(struct scic_sds_phy *sci_phy); +struct scic_sds_port *phy_get_non_dummy_port(struct isci_phy *iphy); void scic_sds_phy_set_port( - struct scic_sds_phy *this_phy, + struct isci_phy *iphy, struct scic_sds_port *owning_port); enum sci_status scic_sds_phy_initialize( - struct scic_sds_phy *this_phy, + struct isci_phy *iphy, struct scu_transport_layer_registers __iomem *transport_layer_registers, struct scu_link_layer_registers __iomem *link_layer_registers); enum sci_status scic_sds_phy_start( - struct scic_sds_phy *this_phy); + struct isci_phy *iphy); enum sci_status scic_sds_phy_stop( - struct scic_sds_phy *this_phy); + struct isci_phy *iphy); enum sci_status scic_sds_phy_reset( - struct scic_sds_phy *this_phy); + struct isci_phy *iphy); void scic_sds_phy_resume( - struct scic_sds_phy *this_phy); + struct isci_phy *iphy); void scic_sds_phy_setup_transport( - struct scic_sds_phy *this_phy, + struct isci_phy *iphy, u32 device_id); enum sci_status scic_sds_phy_event_handler( - struct scic_sds_phy *this_phy, + struct isci_phy *iphy, u32 event_code); enum sci_status scic_sds_phy_frame_handler( - struct scic_sds_phy *this_phy, + struct isci_phy *iphy, u32 frame_index); enum sci_status scic_sds_phy_consume_power_handler( - struct scic_sds_phy *this_phy); + struct isci_phy *iphy); void scic_sds_phy_get_sas_address( - struct scic_sds_phy *this_phy, + struct isci_phy *iphy, struct sci_sas_address *sas_address); void scic_sds_phy_get_attached_sas_address( - struct scic_sds_phy *this_phy, + struct isci_phy *iphy, struct sci_sas_address *sas_address); struct scic_phy_proto; void scic_sds_phy_get_protocols( - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, struct scic_phy_proto *protocols); -enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy); +enum sas_linkrate sci_phy_linkrate(struct isci_phy *iphy); struct isci_host; void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index); diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index bd091549b4f7..d53c0b1748e7 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -154,17 +154,17 @@ static enum sci_status scic_port_get_properties(struct scic_sds_port *port, static void scic_port_bcn_enable(struct scic_sds_port *sci_port) { - struct scic_sds_phy *sci_phy; + struct isci_phy *iphy; u32 val; int i; for (i = 0; i < ARRAY_SIZE(sci_port->phy_table); i++) { - sci_phy = sci_port->phy_table[i]; - if (!sci_phy) + iphy = sci_port->phy_table[i]; + if (!iphy) continue; - val = readl(&sci_phy->link_layer_registers->link_layer_control); + val = readl(&iphy->link_layer_registers->link_layer_control); /* clear the bit by writing 1. */ - writel(val, &sci_phy->link_layer_registers->link_layer_control); + writel(val, &iphy->link_layer_registers->link_layer_control); } } @@ -180,10 +180,9 @@ void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport) return; for (i = 0; i < ARRAY_SIZE(iport->sci.phy_table); i++) { - struct scic_sds_phy *sci_phy = iport->sci.phy_table[i]; - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); + struct isci_phy *iphy = iport->sci.phy_table[i]; - if (!sci_phy) + if (!iphy) continue; ihost->sas_ha.notify_port_event(&iphy->sas_phy, @@ -194,9 +193,8 @@ void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport) void isci_port_bc_change_received(struct isci_host *ihost, struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); struct isci_port *iport = iphy->isci_port; if (iport && test_bit(IPORT_BCN_BLOCKED, &iport->flags)) { @@ -219,33 +217,32 @@ void isci_port_bc_change_received(struct isci_host *ihost, static void isci_port_link_up(struct isci_host *isci_host, struct scic_sds_port *port, - struct scic_sds_phy *phy) + struct isci_phy *iphy) { unsigned long flags; struct scic_port_properties properties; - struct isci_phy *isci_phy = sci_phy_to_iphy(phy); struct isci_port *isci_port = sci_port_to_iport(port); unsigned long success = true; - BUG_ON(isci_phy->isci_port != NULL); + BUG_ON(iphy->isci_port != NULL); - isci_phy->isci_port = isci_port; + iphy->isci_port = isci_port; dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", __func__, isci_port); - spin_lock_irqsave(&isci_phy->sas_phy.frame_rcvd_lock, flags); + spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags); - isci_port_change_state(isci_phy->isci_port, isci_starting); + isci_port_change_state(iphy->isci_port, isci_starting); scic_port_get_properties(port, &properties); - if (phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { + if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { u64 attached_sas_address; - isci_phy->sas_phy.oob_mode = SATA_OOB_MODE; - isci_phy->sas_phy.frame_rcvd_size = sizeof(struct dev_to_host_fis); + iphy->sas_phy.oob_mode = SATA_OOB_MODE; + iphy->sas_phy.frame_rcvd_size = sizeof(struct dev_to_host_fis); /* * For direct-attached SATA devices, the SCI core will @@ -259,28 +256,28 @@ static void isci_port_link_up(struct isci_host *isci_host, attached_sas_address |= properties.remote.sas_address.low; swab64s(&attached_sas_address); - memcpy(&isci_phy->sas_phy.attached_sas_addr, + memcpy(&iphy->sas_phy.attached_sas_addr, &attached_sas_address, sizeof(attached_sas_address)); - } else if (phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { - isci_phy->sas_phy.oob_mode = SAS_OOB_MODE; - isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame); + } else if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + iphy->sas_phy.oob_mode = SAS_OOB_MODE; + iphy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame); /* Copy the attached SAS address from the IAF */ - memcpy(isci_phy->sas_phy.attached_sas_addr, - isci_phy->frame_rcvd.iaf.sas_addr, SAS_ADDR_SIZE); + memcpy(iphy->sas_phy.attached_sas_addr, + iphy->frame_rcvd.iaf.sas_addr, SAS_ADDR_SIZE); } else { dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__); success = false; } - isci_phy->sas_phy.phy->negotiated_linkrate = sci_phy_linkrate(phy); + iphy->sas_phy.phy->negotiated_linkrate = sci_phy_linkrate(iphy); - spin_unlock_irqrestore(&isci_phy->sas_phy.frame_rcvd_lock, flags); + spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags); /* Notify libsas that we have an address frame, if indeed * we've found an SSP, SMP, or STP target */ if (success) - isci_host->sas_ha.notify_port_event(&isci_phy->sas_phy, + isci_host->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BYTES_DMAED); } @@ -495,11 +492,7 @@ static bool scic_sds_port_is_phy_mask_valid( return false; } -/** - * - * @sci_port: This parameter specifies the port from which to return a - * connected phy. - * +/* * This method retrieves a currently active (i.e. connected) phy contained in * the port. Currently, the lowest order phy that is connected is returned. * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is @@ -507,58 +500,38 @@ static bool scic_sds_port_is_phy_mask_valid( * point) phys contained in the port. All other values specify a struct scic_sds_phy * object that is active in the port. */ -static struct scic_sds_phy *scic_sds_port_get_a_connected_phy( - struct scic_sds_port *sci_port - ) { +static struct isci_phy *scic_sds_port_get_a_connected_phy(struct scic_sds_port *sci_port) +{ u32 index; - struct scic_sds_phy *phy; + struct isci_phy *iphy; for (index = 0; index < SCI_MAX_PHYS; index++) { - /* - * Ensure that the phy is both part of the port and currently - * connected to the remote end-point. */ - phy = sci_port->phy_table[index]; - if ( - (phy != NULL) - && scic_sds_port_active_phy(sci_port, phy) - ) { - return phy; - } + /* Ensure that the phy is both part of the port and currently + * connected to the remote end-point. + */ + iphy = sci_port->phy_table[index]; + if (iphy && scic_sds_port_active_phy(sci_port, iphy)) + return iphy; } return NULL; } -/** - * scic_sds_port_set_phy() - - * @out]: port The port object to which the phy assignement is being made. - * @out]: phy The phy which is being assigned to the port. - * - * This method attempts to make the assignment of the phy to the port. If - * successful the phy is assigned to the ports phy table. bool true if the phy - * assignment can be made. false if the phy assignement can not be made. This - * is a functional test that only fails if the phy is currently assigned to a - * different port. - */ -static enum sci_status scic_sds_port_set_phy( - struct scic_sds_port *port, - struct scic_sds_phy *phy) +static enum sci_status scic_sds_port_set_phy(struct scic_sds_port *port, struct isci_phy *iphy) { - /* - * Check to see if we can add this phy to a port + /* Check to see if we can add this phy to a port * that means that the phy is not part of a port and that the port does - * not already have a phy assinged to the phy index. */ - if ( - (port->phy_table[phy->phy_index] == NULL) - && (phy_get_non_dummy_port(phy) == NULL) - && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index) - ) { - /* - * Phy is being added in the stopped state so we are in MPC mode - * make logical port index = physical port index */ + * not already have a phy assinged to the phy index. + */ + if (!port->phy_table[iphy->phy_index] && + !phy_get_non_dummy_port(iphy) && + scic_sds_port_is_valid_phy_assignment(port, iphy->phy_index)) { + /* Phy is being added in the stopped state so we are in MPC mode + * make logical port index = physical port index + */ port->logical_port_index = port->physical_port_index; - port->phy_table[phy->phy_index] = phy; - scic_sds_phy_set_port(phy, port); + port->phy_table[iphy->phy_index] = iphy; + scic_sds_phy_set_port(iphy, port); return SCI_SUCCESS; } @@ -566,28 +539,18 @@ static enum sci_status scic_sds_port_set_phy( return SCI_FAILURE; } -/** - * scic_sds_port_clear_phy() - - * @out]: port The port from which the phy is being cleared. - * @out]: phy The phy being cleared from the port. - * - * This method will clear the phy assigned to this port. This method fails if - * this phy is not currently assinged to this port. bool true if the phy is - * removed from the port. false if this phy is not assined to this port. - */ -static enum sci_status scic_sds_port_clear_phy( - struct scic_sds_port *port, - struct scic_sds_phy *phy) +static enum sci_status scic_sds_port_clear_phy(struct scic_sds_port *port, + struct isci_phy *iphy) { /* Make sure that this phy is part of this port */ - if (port->phy_table[phy->phy_index] == phy && - phy_get_non_dummy_port(phy) == port) { + if (port->phy_table[iphy->phy_index] == iphy && + phy_get_non_dummy_port(iphy) == port) { struct scic_sds_controller *scic = port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); /* Yep it is assigned to this port so remove it */ - scic_sds_phy_set_port(phy, &ihost->ports[SCI_MAX_PORTS].sci); - port->phy_table[phy->phy_index] = NULL; + scic_sds_phy_set_port(iphy, &ihost->ports[SCI_MAX_PORTS].sci); + port->phy_table[iphy->phy_index] = NULL; return SCI_SUCCESS; } @@ -634,20 +597,20 @@ void scic_sds_port_get_attached_sas_address( struct scic_sds_port *sci_port, struct sci_sas_address *sas_address) { - struct scic_sds_phy *sci_phy; + struct isci_phy *iphy; /* * Ensure that the phy is both part of the port and currently * connected to the remote end-point. */ - sci_phy = scic_sds_port_get_a_connected_phy(sci_port); - if (sci_phy) { - if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) { - scic_sds_phy_get_attached_sas_address(sci_phy, + iphy = scic_sds_port_get_a_connected_phy(sci_port); + if (iphy) { + if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) { + scic_sds_phy_get_attached_sas_address(iphy, sas_address); } else { - scic_sds_phy_get_sas_address(sci_phy, sas_address); - sas_address->low += sci_phy->phy_index; + scic_sds_phy_get_sas_address(iphy, sas_address); + sas_address->low += iphy->phy_index; } } else { sas_address->high = 0; @@ -787,39 +750,38 @@ void scic_sds_port_setup_transports( * notifying the user that the link is up. none */ static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, bool do_notify_user) { struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - if (sci_phy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) - scic_sds_phy_resume(sci_phy); + if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) + scic_sds_phy_resume(iphy); - sci_port->active_phy_mask |= 1 << sci_phy->phy_index; + sci_port->active_phy_mask |= 1 << iphy->phy_index; - scic_sds_controller_clear_invalid_phy(scic, sci_phy); + scic_sds_controller_clear_invalid_phy(scic, iphy); if (do_notify_user == true) - isci_port_link_up(ihost, sci_port, sci_phy); + isci_port_link_up(ihost, sci_port, iphy); } void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, bool do_notify_user) { struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); struct isci_port *iport = sci_port_to_iport(sci_port); struct isci_host *ihost = scic_to_ihost(scic); - struct isci_phy *iphy = sci_phy_to_iphy(sci_phy); - sci_port->active_phy_mask &= ~(1 << sci_phy->phy_index); + sci_port->active_phy_mask &= ~(1 << iphy->phy_index); - sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; + iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; /* Re-assign the phy back to the LP as if it were a narrow port */ - writel(sci_phy->phy_index, - &sci_port->port_pe_configuration_register[sci_phy->phy_index]); + writel(iphy->phy_index, + &sci_port->port_pe_configuration_register[iphy->phy_index]); if (do_notify_user == true) isci_port_link_down(ihost, iphy, iport); @@ -834,7 +796,7 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, * this port object. None */ static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { struct scic_sds_controller *scic = sci_port->owning_controller; @@ -843,8 +805,8 @@ static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, * not go ahead and tell the SCI_USER that we have discovered an * invalid link. */ - if ((scic->invalid_phy_mask & (1 << sci_phy->phy_index)) == 0) { - scic_sds_controller_set_invalid_phy(scic, sci_phy); + if ((scic->invalid_phy_mask & (1 << iphy->phy_index)) == 0) { + scic_sds_controller_set_invalid_phy(scic, iphy); dev_warn(&scic_to_ihost(scic)->pdev->dev, "Invalid link up!\n"); } } @@ -879,7 +841,7 @@ static void port_state_machine_change(struct scic_sds_port *sci_port, /** * scic_sds_port_general_link_up_handler - phy can be assigned to port? * @sci_port: scic_sds_port object for which has a phy that has gone link up. - * @sci_phy: This is the struct scic_sds_phy object that has gone link up. + * @sci_phy: This is the struct isci_phy object that has gone link up. * @do_notify_user: This parameter specifies whether to inform the user (via * scic_cb_port_link_up()) as to the fact that a new phy as become ready. * @@ -890,14 +852,14 @@ static void port_state_machine_change(struct scic_sds_port *sci_port, * the same port. none */ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, bool do_notify_user) { struct sci_sas_address port_sas_address; struct sci_sas_address phy_sas_address; scic_sds_port_get_attached_sas_address(sci_port, &port_sas_address); - scic_sds_phy_get_attached_sas_address(sci_phy, &phy_sas_address); + scic_sds_phy_get_attached_sas_address(iphy, &phy_sas_address); /* If the SAS address of the new phy matches the SAS address of * other phys in the port OR this is the first phy in the port, @@ -909,11 +871,11 @@ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port sci_port->active_phy_mask == 0) { struct sci_base_state_machine *sm = &sci_port->sm; - scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); + scic_sds_port_activate_phy(sci_port, iphy, do_notify_user); if (sm->current_state_id == SCI_PORT_RESETTING) port_state_machine_change(sci_port, SCI_PORT_READY); } else - scic_sds_port_invalid_link_up(sci_port, sci_phy); + scic_sds_port_invalid_link_up(sci_port, iphy); } @@ -957,12 +919,12 @@ static bool scic_sds_port_is_wide(struct scic_sds_port *sci_port) */ bool scic_sds_port_link_detected( struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { if ((sci_port->logical_port_index != SCIC_SDS_DUMMY_PORT) && - (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && + (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && scic_sds_port_is_wide(sci_port)) { - scic_sds_port_invalid_link_up(sci_port, sci_phy); + scic_sds_port_invalid_link_up(sci_port, iphy); return false; } @@ -1045,47 +1007,26 @@ static void scic_sds_port_update_viit_entry(struct scic_sds_port *sci_port) &sci_port->viit_registers->status); } -/** - * This method returns the maximum allowed speed for data transfers on this - * port. This maximum allowed speed evaluates to the maximum speed of the - * slowest phy in the port. - * @sci_port: This parameter specifies the port for which to retrieve the - * maximum allowed speed. - * - * This method returns the maximum negotiated speed of the slowest phy in the - * port. - */ -enum sas_linkrate scic_sds_port_get_max_allowed_speed( - struct scic_sds_port *sci_port) +enum sas_linkrate scic_sds_port_get_max_allowed_speed(struct scic_sds_port *sci_port) { u16 index; + struct isci_phy *iphy; enum sas_linkrate max_allowed_speed = SAS_LINK_RATE_6_0_GBPS; - struct scic_sds_phy *phy = NULL; /* * Loop through all of the phys in this port and find the phy with the * lowest maximum link rate. */ for (index = 0; index < SCI_MAX_PHYS; index++) { - phy = sci_port->phy_table[index]; - if ( - (phy != NULL) - && (scic_sds_port_active_phy(sci_port, phy) == true) - && (phy->max_negotiated_speed < max_allowed_speed) - ) - max_allowed_speed = phy->max_negotiated_speed; + iphy = sci_port->phy_table[index]; + if (iphy && scic_sds_port_active_phy(sci_port, iphy) && + iphy->max_negotiated_speed < max_allowed_speed) + max_allowed_speed = iphy->max_negotiated_speed; } return max_allowed_speed; } -/** - * - * @sci_port: This is the struct scic_sds_port object to suspend. - * - * This method will susped the port task scheduler for this port object. none - */ -static void -scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port) +static void scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port) { u32 pts_control_value; @@ -1377,7 +1318,7 @@ enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port) static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 timeout) { enum sci_status status = SCI_FAILURE_INVALID_PHY; - struct scic_sds_phy *selected_phy = NULL; + struct isci_phy *iphy = NULL; enum scic_sds_port_states state; u32 phy_index; @@ -1389,22 +1330,21 @@ static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 } /* Select a phy on which we can send the hard reset request. */ - for (phy_index = 0; phy_index < SCI_MAX_PHYS && !selected_phy; phy_index++) { - selected_phy = sci_port->phy_table[phy_index]; - if (selected_phy && - !scic_sds_port_active_phy(sci_port, selected_phy)) { + for (phy_index = 0; phy_index < SCI_MAX_PHYS && !iphy; phy_index++) { + iphy = sci_port->phy_table[phy_index]; + if (iphy && !scic_sds_port_active_phy(sci_port, iphy)) { /* * We found a phy but it is not ready select * different phy */ - selected_phy = NULL; + iphy = NULL; } } /* If we have a phy then go ahead and start the reset procedure */ - if (!selected_phy) + if (!iphy) return status; - status = scic_sds_phy_reset(selected_phy); + status = scic_sds_phy_reset(iphy); if (status != SCI_SUCCESS) return status; @@ -1412,8 +1352,7 @@ static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 sci_mod_timer(&sci_port->timer, timeout); sci_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; - port_state_machine_change(sci_port, - SCI_PORT_RESETTING); + port_state_machine_change(sci_port, SCI_PORT_RESETTING); return SCI_SUCCESS; } @@ -1427,7 +1366,7 @@ static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 * status is a failure to add the phy to the port. */ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { enum sci_status status; enum scic_sds_port_states state; @@ -1446,32 +1385,32 @@ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, /* Make sure that the PHY SAS Address matches the SAS Address * for this port */ - scic_sds_phy_get_sas_address(sci_phy, &phy_sas_address); + scic_sds_phy_get_sas_address(iphy, &phy_sas_address); if (port_sas_address.high != phy_sas_address.high || port_sas_address.low != phy_sas_address.low) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } - return scic_sds_port_set_phy(sci_port, sci_phy); + return scic_sds_port_set_phy(sci_port, iphy); } case SCI_PORT_SUB_WAITING: case SCI_PORT_SUB_OPERATIONAL: - status = scic_sds_port_set_phy(sci_port, sci_phy); + status = scic_sds_port_set_phy(sci_port, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); + scic_sds_port_general_link_up_handler(sci_port, iphy, true); sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; port_state_machine_change(sci_port, SCI_PORT_SUB_CONFIGURING); return status; case SCI_PORT_SUB_CONFIGURING: - status = scic_sds_port_set_phy(sci_port, sci_phy); + status = scic_sds_port_set_phy(sci_port, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); + scic_sds_port_general_link_up_handler(sci_port, iphy, true); /* Re-enter the configuring state since this may be the last phy in * the port. @@ -1496,7 +1435,7 @@ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, * other status is a failure to add the phy to the port. */ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { enum sci_status status; enum scic_sds_port_states state; @@ -1505,23 +1444,23 @@ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, switch (state) { case SCI_PORT_STOPPED: - return scic_sds_port_clear_phy(sci_port, sci_phy); + return scic_sds_port_clear_phy(sci_port, iphy); case SCI_PORT_SUB_OPERATIONAL: - status = scic_sds_port_clear_phy(sci_port, sci_phy); + status = scic_sds_port_clear_phy(sci_port, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_deactivate_phy(sci_port, sci_phy, true); + scic_sds_port_deactivate_phy(sci_port, iphy, true); sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; port_state_machine_change(sci_port, SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; case SCI_PORT_SUB_CONFIGURING: - status = scic_sds_port_clear_phy(sci_port, sci_phy); + status = scic_sds_port_clear_phy(sci_port, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_deactivate_phy(sci_port, sci_phy, true); + scic_sds_port_deactivate_phy(sci_port, iphy, true); /* Re-enter the configuring state since this may be the last phy in * the port @@ -1537,7 +1476,7 @@ enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, } enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { enum scic_sds_port_states state; @@ -1547,13 +1486,13 @@ enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, /* Since this is the first phy going link up for the port we * can just enable it and continue */ - scic_sds_port_activate_phy(sci_port, sci_phy, true); + scic_sds_port_activate_phy(sci_port, iphy, true); port_state_machine_change(sci_port, SCI_PORT_SUB_OPERATIONAL); return SCI_SUCCESS; case SCI_PORT_SUB_OPERATIONAL: - scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); + scic_sds_port_general_link_up_handler(sci_port, iphy, true); return SCI_SUCCESS; case SCI_PORT_RESETTING: /* TODO We should make sure that the phy that has gone @@ -1570,7 +1509,7 @@ enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, /* In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_general_link_up_handler(sci_port, sci_phy, false); + scic_sds_port_general_link_up_handler(sci_port, iphy, false); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(sci_port), @@ -1580,14 +1519,14 @@ enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, } enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { enum scic_sds_port_states state; state = sci_port->sm.current_state_id; switch (state) { case SCI_PORT_SUB_OPERATIONAL: - scic_sds_port_deactivate_phy(sci_port, sci_phy, true); + scic_sds_port_deactivate_phy(sci_port, iphy, true); /* If there are no active phys left in the port, then * transition the port to the WAITING state until such time @@ -1600,7 +1539,7 @@ enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, case SCI_PORT_RESETTING: /* In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_deactivate_phy(sci_port, sci_phy, false); + scic_sds_port_deactivate_phy(sci_port, iphy, false); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(sci_port), @@ -1879,13 +1818,13 @@ enum isci_status isci_port_get_state( void scic_sds_port_broadcast_change_received( struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { struct scic_sds_controller *scic = sci_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); /* notify the user. */ - isci_port_bc_change_received(ihost, sci_port, sci_phy); + isci_port_bc_change_received(ihost, sci_port, iphy); } int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 668f3a14cd70..b6ce56a6c11d 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -131,7 +131,7 @@ struct scic_sds_port { /** * This field is the table of phys assigned to the port. */ - struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; + struct isci_phy *phy_table[SCI_MAX_PHYS]; /** * This field is a pointer back to the controller that owns this @@ -328,11 +328,11 @@ enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port); enum sci_status scic_sds_port_add_phy( struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); enum sci_status scic_sds_port_remove_phy( struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); void scic_sds_port_setup_transports( struct scic_sds_port *sci_port, @@ -342,17 +342,17 @@ void isci_port_bcn_enable(struct isci_host *, struct isci_port *); void scic_sds_port_deactivate_phy( struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy, + struct isci_phy *iphy, bool do_notify_user); bool scic_sds_port_link_detected( struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); struct isci_request; struct scic_sds_remote_device; @@ -371,7 +371,7 @@ enum sas_linkrate scic_sds_port_get_max_allowed_speed( void scic_sds_port_broadcast_change_received( struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy); + struct isci_phy *iphy); bool scic_sds_port_is_valid_phy_assignment( struct scic_sds_port *sci_port, diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index fcb8f030b7ae..8444fd8219dd 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -114,7 +114,7 @@ static s32 sci_sas_address_compare( */ static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( struct scic_sds_controller *scic, - struct scic_sds_phy *phy) + struct isci_phy *iphy) { u8 i; struct sci_sas_address port_sas_address; @@ -127,8 +127,8 @@ static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( * more phys match the sent and received SAS address as this phy in which * case it should participate in the same port. */ - scic_sds_phy_get_sas_address(phy, &phy_sas_address); - scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); + scic_sds_phy_get_sas_address(iphy, &phy_sas_address); + scic_sds_phy_get_attached_sas_address(iphy, &phy_attached_device_address); for (i = 0; i < scic->logical_port_entries; i++) { struct isci_host *ihost = scic_to_ihost(scic); @@ -196,8 +196,8 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * PE0 and PE3 can never have the same SAS Address unless they * are part of the same x4 wide port and we have already checked * for this condition. */ - scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address); + scic_sds_phy_get_sas_address(&ihost->phys[0], &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -209,8 +209,8 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * part of the same port. */ if (port_agent->phy_valid_port_range[0].min_index == 0 && port_agent->phy_valid_port_range[1].min_index == 1) { - scic_sds_phy_get_sas_address(&ihost->phys[0].sci, &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[2].sci, &second_address); + scic_sds_phy_get_sas_address(&ihost->phys[0], &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[2], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -223,8 +223,8 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * part of the same port. */ if (port_agent->phy_valid_port_range[2].min_index == 2 && port_agent->phy_valid_port_range[3].min_index == 3) { - scic_sds_phy_get_sas_address(&ihost->phys[1].sci, &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[3].sci, &second_address); + scic_sds_phy_get_sas_address(&ihost->phys[1], &first_address); + scic_sds_phy_get_sas_address(&ihost->phys[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -277,7 +277,7 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { if ((phy_mask & (1 << phy_index)) == 0) continue; - scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + scic_sds_phy_get_sas_address(&ihost->phys[phy_index], &sas_address); /* @@ -302,7 +302,7 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( while (phy_index < SCI_MAX_PHYS) { if ((phy_mask & (1 << phy_index)) == 0) continue; - scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + scic_sds_phy_get_sas_address(&ihost->phys[phy_index], &phy_assigned_address); if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { @@ -316,7 +316,7 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( port_agent->phy_valid_port_range[phy_index].max_index = phy_index; scic_sds_port_add_phy(&ihost->ports[port_index].sci, - &ihost->phys[phy_index].sci); + &ihost->phys[phy_index]); assigned_phy_mask |= (1 << phy_index); } @@ -352,12 +352,12 @@ static void mpc_agent_timeout(unsigned long data) configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; for (index = 0; index < SCI_MAX_PHYS; index++) { - struct scic_sds_phy *sci_phy = &ihost->phys[index].sci; + struct isci_phy *iphy = &ihost->phys[index]; if (configure_phy_mask & (1 << index)) { port_agent->link_up_handler(scic, port_agent, - phy_get_non_dummy_port(sci_phy), - sci_phy); + phy_get_non_dummy_port(iphy), + iphy); } } @@ -365,37 +365,22 @@ done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } -/** - * - * @controller: This is the controller object that receives the link up - * notification. - * @port: This is the port object associated with the phy. If the is no - * associated port this is an NULL. - * @phy: This is the phy object which has gone ready. - * - * This method handles the manual port configuration link up notifications. - * Since all ports and phys are associate at initialization time we just turn - * around and notifiy the port object that there is a link up. If this PHY is - * not associated with a port there is no action taken. Is it possible to get a - * link up notification from a phy that has no assocoated port? - */ -static void scic_sds_mpc_agent_link_up( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *port, - struct scic_sds_phy *phy) +static void scic_sds_mpc_agent_link_up(struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct scic_sds_port *port, + struct isci_phy *iphy) { - /* - * If the port has an invalid handle then the phy was not assigned to + /* If the port has an invalid handle then the phy was not assigned to * a port. This is because the phy was not given the same SAS Address - * as the other PHYs in the port. */ + * as the other PHYs in the port. + */ if (port != NULL) { - port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); + port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(iphy)); - scic_sds_port_link_up(port, phy); + scic_sds_port_link_up(port, iphy); - if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0) { - port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy)); + if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(iphy))) != 0) { + port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(iphy)); } } } @@ -421,7 +406,7 @@ static void scic_sds_mpc_agent_link_down( struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent, struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { if (sci_port != NULL) { /* @@ -432,9 +417,9 @@ static void scic_sds_mpc_agent_link_down( * state. */ port_agent->phy_ready_mask &= - ~(1 << scic_sds_phy_get_index(sci_phy)); + ~(1 << scic_sds_phy_get_index(iphy)); port_agent->phy_configured_mask &= - ~(1 << scic_sds_phy_get_index(sci_phy)); + ~(1 << scic_sds_phy_get_index(iphy)); /* * Check to see if there are more phys waiting to be @@ -451,7 +436,7 @@ static void scic_sds_mpc_agent_link_down( SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT); } - scic_sds_port_link_down(sci_port, sci_phy); + scic_sds_port_link_down(sci_port, iphy); } } @@ -482,11 +467,11 @@ static enum sci_status scic_sds_apc_agent_validate_phy_configuration( port_index = phy_index; /* Get the assigned SAS Address for the first PHY on the controller. */ - scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + scic_sds_phy_get_sas_address(&ihost->phys[phy_index], &sas_address); while (++phy_index < SCI_MAX_PHYS) { - scic_sds_phy_get_sas_address(&ihost->phys[phy_index].sci, + scic_sds_phy_get_sas_address(&ihost->phys[phy_index], &phy_assigned_address); /* Verify each of the SAS address are all the same for every PHY */ @@ -504,20 +489,10 @@ static enum sci_status scic_sds_apc_agent_validate_phy_configuration( return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); } -/** - * - * @controller: This is the controller object that receives the link up - * notification. - * @phy: This is the phy object which has gone link up. - * - * This method handles the automatic port configuration for link up - * notifications. - */ -static void scic_sds_apc_agent_configure_ports( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_phy *phy, - bool start_timer) +static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *controller, + struct scic_sds_port_configuration_agent *port_agent, + struct isci_phy *iphy, + bool start_timer) { u8 port_index; enum sci_status status; @@ -525,10 +500,10 @@ static void scic_sds_apc_agent_configure_ports( enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; struct isci_host *ihost = scic_to_ihost(controller); - port = scic_sds_port_configuration_agent_find_port(controller, phy); + port = scic_sds_port_configuration_agent_find_port(controller, iphy); if (port != NULL) { - if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) + if (scic_sds_port_is_valid_phy_assignment(port, iphy->phy_index)) apc_activity = SCIC_SDS_APC_ADD_PHY; else apc_activity = SCIC_SDS_APC_SKIP_PHY; @@ -540,20 +515,20 @@ static void scic_sds_apc_agent_configure_ports( * * Note the break when we reach the condition of the port id == phy id */ for ( - port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index; - port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index; + port_index = port_agent->phy_valid_port_range[iphy->phy_index].min_index; + port_index <= port_agent->phy_valid_port_range[iphy->phy_index].max_index; port_index++ ) { port = &ihost->ports[port_index].sci; /* First we must make sure that this PHY can be added to this Port. */ - if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) { + if (scic_sds_port_is_valid_phy_assignment(port, iphy->phy_index)) { /* * Port contains a PHY with a greater PHY ID than the current * PHY that has gone link up. This phy can not be part of any * port so skip it and move on. */ - if (port->active_phy_mask > (1 << phy->phy_index)) { + if (port->active_phy_mask > (1 << iphy->phy_index)) { apc_activity = SCIC_SDS_APC_SKIP_PHY; break; } @@ -562,7 +537,7 @@ static void scic_sds_apc_agent_configure_ports( * We have reached the end of our Port list and have not found * any reason why we should not either add the PHY to the port * or wait for more phys to become active. */ - if (port->physical_port_index == phy->phy_index) { + if (port->physical_port_index == iphy->phy_index) { /* * The Port either has no active PHYs. * Consider that if the port had any active PHYs we would have @@ -608,10 +583,10 @@ static void scic_sds_apc_agent_configure_ports( switch (apc_activity) { case SCIC_SDS_APC_ADD_PHY: - status = scic_sds_port_add_phy(port, phy); + status = scic_sds_port_add_phy(port, iphy); if (status == SCI_SUCCESS) { - port_agent->phy_configured_mask |= (1 << phy->phy_index); + port_agent->phy_configured_mask |= (1 << iphy->phy_index); } break; @@ -651,14 +626,14 @@ static void scic_sds_apc_agent_configure_ports( static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent, struct scic_sds_port *sci_port, - struct scic_sds_phy *sci_phy) + struct isci_phy *iphy) { - u8 phy_index = sci_phy->phy_index; + u8 phy_index = iphy->phy_index; if (!sci_port) { /* the phy is not the part of this port */ port_agent->phy_ready_mask |= 1 << phy_index; - scic_sds_apc_agent_configure_ports(scic, port_agent, sci_phy, true); + scic_sds_apc_agent_configure_ports(scic, port_agent, iphy, true); } else { /* the phy is already the part of the port */ u32 port_state = sci_port->sm.current_state_id; @@ -669,7 +644,7 @@ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, */ BUG_ON(port_state != SCI_PORT_RESETTING); port_agent->phy_ready_mask |= 1 << phy_index; - scic_sds_port_link_up(sci_port, sci_phy); + scic_sds_port_link_up(sci_port, iphy); } } @@ -690,18 +665,18 @@ static void scic_sds_apc_agent_link_down( struct scic_sds_controller *controller, struct scic_sds_port_configuration_agent *port_agent, struct scic_sds_port *port, - struct scic_sds_phy *phy) + struct isci_phy *iphy) { - port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); + port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(iphy)); if (port != NULL) { - if (port_agent->phy_configured_mask & (1 << phy->phy_index)) { + if (port_agent->phy_configured_mask & (1 << iphy->phy_index)) { enum sci_status status; - status = scic_sds_port_remove_phy(port, phy); + status = scic_sds_port_remove_phy(port, iphy); if (status == SCI_SUCCESS) { - port_agent->phy_configured_mask &= ~(1 << phy->phy_index); + port_agent->phy_configured_mask &= ~(1 << iphy->phy_index); } } } @@ -739,7 +714,7 @@ static void apc_agent_timeout(unsigned long data) continue; scic_sds_apc_agent_configure_ports(scic, port_agent, - &ihost->phys[index].sci, false); + &ihost->phys[index], false); } done: diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index c7cb0c54df57..a81a864d35c4 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -1389,7 +1389,7 @@ int isci_remote_device_found(struct domain_device *domain_dev) sas_port = domain_dev->port; sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy, port_phy_el); - isci_phy = to_isci_phy(sas_phy); + isci_phy = to_iphy(sas_phy); isci_port = isci_phy->isci_port; /* we are being called for a device on this port, -- cgit v1.2.3 From 76802ce6756d605fbd7a9a43c196e9a471b3e57c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 29 Jun 2011 09:45:48 -0700 Subject: isci: fix scic_sds_remote_device_terminate_requests Commit 0815632 "isci: unify remote_device stop_handlers" introduced the possibility that not all requests get terminated if we reach the request_count. Now that we properly reference count devices we don't need this self-defense and can do the straightforward scan of all active requests. Reported-by: Jeff Skirvin Acked-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/remote_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index a81a864d35c4..71ab9081fe24 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -137,10 +137,10 @@ static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds { struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - u32 i, request_count = sci_dev->started_request_count; enum sci_status status = SCI_SUCCESS; + u32 i; - for (i = 0; i < SCI_MAX_IO_REQUESTS && i < request_count; i++) { + for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) { struct isci_request *ireq = ihost->reqs[i]; enum sci_status s; -- cgit v1.2.3 From ffe191c92ff195d73f9130b1490045ca2dd4c5e0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 29 Jun 2011 13:09:25 -0700 Subject: isci: unify isci_port and scic_sds_port Remove the distinction between these two implementations and unify on isci_port (local instances named iport). The duplicate '->owning_port' and '->isci_port' in both isci_phy and isci_remote_device will be fixed in a later patch... this is just the straightforward rename/unification. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 32 +- drivers/scsi/isci/host.h | 11 +- drivers/scsi/isci/phy.c | 10 +- drivers/scsi/isci/phy.h | 10 +- drivers/scsi/isci/port.c | 622 +++++++++++++++++++------------------- drivers/scsi/isci/port.h | 174 ++++------- drivers/scsi/isci/port_config.c | 99 +++--- drivers/scsi/isci/remote_device.c | 61 ++-- drivers/scsi/isci/remote_device.h | 10 +- drivers/scsi/isci/request.c | 33 +- 10 files changed, 481 insertions(+), 581 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index c5c2733a5197..4e11f9e6d766 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1054,9 +1054,9 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, /* Start all of the ports on this controller */ for (index = 0; index < scic->logical_port_entries; index++) { - struct scic_sds_port *sci_port = &ihost->ports[index].sci; + struct isci_port *iport = &ihost->ports[index]; - result = scic_sds_port_start(sci_port); + result = scic_sds_port_start(iport); if (result) return result; } @@ -1306,8 +1306,8 @@ void isci_host_deinit(struct isci_host *ihost) /* Cancel any/all outstanding port timers */ for (i = 0; i < ihost->sci.logical_port_entries; i++) { - struct scic_sds_port *sci_port = &ihost->ports[i].sci; - del_timer_sync(&sci_port->timer.timer); + struct isci_port *iport = &ihost->ports[i]; + del_timer_sync(&iport->timer.timer); } /* Cancel any/all outstanding phy timers */ @@ -1552,9 +1552,9 @@ static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller struct isci_host *ihost = scic_to_ihost(scic); for (index = 0; index < scic->logical_port_entries; index++) { - struct scic_sds_port *sci_port = &ihost->ports[index].sci; + struct isci_port *iport = &ihost->ports[index]; - port_status = scic_sds_port_stop(sci_port); + port_status = scic_sds_port_stop(iport); if ((port_status != SCI_SUCCESS) && (port_status != SCI_FAILURE_INVALID_STATE)) { @@ -1564,7 +1564,7 @@ static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller "%s: Controller stop operation failed to " "stop port %d because of status %d.\n", __func__, - sci_port->logical_port_index, + iport->logical_port_index, port_status); } } @@ -1780,14 +1780,14 @@ static enum sci_status scic_controller_construct(struct scic_sds_controller *sci /* Construct the ports for this controller */ for (i = 0; i < SCI_MAX_PORTS; i++) - scic_sds_port_construct(&ihost->ports[i].sci, i, scic); - scic_sds_port_construct(&ihost->ports[i].sci, SCIC_SDS_DUMMY_PORT, scic); + scic_sds_port_construct(&ihost->ports[i], i, scic); + scic_sds_port_construct(&ihost->ports[i], SCIC_SDS_DUMMY_PORT, scic); /* Construct the phys for this controller */ for (i = 0; i < SCI_MAX_PHYS; i++) { /* Add all the PHYs to the dummy port */ scic_sds_phy_construct(&ihost->phys[i], - &ihost->ports[SCI_MAX_PORTS].sci, i); + &ihost->ports[SCI_MAX_PORTS], i); } scic->invalid_phy_mask = 0; @@ -2233,7 +2233,7 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc } for (i = 0; i < scic->logical_port_entries; i++) { - result = scic_sds_port_initialize(&ihost->ports[i].sci, + result = scic_sds_port_initialize(&ihost->ports[i], &scic->scu_registers->peg0.ptsg.port[i], &scic->scu_registers->peg0.ptsg.protocol_engine, &scic->scu_registers->peg0.viit[i]); @@ -2484,19 +2484,19 @@ int isci_host_init(struct isci_host *isci_host) } void scic_sds_controller_link_up(struct scic_sds_controller *scic, - struct scic_sds_port *port, struct isci_phy *iphy) + struct isci_port *iport, struct isci_phy *iphy) { switch (scic->sm.current_state_id) { case SCIC_STARTING: sci_del_timer(&scic->phy_timer); scic->phy_startup_timer_pending = false; scic->port_agent.link_up_handler(scic, &scic->port_agent, - port, iphy); + iport, iphy); scic_sds_controller_start_next_phy(scic); break; case SCIC_READY: scic->port_agent.link_up_handler(scic, &scic->port_agent, - port, iphy); + iport, iphy); break; default: dev_dbg(scic_to_dev(scic), @@ -2507,13 +2507,13 @@ void scic_sds_controller_link_up(struct scic_sds_controller *scic, } void scic_sds_controller_link_down(struct scic_sds_controller *scic, - struct scic_sds_port *port, struct isci_phy *iphy) + struct isci_port *iport, struct isci_phy *iphy) { switch (scic->sm.current_state_id) { case SCIC_STARTING: case SCIC_READY: scic->port_agent.link_down_handler(scic, &scic->port_agent, - port, iphy); + iport, iphy); break; default: dev_dbg(scic_to_dev(scic), diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 1edd13535c24..fb8048e5fce7 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -108,7 +108,7 @@ struct scic_power_control { struct scic_sds_port_configuration_agent; typedef void (*port_config_fn)(struct scic_sds_controller *, struct scic_sds_port_configuration_agent *, - struct scic_sds_port *, struct isci_phy *); + struct isci_port *, struct isci_phy *); struct scic_sds_port_configuration_agent { u16 phy_configured_mask; @@ -532,9 +532,8 @@ static inline struct device *sciphy_to_dev(struct isci_phy *iphy) return &iphy->isci_port->isci_host->pdev->dev; } -static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port) +static inline struct device *sciport_to_dev(struct isci_port *iport) { - struct isci_port *iport = sci_port_to_iport(sci_port); if (!iport || !iport->isci_host) return NULL; @@ -613,12 +612,12 @@ void scic_sds_controller_power_control_queue_remove( void scic_sds_controller_link_up( struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy); void scic_sds_controller_link_down( struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy); void scic_sds_controller_remote_device_stopped( @@ -649,7 +648,7 @@ void isci_host_deinit( void isci_host_port_link_up( struct isci_host *, - struct scic_sds_port *, + struct isci_port *, struct isci_phy *); int isci_host_dev_found(struct domain_device *); diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 0e60fb7bc1ab..fd0e9734e5d0 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -286,7 +286,7 @@ done: * port (i.e. it's contained in the dummy port). !NULL All other * values indicate a handle/pointer to the port containing the phy. */ -struct scic_sds_port *phy_get_non_dummy_port( +struct isci_port *phy_get_non_dummy_port( struct isci_phy *iphy) { if (scic_sds_port_get_index(iphy->owning_port) == SCIC_SDS_DUMMY_PORT) @@ -304,9 +304,9 @@ struct scic_sds_port *phy_get_non_dummy_port( */ void scic_sds_phy_set_port( struct isci_phy *iphy, - struct scic_sds_port *sci_port) + struct isci_port *iport) { - iphy->owning_port = sci_port; + iphy->owning_port = iport; if (iphy->bcn_received_while_port_unassigned) { iphy->bcn_received_while_port_unassigned = false; @@ -1291,12 +1291,12 @@ static const struct sci_base_state scic_sds_phy_state_table[] = { }; void scic_sds_phy_construct(struct isci_phy *iphy, - struct scic_sds_port *owning_port, u8 phy_index) + struct isci_port *iport, u8 phy_index) { sci_init_sm(&iphy->sm, scic_sds_phy_state_table, SCI_PHY_INITIAL); /* Copy the rest of the input data to our locals */ - iphy->owning_port = owning_port; + iphy->owning_port = iport; iphy->phy_index = phy_index; iphy->bcn_received_while_port_unassigned = false; iphy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 345fbeacb5cf..19aa444517b4 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -93,7 +93,7 @@ enum scic_sds_phy_protocol { */ struct isci_phy { struct sci_base_state_machine sm; - struct scic_sds_port *owning_port; + struct isci_port *owning_port; enum sas_linkrate max_negotiated_speed; enum scic_sds_phy_protocol protocol; u8 phy_index; @@ -178,7 +178,7 @@ struct scic_phy_properties { * supplied phy. This field may be set to NULL * if the phy is not currently contained in a port. */ - struct scic_sds_port *owning_port; + struct isci_port *iport; /** * This field specifies the link rate at which the phy is @@ -459,14 +459,14 @@ enum scic_sds_phy_states { void scic_sds_phy_construct( struct isci_phy *iphy, - struct scic_sds_port *owning_port, + struct isci_port *iport, u8 phy_index); -struct scic_sds_port *phy_get_non_dummy_port(struct isci_phy *iphy); +struct isci_port *phy_get_non_dummy_port(struct isci_phy *iphy); void scic_sds_phy_set_port( struct isci_phy *iphy, - struct scic_sds_port *owning_port); + struct isci_port *iport); enum sci_status scic_sds_phy_initialize( struct isci_phy *iphy, diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index d53c0b1748e7..04591882ee77 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -83,7 +83,7 @@ static void isci_port_change_state(struct isci_port *iport, enum isci_status sta * transmit_identification register. */ static void -scic_sds_port_get_protocols(struct scic_sds_port *sci_port, +scic_sds_port_get_protocols(struct isci_port *iport, struct scic_phy_proto *protocols) { u8 index; @@ -91,8 +91,8 @@ scic_sds_port_get_protocols(struct scic_sds_port *sci_port, protocols->all = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) { - scic_sds_phy_get_protocols(sci_port->phy_table[index], + if (iport->phy_table[index] != NULL) { + scic_sds_phy_get_protocols(iport->phy_table[index], protocols); } } @@ -107,7 +107,7 @@ scic_sds_port_get_protocols(struct scic_sds_port *sci_port, * Return a bit mask indicating which phys are a part of this port. Each bit * corresponds to a phy identifier (e.g. bit 0 = phy id 0). */ -static u32 scic_sds_port_get_phys(struct scic_sds_port *sci_port) +static u32 scic_sds_port_get_phys(struct isci_port *iport) { u32 index; u32 mask; @@ -115,7 +115,7 @@ static u32 scic_sds_port_get_phys(struct scic_sds_port *sci_port) mask = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) { + if (iport->phy_table[index] != NULL) { mask |= (1 << index); } } @@ -136,30 +136,29 @@ static u32 scic_sds_port_get_phys(struct scic_sds_port *sci_port) * value is returned if the specified port is not valid. When this value is * returned, no data is copied to the properties output parameter. */ -static enum sci_status scic_port_get_properties(struct scic_sds_port *port, +static enum sci_status scic_port_get_properties(struct isci_port *iport, struct scic_port_properties *prop) { - if ((port == NULL) || - (port->logical_port_index == SCIC_SDS_DUMMY_PORT)) + if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT) return SCI_FAILURE_INVALID_PORT; - prop->index = port->logical_port_index; - prop->phy_mask = scic_sds_port_get_phys(port); - scic_sds_port_get_sas_address(port, &prop->local.sas_address); - scic_sds_port_get_protocols(port, &prop->local.protocols); - scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address); + prop->index = iport->logical_port_index; + prop->phy_mask = scic_sds_port_get_phys(iport); + scic_sds_port_get_sas_address(iport, &prop->local.sas_address); + scic_sds_port_get_protocols(iport, &prop->local.protocols); + scic_sds_port_get_attached_sas_address(iport, &prop->remote.sas_address); return SCI_SUCCESS; } -static void scic_port_bcn_enable(struct scic_sds_port *sci_port) +static void scic_port_bcn_enable(struct isci_port *iport) { struct isci_phy *iphy; u32 val; int i; - for (i = 0; i < ARRAY_SIZE(sci_port->phy_table); i++) { - iphy = sci_port->phy_table[i]; + for (i = 0; i < ARRAY_SIZE(iport->phy_table); i++) { + iphy = iport->phy_table[i]; if (!iphy) continue; val = readl(&iphy->link_layer_registers->link_layer_control); @@ -179,8 +178,8 @@ void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport) if (!test_and_clear_bit(IPORT_BCN_PENDING, &iport->flags)) return; - for (i = 0; i < ARRAY_SIZE(iport->sci.phy_table); i++) { - struct isci_phy *iphy = iport->sci.phy_table[i]; + for (i = 0; i < ARRAY_SIZE(iport->phy_table); i++) { + struct isci_phy *iphy = iport->phy_table[i]; if (!iphy) continue; @@ -191,12 +190,10 @@ void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport) } } -void isci_port_bc_change_received(struct isci_host *ihost, - struct scic_sds_port *sci_port, - struct isci_phy *iphy) +static void isci_port_bc_change_received(struct isci_host *ihost, + struct isci_port *iport, + struct isci_phy *iphy) { - struct isci_port *iport = iphy->isci_port; - if (iport && test_bit(IPORT_BCN_BLOCKED, &iport->flags)) { dev_dbg(&ihost->pdev->dev, "%s: disabled BCN; isci_phy = %p, sas_phy = %p\n", @@ -212,31 +209,30 @@ void isci_port_bc_change_received(struct isci_host *ihost, ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); } - scic_port_bcn_enable(sci_port); + scic_port_bcn_enable(iport); } static void isci_port_link_up(struct isci_host *isci_host, - struct scic_sds_port *port, + struct isci_port *iport, struct isci_phy *iphy) { unsigned long flags; struct scic_port_properties properties; - struct isci_port *isci_port = sci_port_to_iport(port); unsigned long success = true; BUG_ON(iphy->isci_port != NULL); - iphy->isci_port = isci_port; + iphy->isci_port = iport; dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", - __func__, isci_port); + __func__, iport); spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags); isci_port_change_state(iphy->isci_port, isci_starting); - scic_port_get_properties(port, &properties); + scic_port_get_properties(iport, &properties); if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { u64 attached_sas_address; @@ -370,7 +366,7 @@ static void isci_port_not_ready(struct isci_host *isci_host, struct isci_port *i } static void isci_port_stop_complete(struct scic_sds_controller *scic, - struct scic_sds_port *sci_port, + struct isci_port *iport, enum sci_status completion_status) { dev_dbg(&scic_to_ihost(scic)->pdev->dev, "Port stop complete\n"); @@ -408,30 +404,30 @@ static void isci_port_hard_reset_complete(struct isci_port *isci_port, * assignment for the port false if this is not a valid phy assignment for the * port */ -bool scic_sds_port_is_valid_phy_assignment(struct scic_sds_port *sci_port, +bool scic_sds_port_is_valid_phy_assignment(struct isci_port *iport, u32 phy_index) { /* Initialize to invalid value. */ u32 existing_phy_index = SCI_MAX_PHYS; u32 index; - if ((sci_port->physical_port_index == 1) && (phy_index != 1)) { + if ((iport->physical_port_index == 1) && (phy_index != 1)) { return false; } - if (sci_port->physical_port_index == 3 && phy_index != 3) { + if (iport->physical_port_index == 3 && phy_index != 3) { return false; } if ( - (sci_port->physical_port_index == 2) + (iport->physical_port_index == 2) && ((phy_index == 0) || (phy_index == 1)) ) { return false; } for (index = 0; index < SCI_MAX_PHYS; index++) { - if ((sci_port->phy_table[index] != NULL) + if ((iport->phy_table[index] != NULL) && (index != phy_index)) { existing_phy_index = index; } @@ -442,9 +438,9 @@ bool scic_sds_port_is_valid_phy_assignment(struct scic_sds_port *sci_port, * operating at the same maximum link rate. */ if ( (existing_phy_index < SCI_MAX_PHYS) - && (sci_port->owning_controller->user_parameters.sds1.phys[ + && (iport->owning_controller->user_parameters.sds1.phys[ phy_index].max_speed_generation != - sci_port->owning_controller->user_parameters.sds1.phys[ + iport->owning_controller->user_parameters.sds1.phys[ existing_phy_index].max_speed_generation) ) return false; @@ -465,25 +461,25 @@ bool scic_sds_port_is_valid_phy_assignment(struct scic_sds_port *sci_port, * port false if this is not a valid phy assignment for the port */ static bool scic_sds_port_is_phy_mask_valid( - struct scic_sds_port *sci_port, + struct isci_port *iport, u32 phy_mask) { - if (sci_port->physical_port_index == 0) { + if (iport->physical_port_index == 0) { if (((phy_mask & 0x0F) == 0x0F) || ((phy_mask & 0x03) == 0x03) || ((phy_mask & 0x01) == 0x01) || (phy_mask == 0)) return true; - } else if (sci_port->physical_port_index == 1) { + } else if (iport->physical_port_index == 1) { if (((phy_mask & 0x02) == 0x02) || (phy_mask == 0)) return true; - } else if (sci_port->physical_port_index == 2) { + } else if (iport->physical_port_index == 2) { if (((phy_mask & 0x0C) == 0x0C) || ((phy_mask & 0x04) == 0x04) || (phy_mask == 0)) return true; - } else if (sci_port->physical_port_index == 3) { + } else if (iport->physical_port_index == 3) { if (((phy_mask & 0x08) == 0x08) || (phy_mask == 0)) return true; @@ -500,7 +496,7 @@ static bool scic_sds_port_is_phy_mask_valid( * point) phys contained in the port. All other values specify a struct scic_sds_phy * object that is active in the port. */ -static struct isci_phy *scic_sds_port_get_a_connected_phy(struct scic_sds_port *sci_port) +static struct isci_phy *scic_sds_port_get_a_connected_phy(struct isci_port *iport) { u32 index; struct isci_phy *iphy; @@ -509,29 +505,29 @@ static struct isci_phy *scic_sds_port_get_a_connected_phy(struct scic_sds_port * /* Ensure that the phy is both part of the port and currently * connected to the remote end-point. */ - iphy = sci_port->phy_table[index]; - if (iphy && scic_sds_port_active_phy(sci_port, iphy)) + iphy = iport->phy_table[index]; + if (iphy && scic_sds_port_active_phy(iport, iphy)) return iphy; } return NULL; } -static enum sci_status scic_sds_port_set_phy(struct scic_sds_port *port, struct isci_phy *iphy) +static enum sci_status scic_sds_port_set_phy(struct isci_port *iport, struct isci_phy *iphy) { /* Check to see if we can add this phy to a port * that means that the phy is not part of a port and that the port does * not already have a phy assinged to the phy index. */ - if (!port->phy_table[iphy->phy_index] && + if (!iport->phy_table[iphy->phy_index] && !phy_get_non_dummy_port(iphy) && - scic_sds_port_is_valid_phy_assignment(port, iphy->phy_index)) { + scic_sds_port_is_valid_phy_assignment(iport, iphy->phy_index)) { /* Phy is being added in the stopped state so we are in MPC mode * make logical port index = physical port index */ - port->logical_port_index = port->physical_port_index; - port->phy_table[iphy->phy_index] = iphy; - scic_sds_phy_set_port(iphy, port); + iport->logical_port_index = iport->physical_port_index; + iport->phy_table[iphy->phy_index] = iphy; + scic_sds_phy_set_port(iphy, iport); return SCI_SUCCESS; } @@ -539,18 +535,18 @@ static enum sci_status scic_sds_port_set_phy(struct scic_sds_port *port, struct return SCI_FAILURE; } -static enum sci_status scic_sds_port_clear_phy(struct scic_sds_port *port, +static enum sci_status scic_sds_port_clear_phy(struct isci_port *iport, struct isci_phy *iphy) { /* Make sure that this phy is part of this port */ - if (port->phy_table[iphy->phy_index] == iphy && - phy_get_non_dummy_port(iphy) == port) { - struct scic_sds_controller *scic = port->owning_controller; + if (iport->phy_table[iphy->phy_index] == iphy && + phy_get_non_dummy_port(iphy) == iport) { + struct scic_sds_controller *scic = iport->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); /* Yep it is assigned to this port so remove it */ - scic_sds_phy_set_port(iphy, &ihost->ports[SCI_MAX_PORTS].sci); - port->phy_table[iphy->phy_index] = NULL; + scic_sds_phy_set_port(iphy, &ihost->ports[SCI_MAX_PORTS]); + iport->phy_table[iphy->phy_index] = NULL; return SCI_SUCCESS; } @@ -568,7 +564,7 @@ static enum sci_status scic_sds_port_clear_phy(struct scic_sds_port *port, * */ void scic_sds_port_get_sas_address( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct sci_sas_address *sas_address) { u32 index; @@ -577,8 +573,8 @@ void scic_sds_port_get_sas_address( sas_address->low = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) { - scic_sds_phy_get_sas_address(sci_port->phy_table[index], sas_address); + if (iport->phy_table[index] != NULL) { + scic_sds_phy_get_sas_address(iport->phy_table[index], sas_address); } } } @@ -594,7 +590,7 @@ void scic_sds_port_get_sas_address( * */ void scic_sds_port_get_attached_sas_address( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct sci_sas_address *sas_address) { struct isci_phy *iphy; @@ -603,7 +599,7 @@ void scic_sds_port_get_attached_sas_address( * Ensure that the phy is both part of the port and currently * connected to the remote end-point. */ - iphy = scic_sds_port_get_a_connected_phy(sci_port); + iphy = scic_sds_port_get_a_connected_phy(iport); if (iphy) { if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) { scic_sds_phy_get_attached_sas_address(iphy, @@ -628,11 +624,11 @@ void scic_sds_port_get_attached_sas_address( * This structure will be posted to the hardware to work around a scheduler * error in the hardware. */ -static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u16 rni) +static void scic_sds_port_construct_dummy_rnc(struct isci_port *iport, u16 rni) { union scu_remote_node_context *rnc; - rnc = &sci_port->owning_controller->remote_node_context_table[rni]; + rnc = &iport->owning_controller->remote_node_context_table[rni]; memset(rnc, 0, sizeof(union scu_remote_node_context)); @@ -641,7 +637,7 @@ static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u1 rnc->ssp.remote_node_index = rni; rnc->ssp.remote_node_port_width = 1; - rnc->ssp.logical_port_index = sci_port->physical_port_index; + rnc->ssp.logical_port_index = iport->physical_port_index; rnc->ssp.nexus_loss_timer_enable = false; rnc->ssp.check_bit = false; @@ -656,9 +652,9 @@ static void scic_sds_port_construct_dummy_rnc(struct scic_sds_port *sci_port, u1 * structure will be posted to the hardwre to work around a scheduler error * in the hardware. */ -static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u16 tag) +static void scic_sds_port_construct_dummy_task(struct isci_port *iport, u16 tag) { - struct scic_sds_controller *scic = sci_port->owning_controller; + struct scic_sds_controller *scic = iport->owning_controller; struct scu_task_context *task_context; task_context = &scic->task_context_table[ISCI_TAG_TCI(tag)]; @@ -666,29 +662,29 @@ static void scic_sds_port_construct_dummy_task(struct scic_sds_port *sci_port, u task_context->initiator_request = 1; task_context->connection_rate = 1; - task_context->logical_port_index = sci_port->physical_port_index; + task_context->logical_port_index = iport->physical_port_index; task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; task_context->task_index = ISCI_TAG_TCI(tag); task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; - task_context->remote_node_index = sci_port->reserved_rni; + task_context->remote_node_index = iport->reserved_rni; task_context->do_not_dma_ssp_good_response = 1; task_context->task_phase = 0x01; } -static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port) +static void scic_sds_port_destroy_dummy_resources(struct isci_port *iport) { - struct scic_sds_controller *scic = sci_port->owning_controller; + struct scic_sds_controller *scic = iport->owning_controller; - if (sci_port->reserved_tag != SCI_CONTROLLER_INVALID_IO_TAG) - isci_free_tag(scic_to_ihost(scic), sci_port->reserved_tag); + if (iport->reserved_tag != SCI_CONTROLLER_INVALID_IO_TAG) + isci_free_tag(scic_to_ihost(scic), iport->reserved_tag); - if (sci_port->reserved_rni != SCU_DUMMY_INDEX) + if (iport->reserved_rni != SCU_DUMMY_INDEX) scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes, - 1, sci_port->reserved_rni); + 1, iport->reserved_rni); - sci_port->reserved_rni = SCU_DUMMY_INDEX; - sci_port->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; + iport->reserved_rni = SCU_DUMMY_INDEX; + iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; } /** @@ -704,14 +700,14 @@ static void scic_sds_port_destroy_dummy_resources(struct scic_sds_port *sci_port * if the phy being added to the port */ enum sci_status scic_sds_port_initialize( - struct scic_sds_port *sci_port, + struct isci_port *iport, void __iomem *port_task_scheduler_registers, void __iomem *port_configuration_regsiter, void __iomem *viit_registers) { - sci_port->port_task_scheduler_registers = port_task_scheduler_registers; - sci_port->port_pe_configuration_register = port_configuration_regsiter; - sci_port->viit_registers = viit_registers; + iport->port_task_scheduler_registers = port_task_scheduler_registers; + iport->port_pe_configuration_register = port_configuration_regsiter; + iport->viit_registers = viit_registers; return SCI_SUCCESS; } @@ -720,20 +716,20 @@ enum sci_status scic_sds_port_initialize( /** * This method assigns the direct attached device ID for this port. * - * @param[in] sci_port The port for which the direct attached device id is to + * @param[in] iport The port for which the direct attached device id is to * be assigned. * @param[in] device_id The direct attached device ID to assign to the port. * This will be the RNi for the device */ void scic_sds_port_setup_transports( - struct scic_sds_port *sci_port, + struct isci_port *iport, u32 device_id) { u8 index; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->active_phy_mask & (1 << index)) - scic_sds_phy_setup_transport(sci_port->phy_table[index], device_id); + if (iport->active_phy_mask & (1 << index)) + scic_sds_phy_setup_transport(iport->phy_table[index], device_id); } } @@ -749,39 +745,38 @@ void scic_sds_port_setup_transports( * the phy to the port - enabling the Protocol Engine in the silicon. - * notifying the user that the link is up. none */ -static void scic_sds_port_activate_phy(struct scic_sds_port *sci_port, +static void scic_sds_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user) { - struct scic_sds_controller *scic = sci_port->owning_controller; + struct scic_sds_controller *scic = iport->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) scic_sds_phy_resume(iphy); - sci_port->active_phy_mask |= 1 << iphy->phy_index; + iport->active_phy_mask |= 1 << iphy->phy_index; scic_sds_controller_clear_invalid_phy(scic, iphy); if (do_notify_user == true) - isci_port_link_up(ihost, sci_port, iphy); + isci_port_link_up(ihost, iport, iphy); } -void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, +void scic_sds_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user) { - struct scic_sds_controller *scic = scic_sds_port_get_controller(sci_port); - struct isci_port *iport = sci_port_to_iport(sci_port); + struct scic_sds_controller *scic = scic_sds_port_get_controller(iport); struct isci_host *ihost = scic_to_ihost(scic); - sci_port->active_phy_mask &= ~(1 << iphy->phy_index); + iport->active_phy_mask &= ~(1 << iphy->phy_index); iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; /* Re-assign the phy back to the LP as if it were a narrow port */ writel(iphy->phy_index, - &sci_port->port_pe_configuration_register[iphy->phy_index]); + &iport->port_pe_configuration_register[iphy->phy_index]); if (do_notify_user == true) isci_port_link_down(ihost, iphy, iport); @@ -795,10 +790,10 @@ void scic_sds_port_deactivate_phy(struct scic_sds_port *sci_port, * This function will disable the phy and report that the phy is not valid for * this port object. None */ -static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, +static void scic_sds_port_invalid_link_up(struct isci_port *iport, struct isci_phy *iphy) { - struct scic_sds_controller *scic = sci_port->owning_controller; + struct scic_sds_controller *scic = iport->owning_controller; /* * Check to see if we have alreay reported this link as bad and if @@ -825,17 +820,17 @@ static bool is_port_ready_state(enum scic_sds_port_states state) } /* flag dummy rnc hanling when exiting a ready state */ -static void port_state_machine_change(struct scic_sds_port *sci_port, +static void port_state_machine_change(struct isci_port *iport, enum scic_sds_port_states state) { - struct sci_base_state_machine *sm = &sci_port->sm; + struct sci_base_state_machine *sm = &iport->sm; enum scic_sds_port_states old_state = sm->current_state_id; if (is_port_ready_state(old_state) && !is_port_ready_state(state)) - sci_port->ready_exit = true; + iport->ready_exit = true; sci_change_state(sm, state); - sci_port->ready_exit = false; + iport->ready_exit = false; } /** @@ -851,14 +846,14 @@ static void port_state_machine_change(struct scic_sds_port *sci_port, * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in * the same port. none */ -static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port, +static void scic_sds_port_general_link_up_handler(struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user) { struct sci_sas_address port_sas_address; struct sci_sas_address phy_sas_address; - scic_sds_port_get_attached_sas_address(sci_port, &port_sas_address); + scic_sds_port_get_attached_sas_address(iport, &port_sas_address); scic_sds_phy_get_attached_sas_address(iphy, &phy_sas_address); /* If the SAS address of the new phy matches the SAS address of @@ -868,14 +863,14 @@ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port */ if ((phy_sas_address.high == port_sas_address.high && phy_sas_address.low == port_sas_address.low) || - sci_port->active_phy_mask == 0) { - struct sci_base_state_machine *sm = &sci_port->sm; + iport->active_phy_mask == 0) { + struct sci_base_state_machine *sm = &iport->sm; - scic_sds_port_activate_phy(sci_port, iphy, do_notify_user); + scic_sds_port_activate_phy(iport, iphy, do_notify_user); if (sm->current_state_id == SCI_PORT_RESETTING) - port_state_machine_change(sci_port, SCI_PORT_READY); + port_state_machine_change(iport, SCI_PORT_READY); } else - scic_sds_port_invalid_link_up(sci_port, iphy); + scic_sds_port_invalid_link_up(iport, iphy); } @@ -889,13 +884,13 @@ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port * bool true Is returned if this is a wide ported port. false Is returned if * this is a narrow port. */ -static bool scic_sds_port_is_wide(struct scic_sds_port *sci_port) +static bool scic_sds_port_is_wide(struct isci_port *iport) { u32 index; u32 phy_count = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index] != NULL) { + if (iport->phy_table[index] != NULL) { phy_count++; } } @@ -918,13 +913,13 @@ static bool scic_sds_port_is_wide(struct scic_sds_port *sci_port) * devices this could become an invalid port configuration. */ bool scic_sds_port_link_detected( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy) { - if ((sci_port->logical_port_index != SCIC_SDS_DUMMY_PORT) && + if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) && (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && - scic_sds_port_is_wide(sci_port)) { - scic_sds_port_invalid_link_up(sci_port, iphy); + scic_sds_port_is_wide(iport)) { + scic_sds_port_invalid_link_up(iport, iphy); return false; } @@ -935,8 +930,8 @@ bool scic_sds_port_link_detected( static void port_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; - struct scic_sds_port *sci_port = container_of(tmr, typeof(*sci_port), timer); - struct isci_host *ihost = scic_to_ihost(sci_port->owning_controller); + struct isci_port *iport = container_of(tmr, typeof(*iport), timer); + struct isci_host *ihost = scic_to_ihost(iport->owning_controller); unsigned long flags; u32 current_state; @@ -945,33 +940,33 @@ static void port_timeout(unsigned long data) if (tmr->cancel) goto done; - current_state = sci_port->sm.current_state_id; + current_state = iport->sm.current_state_id; if (current_state == SCI_PORT_RESETTING) { /* if the port is still in the resetting state then the timeout * fired before the reset completed. */ - port_state_machine_change(sci_port, SCI_PORT_FAILED); + port_state_machine_change(iport, SCI_PORT_FAILED); } else if (current_state == SCI_PORT_STOPPED) { /* if the port is stopped then the start request failed In this * case stay in the stopped state. */ - dev_err(sciport_to_dev(sci_port), + dev_err(sciport_to_dev(iport), "%s: SCIC Port 0x%p failed to stop before tiemout.\n", __func__, - sci_port); + iport); } else if (current_state == SCI_PORT_STOPPING) { /* if the port is still stopping then the stop has not completed */ - isci_port_stop_complete(sci_port->owning_controller, - sci_port, + isci_port_stop_complete(iport->owning_controller, + iport, SCI_FAILURE_TIMEOUT); } else { /* The port is in the ready state and we have a timer * reporting a timeout this should not happen. */ - dev_err(sciport_to_dev(sci_port), + dev_err(sciport_to_dev(iport), "%s: SCIC Port 0x%p is processing a timeout operation " - "in state %d.\n", __func__, sci_port, current_state); + "in state %d.\n", __func__, iport, current_state); } done: @@ -985,29 +980,29 @@ done: * * */ -static void scic_sds_port_update_viit_entry(struct scic_sds_port *sci_port) +static void scic_sds_port_update_viit_entry(struct isci_port *iport) { struct sci_sas_address sas_address; - scic_sds_port_get_sas_address(sci_port, &sas_address); + scic_sds_port_get_sas_address(iport, &sas_address); writel(sas_address.high, - &sci_port->viit_registers->initiator_sas_address_hi); + &iport->viit_registers->initiator_sas_address_hi); writel(sas_address.low, - &sci_port->viit_registers->initiator_sas_address_lo); + &iport->viit_registers->initiator_sas_address_lo); /* This value get cleared just in case its not already cleared */ - writel(0, &sci_port->viit_registers->reserved); + writel(0, &iport->viit_registers->reserved); /* We are required to update the status register last */ writel(SCU_VIIT_ENTRY_ID_VIIT | SCU_VIIT_IPPT_INITIATOR | - ((1 << sci_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) | + ((1 << iport->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) | SCU_VIIT_STATUS_ALL_VALID, - &sci_port->viit_registers->status); + &iport->viit_registers->status); } -enum sas_linkrate scic_sds_port_get_max_allowed_speed(struct scic_sds_port *sci_port) +enum sas_linkrate scic_sds_port_get_max_allowed_speed(struct isci_port *iport) { u16 index; struct isci_phy *iphy; @@ -1017,8 +1012,8 @@ enum sas_linkrate scic_sds_port_get_max_allowed_speed(struct scic_sds_port *sci_ * Loop through all of the phys in this port and find the phy with the * lowest maximum link rate. */ for (index = 0; index < SCI_MAX_PHYS; index++) { - iphy = sci_port->phy_table[index]; - if (iphy && scic_sds_port_active_phy(sci_port, iphy) && + iphy = iport->phy_table[index]; + if (iphy && scic_sds_port_active_phy(iport, iphy) && iphy->max_negotiated_speed < max_allowed_speed) max_allowed_speed = iphy->max_negotiated_speed; } @@ -1026,13 +1021,13 @@ enum sas_linkrate scic_sds_port_get_max_allowed_speed(struct scic_sds_port *sci_ return max_allowed_speed; } -static void scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port) +static void scic_sds_port_suspend_port_task_scheduler(struct isci_port *iport) { u32 pts_control_value; - pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value = readl(&iport->port_task_scheduler_registers->control); pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND); - writel(pts_control_value, &port->port_task_scheduler_registers->control); + writel(pts_control_value, &iport->port_task_scheduler_registers->control); } /** @@ -1044,10 +1039,10 @@ static void scic_sds_port_suspend_port_task_scheduler(struct scic_sds_port *port * ongoing requests. * */ -static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) +static void scic_sds_port_post_dummy_request(struct isci_port *iport) { - struct scic_sds_controller *scic = sci_port->owning_controller; - u16 tag = sci_port->reserved_tag; + struct scic_sds_controller *scic = iport->owning_controller; + u16 tag = iport->reserved_tag; struct scu_task_context *tc; u32 command; @@ -1055,7 +1050,7 @@ static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) tc->abort = 0; command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | + iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ISCI_TAG_TCI(tag); scic_sds_controller_post_request(scic, command); @@ -1068,10 +1063,10 @@ static void scic_sds_port_post_dummy_request(struct scic_sds_port *sci_port) * @sci_port: The port on which the task must be aborted. * */ -static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) +static void scic_sds_port_abort_dummy_request(struct isci_port *iport) { - struct scic_sds_controller *scic = sci_port->owning_controller; - u16 tag = sci_port->reserved_tag; + struct scic_sds_controller *scic = iport->owning_controller; + u16 tag = iport->reserved_tag; struct scu_task_context *tc; u32 command; @@ -1079,7 +1074,7 @@ static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) tc->abort = 1; command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT | - sci_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | + iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ISCI_TAG_TCI(tag); scic_sds_controller_post_request(scic, command); @@ -1087,31 +1082,31 @@ static void scic_sds_port_abort_dummy_request(struct scic_sds_port *sci_port) /** * - * @sci_port: This is the struct scic_sds_port object to resume. + * @sci_port: This is the struct isci_port object to resume. * * This method will resume the port task scheduler for this port object. none */ static void -scic_sds_port_resume_port_task_scheduler(struct scic_sds_port *port) +scic_sds_port_resume_port_task_scheduler(struct isci_port *iport) { u32 pts_control_value; - pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value = readl(&iport->port_task_scheduler_registers->control); pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND); - writel(pts_control_value, &port->port_task_scheduler_registers->control); + writel(pts_control_value, &iport->port_task_scheduler_registers->control); } static void scic_sds_port_ready_substate_waiting_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); + struct isci_port *iport = container_of(sm, typeof(*iport), sm); - scic_sds_port_suspend_port_task_scheduler(sci_port); + scic_sds_port_suspend_port_task_scheduler(iport); - sci_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; + iport->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; - if (sci_port->active_phy_mask != 0) { + if (iport->active_phy_mask != 0) { /* At least one of the phys on the port is ready */ - port_state_machine_change(sci_port, + port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); } } @@ -1119,38 +1114,37 @@ static void scic_sds_port_ready_substate_waiting_enter(struct sci_base_state_mac static void scic_sds_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) { u32 index; - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); - struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_port *iport = container_of(sm, typeof(*iport), sm); + struct scic_sds_controller *scic = iport->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port_to_iport(sci_port); isci_port_ready(ihost, iport); for (index = 0; index < SCI_MAX_PHYS; index++) { - if (sci_port->phy_table[index]) { - writel(sci_port->physical_port_index, - &sci_port->port_pe_configuration_register[ - sci_port->phy_table[index]->phy_index]); + if (iport->phy_table[index]) { + writel(iport->physical_port_index, + &iport->port_pe_configuration_register[ + iport->phy_table[index]->phy_index]); } } - scic_sds_port_update_viit_entry(sci_port); + scic_sds_port_update_viit_entry(iport); - scic_sds_port_resume_port_task_scheduler(sci_port); + scic_sds_port_resume_port_task_scheduler(iport); /* * Post the dummy task for the port so the hardware can schedule * io correctly */ - scic_sds_port_post_dummy_request(sci_port); + scic_sds_port_post_dummy_request(iport); } -static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) +static void scic_sds_port_invalidate_dummy_remote_node(struct isci_port *iport) { - struct scic_sds_controller *scic = sci_port->owning_controller; - u8 phys_index = sci_port->physical_port_index; + struct scic_sds_controller *scic = iport->owning_controller; + u8 phys_index = iport->physical_port_index; union scu_remote_node_context *rnc; - u16 rni = sci_port->reserved_rni; + u16 rni = iport->reserved_rni; u32 command; rnc = &scic->remote_node_context_table[rni]; @@ -1172,73 +1166,71 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci /** * - * @object: This is the object which is cast to a struct scic_sds_port object. + * @object: This is the object which is cast to a struct isci_port object. * - * This method will perform the actions required by the struct scic_sds_port on + * This method will perform the actions required by the struct isci_port on * exiting the SCI_PORT_SUB_OPERATIONAL. This function reports * the port not ready and suspends the port task scheduler. none */ static void scic_sds_port_ready_substate_operational_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); - struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_port *iport = container_of(sm, typeof(*iport), sm); + struct scic_sds_controller *scic = iport->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port_to_iport(sci_port); /* * Kill the dummy task for this port if it has not yet posted * the hardware will treat this as a NOP and just return abort * complete. */ - scic_sds_port_abort_dummy_request(sci_port); + scic_sds_port_abort_dummy_request(iport); isci_port_not_ready(ihost, iport); - if (sci_port->ready_exit) - scic_sds_port_invalidate_dummy_remote_node(sci_port); + if (iport->ready_exit) + scic_sds_port_invalidate_dummy_remote_node(iport); } static void scic_sds_port_ready_substate_configuring_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); - struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_port *iport = container_of(sm, typeof(*iport), sm); + struct scic_sds_controller *scic = iport->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port_to_iport(sci_port); - if (sci_port->active_phy_mask == 0) { + if (iport->active_phy_mask == 0) { isci_port_not_ready(ihost, iport); - port_state_machine_change(sci_port, + port_state_machine_change(iport, SCI_PORT_SUB_WAITING); - } else if (sci_port->started_request_count == 0) - port_state_machine_change(sci_port, + } else if (iport->started_request_count == 0) + port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); } static void scic_sds_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); + struct isci_port *iport = container_of(sm, typeof(*iport), sm); - scic_sds_port_suspend_port_task_scheduler(sci_port); - if (sci_port->ready_exit) - scic_sds_port_invalidate_dummy_remote_node(sci_port); + scic_sds_port_suspend_port_task_scheduler(iport); + if (iport->ready_exit) + scic_sds_port_invalidate_dummy_remote_node(iport); } -enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) +enum sci_status scic_sds_port_start(struct isci_port *iport) { - struct scic_sds_controller *scic = sci_port->owning_controller; + struct scic_sds_controller *scic = iport->owning_controller; enum sci_status status = SCI_SUCCESS; enum scic_sds_port_states state; u32 phy_mask; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; if (state != SCI_PORT_STOPPED) { - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - if (sci_port->assigned_device_count > 0) { + if (iport->assigned_device_count > 0) { /* TODO This is a start failure operation because * there are still devices assigned to this port. * There must be no devices assigned to a port on a @@ -1247,18 +1239,18 @@ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } - if (sci_port->reserved_rni == SCU_DUMMY_INDEX) { + if (iport->reserved_rni == SCU_DUMMY_INDEX) { u16 rni = scic_sds_remote_node_table_allocate_remote_node( &scic->available_remote_nodes, 1); if (rni != SCU_DUMMY_INDEX) - scic_sds_port_construct_dummy_rnc(sci_port, rni); + scic_sds_port_construct_dummy_rnc(iport, rni); else status = SCI_FAILURE_INSUFFICIENT_RESOURCES; - sci_port->reserved_rni = rni; + iport->reserved_rni = rni; } - if (sci_port->reserved_tag == SCI_CONTROLLER_INVALID_IO_TAG) { + if (iport->reserved_tag == SCI_CONTROLLER_INVALID_IO_TAG) { struct isci_host *ihost = scic_to_ihost(scic); u16 tag; @@ -1266,20 +1258,20 @@ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) if (tag == SCI_CONTROLLER_INVALID_IO_TAG) status = SCI_FAILURE_INSUFFICIENT_RESOURCES; else - scic_sds_port_construct_dummy_task(sci_port, tag); - sci_port->reserved_tag = tag; + scic_sds_port_construct_dummy_task(iport, tag); + iport->reserved_tag = tag; } if (status == SCI_SUCCESS) { - phy_mask = scic_sds_port_get_phys(sci_port); + phy_mask = scic_sds_port_get_phys(iport); /* * There are one or more phys assigned to this port. Make sure * the port's phy mask is in fact legal and supported by the * silicon. */ - if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { - port_state_machine_change(sci_port, + if (scic_sds_port_is_phy_mask_valid(iport, phy_mask) == true) { + port_state_machine_change(iport, SCI_PORT_READY); return SCI_SUCCESS; @@ -1288,16 +1280,16 @@ enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port) } if (status != SCI_SUCCESS) - scic_sds_port_destroy_dummy_resources(sci_port); + scic_sds_port_destroy_dummy_resources(iport); return status; } -enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port) +enum sci_status scic_sds_port_stop(struct isci_port *iport) { enum scic_sds_port_states state; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; switch (state) { case SCI_PORT_STOPPED: return SCI_SUCCESS; @@ -1305,34 +1297,34 @@ enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port) case SCI_PORT_SUB_OPERATIONAL: case SCI_PORT_SUB_CONFIGURING: case SCI_PORT_RESETTING: - port_state_machine_change(sci_port, + port_state_machine_change(iport, SCI_PORT_STOPPING); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } } -static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 timeout) +static enum sci_status scic_port_hard_reset(struct isci_port *iport, u32 timeout) { enum sci_status status = SCI_FAILURE_INVALID_PHY; struct isci_phy *iphy = NULL; enum scic_sds_port_states state; u32 phy_index; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; if (state != SCI_PORT_SUB_OPERATIONAL) { - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } /* Select a phy on which we can send the hard reset request. */ for (phy_index = 0; phy_index < SCI_MAX_PHYS && !iphy; phy_index++) { - iphy = sci_port->phy_table[phy_index]; - if (iphy && !scic_sds_port_active_phy(sci_port, iphy)) { + iphy = iport->phy_table[phy_index]; + if (iphy && !scic_sds_port_active_phy(iport, iphy)) { /* * We found a phy but it is not ready select * different phy @@ -1349,10 +1341,10 @@ static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 if (status != SCI_SUCCESS) return status; - sci_mod_timer(&sci_port->timer, timeout); - sci_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; + sci_mod_timer(&iport->timer, timeout); + iport->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; - port_state_machine_change(sci_port, SCI_PORT_RESETTING); + port_state_machine_change(iport, SCI_PORT_RESETTING); return SCI_SUCCESS; } @@ -1365,19 +1357,19 @@ static enum sci_status scic_port_hard_reset(struct scic_sds_port *sci_port, u32 * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other * status is a failure to add the phy to the port. */ -enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, +enum sci_status scic_sds_port_add_phy(struct isci_port *iport, struct isci_phy *iphy) { enum sci_status status; enum scic_sds_port_states state; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; switch (state) { case SCI_PORT_STOPPED: { struct sci_sas_address port_sas_address; /* Read the port assigned SAS Address if there is one */ - scic_sds_port_get_sas_address(sci_port, &port_sas_address); + scic_sds_port_get_sas_address(iport, &port_sas_address); if (port_sas_address.high != 0 && port_sas_address.low != 0) { struct sci_sas_address phy_sas_address; @@ -1391,35 +1383,35 @@ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, port_sas_address.low != phy_sas_address.low) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } - return scic_sds_port_set_phy(sci_port, iphy); + return scic_sds_port_set_phy(iport, iphy); } case SCI_PORT_SUB_WAITING: case SCI_PORT_SUB_OPERATIONAL: - status = scic_sds_port_set_phy(sci_port, iphy); + status = scic_sds_port_set_phy(iport, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_general_link_up_handler(sci_port, iphy, true); - sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; - port_state_machine_change(sci_port, SCI_PORT_SUB_CONFIGURING); + scic_sds_port_general_link_up_handler(iport, iphy, true); + iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); return status; case SCI_PORT_SUB_CONFIGURING: - status = scic_sds_port_set_phy(sci_port, iphy); + status = scic_sds_port_set_phy(iport, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_general_link_up_handler(sci_port, iphy, true); + scic_sds_port_general_link_up_handler(iport, iphy, true); /* Re-enter the configuring state since this may be the last phy in * the port. */ - port_state_machine_change(sci_port, + port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } @@ -1434,65 +1426,65 @@ enum sci_status scic_sds_port_add_phy(struct scic_sds_port *sci_port, * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any * other status is a failure to add the phy to the port. */ -enum sci_status scic_sds_port_remove_phy(struct scic_sds_port *sci_port, +enum sci_status scic_sds_port_remove_phy(struct isci_port *iport, struct isci_phy *iphy) { enum sci_status status; enum scic_sds_port_states state; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; switch (state) { case SCI_PORT_STOPPED: - return scic_sds_port_clear_phy(sci_port, iphy); + return scic_sds_port_clear_phy(iport, iphy); case SCI_PORT_SUB_OPERATIONAL: - status = scic_sds_port_clear_phy(sci_port, iphy); + status = scic_sds_port_clear_phy(iport, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_deactivate_phy(sci_port, iphy, true); - sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; - port_state_machine_change(sci_port, + scic_sds_port_deactivate_phy(iport, iphy, true); + iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; + port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; case SCI_PORT_SUB_CONFIGURING: - status = scic_sds_port_clear_phy(sci_port, iphy); + status = scic_sds_port_clear_phy(iport, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_deactivate_phy(sci_port, iphy, true); + scic_sds_port_deactivate_phy(iport, iphy, true); /* Re-enter the configuring state since this may be the last phy in * the port */ - port_state_machine_change(sci_port, + port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } } -enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, +enum sci_status scic_sds_port_link_up(struct isci_port *iport, struct isci_phy *iphy) { enum scic_sds_port_states state; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; switch (state) { case SCI_PORT_SUB_WAITING: /* Since this is the first phy going link up for the port we * can just enable it and continue */ - scic_sds_port_activate_phy(sci_port, iphy, true); + scic_sds_port_activate_phy(iport, iphy, true); - port_state_machine_change(sci_port, + port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); return SCI_SUCCESS; case SCI_PORT_SUB_OPERATIONAL: - scic_sds_port_general_link_up_handler(sci_port, iphy, true); + scic_sds_port_general_link_up_handler(iport, iphy, true); return SCI_SUCCESS; case SCI_PORT_RESETTING: /* TODO We should make sure that the phy that has gone @@ -1509,82 +1501,82 @@ enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, /* In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_general_link_up_handler(sci_port, iphy, false); + scic_sds_port_general_link_up_handler(iport, iphy, false); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } } -enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, +enum sci_status scic_sds_port_link_down(struct isci_port *iport, struct isci_phy *iphy) { enum scic_sds_port_states state; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; switch (state) { case SCI_PORT_SUB_OPERATIONAL: - scic_sds_port_deactivate_phy(sci_port, iphy, true); + scic_sds_port_deactivate_phy(iport, iphy, true); /* If there are no active phys left in the port, then * transition the port to the WAITING state until such time * as a phy goes link up */ - if (sci_port->active_phy_mask == 0) - port_state_machine_change(sci_port, + if (iport->active_phy_mask == 0) + port_state_machine_change(iport, SCI_PORT_SUB_WAITING); return SCI_SUCCESS; case SCI_PORT_RESETTING: /* In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_deactivate_phy(sci_port, iphy, false); + scic_sds_port_deactivate_phy(iport, iphy, false); return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } } -enum sci_status scic_sds_port_start_io(struct scic_sds_port *sci_port, +enum sci_status scic_sds_port_start_io(struct isci_port *iport, struct scic_sds_remote_device *sci_dev, struct isci_request *ireq) { enum scic_sds_port_states state; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; switch (state) { case SCI_PORT_SUB_WAITING: return SCI_FAILURE_INVALID_STATE; case SCI_PORT_SUB_OPERATIONAL: - sci_port->started_request_count++; + iport->started_request_count++; return SCI_SUCCESS; default: - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } } -enum sci_status scic_sds_port_complete_io(struct scic_sds_port *sci_port, +enum sci_status scic_sds_port_complete_io(struct isci_port *iport, struct scic_sds_remote_device *sci_dev, struct isci_request *ireq) { enum scic_sds_port_states state; - state = sci_port->sm.current_state_id; + state = iport->sm.current_state_id; switch (state) { case SCI_PORT_STOPPED: - dev_warn(sciport_to_dev(sci_port), + dev_warn(sciport_to_dev(iport), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; case SCI_PORT_STOPPING: - scic_sds_port_decrement_request_count(sci_port); + scic_sds_port_decrement_request_count(iport); - if (sci_port->started_request_count == 0) - port_state_machine_change(sci_port, + if (iport->started_request_count == 0) + port_state_machine_change(iport, SCI_PORT_STOPPED); break; case SCI_PORT_READY: @@ -1592,12 +1584,12 @@ enum sci_status scic_sds_port_complete_io(struct scic_sds_port *sci_port, case SCI_PORT_FAILED: case SCI_PORT_SUB_WAITING: case SCI_PORT_SUB_OPERATIONAL: - scic_sds_port_decrement_request_count(sci_port); + scic_sds_port_decrement_request_count(iport); break; case SCI_PORT_SUB_CONFIGURING: - scic_sds_port_decrement_request_count(sci_port); - if (sci_port->started_request_count == 0) { - port_state_machine_change(sci_port, + scic_sds_port_decrement_request_count(iport); + if (iport->started_request_count == 0) { + port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); } break; @@ -1613,13 +1605,13 @@ enum sci_status scic_sds_port_complete_io(struct scic_sds_port *sci_port, * will leave the port task scheduler in a suspended state. none */ static void -scic_sds_port_enable_port_task_scheduler(struct scic_sds_port *port) +scic_sds_port_enable_port_task_scheduler(struct isci_port *iport) { u32 pts_control_value; - pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value = readl(&iport->port_task_scheduler_registers->control); pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND); - writel(pts_control_value, &port->port_task_scheduler_registers->control); + writel(pts_control_value, &iport->port_task_scheduler_registers->control); } /** @@ -1630,22 +1622,22 @@ scic_sds_port_enable_port_task_scheduler(struct scic_sds_port *port) * none */ static void -scic_sds_port_disable_port_task_scheduler(struct scic_sds_port *port) +scic_sds_port_disable_port_task_scheduler(struct isci_port *iport) { u32 pts_control_value; - pts_control_value = readl(&port->port_task_scheduler_registers->control); + pts_control_value = readl(&iport->port_task_scheduler_registers->control); pts_control_value &= ~(SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND)); - writel(pts_control_value, &port->port_task_scheduler_registers->control); + writel(pts_control_value, &iport->port_task_scheduler_registers->control); } -static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) +static void scic_sds_port_post_dummy_remote_node(struct isci_port *iport) { - struct scic_sds_controller *scic = sci_port->owning_controller; - u8 phys_index = sci_port->physical_port_index; + struct scic_sds_controller *scic = iport->owning_controller; + u8 phys_index = iport->physical_port_index; union scu_remote_node_context *rnc; - u16 rni = sci_port->reserved_rni; + u16 rni = iport->reserved_rni; u32 command; rnc = &scic->remote_node_context_table[rni]; @@ -1670,67 +1662,65 @@ static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) static void scic_sds_port_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); + struct isci_port *iport = container_of(sm, typeof(*iport), sm); - if (sci_port->sm.previous_state_id == SCI_PORT_STOPPING) { + if (iport->sm.previous_state_id == SCI_PORT_STOPPING) { /* * If we enter this state becasuse of a request to stop * the port then we want to disable the hardwares port * task scheduler. */ - scic_sds_port_disable_port_task_scheduler(sci_port); + scic_sds_port_disable_port_task_scheduler(iport); } } static void scic_sds_port_stopped_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); + struct isci_port *iport = container_of(sm, typeof(*iport), sm); /* Enable and suspend the port task scheduler */ - scic_sds_port_enable_port_task_scheduler(sci_port); + scic_sds_port_enable_port_task_scheduler(iport); } static void scic_sds_port_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); - struct scic_sds_controller *scic = sci_port->owning_controller; + struct isci_port *iport = container_of(sm, typeof(*iport), sm); + struct scic_sds_controller *scic = iport->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); - struct isci_port *iport = sci_port_to_iport(sci_port); u32 prev_state; - prev_state = sci_port->sm.previous_state_id; + prev_state = iport->sm.previous_state_id; if (prev_state == SCI_PORT_RESETTING) isci_port_hard_reset_complete(iport, SCI_SUCCESS); else isci_port_not_ready(ihost, iport); /* Post and suspend the dummy remote node context for this port. */ - scic_sds_port_post_dummy_remote_node(sci_port); + scic_sds_port_post_dummy_remote_node(iport); /* Start the ready substate machine */ - port_state_machine_change(sci_port, + port_state_machine_change(iport, SCI_PORT_SUB_WAITING); } static void scic_sds_port_resetting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); + struct isci_port *iport = container_of(sm, typeof(*iport), sm); - sci_del_timer(&sci_port->timer); + sci_del_timer(&iport->timer); } static void scic_sds_port_stopping_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); + struct isci_port *iport = container_of(sm, typeof(*iport), sm); - sci_del_timer(&sci_port->timer); + sci_del_timer(&iport->timer); - scic_sds_port_destroy_dummy_resources(sci_port); + scic_sds_port_destroy_dummy_resources(iport); } static void scic_sds_port_failed_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_port *sci_port = container_of(sm, typeof(*sci_port), sm); - struct isci_port *iport = sci_port_to_iport(sci_port); + struct isci_port *iport = container_of(sm, typeof(*iport), sm); isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); } @@ -1767,30 +1757,30 @@ static const struct sci_base_state scic_sds_port_state_table[] = { } }; -void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, +void scic_sds_port_construct(struct isci_port *iport, u8 index, struct scic_sds_controller *scic) { - sci_init_sm(&sci_port->sm, scic_sds_port_state_table, SCI_PORT_STOPPED); + sci_init_sm(&iport->sm, scic_sds_port_state_table, SCI_PORT_STOPPED); - sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; - sci_port->physical_port_index = index; - sci_port->active_phy_mask = 0; - sci_port->ready_exit = false; + iport->logical_port_index = SCIC_SDS_DUMMY_PORT; + iport->physical_port_index = index; + iport->active_phy_mask = 0; + iport->ready_exit = false; - sci_port->owning_controller = scic; + iport->owning_controller = scic; - sci_port->started_request_count = 0; - sci_port->assigned_device_count = 0; + iport->started_request_count = 0; + iport->assigned_device_count = 0; - sci_port->reserved_rni = SCU_DUMMY_INDEX; - sci_port->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; + iport->reserved_rni = SCU_DUMMY_INDEX; + iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; - sci_init_timer(&sci_port->timer, port_timeout); + sci_init_timer(&iport->timer, port_timeout); - sci_port->port_task_scheduler_registers = NULL; + iport->port_task_scheduler_registers = NULL; for (index = 0; index < SCI_MAX_PHYS; index++) - sci_port->phy_table[index] = NULL; + iport->phy_table[index] = NULL; } void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index) @@ -1817,14 +1807,14 @@ enum isci_status isci_port_get_state( } void scic_sds_port_broadcast_change_received( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy) { - struct scic_sds_controller *scic = sci_port->owning_controller; + struct scic_sds_controller *scic = iport->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); /* notify the user. */ - isci_port_bc_change_received(ihost, sci_port, iphy); + isci_port_bc_change_received(ihost, iport, iphy); } int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, @@ -1842,7 +1832,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor spin_lock_irqsave(&ihost->scic_lock, flags); #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT - status = scic_port_hard_reset(&iport->sci, ISCI_PORT_RESET_TIMEOUT); + status = scic_port_hard_reset(iport, ISCI_PORT_RESET_TIMEOUT); spin_unlock_irqrestore(&ihost->scic_lock, flags); @@ -1878,14 +1868,12 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor /* Down all phys in the port. */ spin_lock_irqsave(&ihost->scic_lock, flags); for (idx = 0; idx < SCI_MAX_PHYS; ++idx) { + struct isci_phy *iphy = iport->phy_table[idx]; - if (iport->sci.phy_table[idx] != NULL) { - - scic_sds_phy_stop( - iport->sci.phy_table[idx]); - scic_sds_phy_start( - iport->sci.phy_table[idx]); - } + if (!iphy) + continue; + scic_sds_phy_stop(iphy); + scic_sds_phy_start(iphy); } spin_unlock_irqrestore(&ihost->scic_lock, flags); } diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index b6ce56a6c11d..cdea48ece005 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -76,100 +76,19 @@ enum isci_status { }; /** - * struct scic_sds_port - * - * The core port object provides the the abstraction for an SCU port. - */ -struct scic_sds_port { - /** - * This field contains the information for the base port state machine. - */ - struct sci_base_state_machine sm; - - bool ready_exit; - - /** - * This field is the port index that is reported to the SCI USER. - * This allows the actual hardware physical port to change without - * the SCI USER getting a different answer for the get port index. - */ - u8 logical_port_index; - - /** - * This field is the port index used to program the SCU hardware. - */ - u8 physical_port_index; - - /** - * This field contains the active phy mask for the port. - * This mask is used in conjunction with the phy state to determine - * which phy to select for some port operations. - */ - u8 active_phy_mask; - - u16 reserved_rni; - u16 reserved_tag; - - /** - * This field contains the count of the io requests started on this port - * object. It is used to control controller shutdown. - */ - u32 started_request_count; - - /** - * This field contains the number of devices assigned to this port. - * It is used to control port start requests. - */ - u32 assigned_device_count; - - /** - * This field contains the reason for the port not going ready. It is - * assigned in the state handlers and used in the state transition. - */ - u32 not_ready_reason; - - /** - * This field is the table of phys assigned to the port. - */ - struct isci_phy *phy_table[SCI_MAX_PHYS]; - - /** - * This field is a pointer back to the controller that owns this - * port object. - */ - struct scic_sds_controller *owning_controller; - - /* timer used for port start/stop operations */ - struct sci_timer timer; - - /** - * This field is the pointer to the port task scheduler registers - * for the SCU hardware. - */ - struct scu_port_task_scheduler_registers __iomem - *port_task_scheduler_registers; - - /** - * This field is identical for all port objects and points to the port - * task scheduler group PE configuration registers. - * It is used to assign PEs to a port. - */ - u32 __iomem *port_pe_configuration_register; - - /** - * This field is the VIIT register space for ths port object. - */ - struct scu_viit_entry __iomem *viit_registers; -}; - - - -/** - * struct isci_port - This class represents the port object used to internally - * represent libsas port objects. It also keeps a list of remote device - * objects. - * - * + * struct isci_port - isci direct attached sas port object + * @event: counts bcns and port stop events (for bcn filtering) + * @ready_exit: several states constitute 'ready'. When exiting ready we + * need to take extra port-teardown actions that are + * skipped when exiting to another 'ready' state. + * @logical_port_index: software port index + * @physical_port_index: hardware port index + * @active_phy_mask: identifies phy members + * @reserved_tag: + * @reserved_rni: reserver for port task scheduler workaround + * @started_request_count: reference count for outstanding commands + * @not_ready_reason: set during state transitions and notified + * @timer: timeout start/stop operations */ struct isci_port { enum isci_status status; @@ -185,16 +104,25 @@ struct isci_port { struct completion start_complete; struct completion hard_reset_complete; enum sci_status hard_reset_status; - struct scic_sds_port sci; + struct sci_base_state_machine sm; + bool ready_exit; + u8 logical_port_index; + u8 physical_port_index; + u8 active_phy_mask; + u16 reserved_rni; + u16 reserved_tag; + u32 started_request_count; + u32 assigned_device_count; + u32 not_ready_reason; + struct isci_phy *phy_table[SCI_MAX_PHYS]; + struct scic_sds_controller *owning_controller; + struct sci_timer timer; + struct scu_port_task_scheduler_registers __iomem *port_task_scheduler_registers; + /* XXX rework: only one register, no need to replicate per-port */ + u32 __iomem *port_pe_configuration_register; + struct scu_viit_entry __iomem *viit_registers; }; -static inline struct isci_port *sci_port_to_iport(struct scic_sds_port *sci_port) -{ - struct isci_port *iport = container_of(sci_port, typeof(*iport), sci); - - return iport; -} - enum scic_port_not_ready_reason_code { SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, @@ -299,90 +227,90 @@ enum scic_sds_port_states { ((this_port)->physical_port_index) -static inline void scic_sds_port_decrement_request_count(struct scic_sds_port *sci_port) +static inline void scic_sds_port_decrement_request_count(struct isci_port *iport) { - if (WARN_ONCE(sci_port->started_request_count == 0, + if (WARN_ONCE(iport->started_request_count == 0, "%s: tried to decrement started_request_count past 0!?", __func__)) /* pass */; else - sci_port->started_request_count--; + iport->started_request_count--; } #define scic_sds_port_active_phy(port, phy) \ (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) void scic_sds_port_construct( - struct scic_sds_port *sci_port, + struct isci_port *iport, u8 port_index, struct scic_sds_controller *scic); enum sci_status scic_sds_port_initialize( - struct scic_sds_port *sci_port, + struct isci_port *iport, void __iomem *port_task_scheduler_registers, void __iomem *port_configuration_regsiter, void __iomem *viit_registers); -enum sci_status scic_sds_port_start(struct scic_sds_port *sci_port); -enum sci_status scic_sds_port_stop(struct scic_sds_port *sci_port); +enum sci_status scic_sds_port_start(struct isci_port *iport); +enum sci_status scic_sds_port_stop(struct isci_port *iport); enum sci_status scic_sds_port_add_phy( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy); enum sci_status scic_sds_port_remove_phy( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy); void scic_sds_port_setup_transports( - struct scic_sds_port *sci_port, + struct isci_port *iport, u32 device_id); void isci_port_bcn_enable(struct isci_host *, struct isci_port *); void scic_sds_port_deactivate_phy( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user); bool scic_sds_port_link_detected( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy); -enum sci_status scic_sds_port_link_up(struct scic_sds_port *sci_port, +enum sci_status scic_sds_port_link_up(struct isci_port *iport, struct isci_phy *iphy); -enum sci_status scic_sds_port_link_down(struct scic_sds_port *sci_port, +enum sci_status scic_sds_port_link_down(struct isci_port *iport, struct isci_phy *iphy); struct isci_request; struct scic_sds_remote_device; enum sci_status scic_sds_port_start_io( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct scic_sds_remote_device *sci_dev, struct isci_request *ireq); enum sci_status scic_sds_port_complete_io( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct scic_sds_remote_device *sci_dev, struct isci_request *ireq); enum sas_linkrate scic_sds_port_get_max_allowed_speed( - struct scic_sds_port *sci_port); + struct isci_port *iport); void scic_sds_port_broadcast_change_received( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy); bool scic_sds_port_is_valid_phy_assignment( - struct scic_sds_port *sci_port, + struct isci_port *iport, u32 phy_index); void scic_sds_port_get_sas_address( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct sci_sas_address *sas_address); void scic_sds_port_get_attached_sas_address( - struct scic_sds_port *sci_port, + struct isci_port *iport, struct sci_sas_address *sas_address); enum isci_status isci_port_get_state( diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index 8444fd8219dd..bb62d2a25217 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -112,7 +112,7 @@ static s32 sci_sas_address_compare( * port. port address if the port can be found to match the phy. * NULL if there is no matching port for the phy. */ -static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( +static struct isci_port *scic_sds_port_configuration_agent_find_port( struct scic_sds_controller *scic, struct isci_phy *iphy) { @@ -132,14 +132,14 @@ static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( for (i = 0; i < scic->logical_port_entries; i++) { struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_port *sci_port = &ihost->ports[i].sci; + struct isci_port *iport = &ihost->ports[i]; - scic_sds_port_get_sas_address(sci_port, &port_sas_address); - scic_sds_port_get_attached_sas_address(sci_port, &port_attached_device_address); + scic_sds_port_get_sas_address(iport, &port_sas_address); + scic_sds_port_get_attached_sas_address(iport, &port_attached_device_address); if (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0 && sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) - return sci_port; + return iport; } return NULL; @@ -315,7 +315,7 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - scic_sds_port_add_phy(&ihost->ports[port_index].sci, + scic_sds_port_add_phy(&ihost->ports[port_index], &ihost->phys[phy_index]); assigned_phy_mask |= (1 << phy_index); @@ -367,22 +367,20 @@ done: static void scic_sds_mpc_agent_link_up(struct scic_sds_controller *controller, struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *port, + struct isci_port *iport, struct isci_phy *iphy) { - /* If the port has an invalid handle then the phy was not assigned to - * a port. This is because the phy was not given the same SAS Address - * as the other PHYs in the port. + /* If the port is NULL then the phy was not assigned to a port. + * This is because the phy was not given the same SAS Address as + * the other PHYs in the port. */ - if (port != NULL) { - port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(iphy)); - - scic_sds_port_link_up(port, iphy); + if (!iport) + return; - if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(iphy))) != 0) { - port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(iphy)); - } - } + port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(iphy)); + scic_sds_port_link_up(iport, iphy); + if ((iport->active_phy_mask & (1 << scic_sds_phy_get_index(iphy)))) + port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(iphy)); } /** @@ -405,10 +403,10 @@ static void scic_sds_mpc_agent_link_up(struct scic_sds_controller *controller, static void scic_sds_mpc_agent_link_down( struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy) { - if (sci_port != NULL) { + if (iport != NULL) { /* * If we can form a new port from the remainder of the phys * then we want to start the timer to allow the SCI User to @@ -436,7 +434,7 @@ static void scic_sds_mpc_agent_link_down( SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT); } - scic_sds_port_link_down(sci_port, iphy); + scic_sds_port_link_down(iport, iphy); } } @@ -496,14 +494,14 @@ static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *contr { u8 port_index; enum sci_status status; - struct scic_sds_port *port; + struct isci_port *iport; enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; struct isci_host *ihost = scic_to_ihost(controller); - port = scic_sds_port_configuration_agent_find_port(controller, iphy); + iport = scic_sds_port_configuration_agent_find_port(controller, iphy); - if (port != NULL) { - if (scic_sds_port_is_valid_phy_assignment(port, iphy->phy_index)) + if (iport) { + if (scic_sds_port_is_valid_phy_assignment(iport, iphy->phy_index)) apc_activity = SCIC_SDS_APC_ADD_PHY; else apc_activity = SCIC_SDS_APC_SKIP_PHY; @@ -514,21 +512,19 @@ static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *contr * the timer and wait to see if a wider port can be made. * * Note the break when we reach the condition of the port id == phy id */ - for ( - port_index = port_agent->phy_valid_port_range[iphy->phy_index].min_index; - port_index <= port_agent->phy_valid_port_range[iphy->phy_index].max_index; - port_index++ - ) { + for (port_index = port_agent->phy_valid_port_range[iphy->phy_index].min_index; + port_index <= port_agent->phy_valid_port_range[iphy->phy_index].max_index; + port_index++) { - port = &ihost->ports[port_index].sci; + iport = &ihost->ports[port_index]; /* First we must make sure that this PHY can be added to this Port. */ - if (scic_sds_port_is_valid_phy_assignment(port, iphy->phy_index)) { + if (scic_sds_port_is_valid_phy_assignment(iport, iphy->phy_index)) { /* * Port contains a PHY with a greater PHY ID than the current * PHY that has gone link up. This phy can not be part of any * port so skip it and move on. */ - if (port->active_phy_mask > (1 << iphy->phy_index)) { + if (iport->active_phy_mask > (1 << iphy->phy_index)) { apc_activity = SCIC_SDS_APC_SKIP_PHY; break; } @@ -537,7 +533,7 @@ static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *contr * We have reached the end of our Port list and have not found * any reason why we should not either add the PHY to the port * or wait for more phys to become active. */ - if (port->physical_port_index == iphy->phy_index) { + if (iport->physical_port_index == iphy->phy_index) { /* * The Port either has no active PHYs. * Consider that if the port had any active PHYs we would have @@ -554,10 +550,10 @@ static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *contr * The current Port has no active PHYs and this PHY could be part * of this Port. Since we dont know as yet setup to start the * timer and see if there is a better configuration. */ - if (port->active_phy_mask == 0) { + if (iport->active_phy_mask == 0) { apc_activity = SCIC_SDS_APC_START_TIMER; } - } else if (port->active_phy_mask != 0) { + } else if (iport->active_phy_mask != 0) { /* * The Port has an active phy and the current Phy can not * participate in this port so skip the PHY and see if @@ -583,7 +579,7 @@ static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *contr switch (apc_activity) { case SCIC_SDS_APC_ADD_PHY: - status = scic_sds_port_add_phy(port, iphy); + status = scic_sds_port_add_phy(iport, iphy); if (status == SCI_SUCCESS) { port_agent->phy_configured_mask |= (1 << iphy->phy_index); @@ -625,18 +621,18 @@ static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *contr */ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *sci_port, + struct isci_port *iport, struct isci_phy *iphy) { u8 phy_index = iphy->phy_index; - if (!sci_port) { + if (!iport) { /* the phy is not the part of this port */ port_agent->phy_ready_mask |= 1 << phy_index; scic_sds_apc_agent_configure_ports(scic, port_agent, iphy, true); } else { /* the phy is already the part of the port */ - u32 port_state = sci_port->sm.current_state_id; + u32 port_state = iport->sm.current_state_id; /* if the PORT'S state is resetting then the link up is from * port hard reset in this case, we need to tell the port @@ -644,7 +640,7 @@ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, */ BUG_ON(port_state != SCI_PORT_RESETTING); port_agent->phy_ready_mask |= 1 << phy_index; - scic_sds_port_link_up(sci_port, iphy); + scic_sds_port_link_up(iport, iphy); } } @@ -652,9 +648,9 @@ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, * * @controller: This is the controller object that receives the link down * notification. - * @port: This is the port object associated with the phy. If the is no + * @iport: This is the port object associated with the phy. If the is no * associated port this is an NULL. - * @phy: This is the phy object which has gone link down. + * @iphy: This is the phy object which has gone link down. * * This method handles the automatic port configuration link down * notifications. not associated with a port there is no action taken. Is it @@ -664,21 +660,20 @@ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, static void scic_sds_apc_agent_link_down( struct scic_sds_controller *controller, struct scic_sds_port_configuration_agent *port_agent, - struct scic_sds_port *port, + struct isci_port *iport, struct isci_phy *iphy) { port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(iphy)); - if (port != NULL) { - if (port_agent->phy_configured_mask & (1 << iphy->phy_index)) { - enum sci_status status; + if (!iport) + return; + if (port_agent->phy_configured_mask & (1 << iphy->phy_index)) { + enum sci_status status; - status = scic_sds_port_remove_phy(port, iphy); + status = scic_sds_port_remove_phy(iport, iphy); - if (status == SCI_SUCCESS) { - port_agent->phy_configured_mask &= ~(1 << iphy->phy_index); - } - } + if (status == SCI_SUCCESS) + port_agent->phy_configured_mask &= ~(1 << iphy->phy_index); } } diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 71ab9081fe24..627cf731bad8 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -450,11 +450,11 @@ static void scic_sds_remote_device_start_request(struct scic_sds_remote_device * struct isci_request *ireq, enum sci_status status) { - struct scic_sds_port *sci_port = sci_dev->owning_port; + struct isci_port *iport = sci_dev->owning_port; /* cleanup requests that failed after starting on the port */ if (status != SCI_SUCCESS) - scic_sds_port_complete_io(sci_port, sci_dev, ireq); + scic_sds_port_complete_io(iport, sci_dev, ireq); else { kref_get(&sci_dev_to_idev(sci_dev)->kref); scic_sds_remote_device_increment_request_count(sci_dev); @@ -467,7 +467,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic { struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct scic_sds_port *sci_port = sci_dev->owning_port; + struct isci_port *iport = sci_dev->owning_port; enum sci_status status; switch (state) { @@ -489,7 +489,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic * successful it will start the request for the port object then * increment its own request count. */ - status = scic_sds_port_start_io(sci_port, sci_dev, ireq); + status = scic_sds_port_start_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) return status; @@ -511,7 +511,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic enum scic_sds_remote_device_states new_state; struct sas_task *task = isci_request_access_task(ireq); - status = scic_sds_port_start_io(sci_port, sci_dev, ireq); + status = scic_sds_port_start_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) return status; @@ -536,7 +536,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic struct sas_task *task = isci_request_access_task(ireq); if (task->ata_task.use_ncq) { - status = scic_sds_port_start_io(sci_port, sci_dev, ireq); + status = scic_sds_port_start_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) return status; @@ -552,7 +552,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic case SCI_STP_DEV_AWAIT_RESET: return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; case SCI_SMP_DEV_IDLE: - status = scic_sds_port_start_io(sci_port, sci_dev, ireq); + status = scic_sds_port_start_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) return status; @@ -579,7 +579,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic return status; } -static enum sci_status common_complete_io(struct scic_sds_port *sci_port, +static enum sci_status common_complete_io(struct isci_port *iport, struct scic_sds_remote_device *sci_dev, struct isci_request *ireq) { @@ -589,7 +589,7 @@ static enum sci_status common_complete_io(struct scic_sds_port *sci_port, if (status != SCI_SUCCESS) return status; - status = scic_sds_port_complete_io(sci_port, sci_dev, ireq); + status = scic_sds_port_complete_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) return status; @@ -603,7 +603,7 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s { struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct scic_sds_port *sci_port = sci_dev->owning_port; + struct isci_port *iport = sci_dev->owning_port; enum sci_status status; switch (state) { @@ -621,12 +621,12 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s case SCI_DEV_READY: case SCI_STP_DEV_AWAIT_RESET: case SCI_DEV_RESETTING: - status = common_complete_io(sci_port, sci_dev, ireq); + status = common_complete_io(iport, sci_dev, ireq); break; case SCI_STP_DEV_CMD: case SCI_STP_DEV_NCQ: case SCI_STP_DEV_NCQ_ERROR: - status = common_complete_io(sci_port, sci_dev, ireq); + status = common_complete_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) break; @@ -641,13 +641,13 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s sci_change_state(sm, SCI_STP_DEV_IDLE); break; case SCI_SMP_DEV_CMD: - status = common_complete_io(sci_port, sci_dev, ireq); + status = common_complete_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) break; sci_change_state(sm, SCI_SMP_DEV_IDLE); break; case SCI_DEV_STOPPING: - status = common_complete_io(sci_port, sci_dev, ireq); + status = common_complete_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) break; @@ -661,7 +661,7 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s if (status != SCI_SUCCESS) dev_err(scirdev_to_dev(sci_dev), "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " - "could not complete\n", __func__, sci_port, + "could not complete\n", __func__, iport, sci_dev, ireq, status); else isci_put_device(sci_dev_to_idev(sci_dev)); @@ -684,7 +684,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc { struct sci_base_state_machine *sm = &sci_dev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct scic_sds_port *sci_port = sci_dev->owning_port; + struct isci_port *iport = sci_dev->owning_port; enum sci_status status; switch (state) { @@ -706,7 +706,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc case SCI_STP_DEV_NCQ: case SCI_STP_DEV_NCQ_ERROR: case SCI_STP_DEV_AWAIT_RESET: - status = scic_sds_port_start_io(sci_port, sci_dev, ireq); + status = scic_sds_port_start_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) return status; @@ -746,7 +746,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc */ return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; case SCI_DEV_READY: - status = scic_sds_port_start_io(sci_port, sci_dev, ireq); + status = scic_sds_port_start_io(iport, sci_dev, ireq); if (status != SCI_SUCCESS) return status; @@ -1064,10 +1064,10 @@ static const struct sci_base_state scic_sds_remote_device_state_table[] = { * scic_remote_device_[de]a_construct(). scic_remote_device_destruct() * frees the remote_node_context(s) for the device. */ -static void scic_remote_device_construct(struct scic_sds_port *sci_port, +static void scic_remote_device_construct(struct isci_port *iport, struct scic_sds_remote_device *sci_dev) { - sci_dev->owning_port = sci_port; + sci_dev->owning_port = iport; sci_dev->started_request_count = 0; sci_init_sm(&sci_dev->sm, scic_sds_remote_device_state_table, SCI_DEV_INITIAL); @@ -1090,20 +1090,20 @@ static void scic_remote_device_construct(struct scic_sds_port *sci_port, * sata-only controller instance. * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ -static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci_port, +static enum sci_status scic_remote_device_da_construct(struct isci_port *iport, struct scic_sds_remote_device *sci_dev) { enum sci_status status; struct domain_device *dev = sci_dev_to_domain(sci_dev); - scic_remote_device_construct(sci_port, sci_dev); + scic_remote_device_construct(iport, sci_dev); /* * This information is request to determine how many remote node context * entries will be needed to store the remote node. */ sci_dev->is_direct_attached = true; - status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller, + status = scic_sds_controller_allocate_remote_node_context(iport->owning_controller, sci_dev, &sci_dev->rnc.remote_node_index); @@ -1116,7 +1116,7 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci else return SCI_FAILURE_UNSUPPORTED_PROTOCOL; - sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(sci_port); + sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(iport); /* / @todo Should I assign the port width by reading all of the phys on the port? */ sci_dev->device_port_width = 1; @@ -1136,15 +1136,15 @@ static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci * sata-only controller instance. * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ -static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port, +static enum sci_status scic_remote_device_ea_construct(struct isci_port *iport, struct scic_sds_remote_device *sci_dev) { struct domain_device *dev = sci_dev_to_domain(sci_dev); enum sci_status status; - scic_remote_device_construct(sci_port, sci_dev); + scic_remote_device_construct(iport, sci_dev); - status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller, + status = scic_sds_controller_allocate_remote_node_context(iport->owning_controller, sci_dev, &sci_dev->rnc.remote_node_index); if (status != SCI_SUCCESS) @@ -1163,7 +1163,7 @@ static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci * connection the logical link rate is that same as the * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay * one another, so this code works for both situations. */ - sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(sci_port), + sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(iport), dev->linkrate); /* / @todo Should I assign the port width by reading all of the phys on the port? */ @@ -1212,15 +1212,14 @@ static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *s static enum sci_status isci_remote_device_construct(struct isci_port *iport, struct isci_remote_device *idev) { - struct scic_sds_port *sci_port = &iport->sci; struct isci_host *ihost = iport->isci_host; struct domain_device *dev = idev->domain_dev; enum sci_status status; if (dev->parent && dev_is_expander(dev->parent)) - status = scic_remote_device_ea_construct(sci_port, &idev->sci); + status = scic_remote_device_ea_construct(iport, &idev->sci); else - status = scic_remote_device_da_construct(sci_port, &idev->sci); + status = scic_remote_device_da_construct(iport, &idev->sci); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: construct failed: %d\n", diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 6ac5dfb7d1db..578d75b8cd16 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -100,7 +100,7 @@ struct scic_sds_remote_device { * This filed contains a pointer back to the port to which this device * is assigned. */ - struct scic_sds_port *owning_port; + struct isci_port *owning_port; /** * This field contains the SCU silicon remote node context specific @@ -387,14 +387,6 @@ static inline bool dev_is_expander(struct domain_device *dev) #define scic_sds_remote_device_get_request_count(sci_dev) \ ((sci_dev)->started_request_count) -/** - * scic_sds_remote_device_get_port() - - * - * This macro returns the owning port of this remote device obejct. - */ -#define scic_sds_remote_device_get_port(sci_dev) \ - ((sci_dev)->owning_port) - /** * scic_sds_remote_device_get_controller() - * diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c544bc79ce17..2d29abf3ce1f 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -210,10 +210,10 @@ static void scu_ssp_reqeust_construct_task_context( { dma_addr_t dma_addr; struct scic_sds_remote_device *target_device; - struct scic_sds_port *target_port; + struct isci_port *iport; target_device = scic_sds_request_get_device(ireq); - target_port = scic_sds_request_get_port(ireq); + iport = scic_sds_request_get_port(ireq); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -222,8 +222,7 @@ static void scu_ssp_reqeust_construct_task_context( task_context->connection_rate = target_device->connection_rate; task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(controller); - task_context->logical_port_index = - scic_sds_port_get_index(target_port); + task_context->logical_port_index = scic_sds_port_get_index(iport); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; @@ -245,11 +244,11 @@ static void scu_ssp_reqeust_construct_task_context( task_context->task_phase = 0x01; ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(ireq->io_tag)); + (scic_sds_controller_get_protocol_engine_group(controller) << + SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (scic_sds_port_get_index(iport) << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + ISCI_TAG_TCI(ireq->io_tag)); /* * Copy the physical address for the command buffer to the @@ -350,10 +349,10 @@ static void scu_sata_reqeust_construct_task_context( { dma_addr_t dma_addr; struct scic_sds_remote_device *target_device; - struct scic_sds_port *target_port; + struct isci_port *iport; target_device = scic_sds_request_get_device(ireq); - target_port = scic_sds_request_get_port(ireq); + iport = scic_sds_request_get_port(ireq); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -363,7 +362,7 @@ static void scu_sata_reqeust_construct_task_context( task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = - scic_sds_port_get_index(target_port); + scic_sds_port_get_index(iport); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; @@ -391,7 +390,7 @@ static void scu_sata_reqeust_construct_task_context( ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | (scic_sds_controller_get_protocol_engine_group(controller) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(target_port) << + (scic_sds_port_get_index(iport) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | ISCI_TAG_TCI(ireq->io_tag)); /* @@ -3105,7 +3104,7 @@ scic_io_request_construct_smp(struct device *dev, struct scatterlist *sg = &task->smp_task.smp_req; struct scic_sds_remote_device *sci_dev; struct scu_task_context *task_context; - struct scic_sds_port *sci_port; + struct isci_port *iport; struct smp_req *smp_req; void *kaddr; u8 req_len; @@ -3149,7 +3148,7 @@ scic_io_request_construct_smp(struct device *dev, task_context = ireq->tc; sci_dev = scic_sds_request_get_device(ireq); - sci_port = scic_sds_request_get_port(ireq); + iport = scic_sds_request_get_port(ireq); /* * Fill in the TC with the its required data @@ -3160,7 +3159,7 @@ scic_io_request_construct_smp(struct device *dev, task_context->connection_rate = sci_dev->connection_rate; task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(scic); - task_context->logical_port_index = scic_sds_port_get_index(sci_port); + task_context->logical_port_index = scic_sds_port_get_index(iport); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; task_context->abort = 0; task_context->valid = SCU_TASK_CONTEXT_VALID; @@ -3204,7 +3203,7 @@ scic_io_request_construct_smp(struct device *dev, ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | (scic_sds_controller_get_protocol_engine_group(scic) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(sci_port) << + (scic_sds_port_get_index(iport) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | ISCI_TAG_TCI(ireq->io_tag)); /* -- cgit v1.2.3 From 78a6f06e0e82125787d7aa308fe28c2c8381540c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 30 Jun 2011 16:31:37 -0700 Subject: isci: unify isci_remote_device and scic_sds_remote_device Remove the distinction between these two implementations and unify on isci_remote_device (local instances named idev). Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 60 ++--- drivers/scsi/isci/host.h | 27 +-- drivers/scsi/isci/port.c | 4 +- drivers/scsi/isci/port.h | 6 +- drivers/scsi/isci/remote_device.c | 396 ++++++++++++++++---------------- drivers/scsi/isci/remote_device.h | 148 ++++-------- drivers/scsi/isci/remote_node_context.c | 48 ++-- drivers/scsi/isci/remote_node_context.h | 2 +- drivers/scsi/isci/request.c | 60 +++-- drivers/scsi/isci/request.h | 4 +- drivers/scsi/isci/task.c | 47 ++-- 11 files changed, 365 insertions(+), 437 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 4e11f9e6d766..45d7f71c609a 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -272,7 +272,7 @@ static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic { u32 index; struct isci_request *ireq; - struct scic_sds_remote_device *device; + struct isci_remote_device *idev; index = SCU_GET_COMPLETION_INDEX(completion_entry); @@ -289,9 +289,9 @@ static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: - device = scic->device_table[index]; + idev = scic->device_table[index]; dev_warn(scic_to_dev(scic), "%s: %x for device %p\n", - __func__, completion_entry, device); + __func__, completion_entry, idev); /* @todo For a port RNC operation we need to fail the * device */ @@ -312,7 +312,7 @@ static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *sc struct isci_host *ihost = scic_to_ihost(scic); struct scu_unsolicited_frame_header *frame_header; struct isci_phy *iphy; - struct scic_sds_remote_device *device; + struct isci_remote_device *idev; enum sci_status result = SCI_FAILURE; @@ -348,12 +348,12 @@ static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *sc result = scic_sds_phy_frame_handler(iphy, frame_index); } else { if (index < scic->remote_node_entries) - device = scic->device_table[index]; + idev = scic->device_table[index]; else - device = NULL; + idev = NULL; - if (device != NULL) - result = scic_sds_remote_device_frame_handler(device, frame_index); + if (idev != NULL) + result = scic_sds_remote_device_frame_handler(idev, frame_index); else scic_sds_controller_release_frame(scic, frame_index); } @@ -370,7 +370,7 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci u32 completion_entry) { struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_remote_device *device; + struct isci_remote_device *idev; struct isci_request *ireq; struct isci_phy *iphy; u32 index; @@ -426,9 +426,9 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci break; case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: - device = scic->device_table[index]; - if (device != NULL) - scic_sds_remote_device_event_handler(device, completion_entry); + idev = scic->device_table[index]; + if (idev != NULL) + scic_sds_remote_device_event_handler(idev, completion_entry); else dev_warn(scic_to_dev(scic), "%s: SCIC Controller 0x%p received " @@ -460,10 +460,10 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: case SCU_EVENT_TYPE_RNC_OPS_MISC: if (index < scic->remote_node_entries) { - device = scic->device_table[index]; + idev = scic->device_table[index]; - if (device != NULL) - scic_sds_remote_device_event_handler(device, completion_entry); + if (idev != NULL) + scic_sds_remote_device_event_handler(idev, completion_entry); } else dev_err(scic_to_dev(scic), "%s: SCIC Controller 0x%p received event 0x%x " @@ -2549,13 +2549,13 @@ static bool scic_sds_controller_has_remote_devices_stopping( * object that the remote device has stopped. */ void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev) + struct isci_remote_device *idev) { if (scic->sm.current_state_id != SCIC_STOPPING) { dev_dbg(scic_to_dev(scic), "SCIC Controller 0x%p remote device stopped event " "from device 0x%p in unexpected state %d\n", - scic, sci_dev, + scic, idev, scic->sm.current_state_id); return; } @@ -2622,18 +2622,18 @@ struct isci_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 i */ enum sci_status scic_sds_controller_allocate_remote_node_context( struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u16 *node_id) { u16 node_index; - u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev); + u32 remote_node_count = scic_sds_remote_device_node_count(idev); node_index = scic_sds_remote_node_table_allocate_remote_node( &scic->available_remote_nodes, remote_node_count ); if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - scic->device_table[node_index] = sci_dev; + scic->device_table[node_index] = idev; *node_id = node_index; @@ -2654,12 +2654,12 @@ enum sci_status scic_sds_controller_allocate_remote_node_context( */ void scic_sds_controller_free_remote_node_context( struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u16 node_id) { - u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev); + u32 remote_node_count = scic_sds_remote_device_node_count(idev); - if (scic->device_table[node_id] == sci_dev) { + if (scic->device_table[node_id] == idev) { scic->device_table[node_id] = NULL; scic_sds_remote_node_table_release_remote_node_index( @@ -2798,7 +2798,7 @@ enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag) * user desires to be utilized for this request. */ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, + struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; @@ -2808,7 +2808,7 @@ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, return SCI_FAILURE_INVALID_STATE; } - status = scic_sds_remote_device_start_io(scic, rdev, ireq); + status = scic_sds_remote_device_start_io(scic, idev, ireq); if (status != SCI_SUCCESS) return status; @@ -2835,7 +2835,7 @@ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, */ enum sci_status scic_controller_terminate_request( struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, + struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; @@ -2873,7 +2873,7 @@ enum sci_status scic_controller_terminate_request( */ enum sci_status scic_controller_complete_io( struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, + struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; @@ -2884,7 +2884,7 @@ enum sci_status scic_controller_complete_io( /* XXX: Implement this function */ return SCI_FAILURE; case SCIC_READY: - status = scic_sds_remote_device_complete_io(scic, rdev, ireq); + status = scic_sds_remote_device_complete_io(scic, idev, ireq); if (status != SCI_SUCCESS) return status; @@ -2923,7 +2923,7 @@ enum sci_status scic_controller_continue_io(struct isci_request *ireq) */ enum sci_task_status scic_controller_start_task( struct scic_sds_controller *scic, - struct scic_sds_remote_device *rdev, + struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; @@ -2936,7 +2936,7 @@ enum sci_task_status scic_controller_start_task( return SCI_TASK_FAILURE_INVALID_STATE; } - status = scic_sds_remote_device_start_task(scic, rdev, ireq); + status = scic_sds_remote_device_start_task(scic, idev, ireq); switch (status) { case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: set_bit(IREQ_ACTIVE, &ireq->flags); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index fb8048e5fce7..ca2e3b0ee0dd 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -163,7 +163,7 @@ struct scic_sds_controller { * objects that need to handle device completion notifications from the * hardware. The table is RNi based. */ - struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; + struct isci_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; /** * This field is the free RNi data structure @@ -488,12 +488,12 @@ static inline struct isci_host *scic_to_ihost(struct scic_sds_controller *scic) #define ISCI_TAG_TCI(tag) ((tag) & (SCI_MAX_IO_REQUESTS-1)) /* expander attached sata devices require 3 rnc slots */ -static inline int scic_sds_remote_device_node_count(struct scic_sds_remote_device *sci_dev) +static inline int scic_sds_remote_device_node_count(struct isci_remote_device *idev) { - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct domain_device *dev = idev->domain_dev; if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) && - !sci_dev->is_direct_attached) + !idev->is_direct_attached) return SCU_STP_REMOTE_NODE_COUNT; return SCU_SSP_REMOTE_NODE_COUNT; } @@ -541,11 +541,8 @@ static inline struct device *sciport_to_dev(struct isci_port *iport) return &iport->isci_host->pdev->dev; } -static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev) +static inline struct device *scirdev_to_dev(struct isci_remote_device *idev) { - struct isci_remote_device *idev = - container_of(sci_dev, typeof(*idev), sci); - if (!idev || !idev->isci_port || !idev->isci_port->isci_host) return NULL; @@ -589,11 +586,11 @@ void scic_sds_controller_copy_sata_response(void *response_buffer, void *frame_header, void *frame_buffer); enum sci_status scic_sds_controller_allocate_remote_node_context(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u16 *node_id); void scic_sds_controller_free_remote_node_context( struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u16 node_id); union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( struct scic_sds_controller *scic, @@ -622,7 +619,7 @@ void scic_sds_controller_link_down( void scic_sds_controller_remote_device_stopped( struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev); + struct isci_remote_device *idev); void scic_sds_controller_copy_task_context( struct scic_sds_controller *scic, @@ -662,22 +659,22 @@ void scic_controller_disable_interrupts( enum sci_status scic_controller_start_io( struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, + struct isci_remote_device *idev, struct isci_request *ireq); enum sci_task_status scic_controller_start_task( struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, + struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_controller_terminate_request( struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, + struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_controller_complete_io( struct scic_sds_controller *scic, - struct scic_sds_remote_device *remote_device, + struct isci_remote_device *idev, struct isci_request *ireq); void scic_sds_port_configuration_agent_construct( diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 04591882ee77..df37b1bf7d11 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1541,7 +1541,7 @@ enum sci_status scic_sds_port_link_down(struct isci_port *iport, } enum sci_status scic_sds_port_start_io(struct isci_port *iport, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq) { enum scic_sds_port_states state; @@ -1561,7 +1561,7 @@ enum sci_status scic_sds_port_start_io(struct isci_port *iport, } enum sci_status scic_sds_port_complete_io(struct isci_port *iport, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq) { enum scic_sds_port_states state; diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index cdea48ece005..b9bc89bf6519 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -283,15 +283,15 @@ enum sci_status scic_sds_port_link_down(struct isci_port *iport, struct isci_phy *iphy); struct isci_request; -struct scic_sds_remote_device; +struct isci_remote_device; enum sci_status scic_sds_port_start_io( struct isci_port *iport, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_sds_port_complete_io( struct isci_port *iport, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq); enum sas_linkrate scic_sds_port_get_max_allowed_speed( diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 627cf731bad8..3b0234049a3d 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -93,7 +93,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, __func__, idev, ireq); scic_controller_terminate_request(&ihost->sci, - &idev->sci, + idev, ireq); } /* Fall through into the default case... */ @@ -127,15 +127,15 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote */ static void rnc_destruct_done(void *_dev) { - struct scic_sds_remote_device *sci_dev = _dev; + struct isci_remote_device *idev = _dev; - BUG_ON(sci_dev->started_request_count != 0); - sci_change_state(&sci_dev->sm, SCI_DEV_STOPPED); + BUG_ON(idev->started_request_count != 0); + sci_change_state(&idev->sm, SCI_DEV_STOPPED); } -static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds_remote_device *sci_dev) +static enum sci_status scic_sds_remote_device_terminate_requests(struct isci_remote_device *idev) { - struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + struct scic_sds_controller *scic = idev->owning_port->owning_controller; struct isci_host *ihost = scic_to_ihost(scic); enum sci_status status = SCI_SUCCESS; u32 i; @@ -145,10 +145,10 @@ static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds enum sci_status s; if (!test_bit(IREQ_ACTIVE, &ireq->flags) || - ireq->target_device != sci_dev) + ireq->target_device != idev) continue; - s = scic_controller_terminate_request(scic, sci_dev, ireq); + s = scic_controller_terminate_request(scic, idev, ireq); if (s != SCI_SUCCESS) status = s; } @@ -156,10 +156,10 @@ static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds return status; } -enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev, +enum sci_status scic_remote_device_stop(struct isci_remote_device *idev, u32 timeout) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; switch (state) { @@ -167,16 +167,16 @@ enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev, case SCI_DEV_FAILED: case SCI_DEV_FINAL: default: - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; case SCI_DEV_STOPPED: return SCI_SUCCESS; case SCI_DEV_STARTING: /* device not started so there had better be no requests */ - BUG_ON(sci_dev->started_request_count != 0); - scic_sds_remote_node_context_destruct(&sci_dev->rnc, - rnc_destruct_done, sci_dev); + BUG_ON(idev->started_request_count != 0); + scic_sds_remote_node_context_destruct(&idev->rnc, + rnc_destruct_done, idev); /* Transition to the stopping state and wait for the * remote node to complete being posted and invalidated. */ @@ -191,28 +191,28 @@ enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev, case SCI_SMP_DEV_IDLE: case SCI_SMP_DEV_CMD: sci_change_state(sm, SCI_DEV_STOPPING); - if (sci_dev->started_request_count == 0) { - scic_sds_remote_node_context_destruct(&sci_dev->rnc, - rnc_destruct_done, sci_dev); + if (idev->started_request_count == 0) { + scic_sds_remote_node_context_destruct(&idev->rnc, + rnc_destruct_done, idev); return SCI_SUCCESS; } else - return scic_sds_remote_device_terminate_requests(sci_dev); + return scic_sds_remote_device_terminate_requests(idev); break; case SCI_DEV_STOPPING: /* All requests should have been terminated, but if there is an * attempt to stop a device already in the stopping state, then * try again to terminate. */ - return scic_sds_remote_device_terminate_requests(sci_dev); + return scic_sds_remote_device_terminate_requests(idev); case SCI_DEV_RESETTING: sci_change_state(sm, SCI_DEV_STOPPING); return SCI_SUCCESS; } } -enum sci_status scic_remote_device_reset(struct scic_sds_remote_device *sci_dev) +enum sci_status scic_remote_device_reset(struct isci_remote_device *idev) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; switch (state) { @@ -226,7 +226,7 @@ enum sci_status scic_remote_device_reset(struct scic_sds_remote_device *sci_dev) case SCI_DEV_RESETTING: case SCI_DEV_FINAL: default: - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; case SCI_DEV_READY: @@ -240,13 +240,13 @@ enum sci_status scic_remote_device_reset(struct scic_sds_remote_device *sci_dev) } } -enum sci_status scic_remote_device_reset_complete(struct scic_sds_remote_device *sci_dev) +enum sci_status scic_remote_device_reset_complete(struct isci_remote_device *idev) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; if (state != SCI_DEV_RESETTING) { - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } @@ -255,28 +255,28 @@ enum sci_status scic_remote_device_reset_complete(struct scic_sds_remote_device return SCI_SUCCESS; } -enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sci_dev, +enum sci_status scic_sds_remote_device_suspend(struct isci_remote_device *idev, u32 suspend_type) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; if (state != SCI_STP_DEV_CMD) { - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - return scic_sds_remote_node_context_suspend(&sci_dev->rnc, + return scic_sds_remote_node_context_suspend(&idev->rnc, suspend_type, NULL, NULL); } -enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_device *sci_dev, +enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device *idev, u32 frame_index) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + struct scic_sds_controller *scic = idev->owning_port->owning_controller; enum sci_status status; switch (state) { @@ -287,7 +287,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi case SCI_SMP_DEV_IDLE: case SCI_DEV_FINAL: default: - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); /* Return the frame back to the controller */ scic_sds_controller_release_frame(scic, frame_index); @@ -313,7 +313,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi sci_swab32_cpy(&hdr, frame_header, word_cnt); ireq = scic_request_by_tag(scic, be16_to_cpu(hdr.tag)); - if (ireq && ireq->target_device == sci_dev) { + if (ireq && ireq->target_device == idev) { /* The IO request is now in charge of releasing the frame */ status = scic_sds_io_request_frame_handler(ireq, frame_index); } else { @@ -335,7 +335,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi if (hdr->fis_type == FIS_SETDEVBITS && (hdr->status & ATA_ERR)) { - sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + idev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; /* TODO Check sactive and complete associated IO if any. */ sci_change_state(sm, SCI_STP_DEV_NCQ_ERROR); @@ -345,8 +345,8 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi * Some devices return D2H FIS when an NCQ error is detected. * Treat this like an SDB error FIS ready reason. */ - sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; - sci_change_state(&sci_dev->sm, SCI_STP_DEV_NCQ_ERROR); + idev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; + sci_change_state(&idev->sm, SCI_STP_DEV_NCQ_ERROR); } else status = SCI_FAILURE; @@ -359,17 +359,17 @@ enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_devi * in this state. All unsolicited frames are forwarded to the io request * object. */ - status = scic_sds_io_request_frame_handler(sci_dev->working_request, frame_index); + status = scic_sds_io_request_frame_handler(idev->working_request, frame_index); break; } return status; } -static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev) +static bool is_remote_device_ready(struct isci_remote_device *idev) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; switch (state) { @@ -387,10 +387,10 @@ static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev) } } -enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_device *sci_dev, +enum sci_status scic_sds_remote_device_event_handler(struct isci_remote_device *idev, u32 event_code) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; enum sci_status status; @@ -398,21 +398,21 @@ enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_devi case SCU_EVENT_TYPE_RNC_OPS_MISC: case SCU_EVENT_TYPE_RNC_SUSPEND_TX: case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - status = scic_sds_remote_node_context_event_handler(&sci_dev->rnc, event_code); + status = scic_sds_remote_node_context_event_handler(&idev->rnc, event_code); break; case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { status = SCI_SUCCESS; /* Suspend the associated RNC */ - scic_sds_remote_node_context_suspend(&sci_dev->rnc, + scic_sds_remote_node_context_suspend(&idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); - dev_dbg(scirdev_to_dev(sci_dev), + dev_dbg(scirdev_to_dev(idev), "%s: device: %p event code: %x: %s\n", - __func__, sci_dev, event_code, - is_remote_device_ready(sci_dev) + __func__, idev, event_code, + is_remote_device_ready(idev) ? "I_T_Nexus_Timeout event" : "I_T_Nexus_Timeout event in wrong state"); @@ -420,10 +420,10 @@ enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_devi } /* Else, fall through and treat as unhandled... */ default: - dev_dbg(scirdev_to_dev(sci_dev), + dev_dbg(scirdev_to_dev(idev), "%s: device: %p event code: %x: %s\n", - __func__, sci_dev, event_code, - is_remote_device_ready(sci_dev) + __func__, idev, event_code, + is_remote_device_ready(idev) ? "unexpected event" : "unexpected event in wrong state"); status = SCI_FAILURE_INVALID_STATE; @@ -440,34 +440,34 @@ enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_devi */ if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) - status = scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); + status = scic_sds_remote_node_context_resume(&idev->rnc, NULL, NULL); } return status; } -static void scic_sds_remote_device_start_request(struct scic_sds_remote_device *sci_dev, +static void scic_sds_remote_device_start_request(struct isci_remote_device *idev, struct isci_request *ireq, enum sci_status status) { - struct isci_port *iport = sci_dev->owning_port; + struct isci_port *iport = idev->owning_port; /* cleanup requests that failed after starting on the port */ if (status != SCI_SUCCESS) - scic_sds_port_complete_io(iport, sci_dev, ireq); + scic_sds_port_complete_io(iport, idev, ireq); else { - kref_get(&sci_dev_to_idev(sci_dev)->kref); - scic_sds_remote_device_increment_request_count(sci_dev); + kref_get(&idev->kref); + scic_sds_remote_device_increment_request_count(idev); } } enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct isci_port *iport = sci_dev->owning_port; + struct isci_port *iport = idev->owning_port; enum sci_status status; switch (state) { @@ -480,7 +480,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic case SCI_DEV_RESETTING: case SCI_DEV_FINAL: default: - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; case SCI_DEV_READY: @@ -489,11 +489,11 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic * successful it will start the request for the port object then * increment its own request count. */ - status = scic_sds_port_start_io(iport, sci_dev, ireq); + status = scic_sds_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, ireq); + status = scic_sds_remote_node_context_start_io(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; @@ -511,11 +511,11 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic enum scic_sds_remote_device_states new_state; struct sas_task *task = isci_request_access_task(ireq); - status = scic_sds_port_start_io(iport, sci_dev, ireq); + status = scic_sds_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, ireq); + status = scic_sds_remote_node_context_start_io(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; @@ -526,7 +526,7 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic if (task->ata_task.use_ncq) new_state = SCI_STP_DEV_NCQ; else { - sci_dev->working_request = ireq; + idev->working_request = ireq; new_state = SCI_STP_DEV_CMD; } sci_change_state(sm, new_state); @@ -536,11 +536,11 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic struct sas_task *task = isci_request_access_task(ireq); if (task->ata_task.use_ncq) { - status = scic_sds_port_start_io(iport, sci_dev, ireq); + status = scic_sds_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, ireq); + status = scic_sds_remote_node_context_start_io(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; @@ -552,11 +552,11 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic case SCI_STP_DEV_AWAIT_RESET: return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; case SCI_SMP_DEV_IDLE: - status = scic_sds_port_start_io(iport, sci_dev, ireq); + status = scic_sds_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, ireq); + status = scic_sds_remote_node_context_start_io(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; @@ -564,8 +564,8 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic if (status != SCI_SUCCESS) break; - sci_dev->working_request = ireq; - sci_change_state(&sci_dev->sm, SCI_SMP_DEV_CMD); + idev->working_request = ireq; + sci_change_state(&idev->sm, SCI_SMP_DEV_CMD); break; case SCI_STP_DEV_CMD: case SCI_SMP_DEV_CMD: @@ -575,12 +575,12 @@ enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic return SCI_FAILURE_INVALID_STATE; } - scic_sds_remote_device_start_request(sci_dev, ireq, status); + scic_sds_remote_device_start_request(idev, ireq, status); return status; } static enum sci_status common_complete_io(struct isci_port *iport, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; @@ -589,21 +589,21 @@ static enum sci_status common_complete_io(struct isci_port *iport, if (status != SCI_SUCCESS) return status; - status = scic_sds_port_complete_io(iport, sci_dev, ireq); + status = scic_sds_port_complete_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - scic_sds_remote_device_decrement_request_count(sci_dev); + scic_sds_remote_device_decrement_request_count(idev); return status; } enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct isci_port *iport = sci_dev->owning_port; + struct isci_port *iport = idev->owning_port; enum sci_status status; switch (state) { @@ -615,18 +615,18 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s case SCI_DEV_FAILED: case SCI_DEV_FINAL: default: - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; case SCI_DEV_READY: case SCI_STP_DEV_AWAIT_RESET: case SCI_DEV_RESETTING: - status = common_complete_io(iport, sci_dev, ireq); + status = common_complete_io(iport, idev, ireq); break; case SCI_STP_DEV_CMD: case SCI_STP_DEV_NCQ: case SCI_STP_DEV_NCQ_ERROR: - status = common_complete_io(iport, sci_dev, ireq); + status = common_complete_io(iport, idev, ireq); if (status != SCI_SUCCESS) break; @@ -637,54 +637,54 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ sci_change_state(sm, SCI_STP_DEV_AWAIT_RESET); - } else if (scic_sds_remote_device_get_request_count(sci_dev) == 0) + } else if (scic_sds_remote_device_get_request_count(idev) == 0) sci_change_state(sm, SCI_STP_DEV_IDLE); break; case SCI_SMP_DEV_CMD: - status = common_complete_io(iport, sci_dev, ireq); + status = common_complete_io(iport, idev, ireq); if (status != SCI_SUCCESS) break; sci_change_state(sm, SCI_SMP_DEV_IDLE); break; case SCI_DEV_STOPPING: - status = common_complete_io(iport, sci_dev, ireq); + status = common_complete_io(iport, idev, ireq); if (status != SCI_SUCCESS) break; - if (scic_sds_remote_device_get_request_count(sci_dev) == 0) - scic_sds_remote_node_context_destruct(&sci_dev->rnc, + if (scic_sds_remote_device_get_request_count(idev) == 0) + scic_sds_remote_node_context_destruct(&idev->rnc, rnc_destruct_done, - sci_dev); + idev); break; } if (status != SCI_SUCCESS) - dev_err(scirdev_to_dev(sci_dev), + dev_err(scirdev_to_dev(idev), "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " "could not complete\n", __func__, iport, - sci_dev, ireq, status); + idev, ireq, status); else - isci_put_device(sci_dev_to_idev(sci_dev)); + isci_put_device(idev); return status; } static void scic_sds_remote_device_continue_request(void *dev) { - struct scic_sds_remote_device *sci_dev = dev; + struct isci_remote_device *idev = dev; /* we need to check if this request is still valid to continue. */ - if (sci_dev->working_request) - scic_controller_continue_io(sci_dev->working_request); + if (idev->working_request) + scic_controller_continue_io(idev->working_request); } enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct isci_port *iport = sci_dev->owning_port; + struct isci_port *iport = idev->owning_port; enum sci_status status; switch (state) { @@ -698,7 +698,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc case SCI_DEV_RESETTING: case SCI_DEV_FINAL: default: - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; case SCI_STP_DEV_IDLE: @@ -706,11 +706,11 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc case SCI_STP_DEV_NCQ: case SCI_STP_DEV_NCQ_ERROR: case SCI_STP_DEV_AWAIT_RESET: - status = scic_sds_port_start_io(iport, sci_dev, ireq); + status = scic_sds_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, ireq); + status = scic_sds_remote_node_context_start_task(&idev->rnc, ireq); if (status != SCI_SUCCESS) goto out; @@ -722,7 +722,7 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc * replace the request that probably resulted in the task * management request. */ - sci_dev->working_request = ireq; + idev->working_request = ireq; sci_change_state(sm, SCI_STP_DEV_CMD); /* The remote node context must cleanup the TCi to NCQ mapping @@ -732,32 +732,32 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc * the correct action when the remote node context is suspended * and later resumed. */ - scic_sds_remote_node_context_suspend(&sci_dev->rnc, + scic_sds_remote_node_context_suspend(&idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); - scic_sds_remote_node_context_resume(&sci_dev->rnc, + scic_sds_remote_node_context_resume(&idev->rnc, scic_sds_remote_device_continue_request, - sci_dev); + idev); out: - scic_sds_remote_device_start_request(sci_dev, ireq, status); + scic_sds_remote_device_start_request(idev, ireq, status); /* We need to let the controller start request handler know that * it can't post TC yet. We will provide a callback function to * post TC when RNC gets resumed. */ return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; case SCI_DEV_READY: - status = scic_sds_port_start_io(iport, sci_dev, ireq); + status = scic_sds_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, ireq); + status = scic_sds_remote_node_context_start_task(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; status = scic_sds_request_start(ireq); break; } - scic_sds_remote_device_start_request(sci_dev, ireq, status); + scic_sds_remote_device_start_request(idev, ireq, status); return status; } @@ -771,15 +771,15 @@ enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *sc * request and then requests the controller to post the request. none */ void scic_sds_remote_device_post_request( - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u32 request) { u32 context; - context = scic_sds_remote_device_build_command_context(sci_dev, request); + context = scic_sds_remote_device_build_command_context(idev, request); scic_sds_controller_post_request( - scic_sds_remote_device_get_controller(sci_dev), + scic_sds_remote_device_get_controller(idev), context ); } @@ -790,34 +790,33 @@ void scic_sds_remote_device_post_request( */ static void remote_device_resume_done(void *_dev) { - struct scic_sds_remote_device *sci_dev = _dev; + struct isci_remote_device *idev = _dev; - if (is_remote_device_ready(sci_dev)) + if (is_remote_device_ready(idev)) return; /* go 'ready' if we are not already in a ready state */ - sci_change_state(&sci_dev->sm, SCI_DEV_READY); + sci_change_state(&idev->sm, SCI_DEV_READY); } static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) { - struct scic_sds_remote_device *sci_dev = _dev; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); - struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; + struct isci_remote_device *idev = _dev; + struct scic_sds_controller *scic = idev->owning_port->owning_controller; /* For NCQ operation we do not issue a isci_remote_device_not_ready(). * As a result, avoid sending the ready notification. */ - if (sci_dev->sm.previous_state_id != SCI_STP_DEV_NCQ) + if (idev->sm.previous_state_id != SCI_STP_DEV_NCQ) isci_remote_device_ready(scic_to_ihost(scic), idev); } static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); /* Initial state is a transitional state to the stopped state */ - sci_change_state(&sci_dev->sm, SCI_DEV_STOPPED); + sci_change_state(&idev->sm, SCI_DEV_STOPPED); } /** @@ -833,22 +832,22 @@ static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_mac * device isn't valid (e.g. it's already been destoryed, the handle isn't * valid, etc.). */ -static enum sci_status scic_remote_device_destruct(struct scic_sds_remote_device *sci_dev) +static enum sci_status scic_remote_device_destruct(struct isci_remote_device *idev) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; struct scic_sds_controller *scic; if (state != SCI_DEV_STOPPED) { - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - scic = sci_dev->owning_port->owning_controller; - scic_sds_controller_free_remote_node_context(scic, sci_dev, - sci_dev->rnc.remote_node_index); - sci_dev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; + scic = idev->owning_port->owning_controller; + scic_sds_controller_free_remote_node_context(scic, idev, + idev->rnc.remote_node_index); + idev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; sci_change_state(sm, SCI_DEV_FINAL); return SCI_SUCCESS; @@ -871,34 +870,32 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ * io requests in process */ BUG_ON(!list_empty(&idev->reqs_in_process)); - scic_remote_device_destruct(&idev->sci); + scic_remote_device_destruct(idev); list_del_init(&idev->node); isci_put_device(idev); } static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); - struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); + struct scic_sds_controller *scic = idev->owning_port->owning_controller; u32 prev_state; /* If we are entering from the stopping state let the SCI User know that * the stop operation has completed. */ - prev_state = sci_dev->sm.previous_state_id; + prev_state = idev->sm.previous_state_id; if (prev_state == SCI_DEV_STOPPING) isci_remote_device_deconstruct(scic_to_ihost(scic), idev); - scic_sds_controller_remote_device_stopped(scic, sci_dev); + scic_sds_controller_remote_device_stopped(scic, idev); } static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); struct isci_host *ihost = scic_to_ihost(scic); - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); @@ -906,27 +903,25 @@ static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_ma static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); - struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); + struct scic_sds_controller *scic = idev->owning_port->owning_controller; struct domain_device *dev = idev->domain_dev; if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { - sci_change_state(&sci_dev->sm, SCI_STP_DEV_IDLE); + sci_change_state(&idev->sm, SCI_STP_DEV_IDLE); } else if (dev_is_expander(dev)) { - sci_change_state(&sci_dev->sm, SCI_SMP_DEV_IDLE); + sci_change_state(&idev->sm, SCI_SMP_DEV_IDLE); } else isci_remote_device_ready(scic_to_ihost(scic), idev); } static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); + struct domain_device *dev = idev->domain_dev; if (dev->dev_type == SAS_END_DEV) { - struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); + struct scic_sds_controller *scic = idev->owning_port->owning_controller; isci_remote_device_not_ready(scic_to_ihost(scic), idev, SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); @@ -935,82 +930,81 @@ static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machin static void scic_sds_remote_device_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); scic_sds_remote_node_context_suspend( - &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); + &idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); } static void scic_sds_remote_device_resetting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL); + scic_sds_remote_node_context_resume(&idev->rnc, NULL, NULL); } static void scic_sds_stp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - sci_dev->working_request = NULL; - if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { + idev->working_request = NULL; + if (scic_sds_remote_node_context_is_ready(&idev->rnc)) { /* * Since the RNC is ready, it's alright to finish completion * processing (e.g. signal the remote device is ready). */ - scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(sci_dev); + scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(idev); } else { - scic_sds_remote_node_context_resume(&sci_dev->rnc, + scic_sds_remote_node_context_resume(&idev->rnc, scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, - sci_dev); + idev); } } static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); - BUG_ON(sci_dev->working_request == NULL); + BUG_ON(idev->working_request == NULL); - isci_remote_device_not_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev), + isci_remote_device_not_ready(scic_to_ihost(scic), idev, SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); - struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); - if (sci_dev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) + if (idev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) isci_remote_device_not_ready(scic_to_ihost(scic), idev, - sci_dev->not_ready_reason); + idev->not_ready_reason); } static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); - isci_remote_device_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev)); + isci_remote_device_ready(scic_to_ihost(scic), idev); } static void scic_sds_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); + struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); - BUG_ON(sci_dev->working_request == NULL); + BUG_ON(idev->working_request == NULL); - isci_remote_device_not_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev), + isci_remote_device_not_ready(scic_to_ihost(scic), idev, SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); } static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_state_machine *sm) { - struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); + struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - sci_dev->working_request = NULL; + idev->working_request = NULL; } static const struct sci_base_state scic_sds_remote_device_state_table[] = { @@ -1065,14 +1059,14 @@ static const struct sci_base_state scic_sds_remote_device_state_table[] = { * frees the remote_node_context(s) for the device. */ static void scic_remote_device_construct(struct isci_port *iport, - struct scic_sds_remote_device *sci_dev) + struct isci_remote_device *idev) { - sci_dev->owning_port = iport; - sci_dev->started_request_count = 0; + idev->owning_port = iport; + idev->started_request_count = 0; - sci_init_sm(&sci_dev->sm, scic_sds_remote_device_state_table, SCI_DEV_INITIAL); + sci_init_sm(&idev->sm, scic_sds_remote_device_state_table, SCI_DEV_INITIAL); - scic_sds_remote_node_context_construct(&sci_dev->rnc, + scic_sds_remote_node_context_construct(&idev->rnc, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); } @@ -1091,21 +1085,21 @@ static void scic_remote_device_construct(struct isci_port *iport, * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ static enum sci_status scic_remote_device_da_construct(struct isci_port *iport, - struct scic_sds_remote_device *sci_dev) + struct isci_remote_device *idev) { enum sci_status status; - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct domain_device *dev = idev->domain_dev; - scic_remote_device_construct(iport, sci_dev); + scic_remote_device_construct(iport, idev); /* * This information is request to determine how many remote node context * entries will be needed to store the remote node. */ - sci_dev->is_direct_attached = true; + idev->is_direct_attached = true; status = scic_sds_controller_allocate_remote_node_context(iport->owning_controller, - sci_dev, - &sci_dev->rnc.remote_node_index); + idev, + &idev->rnc.remote_node_index); if (status != SCI_SUCCESS) return status; @@ -1116,10 +1110,10 @@ static enum sci_status scic_remote_device_da_construct(struct isci_port *iport, else return SCI_FAILURE_UNSUPPORTED_PROTOCOL; - sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(iport); + idev->connection_rate = scic_sds_port_get_max_allowed_speed(iport); /* / @todo Should I assign the port width by reading all of the phys on the port? */ - sci_dev->device_port_width = 1; + idev->device_port_width = 1; return SCI_SUCCESS; } @@ -1137,16 +1131,16 @@ static enum sci_status scic_remote_device_da_construct(struct isci_port *iport, * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ static enum sci_status scic_remote_device_ea_construct(struct isci_port *iport, - struct scic_sds_remote_device *sci_dev) + struct isci_remote_device *idev) { - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct domain_device *dev = idev->domain_dev; enum sci_status status; - scic_remote_device_construct(iport, sci_dev); + scic_remote_device_construct(iport, idev); status = scic_sds_controller_allocate_remote_node_context(iport->owning_controller, - sci_dev, - &sci_dev->rnc.remote_node_index); + idev, + &idev->rnc.remote_node_index); if (status != SCI_SUCCESS) return status; @@ -1163,11 +1157,11 @@ static enum sci_status scic_remote_device_ea_construct(struct isci_port *iport, * connection the logical link rate is that same as the * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay * one another, so this code works for both situations. */ - sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(iport), + idev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(iport), dev->linkrate); /* / @todo Should I assign the port width by reading all of the phys on the port? */ - sci_dev->device_port_width = 1; + idev->device_port_width = 1; return SCI_SUCCESS; } @@ -1185,22 +1179,22 @@ static enum sci_status scic_remote_device_ea_construct(struct isci_port *iport, * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start * the device when there have been no phys added to it. */ -static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *sci_dev, +static enum sci_status scic_remote_device_start(struct isci_remote_device *idev, u32 timeout) { - struct sci_base_state_machine *sm = &sci_dev->sm; + struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; enum sci_status status; if (state != SCI_DEV_STOPPED) { - dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n", + dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; } - status = scic_sds_remote_node_context_resume(&sci_dev->rnc, + status = scic_sds_remote_node_context_resume(&idev->rnc, remote_device_resume_done, - sci_dev); + idev); if (status != SCI_SUCCESS) return status; @@ -1217,9 +1211,9 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport, enum sci_status status; if (dev->parent && dev_is_expander(dev->parent)) - status = scic_remote_device_ea_construct(iport, &idev->sci); + status = scic_remote_device_ea_construct(iport, idev); else - status = scic_remote_device_da_construct(iport, &idev->sci); + status = scic_remote_device_da_construct(iport, idev); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: construct failed: %d\n", @@ -1229,7 +1223,7 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport, } /* start the device. */ - status = scic_remote_device_start(&idev->sci, ISCI_REMOTE_DEVICE_START_TIMEOUT); + status = scic_remote_device_start(idev, ISCI_REMOTE_DEVICE_START_TIMEOUT); if (status != SCI_SUCCESS) dev_warn(&ihost->pdev->dev, "remote device start failed: %d\n", @@ -1330,7 +1324,7 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem set_bit(IDEV_STOP_PENDING, &idev->flags); spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_stop(&idev->sci, 50); + status = scic_remote_device_stop(idev, 50); spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Wait for the stop complete callback. */ diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 578d75b8cd16..45798582fc14 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -70,65 +70,14 @@ enum scic_remote_device_not_ready_reason_code { SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX }; -struct scic_sds_remote_device { - /** - * This field contains the information for the base remote device state - * machine. - */ - struct sci_base_state_machine sm; - - /** - * This field is the programmed device port width. This value is - * written to the RCN data structure to tell the SCU how many open - * connections this device can have. - */ - u32 device_port_width; - - /** - * This field is the programmed connection rate for this remote device. It is - * used to program the TC with the maximum allowed connection rate. - */ - enum sas_linkrate connection_rate; - - /** - * This filed is assinged the value of true if the device is directly - * attached to the port. - */ - bool is_direct_attached; - - /** - * This filed contains a pointer back to the port to which this device - * is assigned. - */ - struct isci_port *owning_port; - - /** - * This field contains the SCU silicon remote node context specific - * information. - */ - struct scic_sds_remote_node_context rnc; - - /** - * This field contains the stated request count for the remote device. The - * device can not reach the SCI_DEV_STOPPED until all - * requests are complete and the rnc_posted value is false. - */ - u32 started_request_count; - - /** - * This field contains a pointer to the working request object. It is only - * used only for SATA requests since the unsolicited frames we get from the - * hardware have no Tag value to look up the io request object. - */ - struct isci_request *working_request; - - /** - * This field contains the reason for the remote device going not_ready. It is - * assigned in the state handlers and used in the state transition. - */ - u32 not_ready_reason; -}; - +/** + * isci_remote_device - isci representation of a sas expander / end point + * @device_port_width: hw setting for number of simultaneous connections + * @connection_rate: per-taskcontext connection rate for this device + * @working_request: SATA requests have no tag we for unaccelerated + * protocols we need a method to associate unsolicited + * frames with a pending request + */ struct isci_remote_device { #define IDEV_START_PENDING 0 #define IDEV_STOP_PENDING 1 @@ -143,7 +92,16 @@ struct isci_remote_device { struct domain_device *domain_dev; struct list_head node; struct list_head reqs_in_process; - struct scic_sds_remote_device sci; + struct sci_base_state_machine sm; + u32 device_port_width; + enum sas_linkrate connection_rate; + bool is_direct_attached; + struct isci_port *owning_port; + struct scic_sds_remote_node_context rnc; + /* XXX unify with device reference counting and delete */ + u32 started_request_count; + struct isci_request *working_request; + u32 not_ready_reason; }; #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 @@ -191,7 +149,7 @@ void isci_device_clear_reset_pending(struct isci_host *ihost, * successfully stopped. */ enum sci_status scic_remote_device_stop( - struct scic_sds_remote_device *remote_device, + struct isci_remote_device *idev, u32 timeout); /** @@ -207,7 +165,7 @@ enum sci_status scic_remote_device_stop( * started. */ enum sci_status scic_remote_device_reset( - struct scic_sds_remote_device *remote_device); + struct isci_remote_device *idev); /** * scic_remote_device_reset_complete() - This method informs the device object @@ -220,7 +178,7 @@ enum sci_status scic_remote_device_reset( * is resuming operation. */ enum sci_status scic_remote_device_reset_complete( - struct scic_sds_remote_device *remote_device); + struct isci_remote_device *idev); #define scic_remote_device_is_atapi(device_handle) false @@ -335,27 +293,15 @@ enum scic_sds_remote_device_states { SCI_DEV_FINAL, }; -static inline struct scic_sds_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) +static inline struct isci_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) { - struct scic_sds_remote_device *sci_dev; + struct isci_remote_device *idev; - sci_dev = container_of(rnc, typeof(*sci_dev), rnc); - - return sci_dev; -} - -static inline struct isci_remote_device *sci_dev_to_idev(struct scic_sds_remote_device *sci_dev) -{ - struct isci_remote_device *idev = container_of(sci_dev, typeof(*idev), sci); + idev = container_of(rnc, typeof(*idev), rnc); return idev; } -static inline struct domain_device *sci_dev_to_domain(struct scic_sds_remote_device *sci_dev) -{ - return sci_dev_to_idev(sci_dev)->domain_dev; -} - static inline bool dev_is_expander(struct domain_device *dev) { return dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV; @@ -366,8 +312,8 @@ static inline bool dev_is_expander(struct domain_device *dev) * * This macro incrments the request count for this device */ -#define scic_sds_remote_device_increment_request_count(sci_dev) \ - ((sci_dev)->started_request_count++) +#define scic_sds_remote_device_increment_request_count(idev) \ + ((idev)->started_request_count++) /** * scic_sds_remote_device_decrement_request_count() - @@ -375,44 +321,44 @@ static inline bool dev_is_expander(struct domain_device *dev) * This macro decrements the request count for this device. This count will * never decrment past 0. */ -#define scic_sds_remote_device_decrement_request_count(sci_dev) \ - ((sci_dev)->started_request_count > 0 ? \ - (sci_dev)->started_request_count-- : 0) +#define scic_sds_remote_device_decrement_request_count(idev) \ + ((idev)->started_request_count > 0 ? \ + (idev)->started_request_count-- : 0) /** * scic_sds_remote_device_get_request_count() - * * This is a helper macro to return the current device request count. */ -#define scic_sds_remote_device_get_request_count(sci_dev) \ - ((sci_dev)->started_request_count) +#define scic_sds_remote_device_get_request_count(idev) \ + ((idev)->started_request_count) /** * scic_sds_remote_device_get_controller() - * * This macro returns the controller object that contains this device object */ -#define scic_sds_remote_device_get_controller(sci_dev) \ - scic_sds_port_get_controller(scic_sds_remote_device_get_port(sci_dev)) +#define scic_sds_remote_device_get_controller(idev) \ + scic_sds_port_get_controller(scic_sds_remote_device_get_port(idev)) /** * scic_sds_remote_device_get_port() - * * This macro returns the owning port of this device */ -#define scic_sds_remote_device_get_port(sci_dev) \ - ((sci_dev)->owning_port) +#define scic_sds_remote_device_get_port(idev) \ + ((idev)->owning_port) /** * scic_sds_remote_device_get_controller_peg() - * * This macro returns the controllers protocol engine group */ -#define scic_sds_remote_device_get_controller_peg(sci_dev) \ +#define scic_sds_remote_device_get_controller_peg(idev) \ (\ scic_sds_controller_get_protocol_engine_group(\ scic_sds_port_get_controller(\ - scic_sds_remote_device_get_port(sci_dev) \ + scic_sds_remote_device_get_port(idev) \ ) \ ) \ ) @@ -422,8 +368,8 @@ static inline bool dev_is_expander(struct domain_device *dev) * * This macro returns the remote node index for this device object */ -#define scic_sds_remote_device_get_index(sci_dev) \ - ((sci_dev)->rnc.remote_node_index) +#define scic_sds_remote_device_get_index(idev) \ + ((idev)->rnc.remote_node_index) /** * scic_sds_remote_device_build_command_context() - @@ -448,36 +394,36 @@ static inline bool dev_is_expander(struct domain_device *dev) ((device)->working_request = (request)) enum sci_status scic_sds_remote_device_frame_handler( - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u32 frame_index); enum sci_status scic_sds_remote_device_event_handler( - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u32 event_code); enum sci_status scic_sds_remote_device_start_io( struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_sds_remote_device_start_task( struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_sds_remote_device_complete_io( struct scic_sds_controller *controller, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_sds_remote_device_suspend( - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u32 suspend_type); void scic_sds_remote_device_post_request( - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u32 request); -#define scic_sds_remote_device_is_atapi(sci_dev) false +#define scic_sds_remote_device_is_atapi(idev) false #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 1b51fe55314d..e485744e1263 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -103,22 +103,22 @@ bool scic_sds_remote_node_context_is_ready( static void scic_sds_remote_node_context_construct_buffer( struct scic_sds_remote_node_context *sci_rnc) { - struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct isci_remote_device *idev = rnc_to_dev(sci_rnc); + struct domain_device *dev = idev->domain_dev; int rni = sci_rnc->remote_node_index; union scu_remote_node_context *rnc; struct scic_sds_controller *scic; __le64 sas_addr; - scic = scic_sds_remote_device_get_controller(sci_dev); + scic = scic_sds_remote_device_get_controller(idev); rnc = scic_sds_controller_get_remote_node_context_buffer(scic, rni); memset(rnc, 0, sizeof(union scu_remote_node_context) - * scic_sds_remote_device_node_count(sci_dev)); + * scic_sds_remote_device_node_count(idev)); rnc->ssp.remote_node_index = rni; - rnc->ssp.remote_node_port_width = sci_dev->device_port_width; - rnc->ssp.logical_port_index = sci_dev->owning_port->physical_port_index; + rnc->ssp.remote_node_port_width = idev->device_port_width; + rnc->ssp.logical_port_index = idev->owning_port->physical_port_index; /* sas address is __be64, context ram format is __le64 */ sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr)); @@ -148,7 +148,7 @@ static void scic_sds_remote_node_context_construct_buffer( rnc->ssp.initial_arbitration_wait_time = 0; /* Open Address Frame Parameters */ - rnc->ssp.oaf_connection_rate = sci_dev->connection_rate; + rnc->ssp.oaf_connection_rate = idev->connection_rate; rnc->ssp.oaf_features = 0; rnc->ssp.oaf_source_zone_group = 0; rnc->ssp.oaf_more_compatibility_features = 0; @@ -220,26 +220,26 @@ static void scic_sds_remote_node_context_continue_state_transitions(struct scic_ static void scic_sds_remote_node_context_validate_context_buffer( struct scic_sds_remote_node_context *sci_rnc) { - struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct isci_remote_device *idev = rnc_to_dev(sci_rnc); + struct domain_device *dev = idev->domain_dev; union scu_remote_node_context *rnc_buffer; rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(sci_dev), + scic_sds_remote_device_get_controller(idev), sci_rnc->remote_node_index ); rnc_buffer->ssp.is_valid = true; - if (!sci_dev->is_direct_attached && + if (!idev->is_direct_attached && (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))) { - scic_sds_remote_device_post_request(sci_dev, + scic_sds_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_96); } else { - scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_32); + scic_sds_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_32); - if (sci_dev->is_direct_attached) { - scic_sds_port_setup_transports(sci_dev->owning_port, + if (idev->is_direct_attached) { + scic_sds_port_setup_transports(idev->owning_port, sci_rnc->remote_node_index); } } @@ -296,11 +296,11 @@ static void scic_sds_remote_node_context_invalidating_state_enter(struct sci_bas static void scic_sds_remote_node_context_resuming_state_enter(struct sci_base_state_machine *sm) { struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); - struct scic_sds_remote_device *sci_dev; + struct isci_remote_device *idev; struct domain_device *dev; - sci_dev = rnc_to_dev(rnc); - dev = sci_dev_to_domain(sci_dev); + idev = rnc_to_dev(rnc); + dev = idev->domain_dev; /* * For direct attached SATA devices we need to clear the TLCR @@ -309,11 +309,11 @@ static void scic_sds_remote_node_context_resuming_state_enter(struct sci_base_st * the STPTLDARNI register with the RNi of the device */ if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) && - sci_dev->is_direct_attached) - scic_sds_port_setup_transports(sci_dev->owning_port, + idev->is_direct_attached) + scic_sds_port_setup_transports(idev->owning_port, rnc->remote_node_index); - scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); + scic_sds_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); } static void scic_sds_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm) @@ -564,8 +564,8 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ sci_rnc->user_cookie = cb_p; return SCI_SUCCESS; case SCI_RNC_TX_SUSPENDED: { - struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc); - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct isci_remote_device *idev = rnc_to_dev(sci_rnc); + struct domain_device *dev = idev->domain_dev; scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); @@ -573,7 +573,7 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev)) sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { - if (sci_dev->is_direct_attached) { + if (idev->is_direct_attached) { /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); } else { diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index 35e6ae616903..7a24c7a12de1 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -79,7 +79,7 @@ #define SCI_SOFTWARE_SUSPENSION (1) struct isci_request; -struct scic_sds_remote_device; +struct isci_remote_device; struct scic_sds_remote_node_context; typedef void (*scics_sds_remote_node_context_callback)(void *); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 2d29abf3ce1f..90ead662828d 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -209,17 +209,17 @@ static void scu_ssp_reqeust_construct_task_context( struct scu_task_context *task_context) { dma_addr_t dma_addr; - struct scic_sds_remote_device *target_device; + struct isci_remote_device *idev; struct isci_port *iport; - target_device = scic_sds_request_get_device(ireq); + idev = scic_sds_request_get_device(ireq); iport = scic_sds_request_get_port(ireq); /* Fill in the TC with the its required data */ task_context->abort = 0; task_context->priority = 0; task_context->initiator_request = 1; - task_context->connection_rate = target_device->connection_rate; + task_context->connection_rate = idev->connection_rate; task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = scic_sds_port_get_index(iport); @@ -227,8 +227,7 @@ static void scu_ssp_reqeust_construct_task_context( task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; - task_context->remote_node_index = - scic_sds_remote_device_get_index(ireq->target_device); + task_context->remote_node_index = scic_sds_remote_device_get_index(idev); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -348,17 +347,17 @@ static void scu_sata_reqeust_construct_task_context( struct scu_task_context *task_context) { dma_addr_t dma_addr; - struct scic_sds_remote_device *target_device; + struct isci_remote_device *idev; struct isci_port *iport; - target_device = scic_sds_request_get_device(ireq); + idev = scic_sds_request_get_device(ireq); iport = scic_sds_request_get_port(ireq); /* Fill in the TC with the its required data */ task_context->abort = 0; task_context->priority = SCU_TASK_PRIORITY_NORMAL; task_context->initiator_request = 1; - task_context->connection_rate = target_device->connection_rate; + task_context->connection_rate = idev->connection_rate; task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(controller); task_context->logical_port_index = @@ -367,8 +366,7 @@ static void scu_sata_reqeust_construct_task_context( task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; - task_context->remote_node_index = - scic_sds_remote_device_get_index(ireq->target_device); + task_context->remote_node_index = scic_sds_remote_device_get_index(idev); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -2850,7 +2848,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, static void scic_sds_request_started_state_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - struct domain_device *dev = sci_dev_to_domain(ireq->target_device); + struct domain_device *dev = ireq->target_device->domain_dev; struct sas_task *task; /* XXX as hch said always creating an internal sas_task for tmf @@ -2988,12 +2986,12 @@ static const struct sci_base_state scic_sds_request_state_table[] = { static void scic_sds_general_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq) { sci_init_sm(&ireq->sm, scic_sds_request_state_table, SCI_REQ_INIT); - ireq->target_device = sci_dev; + ireq->target_device = idev; ireq->protocol = SCIC_NO_PROTOCOL; ireq->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; @@ -3004,16 +3002,16 @@ scic_sds_general_request_construct(struct scic_sds_controller *scic, static enum sci_status scic_io_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, struct isci_request *ireq) { - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct domain_device *dev = idev->domain_dev; enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, ireq); + scic_sds_general_request_construct(scic, idev, ireq); - if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) + if (idev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; if (dev->dev_type == SAS_END_DEV) @@ -3031,14 +3029,14 @@ scic_io_request_construct(struct scic_sds_controller *scic, } enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u16 io_tag, struct isci_request *ireq) { - struct domain_device *dev = sci_dev_to_domain(sci_dev); + struct domain_device *dev = idev->domain_dev; enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, sci_dev, ireq); + scic_sds_general_request_construct(scic, idev, ireq); if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { @@ -3102,7 +3100,7 @@ scic_io_request_construct_smp(struct device *dev, struct sas_task *task) { struct scatterlist *sg = &task->smp_task.smp_req; - struct scic_sds_remote_device *sci_dev; + struct isci_remote_device *idev; struct scu_task_context *task_context; struct isci_port *iport; struct smp_req *smp_req; @@ -3147,7 +3145,7 @@ scic_io_request_construct_smp(struct device *dev, task_context = ireq->tc; - sci_dev = scic_sds_request_get_device(ireq); + idev = scic_sds_request_get_device(ireq); iport = scic_sds_request_get_port(ireq); /* @@ -3156,7 +3154,7 @@ scic_io_request_construct_smp(struct device *dev, */ task_context->priority = 0; task_context->initiator_request = 1; - task_context->connection_rate = sci_dev->connection_rate; + task_context->connection_rate = idev->connection_rate; task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(scic); task_context->logical_port_index = scic_sds_port_get_index(iport); @@ -3166,7 +3164,7 @@ scic_io_request_construct_smp(struct device *dev, task_context->context_type = SCU_TASK_CONTEXT_TYPE; /* 04h */ - task_context->remote_node_index = sci_dev->rnc.remote_node_index; + task_context->remote_node_index = idev->rnc.remote_node_index; task_context->command_code = 0; task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; @@ -3257,17 +3255,16 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) */ static enum sci_status isci_io_request_build(struct isci_host *isci_host, struct isci_request *request, - struct isci_remote_device *isci_device) + struct isci_remote_device *idev) { enum sci_status status = SCI_SUCCESS; struct sas_task *task = isci_request_access_task(request); - struct scic_sds_remote_device *sci_device = &isci_device->sci; dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = 0x%p; request = %p, " + "%s: idev = 0x%p; request = %p, " "num_scatter = %d\n", __func__, - isci_device, + idev, request, task->num_scatter); @@ -3290,8 +3287,7 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, return SCI_FAILURE_INSUFFICIENT_RESOURCES; } - status = scic_io_request_construct(&isci_host->sci, sci_device, - request); + status = scic_io_request_construct(&isci_host->sci, idev, request); if (status != SCI_SUCCESS) { dev_warn(&isci_host->pdev->dev, @@ -3397,14 +3393,14 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide * ireq->is_task_management_request is false). */ status = scic_controller_start_task(&ihost->sci, - &idev->sci, + idev, ireq); } else { status = SCI_FAILURE; } } else { /* send the request, let the core assign the IO TAG. */ - status = scic_controller_start_io(&ihost->sci, &idev->sci, + status = scic_controller_start_io(&ihost->sci, idev, ireq); } diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 68d8a27357eb..ca64ea207ac8 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -146,7 +146,7 @@ struct isci_request { struct completion *io_request_completion; struct sci_base_state_machine sm; struct scic_sds_controller *owning_controller; - struct scic_sds_remote_device *target_device; + struct isci_remote_device *target_device; u16 io_tag; enum sci_request_protocol protocol; u32 scu_status; /* hardware result */ @@ -501,7 +501,7 @@ void isci_terminate_pending_requests(struct isci_host *ihost, struct isci_remote_device *idev); enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, - struct scic_sds_remote_device *sci_dev, + struct isci_remote_device *idev, u16 io_tag, struct isci_request *ireq); enum sci_status diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 700708c82678..89b01eef44b1 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -257,7 +257,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, return NULL; /* let the core do it's construct. */ - status = scic_task_request_construct(&ihost->sci, &idev->sci, tag, + status = scic_task_request_construct(&ihost->sci, idev, tag, ireq); if (status != SCI_SUCCESS) { @@ -288,12 +288,11 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, } int isci_task_execute_tmf(struct isci_host *ihost, - struct isci_remote_device *isci_device, + struct isci_remote_device *idev, struct isci_tmf *tmf, unsigned long timeout_ms) { DECLARE_COMPLETION_ONSTACK(completion); enum sci_task_status status = SCI_TASK_FAILURE; - struct scic_sds_remote_device *sci_device; struct isci_request *ireq; int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; @@ -310,34 +309,30 @@ int isci_task_execute_tmf(struct isci_host *ihost, /* sanity check, return TMF_RESP_FUNC_FAILED * if the device is not there and ready. */ - if (!isci_device || - (!test_bit(IDEV_IO_READY, &isci_device->flags) && - !test_bit(IDEV_IO_NCQERROR, &isci_device->flags))) { + if (!idev || + (!test_bit(IDEV_IO_READY, &idev->flags) && + !test_bit(IDEV_IO_NCQERROR, &idev->flags))) { dev_dbg(&ihost->pdev->dev, - "%s: isci_device = %p not ready (%#lx)\n", + "%s: idev = %p not ready (%#lx)\n", __func__, - isci_device, isci_device ? isci_device->flags : 0); + idev, idev ? idev->flags : 0); goto err_tci; } else dev_dbg(&ihost->pdev->dev, - "%s: isci_device = %p\n", - __func__, isci_device); - - sci_device = &isci_device->sci; + "%s: idev = %p\n", + __func__, idev); /* Assign the pointer to the TMF's completion kernel wait structure. */ tmf->complete = &completion; - ireq = isci_task_request_build(ihost, isci_device, tag, tmf); + ireq = isci_task_request_build(ihost, idev, tag, tmf); if (!ireq) goto err_tci; spin_lock_irqsave(&ihost->scic_lock, flags); /* start the TMF io. */ - status = scic_controller_start_task(&ihost->sci, - sci_device, - ireq); + status = scic_controller_start_task(&ihost->sci, idev, ireq); if (status != SCI_TASK_SUCCESS) { dev_warn(&ihost->pdev->dev, @@ -355,7 +350,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, isci_request_change_state(ireq, started); /* add the request to the remote device request list. */ - list_add(&ireq->dev_node, &isci_device->reqs_in_process); + list_add(&ireq->dev_node, &idev->reqs_in_process); spin_unlock_irqrestore(&ihost->scic_lock, flags); @@ -370,7 +365,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); scic_controller_terminate_request(&ihost->sci, - &isci_device->sci, + idev, ireq); spin_unlock_irqrestore(&ihost->scic_lock, flags); @@ -520,13 +515,13 @@ static void isci_request_cleanup_completed_loiterer( * from a thread that can wait. Note that the request is terminated and * completed (back to the host, if started there). * @isci_host: This SCU. - * @isci_device: The target. + * @idev: The target. * @isci_request: The I/O request to be terminated. * */ static void isci_terminate_request_core( struct isci_host *isci_host, - struct isci_remote_device *isci_device, + struct isci_remote_device *idev, struct isci_request *isci_request) { enum sci_status status = SCI_SUCCESS; @@ -540,7 +535,7 @@ static void isci_terminate_request_core( dev_dbg(&isci_host->pdev->dev, "%s: device = %p; request = %p\n", - __func__, isci_device, isci_request); + __func__, idev, isci_request); spin_lock_irqsave(&isci_host->scic_lock, flags); @@ -564,7 +559,7 @@ static void isci_terminate_request_core( needs_cleanup_handling = true; status = scic_controller_terminate_request( &isci_host->sci, - &isci_device->sci, + idev, isci_request); } spin_unlock_irqrestore(&isci_host->scic_lock, flags); @@ -683,7 +678,7 @@ static void isci_terminate_request_core( } if (needs_cleanup_handling) isci_request_cleanup_completed_loiterer( - isci_host, isci_device, isci_request, task); + isci_host, idev, isci_request, task); } } @@ -694,7 +689,7 @@ static void isci_terminate_request_core( * called from a thread that can wait. Note that the requests are all * terminated and completed (back to the host, if started there). * @isci_host: This parameter specifies SCU. - * @isci_device: This parameter specifies the target. + * @idev: This parameter specifies the target. * */ void isci_terminate_pending_requests(struct isci_host *ihost, @@ -1521,7 +1516,7 @@ static int isci_reset_device(struct isci_host *ihost, dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_reset(&idev->sci); + status = scic_remote_device_reset(idev); if (status != SCI_SUCCESS) { spin_unlock_irqrestore(&ihost->scic_lock, flags); @@ -1547,7 +1542,7 @@ static int isci_reset_device(struct isci_host *ihost, /* Since all pending TCs have been cleaned, resume the RNC. */ spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_reset_complete(&idev->sci); + status = scic_remote_device_reset_complete(idev); spin_unlock_irqrestore(&ihost->scic_lock, flags); /* If this is a device on an expander, bring the phy back up. */ -- cgit v1.2.3 From d9dcb4ba791de2a06b19ac47cd61601cf3d4e208 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 30 Jun 2011 17:38:32 -0700 Subject: isci: unify isci_host and scic_sds_controller Remove the distinction between these two implementations and unify on isci_host (local instances named ihost). Hmmm, we had two 'oem_parameters' instances, one was unused... nice. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 1000 ++++++++++++------------- drivers/scsi/isci/host.h | 210 ++---- drivers/scsi/isci/init.c | 10 +- drivers/scsi/isci/phy.c | 40 +- drivers/scsi/isci/port.c | 89 +-- drivers/scsi/isci/port.h | 4 +- drivers/scsi/isci/port_config.c | 82 +- drivers/scsi/isci/probe_roms.h | 2 +- drivers/scsi/isci/remote_device.c | 76 +- drivers/scsi/isci/remote_device.h | 6 +- drivers/scsi/isci/remote_node_context.c | 14 +- drivers/scsi/isci/request.c | 200 +++-- drivers/scsi/isci/request.h | 4 +- drivers/scsi/isci/task.c | 44 +- drivers/scsi/isci/unsolicited_frame_control.c | 6 +- drivers/scsi/isci/unsolicited_frame_control.h | 4 +- 16 files changed, 806 insertions(+), 985 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 45d7f71c609a..bb298f8f609a 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -181,35 +181,35 @@ void sci_change_state(struct sci_base_state_machine *sm, u32 next_state) } static bool scic_sds_controller_completion_queue_has_entries( - struct scic_sds_controller *scic) + struct isci_host *ihost) { - u32 get_value = scic->completion_queue_get; + u32 get_value = ihost->completion_queue_get; u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK; if (NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) == - COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index])) + COMPLETION_QUEUE_CYCLE_BIT(ihost->completion_queue[get_index])) return true; return false; } -static bool scic_sds_controller_isr(struct scic_sds_controller *scic) +static bool scic_sds_controller_isr(struct isci_host *ihost) { - if (scic_sds_controller_completion_queue_has_entries(scic)) { + if (scic_sds_controller_completion_queue_has_entries(ihost)) { return true; } else { /* * we have a spurious interrupt it could be that we have already * emptied the completion queue from a previous interrupt */ - writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); + writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status); /* * There is a race in the hardware that could cause us not to be notified * of an interrupt completion if we do not take this step. We will mask * then unmask the interrupts so if there is another interrupt pending * the clearing of the interrupt source we get the next interrupt message. */ - writel(0xFF000000, &scic->smu_registers->interrupt_mask); - writel(0, &scic->smu_registers->interrupt_mask); + writel(0xFF000000, &ihost->smu_registers->interrupt_mask); + writel(0, &ihost->smu_registers->interrupt_mask); } return false; @@ -219,18 +219,18 @@ irqreturn_t isci_msix_isr(int vec, void *data) { struct isci_host *ihost = data; - if (scic_sds_controller_isr(&ihost->sci)) + if (scic_sds_controller_isr(ihost)) tasklet_schedule(&ihost->completion_tasklet); return IRQ_HANDLED; } -static bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) +static bool scic_sds_controller_error_isr(struct isci_host *ihost) { u32 interrupt_status; interrupt_status = - readl(&scic->smu_registers->interrupt_status); + readl(&ihost->smu_registers->interrupt_status); interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); if (interrupt_status != 0) { @@ -246,28 +246,27 @@ static bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) * then unmask the error interrupts so if there was another interrupt * pending we will be notified. * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */ - writel(0xff, &scic->smu_registers->interrupt_mask); - writel(0, &scic->smu_registers->interrupt_mask); + writel(0xff, &ihost->smu_registers->interrupt_mask); + writel(0, &ihost->smu_registers->interrupt_mask); return false; } -static void scic_sds_controller_task_completion(struct scic_sds_controller *scic, +static void scic_sds_controller_task_completion(struct isci_host *ihost, u32 completion_entry) { u32 index = SCU_GET_COMPLETION_INDEX(completion_entry); - struct isci_host *ihost = scic_to_ihost(scic); struct isci_request *ireq = ihost->reqs[index]; /* Make sure that we really want to process this IO request */ if (test_bit(IREQ_ACTIVE, &ireq->flags) && ireq->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && - ISCI_TAG_SEQ(ireq->io_tag) == scic->io_request_sequence[index]) + ISCI_TAG_SEQ(ireq->io_tag) == ihost->io_request_sequence[index]) /* Yep this is a valid io request pass it along to the io request handler */ scic_sds_io_request_tc_completion(ireq, completion_entry); } -static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic, +static void scic_sds_controller_sdma_completion(struct isci_host *ihost, u32 completion_entry) { u32 index; @@ -279,8 +278,8 @@ static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic switch (scu_get_command_request_type(completion_entry)) { case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: - ireq = scic_to_ihost(scic)->reqs[index]; - dev_warn(scic_to_dev(scic), "%s: %x for io request %p\n", + ireq = ihost->reqs[index]; + dev_warn(&ihost->pdev->dev, "%s: %x for io request %p\n", __func__, completion_entry, ireq); /* @todo For a post TC operation we need to fail the IO * request @@ -289,27 +288,26 @@ static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: - idev = scic->device_table[index]; - dev_warn(scic_to_dev(scic), "%s: %x for device %p\n", + idev = ihost->device_table[index]; + dev_warn(&ihost->pdev->dev, "%s: %x for device %p\n", __func__, completion_entry, idev); /* @todo For a port RNC operation we need to fail the * device */ break; default: - dev_warn(scic_to_dev(scic), "%s: unknown completion type %x\n", + dev_warn(&ihost->pdev->dev, "%s: unknown completion type %x\n", __func__, completion_entry); break; } } -static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *scic, +static void scic_sds_controller_unsolicited_frame(struct isci_host *ihost, u32 completion_entry) { u32 index; u32 frame_index; - struct isci_host *ihost = scic_to_ihost(scic); struct scu_unsolicited_frame_header *frame_header; struct isci_phy *iphy; struct isci_remote_device *idev; @@ -318,15 +316,15 @@ static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *sc frame_index = SCU_GET_FRAME_INDEX(completion_entry); - frame_header = scic->uf_control.buffers.array[frame_index].header; - scic->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE; + frame_header = ihost->uf_control.buffers.array[frame_index].header; + ihost->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE; if (SCU_GET_FRAME_ERROR(completion_entry)) { /* * / @todo If the IAF frame or SIGNATURE FIS frame has an error will * / this cause a problem? We expect the phy initialization will * / fail if there is an error in the frame. */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return; } @@ -347,15 +345,15 @@ static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *sc iphy = &ihost->phys[index]; result = scic_sds_phy_frame_handler(iphy, frame_index); } else { - if (index < scic->remote_node_entries) - idev = scic->device_table[index]; + if (index < ihost->remote_node_entries) + idev = ihost->device_table[index]; else idev = NULL; if (idev != NULL) result = scic_sds_remote_device_frame_handler(idev, frame_index); else - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); } } @@ -366,10 +364,9 @@ static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *sc } } -static void scic_sds_controller_event_completion(struct scic_sds_controller *scic, +static void scic_sds_controller_event_completion(struct isci_host *ihost, u32 completion_entry) { - struct isci_host *ihost = scic_to_ihost(scic); struct isci_remote_device *idev; struct isci_request *ireq; struct isci_phy *iphy; @@ -380,11 +377,11 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci switch (scu_get_event_type(completion_entry)) { case SCU_EVENT_TYPE_SMU_COMMAND_ERROR: /* / @todo The driver did something wrong and we need to fix the condtion. */ - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC Controller 0x%p received SMU command error " "0x%x\n", __func__, - scic, + ihost, completion_entry); break; @@ -394,11 +391,11 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci /* * / @todo This is a hardware failure and its likely that we want to * / reset the controller. */ - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC Controller 0x%p received fatal controller " "event 0x%x\n", __func__, - scic, + ihost, completion_entry); break; @@ -415,27 +412,27 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci if (ireq != NULL) scic_sds_io_request_event_handler(ireq, completion_entry); else - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: SCIC Controller 0x%p received " "event 0x%x for io request object " "that doesnt exist.\n", __func__, - scic, + ihost, completion_entry); break; case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: - idev = scic->device_table[index]; + idev = ihost->device_table[index]; if (idev != NULL) scic_sds_remote_device_event_handler(idev, completion_entry); else - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: SCIC Controller 0x%p received " "event 0x%x for remote device object " "that doesnt exist.\n", __func__, - scic, + ihost, completion_entry); break; @@ -459,25 +456,25 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci case SCU_EVENT_TYPE_RNC_SUSPEND_TX: case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: case SCU_EVENT_TYPE_RNC_OPS_MISC: - if (index < scic->remote_node_entries) { - idev = scic->device_table[index]; + if (index < ihost->remote_node_entries) { + idev = ihost->device_table[index]; if (idev != NULL) scic_sds_remote_device_event_handler(idev, completion_entry); } else - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC Controller 0x%p received event 0x%x " "for remote device object 0x%0x that doesnt " "exist.\n", __func__, - scic, + ihost, completion_entry, index); break; default: - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: SCIC Controller received unknown event code %x\n", __func__, completion_entry); @@ -485,7 +482,7 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci } } -static void scic_sds_controller_process_completions(struct scic_sds_controller *scic) +static void scic_sds_controller_process_completions(struct isci_host *ihost) { u32 completion_count = 0; u32 completion_entry; @@ -494,47 +491,47 @@ static void scic_sds_controller_process_completions(struct scic_sds_controller * u32 event_get; u32 event_cycle; - dev_dbg(scic_to_dev(scic), + dev_dbg(&ihost->pdev->dev, "%s: completion queue begining get:0x%08x\n", __func__, - scic->completion_queue_get); + ihost->completion_queue_get); /* Get the component parts of the completion queue */ - get_index = NORMALIZE_GET_POINTER(scic->completion_queue_get); - get_cycle = SMU_CQGR_CYCLE_BIT & scic->completion_queue_get; + get_index = NORMALIZE_GET_POINTER(ihost->completion_queue_get); + get_cycle = SMU_CQGR_CYCLE_BIT & ihost->completion_queue_get; - event_get = NORMALIZE_EVENT_POINTER(scic->completion_queue_get); - event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & scic->completion_queue_get; + event_get = NORMALIZE_EVENT_POINTER(ihost->completion_queue_get); + event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & ihost->completion_queue_get; while ( NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) - == COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index]) + == COMPLETION_QUEUE_CYCLE_BIT(ihost->completion_queue[get_index]) ) { completion_count++; - completion_entry = scic->completion_queue[get_index]; + completion_entry = ihost->completion_queue[get_index]; /* increment the get pointer and check for rollover to toggle the cycle bit */ get_cycle ^= ((get_index+1) & SCU_MAX_COMPLETION_QUEUE_ENTRIES) << (SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT - SCU_MAX_COMPLETION_QUEUE_SHIFT); get_index = (get_index+1) & (SCU_MAX_COMPLETION_QUEUE_ENTRIES-1); - dev_dbg(scic_to_dev(scic), + dev_dbg(&ihost->pdev->dev, "%s: completion queue entry:0x%08x\n", __func__, completion_entry); switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { case SCU_COMPLETION_TYPE_TASK: - scic_sds_controller_task_completion(scic, completion_entry); + scic_sds_controller_task_completion(ihost, completion_entry); break; case SCU_COMPLETION_TYPE_SDMA: - scic_sds_controller_sdma_completion(scic, completion_entry); + scic_sds_controller_sdma_completion(ihost, completion_entry); break; case SCU_COMPLETION_TYPE_UFI: - scic_sds_controller_unsolicited_frame(scic, completion_entry); + scic_sds_controller_unsolicited_frame(ihost, completion_entry); break; case SCU_COMPLETION_TYPE_EVENT: @@ -543,11 +540,11 @@ static void scic_sds_controller_process_completions(struct scic_sds_controller * (SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT - SCU_MAX_EVENTS_SHIFT); event_get = (event_get+1) & (SCU_MAX_EVENTS-1); - scic_sds_controller_event_completion(scic, completion_entry); + scic_sds_controller_event_completion(ihost, completion_entry); break; } default: - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: SCIC Controller received unknown " "completion type %x\n", __func__, @@ -558,7 +555,7 @@ static void scic_sds_controller_process_completions(struct scic_sds_controller * /* Update the get register if we completed one or more entries */ if (completion_count > 0) { - scic->completion_queue_get = + ihost->completion_queue_get = SMU_CQGR_GEN_BIT(ENABLE) | SMU_CQGR_GEN_BIT(EVENT_ENABLE) | event_cycle | @@ -566,35 +563,35 @@ static void scic_sds_controller_process_completions(struct scic_sds_controller * get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); - writel(scic->completion_queue_get, - &scic->smu_registers->completion_queue_get); + writel(ihost->completion_queue_get, + &ihost->smu_registers->completion_queue_get); } - dev_dbg(scic_to_dev(scic), + dev_dbg(&ihost->pdev->dev, "%s: completion queue ending get:0x%08x\n", __func__, - scic->completion_queue_get); + ihost->completion_queue_get); } -static void scic_sds_controller_error_handler(struct scic_sds_controller *scic) +static void scic_sds_controller_error_handler(struct isci_host *ihost) { u32 interrupt_status; interrupt_status = - readl(&scic->smu_registers->interrupt_status); + readl(&ihost->smu_registers->interrupt_status); if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && - scic_sds_controller_completion_queue_has_entries(scic)) { + scic_sds_controller_completion_queue_has_entries(ihost)) { - scic_sds_controller_process_completions(scic); - writel(SMU_ISR_QUEUE_SUSPEND, &scic->smu_registers->interrupt_status); + scic_sds_controller_process_completions(ihost); + writel(SMU_ISR_QUEUE_SUSPEND, &ihost->smu_registers->interrupt_status); } else { - dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, + dev_err(&ihost->pdev->dev, "%s: status: %#x\n", __func__, interrupt_status); - sci_change_state(&scic->sm, SCIC_FAILED); + sci_change_state(&ihost->sm, SCIC_FAILED); return; } @@ -602,22 +599,21 @@ static void scic_sds_controller_error_handler(struct scic_sds_controller *scic) /* If we dont process any completions I am not sure that we want to do this. * We are in the middle of a hardware fault and should probably be reset. */ - writel(0, &scic->smu_registers->interrupt_mask); + writel(0, &ihost->smu_registers->interrupt_mask); } irqreturn_t isci_intx_isr(int vec, void *data) { irqreturn_t ret = IRQ_NONE; struct isci_host *ihost = data; - struct scic_sds_controller *scic = &ihost->sci; - if (scic_sds_controller_isr(scic)) { - writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); + if (scic_sds_controller_isr(ihost)) { + writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status); tasklet_schedule(&ihost->completion_tasklet); ret = IRQ_HANDLED; - } else if (scic_sds_controller_error_isr(scic)) { + } else if (scic_sds_controller_error_isr(ihost)) { spin_lock(&ihost->scic_lock); - scic_sds_controller_error_handler(scic); + scic_sds_controller_error_handler(ihost); spin_unlock(&ihost->scic_lock); ret = IRQ_HANDLED; } @@ -629,8 +625,8 @@ irqreturn_t isci_error_isr(int vec, void *data) { struct isci_host *ihost = data; - if (scic_sds_controller_error_isr(&ihost->sci)) - scic_sds_controller_error_handler(&ihost->sci); + if (scic_sds_controller_error_isr(ihost)) + scic_sds_controller_error_handler(ihost); return IRQ_HANDLED; } @@ -685,11 +681,10 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) * This method returns the number of milliseconds for the suggested start * operation timeout. */ -static u32 scic_controller_get_suggested_start_timeout( - struct scic_sds_controller *sc) +static u32 scic_controller_get_suggested_start_timeout(struct isci_host *ihost) { /* Validate the user supplied parameters. */ - if (sc == NULL) + if (!ihost) return 0; /* @@ -711,35 +706,32 @@ static u32 scic_controller_get_suggested_start_timeout( + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); } -static void scic_controller_enable_interrupts( - struct scic_sds_controller *scic) +static void scic_controller_enable_interrupts(struct isci_host *ihost) { - BUG_ON(scic->smu_registers == NULL); - writel(0, &scic->smu_registers->interrupt_mask); + BUG_ON(ihost->smu_registers == NULL); + writel(0, &ihost->smu_registers->interrupt_mask); } -void scic_controller_disable_interrupts( - struct scic_sds_controller *scic) +void scic_controller_disable_interrupts(struct isci_host *ihost) { - BUG_ON(scic->smu_registers == NULL); - writel(0xffffffff, &scic->smu_registers->interrupt_mask); + BUG_ON(ihost->smu_registers == NULL); + writel(0xffffffff, &ihost->smu_registers->interrupt_mask); } -static void scic_sds_controller_enable_port_task_scheduler( - struct scic_sds_controller *scic) +static void scic_sds_controller_enable_port_task_scheduler(struct isci_host *ihost) { u32 port_task_scheduler_value; port_task_scheduler_value = - readl(&scic->scu_registers->peg0.ptsg.control); + readl(&ihost->scu_registers->peg0.ptsg.control); port_task_scheduler_value |= (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE)); writel(port_task_scheduler_value, - &scic->scu_registers->peg0.ptsg.control); + &ihost->scu_registers->peg0.ptsg.control); } -static void scic_sds_controller_assign_task_entries(struct scic_sds_controller *scic) +static void scic_sds_controller_assign_task_entries(struct isci_host *ihost) { u32 task_assignment; @@ -749,32 +741,32 @@ static void scic_sds_controller_assign_task_entries(struct scic_sds_controller * */ task_assignment = - readl(&scic->smu_registers->task_context_assignment[0]); + readl(&ihost->smu_registers->task_context_assignment[0]); task_assignment |= (SMU_TCA_GEN_VAL(STARTING, 0)) | - (SMU_TCA_GEN_VAL(ENDING, scic->task_context_entries - 1)) | + (SMU_TCA_GEN_VAL(ENDING, ihost->task_context_entries - 1)) | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE)); writel(task_assignment, - &scic->smu_registers->task_context_assignment[0]); + &ihost->smu_registers->task_context_assignment[0]); } -static void scic_sds_controller_initialize_completion_queue(struct scic_sds_controller *scic) +static void scic_sds_controller_initialize_completion_queue(struct isci_host *ihost) { u32 index; u32 completion_queue_control_value; u32 completion_queue_get_value; u32 completion_queue_put_value; - scic->completion_queue_get = 0; + ihost->completion_queue_get = 0; completion_queue_control_value = (SMU_CQC_QUEUE_LIMIT_SET(SCU_MAX_COMPLETION_QUEUE_ENTRIES - 1) | SMU_CQC_EVENT_LIMIT_SET(SCU_MAX_EVENTS - 1)); writel(completion_queue_control_value, - &scic->smu_registers->completion_queue_control); + &ihost->smu_registers->completion_queue_control); /* Set the completion queue get pointer and enable the queue */ @@ -786,7 +778,7 @@ static void scic_sds_controller_initialize_completion_queue(struct scic_sds_cont ); writel(completion_queue_get_value, - &scic->smu_registers->completion_queue_get); + &ihost->smu_registers->completion_queue_get); /* Set the completion queue put pointer */ completion_queue_put_value = ( @@ -795,7 +787,7 @@ static void scic_sds_controller_initialize_completion_queue(struct scic_sds_cont ); writel(completion_queue_put_value, - &scic->smu_registers->completion_queue_put); + &ihost->smu_registers->completion_queue_put); /* Initialize the cycle bit of the completion queue entries */ for (index = 0; index < SCU_MAX_COMPLETION_QUEUE_ENTRIES; index++) { @@ -803,11 +795,11 @@ static void scic_sds_controller_initialize_completion_queue(struct scic_sds_cont * If get.cycle_bit != completion_queue.cycle_bit * its not a valid completion queue entry * so at system start all entries are invalid */ - scic->completion_queue[index] = 0x80000000; + ihost->completion_queue[index] = 0x80000000; } } -static void scic_sds_controller_initialize_unsolicited_frame_queue(struct scic_sds_controller *scic) +static void scic_sds_controller_initialize_unsolicited_frame_queue(struct isci_host *ihost) { u32 frame_queue_control_value; u32 frame_queue_get_value; @@ -818,7 +810,7 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue(struct scic_s SCU_UFQC_GEN_VAL(QUEUE_SIZE, SCU_MAX_UNSOLICITED_FRAMES); writel(frame_queue_control_value, - &scic->scu_registers->sdma.unsolicited_frame_queue_control); + &ihost->scu_registers->sdma.unsolicited_frame_queue_control); /* Setup the get pointer for the unsolicited frame queue */ frame_queue_get_value = ( @@ -827,11 +819,11 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue(struct scic_s ); writel(frame_queue_get_value, - &scic->scu_registers->sdma.unsolicited_frame_get_pointer); + &ihost->scu_registers->sdma.unsolicited_frame_get_pointer); /* Setup the put pointer for the unsolicited frame queue */ frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0); writel(frame_queue_put_value, - &scic->scu_registers->sdma.unsolicited_frame_put_pointer); + &ihost->scu_registers->sdma.unsolicited_frame_put_pointer); } /** @@ -846,17 +838,16 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue(struct scic_s * none. */ static void scic_sds_controller_transition_to_ready( - struct scic_sds_controller *scic, + struct isci_host *ihost, enum sci_status status) { - struct isci_host *ihost = scic_to_ihost(scic); - if (scic->sm.current_state_id == SCIC_STARTING) { + if (ihost->sm.current_state_id == SCIC_STARTING) { /* * We move into the ready state, because some of the phys/ports * may be up and operational. */ - sci_change_state(&scic->sm, SCIC_READY); + sci_change_state(&ihost->sm, SCIC_READY); isci_host_start_complete(ihost, status); } @@ -892,19 +883,18 @@ static bool is_phy_starting(struct isci_phy *iphy) * controller to the READY state and inform the user * (scic_cb_controller_start_complete()). */ -static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic) +static enum sci_status scic_sds_controller_start_next_phy(struct isci_host *ihost) { - struct isci_host *ihost = scic_to_ihost(scic); - struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; + struct scic_sds_oem_params *oem = &ihost->oem_parameters.sds1; struct isci_phy *iphy; enum sci_status status; status = SCI_SUCCESS; - if (scic->phy_startup_timer_pending) + if (ihost->phy_startup_timer_pending) return status; - if (scic->next_phy_to_start >= SCI_MAX_PHYS) { + if (ihost->next_phy_to_start >= SCI_MAX_PHYS) { bool is_controller_start_complete = true; u32 state; u8 index; @@ -934,16 +924,16 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro * The controller has successfully finished the start process. * Inform the SCI Core user and transition to the READY state. */ if (is_controller_start_complete == true) { - scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS); - sci_del_timer(&scic->phy_timer); - scic->phy_startup_timer_pending = false; + scic_sds_controller_transition_to_ready(ihost, SCI_SUCCESS); + sci_del_timer(&ihost->phy_timer); + ihost->phy_startup_timer_pending = false; } } else { - iphy = &ihost->phys[scic->next_phy_to_start]; + iphy = &ihost->phys[ihost->next_phy_to_start]; if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { if (phy_get_non_dummy_port(iphy) == NULL) { - scic->next_phy_to_start++; + ihost->next_phy_to_start++; /* Caution recursion ahead be forwarned * @@ -954,27 +944,27 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro * incorrectly for the PORT or it was never * assigned to a PORT */ - return scic_sds_controller_start_next_phy(scic); + return scic_sds_controller_start_next_phy(ihost); } } status = scic_sds_phy_start(iphy); if (status == SCI_SUCCESS) { - sci_mod_timer(&scic->phy_timer, + sci_mod_timer(&ihost->phy_timer, SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT); - scic->phy_startup_timer_pending = true; + ihost->phy_startup_timer_pending = true; } else { - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: Controller stop operation failed " "to stop phy %d because of status " "%d.\n", __func__, - ihost->phys[scic->next_phy_to_start].phy_index, + ihost->phys[ihost->next_phy_to_start].phy_index, status); } - scic->next_phy_to_start++; + ihost->next_phy_to_start++; } return status; @@ -983,8 +973,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_contro static void phy_startup_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; - struct scic_sds_controller *scic = container_of(tmr, typeof(*scic), phy_timer); - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = container_of(tmr, typeof(*ihost), phy_timer); unsigned long flags; enum sci_status status; @@ -993,10 +982,10 @@ static void phy_startup_timeout(unsigned long data) if (tmr->cancel) goto done; - scic->phy_startup_timer_pending = false; + ihost->phy_startup_timer_pending = false; do { - status = scic_sds_controller_start_next_phy(scic); + status = scic_sds_controller_start_next_phy(ihost); } while (status != SCI_SUCCESS); done: @@ -1008,15 +997,14 @@ static u16 isci_tci_active(struct isci_host *ihost) return CIRC_CNT(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); } -static enum sci_status scic_controller_start(struct scic_sds_controller *scic, +static enum sci_status scic_controller_start(struct isci_host *ihost, u32 timeout) { - struct isci_host *ihost = scic_to_ihost(scic); enum sci_status result; u16 index; - if (scic->sm.current_state_id != SCIC_INITIALIZED) { - dev_warn(scic_to_dev(scic), + if (ihost->sm.current_state_id != SCIC_INITIALIZED) { + dev_warn(&ihost->pdev->dev, "SCIC Controller start operation requested in " "invalid state\n"); return SCI_FAILURE_INVALID_STATE; @@ -1026,34 +1014,34 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, BUILD_BUG_ON(SCI_MAX_IO_REQUESTS > 1 << sizeof(ihost->tci_pool[0]) * 8); ihost->tci_head = 0; ihost->tci_tail = 0; - for (index = 0; index < scic->task_context_entries; index++) + for (index = 0; index < ihost->task_context_entries; index++) isci_tci_free(ihost, index); /* Build the RNi free pool */ scic_sds_remote_node_table_initialize( - &scic->available_remote_nodes, - scic->remote_node_entries); + &ihost->available_remote_nodes, + ihost->remote_node_entries); /* * Before anything else lets make sure we will not be * interrupted by the hardware. */ - scic_controller_disable_interrupts(scic); + scic_controller_disable_interrupts(ihost); /* Enable the port task scheduler */ - scic_sds_controller_enable_port_task_scheduler(scic); + scic_sds_controller_enable_port_task_scheduler(ihost); - /* Assign all the task entries to scic physical function */ - scic_sds_controller_assign_task_entries(scic); + /* Assign all the task entries to ihost physical function */ + scic_sds_controller_assign_task_entries(ihost); /* Now initialize the completion queue */ - scic_sds_controller_initialize_completion_queue(scic); + scic_sds_controller_initialize_completion_queue(ihost); /* Initialize the unsolicited frame queue for use */ - scic_sds_controller_initialize_unsolicited_frame_queue(scic); + scic_sds_controller_initialize_unsolicited_frame_queue(ihost); /* Start all of the ports on this controller */ - for (index = 0; index < scic->logical_port_entries; index++) { + for (index = 0; index < ihost->logical_port_entries; index++) { struct isci_port *iport = &ihost->ports[index]; result = scic_sds_port_start(iport); @@ -1061,11 +1049,11 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, return result; } - scic_sds_controller_start_next_phy(scic); + scic_sds_controller_start_next_phy(ihost); - sci_mod_timer(&scic->timer, timeout); + sci_mod_timer(&ihost->timer, timeout); - sci_change_state(&scic->sm, SCIC_STARTING); + sci_change_state(&ihost->sm, SCIC_STARTING); return SCI_SUCCESS; } @@ -1073,35 +1061,35 @@ static enum sci_status scic_controller_start(struct scic_sds_controller *scic, void isci_host_scan_start(struct Scsi_Host *shost) { struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha; - unsigned long tmo = scic_controller_get_suggested_start_timeout(&ihost->sci); + unsigned long tmo = scic_controller_get_suggested_start_timeout(ihost); set_bit(IHOST_START_PENDING, &ihost->flags); spin_lock_irq(&ihost->scic_lock); - scic_controller_start(&ihost->sci, tmo); - scic_controller_enable_interrupts(&ihost->sci); + scic_controller_start(ihost, tmo); + scic_controller_enable_interrupts(ihost); spin_unlock_irq(&ihost->scic_lock); } static void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) { isci_host_change_state(ihost, isci_stopped); - scic_controller_disable_interrupts(&ihost->sci); + scic_controller_disable_interrupts(ihost); clear_bit(IHOST_STOP_PENDING, &ihost->flags); wake_up(&ihost->eventq); } -static void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) +static void scic_sds_controller_completion_handler(struct isci_host *ihost) { /* Empty out the completion queue */ - if (scic_sds_controller_completion_queue_has_entries(scic)) - scic_sds_controller_process_completions(scic); + if (scic_sds_controller_completion_queue_has_entries(ihost)) + scic_sds_controller_process_completions(ihost); /* Clear the interrupt and enable all interrupts again */ - writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status); + writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status); /* Could we write the value of SMU_ISR_COMPLETION? */ - writel(0xFF000000, &scic->smu_registers->interrupt_mask); - writel(0, &scic->smu_registers->interrupt_mask); + writel(0xFF000000, &ihost->smu_registers->interrupt_mask); + writel(0, &ihost->smu_registers->interrupt_mask); } /** @@ -1114,7 +1102,7 @@ static void scic_sds_controller_completion_handler(struct scic_sds_controller *s */ static void isci_host_completion_routine(unsigned long data) { - struct isci_host *isci_host = (struct isci_host *)data; + struct isci_host *ihost = (struct isci_host *)data; struct list_head completed_request_list; struct list_head errored_request_list; struct list_head *current_position; @@ -1126,20 +1114,20 @@ static void isci_host_completion_routine(unsigned long data) INIT_LIST_HEAD(&completed_request_list); INIT_LIST_HEAD(&errored_request_list); - spin_lock_irq(&isci_host->scic_lock); + spin_lock_irq(&ihost->scic_lock); - scic_sds_controller_completion_handler(&isci_host->sci); + scic_sds_controller_completion_handler(ihost); /* Take the lists of completed I/Os from the host. */ - list_splice_init(&isci_host->requests_to_complete, + list_splice_init(&ihost->requests_to_complete, &completed_request_list); /* Take the list of errored I/Os from the host. */ - list_splice_init(&isci_host->requests_to_errorback, + list_splice_init(&ihost->requests_to_errorback, &errored_request_list); - spin_unlock_irq(&isci_host->scic_lock); + spin_unlock_irq(&ihost->scic_lock); /* Process any completions in the lists. */ list_for_each_safe(current_position, next_position, @@ -1150,7 +1138,7 @@ static void isci_host_completion_routine(unsigned long data) task = isci_request_access_task(request); /* Normal notification (task_done) */ - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: Normal - request/task = %p/%p\n", __func__, request, @@ -1169,9 +1157,9 @@ static void isci_host_completion_routine(unsigned long data) } } - spin_lock_irq(&isci_host->scic_lock); - isci_free_tag(isci_host, request->io_tag); - spin_unlock_irq(&isci_host->scic_lock); + spin_lock_irq(&ihost->scic_lock); + isci_free_tag(ihost, request->io_tag); + spin_unlock_irq(&ihost->scic_lock); } list_for_each_entry_safe(request, next_request, &errored_request_list, completed_node) { @@ -1179,7 +1167,7 @@ static void isci_host_completion_routine(unsigned long data) task = isci_request_access_task(request); /* Use sas_task_abort */ - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: Error - request/task = %p/%p\n", __func__, request, @@ -1202,13 +1190,13 @@ static void isci_host_completion_routine(unsigned long data) * it. */ - spin_lock_irq(&isci_host->scic_lock); + spin_lock_irq(&ihost->scic_lock); /* Remove the request from the remote device's list * of pending requests. */ list_del_init(&request->dev_node); - isci_free_tag(isci_host, request->io_tag); - spin_unlock_irq(&isci_host->scic_lock); + isci_free_tag(ihost, request->io_tag); + spin_unlock_irq(&ihost->scic_lock); } } @@ -1232,18 +1220,18 @@ static void isci_host_completion_routine(unsigned long data) * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the * controller is not either in the STARTED or STOPPED states. */ -static enum sci_status scic_controller_stop(struct scic_sds_controller *scic, +static enum sci_status scic_controller_stop(struct isci_host *ihost, u32 timeout) { - if (scic->sm.current_state_id != SCIC_READY) { - dev_warn(scic_to_dev(scic), + if (ihost->sm.current_state_id != SCIC_READY) { + dev_warn(&ihost->pdev->dev, "SCIC Controller stop operation requested in " "invalid state\n"); return SCI_FAILURE_INVALID_STATE; } - sci_mod_timer(&scic->timer, timeout); - sci_change_state(&scic->sm, SCIC_STOPPING); + sci_mod_timer(&ihost->timer, timeout); + sci_change_state(&ihost->sm, SCIC_STOPPING); return SCI_SUCCESS; } @@ -1259,9 +1247,9 @@ static enum sci_status scic_controller_stop(struct scic_sds_controller *scic, * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if * the controller reset operation is unable to complete. */ -static enum sci_status scic_controller_reset(struct scic_sds_controller *scic) +static enum sci_status scic_controller_reset(struct isci_host *ihost) { - switch (scic->sm.current_state_id) { + switch (ihost->sm.current_state_id) { case SCIC_RESET: case SCIC_READY: case SCIC_STOPPED: @@ -1270,10 +1258,10 @@ static enum sci_status scic_controller_reset(struct scic_sds_controller *scic) * The reset operation is not a graceful cleanup, just * perform the state transition. */ - sci_change_state(&scic->sm, SCIC_RESETTING); + sci_change_state(&ihost->sm, SCIC_RESETTING); return SCI_SUCCESS; default: - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "SCIC Controller reset operation requested in " "invalid state\n"); return SCI_FAILURE_INVALID_STATE; @@ -1298,14 +1286,14 @@ void isci_host_deinit(struct isci_host *ihost) set_bit(IHOST_STOP_PENDING, &ihost->flags); spin_lock_irq(&ihost->scic_lock); - scic_controller_stop(&ihost->sci, SCIC_CONTROLLER_STOP_TIMEOUT); + scic_controller_stop(ihost, SCIC_CONTROLLER_STOP_TIMEOUT); spin_unlock_irq(&ihost->scic_lock); wait_for_stop(ihost); - scic_controller_reset(&ihost->sci); + scic_controller_reset(ihost); /* Cancel any/all outstanding port timers */ - for (i = 0; i < ihost->sci.logical_port_entries; i++) { + for (i = 0; i < ihost->logical_port_entries; i++) { struct isci_port *iport = &ihost->ports[i]; del_timer_sync(&iport->timer.timer); } @@ -1316,13 +1304,13 @@ void isci_host_deinit(struct isci_host *ihost) del_timer_sync(&iphy->sata_timer.timer); } - del_timer_sync(&ihost->sci.port_agent.timer.timer); + del_timer_sync(&ihost->port_agent.timer.timer); - del_timer_sync(&ihost->sci.power_control.timer.timer); + del_timer_sync(&ihost->power_control.timer.timer); - del_timer_sync(&ihost->sci.timer.timer); + del_timer_sync(&ihost->timer.timer); - del_timer_sync(&ihost->sci.phy_timer.timer); + del_timer_sync(&ihost->phy_timer.timer); } static void __iomem *scu_base(struct isci_host *isci_host) @@ -1369,16 +1357,16 @@ static void isci_user_parameters_get( static void scic_sds_controller_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); + struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); - sci_change_state(&scic->sm, SCIC_RESET); + sci_change_state(&ihost->sm, SCIC_RESET); } static inline void scic_sds_controller_starting_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); + struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); - sci_del_timer(&scic->timer); + sci_del_timer(&ihost->timer); } #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853 @@ -1405,10 +1393,10 @@ static inline void scic_sds_controller_starting_state_exit(struct sci_base_state * SCI_SUCCESS The user successfully updated the interrutp coalescence. * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range. */ -static enum sci_status scic_controller_set_interrupt_coalescence( - struct scic_sds_controller *scic_controller, - u32 coalesce_number, - u32 coalesce_timeout) +static enum sci_status +scic_controller_set_interrupt_coalescence(struct isci_host *ihost, + u32 coalesce_number, + u32 coalesce_timeout) { u8 timeout_encode = 0; u32 min = 0; @@ -1491,11 +1479,11 @@ static enum sci_status scic_controller_set_interrupt_coalescence( writel(SMU_ICC_GEN_VAL(NUMBER, coalesce_number) | SMU_ICC_GEN_VAL(TIMER, timeout_encode), - &scic_controller->smu_registers->interrupt_coalesce_control); + &ihost->smu_registers->interrupt_coalesce_control); - scic_controller->interrupt_coalesce_number = (u16)coalesce_number; - scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100; + ihost->interrupt_coalesce_number = (u16)coalesce_number; + ihost->interrupt_coalesce_timeout = coalesce_timeout / 100; return SCI_SUCCESS; } @@ -1503,26 +1491,25 @@ static enum sci_status scic_controller_set_interrupt_coalescence( static void scic_sds_controller_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); + struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); /* set the default interrupt coalescence number and timeout value. */ - scic_controller_set_interrupt_coalescence(scic, 0x10, 250); + scic_controller_set_interrupt_coalescence(ihost, 0x10, 250); } static void scic_sds_controller_ready_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); + struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); /* disable interrupt coalescence. */ - scic_controller_set_interrupt_coalescence(scic, 0, 0); + scic_controller_set_interrupt_coalescence(ihost, 0, 0); } -static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller *scic) +static enum sci_status scic_sds_controller_stop_phys(struct isci_host *ihost) { u32 index; enum sci_status status; enum sci_status phy_status; - struct isci_host *ihost = scic_to_ihost(scic); status = SCI_SUCCESS; @@ -1533,7 +1520,7 @@ static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller phy_status != SCI_FAILURE_INVALID_STATE) { status = SCI_FAILURE; - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: Controller stop operation failed to stop " "phy %d because of status %d.\n", __func__, @@ -1544,14 +1531,13 @@ static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller return status; } -static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) +static enum sci_status scic_sds_controller_stop_ports(struct isci_host *ihost) { u32 index; enum sci_status port_status; enum sci_status status = SCI_SUCCESS; - struct isci_host *ihost = scic_to_ihost(scic); - for (index = 0; index < scic->logical_port_entries; index++) { + for (index = 0; index < ihost->logical_port_entries; index++) { struct isci_port *iport = &ihost->ports[index]; port_status = scic_sds_port_stop(iport); @@ -1560,7 +1546,7 @@ static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller (port_status != SCI_FAILURE_INVALID_STATE)) { status = SCI_FAILURE; - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: Controller stop operation failed to " "stop port %d because of status %d.\n", __func__, @@ -1572,7 +1558,7 @@ static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller return status; } -static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controller *scic) +static enum sci_status scic_sds_controller_stop_devices(struct isci_host *ihost) { u32 index; enum sci_status status; @@ -1580,19 +1566,19 @@ static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controll status = SCI_SUCCESS; - for (index = 0; index < scic->remote_node_entries; index++) { - if (scic->device_table[index] != NULL) { + for (index = 0; index < ihost->remote_node_entries; index++) { + if (ihost->device_table[index] != NULL) { /* / @todo What timeout value do we want to provide to this request? */ - device_status = scic_remote_device_stop(scic->device_table[index], 0); + device_status = scic_remote_device_stop(ihost->device_table[index], 0); if ((device_status != SCI_SUCCESS) && (device_status != SCI_FAILURE_INVALID_STATE)) { - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: Controller stop operation failed " "to stop device 0x%p because of " "status %d.\n", __func__, - scic->device_table[index], device_status); + ihost->device_table[index], device_status); } } } @@ -1602,19 +1588,19 @@ static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controll static void scic_sds_controller_stopping_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); + struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); /* Stop all of the components for this controller */ - scic_sds_controller_stop_phys(scic); - scic_sds_controller_stop_ports(scic); - scic_sds_controller_stop_devices(scic); + scic_sds_controller_stop_phys(ihost); + scic_sds_controller_stop_ports(ihost); + scic_sds_controller_stop_devices(ihost); } static void scic_sds_controller_stopping_state_exit(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); + struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); - sci_del_timer(&scic->timer); + sci_del_timer(&ihost->timer); } @@ -1623,30 +1609,30 @@ static void scic_sds_controller_stopping_state_exit(struct sci_base_state_machin * * This method will reset the controller hardware. */ -static void scic_sds_controller_reset_hardware(struct scic_sds_controller *scic) +static void scic_sds_controller_reset_hardware(struct isci_host *ihost) { /* Disable interrupts so we dont take any spurious interrupts */ - scic_controller_disable_interrupts(scic); + scic_controller_disable_interrupts(ihost); /* Reset the SCU */ - writel(0xFFFFFFFF, &scic->smu_registers->soft_reset_control); + writel(0xFFFFFFFF, &ihost->smu_registers->soft_reset_control); /* Delay for 1ms to before clearing the CQP and UFQPR. */ udelay(1000); /* The write to the CQGR clears the CQP */ - writel(0x00000000, &scic->smu_registers->completion_queue_get); + writel(0x00000000, &ihost->smu_registers->completion_queue_get); /* The write to the UFQGP clears the UFQPR */ - writel(0, &scic->scu_registers->sdma.unsolicited_frame_get_pointer); + writel(0, &ihost->scu_registers->sdma.unsolicited_frame_get_pointer); } static void scic_sds_controller_resetting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_controller *scic = container_of(sm, typeof(*scic), sm); + struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); - scic_sds_controller_reset_hardware(scic); - sci_change_state(&scic->sm, SCIC_RESET); + scic_sds_controller_reset_hardware(ihost); + sci_change_state(&ihost->sm, SCIC_RESET); } static const struct sci_base_state scic_sds_controller_state_table[] = { @@ -1674,58 +1660,56 @@ static const struct sci_base_state scic_sds_controller_state_table[] = { [SCIC_FAILED] = {} }; -static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) +static void scic_sds_controller_set_default_config_parameters(struct isci_host *ihost) { /* these defaults are overridden by the platform / firmware */ - struct isci_host *ihost = scic_to_ihost(scic); u16 index; /* Default to APC mode. */ - scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; + ihost->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; /* Default to APC mode. */ - scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1; + ihost->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1; /* Default to no SSC operation. */ - scic->oem_parameters.sds1.controller.do_enable_ssc = false; + ihost->oem_parameters.sds1.controller.do_enable_ssc = false; /* Initialize all of the port parameter information to narrow ports. */ for (index = 0; index < SCI_MAX_PORTS; index++) { - scic->oem_parameters.sds1.ports[index].phy_mask = 0; + ihost->oem_parameters.sds1.ports[index].phy_mask = 0; } /* Initialize all of the phy parameter information. */ for (index = 0; index < SCI_MAX_PHYS; index++) { /* Default to 6G (i.e. Gen 3) for now. */ - scic->user_parameters.sds1.phys[index].max_speed_generation = 3; + ihost->user_parameters.sds1.phys[index].max_speed_generation = 3; /* the frequencies cannot be 0 */ - scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f; - scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff; - scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; + ihost->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f; + ihost->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff; + ihost->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; /* * Previous Vitesse based expanders had a arbitration issue that * is worked around by having the upper 32-bits of SAS address * with a value greater then the Vitesse company identifier. * Hence, usage of 0x5FCFFFFF. */ - scic->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id; - scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF; + ihost->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id; + ihost->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF; } - scic->user_parameters.sds1.stp_inactivity_timeout = 5; - scic->user_parameters.sds1.ssp_inactivity_timeout = 5; - scic->user_parameters.sds1.stp_max_occupancy_timeout = 5; - scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20; - scic->user_parameters.sds1.no_outbound_task_timeout = 20; + ihost->user_parameters.sds1.stp_inactivity_timeout = 5; + ihost->user_parameters.sds1.ssp_inactivity_timeout = 5; + ihost->user_parameters.sds1.stp_max_occupancy_timeout = 5; + ihost->user_parameters.sds1.ssp_max_occupancy_timeout = 20; + ihost->user_parameters.sds1.no_outbound_task_timeout = 20; } static void controller_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; - struct scic_sds_controller *scic = container_of(tmr, typeof(*scic), timer); - struct isci_host *ihost = scic_to_ihost(scic); - struct sci_base_state_machine *sm = &scic->sm; + struct isci_host *ihost = container_of(tmr, typeof(*ihost), timer); + struct sci_base_state_machine *sm = &ihost->sm; unsigned long flags; spin_lock_irqsave(&ihost->scic_lock, flags); @@ -1734,12 +1718,12 @@ static void controller_timeout(unsigned long data) goto done; if (sm->current_state_id == SCIC_STARTING) - scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT); + scic_sds_controller_transition_to_ready(ihost, SCI_FAILURE_TIMEOUT); else if (sm->current_state_id == SCIC_STOPPING) { sci_change_state(sm, SCIC_FAILED); isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); } else /* / @todo Now what do we want to do in this case? */ - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: Controller timer fired when controller was not " "in a state being timed.\n", __func__); @@ -1764,24 +1748,23 @@ done: * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the * controller does not support the supplied initialization data version. */ -static enum sci_status scic_controller_construct(struct scic_sds_controller *scic, +static enum sci_status scic_controller_construct(struct isci_host *ihost, void __iomem *scu_base, void __iomem *smu_base) { - struct isci_host *ihost = scic_to_ihost(scic); u8 i; - sci_init_sm(&scic->sm, scic_sds_controller_state_table, SCIC_INITIAL); + sci_init_sm(&ihost->sm, scic_sds_controller_state_table, SCIC_INITIAL); - scic->scu_registers = scu_base; - scic->smu_registers = smu_base; + ihost->scu_registers = scu_base; + ihost->smu_registers = smu_base; - scic_sds_port_configuration_agent_construct(&scic->port_agent); + scic_sds_port_configuration_agent_construct(&ihost->port_agent); /* Construct the ports for this controller */ for (i = 0; i < SCI_MAX_PORTS; i++) - scic_sds_port_construct(&ihost->ports[i], i, scic); - scic_sds_port_construct(&ihost->ports[i], SCIC_SDS_DUMMY_PORT, scic); + scic_sds_port_construct(&ihost->ports[i], i, ihost); + scic_sds_port_construct(&ihost->ports[i], SCIC_SDS_DUMMY_PORT, ihost); /* Construct the phys for this controller */ for (i = 0; i < SCI_MAX_PHYS; i++) { @@ -1790,14 +1773,14 @@ static enum sci_status scic_controller_construct(struct scic_sds_controller *sci &ihost->ports[SCI_MAX_PORTS], i); } - scic->invalid_phy_mask = 0; + ihost->invalid_phy_mask = 0; - sci_init_timer(&scic->timer, controller_timeout); + sci_init_timer(&ihost->timer, controller_timeout); /* Initialize the User and OEM parameters to default values. */ - scic_sds_controller_set_default_config_parameters(scic); + scic_sds_controller_set_default_config_parameters(ihost); - return scic_controller_reset(scic); + return scic_controller_reset(ihost); } int scic_oem_parameters_validate(struct scic_sds_oem_params *oem) @@ -1834,10 +1817,10 @@ int scic_oem_parameters_validate(struct scic_sds_oem_params *oem) return 0; } -static enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic, +static enum sci_status scic_oem_parameters_set(struct isci_host *ihost, union scic_oem_parameters *scic_parms) { - u32 state = scic->sm.current_state_id; + u32 state = ihost->sm.current_state_id; if (state == SCIC_RESET || state == SCIC_INITIALIZING || @@ -1845,7 +1828,7 @@ static enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic, if (scic_oem_parameters_validate(&scic_parms->sds1)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - scic->oem_parameters.sds1 = scic_parms->sds1; + ihost->oem_parameters.sds1 = scic_parms->sds1; return SCI_SUCCESS; } @@ -1854,17 +1837,16 @@ static enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic, } void scic_oem_parameters_get( - struct scic_sds_controller *scic, + struct isci_host *ihost, union scic_oem_parameters *scic_parms) { - memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms)); + memcpy(scic_parms, (&ihost->oem_parameters), sizeof(*scic_parms)); } static void power_control_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; - struct scic_sds_controller *scic = container_of(tmr, typeof(*scic), power_control.timer); - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = container_of(tmr, typeof(*ihost), power_control.timer); struct isci_phy *iphy; unsigned long flags; u8 i; @@ -1874,29 +1856,29 @@ static void power_control_timeout(unsigned long data) if (tmr->cancel) goto done; - scic->power_control.phys_granted_power = 0; + ihost->power_control.phys_granted_power = 0; - if (scic->power_control.phys_waiting == 0) { - scic->power_control.timer_started = false; + if (ihost->power_control.phys_waiting == 0) { + ihost->power_control.timer_started = false; goto done; } for (i = 0; i < SCI_MAX_PHYS; i++) { - if (scic->power_control.phys_waiting == 0) + if (ihost->power_control.phys_waiting == 0) break; - iphy = scic->power_control.requesters[i]; + iphy = ihost->power_control.requesters[i]; if (iphy == NULL) continue; - if (scic->power_control.phys_granted_power >= - scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) + if (ihost->power_control.phys_granted_power >= + ihost->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) break; - scic->power_control.requesters[i] = NULL; - scic->power_control.phys_waiting--; - scic->power_control.phys_granted_power++; + ihost->power_control.requesters[i] = NULL; + ihost->power_control.phys_waiting--; + ihost->power_control.phys_granted_power++; scic_sds_phy_consume_power_handler(iphy); } @@ -1905,7 +1887,7 @@ static void power_control_timeout(unsigned long data) * timer in case another phy becomes ready. */ sci_mod_timer(tmr, SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); - scic->power_control.timer_started = true; + ihost->power_control.timer_started = true; done: spin_unlock_irqrestore(&ihost->scic_lock, flags); @@ -1918,31 +1900,31 @@ done: * */ void scic_sds_controller_power_control_queue_insert( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_phy *iphy) { BUG_ON(iphy == NULL); - if (scic->power_control.phys_granted_power < - scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { - scic->power_control.phys_granted_power++; + if (ihost->power_control.phys_granted_power < + ihost->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { + ihost->power_control.phys_granted_power++; scic_sds_phy_consume_power_handler(iphy); /* * stop and start the power_control timer. When the timer fires, the * no_of_phys_granted_power will be set to 0 */ - if (scic->power_control.timer_started) - sci_del_timer(&scic->power_control.timer); + if (ihost->power_control.timer_started) + sci_del_timer(&ihost->power_control.timer); - sci_mod_timer(&scic->power_control.timer, + sci_mod_timer(&ihost->power_control.timer, SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); - scic->power_control.timer_started = true; + ihost->power_control.timer_started = true; } else { /* Add the phy in the waiting list */ - scic->power_control.requesters[iphy->phy_index] = iphy; - scic->power_control.phys_waiting++; + ihost->power_control.requesters[iphy->phy_index] = iphy; + ihost->power_control.phys_waiting++; } } @@ -1953,16 +1935,16 @@ void scic_sds_controller_power_control_queue_insert( * */ void scic_sds_controller_power_control_queue_remove( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_phy *iphy) { BUG_ON(iphy == NULL); - if (scic->power_control.requesters[iphy->phy_index] != NULL) { - scic->power_control.phys_waiting--; + if (ihost->power_control.requesters[iphy->phy_index] != NULL) { + ihost->power_control.phys_waiting--; } - scic->power_control.requesters[iphy->phy_index] = NULL; + ihost->power_control.requesters[iphy->phy_index] = NULL; } #define AFE_REGISTER_WRITE_DELAY 10 @@ -1970,50 +1952,50 @@ void scic_sds_controller_power_control_queue_remove( /* Initialize the AFE for this phy index. We need to read the AFE setup from * the OEM parameters */ -static void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) +static void scic_sds_controller_afe_initialization(struct isci_host *ihost) { - const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1; + const struct scic_sds_oem_params *oem = &ihost->oem_parameters.sds1; u32 afe_status; u32 phy_id; /* Clear DFX Status registers */ - writel(0x0081000f, &scic->scu_registers->afe.afe_dfx_master_control0); + writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); if (is_b0()) { /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement * Timer, PM Stagger Timer */ - writel(0x0007BFFF, &scic->scu_registers->afe.afe_pmsn_master_control2); + writel(0x0007BFFF, &ihost->scu_registers->afe.afe_pmsn_master_control2); udelay(AFE_REGISTER_WRITE_DELAY); } /* Configure bias currents to normal */ if (is_a0()) - writel(0x00005500, &scic->scu_registers->afe.afe_bias_control); + writel(0x00005500, &ihost->scu_registers->afe.afe_bias_control); else if (is_a2()) - writel(0x00005A00, &scic->scu_registers->afe.afe_bias_control); + writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control); else if (is_b0() || is_c0()) - writel(0x00005F00, &scic->scu_registers->afe.afe_bias_control); + writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable PLL */ if (is_b0() || is_c0()) - writel(0x80040A08, &scic->scu_registers->afe.afe_pll_control0); + writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0); else - writel(0x80040908, &scic->scu_registers->afe.afe_pll_control0); + writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Wait for the PLL to lock */ do { - afe_status = readl(&scic->scu_registers->afe.afe_common_block_status); + afe_status = readl(&ihost->scu_registers->afe.afe_common_block_status); udelay(AFE_REGISTER_WRITE_DELAY); } while ((afe_status & 0x00001000) == 0); if (is_a0() || is_a2()) { /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ - writel(0x7bcc96ad, &scic->scu_registers->afe.afe_pmsn_master_control0); + writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); } @@ -2022,26 +2004,26 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s if (is_b0()) { /* Configure transmitter SSC parameters */ - writel(0x00030000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); + writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); } else if (is_c0()) { /* Configure transmitter SSC parameters */ - writel(0x0003000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); + writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); /* * All defaults, except the Receive Word Alignament/Comma Detect * Enable....(0xe800) */ - writel(0x00004500, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + writel(0x00004500, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); } else { /* * All defaults, except the Receive Word Alignament/Comma Detect * Enable....(0xe800) */ - writel(0x00004512, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + writel(0x00004512, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); - writel(0x0050100F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1); + writel(0x0050100F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1); udelay(AFE_REGISTER_WRITE_DELAY); } @@ -2049,106 +2031,105 @@ static void scic_sds_controller_afe_initialization(struct scic_sds_controller *s * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) * & increase TX int & ext bias 20%....(0xe85c) */ if (is_a0()) - writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); else if (is_a2()) - writel(0x000003F0, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000003F0, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); else if (is_b0()) { /* Power down TX and RX (PWRDNTX and PWRDNRX) */ - writel(0x000003D7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); /* * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) * & increase TX int & ext bias 20%....(0xe85c) */ - writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); } else { - writel(0x000001E7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000001E7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); /* * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) * & increase TX int & ext bias 20%....(0xe85c) */ - writel(0x000001E4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000001E4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); } udelay(AFE_REGISTER_WRITE_DELAY); if (is_a0() || is_a2()) { /* Enable TX equalization (0xe824) */ - writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); udelay(AFE_REGISTER_WRITE_DELAY); } /* * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On), * RDD=0x0(RX Detect Enabled) ....(0xe800) */ - writel(0x00004100, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + writel(0x00004100, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Leave DFE/FFE on */ if (is_a0()) - writel(0x3F09983F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + writel(0x3F09983F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); else if (is_a2()) - writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); else if (is_b0()) { - writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable TX equalization (0xe824) */ - writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); } else { - writel(0x0140DF0F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control1); + writel(0x0140DF0F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control1); udelay(AFE_REGISTER_WRITE_DELAY); - writel(0x3F6F103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + writel(0x3F6F103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable TX equalization (0xe824) */ - writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); } udelay(AFE_REGISTER_WRITE_DELAY); writel(oem_phy->afe_tx_amp_control0, - &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0); + &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0); udelay(AFE_REGISTER_WRITE_DELAY); writel(oem_phy->afe_tx_amp_control1, - &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1); + &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1); udelay(AFE_REGISTER_WRITE_DELAY); writel(oem_phy->afe_tx_amp_control2, - &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2); + &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2); udelay(AFE_REGISTER_WRITE_DELAY); writel(oem_phy->afe_tx_amp_control3, - &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3); + &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3); udelay(AFE_REGISTER_WRITE_DELAY); } /* Transfer control to the PEs */ - writel(0x00010f00, &scic->scu_registers->afe.afe_dfx_master_control0); + writel(0x00010f00, &ihost->scu_registers->afe.afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); } -static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic) +static void scic_sds_controller_initialize_power_control(struct isci_host *ihost) { - sci_init_timer(&scic->power_control.timer, power_control_timeout); + sci_init_timer(&ihost->power_control.timer, power_control_timeout); - memset(scic->power_control.requesters, 0, - sizeof(scic->power_control.requesters)); + memset(ihost->power_control.requesters, 0, + sizeof(ihost->power_control.requesters)); - scic->power_control.phys_waiting = 0; - scic->power_control.phys_granted_power = 0; + ihost->power_control.phys_waiting = 0; + ihost->power_control.phys_granted_power = 0; } -static enum sci_status scic_controller_initialize(struct scic_sds_controller *scic) +static enum sci_status scic_controller_initialize(struct isci_host *ihost) { - struct sci_base_state_machine *sm = &scic->sm; - struct isci_host *ihost = scic_to_ihost(scic); + struct sci_base_state_machine *sm = &ihost->sm; enum sci_status result = SCI_FAILURE; unsigned long i, state, val; - if (scic->sm.current_state_id != SCIC_RESET) { - dev_warn(scic_to_dev(scic), + if (ihost->sm.current_state_id != SCIC_RESET) { + dev_warn(&ihost->pdev->dev, "SCIC Controller initialize operation requested " "in invalid state\n"); return SCI_FAILURE_INVALID_STATE; @@ -2156,23 +2137,23 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc sci_change_state(sm, SCIC_INITIALIZING); - sci_init_timer(&scic->phy_timer, phy_startup_timeout); + sci_init_timer(&ihost->phy_timer, phy_startup_timeout); - scic->next_phy_to_start = 0; - scic->phy_startup_timer_pending = false; + ihost->next_phy_to_start = 0; + ihost->phy_startup_timer_pending = false; - scic_sds_controller_initialize_power_control(scic); + scic_sds_controller_initialize_power_control(ihost); /* * There is nothing to do here for B0 since we do not have to * program the AFE registers. * / @todo The AFE settings are supposed to be correct for the B0 but * / presently they seem to be wrong. */ - scic_sds_controller_afe_initialization(scic); + scic_sds_controller_afe_initialization(ihost); /* Take the hardware out of reset */ - writel(0, &scic->smu_registers->soft_reset_control); + writel(0, &ihost->smu_registers->soft_reset_control); /* * / @todo Provide meaningfull error code for hardware failure @@ -2182,7 +2163,7 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc /* Loop until the hardware reports success */ udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME); - status = readl(&scic->smu_registers->control_status); + status = readl(&ihost->smu_registers->control_status); if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) break; @@ -2193,32 +2174,32 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc /* * Determine what are the actaul device capacities that the * hardware will support */ - val = readl(&scic->smu_registers->device_context_capacity); + val = readl(&ihost->smu_registers->device_context_capacity); /* Record the smaller of the two capacity values */ - scic->logical_port_entries = min(smu_max_ports(val), SCI_MAX_PORTS); - scic->task_context_entries = min(smu_max_task_contexts(val), SCI_MAX_IO_REQUESTS); - scic->remote_node_entries = min(smu_max_rncs(val), SCI_MAX_REMOTE_DEVICES); + ihost->logical_port_entries = min(smu_max_ports(val), SCI_MAX_PORTS); + ihost->task_context_entries = min(smu_max_task_contexts(val), SCI_MAX_IO_REQUESTS); + ihost->remote_node_entries = min(smu_max_rncs(val), SCI_MAX_REMOTE_DEVICES); /* * Make all PEs that are unassigned match up with the * logical ports */ - for (i = 0; i < scic->logical_port_entries; i++) { + for (i = 0; i < ihost->logical_port_entries; i++) { struct scu_port_task_scheduler_group_registers __iomem - *ptsg = &scic->scu_registers->peg0.ptsg; + *ptsg = &ihost->scu_registers->peg0.ptsg; writel(i, &ptsg->protocol_engine[i]); } /* Initialize hardware PCI Relaxed ordering in DMA engines */ - val = readl(&scic->scu_registers->sdma.pdma_configuration); + val = readl(&ihost->scu_registers->sdma.pdma_configuration); val |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - writel(val, &scic->scu_registers->sdma.pdma_configuration); + writel(val, &ihost->scu_registers->sdma.pdma_configuration); - val = readl(&scic->scu_registers->sdma.cdma_configuration); + val = readl(&ihost->scu_registers->sdma.cdma_configuration); val |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); - writel(val, &scic->scu_registers->sdma.cdma_configuration); + writel(val, &ihost->scu_registers->sdma.cdma_configuration); /* * Initialize the PHYs before the PORTs because the PHY registers @@ -2226,23 +2207,23 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc */ for (i = 0; i < SCI_MAX_PHYS; i++) { result = scic_sds_phy_initialize(&ihost->phys[i], - &scic->scu_registers->peg0.pe[i].tl, - &scic->scu_registers->peg0.pe[i].ll); + &ihost->scu_registers->peg0.pe[i].tl, + &ihost->scu_registers->peg0.pe[i].ll); if (result != SCI_SUCCESS) goto out; } - for (i = 0; i < scic->logical_port_entries; i++) { + for (i = 0; i < ihost->logical_port_entries; i++) { result = scic_sds_port_initialize(&ihost->ports[i], - &scic->scu_registers->peg0.ptsg.port[i], - &scic->scu_registers->peg0.ptsg.protocol_engine, - &scic->scu_registers->peg0.viit[i]); + &ihost->scu_registers->peg0.ptsg.port[i], + &ihost->scu_registers->peg0.ptsg.protocol_engine, + &ihost->scu_registers->peg0.viit[i]); if (result != SCI_SUCCESS) goto out; } - result = scic_sds_port_configuration_agent_initialize(scic, &scic->port_agent); + result = scic_sds_port_configuration_agent_initialize(ihost, &ihost->port_agent); out: /* Advance the controller state machine */ @@ -2256,10 +2237,10 @@ static enum sci_status scic_controller_initialize(struct scic_sds_controller *sc } static enum sci_status scic_user_parameters_set( - struct scic_sds_controller *scic, + struct isci_host *ihost, union scic_user_parameters *scic_parms) { - u32 state = scic->sm.current_state_id; + u32 state = ihost->sm.current_state_id; if (state == SCIC_RESET || state == SCIC_INITIALIZING || @@ -2301,7 +2282,7 @@ static enum sci_status scic_user_parameters_set( (scic_parms->sds1.no_outbound_task_timeout == 0)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms)); + memcpy(&ihost->user_parameters, scic_parms, sizeof(*scic_parms)); return SCI_SUCCESS; } @@ -2309,40 +2290,40 @@ static enum sci_status scic_user_parameters_set( return SCI_FAILURE_INVALID_STATE; } -static int scic_controller_mem_init(struct scic_sds_controller *scic) +static int scic_controller_mem_init(struct isci_host *ihost) { - struct device *dev = scic_to_dev(scic); + struct device *dev = &ihost->pdev->dev; dma_addr_t dma; size_t size; int err; size = SCU_MAX_COMPLETION_QUEUE_ENTRIES * sizeof(u32); - scic->completion_queue = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); - if (!scic->completion_queue) + ihost->completion_queue = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); + if (!ihost->completion_queue) return -ENOMEM; - writel(lower_32_bits(dma), &scic->smu_registers->completion_queue_lower); - writel(upper_32_bits(dma), &scic->smu_registers->completion_queue_upper); + writel(lower_32_bits(dma), &ihost->smu_registers->completion_queue_lower); + writel(upper_32_bits(dma), &ihost->smu_registers->completion_queue_upper); - size = scic->remote_node_entries * sizeof(union scu_remote_node_context); - scic->remote_node_context_table = dmam_alloc_coherent(dev, size, &dma, + size = ihost->remote_node_entries * sizeof(union scu_remote_node_context); + ihost->remote_node_context_table = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); - if (!scic->remote_node_context_table) + if (!ihost->remote_node_context_table) return -ENOMEM; - writel(lower_32_bits(dma), &scic->smu_registers->remote_node_context_lower); - writel(upper_32_bits(dma), &scic->smu_registers->remote_node_context_upper); + writel(lower_32_bits(dma), &ihost->smu_registers->remote_node_context_lower); + writel(upper_32_bits(dma), &ihost->smu_registers->remote_node_context_upper); - size = scic->task_context_entries * sizeof(struct scu_task_context), - scic->task_context_table = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); - if (!scic->task_context_table) + size = ihost->task_context_entries * sizeof(struct scu_task_context), + ihost->task_context_table = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); + if (!ihost->task_context_table) return -ENOMEM; - scic->task_context_dma = dma; - writel(lower_32_bits(dma), &scic->smu_registers->host_task_table_lower); - writel(upper_32_bits(dma), &scic->smu_registers->host_task_table_upper); + ihost->task_context_dma = dma; + writel(lower_32_bits(dma), &ihost->smu_registers->host_task_table_lower); + writel(upper_32_bits(dma), &ihost->smu_registers->host_task_table_upper); - err = scic_sds_unsolicited_frame_control_construct(scic); + err = scic_sds_unsolicited_frame_control_construct(ihost); if (err) return err; @@ -2350,112 +2331,112 @@ static int scic_controller_mem_init(struct scic_sds_controller *scic) * Inform the silicon as to the location of the UF headers and * address table. */ - writel(lower_32_bits(scic->uf_control.headers.physical_address), - &scic->scu_registers->sdma.uf_header_base_address_lower); - writel(upper_32_bits(scic->uf_control.headers.physical_address), - &scic->scu_registers->sdma.uf_header_base_address_upper); + writel(lower_32_bits(ihost->uf_control.headers.physical_address), + &ihost->scu_registers->sdma.uf_header_base_address_lower); + writel(upper_32_bits(ihost->uf_control.headers.physical_address), + &ihost->scu_registers->sdma.uf_header_base_address_upper); - writel(lower_32_bits(scic->uf_control.address_table.physical_address), - &scic->scu_registers->sdma.uf_address_table_lower); - writel(upper_32_bits(scic->uf_control.address_table.physical_address), - &scic->scu_registers->sdma.uf_address_table_upper); + writel(lower_32_bits(ihost->uf_control.address_table.physical_address), + &ihost->scu_registers->sdma.uf_address_table_lower); + writel(upper_32_bits(ihost->uf_control.address_table.physical_address), + &ihost->scu_registers->sdma.uf_address_table_upper); return 0; } -int isci_host_init(struct isci_host *isci_host) +int isci_host_init(struct isci_host *ihost) { int err = 0, i; enum sci_status status; union scic_oem_parameters oem; union scic_user_parameters scic_user_params; - struct isci_pci_info *pci_info = to_pci_info(isci_host->pdev); + struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); - spin_lock_init(&isci_host->state_lock); - spin_lock_init(&isci_host->scic_lock); - init_waitqueue_head(&isci_host->eventq); + spin_lock_init(&ihost->state_lock); + spin_lock_init(&ihost->scic_lock); + init_waitqueue_head(&ihost->eventq); - isci_host_change_state(isci_host, isci_starting); + isci_host_change_state(ihost, isci_starting); - status = scic_controller_construct(&isci_host->sci, scu_base(isci_host), - smu_base(isci_host)); + status = scic_controller_construct(ihost, scu_base(ihost), + smu_base(ihost)); if (status != SCI_SUCCESS) { - dev_err(&isci_host->pdev->dev, + dev_err(&ihost->pdev->dev, "%s: scic_controller_construct failed - status = %x\n", __func__, status); return -ENODEV; } - isci_host->sas_ha.dev = &isci_host->pdev->dev; - isci_host->sas_ha.lldd_ha = isci_host; + ihost->sas_ha.dev = &ihost->pdev->dev; + ihost->sas_ha.lldd_ha = ihost; /* * grab initial values stored in the controller object for OEM and USER * parameters */ - isci_user_parameters_get(isci_host, &scic_user_params); - status = scic_user_parameters_set(&isci_host->sci, + isci_user_parameters_get(ihost, &scic_user_params); + status = scic_user_parameters_set(ihost, &scic_user_params); if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: scic_user_parameters_set failed\n", __func__); return -ENODEV; } - scic_oem_parameters_get(&isci_host->sci, &oem); + scic_oem_parameters_get(ihost, &oem); /* grab any OEM parameters specified in orom */ if (pci_info->orom) { status = isci_parse_oem_parameters(&oem, pci_info->orom, - isci_host->id); + ihost->id); if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "parsing firmware oem parameters failed\n"); return -EINVAL; } } - status = scic_oem_parameters_set(&isci_host->sci, &oem); + status = scic_oem_parameters_set(ihost, &oem); if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: scic_oem_parameters_set failed\n", __func__); return -ENODEV; } - tasklet_init(&isci_host->completion_tasklet, - isci_host_completion_routine, (unsigned long)isci_host); + tasklet_init(&ihost->completion_tasklet, + isci_host_completion_routine, (unsigned long)ihost); - INIT_LIST_HEAD(&isci_host->requests_to_complete); - INIT_LIST_HEAD(&isci_host->requests_to_errorback); + INIT_LIST_HEAD(&ihost->requests_to_complete); + INIT_LIST_HEAD(&ihost->requests_to_errorback); - spin_lock_irq(&isci_host->scic_lock); - status = scic_controller_initialize(&isci_host->sci); - spin_unlock_irq(&isci_host->scic_lock); + spin_lock_irq(&ihost->scic_lock); + status = scic_controller_initialize(ihost); + spin_unlock_irq(&ihost->scic_lock); if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: scic_controller_initialize failed -" " status = 0x%x\n", __func__, status); return -ENODEV; } - err = scic_controller_mem_init(&isci_host->sci); + err = scic_controller_mem_init(ihost); if (err) return err; for (i = 0; i < SCI_MAX_PORTS; i++) - isci_port_init(&isci_host->ports[i], isci_host, i); + isci_port_init(&ihost->ports[i], ihost, i); for (i = 0; i < SCI_MAX_PHYS; i++) - isci_phy_init(&isci_host->phys[i], isci_host, i); + isci_phy_init(&ihost->phys[i], ihost, i); for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { - struct isci_remote_device *idev = &isci_host->devices[i]; + struct isci_remote_device *idev = &ihost->devices[i]; INIT_LIST_HEAD(&idev->reqs_in_process); INIT_LIST_HEAD(&idev->node); @@ -2465,63 +2446,62 @@ int isci_host_init(struct isci_host *isci_host) struct isci_request *ireq; dma_addr_t dma; - ireq = dmam_alloc_coherent(&isci_host->pdev->dev, + ireq = dmam_alloc_coherent(&ihost->pdev->dev, sizeof(struct isci_request), &dma, GFP_KERNEL); if (!ireq) return -ENOMEM; - ireq->tc = &isci_host->sci.task_context_table[i]; - ireq->owning_controller = &isci_host->sci; + ireq->tc = &ihost->task_context_table[i]; + ireq->owning_controller = ihost; spin_lock_init(&ireq->state_lock); ireq->request_daddr = dma; - ireq->isci_host = isci_host; - - isci_host->reqs[i] = ireq; + ireq->isci_host = ihost; + ihost->reqs[i] = ireq; } return 0; } -void scic_sds_controller_link_up(struct scic_sds_controller *scic, +void scic_sds_controller_link_up(struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy) { - switch (scic->sm.current_state_id) { + switch (ihost->sm.current_state_id) { case SCIC_STARTING: - sci_del_timer(&scic->phy_timer); - scic->phy_startup_timer_pending = false; - scic->port_agent.link_up_handler(scic, &scic->port_agent, + sci_del_timer(&ihost->phy_timer); + ihost->phy_startup_timer_pending = false; + ihost->port_agent.link_up_handler(ihost, &ihost->port_agent, iport, iphy); - scic_sds_controller_start_next_phy(scic); + scic_sds_controller_start_next_phy(ihost); break; case SCIC_READY: - scic->port_agent.link_up_handler(scic, &scic->port_agent, + ihost->port_agent.link_up_handler(ihost, &ihost->port_agent, iport, iphy); break; default: - dev_dbg(scic_to_dev(scic), + dev_dbg(&ihost->pdev->dev, "%s: SCIC Controller linkup event from phy %d in " "unexpected state %d\n", __func__, iphy->phy_index, - scic->sm.current_state_id); + ihost->sm.current_state_id); } } -void scic_sds_controller_link_down(struct scic_sds_controller *scic, +void scic_sds_controller_link_down(struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy) { - switch (scic->sm.current_state_id) { + switch (ihost->sm.current_state_id) { case SCIC_STARTING: case SCIC_READY: - scic->port_agent.link_down_handler(scic, &scic->port_agent, + ihost->port_agent.link_down_handler(ihost, &ihost->port_agent, iport, iphy); break; default: - dev_dbg(scic_to_dev(scic), + dev_dbg(&ihost->pdev->dev, "%s: SCIC Controller linkdown event from phy %d in " "unexpected state %d\n", __func__, iphy->phy_index, - scic->sm.current_state_id); + ihost->sm.current_state_id); } } @@ -2530,14 +2510,13 @@ void scic_sds_controller_link_down(struct scic_sds_controller *scic, * controller are still in the stopping state. * */ -static bool scic_sds_controller_has_remote_devices_stopping( - struct scic_sds_controller *controller) +static bool scic_sds_controller_has_remote_devices_stopping(struct isci_host *ihost) { u32 index; - for (index = 0; index < controller->remote_node_entries; index++) { - if ((controller->device_table[index] != NULL) && - (controller->device_table[index]->sm.current_state_id == SCI_DEV_STOPPING)) + for (index = 0; index < ihost->remote_node_entries; index++) { + if ((ihost->device_table[index] != NULL) && + (ihost->device_table[index]->sm.current_state_id == SCI_DEV_STOPPING)) return true; } @@ -2548,20 +2527,20 @@ static bool scic_sds_controller_has_remote_devices_stopping( * This method is called by the remote device to inform the controller * object that the remote device has stopped. */ -void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, +void scic_sds_controller_remote_device_stopped(struct isci_host *ihost, struct isci_remote_device *idev) { - if (scic->sm.current_state_id != SCIC_STOPPING) { - dev_dbg(scic_to_dev(scic), + if (ihost->sm.current_state_id != SCIC_STOPPING) { + dev_dbg(&ihost->pdev->dev, "SCIC Controller 0x%p remote device stopped event " "from device 0x%p in unexpected state %d\n", - scic, idev, - scic->sm.current_state_id); + ihost, idev, + ihost->sm.current_state_id); return; } - if (!scic_sds_controller_has_remote_devices_stopping(scic)) { - sci_change_state(&scic->sm, SCIC_STOPPED); + if (!scic_sds_controller_has_remote_devices_stopping(ihost)) { + sci_change_state(&ihost->sm, SCIC_STOPPED); } } @@ -2573,32 +2552,32 @@ void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic, * */ void scic_sds_controller_post_request( - struct scic_sds_controller *scic, + struct isci_host *ihost, u32 request) { - dev_dbg(scic_to_dev(scic), + dev_dbg(&ihost->pdev->dev, "%s: SCIC Controller 0x%p post request 0x%08x\n", __func__, - scic, + ihost, request); - writel(request, &scic->smu_registers->post_context_port); + writel(request, &ihost->smu_registers->post_context_port); } -struct isci_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 io_tag) +struct isci_request *scic_request_by_tag(struct isci_host *ihost, u16 io_tag) { u16 task_index; u16 task_sequence; task_index = ISCI_TAG_TCI(io_tag); - if (task_index < scic->task_context_entries) { - struct isci_request *ireq = scic_to_ihost(scic)->reqs[task_index]; + if (task_index < ihost->task_context_entries) { + struct isci_request *ireq = ihost->reqs[task_index]; if (test_bit(IREQ_ACTIVE, &ireq->flags)) { task_sequence = ISCI_TAG_SEQ(io_tag); - if (task_sequence == scic->io_request_sequence[task_index]) + if (task_sequence == ihost->io_request_sequence[task_index]) return ireq; } } @@ -2621,7 +2600,7 @@ struct isci_request *scic_request_by_tag(struct scic_sds_controller *scic, u16 i * node index available. */ enum sci_status scic_sds_controller_allocate_remote_node_context( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, u16 *node_id) { @@ -2629,11 +2608,11 @@ enum sci_status scic_sds_controller_allocate_remote_node_context( u32 remote_node_count = scic_sds_remote_device_node_count(idev); node_index = scic_sds_remote_node_table_allocate_remote_node( - &scic->available_remote_nodes, remote_node_count + &ihost->available_remote_nodes, remote_node_count ); if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { - scic->device_table[node_index] = idev; + ihost->device_table[node_index] = idev; *node_id = node_index; @@ -2653,17 +2632,17 @@ enum sci_status scic_sds_controller_allocate_remote_node_context( * */ void scic_sds_controller_free_remote_node_context( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, u16 node_id) { u32 remote_node_count = scic_sds_remote_device_node_count(idev); - if (scic->device_table[node_id] == idev) { - scic->device_table[node_id] = NULL; + if (ihost->device_table[node_id] == idev) { + ihost->device_table[node_id] = NULL; scic_sds_remote_node_table_release_remote_node_index( - &scic->available_remote_nodes, remote_node_count, node_id + &ihost->available_remote_nodes, remote_node_count, node_id ); } } @@ -2677,14 +2656,14 @@ void scic_sds_controller_free_remote_node_context( * union scu_remote_node_context* */ union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( - struct scic_sds_controller *scic, + struct isci_host *ihost, u16 node_id ) { if ( - (node_id < scic->remote_node_entries) - && (scic->device_table[node_id] != NULL) + (node_id < ihost->remote_node_entries) + && (ihost->device_table[node_id] != NULL) ) { - return &scic->remote_node_context_table[node_id]; + return &ihost->remote_node_context_table[node_id]; } return NULL; @@ -2722,13 +2701,13 @@ void scic_sds_controller_copy_sata_response( * */ void scic_sds_controller_release_frame( - struct scic_sds_controller *scic, + struct isci_host *ihost, u32 frame_index) { if (scic_sds_unsolicited_frame_control_release_frame( - &scic->uf_control, frame_index) == true) - writel(scic->uf_control.get, - &scic->scu_registers->sdma.unsolicited_frame_get_pointer); + &ihost->uf_control, frame_index) == true) + writel(ihost->uf_control.get, + &ihost->scu_registers->sdma.unsolicited_frame_get_pointer); } void isci_tci_free(struct isci_host *ihost, u16 tci) @@ -2757,7 +2736,7 @@ u16 isci_alloc_tag(struct isci_host *ihost) { if (isci_tci_space(ihost)) { u16 tci = isci_tci_alloc(ihost); - u8 seq = ihost->sci.io_request_sequence[tci]; + u8 seq = ihost->io_request_sequence[tci]; return ISCI_TAG(seq, tci); } @@ -2767,7 +2746,6 @@ u16 isci_alloc_tag(struct isci_host *ihost) enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag) { - struct scic_sds_controller *scic = &ihost->sci; u16 tci = ISCI_TAG_TCI(io_tag); u16 seq = ISCI_TAG_SEQ(io_tag); @@ -2775,8 +2753,8 @@ enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag) if (isci_tci_active(ihost) == 0) return SCI_FAILURE_INVALID_IO_TAG; - if (seq == scic->io_request_sequence[tci]) { - scic->io_request_sequence[tci] = (seq+1) & (SCI_MAX_SEQ-1); + if (seq == ihost->io_request_sequence[tci]) { + ihost->io_request_sequence[tci] = (seq+1) & (SCI_MAX_SEQ-1); isci_tci_free(ihost, tci); @@ -2797,23 +2775,23 @@ enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag) * @io_tag: This parameter specifies a previously allocated IO tag that the * user desires to be utilized for this request. */ -enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, +enum sci_status scic_controller_start_io(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; - if (scic->sm.current_state_id != SCIC_READY) { - dev_warn(scic_to_dev(scic), "invalid state to start I/O"); + if (ihost->sm.current_state_id != SCIC_READY) { + dev_warn(&ihost->pdev->dev, "invalid state to start I/O"); return SCI_FAILURE_INVALID_STATE; } - status = scic_sds_remote_device_start_io(scic, idev, ireq); + status = scic_sds_remote_device_start_io(ihost, idev, ireq); if (status != SCI_SUCCESS) return status; set_bit(IREQ_ACTIVE, &ireq->flags); - scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(ireq)); + scic_sds_controller_post_request(ihost, scic_sds_request_get_post_context(ireq)); return SCI_SUCCESS; } @@ -2834,14 +2812,14 @@ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, * for the request. Determine the failure situations and return values. */ enum sci_status scic_controller_terminate_request( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; - if (scic->sm.current_state_id != SCIC_READY) { - dev_warn(scic_to_dev(scic), + if (ihost->sm.current_state_id != SCIC_READY) { + dev_warn(&ihost->pdev->dev, "invalid state to terminate request\n"); return SCI_FAILURE_INVALID_STATE; } @@ -2854,7 +2832,7 @@ enum sci_status scic_controller_terminate_request( * Utilize the original post context command and or in the POST_TC_ABORT * request sub-type. */ - scic_sds_controller_post_request(scic, + scic_sds_controller_post_request(ihost, scic_sds_request_get_post_context(ireq) | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); return SCI_SUCCESS; @@ -2872,19 +2850,19 @@ enum sci_status scic_controller_terminate_request( * @io_request: the handle to the io request object to complete. */ enum sci_status scic_controller_complete_io( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; u16 index; - switch (scic->sm.current_state_id) { + switch (ihost->sm.current_state_id) { case SCIC_STOPPING: /* XXX: Implement this function */ return SCI_FAILURE; case SCIC_READY: - status = scic_sds_remote_device_complete_io(scic, idev, ireq); + status = scic_sds_remote_device_complete_io(ihost, idev, ireq); if (status != SCI_SUCCESS) return status; @@ -2892,7 +2870,7 @@ enum sci_status scic_controller_complete_io( clear_bit(IREQ_ACTIVE, &ireq->flags); return SCI_SUCCESS; default: - dev_warn(scic_to_dev(scic), "invalid state to complete I/O"); + dev_warn(&ihost->pdev->dev, "invalid state to complete I/O"); return SCI_FAILURE_INVALID_STATE; } @@ -2900,15 +2878,15 @@ enum sci_status scic_controller_complete_io( enum sci_status scic_controller_continue_io(struct isci_request *ireq) { - struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_host *ihost = ireq->owning_controller; - if (scic->sm.current_state_id != SCIC_READY) { - dev_warn(scic_to_dev(scic), "invalid state to continue I/O"); + if (ihost->sm.current_state_id != SCIC_READY) { + dev_warn(&ihost->pdev->dev, "invalid state to continue I/O"); return SCI_FAILURE_INVALID_STATE; } set_bit(IREQ_ACTIVE, &ireq->flags); - scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(ireq)); + scic_sds_controller_post_request(ihost, scic_sds_request_get_post_context(ireq)); return SCI_SUCCESS; } @@ -2922,21 +2900,21 @@ enum sci_status scic_controller_continue_io(struct isci_request *ireq) * @task_request: the handle to the task request object to start. */ enum sci_task_status scic_controller_start_task( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { enum sci_status status; - if (scic->sm.current_state_id != SCIC_READY) { - dev_warn(scic_to_dev(scic), + if (ihost->sm.current_state_id != SCIC_READY) { + dev_warn(&ihost->pdev->dev, "%s: SCIC Controller starting task from invalid " "state\n", __func__); return SCI_TASK_FAILURE_INVALID_STATE; } - status = scic_sds_remote_device_start_task(scic, idev, ireq); + status = scic_sds_remote_device_start_task(ihost, idev, ireq); switch (status) { case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: set_bit(IREQ_ACTIVE, &ireq->flags); @@ -2950,7 +2928,7 @@ enum sci_task_status scic_controller_start_task( case SCI_SUCCESS: set_bit(IREQ_ACTIVE, &ireq->flags); - scic_sds_controller_post_request(scic, + scic_sds_controller_post_request(ihost, scic_sds_request_get_post_context(ireq)); break; default: diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index ca2e3b0ee0dd..013f672a8fd7 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -106,7 +106,7 @@ struct scic_power_control { }; struct scic_sds_port_configuration_agent; -typedef void (*port_config_fn)(struct scic_sds_controller *, +typedef void (*port_config_fn)(struct isci_host *, struct scic_sds_port_configuration_agent *, struct isci_port *, struct isci_phy *); @@ -124,171 +124,66 @@ struct scic_sds_port_configuration_agent { }; /** - * struct scic_sds_controller - - * - * This structure represents the SCU controller object. + * isci_host - primary host/controller object + * @timer: timeout start/stop operations + * @device_table: rni (hw remote node index) to remote device lookup table + * @available_remote_nodes: rni allocator + * @power_control: manage device spin up + * @io_request_sequence: generation number for tci's (task contexts) + * @task_context_table: hw task context table + * @remote_node_context_table: hw remote node context table + * @completion_queue: hw-producer driver-consumer communication ring + * @completion_queue_get: tracks the driver 'head' of the ring to notify hw + * @logical_port_entries: min({driver|silicon}-supported-port-count) + * @remote_node_entries: min({driver|silicon}-supported-node-count) + * @task_context_entries: min({driver|silicon}-supported-task-count) + * @phy_timer: phy startup timer + * @invalid_phy_mask: if an invalid_link_up notification is reported a bit for + * the phy index is set so further notifications are not + * made. Once the phy reports link up and is made part of a + * port then this bit is cleared. + */ -struct scic_sds_controller { - /** - * This field contains the information for the base controller state - * machine. - */ +struct isci_host { struct sci_base_state_machine sm; - - /** - * Timer for controller start/stop operations. - */ + /* XXX can we time this externally */ struct sci_timer timer; - - /** - * This field contains the user parameters to be utilized for this - * core controller object. - */ + /* XXX drop reference module params directly */ union scic_user_parameters user_parameters; - - /** - * This field contains the OEM parameters to be utilized for this - * core controller object. - */ + /* XXX no need to be a union */ union scic_oem_parameters oem_parameters; - - /** - * This field contains the port configuration agent for this controller. - */ struct scic_sds_port_configuration_agent port_agent; - - /** - * This field is the array of device objects that are currently constructed - * for this controller object. This table is used as a fast lookup of device - * objects that need to handle device completion notifications from the - * hardware. The table is RNi based. - */ struct isci_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; - - /** - * This field is the free RNi data structure - */ struct scic_remote_node_table available_remote_nodes; - - /** - * This filed is the struct scic_power_control data used to controll when direct - * attached devices can consume power. - */ struct scic_power_control power_control; - - /* sequence number per tci */ u8 io_request_sequence[SCI_MAX_IO_REQUESTS]; - - /** - * This field is a pointer to the memory allocated by the driver for the task - * context table. This data is shared between the hardware and software. - */ struct scu_task_context *task_context_table; dma_addr_t task_context_dma; - - /** - * This field is a pointer to the memory allocated by the driver for the - * remote node context table. This table is shared between the hardware and - * software. - */ union scu_remote_node_context *remote_node_context_table; - - /** - * This field is a pointer to the completion queue. This memory is - * written to by the hardware and read by the software. - */ u32 *completion_queue; - - /** - * This field is the software copy of the completion queue get pointer. The - * controller object writes this value to the hardware after processing the - * completion entries. - */ u32 completion_queue_get; - - /** - * This field is the minimum of the number of hardware supported port entries - * and the software requested port entries. - */ u32 logical_port_entries; - - /** - * This field is the minimum number of devices supported by the hardware and - * the number of devices requested by the software. - */ u32 remote_node_entries; - - /** - * This field is the minimum number of IO requests supported by the hardware - * and the number of IO requests requested by the software. - */ u32 task_context_entries; - - /** - * This object contains all of the unsolicited frame specific - * data utilized by the core controller. - */ struct scic_sds_unsolicited_frame_control uf_control; - /* Phy Startup Data */ - /** - * Timer for controller phy request startup. On controller start the - * controller will start each PHY individually in order of phy index. - */ + /* phy startup */ struct sci_timer phy_timer; - - /** - * This field is set when the phy_timer is running and is cleared when - * the phy_timer is stopped. - */ + /* XXX kill */ bool phy_startup_timer_pending; - - /** - * This field is the index of the next phy start. It is initialized to 0 and - * increments for each phy index that is started. - */ u32 next_phy_to_start; - - /** - * This field controlls the invalid link up notifications to the SCI_USER. If - * an invalid_link_up notification is reported a bit for the PHY index is set - * so further notifications are not made. Once the PHY object reports link up - * and is made part of a port then this bit for the PHY index is cleared. - */ u8 invalid_phy_mask; - /* - * This field saves the current interrupt coalescing number of the controller. - */ + /* TODO attempt dynamic interrupt coalescing scheme */ u16 interrupt_coalesce_number; - - /* - * This field saves the current interrupt coalescing timeout value in microseconds. - */ u32 interrupt_coalesce_timeout; - - /** - * This field is a pointer to the memory mapped register space for the - * struct smu_registers. - */ struct smu_registers __iomem *smu_registers; - - /** - * This field is a pointer to the memory mapped register space for the - * struct scu_registers. - */ struct scu_registers __iomem *scu_registers; -}; - -struct isci_host { - struct scic_sds_controller sci; u16 tci_head; u16 tci_tail; u16 tci_pool[SCI_MAX_IO_REQUESTS]; - union scic_oem_parameters oem_parameters; - int id; /* unique within a given pci device */ struct isci_phy phys[SCI_MAX_PHYS]; struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ @@ -464,14 +359,6 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev) return dev->port->ha->lldd_ha; } -static inline struct isci_host *scic_to_ihost(struct scic_sds_controller *scic) -{ - /* XXX delete after merging scic_sds_contoller and isci_host */ - struct isci_host *ihost = container_of(scic, typeof(*ihost), sci); - - return ihost; -} - /** * scic_sds_controller_get_protocol_engine_group() - * @@ -518,11 +405,6 @@ static inline int scic_sds_remote_device_node_count(struct isci_remote_device *i #define scic_sds_controller_clear_invalid_phy(controller, phy) \ ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) -static inline struct device *scic_to_dev(struct scic_sds_controller *scic) -{ - return &scic_to_ihost(scic)->pdev->dev; -} - static inline struct device *sciphy_to_dev(struct isci_phy *iphy) { @@ -578,54 +460,54 @@ static inline bool is_c0(void) return isci_si_rev > ISCI_SI_REVB0; } -void scic_sds_controller_post_request(struct scic_sds_controller *scic, +void scic_sds_controller_post_request(struct isci_host *ihost, u32 request); -void scic_sds_controller_release_frame(struct scic_sds_controller *scic, +void scic_sds_controller_release_frame(struct isci_host *ihost, u32 frame_index); void scic_sds_controller_copy_sata_response(void *response_buffer, void *frame_header, void *frame_buffer); -enum sci_status scic_sds_controller_allocate_remote_node_context(struct scic_sds_controller *scic, +enum sci_status scic_sds_controller_allocate_remote_node_context(struct isci_host *ihost, struct isci_remote_device *idev, u16 *node_id); void scic_sds_controller_free_remote_node_context( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, u16 node_id); union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( - struct scic_sds_controller *scic, + struct isci_host *ihost, u16 node_id); -struct isci_request *scic_request_by_tag(struct scic_sds_controller *scic, +struct isci_request *scic_request_by_tag(struct isci_host *ihost, u16 io_tag); void scic_sds_controller_power_control_queue_insert( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_phy *iphy); void scic_sds_controller_power_control_queue_remove( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_phy *iphy); void scic_sds_controller_link_up( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy); void scic_sds_controller_link_down( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy); void scic_sds_controller_remote_device_stopped( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev); void scic_sds_controller_copy_task_context( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_request *ireq); -void scic_sds_controller_register_setup(struct scic_sds_controller *scic); +void scic_sds_controller_register_setup(struct isci_host *ihost); enum sci_status scic_controller_continue_io(struct isci_request *ireq); int isci_host_scan_finished(struct Scsi_Host *, unsigned long); @@ -655,25 +537,25 @@ void isci_host_remote_device_start_complete( enum sci_status); void scic_controller_disable_interrupts( - struct scic_sds_controller *scic); + struct isci_host *ihost); enum sci_status scic_controller_start_io( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); enum sci_task_status scic_controller_start_task( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_controller_terminate_request( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_controller_complete_io( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); @@ -681,6 +563,6 @@ void scic_sds_port_configuration_agent_construct( struct scic_sds_port_configuration_agent *port_agent); enum sci_status scic_sds_port_configuration_agent_initialize( - struct scic_sds_controller *controller, + struct isci_host *ihost, struct scic_sds_port_configuration_agent *port_agent); #endif diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index bbfb6e563207..68ca1a4f30af 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -548,13 +548,13 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic static void __devexit isci_pci_remove(struct pci_dev *pdev) { - struct isci_host *isci_host; + struct isci_host *ihost; int i; - for_each_isci_host(i, isci_host, pdev) { - isci_unregister(isci_host); - isci_host_deinit(isci_host); - scic_controller_disable_interrupts(&isci_host->sci); + for_each_isci_host(i, ihost, pdev) { + isci_unregister(ihost); + isci_host_deinit(ihost); + scic_controller_disable_interrupts(ihost); } } diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index fd0e9734e5d0..ca96b5ad0d52 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -112,13 +112,13 @@ static enum sci_status scic_sds_phy_link_layer_initialization(struct isci_phy *iphy, struct scu_link_layer_registers __iomem *link_layer_registers) { - struct scic_sds_controller *scic = + struct isci_host *ihost = iphy->owning_port->owning_controller; int phy_idx = iphy->phy_index; struct sci_phy_user_params *phy_user = - &scic->user_parameters.sds1.phys[phy_idx]; + &ihost->user_parameters.sds1.phys[phy_idx]; struct sci_phy_oem_params *phy_oem = - &scic->oem_parameters.sds1.phys[phy_idx]; + &ihost->oem_parameters.sds1.phys[phy_idx]; u32 phy_configuration; struct scic_phy_cap phy_cap; u32 parity_check = 0; @@ -169,7 +169,7 @@ scic_sds_phy_link_layer_initialization(struct isci_phy *iphy, phy_cap.gen3_no_ssc = 1; phy_cap.gen2_no_ssc = 1; phy_cap.gen1_no_ssc = 1; - if (scic->oem_parameters.sds1.controller.do_enable_ssc == true) { + if (ihost->oem_parameters.sds1.controller.do_enable_ssc == true) { phy_cap.gen3_ssc = 1; phy_cap.gen2_ssc = 1; phy_cap.gen1_ssc = 1; @@ -216,7 +216,7 @@ scic_sds_phy_link_layer_initialization(struct isci_phy *iphy, &iphy->link_layer_registers->afe_lookup_table_control); llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, - (u8)scic->user_parameters.sds1.no_outbound_task_timeout); + (u8)ihost->user_parameters.sds1.no_outbound_task_timeout); switch(phy_user->max_speed_generation) { case SCIC_SDS_PARM_GEN3_SPEED: @@ -255,7 +255,7 @@ static void phy_sata_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; struct isci_phy *iphy = container_of(tmr, typeof(*iphy), sata_timer); - struct isci_host *ihost = scic_to_ihost(iphy->owning_port->owning_controller); + struct isci_host *ihost = iphy->owning_port->owning_controller; unsigned long flags; spin_lock_irqsave(&ihost->scic_lock, flags); @@ -890,7 +890,7 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, u32 frame_index) { enum scic_sds_phy_states state = iphy->sm.current_state_id; - struct scic_sds_controller *scic = iphy->owning_port->owning_controller; + struct isci_host *ihost = iphy->owning_port->owning_controller; enum sci_status result; unsigned long flags; @@ -899,7 +899,7 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, u32 *frame_words; struct sas_identify_frame iaf; - result = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + result = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_words); @@ -933,7 +933,7 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, "unexpected frame id %x\n", __func__, frame_index); - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return result; } case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: { @@ -950,7 +950,7 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, if ((frame_header->fis_type == FIS_REGD2H) && !(frame_header->status & ATA_BUSY)) { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&fis_frame_data); @@ -971,7 +971,7 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, __func__, frame_index); /* Regardless of the result we are done with this frame with it */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return result; } @@ -994,33 +994,33 @@ static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_state_m static void scic_sds_phy_starting_await_sas_power_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - struct scic_sds_controller *scic = iphy->owning_port->owning_controller; + struct isci_host *ihost = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_insert(scic, iphy); + scic_sds_controller_power_control_queue_insert(ihost, iphy); } static void scic_sds_phy_starting_await_sas_power_substate_exit(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - struct scic_sds_controller *scic = iphy->owning_port->owning_controller; + struct isci_host *ihost = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_remove(scic, iphy); + scic_sds_controller_power_control_queue_remove(ihost, iphy); } static void scic_sds_phy_starting_await_sata_power_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - struct scic_sds_controller *scic = iphy->owning_port->owning_controller; + struct isci_host *ihost = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_insert(scic, iphy); + scic_sds_controller_power_control_queue_insert(ihost, iphy); } static void scic_sds_phy_starting_await_sata_power_substate_exit(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - struct scic_sds_controller *scic = iphy->owning_port->owning_controller; + struct isci_host *ihost = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_remove(scic, iphy); + scic_sds_controller_power_control_queue_remove(ihost, iphy); } static void scic_sds_phy_starting_await_sata_phy_substate_enter(struct sci_base_state_machine *sm) @@ -1313,7 +1313,7 @@ void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index) u64 sci_sas_addr; __be64 sas_addr; - scic_oem_parameters_get(&ihost->sci, &oem); + scic_oem_parameters_get(ihost, &oem); sci_sas_addr = oem.sds1.phys[index].sas_address.high; sci_sas_addr <<= 32; sci_sas_addr |= oem.sds1.phys[index].sas_address.low; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index df37b1bf7d11..c434d5a0effa 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -365,11 +365,11 @@ static void isci_port_not_ready(struct isci_host *isci_host, struct isci_port *i "%s: isci_port = %p\n", __func__, isci_port); } -static void isci_port_stop_complete(struct scic_sds_controller *scic, +static void isci_port_stop_complete(struct isci_host *ihost, struct isci_port *iport, enum sci_status completion_status) { - dev_dbg(&scic_to_ihost(scic)->pdev->dev, "Port stop complete\n"); + dev_dbg(&ihost->pdev->dev, "Port stop complete\n"); } /** @@ -541,8 +541,7 @@ static enum sci_status scic_sds_port_clear_phy(struct isci_port *iport, /* Make sure that this phy is part of this port */ if (iport->phy_table[iphy->phy_index] == iphy && phy_get_non_dummy_port(iphy) == iport) { - struct scic_sds_controller *scic = iport->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = iport->owning_controller; /* Yep it is assigned to this port so remove it */ scic_sds_phy_set_port(iphy, &ihost->ports[SCI_MAX_PORTS]); @@ -654,10 +653,10 @@ static void scic_sds_port_construct_dummy_rnc(struct isci_port *iport, u16 rni) */ static void scic_sds_port_construct_dummy_task(struct isci_port *iport, u16 tag) { - struct scic_sds_controller *scic = iport->owning_controller; + struct isci_host *ihost = iport->owning_controller; struct scu_task_context *task_context; - task_context = &scic->task_context_table[ISCI_TAG_TCI(tag)]; + task_context = &ihost->task_context_table[ISCI_TAG_TCI(tag)]; memset(task_context, 0, sizeof(struct scu_task_context)); task_context->initiator_request = 1; @@ -674,13 +673,13 @@ static void scic_sds_port_construct_dummy_task(struct isci_port *iport, u16 tag) static void scic_sds_port_destroy_dummy_resources(struct isci_port *iport) { - struct scic_sds_controller *scic = iport->owning_controller; + struct isci_host *ihost = iport->owning_controller; if (iport->reserved_tag != SCI_CONTROLLER_INVALID_IO_TAG) - isci_free_tag(scic_to_ihost(scic), iport->reserved_tag); + isci_free_tag(ihost, iport->reserved_tag); if (iport->reserved_rni != SCU_DUMMY_INDEX) - scic_sds_remote_node_table_release_remote_node_index(&scic->available_remote_nodes, + scic_sds_remote_node_table_release_remote_node_index(&ihost->available_remote_nodes, 1, iport->reserved_rni); iport->reserved_rni = SCU_DUMMY_INDEX; @@ -749,15 +748,14 @@ static void scic_sds_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user) { - struct scic_sds_controller *scic = iport->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = iport->owning_controller; if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) scic_sds_phy_resume(iphy); iport->active_phy_mask |= 1 << iphy->phy_index; - scic_sds_controller_clear_invalid_phy(scic, iphy); + scic_sds_controller_clear_invalid_phy(ihost, iphy); if (do_notify_user == true) isci_port_link_up(ihost, iport, iphy); @@ -767,8 +765,7 @@ void scic_sds_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user) { - struct scic_sds_controller *scic = scic_sds_port_get_controller(iport); - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = scic_sds_port_get_controller(iport); iport->active_phy_mask &= ~(1 << iphy->phy_index); @@ -793,16 +790,16 @@ void scic_sds_port_deactivate_phy(struct isci_port *iport, static void scic_sds_port_invalid_link_up(struct isci_port *iport, struct isci_phy *iphy) { - struct scic_sds_controller *scic = iport->owning_controller; + struct isci_host *ihost = iport->owning_controller; /* * Check to see if we have alreay reported this link as bad and if * not go ahead and tell the SCI_USER that we have discovered an * invalid link. */ - if ((scic->invalid_phy_mask & (1 << iphy->phy_index)) == 0) { - scic_sds_controller_set_invalid_phy(scic, iphy); - dev_warn(&scic_to_ihost(scic)->pdev->dev, "Invalid link up!\n"); + if ((ihost->invalid_phy_mask & (1 << iphy->phy_index)) == 0) { + scic_sds_controller_set_invalid_phy(ihost, iphy); + dev_warn(&ihost->pdev->dev, "Invalid link up!\n"); } } @@ -931,7 +928,7 @@ static void port_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; struct isci_port *iport = container_of(tmr, typeof(*iport), timer); - struct isci_host *ihost = scic_to_ihost(iport->owning_controller); + struct isci_host *ihost = iport->owning_controller; unsigned long flags; u32 current_state; @@ -1041,19 +1038,19 @@ static void scic_sds_port_suspend_port_task_scheduler(struct isci_port *iport) */ static void scic_sds_port_post_dummy_request(struct isci_port *iport) { - struct scic_sds_controller *scic = iport->owning_controller; + struct isci_host *ihost = iport->owning_controller; u16 tag = iport->reserved_tag; struct scu_task_context *tc; u32 command; - tc = &scic->task_context_table[ISCI_TAG_TCI(tag)]; + tc = &ihost->task_context_table[ISCI_TAG_TCI(tag)]; tc->abort = 0; command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ISCI_TAG_TCI(tag); - scic_sds_controller_post_request(scic, command); + scic_sds_controller_post_request(ihost, command); } /** @@ -1065,19 +1062,19 @@ static void scic_sds_port_post_dummy_request(struct isci_port *iport) */ static void scic_sds_port_abort_dummy_request(struct isci_port *iport) { - struct scic_sds_controller *scic = iport->owning_controller; + struct isci_host *ihost = iport->owning_controller; u16 tag = iport->reserved_tag; struct scu_task_context *tc; u32 command; - tc = &scic->task_context_table[ISCI_TAG_TCI(tag)]; + tc = &ihost->task_context_table[ISCI_TAG_TCI(tag)]; tc->abort = 1; command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT | iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ISCI_TAG_TCI(tag); - scic_sds_controller_post_request(scic, command); + scic_sds_controller_post_request(ihost, command); } /** @@ -1115,8 +1112,7 @@ static void scic_sds_port_ready_substate_operational_enter(struct sci_base_state { u32 index; struct isci_port *iport = container_of(sm, typeof(*iport), sm); - struct scic_sds_controller *scic = iport->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = iport->owning_controller; isci_port_ready(ihost, iport); @@ -1141,13 +1137,13 @@ static void scic_sds_port_ready_substate_operational_enter(struct sci_base_state static void scic_sds_port_invalidate_dummy_remote_node(struct isci_port *iport) { - struct scic_sds_controller *scic = iport->owning_controller; + struct isci_host *ihost = iport->owning_controller; u8 phys_index = iport->physical_port_index; union scu_remote_node_context *rnc; u16 rni = iport->reserved_rni; u32 command; - rnc = &scic->remote_node_context_table[rni]; + rnc = &ihost->remote_node_context_table[rni]; rnc->ssp.is_valid = false; @@ -1155,13 +1151,13 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct isci_port *iport) * controller and give it ample time to act before posting the rnc * invalidate */ - readl(&scic->smu_registers->interrupt_status); /* flush */ + readl(&ihost->smu_registers->interrupt_status); /* flush */ udelay(10); command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - scic_sds_controller_post_request(scic, command); + scic_sds_controller_post_request(ihost, command); } /** @@ -1175,8 +1171,7 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct isci_port *iport) static void scic_sds_port_ready_substate_operational_exit(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); - struct scic_sds_controller *scic = iport->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = iport->owning_controller; /* * Kill the dummy task for this port if it has not yet posted @@ -1194,8 +1189,7 @@ static void scic_sds_port_ready_substate_operational_exit(struct sci_base_state_ static void scic_sds_port_ready_substate_configuring_enter(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); - struct scic_sds_controller *scic = iport->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = iport->owning_controller; if (iport->active_phy_mask == 0) { isci_port_not_ready(ihost, iport); @@ -1218,7 +1212,7 @@ static void scic_sds_port_ready_substate_configuring_exit(struct sci_base_state_ enum sci_status scic_sds_port_start(struct isci_port *iport) { - struct scic_sds_controller *scic = iport->owning_controller; + struct isci_host *ihost = iport->owning_controller; enum sci_status status = SCI_SUCCESS; enum scic_sds_port_states state; u32 phy_mask; @@ -1241,7 +1235,7 @@ enum sci_status scic_sds_port_start(struct isci_port *iport) if (iport->reserved_rni == SCU_DUMMY_INDEX) { u16 rni = scic_sds_remote_node_table_allocate_remote_node( - &scic->available_remote_nodes, 1); + &ihost->available_remote_nodes, 1); if (rni != SCU_DUMMY_INDEX) scic_sds_port_construct_dummy_rnc(iport, rni); @@ -1251,7 +1245,6 @@ enum sci_status scic_sds_port_start(struct isci_port *iport) } if (iport->reserved_tag == SCI_CONTROLLER_INVALID_IO_TAG) { - struct isci_host *ihost = scic_to_ihost(scic); u16 tag; tag = isci_alloc_tag(ihost); @@ -1634,30 +1627,30 @@ scic_sds_port_disable_port_task_scheduler(struct isci_port *iport) static void scic_sds_port_post_dummy_remote_node(struct isci_port *iport) { - struct scic_sds_controller *scic = iport->owning_controller; + struct isci_host *ihost = iport->owning_controller; u8 phys_index = iport->physical_port_index; union scu_remote_node_context *rnc; u16 rni = iport->reserved_rni; u32 command; - rnc = &scic->remote_node_context_table[rni]; + rnc = &ihost->remote_node_context_table[rni]; rnc->ssp.is_valid = true; command = SCU_CONTEXT_COMMAND_POST_RNC_32 | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - scic_sds_controller_post_request(scic, command); + scic_sds_controller_post_request(ihost, command); /* ensure hardware has seen the post rnc command and give it * ample time to act before sending the suspend */ - readl(&scic->smu_registers->interrupt_status); /* flush */ + readl(&ihost->smu_registers->interrupt_status); /* flush */ udelay(10); command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - scic_sds_controller_post_request(scic, command); + scic_sds_controller_post_request(ihost, command); } static void scic_sds_port_stopped_state_enter(struct sci_base_state_machine *sm) @@ -1684,8 +1677,7 @@ static void scic_sds_port_stopped_state_exit(struct sci_base_state_machine *sm) static void scic_sds_port_ready_state_enter(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); - struct scic_sds_controller *scic = iport->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = iport->owning_controller; u32 prev_state; prev_state = iport->sm.previous_state_id; @@ -1758,7 +1750,7 @@ static const struct sci_base_state scic_sds_port_state_table[] = { }; void scic_sds_port_construct(struct isci_port *iport, u8 index, - struct scic_sds_controller *scic) + struct isci_host *ihost) { sci_init_sm(&iport->sm, scic_sds_port_state_table, SCI_PORT_STOPPED); @@ -1767,7 +1759,7 @@ void scic_sds_port_construct(struct isci_port *iport, u8 index, iport->active_phy_mask = 0; iport->ready_exit = false; - iport->owning_controller = scic; + iport->owning_controller = ihost; iport->started_request_count = 0; iport->assigned_device_count = 0; @@ -1810,8 +1802,7 @@ void scic_sds_port_broadcast_change_received( struct isci_port *iport, struct isci_phy *iphy) { - struct scic_sds_controller *scic = iport->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = iport->owning_controller; /* notify the user. */ isci_port_bc_change_received(ihost, iport, iphy); diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index b9bc89bf6519..9a9be7b47b4a 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -115,7 +115,7 @@ struct isci_port { u32 assigned_device_count; u32 not_ready_reason; struct isci_phy *phy_table[SCI_MAX_PHYS]; - struct scic_sds_controller *owning_controller; + struct isci_host *owning_controller; struct sci_timer timer; struct scu_port_task_scheduler_registers __iomem *port_task_scheduler_registers; /* XXX rework: only one register, no need to replicate per-port */ @@ -243,7 +243,7 @@ static inline void scic_sds_port_decrement_request_count(struct isci_port *iport void scic_sds_port_construct( struct isci_port *iport, u8 port_index, - struct scic_sds_controller *scic); + struct isci_host *ihost); enum sci_status scic_sds_port_initialize( struct isci_port *iport, diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index bb62d2a25217..a0a135d54e95 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -113,7 +113,7 @@ static s32 sci_sas_address_compare( * NULL if there is no matching port for the phy. */ static struct isci_port *scic_sds_port_configuration_agent_find_port( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct isci_phy *iphy) { u8 i; @@ -130,8 +130,7 @@ static struct isci_port *scic_sds_port_configuration_agent_find_port( scic_sds_phy_get_sas_address(iphy, &phy_sas_address); scic_sds_phy_get_attached_sas_address(iphy, &phy_attached_device_address); - for (i = 0; i < scic->logical_port_entries; i++) { - struct isci_host *ihost = scic_to_ihost(scic); + for (i = 0; i < ihost->logical_port_entries; i++) { struct isci_port *iport = &ihost->ports[i]; scic_sds_port_get_sas_address(iport, &port_sas_address); @@ -158,10 +157,9 @@ static struct isci_port *scic_sds_port_configuration_agent_find_port( * the port configuration is not valid for this port configuration agent. */ static enum sci_status scic_sds_port_configuration_agent_validate_ports( - struct scic_sds_controller *controller, + struct isci_host *ihost, struct scic_sds_port_configuration_agent *port_agent) { - struct isci_host *ihost = scic_to_ihost(controller); struct sci_sas_address first_address; struct sci_sas_address second_address; @@ -239,17 +237,11 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * Manual port configuration agent routines * ****************************************************************************** */ -/** - * - * - * This routine will verify that all of the phys in the same port are using the - * same SAS address. - */ -static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent) +/* verify all of the phys in the same port are using the same SAS address */ +static enum sci_status +scic_sds_mpc_agent_validate_phy_configuration(struct isci_host *ihost, + struct scic_sds_port_configuration_agent *port_agent) { - struct isci_host *ihost = scic_to_ihost(controller); u32 phy_mask; u32 assigned_phy_mask; struct sci_sas_address sas_address; @@ -262,7 +254,7 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( sas_address.low = 0; for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { - phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask; + phy_mask = ihost->oem_parameters.sds1.ports[port_index].phy_mask; if (!phy_mask) continue; @@ -324,7 +316,7 @@ static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( phy_index++; } - return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); + return scic_sds_port_configuration_agent_validate_ports(ihost, port_agent); } static void mpc_agent_timeout(unsigned long data) @@ -332,14 +324,12 @@ static void mpc_agent_timeout(unsigned long data) u8 index; struct sci_timer *tmr = (struct sci_timer *)data; struct scic_sds_port_configuration_agent *port_agent; - struct scic_sds_controller *scic; struct isci_host *ihost; unsigned long flags; u16 configure_phy_mask; port_agent = container_of(tmr, typeof(*port_agent), timer); - scic = container_of(port_agent, typeof(*scic), port_agent); - ihost = scic_to_ihost(scic); + ihost = container_of(port_agent, typeof(*ihost), port_agent); spin_lock_irqsave(&ihost->scic_lock, flags); @@ -355,7 +345,7 @@ static void mpc_agent_timeout(unsigned long data) struct isci_phy *iphy = &ihost->phys[index]; if (configure_phy_mask & (1 << index)) { - port_agent->link_up_handler(scic, port_agent, + port_agent->link_up_handler(ihost, port_agent, phy_get_non_dummy_port(iphy), iphy); } @@ -365,7 +355,7 @@ done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } -static void scic_sds_mpc_agent_link_up(struct scic_sds_controller *controller, +static void scic_sds_mpc_agent_link_up(struct isci_host *ihost, struct scic_sds_port_configuration_agent *port_agent, struct isci_port *iport, struct isci_phy *iphy) @@ -401,7 +391,7 @@ static void scic_sds_mpc_agent_link_up(struct scic_sds_controller *controller, * link down notification from a phy that has no assocoated port? */ static void scic_sds_mpc_agent_link_down( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct scic_sds_port_configuration_agent *port_agent, struct isci_port *iport, struct isci_phy *iphy) @@ -438,26 +428,17 @@ static void scic_sds_mpc_agent_link_down( } } -/* - * ****************************************************************************** - * Automatic port configuration agent routines - * ****************************************************************************** */ - -/** - * - * - * This routine will verify that the phys are assigned a valid SAS address for - * automatic port configuration mode. +/* verify phys are assigned a valid SAS address for automatic port + * configuration mode. */ -static enum sci_status scic_sds_apc_agent_validate_phy_configuration( - struct scic_sds_controller *controller, - struct scic_sds_port_configuration_agent *port_agent) +static enum sci_status +scic_sds_apc_agent_validate_phy_configuration(struct isci_host *ihost, + struct scic_sds_port_configuration_agent *port_agent) { u8 phy_index; u8 port_index; struct sci_sas_address sas_address; struct sci_sas_address phy_assigned_address; - struct isci_host *ihost = scic_to_ihost(controller); phy_index = 0; @@ -484,10 +465,10 @@ static enum sci_status scic_sds_apc_agent_validate_phy_configuration( } } - return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); + return scic_sds_port_configuration_agent_validate_ports(ihost, port_agent); } -static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *controller, +static void scic_sds_apc_agent_configure_ports(struct isci_host *ihost, struct scic_sds_port_configuration_agent *port_agent, struct isci_phy *iphy, bool start_timer) @@ -496,9 +477,8 @@ static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *contr enum sci_status status; struct isci_port *iport; enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; - struct isci_host *ihost = scic_to_ihost(controller); - iport = scic_sds_port_configuration_agent_find_port(controller, iphy); + iport = scic_sds_port_configuration_agent_find_port(ihost, iphy); if (iport) { if (scic_sds_port_is_valid_phy_assignment(iport, iphy->phy_index)) @@ -619,7 +599,7 @@ static void scic_sds_apc_agent_configure_ports(struct scic_sds_controller *contr * notifications. Is it possible to get a link down notification from a phy * that has no assocoated port? */ -static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, +static void scic_sds_apc_agent_link_up(struct isci_host *ihost, struct scic_sds_port_configuration_agent *port_agent, struct isci_port *iport, struct isci_phy *iphy) @@ -629,7 +609,7 @@ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, if (!iport) { /* the phy is not the part of this port */ port_agent->phy_ready_mask |= 1 << phy_index; - scic_sds_apc_agent_configure_ports(scic, port_agent, iphy, true); + scic_sds_apc_agent_configure_ports(ihost, port_agent, iphy, true); } else { /* the phy is already the part of the port */ u32 port_state = iport->sm.current_state_id; @@ -658,7 +638,7 @@ static void scic_sds_apc_agent_link_up(struct scic_sds_controller *scic, * port? */ static void scic_sds_apc_agent_link_down( - struct scic_sds_controller *controller, + struct isci_host *ihost, struct scic_sds_port_configuration_agent *port_agent, struct isci_port *iport, struct isci_phy *iphy) @@ -683,14 +663,12 @@ static void apc_agent_timeout(unsigned long data) u32 index; struct sci_timer *tmr = (struct sci_timer *)data; struct scic_sds_port_configuration_agent *port_agent; - struct scic_sds_controller *scic; struct isci_host *ihost; unsigned long flags; u16 configure_phy_mask; port_agent = container_of(tmr, typeof(*port_agent), timer); - scic = container_of(port_agent, typeof(*scic), port_agent); - ihost = scic_to_ihost(scic); + ihost = container_of(port_agent, typeof(*ihost), port_agent); spin_lock_irqsave(&ihost->scic_lock, flags); @@ -708,7 +686,7 @@ static void apc_agent_timeout(unsigned long data) if ((configure_phy_mask & (1 << index)) == 0) continue; - scic_sds_apc_agent_configure_ports(scic, port_agent, + scic_sds_apc_agent_configure_ports(ihost, port_agent, &ihost->phys[index], false); } @@ -748,17 +726,17 @@ void scic_sds_port_configuration_agent_construct( } enum sci_status scic_sds_port_configuration_agent_initialize( - struct scic_sds_controller *scic, + struct isci_host *ihost, struct scic_sds_port_configuration_agent *port_agent) { enum sci_status status; enum scic_port_configuration_mode mode; - mode = scic->oem_parameters.sds1.controller.mode_type; + mode = ihost->oem_parameters.sds1.controller.mode_type; if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { status = scic_sds_mpc_agent_validate_phy_configuration( - scic, port_agent); + ihost, port_agent); port_agent->link_up_handler = scic_sds_mpc_agent_link_up; port_agent->link_down_handler = scic_sds_mpc_agent_link_down; @@ -766,7 +744,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize( sci_init_timer(&port_agent->timer, mpc_agent_timeout); } else { status = scic_sds_apc_agent_validate_phy_configuration( - scic, port_agent); + ihost, port_agent); port_agent->link_up_handler = scic_sds_apc_agent_link_up; port_agent->link_down_handler = scic_sds_apc_agent_link_down; diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 95c8d91aab8d..e40cb5f6eba5 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -165,7 +165,7 @@ struct scic_sds_oem_params; int scic_oem_parameters_validate(struct scic_sds_oem_params *oem); union scic_oem_parameters; -void scic_oem_parameters_get(struct scic_sds_controller *scic, +void scic_oem_parameters_get(struct isci_host *ihost, union scic_oem_parameters *oem); struct isci_orom; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 3b0234049a3d..9043b458c999 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -62,7 +62,7 @@ #include "task.h" /** - * isci_remote_device_not_ready() - This function is called by the scic when + * isci_remote_device_not_ready() - This function is called by the ihost when * the remote device is not ready. We mark the isci device as ready (not * "ready_for_io") and signal the waiting proccess. * @isci_host: This parameter specifies the isci host object. @@ -92,7 +92,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, "%s: isci_device = %p request = %p\n", __func__, idev, ireq); - scic_controller_terminate_request(&ihost->sci, + scic_controller_terminate_request(ihost, idev, ireq); } @@ -104,7 +104,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, } /** - * isci_remote_device_ready() - This function is called by the scic when the + * isci_remote_device_ready() - This function is called by the ihost when the * remote device is ready. We mark the isci device as ready and signal the * waiting proccess. * @ihost: our valid isci_host @@ -135,8 +135,7 @@ static void rnc_destruct_done(void *_dev) static enum sci_status scic_sds_remote_device_terminate_requests(struct isci_remote_device *idev) { - struct scic_sds_controller *scic = idev->owning_port->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = idev->owning_port->owning_controller; enum sci_status status = SCI_SUCCESS; u32 i; @@ -148,7 +147,7 @@ static enum sci_status scic_sds_remote_device_terminate_requests(struct isci_rem ireq->target_device != idev) continue; - s = scic_controller_terminate_request(scic, idev, ireq); + s = scic_controller_terminate_request(ihost, idev, ireq); if (s != SCI_SUCCESS) status = s; } @@ -276,7 +275,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * { struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct scic_sds_controller *scic = idev->owning_port->owning_controller; + struct isci_host *ihost = idev->owning_port->owning_controller; enum sci_status status; switch (state) { @@ -290,7 +289,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); /* Return the frame back to the controller */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return SCI_FAILURE_INVALID_STATE; case SCI_DEV_READY: case SCI_STP_DEV_NCQ_ERROR: @@ -303,7 +302,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * void *frame_header; ssize_t word_cnt; - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, &frame_header); if (status != SCI_SUCCESS) @@ -312,7 +311,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * word_cnt = sizeof(hdr) / sizeof(u32); sci_swab32_cpy(&hdr, frame_header, word_cnt); - ireq = scic_request_by_tag(scic, be16_to_cpu(hdr.tag)); + ireq = scic_request_by_tag(ihost, be16_to_cpu(hdr.tag)); if (ireq && ireq->target_device == idev) { /* The IO request is now in charge of releasing the frame */ status = scic_sds_io_request_frame_handler(ireq, frame_index); @@ -320,14 +319,14 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * /* We could not map this tag to a valid IO * request Just toss the frame and continue */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); } break; } case SCI_STP_DEV_NCQ: { struct dev_to_host_fis *hdr; - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&hdr); if (status != SCI_SUCCESS) @@ -350,7 +349,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * } else status = SCI_FAILURE; - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); break; } case SCI_STP_DEV_CMD: @@ -461,7 +460,7 @@ static void scic_sds_remote_device_start_request(struct isci_remote_device *idev } } -enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic, +enum sci_status scic_sds_remote_device_start_io(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { @@ -597,7 +596,7 @@ static enum sci_status common_complete_io(struct isci_port *iport, return status; } -enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *scic, +enum sci_status scic_sds_remote_device_complete_io(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { @@ -678,7 +677,7 @@ static void scic_sds_remote_device_continue_request(void *dev) scic_controller_continue_io(idev->working_request); } -enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *scic, +enum sci_status scic_sds_remote_device_start_task(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { @@ -802,13 +801,13 @@ static void remote_device_resume_done(void *_dev) static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) { struct isci_remote_device *idev = _dev; - struct scic_sds_controller *scic = idev->owning_port->owning_controller; + struct isci_host *ihost = idev->owning_port->owning_controller; /* For NCQ operation we do not issue a isci_remote_device_not_ready(). * As a result, avoid sending the ready notification. */ if (idev->sm.previous_state_id != SCI_STP_DEV_NCQ) - isci_remote_device_ready(scic_to_ihost(scic), idev); + isci_remote_device_ready(ihost, idev); } static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_machine *sm) @@ -836,7 +835,7 @@ static enum sci_status scic_remote_device_destruct(struct isci_remote_device *id { struct sci_base_state_machine *sm = &idev->sm; enum scic_sds_remote_device_states state = sm->current_state_id; - struct scic_sds_controller *scic; + struct isci_host *ihost; if (state != SCI_DEV_STOPPED) { dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", @@ -844,8 +843,8 @@ static enum sci_status scic_remote_device_destruct(struct isci_remote_device *id return SCI_FAILURE_INVALID_STATE; } - scic = idev->owning_port->owning_controller; - scic_sds_controller_free_remote_node_context(scic, idev, + ihost = idev->owning_port->owning_controller; + scic_sds_controller_free_remote_node_context(ihost, idev, idev->rnc.remote_node_index); idev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; sci_change_state(sm, SCI_DEV_FINAL); @@ -878,7 +877,7 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct scic_sds_controller *scic = idev->owning_port->owning_controller; + struct isci_host *ihost = idev->owning_port->owning_controller; u32 prev_state; /* If we are entering from the stopping state let the SCI User know that @@ -886,16 +885,15 @@ static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_mac */ prev_state = idev->sm.previous_state_id; if (prev_state == SCI_DEV_STOPPING) - isci_remote_device_deconstruct(scic_to_ihost(scic), idev); + isci_remote_device_deconstruct(ihost, idev); - scic_sds_controller_remote_device_stopped(scic, idev); + scic_sds_controller_remote_device_stopped(ihost, idev); } static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); @@ -904,7 +902,7 @@ static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_ma static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct scic_sds_controller *scic = idev->owning_port->owning_controller; + struct isci_host *ihost = idev->owning_port->owning_controller; struct domain_device *dev = idev->domain_dev; if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { @@ -912,7 +910,7 @@ static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machi } else if (dev_is_expander(dev)) { sci_change_state(&idev->sm, SCI_SMP_DEV_IDLE); } else - isci_remote_device_ready(scic_to_ihost(scic), idev); + isci_remote_device_ready(ihost, idev); } static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machine *sm) @@ -921,9 +919,9 @@ static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machin struct domain_device *dev = idev->domain_dev; if (dev->dev_type == SAS_END_DEV) { - struct scic_sds_controller *scic = idev->owning_port->owning_controller; + struct isci_host *ihost = idev->owning_port->owning_controller; - isci_remote_device_not_ready(scic_to_ihost(scic), idev, + isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); } } @@ -963,40 +961,40 @@ static void scic_sds_stp_remote_device_ready_idle_substate_enter(struct sci_base static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); BUG_ON(idev->working_request == NULL); - isci_remote_device_not_ready(scic_to_ihost(scic), idev, + isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); if (idev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) - isci_remote_device_not_ready(scic_to_ihost(scic), idev, + isci_remote_device_not_ready(ihost, idev, idev->not_ready_reason); } static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); - isci_remote_device_ready(scic_to_ihost(scic), idev); + isci_remote_device_ready(ihost, idev); } static void scic_sds_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); BUG_ON(idev->working_request == NULL); - isci_remote_device_not_ready(scic_to_ihost(scic), idev, + isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); } @@ -1303,7 +1301,7 @@ void isci_remote_device_release(struct kref *kref) * @isci_host: This parameter specifies the isci host object. * @isci_device: This parameter specifies the remote device. * - * The status of the scic request to stop. + * The status of the ihost request to stop. */ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev) { diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 45798582fc14..bc4da20a13fa 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -402,17 +402,17 @@ enum sci_status scic_sds_remote_device_event_handler( u32 event_code); enum sci_status scic_sds_remote_device_start_io( - struct scic_sds_controller *controller, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_sds_remote_device_start_task( - struct scic_sds_controller *controller, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); enum sci_status scic_sds_remote_device_complete_io( - struct scic_sds_controller *controller, + struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index e485744e1263..8a5203b6eb09 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -107,11 +107,11 @@ static void scic_sds_remote_node_context_construct_buffer( struct domain_device *dev = idev->domain_dev; int rni = sci_rnc->remote_node_index; union scu_remote_node_context *rnc; - struct scic_sds_controller *scic; + struct isci_host *ihost; __le64 sas_addr; - scic = scic_sds_remote_device_get_controller(idev); - rnc = scic_sds_controller_get_remote_node_context_buffer(scic, rni); + ihost = scic_sds_remote_device_get_controller(idev); + rnc = scic_sds_controller_get_remote_node_context_buffer(ihost, rni); memset(rnc, 0, sizeof(union scu_remote_node_context) * scic_sds_remote_device_node_count(idev)); @@ -135,14 +135,14 @@ static void scic_sds_remote_node_context_construct_buffer( if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { rnc->ssp.connection_occupancy_timeout = - scic->user_parameters.sds1.stp_max_occupancy_timeout; + ihost->user_parameters.sds1.stp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = - scic->user_parameters.sds1.stp_inactivity_timeout; + ihost->user_parameters.sds1.stp_inactivity_timeout; } else { rnc->ssp.connection_occupancy_timeout = - scic->user_parameters.sds1.ssp_max_occupancy_timeout; + ihost->user_parameters.sds1.ssp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = - scic->user_parameters.sds1.ssp_inactivity_timeout; + ihost->user_parameters.sds1.ssp_inactivity_timeout; } rnc->ssp.initial_arbitration_wait_time = 0; diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 90ead662828d..36e674896bc5 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -74,19 +74,19 @@ static struct scu_sgl_element_pair *to_sgl_element_pair(struct isci_request *ire return &ireq->sg_table[idx - 2]; } -static dma_addr_t to_sgl_element_pair_dma(struct scic_sds_controller *scic, +static dma_addr_t to_sgl_element_pair_dma(struct isci_host *ihost, struct isci_request *ireq, u32 idx) { u32 offset; if (idx == 0) { offset = (void *) &ireq->tc->sgl_pair_ab - - (void *) &scic->task_context_table[0]; - return scic->task_context_dma + offset; + (void *) &ihost->task_context_table[0]; + return ihost->task_context_dma + offset; } else if (idx == 1) { offset = (void *) &ireq->tc->sgl_pair_cd - - (void *) &scic->task_context_table[0]; - return scic->task_context_dma + offset; + (void *) &ihost->task_context_table[0]; + return ihost->task_context_dma + offset; } return scic_io_request_get_dma_addr(ireq, &ireq->sg_table[idx - 2]); @@ -102,8 +102,7 @@ static void init_sgl_element(struct scu_sgl_element *e, struct scatterlist *sg) static void scic_sds_request_build_sgl(struct isci_request *ireq) { - struct isci_host *isci_host = ireq->isci_host; - struct scic_sds_controller *scic = &isci_host->sci; + struct isci_host *ihost = ireq->isci_host; struct sas_task *task = isci_request_access_task(ireq); struct scatterlist *sg = NULL; dma_addr_t dma_addr; @@ -125,7 +124,7 @@ static void scic_sds_request_build_sgl(struct isci_request *ireq) memset(&scu_sg->B, 0, sizeof(scu_sg->B)); if (prev_sg) { - dma_addr = to_sgl_element_pair_dma(scic, + dma_addr = to_sgl_element_pair_dma(ihost, ireq, sg_idx); @@ -141,7 +140,7 @@ static void scic_sds_request_build_sgl(struct isci_request *ireq) } else { /* handle when no sg */ scu_sg = to_sgl_element_pair(ireq, sg_idx); - dma_addr = dma_map_single(&isci_host->pdev->dev, + dma_addr = dma_map_single(&ihost->pdev->dev, task->scatter, task->total_xfer_len, task->data_dir); @@ -508,7 +507,7 @@ scic_io_request_construct_sata(struct isci_request *ireq, scu_stp_raw_request_construct_task_context(ireq); return SCI_SUCCESS; } else { - dev_err(scic_to_dev(ireq->owning_controller), + dev_err(&ireq->owning_controller->pdev->dev, "%s: Request 0x%p received un-handled SAT " "management protocol 0x%x.\n", __func__, ireq, tmf->tmf_code); @@ -518,7 +517,7 @@ scic_io_request_construct_sata(struct isci_request *ireq, } if (!sas_protocol_ata(task->task_proto)) { - dev_err(scic_to_dev(ireq->owning_controller), + dev_err(&ireq->owning_controller->pdev->dev, "%s: Non-ATA protocol in SATA path: 0x%x\n", __func__, task->task_proto); @@ -616,7 +615,7 @@ enum sci_status scic_task_request_construct_sata(struct isci_request *ireq) tmf->tmf_code == isci_tmf_sata_srst_low) { scu_stp_raw_request_construct_task_context(ireq); } else { - dev_err(scic_to_dev(ireq->owning_controller), + dev_err(&ireq->owning_controller->pdev->dev, "%s: Request 0x%p received un-handled SAT " "Protocol 0x%x.\n", __func__, ireq, tmf->tmf_code); @@ -639,11 +638,11 @@ enum sci_status scic_task_request_construct_sata(struct isci_request *ireq) #define SCU_TASK_CONTEXT_SRAM 0x200000 static u32 sci_req_tx_bytes(struct isci_request *ireq) { - struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_host *ihost = ireq->owning_controller; u32 ret_val = 0; - if (readl(&scic->smu_registers->address_modifier) == 0) { - void __iomem *scu_reg_base = scic->scu_registers; + if (readl(&ihost->smu_registers->address_modifier) == 0) { + void __iomem *scu_reg_base = ihost->scu_registers; /* get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where * BAR1 is the scu_registers @@ -663,11 +662,11 @@ enum sci_status scic_sds_request_start(struct isci_request *ireq) { enum sci_base_request_states state; struct scu_task_context *tc = ireq->tc; - struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_host *ihost = ireq->owning_controller; state = ireq->sm.current_state_id; if (state != SCI_REQ_CONSTRUCTED) { - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: SCIC IO Request requested to start while in wrong " "state %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; @@ -749,7 +748,7 @@ scic_sds_io_request_terminate(struct isci_request *ireq) return SCI_SUCCESS; case SCI_REQ_COMPLETED: default: - dev_warn(scic_to_dev(ireq->owning_controller), + dev_warn(&ireq->owning_controller->pdev->dev, "%s: SCIC IO Request requested to abort while in wrong " "state %d\n", __func__, @@ -763,7 +762,7 @@ scic_sds_io_request_terminate(struct isci_request *ireq) enum sci_status scic_sds_request_complete(struct isci_request *ireq) { enum sci_base_request_states state; - struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_host *ihost = ireq->owning_controller; state = ireq->sm.current_state_id; if (WARN_ONCE(state != SCI_REQ_COMPLETED, @@ -771,7 +770,7 @@ enum sci_status scic_sds_request_complete(struct isci_request *ireq) return SCI_FAILURE_INVALID_STATE; if (ireq->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) - scic_sds_controller_release_frame(scic, + scic_sds_controller_release_frame(ihost, ireq->saved_rx_frame_index); /* XXX can we just stop the machine and remove the 'final' state? */ @@ -783,12 +782,12 @@ enum sci_status scic_sds_io_request_event_handler(struct isci_request *ireq, u32 event_code) { enum sci_base_request_states state; - struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_host *ihost = ireq->owning_controller; state = ireq->sm.current_state_id; if (state != SCI_REQ_STP_PIO_DATA_IN) { - dev_warn(scic_to_dev(scic), "%s: (%x) in wrong state %d\n", + dev_warn(&ihost->pdev->dev, "%s: (%x) in wrong state %d\n", __func__, event_code, state); return SCI_FAILURE_INVALID_STATE; @@ -802,7 +801,7 @@ enum sci_status scic_sds_io_request_event_handler(struct isci_request *ireq, sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_WAIT_FRAME); return SCI_SUCCESS; default: - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: pio request unexpected event %#x\n", __func__, event_code); @@ -1024,7 +1023,7 @@ static enum sci_status ssp_task_request_await_tc_event(struct isci_request *ireq * There is a potential for receiving multiple task responses if * we decide to send the task IU again. */ - dev_warn(scic_to_dev(ireq->owning_controller), + dev_warn(&ireq->owning_controller->pdev->dev, "%s: TaskRequest:0x%p CompletionCode:%x - " "ACK/NAK timeout\n", __func__, ireq, completion_code); @@ -1073,7 +1072,7 @@ smp_request_await_response_tc_event(struct isci_request *ireq, * response within 2 ms. This causes our hardware break * the connection and set TC completion with one of * these SMP_XXX_XX_ERR status. For these type of error, - * we ask scic user to retry the request. + * we ask ihost user to retry the request. */ scic_sds_request_set_status(ireq, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED); @@ -1451,18 +1450,18 @@ static void scic_sds_stp_request_udma_complete_request( static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct isci_request *ireq, u32 frame_index) { - struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_host *ihost = ireq->owning_controller; struct dev_to_host_fis *frame_header; enum sci_status status; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); if ((status == SCI_SUCCESS) && (frame_header->fis_type == FIS_REGD2H)) { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); @@ -1471,7 +1470,7 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct is frame_buffer); } - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return status; } @@ -1480,7 +1479,7 @@ enum sci_status scic_sds_io_request_frame_handler(struct isci_request *ireq, u32 frame_index) { - struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_host *ihost = ireq->owning_controller; struct isci_stp_request *stp_req = &ireq->stp.req; enum sci_base_request_states state; enum sci_status status; @@ -1492,7 +1491,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct ssp_frame_hdr ssp_hdr; void *frame_header; - scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, &frame_header); @@ -1503,7 +1502,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct ssp_response_iu *resp_iu; ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&resp_iu); @@ -1522,7 +1521,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, SCI_SUCCESS); } else { /* not a response frame, why did it get forwarded? */ - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC IO Request 0x%p received unexpected " "frame %d type 0x%02x\n", __func__, ireq, frame_index, ssp_hdr.frame_type); @@ -1532,7 +1531,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, * In any case we are done with this frame buffer return it to * the controller */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return SCI_SUCCESS; } @@ -1540,14 +1539,14 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, case SCI_REQ_TASK_WAIT_TC_RESP: scic_sds_io_request_copy_response(ireq); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); - scic_sds_controller_release_frame(scic,frame_index); + scic_sds_controller_release_frame(ihost,frame_index); return SCI_SUCCESS; case SCI_REQ_SMP_WAIT_RESP: { struct smp_resp *rsp_hdr = &ireq->smp.rsp; void *frame_header; - scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, &frame_header); @@ -1558,7 +1557,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, if (rsp_hdr->frame_type == SMP_RESPONSE) { void *smp_resp; - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, &smp_resp); @@ -1577,7 +1576,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, * This was not a response frame why did it get * forwarded? */ - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC SMP Request 0x%p received unexpected " "frame %d type 0x%02x\n", __func__, @@ -1592,7 +1591,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return SCI_SUCCESS; } @@ -1619,12 +1618,12 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct dev_to_host_fis *frame_header; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC IO Request 0x%p could not get frame " "header for frame index %d, status %x\n", __func__, @@ -1637,7 +1636,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, switch (frame_header->fis_type) { case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); @@ -1651,7 +1650,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, break; default: - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: IO Request:0x%p Frame Id:%d protocol " "violation occurred\n", __func__, stp_req, frame_index); @@ -1664,7 +1663,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return status; } @@ -1674,12 +1673,12 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct dev_to_host_fis *frame_header; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC IO Request 0x%p could not get frame " "header for frame index %d, status %x\n", __func__, stp_req, frame_index, status); @@ -1689,7 +1688,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, switch (frame_header->fis_type) { case FIS_PIO_SETUP: /* Get from the frame buffer the PIO Setup Data */ - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); @@ -1736,7 +1735,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, * FIS when it is still busy? Do nothing since * we are still in the right state. */ - dev_dbg(scic_to_dev(scic), + dev_dbg(&ihost->pdev->dev, "%s: SCIC PIO Request 0x%p received " "D2H Register FIS with BSY status " "0x%x\n", @@ -1746,7 +1745,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, break; } - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); @@ -1767,7 +1766,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, } /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return status; } @@ -1776,12 +1775,12 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct dev_to_host_fis *frame_header; struct sata_fis_data *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC IO Request 0x%p could not get frame " "header for frame index %d, status %x\n", __func__, @@ -1792,7 +1791,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, } if (frame_header->fis_type != FIS_DATA) { - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC PIO Request 0x%p received frame %d " "with fis type 0x%02x when expecting a data " "fis.\n", @@ -1808,7 +1807,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return status; } @@ -1816,7 +1815,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, ireq->saved_rx_frame_index = frame_index; stp_req->pio_len = 0; } else { - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); @@ -1824,7 +1823,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, (u8 *)frame_buffer); /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); } /* Check for the end of the transfer, are there more @@ -1849,11 +1848,11 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct dev_to_host_fis *frame_header; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control, + status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); if (status != SCI_SUCCESS) { - dev_err(scic_to_dev(scic), + dev_err(&ihost->pdev->dev, "%s: SCIC IO Request 0x%p could not get frame " "header for frame index %d, status %x\n", __func__, @@ -1865,7 +1864,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, switch (frame_header->fis_type) { case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control, + scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); @@ -1880,7 +1879,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, break; default: - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: IO Request:0x%p Frame Id:%d protocol " "violation occurred\n", __func__, @@ -1896,7 +1895,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return status; } @@ -1905,18 +1904,18 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, * TODO: Is it even possible to get an unsolicited frame in the * aborting state? */ - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return SCI_SUCCESS; default: - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: SCIC IO Request given unexpected frame %x while " "in state %d\n", __func__, frame_index, state); - scic_sds_controller_release_frame(scic, frame_index); + scic_sds_controller_release_frame(ihost, frame_index); return SCI_FAILURE_INVALID_STATE; } } @@ -2042,7 +2041,7 @@ scic_sds_io_request_tc_completion(struct isci_request *ireq, u32 completion_code) { enum sci_base_request_states state; - struct scic_sds_controller *scic = ireq->owning_controller; + struct isci_host *ihost = ireq->owning_controller; state = ireq->sm.current_state_id; @@ -2089,7 +2088,7 @@ scic_sds_io_request_tc_completion(struct isci_request *ireq, completion_code); default: - dev_warn(scic_to_dev(scic), + dev_warn(&ihost->pdev->dev, "%s: SCIC IO Request given task completion " "notification %x while in wrong state %d\n", __func__, @@ -2480,7 +2479,7 @@ static void isci_task_save_for_upper_layer_completion( } } -static void isci_request_io_request_complete(struct isci_host *isci_host, +static void isci_request_io_request_complete(struct isci_host *ihost, struct isci_request *request, enum sci_io_status completion_status) { @@ -2495,7 +2494,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, enum isci_completion_selection complete_to_host = isci_perform_normal_io_completion; - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: request = %p, task = %p,\n" "task->data_dir = %d completion_status = 0x%x\n", __func__, @@ -2616,7 +2615,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, switch (completion_status) { case SCI_IO_FAILURE_RESPONSE_VALID: - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: SCI_IO_FAILURE_RESPONSE_VALID (%p/%p)\n", __func__, request, @@ -2631,17 +2630,17 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, /* crack the iu response buffer. */ resp_iu = &request->ssp.rsp; isci_request_process_response_iu(task, resp_iu, - &isci_host->pdev->dev); + &ihost->pdev->dev); } else if (SAS_PROTOCOL_SMP == task->task_proto) { - dev_err(&isci_host->pdev->dev, + dev_err(&ihost->pdev->dev, "%s: SCI_IO_FAILURE_RESPONSE_VALID: " "SAS_PROTOCOL_SMP protocol\n", __func__); } else - dev_err(&isci_host->pdev->dev, + dev_err(&ihost->pdev->dev, "%s: unknown protocol\n", __func__); /* use the task status set in the task struct by the @@ -2662,7 +2661,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, if (task->task_proto == SAS_PROTOCOL_SMP) { void *rsp = &request->smp.rsp; - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: SMP protocol completion\n", __func__); @@ -2687,20 +2686,20 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, if (task->task_status.residual != 0) status = SAS_DATA_UNDERRUN; - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: SCI_IO_SUCCESS_IO_DONE_EARLY %d\n", __func__, status); } else - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: SCI_IO_SUCCESS\n", __func__); break; case SCI_IO_FAILURE_TERMINATED: - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: SCI_IO_FAILURE_TERMINATED (%p/%p)\n", __func__, request, @@ -2768,7 +2767,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, default: /* Catch any otherwise unhandled error codes here. */ - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: invalid completion code: 0x%x - " "isci_request = %p\n", __func__, completion_status, request); @@ -2802,11 +2801,11 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, break; if (task->num_scatter == 0) /* 0 indicates a single dma address */ - dma_unmap_single(&isci_host->pdev->dev, + dma_unmap_single(&ihost->pdev->dev, request->zero_scatter_daddr, task->total_xfer_len, task->data_dir); else /* unmap the sgl dma addresses */ - dma_unmap_sg(&isci_host->pdev->dev, task->scatter, + dma_unmap_sg(&ihost->pdev->dev, task->scatter, request->num_sg_entries, task->data_dir); break; case SAS_PROTOCOL_SMP: { @@ -2814,7 +2813,7 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, struct smp_req *smp_req; void *kaddr; - dma_unmap_sg(&isci_host->pdev->dev, sg, 1, DMA_TO_DEVICE); + dma_unmap_sg(&ihost->pdev->dev, sg, 1, DMA_TO_DEVICE); /* need to swab it back in case the command buffer is re-used */ kaddr = kmap_atomic(sg_page(sg), KM_IRQ0); @@ -2828,14 +2827,12 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, } /* Put the completed request on the correct list */ - isci_task_save_for_upper_layer_completion(isci_host, request, response, + isci_task_save_for_upper_layer_completion(ihost, request, response, status, complete_to_host ); /* complete the io request to the core. */ - scic_controller_complete_io(&isci_host->sci, - request->target_device, - request); + scic_controller_complete_io(ihost, request->target_device, request); isci_put_device(idev); /* set terminated handle so it cannot be completed or @@ -2885,8 +2882,7 @@ static void scic_sds_request_started_state_enter(struct sci_base_state_machine * static void scic_sds_request_completed_state_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - struct scic_sds_controller *scic = ireq->owning_controller; - struct isci_host *ihost = scic_to_ihost(scic); + struct isci_host *ihost = ireq->owning_controller; /* Tell the SCI_USER that the IO request is complete */ if (!test_bit(IREQ_TMF, &ireq->flags)) @@ -2985,7 +2981,7 @@ static const struct sci_base_state scic_sds_request_state_table[] = { }; static void -scic_sds_general_request_construct(struct scic_sds_controller *scic, +scic_sds_general_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { @@ -3001,7 +2997,7 @@ scic_sds_general_request_construct(struct scic_sds_controller *scic, } static enum sci_status -scic_io_request_construct(struct scic_sds_controller *scic, +scic_io_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { @@ -3009,7 +3005,7 @@ scic_io_request_construct(struct scic_sds_controller *scic, enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, idev, ireq); + scic_sds_general_request_construct(ihost, idev, ireq); if (idev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; @@ -3028,7 +3024,7 @@ scic_io_request_construct(struct scic_sds_controller *scic, return status; } -enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, +enum sci_status scic_task_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, u16 io_tag, struct isci_request *ireq) { @@ -3036,7 +3032,7 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(scic, idev, ireq); + scic_sds_general_request_construct(ihost, idev, ireq); if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { @@ -3156,7 +3152,7 @@ scic_io_request_construct_smp(struct device *dev, task_context->initiator_request = 1; task_context->connection_rate = idev->connection_rate; task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(scic); + scic_sds_controller_get_protocol_engine_group(ihost); task_context->logical_port_index = scic_sds_port_get_index(iport); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; task_context->abort = 0; @@ -3199,7 +3195,7 @@ scic_io_request_construct_smp(struct device *dev, task_context->task_phase = 0; ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(scic) << + (scic_sds_controller_get_protocol_engine_group(ihost) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | (scic_sds_port_get_index(iport) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | @@ -3245,7 +3241,7 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) /** * isci_io_request_build() - This function builds the io request object. - * @isci_host: This parameter specifies the ISCI host object + * @ihost: This parameter specifies the ISCI host object * @request: This parameter points to the isci_request object allocated in the * request construct function. * @sci_device: This parameter is the handle for the sci core's remote device @@ -3253,14 +3249,14 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) * * SCI_SUCCESS on successfull completion, or specific failure code. */ -static enum sci_status isci_io_request_build(struct isci_host *isci_host, +static enum sci_status isci_io_request_build(struct isci_host *ihost, struct isci_request *request, struct isci_remote_device *idev) { enum sci_status status = SCI_SUCCESS; struct sas_task *task = isci_request_access_task(request); - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: idev = 0x%p; request = %p, " "num_scatter = %d\n", __func__, @@ -3277,7 +3273,7 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, !(SAS_PROTOCOL_SMP & task->task_proto)) { request->num_sg_entries = dma_map_sg( - &isci_host->pdev->dev, + &ihost->pdev->dev, task->scatter, task->num_scatter, task->data_dir @@ -3287,10 +3283,10 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, return SCI_FAILURE_INSUFFICIENT_RESOURCES; } - status = scic_io_request_construct(&isci_host->sci, idev, request); + status = scic_io_request_construct(ihost, idev, request); if (status != SCI_SUCCESS) { - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: failed request construct\n", __func__); return SCI_FAILURE; @@ -3309,7 +3305,7 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, status = isci_request_stp_request_construct(request); break; default: - dev_warn(&isci_host->pdev->dev, + dev_warn(&ihost->pdev->dev, "%s: unknown protocol\n", __func__); return SCI_FAILURE; } @@ -3392,7 +3388,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide * request was built that way (ie. * ireq->is_task_management_request is false). */ - status = scic_controller_start_task(&ihost->sci, + status = scic_controller_start_task(ihost, idev, ireq); } else { @@ -3400,7 +3396,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide } } else { /* send the request, let the core assign the IO TAG. */ - status = scic_controller_start_io(&ihost->sci, idev, + status = scic_controller_start_io(ihost, idev, ireq); } diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index ca64ea207ac8..0cafcead7a01 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -145,7 +145,7 @@ struct isci_request { */ struct completion *io_request_completion; struct sci_base_state_machine sm; - struct scic_sds_controller *owning_controller; + struct isci_host *owning_controller; struct isci_remote_device *target_device; u16 io_tag; enum sci_request_protocol protocol; @@ -500,7 +500,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide void isci_terminate_pending_requests(struct isci_host *ihost, struct isci_remote_device *idev); enum sci_status -scic_task_request_construct(struct scic_sds_controller *scic, +scic_task_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, u16 io_tag, struct isci_request *ireq); diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 89b01eef44b1..3a1fc55a7557 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -257,7 +257,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, return NULL; /* let the core do it's construct. */ - status = scic_task_request_construct(&ihost->sci, idev, tag, + status = scic_task_request_construct(ihost, idev, tag, ireq); if (status != SCI_SUCCESS) { @@ -332,7 +332,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, spin_lock_irqsave(&ihost->scic_lock, flags); /* start the TMF io. */ - status = scic_controller_start_task(&ihost->sci, idev, ireq); + status = scic_controller_start_task(ihost, idev, ireq); if (status != SCI_TASK_SUCCESS) { dev_warn(&ihost->pdev->dev, @@ -364,7 +364,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, if (tmf->cb_state_func != NULL) tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); - scic_controller_terminate_request(&ihost->sci, + scic_controller_terminate_request(ihost, idev, ireq); @@ -514,15 +514,14 @@ static void isci_request_cleanup_completed_loiterer( * request, and wait for it to complete. This function must only be called * from a thread that can wait. Note that the request is terminated and * completed (back to the host, if started there). - * @isci_host: This SCU. + * @ihost: This SCU. * @idev: The target. * @isci_request: The I/O request to be terminated. * */ -static void isci_terminate_request_core( - struct isci_host *isci_host, - struct isci_remote_device *idev, - struct isci_request *isci_request) +static void isci_terminate_request_core(struct isci_host *ihost, + struct isci_remote_device *idev, + struct isci_request *isci_request) { enum sci_status status = SCI_SUCCESS; bool was_terminated = false; @@ -533,11 +532,11 @@ static void isci_terminate_request_core( struct completion *io_request_completion; struct sas_task *task; - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: device = %p; request = %p\n", __func__, idev, isci_request); - spin_lock_irqsave(&isci_host->scic_lock, flags); + spin_lock_irqsave(&ihost->scic_lock, flags); io_request_completion = isci_request->io_request_completion; @@ -557,12 +556,11 @@ static void isci_terminate_request_core( if (!test_bit(IREQ_TERMINATED, &isci_request->flags)) { was_terminated = true; needs_cleanup_handling = true; - status = scic_controller_terminate_request( - &isci_host->sci, - idev, - isci_request); + status = scic_controller_terminate_request(ihost, + idev, + isci_request); } - spin_unlock_irqrestore(&isci_host->scic_lock, flags); + spin_unlock_irqrestore(&ihost->scic_lock, flags); /* * The only time the request to terminate will @@ -570,7 +568,7 @@ static void isci_terminate_request_core( * being aborted. */ if (status != SCI_SUCCESS) { - dev_err(&isci_host->pdev->dev, + dev_err(&ihost->pdev->dev, "%s: scic_controller_terminate_request" " returned = 0x%x\n", __func__, status); @@ -579,7 +577,7 @@ static void isci_terminate_request_core( } else { if (was_terminated) { - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: before completion wait (%p/%p)\n", __func__, isci_request, io_request_completion); @@ -593,7 +591,7 @@ static void isci_terminate_request_core( if (!termination_completed) { /* The request to terminate has timed out. */ - spin_lock_irqsave(&isci_host->scic_lock, + spin_lock_irqsave(&ihost->scic_lock, flags); /* Check for state changes. */ @@ -623,12 +621,12 @@ static void isci_terminate_request_core( } else termination_completed = 1; - spin_unlock_irqrestore(&isci_host->scic_lock, + spin_unlock_irqrestore(&ihost->scic_lock, flags); if (!termination_completed) { - dev_err(&isci_host->pdev->dev, + dev_err(&ihost->pdev->dev, "%s: *** Timeout waiting for " "termination(%p/%p)\n", __func__, io_request_completion, @@ -642,7 +640,7 @@ static void isci_terminate_request_core( } } if (termination_completed) - dev_dbg(&isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: after completion wait (%p/%p)\n", __func__, isci_request, io_request_completion); } @@ -678,7 +676,7 @@ static void isci_terminate_request_core( } if (needs_cleanup_handling) isci_request_cleanup_completed_loiterer( - isci_host, idev, isci_request, task); + ihost, idev, isci_request, task); } } @@ -1253,7 +1251,7 @@ isci_task_request_complete(struct isci_host *ihost, /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; - scic_controller_complete_io(&ihost->sci, ireq->target_device, ireq); + scic_controller_complete_io(ihost, ireq->target_device, ireq); /* set the 'terminated' flag handle to make sure it cannot be terminated * or completed again. */ diff --git a/drivers/scsi/isci/unsolicited_frame_control.c b/drivers/scsi/isci/unsolicited_frame_control.c index 680582d8cde5..a0e6f89fc6a1 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.c +++ b/drivers/scsi/isci/unsolicited_frame_control.c @@ -57,9 +57,9 @@ #include "unsolicited_frame_control.h" #include "registers.h" -int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic) +int scic_sds_unsolicited_frame_control_construct(struct isci_host *ihost) { - struct scic_sds_unsolicited_frame_control *uf_control = &scic->uf_control; + struct scic_sds_unsolicited_frame_control *uf_control = &ihost->uf_control; struct scic_sds_unsolicited_frame *uf; u32 buf_len, header_len, i; dma_addr_t dma; @@ -79,7 +79,7 @@ int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *sci * memory descriptor entry. The headers and address table will be * placed after the buffers. */ - virt = dmam_alloc_coherent(scic_to_dev(scic), size, &dma, GFP_KERNEL); + virt = dmam_alloc_coherent(&ihost->pdev->dev, size, &dma, GFP_KERNEL); if (!virt) return -ENOMEM; diff --git a/drivers/scsi/isci/unsolicited_frame_control.h b/drivers/scsi/isci/unsolicited_frame_control.h index 2954904f025a..c0285a3db562 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.h +++ b/drivers/scsi/isci/unsolicited_frame_control.h @@ -214,9 +214,9 @@ struct scic_sds_unsolicited_frame_control { }; -struct scic_sds_controller; +struct isci_host; -int scic_sds_unsolicited_frame_control_construct(struct scic_sds_controller *scic); +int scic_sds_unsolicited_frame_control_construct(struct isci_host *ihost); enum sci_status scic_sds_unsolicited_frame_control_get_header( struct scic_sds_unsolicited_frame_control *uf_control, -- cgit v1.2.3 From 89a7301f21fb00e753089671eb9e4132aab8ea08 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 30 Jun 2011 19:14:33 -0700 Subject: isci: retire scic_sds_ and scic_ prefixes The distinction between scic_sds_ scic_ and sci_ are no longer relevant so just unify the prefixes on sci_. The distinction between isci_ and sci_ is historically significant, and useful for comparing the old 'core' to the current Linux driver. 'sci_' represents the former core as well as the routines that are closer to the hardware and protocol than their 'isci_' brethren. sci == sas controller interface. Also unwind the 'sds1' out of the parameter structs. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 742 ++++++++++---------------- drivers/scsi/isci/host.h | 93 ++-- drivers/scsi/isci/init.c | 4 +- drivers/scsi/isci/isci.h | 6 +- drivers/scsi/isci/phy.c | 385 ++++++------- drivers/scsi/isci/phy.h | 70 +-- drivers/scsi/isci/port.c | 551 +++++++------------ drivers/scsi/isci/port.h | 68 ++- drivers/scsi/isci/port_config.c | 132 ++--- drivers/scsi/isci/probe_roms.c | 16 +- drivers/scsi/isci/probe_roms.h | 38 +- drivers/scsi/isci/remote_device.c | 300 +++++------ drivers/scsi/isci/remote_device.h | 90 ++-- drivers/scsi/isci/remote_node_context.c | 198 ++++--- drivers/scsi/isci/remote_node_context.h | 30 +- drivers/scsi/isci/remote_node_table.c | 114 ++-- drivers/scsi/isci/remote_node_table.h | 16 +- drivers/scsi/isci/request.c | 360 ++++++------- drivers/scsi/isci/request.h | 52 +- drivers/scsi/isci/sata.c | 4 +- drivers/scsi/isci/task.c | 24 +- drivers/scsi/isci/unsolicited_frame_control.c | 57 +- drivers/scsi/isci/unsolicited_frame_control.h | 42 +- 23 files changed, 1449 insertions(+), 1943 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index bb298f8f609a..f31f64e4b713 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -180,8 +180,7 @@ void sci_change_state(struct sci_base_state_machine *sm, u32 next_state) handler(sm); } -static bool scic_sds_controller_completion_queue_has_entries( - struct isci_host *ihost) +static bool sci_controller_completion_queue_has_entries(struct isci_host *ihost) { u32 get_value = ihost->completion_queue_get; u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK; @@ -193,9 +192,9 @@ static bool scic_sds_controller_completion_queue_has_entries( return false; } -static bool scic_sds_controller_isr(struct isci_host *ihost) +static bool sci_controller_isr(struct isci_host *ihost) { - if (scic_sds_controller_completion_queue_has_entries(ihost)) { + if (sci_controller_completion_queue_has_entries(ihost)) { return true; } else { /* @@ -219,13 +218,13 @@ irqreturn_t isci_msix_isr(int vec, void *data) { struct isci_host *ihost = data; - if (scic_sds_controller_isr(ihost)) + if (sci_controller_isr(ihost)) tasklet_schedule(&ihost->completion_tasklet); return IRQ_HANDLED; } -static bool scic_sds_controller_error_isr(struct isci_host *ihost) +static bool sci_controller_error_isr(struct isci_host *ihost) { u32 interrupt_status; @@ -252,35 +251,35 @@ static bool scic_sds_controller_error_isr(struct isci_host *ihost) return false; } -static void scic_sds_controller_task_completion(struct isci_host *ihost, - u32 completion_entry) +static void sci_controller_task_completion(struct isci_host *ihost, u32 ent) { - u32 index = SCU_GET_COMPLETION_INDEX(completion_entry); + u32 index = SCU_GET_COMPLETION_INDEX(ent); struct isci_request *ireq = ihost->reqs[index]; /* Make sure that we really want to process this IO request */ if (test_bit(IREQ_ACTIVE, &ireq->flags) && ireq->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && ISCI_TAG_SEQ(ireq->io_tag) == ihost->io_request_sequence[index]) - /* Yep this is a valid io request pass it along to the io request handler */ - scic_sds_io_request_tc_completion(ireq, completion_entry); + /* Yep this is a valid io request pass it along to the + * io request handler + */ + sci_io_request_tc_completion(ireq, ent); } -static void scic_sds_controller_sdma_completion(struct isci_host *ihost, - u32 completion_entry) +static void sci_controller_sdma_completion(struct isci_host *ihost, u32 ent) { u32 index; struct isci_request *ireq; struct isci_remote_device *idev; - index = SCU_GET_COMPLETION_INDEX(completion_entry); + index = SCU_GET_COMPLETION_INDEX(ent); - switch (scu_get_command_request_type(completion_entry)) { + switch (scu_get_command_request_type(ent)) { case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: ireq = ihost->reqs[index]; dev_warn(&ihost->pdev->dev, "%s: %x for io request %p\n", - __func__, completion_entry, ireq); + __func__, ent, ireq); /* @todo For a post TC operation we need to fail the IO * request */ @@ -290,20 +289,19 @@ static void scic_sds_controller_sdma_completion(struct isci_host *ihost, case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: idev = ihost->device_table[index]; dev_warn(&ihost->pdev->dev, "%s: %x for device %p\n", - __func__, completion_entry, idev); + __func__, ent, idev); /* @todo For a port RNC operation we need to fail the * device */ break; default: dev_warn(&ihost->pdev->dev, "%s: unknown completion type %x\n", - __func__, completion_entry); + __func__, ent); break; } } -static void scic_sds_controller_unsolicited_frame(struct isci_host *ihost, - u32 completion_entry) +static void sci_controller_unsolicited_frame(struct isci_host *ihost, u32 ent) { u32 index; u32 frame_index; @@ -314,36 +312,36 @@ static void scic_sds_controller_unsolicited_frame(struct isci_host *ihost, enum sci_status result = SCI_FAILURE; - frame_index = SCU_GET_FRAME_INDEX(completion_entry); + frame_index = SCU_GET_FRAME_INDEX(ent); frame_header = ihost->uf_control.buffers.array[frame_index].header; ihost->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE; - if (SCU_GET_FRAME_ERROR(completion_entry)) { + if (SCU_GET_FRAME_ERROR(ent)) { /* * / @todo If the IAF frame or SIGNATURE FIS frame has an error will * / this cause a problem? We expect the phy initialization will * / fail if there is an error in the frame. */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return; } if (frame_header->is_address_frame) { - index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + index = SCU_GET_PROTOCOL_ENGINE_INDEX(ent); iphy = &ihost->phys[index]; - result = scic_sds_phy_frame_handler(iphy, frame_index); + result = sci_phy_frame_handler(iphy, frame_index); } else { - index = SCU_GET_COMPLETION_INDEX(completion_entry); + index = SCU_GET_COMPLETION_INDEX(ent); if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { /* * This is a signature fis or a frame from a direct attached SATA * device that has not yet been created. In either case forwared * the frame to the PE and let it take care of the frame data. */ - index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + index = SCU_GET_PROTOCOL_ENGINE_INDEX(ent); iphy = &ihost->phys[index]; - result = scic_sds_phy_frame_handler(iphy, frame_index); + result = sci_phy_frame_handler(iphy, frame_index); } else { if (index < ihost->remote_node_entries) idev = ihost->device_table[index]; @@ -351,9 +349,9 @@ static void scic_sds_controller_unsolicited_frame(struct isci_host *ihost, idev = NULL; if (idev != NULL) - result = scic_sds_remote_device_frame_handler(idev, frame_index); + result = sci_remote_device_frame_handler(idev, frame_index); else - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); } } @@ -364,17 +362,16 @@ static void scic_sds_controller_unsolicited_frame(struct isci_host *ihost, } } -static void scic_sds_controller_event_completion(struct isci_host *ihost, - u32 completion_entry) +static void sci_controller_event_completion(struct isci_host *ihost, u32 ent) { struct isci_remote_device *idev; struct isci_request *ireq; struct isci_phy *iphy; u32 index; - index = SCU_GET_COMPLETION_INDEX(completion_entry); + index = SCU_GET_COMPLETION_INDEX(ent); - switch (scu_get_event_type(completion_entry)) { + switch (scu_get_event_type(ent)) { case SCU_EVENT_TYPE_SMU_COMMAND_ERROR: /* / @todo The driver did something wrong and we need to fix the condtion. */ dev_err(&ihost->pdev->dev, @@ -382,7 +379,7 @@ static void scic_sds_controller_event_completion(struct isci_host *ihost, "0x%x\n", __func__, ihost, - completion_entry); + ent); break; case SCU_EVENT_TYPE_SMU_PCQ_ERROR: @@ -396,21 +393,21 @@ static void scic_sds_controller_event_completion(struct isci_host *ihost, "event 0x%x\n", __func__, ihost, - completion_entry); + ent); break; case SCU_EVENT_TYPE_TRANSPORT_ERROR: ireq = ihost->reqs[index]; - scic_sds_io_request_event_handler(ireq, completion_entry); + sci_io_request_event_handler(ireq, ent); break; case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: - switch (scu_get_event_specifier(completion_entry)) { + switch (scu_get_event_specifier(ent)) { case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: ireq = ihost->reqs[index]; if (ireq != NULL) - scic_sds_io_request_event_handler(ireq, completion_entry); + sci_io_request_event_handler(ireq, ent); else dev_warn(&ihost->pdev->dev, "%s: SCIC Controller 0x%p received " @@ -418,14 +415,14 @@ static void scic_sds_controller_event_completion(struct isci_host *ihost, "that doesnt exist.\n", __func__, ihost, - completion_entry); + ent); break; case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: idev = ihost->device_table[index]; if (idev != NULL) - scic_sds_remote_device_event_handler(idev, completion_entry); + sci_remote_device_event_handler(idev, ent); else dev_warn(&ihost->pdev->dev, "%s: SCIC Controller 0x%p received " @@ -433,7 +430,7 @@ static void scic_sds_controller_event_completion(struct isci_host *ihost, "that doesnt exist.\n", __func__, ihost, - completion_entry); + ent); break; } @@ -448,9 +445,9 @@ static void scic_sds_controller_event_completion(struct isci_host *ihost, * direct error counter event to the phy object since that is where * we get the event notification. This is a type 4 event. */ case SCU_EVENT_TYPE_OSSP_EVENT: - index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); + index = SCU_GET_PROTOCOL_ENGINE_INDEX(ent); iphy = &ihost->phys[index]; - scic_sds_phy_event_handler(iphy, completion_entry); + sci_phy_event_handler(iphy, ent); break; case SCU_EVENT_TYPE_RNC_SUSPEND_TX: @@ -460,7 +457,7 @@ static void scic_sds_controller_event_completion(struct isci_host *ihost, idev = ihost->device_table[index]; if (idev != NULL) - scic_sds_remote_device_event_handler(idev, completion_entry); + sci_remote_device_event_handler(idev, ent); } else dev_err(&ihost->pdev->dev, "%s: SCIC Controller 0x%p received event 0x%x " @@ -468,7 +465,7 @@ static void scic_sds_controller_event_completion(struct isci_host *ihost, "exist.\n", __func__, ihost, - completion_entry, + ent, index); break; @@ -477,15 +474,15 @@ static void scic_sds_controller_event_completion(struct isci_host *ihost, dev_warn(&ihost->pdev->dev, "%s: SCIC Controller received unknown event code %x\n", __func__, - completion_entry); + ent); break; } } -static void scic_sds_controller_process_completions(struct isci_host *ihost) +static void sci_controller_process_completions(struct isci_host *ihost) { u32 completion_count = 0; - u32 completion_entry; + u32 ent; u32 get_index; u32 get_cycle; u32 event_get; @@ -509,7 +506,7 @@ static void scic_sds_controller_process_completions(struct isci_host *ihost) ) { completion_count++; - completion_entry = ihost->completion_queue[get_index]; + ent = ihost->completion_queue[get_index]; /* increment the get pointer and check for rollover to toggle the cycle bit */ get_cycle ^= ((get_index+1) & SCU_MAX_COMPLETION_QUEUE_ENTRIES) << @@ -519,19 +516,19 @@ static void scic_sds_controller_process_completions(struct isci_host *ihost) dev_dbg(&ihost->pdev->dev, "%s: completion queue entry:0x%08x\n", __func__, - completion_entry); + ent); - switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { + switch (SCU_GET_COMPLETION_TYPE(ent)) { case SCU_COMPLETION_TYPE_TASK: - scic_sds_controller_task_completion(ihost, completion_entry); + sci_controller_task_completion(ihost, ent); break; case SCU_COMPLETION_TYPE_SDMA: - scic_sds_controller_sdma_completion(ihost, completion_entry); + sci_controller_sdma_completion(ihost, ent); break; case SCU_COMPLETION_TYPE_UFI: - scic_sds_controller_unsolicited_frame(ihost, completion_entry); + sci_controller_unsolicited_frame(ihost, ent); break; case SCU_COMPLETION_TYPE_EVENT: @@ -540,7 +537,7 @@ static void scic_sds_controller_process_completions(struct isci_host *ihost) (SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT - SCU_MAX_EVENTS_SHIFT); event_get = (event_get+1) & (SCU_MAX_EVENTS-1); - scic_sds_controller_event_completion(ihost, completion_entry); + sci_controller_event_completion(ihost, ent); break; } default: @@ -548,7 +545,7 @@ static void scic_sds_controller_process_completions(struct isci_host *ihost) "%s: SCIC Controller received unknown " "completion type %x\n", __func__, - completion_entry); + ent); break; } } @@ -575,7 +572,7 @@ static void scic_sds_controller_process_completions(struct isci_host *ihost) } -static void scic_sds_controller_error_handler(struct isci_host *ihost) +static void sci_controller_error_handler(struct isci_host *ihost) { u32 interrupt_status; @@ -583,9 +580,9 @@ static void scic_sds_controller_error_handler(struct isci_host *ihost) readl(&ihost->smu_registers->interrupt_status); if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && - scic_sds_controller_completion_queue_has_entries(ihost)) { + sci_controller_completion_queue_has_entries(ihost)) { - scic_sds_controller_process_completions(ihost); + sci_controller_process_completions(ihost); writel(SMU_ISR_QUEUE_SUSPEND, &ihost->smu_registers->interrupt_status); } else { dev_err(&ihost->pdev->dev, "%s: status: %#x\n", __func__, @@ -607,13 +604,13 @@ irqreturn_t isci_intx_isr(int vec, void *data) irqreturn_t ret = IRQ_NONE; struct isci_host *ihost = data; - if (scic_sds_controller_isr(ihost)) { + if (sci_controller_isr(ihost)) { writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status); tasklet_schedule(&ihost->completion_tasklet); ret = IRQ_HANDLED; - } else if (scic_sds_controller_error_isr(ihost)) { + } else if (sci_controller_error_isr(ihost)) { spin_lock(&ihost->scic_lock); - scic_sds_controller_error_handler(ihost); + sci_controller_error_handler(ihost); spin_unlock(&ihost->scic_lock); ret = IRQ_HANDLED; } @@ -625,8 +622,8 @@ irqreturn_t isci_error_isr(int vec, void *data) { struct isci_host *ihost = data; - if (scic_sds_controller_error_isr(ihost)) - scic_sds_controller_error_handler(ihost); + if (sci_controller_error_isr(ihost)) + sci_controller_error_handler(ihost); return IRQ_HANDLED; } @@ -670,8 +667,8 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) } /** - * scic_controller_get_suggested_start_timeout() - This method returns the - * suggested scic_controller_start() timeout amount. The user is free to + * sci_controller_get_suggested_start_timeout() - This method returns the + * suggested sci_controller_start() timeout amount. The user is free to * use any timeout value, but this method provides the suggested minimum * start timeout value. The returned value is based upon empirical * information determined as a result of interoperability testing. @@ -681,7 +678,7 @@ int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time) * This method returns the number of milliseconds for the suggested start * operation timeout. */ -static u32 scic_controller_get_suggested_start_timeout(struct isci_host *ihost) +static u32 sci_controller_get_suggested_start_timeout(struct isci_host *ihost) { /* Validate the user supplied parameters. */ if (!ihost) @@ -706,19 +703,19 @@ static u32 scic_controller_get_suggested_start_timeout(struct isci_host *ihost) + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); } -static void scic_controller_enable_interrupts(struct isci_host *ihost) +static void sci_controller_enable_interrupts(struct isci_host *ihost) { BUG_ON(ihost->smu_registers == NULL); writel(0, &ihost->smu_registers->interrupt_mask); } -void scic_controller_disable_interrupts(struct isci_host *ihost) +void sci_controller_disable_interrupts(struct isci_host *ihost) { BUG_ON(ihost->smu_registers == NULL); writel(0xffffffff, &ihost->smu_registers->interrupt_mask); } -static void scic_sds_controller_enable_port_task_scheduler(struct isci_host *ihost) +static void sci_controller_enable_port_task_scheduler(struct isci_host *ihost) { u32 port_task_scheduler_value; @@ -731,7 +728,7 @@ static void scic_sds_controller_enable_port_task_scheduler(struct isci_host *iho &ihost->scu_registers->peg0.ptsg.control); } -static void scic_sds_controller_assign_task_entries(struct isci_host *ihost) +static void sci_controller_assign_task_entries(struct isci_host *ihost) { u32 task_assignment; @@ -752,7 +749,7 @@ static void scic_sds_controller_assign_task_entries(struct isci_host *ihost) } -static void scic_sds_controller_initialize_completion_queue(struct isci_host *ihost) +static void sci_controller_initialize_completion_queue(struct isci_host *ihost) { u32 index; u32 completion_queue_control_value; @@ -799,7 +796,7 @@ static void scic_sds_controller_initialize_completion_queue(struct isci_host *ih } } -static void scic_sds_controller_initialize_unsolicited_frame_queue(struct isci_host *ihost) +static void sci_controller_initialize_unsolicited_frame_queue(struct isci_host *ihost) { u32 frame_queue_control_value; u32 frame_queue_get_value; @@ -826,22 +823,8 @@ static void scic_sds_controller_initialize_unsolicited_frame_queue(struct isci_h &ihost->scu_registers->sdma.unsolicited_frame_put_pointer); } -/** - * This method will attempt to transition into the ready state for the - * controller and indicate that the controller start operation has completed - * if all criteria are met. - * @scic: This parameter indicates the controller object for which - * to transition to ready. - * @status: This parameter indicates the status value to be pass into the call - * to scic_cb_controller_start_complete(). - * - * none. - */ -static void scic_sds_controller_transition_to_ready( - struct isci_host *ihost, - enum sci_status status) +static void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status) { - if (ihost->sm.current_state_id == SCIC_STARTING) { /* * We move into the ready state, because some of the phys/ports @@ -855,7 +838,7 @@ static void scic_sds_controller_transition_to_ready( static bool is_phy_starting(struct isci_phy *iphy) { - enum scic_sds_phy_states state; + enum sci_phy_states state; state = iphy->sm.current_state_id; switch (state) { @@ -876,16 +859,16 @@ static bool is_phy_starting(struct isci_phy *iphy) } /** - * scic_sds_controller_start_next_phy - start phy + * sci_controller_start_next_phy - start phy * @scic: controller * * If all the phys have been started, then attempt to transition the * controller to the READY state and inform the user - * (scic_cb_controller_start_complete()). + * (sci_cb_controller_start_complete()). */ -static enum sci_status scic_sds_controller_start_next_phy(struct isci_host *ihost) +static enum sci_status sci_controller_start_next_phy(struct isci_host *ihost) { - struct scic_sds_oem_params *oem = &ihost->oem_parameters.sds1; + struct sci_oem_params *oem = &ihost->oem_parameters; struct isci_phy *iphy; enum sci_status status; @@ -924,7 +907,7 @@ static enum sci_status scic_sds_controller_start_next_phy(struct isci_host *ihos * The controller has successfully finished the start process. * Inform the SCI Core user and transition to the READY state. */ if (is_controller_start_complete == true) { - scic_sds_controller_transition_to_ready(ihost, SCI_SUCCESS); + sci_controller_transition_to_ready(ihost, SCI_SUCCESS); sci_del_timer(&ihost->phy_timer); ihost->phy_startup_timer_pending = false; } @@ -944,11 +927,11 @@ static enum sci_status scic_sds_controller_start_next_phy(struct isci_host *ihos * incorrectly for the PORT or it was never * assigned to a PORT */ - return scic_sds_controller_start_next_phy(ihost); + return sci_controller_start_next_phy(ihost); } } - status = scic_sds_phy_start(iphy); + status = sci_phy_start(iphy); if (status == SCI_SUCCESS) { sci_mod_timer(&ihost->phy_timer, @@ -985,7 +968,7 @@ static void phy_startup_timeout(unsigned long data) ihost->phy_startup_timer_pending = false; do { - status = scic_sds_controller_start_next_phy(ihost); + status = sci_controller_start_next_phy(ihost); } while (status != SCI_SUCCESS); done: @@ -997,7 +980,7 @@ static u16 isci_tci_active(struct isci_host *ihost) return CIRC_CNT(ihost->tci_head, ihost->tci_tail, SCI_MAX_IO_REQUESTS); } -static enum sci_status scic_controller_start(struct isci_host *ihost, +static enum sci_status sci_controller_start(struct isci_host *ihost, u32 timeout) { enum sci_status result; @@ -1018,38 +1001,37 @@ static enum sci_status scic_controller_start(struct isci_host *ihost, isci_tci_free(ihost, index); /* Build the RNi free pool */ - scic_sds_remote_node_table_initialize( - &ihost->available_remote_nodes, - ihost->remote_node_entries); + sci_remote_node_table_initialize(&ihost->available_remote_nodes, + ihost->remote_node_entries); /* * Before anything else lets make sure we will not be * interrupted by the hardware. */ - scic_controller_disable_interrupts(ihost); + sci_controller_disable_interrupts(ihost); /* Enable the port task scheduler */ - scic_sds_controller_enable_port_task_scheduler(ihost); + sci_controller_enable_port_task_scheduler(ihost); /* Assign all the task entries to ihost physical function */ - scic_sds_controller_assign_task_entries(ihost); + sci_controller_assign_task_entries(ihost); /* Now initialize the completion queue */ - scic_sds_controller_initialize_completion_queue(ihost); + sci_controller_initialize_completion_queue(ihost); /* Initialize the unsolicited frame queue for use */ - scic_sds_controller_initialize_unsolicited_frame_queue(ihost); + sci_controller_initialize_unsolicited_frame_queue(ihost); /* Start all of the ports on this controller */ for (index = 0; index < ihost->logical_port_entries; index++) { struct isci_port *iport = &ihost->ports[index]; - result = scic_sds_port_start(iport); + result = sci_port_start(iport); if (result) return result; } - scic_sds_controller_start_next_phy(ihost); + sci_controller_start_next_phy(ihost); sci_mod_timer(&ihost->timer, timeout); @@ -1061,29 +1043,29 @@ static enum sci_status scic_controller_start(struct isci_host *ihost, void isci_host_scan_start(struct Scsi_Host *shost) { struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha; - unsigned long tmo = scic_controller_get_suggested_start_timeout(ihost); + unsigned long tmo = sci_controller_get_suggested_start_timeout(ihost); set_bit(IHOST_START_PENDING, &ihost->flags); spin_lock_irq(&ihost->scic_lock); - scic_controller_start(ihost, tmo); - scic_controller_enable_interrupts(ihost); + sci_controller_start(ihost, tmo); + sci_controller_enable_interrupts(ihost); spin_unlock_irq(&ihost->scic_lock); } static void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) { isci_host_change_state(ihost, isci_stopped); - scic_controller_disable_interrupts(ihost); + sci_controller_disable_interrupts(ihost); clear_bit(IHOST_STOP_PENDING, &ihost->flags); wake_up(&ihost->eventq); } -static void scic_sds_controller_completion_handler(struct isci_host *ihost) +static void sci_controller_completion_handler(struct isci_host *ihost) { /* Empty out the completion queue */ - if (scic_sds_controller_completion_queue_has_entries(ihost)) - scic_sds_controller_process_completions(ihost); + if (sci_controller_completion_queue_has_entries(ihost)) + sci_controller_process_completions(ihost); /* Clear the interrupt and enable all interrupts again */ writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status); @@ -1116,7 +1098,7 @@ static void isci_host_completion_routine(unsigned long data) spin_lock_irq(&ihost->scic_lock); - scic_sds_controller_completion_handler(ihost); + sci_controller_completion_handler(ihost); /* Take the lists of completed I/Os from the host. */ @@ -1203,7 +1185,7 @@ static void isci_host_completion_routine(unsigned long data) } /** - * scic_controller_stop() - This method will stop an individual controller + * sci_controller_stop() - This method will stop an individual controller * object.This method will invoke the associated user callback upon * completion. The completion callback is called when the following * conditions are met: -# the method return status is SCI_SUCCESS. -# the @@ -1220,8 +1202,7 @@ static void isci_host_completion_routine(unsigned long data) * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the * controller is not either in the STARTED or STOPPED states. */ -static enum sci_status scic_controller_stop(struct isci_host *ihost, - u32 timeout) +static enum sci_status sci_controller_stop(struct isci_host *ihost, u32 timeout) { if (ihost->sm.current_state_id != SCIC_READY) { dev_warn(&ihost->pdev->dev, @@ -1236,7 +1217,7 @@ static enum sci_status scic_controller_stop(struct isci_host *ihost, } /** - * scic_controller_reset() - This method will reset the supplied core + * sci_controller_reset() - This method will reset the supplied core * controller regardless of the state of said controller. This operation is * considered destructive. In other words, all current operations are wiped * out. No IO completions for outstanding devices occur. Outstanding IO @@ -1247,7 +1228,7 @@ static enum sci_status scic_controller_stop(struct isci_host *ihost, * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if * the controller reset operation is unable to complete. */ -static enum sci_status scic_controller_reset(struct isci_host *ihost) +static enum sci_status sci_controller_reset(struct isci_host *ihost) { switch (ihost->sm.current_state_id) { case SCIC_RESET: @@ -1286,11 +1267,11 @@ void isci_host_deinit(struct isci_host *ihost) set_bit(IHOST_STOP_PENDING, &ihost->flags); spin_lock_irq(&ihost->scic_lock); - scic_controller_stop(ihost, SCIC_CONTROLLER_STOP_TIMEOUT); + sci_controller_stop(ihost, SCIC_CONTROLLER_STOP_TIMEOUT); spin_unlock_irq(&ihost->scic_lock); wait_for_stop(ihost); - scic_controller_reset(ihost); + sci_controller_reset(ihost); /* Cancel any/all outstanding port timers */ for (i = 0; i < ihost->logical_port_entries; i++) { @@ -1329,11 +1310,8 @@ static void __iomem *smu_base(struct isci_host *isci_host) return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; } -static void isci_user_parameters_get( - struct isci_host *isci_host, - union scic_user_parameters *scic_user_params) +static void isci_user_parameters_get(struct sci_user_parameters *u) { - struct scic_sds_user_parameters *u = &scic_user_params->sds1; int i; for (i = 0; i < SCI_MAX_PHYS; i++) { @@ -1355,14 +1333,14 @@ static void isci_user_parameters_get( u->max_number_concurrent_device_spin_up = max_concurr_spinup; } -static void scic_sds_controller_initial_state_enter(struct sci_base_state_machine *sm) +static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm) { struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); sci_change_state(&ihost->sm, SCIC_RESET); } -static inline void scic_sds_controller_starting_state_exit(struct sci_base_state_machine *sm) +static inline void sci_controller_starting_state_exit(struct sci_base_state_machine *sm) { struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); @@ -1377,7 +1355,7 @@ static inline void scic_sds_controller_starting_state_exit(struct sci_base_state #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28 /** - * scic_controller_set_interrupt_coalescence() - This method allows the user to + * sci_controller_set_interrupt_coalescence() - This method allows the user to * configure the interrupt coalescence. * @controller: This parameter represents the handle to the controller object * for which its interrupt coalesce register is overridden. @@ -1394,9 +1372,9 @@ static inline void scic_sds_controller_starting_state_exit(struct sci_base_state * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range. */ static enum sci_status -scic_controller_set_interrupt_coalescence(struct isci_host *ihost, - u32 coalesce_number, - u32 coalesce_timeout) +sci_controller_set_interrupt_coalescence(struct isci_host *ihost, + u32 coalesce_number, + u32 coalesce_timeout) { u8 timeout_encode = 0; u32 min = 0; @@ -1489,23 +1467,23 @@ scic_controller_set_interrupt_coalescence(struct isci_host *ihost, } -static void scic_sds_controller_ready_state_enter(struct sci_base_state_machine *sm) +static void sci_controller_ready_state_enter(struct sci_base_state_machine *sm) { struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); /* set the default interrupt coalescence number and timeout value. */ - scic_controller_set_interrupt_coalescence(ihost, 0x10, 250); + sci_controller_set_interrupt_coalescence(ihost, 0x10, 250); } -static void scic_sds_controller_ready_state_exit(struct sci_base_state_machine *sm) +static void sci_controller_ready_state_exit(struct sci_base_state_machine *sm) { struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); /* disable interrupt coalescence. */ - scic_controller_set_interrupt_coalescence(ihost, 0, 0); + sci_controller_set_interrupt_coalescence(ihost, 0, 0); } -static enum sci_status scic_sds_controller_stop_phys(struct isci_host *ihost) +static enum sci_status sci_controller_stop_phys(struct isci_host *ihost) { u32 index; enum sci_status status; @@ -1514,7 +1492,7 @@ static enum sci_status scic_sds_controller_stop_phys(struct isci_host *ihost) status = SCI_SUCCESS; for (index = 0; index < SCI_MAX_PHYS; index++) { - phy_status = scic_sds_phy_stop(&ihost->phys[index]); + phy_status = sci_phy_stop(&ihost->phys[index]); if (phy_status != SCI_SUCCESS && phy_status != SCI_FAILURE_INVALID_STATE) { @@ -1531,7 +1509,7 @@ static enum sci_status scic_sds_controller_stop_phys(struct isci_host *ihost) return status; } -static enum sci_status scic_sds_controller_stop_ports(struct isci_host *ihost) +static enum sci_status sci_controller_stop_ports(struct isci_host *ihost) { u32 index; enum sci_status port_status; @@ -1540,7 +1518,7 @@ static enum sci_status scic_sds_controller_stop_ports(struct isci_host *ihost) for (index = 0; index < ihost->logical_port_entries; index++) { struct isci_port *iport = &ihost->ports[index]; - port_status = scic_sds_port_stop(iport); + port_status = sci_port_stop(iport); if ((port_status != SCI_SUCCESS) && (port_status != SCI_FAILURE_INVALID_STATE)) { @@ -1558,7 +1536,7 @@ static enum sci_status scic_sds_controller_stop_ports(struct isci_host *ihost) return status; } -static enum sci_status scic_sds_controller_stop_devices(struct isci_host *ihost) +static enum sci_status sci_controller_stop_devices(struct isci_host *ihost) { u32 index; enum sci_status status; @@ -1569,7 +1547,7 @@ static enum sci_status scic_sds_controller_stop_devices(struct isci_host *ihost) for (index = 0; index < ihost->remote_node_entries; index++) { if (ihost->device_table[index] != NULL) { /* / @todo What timeout value do we want to provide to this request? */ - device_status = scic_remote_device_stop(ihost->device_table[index], 0); + device_status = sci_remote_device_stop(ihost->device_table[index], 0); if ((device_status != SCI_SUCCESS) && (device_status != SCI_FAILURE_INVALID_STATE)) { @@ -1586,33 +1564,27 @@ static enum sci_status scic_sds_controller_stop_devices(struct isci_host *ihost) return status; } -static void scic_sds_controller_stopping_state_enter(struct sci_base_state_machine *sm) +static void sci_controller_stopping_state_enter(struct sci_base_state_machine *sm) { struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); /* Stop all of the components for this controller */ - scic_sds_controller_stop_phys(ihost); - scic_sds_controller_stop_ports(ihost); - scic_sds_controller_stop_devices(ihost); + sci_controller_stop_phys(ihost); + sci_controller_stop_ports(ihost); + sci_controller_stop_devices(ihost); } -static void scic_sds_controller_stopping_state_exit(struct sci_base_state_machine *sm) +static void sci_controller_stopping_state_exit(struct sci_base_state_machine *sm) { struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); sci_del_timer(&ihost->timer); } - -/** - * scic_sds_controller_reset_hardware() - - * - * This method will reset the controller hardware. - */ -static void scic_sds_controller_reset_hardware(struct isci_host *ihost) +static void sci_controller_reset_hardware(struct isci_host *ihost) { /* Disable interrupts so we dont take any spurious interrupts */ - scic_controller_disable_interrupts(ihost); + sci_controller_disable_interrupts(ihost); /* Reset the SCU */ writel(0xFFFFFFFF, &ihost->smu_registers->soft_reset_control); @@ -1627,82 +1599,82 @@ static void scic_sds_controller_reset_hardware(struct isci_host *ihost) writel(0, &ihost->scu_registers->sdma.unsolicited_frame_get_pointer); } -static void scic_sds_controller_resetting_state_enter(struct sci_base_state_machine *sm) +static void sci_controller_resetting_state_enter(struct sci_base_state_machine *sm) { struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); - scic_sds_controller_reset_hardware(ihost); + sci_controller_reset_hardware(ihost); sci_change_state(&ihost->sm, SCIC_RESET); } -static const struct sci_base_state scic_sds_controller_state_table[] = { +static const struct sci_base_state sci_controller_state_table[] = { [SCIC_INITIAL] = { - .enter_state = scic_sds_controller_initial_state_enter, + .enter_state = sci_controller_initial_state_enter, }, [SCIC_RESET] = {}, [SCIC_INITIALIZING] = {}, [SCIC_INITIALIZED] = {}, [SCIC_STARTING] = { - .exit_state = scic_sds_controller_starting_state_exit, + .exit_state = sci_controller_starting_state_exit, }, [SCIC_READY] = { - .enter_state = scic_sds_controller_ready_state_enter, - .exit_state = scic_sds_controller_ready_state_exit, + .enter_state = sci_controller_ready_state_enter, + .exit_state = sci_controller_ready_state_exit, }, [SCIC_RESETTING] = { - .enter_state = scic_sds_controller_resetting_state_enter, + .enter_state = sci_controller_resetting_state_enter, }, [SCIC_STOPPING] = { - .enter_state = scic_sds_controller_stopping_state_enter, - .exit_state = scic_sds_controller_stopping_state_exit, + .enter_state = sci_controller_stopping_state_enter, + .exit_state = sci_controller_stopping_state_exit, }, [SCIC_STOPPED] = {}, [SCIC_FAILED] = {} }; -static void scic_sds_controller_set_default_config_parameters(struct isci_host *ihost) +static void sci_controller_set_default_config_parameters(struct isci_host *ihost) { /* these defaults are overridden by the platform / firmware */ u16 index; /* Default to APC mode. */ - ihost->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; + ihost->oem_parameters.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; /* Default to APC mode. */ - ihost->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1; + ihost->oem_parameters.controller.max_concurrent_dev_spin_up = 1; /* Default to no SSC operation. */ - ihost->oem_parameters.sds1.controller.do_enable_ssc = false; + ihost->oem_parameters.controller.do_enable_ssc = false; /* Initialize all of the port parameter information to narrow ports. */ for (index = 0; index < SCI_MAX_PORTS; index++) { - ihost->oem_parameters.sds1.ports[index].phy_mask = 0; + ihost->oem_parameters.ports[index].phy_mask = 0; } /* Initialize all of the phy parameter information. */ for (index = 0; index < SCI_MAX_PHYS; index++) { /* Default to 6G (i.e. Gen 3) for now. */ - ihost->user_parameters.sds1.phys[index].max_speed_generation = 3; + ihost->user_parameters.phys[index].max_speed_generation = 3; /* the frequencies cannot be 0 */ - ihost->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f; - ihost->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff; - ihost->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; + ihost->user_parameters.phys[index].align_insertion_frequency = 0x7f; + ihost->user_parameters.phys[index].in_connection_align_insertion_frequency = 0xff; + ihost->user_parameters.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; /* * Previous Vitesse based expanders had a arbitration issue that * is worked around by having the upper 32-bits of SAS address * with a value greater then the Vitesse company identifier. * Hence, usage of 0x5FCFFFFF. */ - ihost->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id; - ihost->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF; + ihost->oem_parameters.phys[index].sas_address.low = 0x1 + ihost->id; + ihost->oem_parameters.phys[index].sas_address.high = 0x5FCFFFFF; } - ihost->user_parameters.sds1.stp_inactivity_timeout = 5; - ihost->user_parameters.sds1.ssp_inactivity_timeout = 5; - ihost->user_parameters.sds1.stp_max_occupancy_timeout = 5; - ihost->user_parameters.sds1.ssp_max_occupancy_timeout = 20; - ihost->user_parameters.sds1.no_outbound_task_timeout = 20; + ihost->user_parameters.stp_inactivity_timeout = 5; + ihost->user_parameters.ssp_inactivity_timeout = 5; + ihost->user_parameters.stp_max_occupancy_timeout = 5; + ihost->user_parameters.ssp_max_occupancy_timeout = 20; + ihost->user_parameters.no_outbound_task_timeout = 20; } static void controller_timeout(unsigned long data) @@ -1718,7 +1690,7 @@ static void controller_timeout(unsigned long data) goto done; if (sm->current_state_id == SCIC_STARTING) - scic_sds_controller_transition_to_ready(ihost, SCI_FAILURE_TIMEOUT); + sci_controller_transition_to_ready(ihost, SCI_FAILURE_TIMEOUT); else if (sm->current_state_id == SCIC_STOPPING) { sci_change_state(sm, SCIC_FAILED); isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); @@ -1732,45 +1704,29 @@ done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } -/** - * scic_controller_construct() - This method will attempt to construct a - * controller object utilizing the supplied parameter information. - * @c: This parameter specifies the controller to be constructed. - * @scu_base: mapped base address of the scu registers - * @smu_base: mapped base address of the smu registers - * - * Indicate if the controller was successfully constructed or if it failed in - * some way. SCI_SUCCESS This value is returned if the controller was - * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned - * if the interrupt coalescence timer may cause SAS compliance issues for SMP - * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE - * This value is returned if the controller does not support the supplied type. - * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the - * controller does not support the supplied initialization data version. - */ -static enum sci_status scic_controller_construct(struct isci_host *ihost, - void __iomem *scu_base, - void __iomem *smu_base) +static enum sci_status sci_controller_construct(struct isci_host *ihost, + void __iomem *scu_base, + void __iomem *smu_base) { u8 i; - sci_init_sm(&ihost->sm, scic_sds_controller_state_table, SCIC_INITIAL); + sci_init_sm(&ihost->sm, sci_controller_state_table, SCIC_INITIAL); ihost->scu_registers = scu_base; ihost->smu_registers = smu_base; - scic_sds_port_configuration_agent_construct(&ihost->port_agent); + sci_port_configuration_agent_construct(&ihost->port_agent); /* Construct the ports for this controller */ for (i = 0; i < SCI_MAX_PORTS; i++) - scic_sds_port_construct(&ihost->ports[i], i, ihost); - scic_sds_port_construct(&ihost->ports[i], SCIC_SDS_DUMMY_PORT, ihost); + sci_port_construct(&ihost->ports[i], i, ihost); + sci_port_construct(&ihost->ports[i], SCIC_SDS_DUMMY_PORT, ihost); /* Construct the phys for this controller */ for (i = 0; i < SCI_MAX_PHYS; i++) { /* Add all the PHYs to the dummy port */ - scic_sds_phy_construct(&ihost->phys[i], - &ihost->ports[SCI_MAX_PORTS], i); + sci_phy_construct(&ihost->phys[i], + &ihost->ports[SCI_MAX_PORTS], i); } ihost->invalid_phy_mask = 0; @@ -1778,12 +1734,12 @@ static enum sci_status scic_controller_construct(struct isci_host *ihost, sci_init_timer(&ihost->timer, controller_timeout); /* Initialize the User and OEM parameters to default values. */ - scic_sds_controller_set_default_config_parameters(ihost); + sci_controller_set_default_config_parameters(ihost); - return scic_controller_reset(ihost); + return sci_controller_reset(ihost); } -int scic_oem_parameters_validate(struct scic_sds_oem_params *oem) +int sci_oem_parameters_validate(struct sci_oem_params *oem) { int i; @@ -1817,8 +1773,7 @@ int scic_oem_parameters_validate(struct scic_sds_oem_params *oem) return 0; } -static enum sci_status scic_oem_parameters_set(struct isci_host *ihost, - union scic_oem_parameters *scic_parms) +static enum sci_status sci_oem_parameters_set(struct isci_host *ihost) { u32 state = ihost->sm.current_state_id; @@ -1826,9 +1781,8 @@ static enum sci_status scic_oem_parameters_set(struct isci_host *ihost, state == SCIC_INITIALIZING || state == SCIC_INITIALIZED) { - if (scic_oem_parameters_validate(&scic_parms->sds1)) + if (sci_oem_parameters_validate(&ihost->oem_parameters)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - ihost->oem_parameters.sds1 = scic_parms->sds1; return SCI_SUCCESS; } @@ -1836,13 +1790,6 @@ static enum sci_status scic_oem_parameters_set(struct isci_host *ihost, return SCI_FAILURE_INVALID_STATE; } -void scic_oem_parameters_get( - struct isci_host *ihost, - union scic_oem_parameters *scic_parms) -{ - memcpy(scic_parms, (&ihost->oem_parameters), sizeof(*scic_parms)); -} - static void power_control_timeout(unsigned long data) { struct sci_timer *tmr = (struct sci_timer *)data; @@ -1873,13 +1820,13 @@ static void power_control_timeout(unsigned long data) continue; if (ihost->power_control.phys_granted_power >= - ihost->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) + ihost->oem_parameters.controller.max_concurrent_dev_spin_up) break; ihost->power_control.requesters[i] = NULL; ihost->power_control.phys_waiting--; ihost->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(iphy); + sci_phy_consume_power_handler(iphy); } /* @@ -1893,22 +1840,15 @@ done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } -/** - * This method inserts the phy in the stagger spinup control queue. - * @scic: - * - * - */ -void scic_sds_controller_power_control_queue_insert( - struct isci_host *ihost, - struct isci_phy *iphy) +void sci_controller_power_control_queue_insert(struct isci_host *ihost, + struct isci_phy *iphy) { BUG_ON(iphy == NULL); if (ihost->power_control.phys_granted_power < - ihost->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) { + ihost->oem_parameters.controller.max_concurrent_dev_spin_up) { ihost->power_control.phys_granted_power++; - scic_sds_phy_consume_power_handler(iphy); + sci_phy_consume_power_handler(iphy); /* * stop and start the power_control timer. When the timer fires, the @@ -1928,21 +1868,13 @@ void scic_sds_controller_power_control_queue_insert( } } -/** - * This method removes the phy from the stagger spinup control queue. - * @scic: - * - * - */ -void scic_sds_controller_power_control_queue_remove( - struct isci_host *ihost, - struct isci_phy *iphy) +void sci_controller_power_control_queue_remove(struct isci_host *ihost, + struct isci_phy *iphy) { BUG_ON(iphy == NULL); - if (ihost->power_control.requesters[iphy->phy_index] != NULL) { + if (ihost->power_control.requesters[iphy->phy_index]) ihost->power_control.phys_waiting--; - } ihost->power_control.requesters[iphy->phy_index] = NULL; } @@ -1952,9 +1884,9 @@ void scic_sds_controller_power_control_queue_remove( /* Initialize the AFE for this phy index. We need to read the AFE setup from * the OEM parameters */ -static void scic_sds_controller_afe_initialization(struct isci_host *ihost) +static void sci_controller_afe_initialization(struct isci_host *ihost) { - const struct scic_sds_oem_params *oem = &ihost->oem_parameters.sds1; + const struct sci_oem_params *oem = &ihost->oem_parameters; u32 afe_status; u32 phy_id; @@ -2111,7 +2043,7 @@ static void scic_sds_controller_afe_initialization(struct isci_host *ihost) udelay(AFE_REGISTER_WRITE_DELAY); } -static void scic_sds_controller_initialize_power_control(struct isci_host *ihost) +static void sci_controller_initialize_power_control(struct isci_host *ihost) { sci_init_timer(&ihost->power_control.timer, power_control_timeout); @@ -2122,7 +2054,7 @@ static void scic_sds_controller_initialize_power_control(struct isci_host *ihost ihost->power_control.phys_granted_power = 0; } -static enum sci_status scic_controller_initialize(struct isci_host *ihost) +static enum sci_status sci_controller_initialize(struct isci_host *ihost) { struct sci_base_state_machine *sm = &ihost->sm; enum sci_status result = SCI_FAILURE; @@ -2142,14 +2074,14 @@ static enum sci_status scic_controller_initialize(struct isci_host *ihost) ihost->next_phy_to_start = 0; ihost->phy_startup_timer_pending = false; - scic_sds_controller_initialize_power_control(ihost); + sci_controller_initialize_power_control(ihost); /* * There is nothing to do here for B0 since we do not have to * program the AFE registers. * / @todo The AFE settings are supposed to be correct for the B0 but * / presently they seem to be wrong. */ - scic_sds_controller_afe_initialization(ihost); + sci_controller_afe_initialization(ihost); /* Take the hardware out of reset */ @@ -2206,24 +2138,22 @@ static enum sci_status scic_controller_initialize(struct isci_host *ihost) * are accessed during the port initialization. */ for (i = 0; i < SCI_MAX_PHYS; i++) { - result = scic_sds_phy_initialize(&ihost->phys[i], - &ihost->scu_registers->peg0.pe[i].tl, - &ihost->scu_registers->peg0.pe[i].ll); + result = sci_phy_initialize(&ihost->phys[i], + &ihost->scu_registers->peg0.pe[i].tl, + &ihost->scu_registers->peg0.pe[i].ll); if (result != SCI_SUCCESS) goto out; } for (i = 0; i < ihost->logical_port_entries; i++) { - result = scic_sds_port_initialize(&ihost->ports[i], - &ihost->scu_registers->peg0.ptsg.port[i], - &ihost->scu_registers->peg0.ptsg.protocol_engine, - &ihost->scu_registers->peg0.viit[i]); + struct isci_port *iport = &ihost->ports[i]; - if (result != SCI_SUCCESS) - goto out; + iport->port_task_scheduler_registers = &ihost->scu_registers->peg0.ptsg.port[i]; + iport->port_pe_configuration_register = &ihost->scu_registers->peg0.ptsg.protocol_engine[0]; + iport->viit_registers = &ihost->scu_registers->peg0.viit[i]; } - result = scic_sds_port_configuration_agent_initialize(ihost, &ihost->port_agent); + result = sci_port_configuration_agent_initialize(ihost, &ihost->port_agent); out: /* Advance the controller state machine */ @@ -2236,9 +2166,8 @@ static enum sci_status scic_controller_initialize(struct isci_host *ihost) return result; } -static enum sci_status scic_user_parameters_set( - struct isci_host *ihost, - union scic_user_parameters *scic_parms) +static enum sci_status sci_user_parameters_set(struct isci_host *ihost, + struct sci_user_parameters *sci_parms) { u32 state = ihost->sm.current_state_id; @@ -2254,7 +2183,7 @@ static enum sci_status scic_user_parameters_set( for (index = 0; index < SCI_MAX_PHYS; index++) { struct sci_phy_user_params *user_phy; - user_phy = &scic_parms->sds1.phys[index]; + user_phy = &sci_parms->phys[index]; if (!((user_phy->max_speed_generation <= SCIC_SDS_PARM_MAX_SPEED) && @@ -2275,14 +2204,14 @@ static enum sci_status scic_user_parameters_set( return SCI_FAILURE_INVALID_PARAMETER_VALUE; } - if ((scic_parms->sds1.stp_inactivity_timeout == 0) || - (scic_parms->sds1.ssp_inactivity_timeout == 0) || - (scic_parms->sds1.stp_max_occupancy_timeout == 0) || - (scic_parms->sds1.ssp_max_occupancy_timeout == 0) || - (scic_parms->sds1.no_outbound_task_timeout == 0)) + if ((sci_parms->stp_inactivity_timeout == 0) || + (sci_parms->ssp_inactivity_timeout == 0) || + (sci_parms->stp_max_occupancy_timeout == 0) || + (sci_parms->ssp_max_occupancy_timeout == 0) || + (sci_parms->no_outbound_task_timeout == 0)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; - memcpy(&ihost->user_parameters, scic_parms, sizeof(*scic_parms)); + memcpy(&ihost->user_parameters, sci_parms, sizeof(*sci_parms)); return SCI_SUCCESS; } @@ -2290,7 +2219,7 @@ static enum sci_status scic_user_parameters_set( return SCI_FAILURE_INVALID_STATE; } -static int scic_controller_mem_init(struct isci_host *ihost) +static int sci_controller_mem_init(struct isci_host *ihost) { struct device *dev = &ihost->pdev->dev; dma_addr_t dma; @@ -2307,7 +2236,7 @@ static int scic_controller_mem_init(struct isci_host *ihost) size = ihost->remote_node_entries * sizeof(union scu_remote_node_context); ihost->remote_node_context_table = dmam_alloc_coherent(dev, size, &dma, - GFP_KERNEL); + GFP_KERNEL); if (!ihost->remote_node_context_table) return -ENOMEM; @@ -2323,7 +2252,7 @@ static int scic_controller_mem_init(struct isci_host *ihost) writel(lower_32_bits(dma), &ihost->smu_registers->host_task_table_lower); writel(upper_32_bits(dma), &ihost->smu_registers->host_task_table_upper); - err = scic_sds_unsolicited_frame_control_construct(ihost); + err = sci_unsolicited_frame_control_construct(ihost); if (err) return err; @@ -2348,8 +2277,7 @@ int isci_host_init(struct isci_host *ihost) { int err = 0, i; enum sci_status status; - union scic_oem_parameters oem; - union scic_user_parameters scic_user_params; + struct sci_user_parameters sci_user_params; struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); spin_lock_init(&ihost->state_lock); @@ -2358,12 +2286,12 @@ int isci_host_init(struct isci_host *ihost) isci_host_change_state(ihost, isci_starting); - status = scic_controller_construct(ihost, scu_base(ihost), - smu_base(ihost)); + status = sci_controller_construct(ihost, scu_base(ihost), + smu_base(ihost)); if (status != SCI_SUCCESS) { dev_err(&ihost->pdev->dev, - "%s: scic_controller_construct failed - status = %x\n", + "%s: sci_controller_construct failed - status = %x\n", __func__, status); return -ENODEV; @@ -2376,21 +2304,18 @@ int isci_host_init(struct isci_host *ihost) * grab initial values stored in the controller object for OEM and USER * parameters */ - isci_user_parameters_get(ihost, &scic_user_params); - status = scic_user_parameters_set(ihost, - &scic_user_params); + isci_user_parameters_get(&sci_user_params); + status = sci_user_parameters_set(ihost, &sci_user_params); if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, - "%s: scic_user_parameters_set failed\n", + "%s: sci_user_parameters_set failed\n", __func__); return -ENODEV; } - scic_oem_parameters_get(ihost, &oem); - /* grab any OEM parameters specified in orom */ if (pci_info->orom) { - status = isci_parse_oem_parameters(&oem, + status = isci_parse_oem_parameters(&ihost->oem_parameters, pci_info->orom, ihost->id); if (status != SCI_SUCCESS) { @@ -2400,10 +2325,10 @@ int isci_host_init(struct isci_host *ihost) } } - status = scic_oem_parameters_set(ihost, &oem); + status = sci_oem_parameters_set(ihost); if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, - "%s: scic_oem_parameters_set failed\n", + "%s: sci_oem_parameters_set failed\n", __func__); return -ENODEV; } @@ -2415,17 +2340,17 @@ int isci_host_init(struct isci_host *ihost) INIT_LIST_HEAD(&ihost->requests_to_errorback); spin_lock_irq(&ihost->scic_lock); - status = scic_controller_initialize(ihost); + status = sci_controller_initialize(ihost); spin_unlock_irq(&ihost->scic_lock); if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, - "%s: scic_controller_initialize failed -" + "%s: sci_controller_initialize failed -" " status = 0x%x\n", __func__, status); return -ENODEV; } - err = scic_controller_mem_init(ihost); + err = sci_controller_mem_init(ihost); if (err) return err; @@ -2463,20 +2388,20 @@ int isci_host_init(struct isci_host *ihost) return 0; } -void scic_sds_controller_link_up(struct isci_host *ihost, - struct isci_port *iport, struct isci_phy *iphy) +void sci_controller_link_up(struct isci_host *ihost, struct isci_port *iport, + struct isci_phy *iphy) { switch (ihost->sm.current_state_id) { case SCIC_STARTING: sci_del_timer(&ihost->phy_timer); ihost->phy_startup_timer_pending = false; ihost->port_agent.link_up_handler(ihost, &ihost->port_agent, - iport, iphy); - scic_sds_controller_start_next_phy(ihost); + iport, iphy); + sci_controller_start_next_phy(ihost); break; case SCIC_READY: ihost->port_agent.link_up_handler(ihost, &ihost->port_agent, - iport, iphy); + iport, iphy); break; default: dev_dbg(&ihost->pdev->dev, @@ -2486,8 +2411,8 @@ void scic_sds_controller_link_up(struct isci_host *ihost, } } -void scic_sds_controller_link_down(struct isci_host *ihost, - struct isci_port *iport, struct isci_phy *iphy) +void sci_controller_link_down(struct isci_host *ihost, struct isci_port *iport, + struct isci_phy *iphy) { switch (ihost->sm.current_state_id) { case SCIC_STARTING: @@ -2505,12 +2430,7 @@ void scic_sds_controller_link_down(struct isci_host *ihost, } } -/** - * This is a helper method to determine if any remote devices on this - * controller are still in the stopping state. - * - */ -static bool scic_sds_controller_has_remote_devices_stopping(struct isci_host *ihost) +static bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost) { u32 index; @@ -2523,12 +2443,8 @@ static bool scic_sds_controller_has_remote_devices_stopping(struct isci_host *ih return false; } -/** - * This method is called by the remote device to inform the controller - * object that the remote device has stopped. - */ -void scic_sds_controller_remote_device_stopped(struct isci_host *ihost, - struct isci_remote_device *idev) +void sci_controller_remote_device_stopped(struct isci_host *ihost, + struct isci_remote_device *idev) { if (ihost->sm.current_state_id != SCIC_STOPPING) { dev_dbg(&ihost->pdev->dev, @@ -2539,32 +2455,19 @@ void scic_sds_controller_remote_device_stopped(struct isci_host *ihost, return; } - if (!scic_sds_controller_has_remote_devices_stopping(ihost)) { + if (!sci_controller_has_remote_devices_stopping(ihost)) sci_change_state(&ihost->sm, SCIC_STOPPED); - } } -/** - * This method will write to the SCU PCP register the request value. The method - * is used to suspend/resume ports, devices, and phys. - * @scic: - * - * - */ -void scic_sds_controller_post_request( - struct isci_host *ihost, - u32 request) +void sci_controller_post_request(struct isci_host *ihost, u32 request) { - dev_dbg(&ihost->pdev->dev, - "%s: SCIC Controller 0x%p post request 0x%08x\n", - __func__, - ihost, - request); + dev_dbg(&ihost->pdev->dev, "%s[%d]: %#x\n", + __func__, ihost->id, request); writel(request, &ihost->smu_registers->post_context_port); } -struct isci_request *scic_request_by_tag(struct isci_host *ihost, u16 io_tag) +struct isci_request *sci_request_by_tag(struct isci_host *ihost, u16 io_tag) { u16 task_index; u16 task_sequence; @@ -2599,15 +2502,14 @@ struct isci_request *scic_request_by_tag(struct isci_host *ihost, u16 io_tag) * enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote * node index available. */ -enum sci_status scic_sds_controller_allocate_remote_node_context( - struct isci_host *ihost, - struct isci_remote_device *idev, - u16 *node_id) +enum sci_status sci_controller_allocate_remote_node_context(struct isci_host *ihost, + struct isci_remote_device *idev, + u16 *node_id) { u16 node_index; - u32 remote_node_count = scic_sds_remote_device_node_count(idev); + u32 remote_node_count = sci_remote_device_node_count(idev); - node_index = scic_sds_remote_node_table_allocate_remote_node( + node_index = sci_remote_node_table_allocate_remote_node( &ihost->available_remote_nodes, remote_node_count ); @@ -2622,68 +2524,26 @@ enum sci_status scic_sds_controller_allocate_remote_node_context( return SCI_FAILURE_INSUFFICIENT_RESOURCES; } -/** - * This method frees the remote node index back to the available pool. Once - * this is done the remote node context buffer is no longer valid and can - * not be used. - * @scic: - * @sci_dev: - * @node_id: - * - */ -void scic_sds_controller_free_remote_node_context( - struct isci_host *ihost, - struct isci_remote_device *idev, - u16 node_id) +void sci_controller_free_remote_node_context(struct isci_host *ihost, + struct isci_remote_device *idev, + u16 node_id) { - u32 remote_node_count = scic_sds_remote_device_node_count(idev); + u32 remote_node_count = sci_remote_device_node_count(idev); if (ihost->device_table[node_id] == idev) { ihost->device_table[node_id] = NULL; - scic_sds_remote_node_table_release_remote_node_index( + sci_remote_node_table_release_remote_node_index( &ihost->available_remote_nodes, remote_node_count, node_id ); } } -/** - * This method returns the union scu_remote_node_context for the specified remote - * node id. - * @scic: - * @node_id: - * - * union scu_remote_node_context* - */ -union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( - struct isci_host *ihost, - u16 node_id - ) { - if ( - (node_id < ihost->remote_node_entries) - && (ihost->device_table[node_id] != NULL) - ) { - return &ihost->remote_node_context_table[node_id]; - } - - return NULL; -} - -/** - * - * @resposne_buffer: This is the buffer into which the D2H register FIS will be - * constructed. - * @frame_header: This is the frame header returned by the hardware. - * @frame_buffer: This is the frame buffer returned by the hardware. - * - * This method will combind the frame header and frame buffer to create a SATA - * D2H register FIS none - */ -void scic_sds_controller_copy_sata_response( - void *response_buffer, - void *frame_header, - void *frame_buffer) +void sci_controller_copy_sata_response(void *response_buffer, + void *frame_header, + void *frame_buffer) { + /* XXX type safety? */ memcpy(response_buffer, frame_header, sizeof(u32)); memcpy(response_buffer + sizeof(u32), @@ -2691,21 +2551,9 @@ void scic_sds_controller_copy_sata_response( sizeof(struct dev_to_host_fis) - sizeof(u32)); } -/** - * This method releases the frame once this is done the frame is available for - * re-use by the hardware. The data contained in the frame header and frame - * buffer is no longer valid. The UF queue get pointer is only updated if UF - * control indicates this is appropriate. - * @scic: - * @frame_index: - * - */ -void scic_sds_controller_release_frame( - struct isci_host *ihost, - u32 frame_index) +void sci_controller_release_frame(struct isci_host *ihost, u32 frame_index) { - if (scic_sds_unsolicited_frame_control_release_frame( - &ihost->uf_control, frame_index) == true) + if (sci_unsolicited_frame_control_release_frame(&ihost->uf_control, frame_index)) writel(ihost->uf_control.get, &ihost->scu_registers->sdma.unsolicited_frame_get_pointer); } @@ -2763,21 +2611,9 @@ enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag) return SCI_FAILURE_INVALID_IO_TAG; } -/** - * scic_controller_start_io() - This method is called by the SCI user to - * send/start an IO request. If the method invocation is successful, then - * the IO request has been queued to the hardware for processing. - * @controller: the handle to the controller object for which to start an IO - * request. - * @remote_device: the handle to the remote device object for which to start an - * IO request. - * @io_request: the handle to the io request object to start. - * @io_tag: This parameter specifies a previously allocated IO tag that the - * user desires to be utilized for this request. - */ -enum sci_status scic_controller_start_io(struct isci_host *ihost, - struct isci_remote_device *idev, - struct isci_request *ireq) +enum sci_status sci_controller_start_io(struct isci_host *ihost, + struct isci_remote_device *idev, + struct isci_request *ireq) { enum sci_status status; @@ -2786,36 +2622,23 @@ enum sci_status scic_controller_start_io(struct isci_host *ihost, return SCI_FAILURE_INVALID_STATE; } - status = scic_sds_remote_device_start_io(ihost, idev, ireq); + status = sci_remote_device_start_io(ihost, idev, ireq); if (status != SCI_SUCCESS) return status; set_bit(IREQ_ACTIVE, &ireq->flags); - scic_sds_controller_post_request(ihost, scic_sds_request_get_post_context(ireq)); + sci_controller_post_request(ihost, sci_request_get_post_context(ireq)); return SCI_SUCCESS; } -/** - * scic_controller_terminate_request() - This method is called by the SCI Core - * user to terminate an ongoing (i.e. started) core IO request. This does - * not abort the IO request at the target, but rather removes the IO request - * from the host controller. - * @controller: the handle to the controller object for which to terminate a - * request. - * @remote_device: the handle to the remote device object for which to - * terminate a request. - * @request: the handle to the io or task management request object to - * terminate. - * - * Indicate if the controller successfully began the terminate process for the - * IO request. SCI_SUCCESS if the terminate process was successfully started - * for the request. Determine the failure situations and return values. - */ -enum sci_status scic_controller_terminate_request( - struct isci_host *ihost, - struct isci_remote_device *idev, - struct isci_request *ireq) +enum sci_status sci_controller_terminate_request(struct isci_host *ihost, + struct isci_remote_device *idev, + struct isci_request *ireq) { + /* terminate an ongoing (i.e. started) core IO request. This does not + * abort the IO request at the target, but rather removes the IO + * request from the host controller. + */ enum sci_status status; if (ihost->sm.current_state_id != SCIC_READY) { @@ -2824,7 +2647,7 @@ enum sci_status scic_controller_terminate_request( return SCI_FAILURE_INVALID_STATE; } - status = scic_sds_io_request_terminate(ireq); + status = sci_io_request_terminate(ireq); if (status != SCI_SUCCESS) return status; @@ -2832,27 +2655,25 @@ enum sci_status scic_controller_terminate_request( * Utilize the original post context command and or in the POST_TC_ABORT * request sub-type. */ - scic_sds_controller_post_request(ihost, - scic_sds_request_get_post_context(ireq) | - SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); + sci_controller_post_request(ihost, + ireq->post_context | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); return SCI_SUCCESS; } /** - * scic_controller_complete_io() - This method will perform core specific + * sci_controller_complete_io() - This method will perform core specific * completion operations for an IO request. After this method is invoked, * the user should consider the IO request as invalid until it is properly * reused (i.e. re-constructed). - * @controller: The handle to the controller object for which to complete the + * @ihost: The handle to the controller object for which to complete the * IO request. - * @remote_device: The handle to the remote device object for which to complete + * @idev: The handle to the remote device object for which to complete * the IO request. - * @io_request: the handle to the io request object to complete. + * @ireq: the handle to the io request object to complete. */ -enum sci_status scic_controller_complete_io( - struct isci_host *ihost, - struct isci_remote_device *idev, - struct isci_request *ireq) +enum sci_status sci_controller_complete_io(struct isci_host *ihost, + struct isci_remote_device *idev, + struct isci_request *ireq) { enum sci_status status; u16 index; @@ -2862,7 +2683,7 @@ enum sci_status scic_controller_complete_io( /* XXX: Implement this function */ return SCI_FAILURE; case SCIC_READY: - status = scic_sds_remote_device_complete_io(ihost, idev, ireq); + status = sci_remote_device_complete_io(ihost, idev, ireq); if (status != SCI_SUCCESS) return status; @@ -2876,7 +2697,7 @@ enum sci_status scic_controller_complete_io( } -enum sci_status scic_controller_continue_io(struct isci_request *ireq) +enum sci_status sci_controller_continue_io(struct isci_request *ireq) { struct isci_host *ihost = ireq->owning_controller; @@ -2886,12 +2707,12 @@ enum sci_status scic_controller_continue_io(struct isci_request *ireq) } set_bit(IREQ_ACTIVE, &ireq->flags); - scic_sds_controller_post_request(ihost, scic_sds_request_get_post_context(ireq)); + sci_controller_post_request(ihost, sci_request_get_post_context(ireq)); return SCI_SUCCESS; } /** - * scic_controller_start_task() - This method is called by the SCIC user to + * sci_controller_start_task() - This method is called by the SCIC user to * send/start a framework task management request. * @controller: the handle to the controller object for which to start the task * management request. @@ -2899,10 +2720,9 @@ enum sci_status scic_controller_continue_io(struct isci_request *ireq) * the task management request. * @task_request: the handle to the task request object to start. */ -enum sci_task_status scic_controller_start_task( - struct isci_host *ihost, - struct isci_remote_device *idev, - struct isci_request *ireq) +enum sci_task_status sci_controller_start_task(struct isci_host *ihost, + struct isci_remote_device *idev, + struct isci_request *ireq) { enum sci_status status; @@ -2914,7 +2734,7 @@ enum sci_task_status scic_controller_start_task( return SCI_TASK_FAILURE_INVALID_STATE; } - status = scic_sds_remote_device_start_task(ihost, idev, ireq); + status = sci_remote_device_start_task(ihost, idev, ireq); switch (status) { case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: set_bit(IREQ_ACTIVE, &ireq->flags); @@ -2928,8 +2748,8 @@ enum sci_task_status scic_controller_start_task( case SCI_SUCCESS: set_bit(IREQ_ACTIVE, &ireq->flags); - scic_sds_controller_post_request(ihost, - scic_sds_request_get_post_context(ireq)); + sci_controller_post_request(ihost, + sci_request_get_post_context(ireq)); break; default: break; diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 013f672a8fd7..d87f21de1807 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -69,12 +69,12 @@ struct scu_task_context; /** - * struct scic_power_control - + * struct sci_power_control - * * This structure defines the fields for managing power control for direct * attached disk devices. */ -struct scic_power_control { +struct sci_power_control { /** * This field is set when the power control timer is running and cleared when * it is not. @@ -99,18 +99,18 @@ struct scic_power_control { /** * This field is an array of phys that we are waiting on. The phys are direct - * mapped into requesters via struct scic_sds_phy.phy_index + * mapped into requesters via struct sci_phy.phy_index */ struct isci_phy *requesters[SCI_MAX_PHYS]; }; -struct scic_sds_port_configuration_agent; +struct sci_port_configuration_agent; typedef void (*port_config_fn)(struct isci_host *, - struct scic_sds_port_configuration_agent *, + struct sci_port_configuration_agent *, struct isci_port *, struct isci_phy *); -struct scic_sds_port_configuration_agent { +struct sci_port_configuration_agent { u16 phy_configured_mask; u16 phy_ready_mask; struct { @@ -149,13 +149,13 @@ struct isci_host { /* XXX can we time this externally */ struct sci_timer timer; /* XXX drop reference module params directly */ - union scic_user_parameters user_parameters; + struct sci_user_parameters user_parameters; /* XXX no need to be a union */ - union scic_oem_parameters oem_parameters; - struct scic_sds_port_configuration_agent port_agent; + struct sci_oem_params oem_parameters; + struct sci_port_configuration_agent port_agent; struct isci_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; - struct scic_remote_node_table available_remote_nodes; - struct scic_power_control power_control; + struct sci_remote_node_table available_remote_nodes; + struct sci_power_control power_control; u8 io_request_sequence[SCI_MAX_IO_REQUESTS]; struct scu_task_context *task_context_table; dma_addr_t task_context_dma; @@ -165,7 +165,7 @@ struct isci_host { u32 logical_port_entries; u32 remote_node_entries; u32 task_context_entries; - struct scic_sds_unsolicited_frame_control uf_control; + struct sci_unsolicited_frame_control uf_control; /* phy startup */ struct sci_timer phy_timer; @@ -206,10 +206,10 @@ struct isci_host { }; /** - * enum scic_sds_controller_states - This enumeration depicts all the states + * enum sci_controller_states - This enumeration depicts all the states * for the common controller state machine. */ -enum scic_sds_controller_states { +enum sci_controller_states { /** * Simply the initial state for the base controller state machine. */ @@ -360,14 +360,14 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev) } /** - * scic_sds_controller_get_protocol_engine_group() - + * sci_controller_get_protocol_engine_group() - * * This macro returns the protocol engine group for this controller object. * Presently we only support protocol engine group 0 so just return that */ -#define scic_sds_controller_get_protocol_engine_group(controller) 0 +#define sci_controller_get_protocol_engine_group(controller) 0 -/* see scic_controller_io_tag_allocate|free for how seq and tci are built */ +/* see sci_controller_io_tag_allocate|free for how seq and tci are built */ #define ISCI_TAG(seq, tci) (((u16) (seq)) << 12 | tci) /* these are returned by the hardware, so sanitize them */ @@ -375,7 +375,7 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev) #define ISCI_TAG_TCI(tag) ((tag) & (SCI_MAX_IO_REQUESTS-1)) /* expander attached sata devices require 3 rnc slots */ -static inline int scic_sds_remote_device_node_count(struct isci_remote_device *idev) +static inline int sci_remote_device_node_count(struct isci_remote_device *idev) { struct domain_device *dev = idev->domain_dev; @@ -386,23 +386,23 @@ static inline int scic_sds_remote_device_node_count(struct isci_remote_device *i } /** - * scic_sds_controller_set_invalid_phy() - + * sci_controller_set_invalid_phy() - * * This macro will set the bit in the invalid phy mask for this controller * object. This is used to control messages reported for invalid link up * notifications. */ -#define scic_sds_controller_set_invalid_phy(controller, phy) \ +#define sci_controller_set_invalid_phy(controller, phy) \ ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index)) /** - * scic_sds_controller_clear_invalid_phy() - + * sci_controller_clear_invalid_phy() - * * This macro will clear the bit in the invalid phy mask for this controller * object. This is used to control messages reported for invalid link up * notifications. */ -#define scic_sds_controller_clear_invalid_phy(controller, phy) \ +#define sci_controller_clear_invalid_phy(controller, phy) \ ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) static inline struct device *sciphy_to_dev(struct isci_phy *iphy) @@ -460,56 +460,53 @@ static inline bool is_c0(void) return isci_si_rev > ISCI_SI_REVB0; } -void scic_sds_controller_post_request(struct isci_host *ihost, +void sci_controller_post_request(struct isci_host *ihost, u32 request); -void scic_sds_controller_release_frame(struct isci_host *ihost, +void sci_controller_release_frame(struct isci_host *ihost, u32 frame_index); -void scic_sds_controller_copy_sata_response(void *response_buffer, +void sci_controller_copy_sata_response(void *response_buffer, void *frame_header, void *frame_buffer); -enum sci_status scic_sds_controller_allocate_remote_node_context(struct isci_host *ihost, +enum sci_status sci_controller_allocate_remote_node_context(struct isci_host *ihost, struct isci_remote_device *idev, u16 *node_id); -void scic_sds_controller_free_remote_node_context( +void sci_controller_free_remote_node_context( struct isci_host *ihost, struct isci_remote_device *idev, u16 node_id); -union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( - struct isci_host *ihost, - u16 node_id); -struct isci_request *scic_request_by_tag(struct isci_host *ihost, +struct isci_request *sci_request_by_tag(struct isci_host *ihost, u16 io_tag); -void scic_sds_controller_power_control_queue_insert( +void sci_controller_power_control_queue_insert( struct isci_host *ihost, struct isci_phy *iphy); -void scic_sds_controller_power_control_queue_remove( +void sci_controller_power_control_queue_remove( struct isci_host *ihost, struct isci_phy *iphy); -void scic_sds_controller_link_up( +void sci_controller_link_up( struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy); -void scic_sds_controller_link_down( +void sci_controller_link_down( struct isci_host *ihost, struct isci_port *iport, struct isci_phy *iphy); -void scic_sds_controller_remote_device_stopped( +void sci_controller_remote_device_stopped( struct isci_host *ihost, struct isci_remote_device *idev); -void scic_sds_controller_copy_task_context( +void sci_controller_copy_task_context( struct isci_host *ihost, struct isci_request *ireq); -void scic_sds_controller_register_setup(struct isci_host *ihost); +void sci_controller_register_setup(struct isci_host *ihost); -enum sci_status scic_controller_continue_io(struct isci_request *ireq); +enum sci_status sci_controller_continue_io(struct isci_request *ireq); int isci_host_scan_finished(struct Scsi_Host *, unsigned long); void isci_host_scan_start(struct Scsi_Host *); u16 isci_alloc_tag(struct isci_host *ihost); @@ -536,33 +533,33 @@ void isci_host_remote_device_start_complete( struct isci_remote_device *, enum sci_status); -void scic_controller_disable_interrupts( +void sci_controller_disable_interrupts( struct isci_host *ihost); -enum sci_status scic_controller_start_io( +enum sci_status sci_controller_start_io( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); -enum sci_task_status scic_controller_start_task( +enum sci_task_status sci_controller_start_task( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); -enum sci_status scic_controller_terminate_request( +enum sci_status sci_controller_terminate_request( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); -enum sci_status scic_controller_complete_io( +enum sci_status sci_controller_complete_io( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); -void scic_sds_port_configuration_agent_construct( - struct scic_sds_port_configuration_agent *port_agent); +void sci_port_configuration_agent_construct( + struct sci_port_configuration_agent *port_agent); -enum sci_status scic_sds_port_configuration_agent_initialize( +enum sci_status sci_port_configuration_agent_initialize( struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent); + struct sci_port_configuration_agent *port_agent); #endif diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 68ca1a4f30af..8d9a8bfff4d5 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -484,7 +484,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic orom = isci_request_oprom(pdev); for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) { - if (scic_oem_parameters_validate(&orom->ctrl[i])) { + if (sci_oem_parameters_validate(&orom->ctrl[i])) { dev_warn(&pdev->dev, "[%d]: invalid oem parameters detected, falling back to firmware\n", i); devm_kfree(&pdev->dev, orom); @@ -554,7 +554,7 @@ static void __devexit isci_pci_remove(struct pci_dev *pdev) for_each_isci_host(i, ihost, pdev) { isci_unregister(ihost); isci_host_deinit(ihost); - scic_controller_disable_interrupts(ihost); + sci_controller_disable_interrupts(ihost); } } diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 207328369edd..3afccfcb94e1 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -304,7 +304,7 @@ enum sci_status { * This member indicates that the operation failed, the failure is * controller implementation specific, and the response data associated * with the request is not valid. You can query for the controller - * specific error information via scic_controller_get_request_status() + * specific error information via sci_controller_get_request_status() */ SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, @@ -395,7 +395,7 @@ enum sci_status { /** * This value indicates that an unsupported PCI device ID has been * specified. This indicates that attempts to invoke - * scic_library_allocate_controller() will fail. + * sci_library_allocate_controller() will fail. */ SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID @@ -493,7 +493,7 @@ irqreturn_t isci_error_isr(int vec, void *data); /* * Each timer is associated with a cancellation flag that is set when * del_timer() is called and checked in the timer callback function. This - * is needed since del_timer_sync() cannot be called with scic_lock held. + * is needed since del_timer_sync() cannot be called with sci_lock held. * For deinit however, del_timer_sync() is used without holding the lock. */ struct sci_timer { diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index ca96b5ad0d52..0df9f713f487 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -67,25 +67,13 @@ enum sas_linkrate sci_phy_linkrate(struct isci_phy *iphy) return iphy->max_negotiated_speed; } -/* - * ***************************************************************************** - * * SCIC SDS PHY Internal Methods - * ***************************************************************************** */ - -/** - * This method will initialize the phy transport layer registers - * @sci_phy: - * @transport_layer_registers - * - * enum sci_status - */ -static enum sci_status scic_sds_phy_transport_layer_initialization( - struct isci_phy *iphy, - struct scu_transport_layer_registers __iomem *transport_layer_registers) +static enum sci_status +sci_phy_transport_layer_initialization(struct isci_phy *iphy, + struct scu_transport_layer_registers __iomem *reg) { u32 tl_control; - iphy->transport_layer_registers = transport_layer_registers; + iphy->transport_layer_registers = reg; writel(SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX, &iphy->transport_layer_registers->stp_rni); @@ -101,32 +89,23 @@ static enum sci_status scic_sds_phy_transport_layer_initialization( return SCI_SUCCESS; } -/** - * This method will initialize the phy link layer registers - * @sci_phy: - * @link_layer_registers: - * - * enum sci_status - */ static enum sci_status -scic_sds_phy_link_layer_initialization(struct isci_phy *iphy, - struct scu_link_layer_registers __iomem *link_layer_registers) +sci_phy_link_layer_initialization(struct isci_phy *iphy, + struct scu_link_layer_registers __iomem *reg) { - struct isci_host *ihost = - iphy->owning_port->owning_controller; + struct isci_host *ihost = iphy->owning_port->owning_controller; int phy_idx = iphy->phy_index; - struct sci_phy_user_params *phy_user = - &ihost->user_parameters.sds1.phys[phy_idx]; + struct sci_phy_user_params *phy_user = &ihost->user_parameters.phys[phy_idx]; struct sci_phy_oem_params *phy_oem = - &ihost->oem_parameters.sds1.phys[phy_idx]; + &ihost->oem_parameters.phys[phy_idx]; u32 phy_configuration; - struct scic_phy_cap phy_cap; + struct sci_phy_cap phy_cap; u32 parity_check = 0; u32 parity_count = 0; u32 llctl, link_rate; u32 clksm_value = 0; - iphy->link_layer_registers = link_layer_registers; + iphy->link_layer_registers = reg; /* Set our IDENTIFY frame data */ #define SCI_END_DEVICE 0x01 @@ -169,7 +148,7 @@ scic_sds_phy_link_layer_initialization(struct isci_phy *iphy, phy_cap.gen3_no_ssc = 1; phy_cap.gen2_no_ssc = 1; phy_cap.gen1_no_ssc = 1; - if (ihost->oem_parameters.sds1.controller.do_enable_ssc == true) { + if (ihost->oem_parameters.controller.do_enable_ssc == true) { phy_cap.gen3_ssc = 1; phy_cap.gen2_ssc = 1; phy_cap.gen1_ssc = 1; @@ -216,7 +195,7 @@ scic_sds_phy_link_layer_initialization(struct isci_phy *iphy, &iphy->link_layer_registers->afe_lookup_table_control); llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, - (u8)ihost->user_parameters.sds1.no_outbound_task_timeout); + (u8)ihost->user_parameters.no_outbound_task_timeout); switch(phy_user->max_speed_generation) { case SCIC_SDS_PARM_GEN3_SPEED: @@ -289,7 +268,7 @@ done: struct isci_port *phy_get_non_dummy_port( struct isci_phy *iphy) { - if (scic_sds_port_get_index(iphy->owning_port) == SCIC_SDS_DUMMY_PORT) + if (sci_port_get_index(iphy->owning_port) == SCIC_SDS_DUMMY_PORT) return NULL; return iphy->owning_port; @@ -302,7 +281,7 @@ struct isci_port *phy_get_non_dummy_port( * * */ -void scic_sds_phy_set_port( +void sci_phy_set_port( struct isci_phy *iphy, struct isci_port *iport) { @@ -310,33 +289,23 @@ void scic_sds_phy_set_port( if (iphy->bcn_received_while_port_unassigned) { iphy->bcn_received_while_port_unassigned = false; - scic_sds_port_broadcast_change_received(iphy->owning_port, iphy); + sci_port_broadcast_change_received(iphy->owning_port, iphy); } } -/** - * This method will initialize the constructed phy - * @sci_phy: - * @link_layer_registers: - * - * enum sci_status - */ -enum sci_status scic_sds_phy_initialize( - struct isci_phy *iphy, - struct scu_transport_layer_registers __iomem *transport_layer_registers, - struct scu_link_layer_registers __iomem *link_layer_registers) +enum sci_status sci_phy_initialize(struct isci_phy *iphy, + struct scu_transport_layer_registers __iomem *tl, + struct scu_link_layer_registers __iomem *ll) { /* Perfrom the initialization of the TL hardware */ - scic_sds_phy_transport_layer_initialization( - iphy, - transport_layer_registers); + sci_phy_transport_layer_initialization(iphy, tl); /* Perofrm the initialization of the PE hardware */ - scic_sds_phy_link_layer_initialization(iphy, link_layer_registers); + sci_phy_link_layer_initialization(iphy, ll); - /* - * There is nothing that needs to be done in this state just - * transition to the stopped state. */ + /* There is nothing that needs to be done in this state just + * transition to the stopped state + */ sci_change_state(&iphy->sm, SCI_PHY_STOPPED); return SCI_SUCCESS; @@ -351,9 +320,7 @@ enum sci_status scic_sds_phy_initialize( * This will either be the RNi for the device or an invalid RNi if there * is no current device assigned to the phy. */ -void scic_sds_phy_setup_transport( - struct isci_phy *iphy, - u32 device_id) +void sci_phy_setup_transport(struct isci_phy *iphy, u32 device_id) { u32 tl_control; @@ -368,15 +335,7 @@ void scic_sds_phy_setup_transport( writel(tl_control, &iphy->transport_layer_registers->control); } -/** - * - * @sci_phy: The phy object to be suspended. - * - * This function will perform the register reads/writes to suspend the SCU - * hardware protocol engine. none - */ -static void scic_sds_phy_suspend( - struct isci_phy *iphy) +static void sci_phy_suspend(struct isci_phy *iphy) { u32 scu_sas_pcfg_value; @@ -386,12 +345,10 @@ static void scic_sds_phy_suspend( writel(scu_sas_pcfg_value, &iphy->link_layer_registers->phy_configuration); - scic_sds_phy_setup_transport( - iphy, - SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); + sci_phy_setup_transport(iphy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); } -void scic_sds_phy_resume(struct isci_phy *iphy) +void sci_phy_resume(struct isci_phy *iphy) { u32 scu_sas_pcfg_value; @@ -402,34 +359,28 @@ void scic_sds_phy_resume(struct isci_phy *iphy) &iphy->link_layer_registers->phy_configuration); } -void scic_sds_phy_get_sas_address(struct isci_phy *iphy, - struct sci_sas_address *sas_address) +void sci_phy_get_sas_address(struct isci_phy *iphy, struct sci_sas_address *sas) { - sas_address->high = readl(&iphy->link_layer_registers->source_sas_address_high); - sas_address->low = readl(&iphy->link_layer_registers->source_sas_address_low); + sas->high = readl(&iphy->link_layer_registers->source_sas_address_high); + sas->low = readl(&iphy->link_layer_registers->source_sas_address_low); } -void scic_sds_phy_get_attached_sas_address(struct isci_phy *iphy, - struct sci_sas_address *sas_address) +void sci_phy_get_attached_sas_address(struct isci_phy *iphy, struct sci_sas_address *sas) { struct sas_identify_frame *iaf; iaf = &iphy->frame_rcvd.iaf; - memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE); + memcpy(sas, iaf->sas_addr, SAS_ADDR_SIZE); } -void scic_sds_phy_get_protocols(struct isci_phy *iphy, - struct scic_phy_proto *protocols) +void sci_phy_get_protocols(struct isci_phy *iphy, struct sci_phy_proto *proto) { - protocols->all = - (u16)(readl(&iphy-> - link_layer_registers->transmit_identification) & - 0x0000FFFF); + proto->all = readl(&iphy->link_layer_registers->transmit_identification); } -enum sci_status scic_sds_phy_start(struct isci_phy *iphy) +enum sci_status sci_phy_start(struct isci_phy *iphy) { - enum scic_sds_phy_states state = iphy->sm.current_state_id; + enum sci_phy_states state = iphy->sm.current_state_id; if (state != SCI_PHY_STOPPED) { dev_dbg(sciphy_to_dev(iphy), @@ -441,9 +392,9 @@ enum sci_status scic_sds_phy_start(struct isci_phy *iphy) return SCI_SUCCESS; } -enum sci_status scic_sds_phy_stop(struct isci_phy *iphy) +enum sci_status sci_phy_stop(struct isci_phy *iphy) { - enum scic_sds_phy_states state = iphy->sm.current_state_id; + enum sci_phy_states state = iphy->sm.current_state_id; switch (state) { case SCI_PHY_SUB_INITIAL: @@ -467,9 +418,9 @@ enum sci_status scic_sds_phy_stop(struct isci_phy *iphy) return SCI_SUCCESS; } -enum sci_status scic_sds_phy_reset(struct isci_phy *iphy) +enum sci_status sci_phy_reset(struct isci_phy *iphy) { - enum scic_sds_phy_states state = iphy->sm.current_state_id; + enum sci_phy_states state = iphy->sm.current_state_id; if (state != SCI_PHY_READY) { dev_dbg(sciphy_to_dev(iphy), @@ -481,9 +432,9 @@ enum sci_status scic_sds_phy_reset(struct isci_phy *iphy) return SCI_SUCCESS; } -enum sci_status scic_sds_phy_consume_power_handler(struct isci_phy *iphy) +enum sci_status sci_phy_consume_power_handler(struct isci_phy *iphy) { - enum scic_sds_phy_states state = iphy->sm.current_state_id; + enum sci_phy_states state = iphy->sm.current_state_id; switch (state) { case SCI_PHY_SUB_AWAIT_SAS_POWER: { @@ -528,55 +479,37 @@ enum sci_status scic_sds_phy_consume_power_handler(struct isci_phy *iphy) } } -/* - * ***************************************************************************** - * * SCIC SDS PHY HELPER FUNCTIONS - * ***************************************************************************** */ - - -/** - * - * @sci_phy: The phy object that received SAS PHY DETECTED. - * - * This method continues the link training for the phy as if it were a SAS PHY - * instead of a SATA PHY. This is done because the completion queue had a SAS - * PHY DETECTED event when the state machine was expecting a SATA PHY event. - * none - */ -static void scic_sds_phy_start_sas_link_training( - struct isci_phy *iphy) +static void sci_phy_start_sas_link_training(struct isci_phy *iphy) { + /* continue the link training for the phy as if it were a SAS PHY + * instead of a SATA PHY. This is done because the completion queue had a SAS + * PHY DETECTED event when the state machine was expecting a SATA PHY event. + */ u32 phy_control; - phy_control = - readl(&iphy->link_layer_registers->phy_configuration); + phy_control = readl(&iphy->link_layer_registers->phy_configuration); phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); writel(phy_control, - &iphy->link_layer_registers->phy_configuration); + &iphy->link_layer_registers->phy_configuration); sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SAS_SPEED_EN); iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; } -/** - * - * @sci_phy: The phy object that received a SATA SPINUP HOLD event - * - * This method continues the link training for the phy as if it were a SATA PHY - * instead of a SAS PHY. This is done because the completion queue had a SATA - * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none - */ -static void scic_sds_phy_start_sata_link_training( - struct isci_phy *iphy) +static void sci_phy_start_sata_link_training(struct isci_phy *iphy) { + /* This method continues the link training for the phy as if it were a SATA PHY + * instead of a SAS PHY. This is done because the completion queue had a SATA + * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none + */ sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_POWER); iphy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; } /** - * scic_sds_phy_complete_link_training - perform processing common to + * sci_phy_complete_link_training - perform processing common to * all protocols upon completion of link training. * @sci_phy: This parameter specifies the phy object for which link training * has completed. @@ -586,30 +519,28 @@ static void scic_sds_phy_start_sata_link_training( * sub-state machine. * */ -static void scic_sds_phy_complete_link_training( - struct isci_phy *iphy, - enum sas_linkrate max_link_rate, - u32 next_state) +static void sci_phy_complete_link_training(struct isci_phy *iphy, + enum sas_linkrate max_link_rate, + u32 next_state) { iphy->max_negotiated_speed = max_link_rate; sci_change_state(&iphy->sm, next_state); } -enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, - u32 event_code) +enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) { - enum scic_sds_phy_states state = iphy->sm.current_state_id; + enum sci_phy_states state = iphy->sm.current_state_id; switch (state) { case SCI_PHY_SUB_AWAIT_OSSP_EN: switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: - scic_sds_phy_start_sas_link_training(iphy); + sci_phy_start_sas_link_training(iphy); iphy->is_in_link_training = true; break; case SCU_EVENT_SATA_SPINUP_HOLD: - scic_sds_phy_start_sata_link_training(iphy); + sci_phy_start_sata_link_training(iphy); iphy->is_in_link_training = true; break; default: @@ -630,30 +561,24 @@ enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, break; case SCU_EVENT_SAS_15: case SCU_EVENT_SAS_15_SSC: - scic_sds_phy_complete_link_training( - iphy, - SAS_LINK_RATE_1_5_GBPS, - SCI_PHY_SUB_AWAIT_IAF_UF); + sci_phy_complete_link_training(iphy, SAS_LINK_RATE_1_5_GBPS, + SCI_PHY_SUB_AWAIT_IAF_UF); break; case SCU_EVENT_SAS_30: case SCU_EVENT_SAS_30_SSC: - scic_sds_phy_complete_link_training( - iphy, - SAS_LINK_RATE_3_0_GBPS, - SCI_PHY_SUB_AWAIT_IAF_UF); + sci_phy_complete_link_training(iphy, SAS_LINK_RATE_3_0_GBPS, + SCI_PHY_SUB_AWAIT_IAF_UF); break; case SCU_EVENT_SAS_60: case SCU_EVENT_SAS_60_SSC: - scic_sds_phy_complete_link_training( - iphy, - SAS_LINK_RATE_6_0_GBPS, - SCI_PHY_SUB_AWAIT_IAF_UF); + sci_phy_complete_link_training(iphy, SAS_LINK_RATE_6_0_GBPS, + SCI_PHY_SUB_AWAIT_IAF_UF); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* * We were doing SAS PHY link training and received a SATA PHY event * continue OOB/SN as if this were a SATA PHY */ - scic_sds_phy_start_sata_link_training(iphy); + sci_phy_start_sata_link_training(iphy); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ @@ -673,14 +598,14 @@ enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, switch (scu_get_event_code(event_code)) { case SCU_EVENT_SAS_PHY_DETECTED: /* Backup the state machine */ - scic_sds_phy_start_sas_link_training(iphy); + sci_phy_start_sas_link_training(iphy); break; case SCU_EVENT_SATA_SPINUP_HOLD: /* We were doing SAS PHY link training and received a * SATA PHY event continue OOB/SN as if this were a * SATA PHY */ - scic_sds_phy_start_sata_link_training(iphy); + sci_phy_start_sata_link_training(iphy); break; case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: case SCU_EVENT_LINK_FAILURE: @@ -727,7 +652,7 @@ enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, /* There has been a change in the phy type before OOB/SN for the * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(iphy); + sci_phy_start_sas_link_training(iphy); break; default: @@ -760,7 +685,7 @@ enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, /* There has been a change in the phy type before OOB/SN for the * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(iphy); + sci_phy_start_sas_link_training(iphy); break; default: dev_warn(sciphy_to_dev(iphy), @@ -781,24 +706,18 @@ enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, break; case SCU_EVENT_SATA_15: case SCU_EVENT_SATA_15_SSC: - scic_sds_phy_complete_link_training( - iphy, - SAS_LINK_RATE_1_5_GBPS, - SCI_PHY_SUB_AWAIT_SIG_FIS_UF); + sci_phy_complete_link_training(iphy, SAS_LINK_RATE_1_5_GBPS, + SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_SATA_30: case SCU_EVENT_SATA_30_SSC: - scic_sds_phy_complete_link_training( - iphy, - SAS_LINK_RATE_3_0_GBPS, - SCI_PHY_SUB_AWAIT_SIG_FIS_UF); + sci_phy_complete_link_training(iphy, SAS_LINK_RATE_3_0_GBPS, + SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_SATA_60: case SCU_EVENT_SATA_60_SSC: - scic_sds_phy_complete_link_training( - iphy, - SAS_LINK_RATE_6_0_GBPS, - SCI_PHY_SUB_AWAIT_SIG_FIS_UF); + sci_phy_complete_link_training(iphy, SAS_LINK_RATE_6_0_GBPS, + SCI_PHY_SUB_AWAIT_SIG_FIS_UF); break; case SCU_EVENT_LINK_FAILURE: /* Link failure change state back to the starting state */ @@ -808,7 +727,7 @@ enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, /* * There has been a change in the phy type before OOB/SN for the * SATA finished start down the SAS link traning path. */ - scic_sds_phy_start_sas_link_training(iphy); + sci_phy_start_sas_link_training(iphy); break; default: dev_warn(sciphy_to_dev(iphy), @@ -851,7 +770,7 @@ enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, case SCU_EVENT_BROADCAST_CHANGE: /* Broadcast change received. Notify the port. */ if (phy_get_non_dummy_port(iphy) != NULL) - scic_sds_port_broadcast_change_received(iphy->owning_port, iphy); + sci_port_broadcast_change_received(iphy->owning_port, iphy); else iphy->bcn_received_while_port_unassigned = true; break; @@ -886,10 +805,9 @@ enum sci_status scic_sds_phy_event_handler(struct isci_phy *iphy, } } -enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, - u32 frame_index) +enum sci_status sci_phy_frame_handler(struct isci_phy *iphy, u32 frame_index) { - enum scic_sds_phy_states state = iphy->sm.current_state_id; + enum sci_phy_states state = iphy->sm.current_state_id; struct isci_host *ihost = iphy->owning_port->owning_controller; enum sci_status result; unsigned long flags; @@ -899,9 +817,9 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, u32 *frame_words; struct sas_identify_frame iaf; - result = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, - frame_index, - (void **)&frame_words); + result = sci_unsolicited_frame_control_get_header(&ihost->uf_control, + frame_index, + (void **)&frame_words); if (result != SCI_SUCCESS) return result; @@ -933,15 +851,15 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, "unexpected frame id %x\n", __func__, frame_index); - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return result; } case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: { struct dev_to_host_fis *frame_header; u32 *fis_frame_data; - result = scic_sds_unsolicited_frame_control_get_header( - &(scic_sds_phy_get_controller(iphy)->uf_control), + result = sci_unsolicited_frame_control_get_header( + &(sci_phy_get_controller(iphy)->uf_control), frame_index, (void **)&frame_header); @@ -950,14 +868,14 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, if ((frame_header->fis_type == FIS_REGD2H) && !(frame_header->status & ATA_BUSY)) { - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, - frame_index, - (void **)&fis_frame_data); + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, + frame_index, + (void **)&fis_frame_data); spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags); - scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis, - frame_header, - fis_frame_data); + sci_controller_copy_sata_response(&iphy->frame_rcvd.fis, + frame_header, + fis_frame_data); spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags); /* got IAF we can now go to the await spinup semaphore state */ @@ -971,7 +889,7 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, __func__, frame_index); /* Regardless of the result we are done with this frame with it */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return result; } @@ -983,7 +901,7 @@ enum sci_status scic_sds_phy_frame_handler(struct isci_phy *iphy, } -static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_state_machine *sm) +static void sci_phy_starting_initial_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); @@ -991,71 +909,71 @@ static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_state_m sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_OSSP_EN); } -static void scic_sds_phy_starting_await_sas_power_substate_enter(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sas_power_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); struct isci_host *ihost = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_insert(ihost, iphy); + sci_controller_power_control_queue_insert(ihost, iphy); } -static void scic_sds_phy_starting_await_sas_power_substate_exit(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sas_power_substate_exit(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); struct isci_host *ihost = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_remove(ihost, iphy); + sci_controller_power_control_queue_remove(ihost, iphy); } -static void scic_sds_phy_starting_await_sata_power_substate_enter(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sata_power_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); struct isci_host *ihost = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_insert(ihost, iphy); + sci_controller_power_control_queue_insert(ihost, iphy); } -static void scic_sds_phy_starting_await_sata_power_substate_exit(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sata_power_substate_exit(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); struct isci_host *ihost = iphy->owning_port->owning_controller; - scic_sds_controller_power_control_queue_remove(ihost, iphy); + sci_controller_power_control_queue_remove(ihost, iphy); } -static void scic_sds_phy_starting_await_sata_phy_substate_enter(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sata_phy_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); sci_mod_timer(&iphy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } -static void scic_sds_phy_starting_await_sata_phy_substate_exit(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sata_phy_substate_exit(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); sci_del_timer(&iphy->sata_timer); } -static void scic_sds_phy_starting_await_sata_speed_substate_enter(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sata_speed_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); sci_mod_timer(&iphy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT); } -static void scic_sds_phy_starting_await_sata_speed_substate_exit(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sata_speed_substate_exit(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); sci_del_timer(&iphy->sata_timer); } -static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sig_fis_uf_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - if (scic_sds_port_link_detected(iphy->owning_port, iphy)) { + if (sci_port_link_detected(iphy->owning_port, iphy)) { /* * Clear the PE suspend condition so we can actually @@ -1063,7 +981,7 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_bas * The hardware will not respond to the XRDY until the PE * suspend condition is cleared. */ - scic_sds_phy_resume(iphy); + sci_phy_resume(iphy); sci_mod_timer(&iphy->sata_timer, SCIC_SDS_SIGNATURE_FIS_TIMEOUT); @@ -1071,14 +989,14 @@ static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_bas iphy->is_in_link_training = false; } -static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(struct sci_base_state_machine *sm) +static void sci_phy_starting_await_sig_fis_uf_substate_exit(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); sci_del_timer(&iphy->sata_timer); } -static void scic_sds_phy_starting_final_substate_enter(struct sci_base_state_machine *sm) +static void sci_phy_starting_final_substate_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); @@ -1169,7 +1087,7 @@ static void scu_link_layer_tx_hard_reset( &iphy->link_layer_registers->phy_configuration); } -static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm) +static void sci_phy_stopped_state_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); @@ -1182,12 +1100,12 @@ static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm) scu_link_layer_stop_protocol_engine(iphy); if (iphy->sm.previous_state_id != SCI_PHY_INITIAL) - scic_sds_controller_link_down(scic_sds_phy_get_controller(iphy), + sci_controller_link_down(sci_phy_get_controller(iphy), phy_get_non_dummy_port(iphy), iphy); } -static void scic_sds_phy_starting_state_enter(struct sci_base_state_machine *sm) +static void sci_phy_starting_state_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); @@ -1199,31 +1117,31 @@ static void scic_sds_phy_starting_state_enter(struct sci_base_state_machine *sm) iphy->bcn_received_while_port_unassigned = false; if (iphy->sm.previous_state_id == SCI_PHY_READY) - scic_sds_controller_link_down(scic_sds_phy_get_controller(iphy), + sci_controller_link_down(sci_phy_get_controller(iphy), phy_get_non_dummy_port(iphy), iphy); sci_change_state(&iphy->sm, SCI_PHY_SUB_INITIAL); } -static void scic_sds_phy_ready_state_enter(struct sci_base_state_machine *sm) +static void sci_phy_ready_state_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - scic_sds_controller_link_up(scic_sds_phy_get_controller(iphy), + sci_controller_link_up(sci_phy_get_controller(iphy), phy_get_non_dummy_port(iphy), iphy); } -static void scic_sds_phy_ready_state_exit(struct sci_base_state_machine *sm) +static void sci_phy_ready_state_exit(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); - scic_sds_phy_suspend(iphy); + sci_phy_suspend(iphy); } -static void scic_sds_phy_resetting_state_enter(struct sci_base_state_machine *sm) +static void sci_phy_resetting_state_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); @@ -1231,7 +1149,7 @@ static void scic_sds_phy_resetting_state_enter(struct sci_base_state_machine *sm * the resetting state we don't notify the user regarding link up and * link down notifications */ - scic_sds_port_deactivate_phy(iphy->owning_port, iphy, false); + sci_port_deactivate_phy(iphy->owning_port, iphy, false); if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { scu_link_layer_tx_hard_reset(iphy); @@ -1243,57 +1161,57 @@ static void scic_sds_phy_resetting_state_enter(struct sci_base_state_machine *sm } } -static const struct sci_base_state scic_sds_phy_state_table[] = { +static const struct sci_base_state sci_phy_state_table[] = { [SCI_PHY_INITIAL] = { }, [SCI_PHY_STOPPED] = { - .enter_state = scic_sds_phy_stopped_state_enter, + .enter_state = sci_phy_stopped_state_enter, }, [SCI_PHY_STARTING] = { - .enter_state = scic_sds_phy_starting_state_enter, + .enter_state = sci_phy_starting_state_enter, }, [SCI_PHY_SUB_INITIAL] = { - .enter_state = scic_sds_phy_starting_initial_substate_enter, + .enter_state = sci_phy_starting_initial_substate_enter, }, [SCI_PHY_SUB_AWAIT_OSSP_EN] = { }, [SCI_PHY_SUB_AWAIT_SAS_SPEED_EN] = { }, [SCI_PHY_SUB_AWAIT_IAF_UF] = { }, [SCI_PHY_SUB_AWAIT_SAS_POWER] = { - .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, - .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, + .enter_state = sci_phy_starting_await_sas_power_substate_enter, + .exit_state = sci_phy_starting_await_sas_power_substate_exit, }, [SCI_PHY_SUB_AWAIT_SATA_POWER] = { - .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit + .enter_state = sci_phy_starting_await_sata_power_substate_enter, + .exit_state = sci_phy_starting_await_sata_power_substate_exit }, [SCI_PHY_SUB_AWAIT_SATA_PHY_EN] = { - .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit + .enter_state = sci_phy_starting_await_sata_phy_substate_enter, + .exit_state = sci_phy_starting_await_sata_phy_substate_exit }, [SCI_PHY_SUB_AWAIT_SATA_SPEED_EN] = { - .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter, - .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit + .enter_state = sci_phy_starting_await_sata_speed_substate_enter, + .exit_state = sci_phy_starting_await_sata_speed_substate_exit }, [SCI_PHY_SUB_AWAIT_SIG_FIS_UF] = { - .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter, - .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit + .enter_state = sci_phy_starting_await_sig_fis_uf_substate_enter, + .exit_state = sci_phy_starting_await_sig_fis_uf_substate_exit }, [SCI_PHY_SUB_FINAL] = { - .enter_state = scic_sds_phy_starting_final_substate_enter, + .enter_state = sci_phy_starting_final_substate_enter, }, [SCI_PHY_READY] = { - .enter_state = scic_sds_phy_ready_state_enter, - .exit_state = scic_sds_phy_ready_state_exit, + .enter_state = sci_phy_ready_state_enter, + .exit_state = sci_phy_ready_state_exit, }, [SCI_PHY_RESETTING] = { - .enter_state = scic_sds_phy_resetting_state_enter, + .enter_state = sci_phy_resetting_state_enter, }, [SCI_PHY_FINAL] = { }, }; -void scic_sds_phy_construct(struct isci_phy *iphy, +void sci_phy_construct(struct isci_phy *iphy, struct isci_port *iport, u8 phy_index) { - sci_init_sm(&iphy->sm, scic_sds_phy_state_table, SCI_PHY_INITIAL); + sci_init_sm(&iphy->sm, sci_phy_state_table, SCI_PHY_INITIAL); /* Copy the rest of the input data to our locals */ iphy->owning_port = iport; @@ -1309,14 +1227,13 @@ void scic_sds_phy_construct(struct isci_phy *iphy, void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index) { - union scic_oem_parameters oem; + struct sci_oem_params *oem = &ihost->oem_parameters; u64 sci_sas_addr; __be64 sas_addr; - scic_oem_parameters_get(ihost, &oem); - sci_sas_addr = oem.sds1.phys[index].sas_address.high; + sci_sas_addr = oem->phys[index].sas_address.high; sci_sas_addr <<= 32; - sci_sas_addr |= oem.sds1.phys[index].sas_address.low; + sci_sas_addr |= oem->phys[index].sas_address.low; sas_addr = cpu_to_be64(sci_sas_addr); memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr)); @@ -1365,14 +1282,14 @@ int isci_phy_control(struct asd_sas_phy *sas_phy, switch (func) { case PHY_FUNC_DISABLE: spin_lock_irqsave(&ihost->scic_lock, flags); - scic_sds_phy_stop(iphy); + sci_phy_stop(iphy); spin_unlock_irqrestore(&ihost->scic_lock, flags); break; case PHY_FUNC_LINK_RESET: spin_lock_irqsave(&ihost->scic_lock, flags); - scic_sds_phy_stop(iphy); - scic_sds_phy_start(iphy); + sci_phy_stop(iphy); + sci_phy_start(iphy); spin_unlock_irqrestore(&ihost->scic_lock, flags); break; diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 19aa444517b4..5d2c1b4906a3 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -76,7 +76,7 @@ */ #define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250 -enum scic_sds_phy_protocol { +enum sci_phy_protocol { SCIC_SDS_PHY_PROTOCOL_UNKNOWN, SCIC_SDS_PHY_PROTOCOL_SAS, SCIC_SDS_PHY_PROTOCOL_SATA, @@ -95,7 +95,7 @@ struct isci_phy { struct sci_base_state_machine sm; struct isci_port *owning_port; enum sas_linkrate max_negotiated_speed; - enum scic_sds_phy_protocol protocol; + enum sci_phy_protocol protocol; u8 phy_index; bool bcn_received_while_port_unassigned; bool is_in_link_training; @@ -118,7 +118,7 @@ static inline struct isci_phy *to_iphy(struct asd_sas_phy *sas_phy) return iphy; } -struct scic_phy_cap { +struct sci_phy_cap { union { struct { /* @@ -147,7 +147,7 @@ struct scic_phy_cap { } __packed; /* this data structure reflects the link layer transmit identification reg */ -struct scic_phy_proto { +struct sci_phy_proto { union { struct { u16 _r_a:1; @@ -167,12 +167,12 @@ struct scic_phy_proto { /** - * struct scic_phy_properties - This structure defines the properties common to + * struct sci_phy_properties - This structure defines the properties common to * all phys that can be retrieved. * * */ -struct scic_phy_properties { +struct sci_phy_properties { /** * This field specifies the port that currently contains the * supplied phy. This field may be set to NULL @@ -194,12 +194,12 @@ struct scic_phy_properties { }; /** - * struct scic_sas_phy_properties - This structure defines the properties, + * struct sci_sas_phy_properties - This structure defines the properties, * specific to a SAS phy, that can be retrieved. * * */ -struct scic_sas_phy_properties { +struct sci_sas_phy_properties { /** * This field delineates the Identify Address Frame received * from the remote end point. @@ -210,17 +210,17 @@ struct scic_sas_phy_properties { * This field delineates the Phy capabilities structure received * from the remote end point. */ - struct scic_phy_cap rcvd_cap; + struct sci_phy_cap rcvd_cap; }; /** - * struct scic_sata_phy_properties - This structure defines the properties, + * struct sci_sata_phy_properties - This structure defines the properties, * specific to a SATA phy, that can be retrieved. * * */ -struct scic_sata_phy_properties { +struct sci_sata_phy_properties { /** * This field delineates the signature FIS received from the * attached target. @@ -236,12 +236,12 @@ struct scic_sata_phy_properties { }; /** - * enum scic_phy_counter_id - This enumeration depicts the various pieces of + * enum sci_phy_counter_id - This enumeration depicts the various pieces of * optional information that can be retrieved for a specific phy. * * */ -enum scic_phy_counter_id { +enum sci_phy_counter_id { /** * This PHY information field tracks the number of frames received. */ @@ -344,7 +344,7 @@ enum scic_phy_counter_id { SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR }; -enum scic_sds_phy_states { +enum sci_phy_states { /** * Simply the initial state for the base domain state machine. */ @@ -441,77 +441,77 @@ enum scic_sds_phy_states { }; /** - * scic_sds_phy_get_index() - + * sci_phy_get_index() - * * This macro returns the phy index for the specified phy */ -#define scic_sds_phy_get_index(phy) \ +#define sci_phy_get_index(phy) \ ((phy)->phy_index) /** - * scic_sds_phy_get_controller() - This macro returns the controller for this + * sci_phy_get_controller() - This macro returns the controller for this * phy * * */ -#define scic_sds_phy_get_controller(phy) \ - (scic_sds_port_get_controller((phy)->owning_port)) +#define sci_phy_get_controller(phy) \ + (sci_port_get_controller((phy)->owning_port)) -void scic_sds_phy_construct( +void sci_phy_construct( struct isci_phy *iphy, struct isci_port *iport, u8 phy_index); struct isci_port *phy_get_non_dummy_port(struct isci_phy *iphy); -void scic_sds_phy_set_port( +void sci_phy_set_port( struct isci_phy *iphy, struct isci_port *iport); -enum sci_status scic_sds_phy_initialize( +enum sci_status sci_phy_initialize( struct isci_phy *iphy, struct scu_transport_layer_registers __iomem *transport_layer_registers, struct scu_link_layer_registers __iomem *link_layer_registers); -enum sci_status scic_sds_phy_start( +enum sci_status sci_phy_start( struct isci_phy *iphy); -enum sci_status scic_sds_phy_stop( +enum sci_status sci_phy_stop( struct isci_phy *iphy); -enum sci_status scic_sds_phy_reset( +enum sci_status sci_phy_reset( struct isci_phy *iphy); -void scic_sds_phy_resume( +void sci_phy_resume( struct isci_phy *iphy); -void scic_sds_phy_setup_transport( +void sci_phy_setup_transport( struct isci_phy *iphy, u32 device_id); -enum sci_status scic_sds_phy_event_handler( +enum sci_status sci_phy_event_handler( struct isci_phy *iphy, u32 event_code); -enum sci_status scic_sds_phy_frame_handler( +enum sci_status sci_phy_frame_handler( struct isci_phy *iphy, u32 frame_index); -enum sci_status scic_sds_phy_consume_power_handler( +enum sci_status sci_phy_consume_power_handler( struct isci_phy *iphy); -void scic_sds_phy_get_sas_address( +void sci_phy_get_sas_address( struct isci_phy *iphy, struct sci_sas_address *sas_address); -void scic_sds_phy_get_attached_sas_address( +void sci_phy_get_attached_sas_address( struct isci_phy *iphy, struct sci_sas_address *sas_address); -struct scic_phy_proto; -void scic_sds_phy_get_protocols( +struct sci_phy_proto; +void sci_phy_get_protocols( struct isci_phy *iphy, - struct scic_phy_proto *protocols); + struct sci_phy_proto *protocols); enum sas_linkrate sci_phy_linkrate(struct isci_phy *iphy); struct isci_host; diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index c434d5a0effa..1822ed68409e 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -74,57 +74,35 @@ static void isci_port_change_state(struct isci_port *iport, enum isci_status sta spin_unlock_irqrestore(&iport->state_lock, flags); } -/* - * This function will indicate which protocols are supported by this port. - * @sci_port: a handle corresponding to the SAS port for which to return the - * supported protocols. - * @protocols: This parameter specifies a pointer to a data structure - * which the core will copy the protocol values for the port from the - * transmit_identification register. - */ -static void -scic_sds_port_get_protocols(struct isci_port *iport, - struct scic_phy_proto *protocols) +static void sci_port_get_protocols(struct isci_port *iport, struct sci_phy_proto *proto) { u8 index; - protocols->all = 0; - + proto->all = 0; for (index = 0; index < SCI_MAX_PHYS; index++) { - if (iport->phy_table[index] != NULL) { - scic_sds_phy_get_protocols(iport->phy_table[index], - protocols); - } + struct isci_phy *iphy = iport->phy_table[index]; + + if (!iphy) + continue; + sci_phy_get_protocols(iphy, proto); } } -/** - * This method requests a list (mask) of the phys contained in the supplied SAS - * port. - * @sci_port: a handle corresponding to the SAS port for which to return the - * phy mask. - * - * Return a bit mask indicating which phys are a part of this port. Each bit - * corresponds to a phy identifier (e.g. bit 0 = phy id 0). - */ -static u32 scic_sds_port_get_phys(struct isci_port *iport) +static u32 sci_port_get_phys(struct isci_port *iport) { u32 index; u32 mask; mask = 0; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (iport->phy_table[index] != NULL) { + for (index = 0; index < SCI_MAX_PHYS; index++) + if (iport->phy_table[index]) mask |= (1 << index); - } - } return mask; } /** - * scic_port_get_properties() - This method simply returns the properties + * sci_port_get_properties() - This method simply returns the properties * regarding the port, such as: physical index, protocols, sas address, etc. * @port: this parameter specifies the port for which to retrieve the physical * index. @@ -136,22 +114,22 @@ static u32 scic_sds_port_get_phys(struct isci_port *iport) * value is returned if the specified port is not valid. When this value is * returned, no data is copied to the properties output parameter. */ -static enum sci_status scic_port_get_properties(struct isci_port *iport, - struct scic_port_properties *prop) +static enum sci_status sci_port_get_properties(struct isci_port *iport, + struct sci_port_properties *prop) { if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT) return SCI_FAILURE_INVALID_PORT; - prop->index = iport->logical_port_index; - prop->phy_mask = scic_sds_port_get_phys(iport); - scic_sds_port_get_sas_address(iport, &prop->local.sas_address); - scic_sds_port_get_protocols(iport, &prop->local.protocols); - scic_sds_port_get_attached_sas_address(iport, &prop->remote.sas_address); + prop->index = iport->logical_port_index; + prop->phy_mask = sci_port_get_phys(iport); + sci_port_get_sas_address(iport, &prop->local.sas_address); + sci_port_get_protocols(iport, &prop->local.protocols); + sci_port_get_attached_sas_address(iport, &prop->remote.sas_address); return SCI_SUCCESS; } -static void scic_port_bcn_enable(struct isci_port *iport) +static void sci_port_bcn_enable(struct isci_port *iport) { struct isci_phy *iphy; u32 val; @@ -167,7 +145,7 @@ static void scic_port_bcn_enable(struct isci_port *iport) } } -/* called under scic_lock to stabilize phy:port associations */ +/* called under sci_lock to stabilize phy:port associations */ void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport) { int i; @@ -209,7 +187,7 @@ static void isci_port_bc_change_received(struct isci_host *ihost, ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); } - scic_port_bcn_enable(iport); + sci_port_bcn_enable(iport); } static void isci_port_link_up(struct isci_host *isci_host, @@ -217,7 +195,7 @@ static void isci_port_link_up(struct isci_host *isci_host, struct isci_phy *iphy) { unsigned long flags; - struct scic_port_properties properties; + struct sci_port_properties properties; unsigned long success = true; BUG_ON(iphy->isci_port != NULL); @@ -232,7 +210,7 @@ static void isci_port_link_up(struct isci_host *isci_host, isci_port_change_state(iphy->isci_port, isci_starting); - scic_port_get_properties(iport, &properties); + sci_port_get_properties(iport, &properties); if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { u64 attached_sas_address; @@ -245,7 +223,7 @@ static void isci_port_link_up(struct isci_host *isci_host, * automagically assign a SAS address to the end device * for the purpose of creating a port. This SAS address * will not be the same as assigned to the PHY and needs - * to be obtained from struct scic_port_properties properties. + * to be obtained from struct sci_port_properties properties. */ attached_sas_address = properties.remote.sas_address.high; attached_sas_address <<= 32; @@ -399,50 +377,40 @@ static void isci_port_hard_reset_complete(struct isci_port *isci_port, * doesn't preclude all configurations. It merely ensures that a phy is part * of the allowable set of phy identifiers for that port. For example, one * could assign phy 3 to port 0 and no other phys. Please refer to - * scic_sds_port_is_phy_mask_valid() for information regarding whether the + * sci_port_is_phy_mask_valid() for information regarding whether the * phy_mask for a port can be supported. bool true if this is a valid phy * assignment for the port false if this is not a valid phy assignment for the * port */ -bool scic_sds_port_is_valid_phy_assignment(struct isci_port *iport, - u32 phy_index) +bool sci_port_is_valid_phy_assignment(struct isci_port *iport, u32 phy_index) { + struct isci_host *ihost = iport->owning_controller; + struct sci_user_parameters *user = &ihost->user_parameters; + /* Initialize to invalid value. */ u32 existing_phy_index = SCI_MAX_PHYS; u32 index; - if ((iport->physical_port_index == 1) && (phy_index != 1)) { + if ((iport->physical_port_index == 1) && (phy_index != 1)) return false; - } - if (iport->physical_port_index == 3 && phy_index != 3) { + if (iport->physical_port_index == 3 && phy_index != 3) return false; - } - if ( - (iport->physical_port_index == 2) - && ((phy_index == 0) || (phy_index == 1)) - ) { + if (iport->physical_port_index == 2 && + (phy_index == 0 || phy_index == 1)) return false; - } - for (index = 0; index < SCI_MAX_PHYS; index++) { - if ((iport->phy_table[index] != NULL) - && (index != phy_index)) { + for (index = 0; index < SCI_MAX_PHYS; index++) + if (iport->phy_table[index] && index != phy_index) existing_phy_index = index; - } - } - /* - * Ensure that all of the phys in the port are capable of - * operating at the same maximum link rate. */ - if ( - (existing_phy_index < SCI_MAX_PHYS) - && (iport->owning_controller->user_parameters.sds1.phys[ - phy_index].max_speed_generation != - iport->owning_controller->user_parameters.sds1.phys[ - existing_phy_index].max_speed_generation) - ) + /* Ensure that all of the phys in the port are capable of + * operating at the same maximum link rate. + */ + if (existing_phy_index < SCI_MAX_PHYS && + user->phys[phy_index].max_speed_generation != + user->phys[existing_phy_index].max_speed_generation) return false; return true; @@ -460,7 +428,7 @@ bool scic_sds_port_is_valid_phy_assignment(struct isci_port *iport, * phy mask can be supported. true if this is a valid phy assignment for the * port false if this is not a valid phy assignment for the port */ -static bool scic_sds_port_is_phy_mask_valid( +static bool sci_port_is_phy_mask_valid( struct isci_port *iport, u32 phy_mask) { @@ -493,10 +461,10 @@ static bool scic_sds_port_is_phy_mask_valid( * the port. Currently, the lowest order phy that is connected is returned. * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is * returned if there are no currently active (i.e. connected to a remote end - * point) phys contained in the port. All other values specify a struct scic_sds_phy + * point) phys contained in the port. All other values specify a struct sci_phy * object that is active in the port. */ -static struct isci_phy *scic_sds_port_get_a_connected_phy(struct isci_port *iport) +static struct isci_phy *sci_port_get_a_connected_phy(struct isci_port *iport) { u32 index; struct isci_phy *iphy; @@ -506,14 +474,14 @@ static struct isci_phy *scic_sds_port_get_a_connected_phy(struct isci_port *ipor * connected to the remote end-point. */ iphy = iport->phy_table[index]; - if (iphy && scic_sds_port_active_phy(iport, iphy)) + if (iphy && sci_port_active_phy(iport, iphy)) return iphy; } return NULL; } -static enum sci_status scic_sds_port_set_phy(struct isci_port *iport, struct isci_phy *iphy) +static enum sci_status sci_port_set_phy(struct isci_port *iport, struct isci_phy *iphy) { /* Check to see if we can add this phy to a port * that means that the phy is not part of a port and that the port does @@ -521,13 +489,13 @@ static enum sci_status scic_sds_port_set_phy(struct isci_port *iport, struct isc */ if (!iport->phy_table[iphy->phy_index] && !phy_get_non_dummy_port(iphy) && - scic_sds_port_is_valid_phy_assignment(iport, iphy->phy_index)) { + sci_port_is_valid_phy_assignment(iport, iphy->phy_index)) { /* Phy is being added in the stopped state so we are in MPC mode * make logical port index = physical port index */ iport->logical_port_index = iport->physical_port_index; iport->phy_table[iphy->phy_index] = iphy; - scic_sds_phy_set_port(iphy, iport); + sci_phy_set_port(iphy, iport); return SCI_SUCCESS; } @@ -535,8 +503,7 @@ static enum sci_status scic_sds_port_set_phy(struct isci_port *iport, struct isc return SCI_FAILURE; } -static enum sci_status scic_sds_port_clear_phy(struct isci_port *iport, - struct isci_phy *iphy) +static enum sci_status sci_port_clear_phy(struct isci_port *iport, struct isci_phy *iphy) { /* Make sure that this phy is part of this port */ if (iport->phy_table[iphy->phy_index] == iphy && @@ -544,7 +511,7 @@ static enum sci_status scic_sds_port_clear_phy(struct isci_port *iport, struct isci_host *ihost = iport->owning_controller; /* Yep it is assigned to this port so remove it */ - scic_sds_phy_set_port(iphy, &ihost->ports[SCI_MAX_PORTS]); + sci_phy_set_port(iphy, &ihost->ports[SCI_MAX_PORTS]); iport->phy_table[iphy->phy_index] = NULL; return SCI_SUCCESS; } @@ -552,45 +519,18 @@ static enum sci_status scic_sds_port_clear_phy(struct isci_port *iport, return SCI_FAILURE; } - -/** - * This method requests the SAS address for the supplied SAS port from the SCI - * implementation. - * @sci_port: a handle corresponding to the SAS port for which to return the - * SAS address. - * @sas_address: This parameter specifies a pointer to a SAS address structure - * into which the core will copy the SAS address for the port. - * - */ -void scic_sds_port_get_sas_address( - struct isci_port *iport, - struct sci_sas_address *sas_address) +void sci_port_get_sas_address(struct isci_port *iport, struct sci_sas_address *sas) { u32 index; - sas_address->high = 0; - sas_address->low = 0; - - for (index = 0; index < SCI_MAX_PHYS; index++) { - if (iport->phy_table[index] != NULL) { - scic_sds_phy_get_sas_address(iport->phy_table[index], sas_address); - } - } + sas->high = 0; + sas->low = 0; + for (index = 0; index < SCI_MAX_PHYS; index++) + if (iport->phy_table[index]) + sci_phy_get_sas_address(iport->phy_table[index], sas); } -/* - * This function requests the SAS address for the device directly attached to - * this SAS port. - * @sci_port: a handle corresponding to the SAS port for which to return the - * SAS address. - * @sas_address: This parameter specifies a pointer to a SAS address structure - * into which the core will copy the SAS address for the device directly - * attached to the port. - * - */ -void scic_sds_port_get_attached_sas_address( - struct isci_port *iport, - struct sci_sas_address *sas_address) +void sci_port_get_attached_sas_address(struct isci_port *iport, struct sci_sas_address *sas) { struct isci_phy *iphy; @@ -598,23 +538,22 @@ void scic_sds_port_get_attached_sas_address( * Ensure that the phy is both part of the port and currently * connected to the remote end-point. */ - iphy = scic_sds_port_get_a_connected_phy(iport); + iphy = sci_port_get_a_connected_phy(iport); if (iphy) { if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) { - scic_sds_phy_get_attached_sas_address(iphy, - sas_address); + sci_phy_get_attached_sas_address(iphy, sas); } else { - scic_sds_phy_get_sas_address(iphy, sas_address); - sas_address->low += iphy->phy_index; + sci_phy_get_sas_address(iphy, sas); + sas->low += iphy->phy_index; } } else { - sas_address->high = 0; - sas_address->low = 0; + sas->high = 0; + sas->low = 0; } } /** - * scic_sds_port_construct_dummy_rnc() - create dummy rnc for si workaround + * sci_port_construct_dummy_rnc() - create dummy rnc for si workaround * * @sci_port: logical port on which we need to create the remote node context * @rni: remote node index for this remote node context. @@ -623,7 +562,7 @@ void scic_sds_port_get_attached_sas_address( * This structure will be posted to the hardware to work around a scheduler * error in the hardware. */ -static void scic_sds_port_construct_dummy_rnc(struct isci_port *iport, u16 rni) +static void sci_port_construct_dummy_rnc(struct isci_port *iport, u16 rni) { union scu_remote_node_context *rnc; @@ -651,7 +590,7 @@ static void scic_sds_port_construct_dummy_rnc(struct isci_port *iport, u16 rni) * structure will be posted to the hardwre to work around a scheduler error * in the hardware. */ -static void scic_sds_port_construct_dummy_task(struct isci_port *iport, u16 tag) +static void sci_port_construct_dummy_task(struct isci_port *iport, u16 tag) { struct isci_host *ihost = iport->owning_controller; struct scu_task_context *task_context; @@ -671,7 +610,7 @@ static void scic_sds_port_construct_dummy_task(struct isci_port *iport, u16 tag) task_context->task_phase = 0x01; } -static void scic_sds_port_destroy_dummy_resources(struct isci_port *iport) +static void sci_port_destroy_dummy_resources(struct isci_port *iport) { struct isci_host *ihost = iport->owning_controller; @@ -679,93 +618,43 @@ static void scic_sds_port_destroy_dummy_resources(struct isci_port *iport) isci_free_tag(ihost, iport->reserved_tag); if (iport->reserved_rni != SCU_DUMMY_INDEX) - scic_sds_remote_node_table_release_remote_node_index(&ihost->available_remote_nodes, + sci_remote_node_table_release_remote_node_index(&ihost->available_remote_nodes, 1, iport->reserved_rni); iport->reserved_rni = SCU_DUMMY_INDEX; iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; } -/** - * This method performs initialization of the supplied port. Initialization - * includes: - state machine initialization - member variable initialization - * - configuring the phy_mask - * @sci_port: - * @transport_layer_registers: - * @port_task_scheduler_registers: - * @port_configuration_regsiter: - * - * enum sci_status SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned - * if the phy being added to the port - */ -enum sci_status scic_sds_port_initialize( - struct isci_port *iport, - void __iomem *port_task_scheduler_registers, - void __iomem *port_configuration_regsiter, - void __iomem *viit_registers) -{ - iport->port_task_scheduler_registers = port_task_scheduler_registers; - iport->port_pe_configuration_register = port_configuration_regsiter; - iport->viit_registers = viit_registers; - - return SCI_SUCCESS; -} - - -/** - * This method assigns the direct attached device ID for this port. - * - * @param[in] iport The port for which the direct attached device id is to - * be assigned. - * @param[in] device_id The direct attached device ID to assign to the port. - * This will be the RNi for the device - */ -void scic_sds_port_setup_transports( - struct isci_port *iport, - u32 device_id) +void sci_port_setup_transports(struct isci_port *iport, u32 device_id) { u8 index; for (index = 0; index < SCI_MAX_PHYS; index++) { if (iport->active_phy_mask & (1 << index)) - scic_sds_phy_setup_transport(iport->phy_table[index], device_id); + sci_phy_setup_transport(iport->phy_table[index], device_id); } } -/** - * - * @sci_port: This is the port on which the phy should be enabled. - * @sci_phy: This is the specific phy which to enable. - * @do_notify_user: This parameter specifies whether to inform the user (via - * scic_cb_port_link_up()) as to the fact that a new phy as become ready. - * - * This function will activate the phy in the port. - * Activation includes: - adding - * the phy to the port - enabling the Protocol Engine in the silicon. - - * notifying the user that the link is up. none - */ -static void scic_sds_port_activate_phy(struct isci_port *iport, - struct isci_phy *iphy, - bool do_notify_user) +static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy, + bool do_notify_user) { struct isci_host *ihost = iport->owning_controller; if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) - scic_sds_phy_resume(iphy); + sci_phy_resume(iphy); iport->active_phy_mask |= 1 << iphy->phy_index; - scic_sds_controller_clear_invalid_phy(ihost, iphy); + sci_controller_clear_invalid_phy(ihost, iphy); if (do_notify_user == true) isci_port_link_up(ihost, iport, iphy); } -void scic_sds_port_deactivate_phy(struct isci_port *iport, - struct isci_phy *iphy, - bool do_notify_user) +void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy, + bool do_notify_user) { - struct isci_host *ihost = scic_sds_port_get_controller(iport); + struct isci_host *ihost = sci_port_get_controller(iport); iport->active_phy_mask &= ~(1 << iphy->phy_index); @@ -779,16 +668,7 @@ void scic_sds_port_deactivate_phy(struct isci_port *iport, isci_port_link_down(ihost, iphy, iport); } -/** - * - * @sci_port: This is the port on which the phy should be disabled. - * @sci_phy: This is the specific phy which to disabled. - * - * This function will disable the phy and report that the phy is not valid for - * this port object. None - */ -static void scic_sds_port_invalid_link_up(struct isci_port *iport, - struct isci_phy *iphy) +static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *iphy) { struct isci_host *ihost = iport->owning_controller; @@ -798,12 +678,12 @@ static void scic_sds_port_invalid_link_up(struct isci_port *iport, * invalid link. */ if ((ihost->invalid_phy_mask & (1 << iphy->phy_index)) == 0) { - scic_sds_controller_set_invalid_phy(ihost, iphy); + sci_controller_set_invalid_phy(ihost, iphy); dev_warn(&ihost->pdev->dev, "Invalid link up!\n"); } } -static bool is_port_ready_state(enum scic_sds_port_states state) +static bool is_port_ready_state(enum sci_port_states state) { switch (state) { case SCI_PORT_READY: @@ -818,10 +698,10 @@ static bool is_port_ready_state(enum scic_sds_port_states state) /* flag dummy rnc hanling when exiting a ready state */ static void port_state_machine_change(struct isci_port *iport, - enum scic_sds_port_states state) + enum sci_port_states state) { struct sci_base_state_machine *sm = &iport->sm; - enum scic_sds_port_states old_state = sm->current_state_id; + enum sci_port_states old_state = sm->current_state_id; if (is_port_ready_state(old_state) && !is_port_ready_state(state)) iport->ready_exit = true; @@ -831,11 +711,11 @@ static void port_state_machine_change(struct isci_port *iport, } /** - * scic_sds_port_general_link_up_handler - phy can be assigned to port? - * @sci_port: scic_sds_port object for which has a phy that has gone link up. + * sci_port_general_link_up_handler - phy can be assigned to port? + * @sci_port: sci_port object for which has a phy that has gone link up. * @sci_phy: This is the struct isci_phy object that has gone link up. * @do_notify_user: This parameter specifies whether to inform the user (via - * scic_cb_port_link_up()) as to the fact that a new phy as become ready. + * sci_port_link_up()) as to the fact that a new phy as become ready. * * Determine if this phy can be assigned to this * port . If the phy is not a valid PHY for @@ -843,15 +723,15 @@ static void port_state_machine_change(struct isci_port *iport, * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in * the same port. none */ -static void scic_sds_port_general_link_up_handler(struct isci_port *iport, +static void sci_port_general_link_up_handler(struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user) { struct sci_sas_address port_sas_address; struct sci_sas_address phy_sas_address; - scic_sds_port_get_attached_sas_address(iport, &port_sas_address); - scic_sds_phy_get_attached_sas_address(iphy, &phy_sas_address); + sci_port_get_attached_sas_address(iport, &port_sas_address); + sci_phy_get_attached_sas_address(iphy, &phy_sas_address); /* If the SAS address of the new phy matches the SAS address of * other phys in the port OR this is the first phy in the port, @@ -863,11 +743,11 @@ static void scic_sds_port_general_link_up_handler(struct isci_port *iport, iport->active_phy_mask == 0) { struct sci_base_state_machine *sm = &iport->sm; - scic_sds_port_activate_phy(iport, iphy, do_notify_user); + sci_port_activate_phy(iport, iphy, do_notify_user); if (sm->current_state_id == SCI_PORT_RESETTING) port_state_machine_change(iport, SCI_PORT_READY); } else - scic_sds_port_invalid_link_up(iport, iphy); + sci_port_invalid_link_up(iport, iphy); } @@ -881,7 +761,7 @@ static void scic_sds_port_general_link_up_handler(struct isci_port *iport, * bool true Is returned if this is a wide ported port. false Is returned if * this is a narrow port. */ -static bool scic_sds_port_is_wide(struct isci_port *iport) +static bool sci_port_is_wide(struct isci_port *iport) { u32 index; u32 phy_count = 0; @@ -909,14 +789,14 @@ static bool scic_sds_port_is_wide(struct isci_port *iport) * wide ports and direct attached phys. Since there are no wide ported SATA * devices this could become an invalid port configuration. */ -bool scic_sds_port_link_detected( +bool sci_port_link_detected( struct isci_port *iport, struct isci_phy *iphy) { if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) && (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && - scic_sds_port_is_wide(iport)) { - scic_sds_port_invalid_link_up(iport, iphy); + sci_port_is_wide(iport)) { + sci_port_invalid_link_up(iport, iphy); return false; } @@ -977,11 +857,11 @@ done: * * */ -static void scic_sds_port_update_viit_entry(struct isci_port *iport) +static void sci_port_update_viit_entry(struct isci_port *iport) { struct sci_sas_address sas_address; - scic_sds_port_get_sas_address(iport, &sas_address); + sci_port_get_sas_address(iport, &sas_address); writel(sas_address.high, &iport->viit_registers->initiator_sas_address_hi); @@ -999,7 +879,7 @@ static void scic_sds_port_update_viit_entry(struct isci_port *iport) &iport->viit_registers->status); } -enum sas_linkrate scic_sds_port_get_max_allowed_speed(struct isci_port *iport) +enum sas_linkrate sci_port_get_max_allowed_speed(struct isci_port *iport) { u16 index; struct isci_phy *iphy; @@ -1010,7 +890,7 @@ enum sas_linkrate scic_sds_port_get_max_allowed_speed(struct isci_port *iport) * lowest maximum link rate. */ for (index = 0; index < SCI_MAX_PHYS; index++) { iphy = iport->phy_table[index]; - if (iphy && scic_sds_port_active_phy(iport, iphy) && + if (iphy && sci_port_active_phy(iport, iphy) && iphy->max_negotiated_speed < max_allowed_speed) max_allowed_speed = iphy->max_negotiated_speed; } @@ -1018,7 +898,7 @@ enum sas_linkrate scic_sds_port_get_max_allowed_speed(struct isci_port *iport) return max_allowed_speed; } -static void scic_sds_port_suspend_port_task_scheduler(struct isci_port *iport) +static void sci_port_suspend_port_task_scheduler(struct isci_port *iport) { u32 pts_control_value; @@ -1028,7 +908,7 @@ static void scic_sds_port_suspend_port_task_scheduler(struct isci_port *iport) } /** - * scic_sds_port_post_dummy_request() - post dummy/workaround request + * sci_port_post_dummy_request() - post dummy/workaround request * @sci_port: port to post task * * Prevent the hardware scheduler from posting new requests to the front @@ -1036,7 +916,7 @@ static void scic_sds_port_suspend_port_task_scheduler(struct isci_port *iport) * ongoing requests. * */ -static void scic_sds_port_post_dummy_request(struct isci_port *iport) +static void sci_port_post_dummy_request(struct isci_port *iport) { struct isci_host *ihost = iport->owning_controller; u16 tag = iport->reserved_tag; @@ -1050,7 +930,7 @@ static void scic_sds_port_post_dummy_request(struct isci_port *iport) iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ISCI_TAG_TCI(tag); - scic_sds_controller_post_request(ihost, command); + sci_controller_post_request(ihost, command); } /** @@ -1060,7 +940,7 @@ static void scic_sds_port_post_dummy_request(struct isci_port *iport) * @sci_port: The port on which the task must be aborted. * */ -static void scic_sds_port_abort_dummy_request(struct isci_port *iport) +static void sci_port_abort_dummy_request(struct isci_port *iport) { struct isci_host *ihost = iport->owning_controller; u16 tag = iport->reserved_tag; @@ -1074,7 +954,7 @@ static void scic_sds_port_abort_dummy_request(struct isci_port *iport) iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ISCI_TAG_TCI(tag); - scic_sds_controller_post_request(ihost, command); + sci_controller_post_request(ihost, command); } /** @@ -1084,7 +964,7 @@ static void scic_sds_port_abort_dummy_request(struct isci_port *iport) * This method will resume the port task scheduler for this port object. none */ static void -scic_sds_port_resume_port_task_scheduler(struct isci_port *iport) +sci_port_resume_port_task_scheduler(struct isci_port *iport) { u32 pts_control_value; @@ -1093,11 +973,11 @@ scic_sds_port_resume_port_task_scheduler(struct isci_port *iport) writel(pts_control_value, &iport->port_task_scheduler_registers->control); } -static void scic_sds_port_ready_substate_waiting_enter(struct sci_base_state_machine *sm) +static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); - scic_sds_port_suspend_port_task_scheduler(iport); + sci_port_suspend_port_task_scheduler(iport); iport->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; @@ -1108,7 +988,7 @@ static void scic_sds_port_ready_substate_waiting_enter(struct sci_base_state_mac } } -static void scic_sds_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) +static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) { u32 index; struct isci_port *iport = container_of(sm, typeof(*iport), sm); @@ -1124,18 +1004,18 @@ static void scic_sds_port_ready_substate_operational_enter(struct sci_base_state } } - scic_sds_port_update_viit_entry(iport); + sci_port_update_viit_entry(iport); - scic_sds_port_resume_port_task_scheduler(iport); + sci_port_resume_port_task_scheduler(iport); /* * Post the dummy task for the port so the hardware can schedule * io correctly */ - scic_sds_port_post_dummy_request(iport); + sci_port_post_dummy_request(iport); } -static void scic_sds_port_invalidate_dummy_remote_node(struct isci_port *iport) +static void sci_port_invalidate_dummy_remote_node(struct isci_port *iport) { struct isci_host *ihost = iport->owning_controller; u8 phys_index = iport->physical_port_index; @@ -1157,7 +1037,7 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct isci_port *iport) command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - scic_sds_controller_post_request(ihost, command); + sci_controller_post_request(ihost, command); } /** @@ -1168,7 +1048,7 @@ static void scic_sds_port_invalidate_dummy_remote_node(struct isci_port *iport) * exiting the SCI_PORT_SUB_OPERATIONAL. This function reports * the port not ready and suspends the port task scheduler. none */ -static void scic_sds_port_ready_substate_operational_exit(struct sci_base_state_machine *sm) +static void sci_port_ready_substate_operational_exit(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); struct isci_host *ihost = iport->owning_controller; @@ -1178,15 +1058,15 @@ static void scic_sds_port_ready_substate_operational_exit(struct sci_base_state_ * the hardware will treat this as a NOP and just return abort * complete. */ - scic_sds_port_abort_dummy_request(iport); + sci_port_abort_dummy_request(iport); isci_port_not_ready(ihost, iport); if (iport->ready_exit) - scic_sds_port_invalidate_dummy_remote_node(iport); + sci_port_invalidate_dummy_remote_node(iport); } -static void scic_sds_port_ready_substate_configuring_enter(struct sci_base_state_machine *sm) +static void sci_port_ready_substate_configuring_enter(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); struct isci_host *ihost = iport->owning_controller; @@ -1201,20 +1081,20 @@ static void scic_sds_port_ready_substate_configuring_enter(struct sci_base_state SCI_PORT_SUB_OPERATIONAL); } -static void scic_sds_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm) +static void sci_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); - scic_sds_port_suspend_port_task_scheduler(iport); + sci_port_suspend_port_task_scheduler(iport); if (iport->ready_exit) - scic_sds_port_invalidate_dummy_remote_node(iport); + sci_port_invalidate_dummy_remote_node(iport); } -enum sci_status scic_sds_port_start(struct isci_port *iport) +enum sci_status sci_port_start(struct isci_port *iport) { struct isci_host *ihost = iport->owning_controller; enum sci_status status = SCI_SUCCESS; - enum scic_sds_port_states state; + enum sci_port_states state; u32 phy_mask; state = iport->sm.current_state_id; @@ -1234,11 +1114,11 @@ enum sci_status scic_sds_port_start(struct isci_port *iport) } if (iport->reserved_rni == SCU_DUMMY_INDEX) { - u16 rni = scic_sds_remote_node_table_allocate_remote_node( + u16 rni = sci_remote_node_table_allocate_remote_node( &ihost->available_remote_nodes, 1); if (rni != SCU_DUMMY_INDEX) - scic_sds_port_construct_dummy_rnc(iport, rni); + sci_port_construct_dummy_rnc(iport, rni); else status = SCI_FAILURE_INSUFFICIENT_RESOURCES; iport->reserved_rni = rni; @@ -1251,19 +1131,19 @@ enum sci_status scic_sds_port_start(struct isci_port *iport) if (tag == SCI_CONTROLLER_INVALID_IO_TAG) status = SCI_FAILURE_INSUFFICIENT_RESOURCES; else - scic_sds_port_construct_dummy_task(iport, tag); + sci_port_construct_dummy_task(iport, tag); iport->reserved_tag = tag; } if (status == SCI_SUCCESS) { - phy_mask = scic_sds_port_get_phys(iport); + phy_mask = sci_port_get_phys(iport); /* * There are one or more phys assigned to this port. Make sure * the port's phy mask is in fact legal and supported by the * silicon. */ - if (scic_sds_port_is_phy_mask_valid(iport, phy_mask) == true) { + if (sci_port_is_phy_mask_valid(iport, phy_mask) == true) { port_state_machine_change(iport, SCI_PORT_READY); @@ -1273,14 +1153,14 @@ enum sci_status scic_sds_port_start(struct isci_port *iport) } if (status != SCI_SUCCESS) - scic_sds_port_destroy_dummy_resources(iport); + sci_port_destroy_dummy_resources(iport); return status; } -enum sci_status scic_sds_port_stop(struct isci_port *iport) +enum sci_status sci_port_stop(struct isci_port *iport) { - enum scic_sds_port_states state; + enum sci_port_states state; state = iport->sm.current_state_id; switch (state) { @@ -1300,11 +1180,11 @@ enum sci_status scic_sds_port_stop(struct isci_port *iport) } } -static enum sci_status scic_port_hard_reset(struct isci_port *iport, u32 timeout) +static enum sci_status sci_port_hard_reset(struct isci_port *iport, u32 timeout) { enum sci_status status = SCI_FAILURE_INVALID_PHY; struct isci_phy *iphy = NULL; - enum scic_sds_port_states state; + enum sci_port_states state; u32 phy_index; state = iport->sm.current_state_id; @@ -1317,7 +1197,7 @@ static enum sci_status scic_port_hard_reset(struct isci_port *iport, u32 timeout /* Select a phy on which we can send the hard reset request. */ for (phy_index = 0; phy_index < SCI_MAX_PHYS && !iphy; phy_index++) { iphy = iport->phy_table[phy_index]; - if (iphy && !scic_sds_port_active_phy(iport, iphy)) { + if (iphy && !sci_port_active_phy(iport, iphy)) { /* * We found a phy but it is not ready select * different phy @@ -1329,7 +1209,7 @@ static enum sci_status scic_port_hard_reset(struct isci_port *iport, u32 timeout /* If we have a phy then go ahead and start the reset procedure */ if (!iphy) return status; - status = scic_sds_phy_reset(iphy); + status = sci_phy_reset(iphy); if (status != SCI_SUCCESS) return status; @@ -1342,7 +1222,7 @@ static enum sci_status scic_port_hard_reset(struct isci_port *iport, u32 timeout } /** - * scic_sds_port_add_phy() - + * sci_port_add_phy() - * @sci_port: This parameter specifies the port in which the phy will be added. * @sci_phy: This parameter is the phy which is to be added to the port. * @@ -1350,11 +1230,11 @@ static enum sci_status scic_port_hard_reset(struct isci_port *iport, u32 timeout * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other * status is a failure to add the phy to the port. */ -enum sci_status scic_sds_port_add_phy(struct isci_port *iport, +enum sci_status sci_port_add_phy(struct isci_port *iport, struct isci_phy *iphy) { enum sci_status status; - enum scic_sds_port_states state; + enum sci_port_states state; state = iport->sm.current_state_id; switch (state) { @@ -1362,7 +1242,7 @@ enum sci_status scic_sds_port_add_phy(struct isci_port *iport, struct sci_sas_address port_sas_address; /* Read the port assigned SAS Address if there is one */ - scic_sds_port_get_sas_address(iport, &port_sas_address); + sci_port_get_sas_address(iport, &port_sas_address); if (port_sas_address.high != 0 && port_sas_address.low != 0) { struct sci_sas_address phy_sas_address; @@ -1370,32 +1250,32 @@ enum sci_status scic_sds_port_add_phy(struct isci_port *iport, /* Make sure that the PHY SAS Address matches the SAS Address * for this port */ - scic_sds_phy_get_sas_address(iphy, &phy_sas_address); + sci_phy_get_sas_address(iphy, &phy_sas_address); if (port_sas_address.high != phy_sas_address.high || port_sas_address.low != phy_sas_address.low) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; } - return scic_sds_port_set_phy(iport, iphy); + return sci_port_set_phy(iport, iphy); } case SCI_PORT_SUB_WAITING: case SCI_PORT_SUB_OPERATIONAL: - status = scic_sds_port_set_phy(iport, iphy); + status = sci_port_set_phy(iport, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_general_link_up_handler(iport, iphy, true); + sci_port_general_link_up_handler(iport, iphy, true); iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); return status; case SCI_PORT_SUB_CONFIGURING: - status = scic_sds_port_set_phy(iport, iphy); + status = sci_port_set_phy(iport, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_general_link_up_handler(iport, iphy, true); + sci_port_general_link_up_handler(iport, iphy, true); /* Re-enter the configuring state since this may be the last phy in * the port. @@ -1411,7 +1291,7 @@ enum sci_status scic_sds_port_add_phy(struct isci_port *iport, } /** - * scic_sds_port_remove_phy() - + * sci_port_remove_phy() - * @sci_port: This parameter specifies the port in which the phy will be added. * @sci_phy: This parameter is the phy which is to be added to the port. * @@ -1419,33 +1299,33 @@ enum sci_status scic_sds_port_add_phy(struct isci_port *iport, * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any * other status is a failure to add the phy to the port. */ -enum sci_status scic_sds_port_remove_phy(struct isci_port *iport, +enum sci_status sci_port_remove_phy(struct isci_port *iport, struct isci_phy *iphy) { enum sci_status status; - enum scic_sds_port_states state; + enum sci_port_states state; state = iport->sm.current_state_id; switch (state) { case SCI_PORT_STOPPED: - return scic_sds_port_clear_phy(iport, iphy); + return sci_port_clear_phy(iport, iphy); case SCI_PORT_SUB_OPERATIONAL: - status = scic_sds_port_clear_phy(iport, iphy); + status = sci_port_clear_phy(iport, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_deactivate_phy(iport, iphy, true); + sci_port_deactivate_phy(iport, iphy, true); iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); return SCI_SUCCESS; case SCI_PORT_SUB_CONFIGURING: - status = scic_sds_port_clear_phy(iport, iphy); + status = sci_port_clear_phy(iport, iphy); if (status != SCI_SUCCESS) return status; - scic_sds_port_deactivate_phy(iport, iphy, true); + sci_port_deactivate_phy(iport, iphy, true); /* Re-enter the configuring state since this may be the last phy in * the port @@ -1460,10 +1340,10 @@ enum sci_status scic_sds_port_remove_phy(struct isci_port *iport, } } -enum sci_status scic_sds_port_link_up(struct isci_port *iport, +enum sci_status sci_port_link_up(struct isci_port *iport, struct isci_phy *iphy) { - enum scic_sds_port_states state; + enum sci_port_states state; state = iport->sm.current_state_id; switch (state) { @@ -1471,13 +1351,13 @@ enum sci_status scic_sds_port_link_up(struct isci_port *iport, /* Since this is the first phy going link up for the port we * can just enable it and continue */ - scic_sds_port_activate_phy(iport, iphy, true); + sci_port_activate_phy(iport, iphy, true); port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); return SCI_SUCCESS; case SCI_PORT_SUB_OPERATIONAL: - scic_sds_port_general_link_up_handler(iport, iphy, true); + sci_port_general_link_up_handler(iport, iphy, true); return SCI_SUCCESS; case SCI_PORT_RESETTING: /* TODO We should make sure that the phy that has gone @@ -1494,7 +1374,7 @@ enum sci_status scic_sds_port_link_up(struct isci_port *iport, /* In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_general_link_up_handler(iport, iphy, false); + sci_port_general_link_up_handler(iport, iphy, false); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(iport), @@ -1503,15 +1383,15 @@ enum sci_status scic_sds_port_link_up(struct isci_port *iport, } } -enum sci_status scic_sds_port_link_down(struct isci_port *iport, +enum sci_status sci_port_link_down(struct isci_port *iport, struct isci_phy *iphy) { - enum scic_sds_port_states state; + enum sci_port_states state; state = iport->sm.current_state_id; switch (state) { case SCI_PORT_SUB_OPERATIONAL: - scic_sds_port_deactivate_phy(iport, iphy, true); + sci_port_deactivate_phy(iport, iphy, true); /* If there are no active phys left in the port, then * transition the port to the WAITING state until such time @@ -1524,7 +1404,7 @@ enum sci_status scic_sds_port_link_down(struct isci_port *iport, case SCI_PORT_RESETTING: /* In the resetting state we don't notify the user regarding * link up and link down notifications. */ - scic_sds_port_deactivate_phy(iport, iphy, false); + sci_port_deactivate_phy(iport, iphy, false); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(iport), @@ -1533,11 +1413,11 @@ enum sci_status scic_sds_port_link_down(struct isci_port *iport, } } -enum sci_status scic_sds_port_start_io(struct isci_port *iport, - struct isci_remote_device *idev, - struct isci_request *ireq) +enum sci_status sci_port_start_io(struct isci_port *iport, + struct isci_remote_device *idev, + struct isci_request *ireq) { - enum scic_sds_port_states state; + enum sci_port_states state; state = iport->sm.current_state_id; switch (state) { @@ -1553,11 +1433,11 @@ enum sci_status scic_sds_port_start_io(struct isci_port *iport, } } -enum sci_status scic_sds_port_complete_io(struct isci_port *iport, - struct isci_remote_device *idev, - struct isci_request *ireq) +enum sci_status sci_port_complete_io(struct isci_port *iport, + struct isci_remote_device *idev, + struct isci_request *ireq) { - enum scic_sds_port_states state; + enum sci_port_states state; state = iport->sm.current_state_id; switch (state) { @@ -1566,7 +1446,7 @@ enum sci_status scic_sds_port_complete_io(struct isci_port *iport, "%s: in wrong state: %d\n", __func__, state); return SCI_FAILURE_INVALID_STATE; case SCI_PORT_STOPPING: - scic_sds_port_decrement_request_count(iport); + sci_port_decrement_request_count(iport); if (iport->started_request_count == 0) port_state_machine_change(iport, @@ -1577,10 +1457,10 @@ enum sci_status scic_sds_port_complete_io(struct isci_port *iport, case SCI_PORT_FAILED: case SCI_PORT_SUB_WAITING: case SCI_PORT_SUB_OPERATIONAL: - scic_sds_port_decrement_request_count(iport); + sci_port_decrement_request_count(iport); break; case SCI_PORT_SUB_CONFIGURING: - scic_sds_port_decrement_request_count(iport); + sci_port_decrement_request_count(iport); if (iport->started_request_count == 0) { port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); @@ -1590,32 +1470,17 @@ enum sci_status scic_sds_port_complete_io(struct isci_port *iport, return SCI_SUCCESS; } -/** - * - * @sci_port: This is the port object which to suspend. - * - * This method will enable the SCU Port Task Scheduler for this port object but - * will leave the port task scheduler in a suspended state. none - */ -static void -scic_sds_port_enable_port_task_scheduler(struct isci_port *iport) +static void sci_port_enable_port_task_scheduler(struct isci_port *iport) { u32 pts_control_value; + /* enable the port task scheduler in a suspended state */ pts_control_value = readl(&iport->port_task_scheduler_registers->control); pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND); writel(pts_control_value, &iport->port_task_scheduler_registers->control); } -/** - * - * @sci_port: This is the port object which to resume. - * - * This method will disable the SCU port task scheduler for this port object. - * none - */ -static void -scic_sds_port_disable_port_task_scheduler(struct isci_port *iport) +static void sci_port_disable_port_task_scheduler(struct isci_port *iport) { u32 pts_control_value; @@ -1625,7 +1490,7 @@ scic_sds_port_disable_port_task_scheduler(struct isci_port *iport) writel(pts_control_value, &iport->port_task_scheduler_registers->control); } -static void scic_sds_port_post_dummy_remote_node(struct isci_port *iport) +static void sci_port_post_dummy_remote_node(struct isci_port *iport) { struct isci_host *ihost = iport->owning_controller; u8 phys_index = iport->physical_port_index; @@ -1639,7 +1504,7 @@ static void scic_sds_port_post_dummy_remote_node(struct isci_port *iport) command = SCU_CONTEXT_COMMAND_POST_RNC_32 | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - scic_sds_controller_post_request(ihost, command); + sci_controller_post_request(ihost, command); /* ensure hardware has seen the post rnc command and give it * ample time to act before sending the suspend @@ -1650,10 +1515,10 @@ static void scic_sds_port_post_dummy_remote_node(struct isci_port *iport) command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; - scic_sds_controller_post_request(ihost, command); + sci_controller_post_request(ihost, command); } -static void scic_sds_port_stopped_state_enter(struct sci_base_state_machine *sm) +static void sci_port_stopped_state_enter(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); @@ -1662,19 +1527,19 @@ static void scic_sds_port_stopped_state_enter(struct sci_base_state_machine *sm) * If we enter this state becasuse of a request to stop * the port then we want to disable the hardwares port * task scheduler. */ - scic_sds_port_disable_port_task_scheduler(iport); + sci_port_disable_port_task_scheduler(iport); } } -static void scic_sds_port_stopped_state_exit(struct sci_base_state_machine *sm) +static void sci_port_stopped_state_exit(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); /* Enable and suspend the port task scheduler */ - scic_sds_port_enable_port_task_scheduler(iport); + sci_port_enable_port_task_scheduler(iport); } -static void scic_sds_port_ready_state_enter(struct sci_base_state_machine *sm) +static void sci_port_ready_state_enter(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); struct isci_host *ihost = iport->owning_controller; @@ -1687,30 +1552,30 @@ static void scic_sds_port_ready_state_enter(struct sci_base_state_machine *sm) isci_port_not_ready(ihost, iport); /* Post and suspend the dummy remote node context for this port. */ - scic_sds_port_post_dummy_remote_node(iport); + sci_port_post_dummy_remote_node(iport); /* Start the ready substate machine */ port_state_machine_change(iport, SCI_PORT_SUB_WAITING); } -static void scic_sds_port_resetting_state_exit(struct sci_base_state_machine *sm) +static void sci_port_resetting_state_exit(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); sci_del_timer(&iport->timer); } -static void scic_sds_port_stopping_state_exit(struct sci_base_state_machine *sm) +static void sci_port_stopping_state_exit(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); sci_del_timer(&iport->timer); - scic_sds_port_destroy_dummy_resources(iport); + sci_port_destroy_dummy_resources(iport); } -static void scic_sds_port_failed_state_enter(struct sci_base_state_machine *sm) +static void sci_port_failed_state_enter(struct sci_base_state_machine *sm) { struct isci_port *iport = container_of(sm, typeof(*iport), sm); @@ -1719,40 +1584,40 @@ static void scic_sds_port_failed_state_enter(struct sci_base_state_machine *sm) /* --------------------------------------------------------------------------- */ -static const struct sci_base_state scic_sds_port_state_table[] = { +static const struct sci_base_state sci_port_state_table[] = { [SCI_PORT_STOPPED] = { - .enter_state = scic_sds_port_stopped_state_enter, - .exit_state = scic_sds_port_stopped_state_exit + .enter_state = sci_port_stopped_state_enter, + .exit_state = sci_port_stopped_state_exit }, [SCI_PORT_STOPPING] = { - .exit_state = scic_sds_port_stopping_state_exit + .exit_state = sci_port_stopping_state_exit }, [SCI_PORT_READY] = { - .enter_state = scic_sds_port_ready_state_enter, + .enter_state = sci_port_ready_state_enter, }, [SCI_PORT_SUB_WAITING] = { - .enter_state = scic_sds_port_ready_substate_waiting_enter, + .enter_state = sci_port_ready_substate_waiting_enter, }, [SCI_PORT_SUB_OPERATIONAL] = { - .enter_state = scic_sds_port_ready_substate_operational_enter, - .exit_state = scic_sds_port_ready_substate_operational_exit + .enter_state = sci_port_ready_substate_operational_enter, + .exit_state = sci_port_ready_substate_operational_exit }, [SCI_PORT_SUB_CONFIGURING] = { - .enter_state = scic_sds_port_ready_substate_configuring_enter, - .exit_state = scic_sds_port_ready_substate_configuring_exit + .enter_state = sci_port_ready_substate_configuring_enter, + .exit_state = sci_port_ready_substate_configuring_exit }, [SCI_PORT_RESETTING] = { - .exit_state = scic_sds_port_resetting_state_exit + .exit_state = sci_port_resetting_state_exit }, [SCI_PORT_FAILED] = { - .enter_state = scic_sds_port_failed_state_enter, + .enter_state = sci_port_failed_state_enter, } }; -void scic_sds_port_construct(struct isci_port *iport, u8 index, +void sci_port_construct(struct isci_port *iport, u8 index, struct isci_host *ihost) { - sci_init_sm(&iport->sm, scic_sds_port_state_table, SCI_PORT_STOPPED); + sci_init_sm(&iport->sm, sci_port_state_table, SCI_PORT_STOPPED); iport->logical_port_index = SCIC_SDS_DUMMY_PORT; iport->physical_port_index = index; @@ -1798,9 +1663,7 @@ enum isci_status isci_port_get_state( return isci_port->status; } -void scic_sds_port_broadcast_change_received( - struct isci_port *iport, - struct isci_phy *iphy) +void sci_port_broadcast_change_received(struct isci_port *iport, struct isci_phy *iphy) { struct isci_host *ihost = iport->owning_controller; @@ -1823,7 +1686,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor spin_lock_irqsave(&ihost->scic_lock, flags); #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT - status = scic_port_hard_reset(iport, ISCI_PORT_RESET_TIMEOUT); + status = sci_port_hard_reset(iport, ISCI_PORT_RESET_TIMEOUT); spin_unlock_irqrestore(&ihost->scic_lock, flags); @@ -1840,7 +1703,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor ret = TMF_RESP_FUNC_FAILED; dev_err(&ihost->pdev->dev, - "%s: iport = %p; scic_port_hard_reset call" + "%s: iport = %p; sci_port_hard_reset call" " failed 0x%x\n", __func__, iport, status); @@ -1863,8 +1726,8 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor if (!iphy) continue; - scic_sds_phy_stop(iphy); - scic_sds_phy_start(iphy); + sci_phy_stop(iphy); + sci_phy_start(iphy); } spin_unlock_irqrestore(&ihost->scic_lock, flags); } diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 9a9be7b47b4a..4c4ab8126d9f 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -123,7 +123,7 @@ struct isci_port { struct scu_viit_entry __iomem *viit_registers; }; -enum scic_port_not_ready_reason_code { +enum sci_port_not_ready_reason_code { SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, @@ -132,25 +132,25 @@ enum scic_port_not_ready_reason_code { SCIC_PORT_NOT_READY_REASON_CODE_MAX }; -struct scic_port_end_point_properties { +struct sci_port_end_point_properties { struct sci_sas_address sas_address; - struct scic_phy_proto protocols; + struct sci_phy_proto protocols; }; -struct scic_port_properties { +struct sci_port_properties { u32 index; - struct scic_port_end_point_properties local; - struct scic_port_end_point_properties remote; + struct sci_port_end_point_properties local; + struct sci_port_end_point_properties remote; u32 phy_mask; }; /** - * enum scic_sds_port_states - This enumeration depicts all the states for the + * enum sci_port_states - This enumeration depicts all the states for the * common port state machine. * * */ -enum scic_sds_port_states { +enum sci_port_states { /** * This state indicates that the port has successfully been stopped. * In this state no new IO operations are permitted. @@ -211,23 +211,23 @@ enum scic_sds_port_states { }; /** - * scic_sds_port_get_controller() - + * sci_port_get_controller() - * * Helper macro to get the owning controller of this port */ -#define scic_sds_port_get_controller(this_port) \ +#define sci_port_get_controller(this_port) \ ((this_port)->owning_controller) /** - * scic_sds_port_get_index() - + * sci_port_get_index() - * * This macro returns the physical port index for this port object */ -#define scic_sds_port_get_index(this_port) \ +#define sci_port_get_index(this_port) \ ((this_port)->physical_port_index) -static inline void scic_sds_port_decrement_request_count(struct isci_port *iport) +static inline void sci_port_decrement_request_count(struct isci_port *iport) { if (WARN_ONCE(iport->started_request_count == 0, "%s: tried to decrement started_request_count past 0!?", @@ -237,79 +237,73 @@ static inline void scic_sds_port_decrement_request_count(struct isci_port *iport iport->started_request_count--; } -#define scic_sds_port_active_phy(port, phy) \ +#define sci_port_active_phy(port, phy) \ (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) -void scic_sds_port_construct( +void sci_port_construct( struct isci_port *iport, u8 port_index, struct isci_host *ihost); -enum sci_status scic_sds_port_initialize( - struct isci_port *iport, - void __iomem *port_task_scheduler_registers, - void __iomem *port_configuration_regsiter, - void __iomem *viit_registers); - -enum sci_status scic_sds_port_start(struct isci_port *iport); -enum sci_status scic_sds_port_stop(struct isci_port *iport); +enum sci_status sci_port_start(struct isci_port *iport); +enum sci_status sci_port_stop(struct isci_port *iport); -enum sci_status scic_sds_port_add_phy( +enum sci_status sci_port_add_phy( struct isci_port *iport, struct isci_phy *iphy); -enum sci_status scic_sds_port_remove_phy( +enum sci_status sci_port_remove_phy( struct isci_port *iport, struct isci_phy *iphy); -void scic_sds_port_setup_transports( +void sci_port_setup_transports( struct isci_port *iport, u32 device_id); void isci_port_bcn_enable(struct isci_host *, struct isci_port *); -void scic_sds_port_deactivate_phy( +void sci_port_deactivate_phy( struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user); -bool scic_sds_port_link_detected( +bool sci_port_link_detected( struct isci_port *iport, struct isci_phy *iphy); -enum sci_status scic_sds_port_link_up(struct isci_port *iport, +enum sci_status sci_port_link_up(struct isci_port *iport, struct isci_phy *iphy); -enum sci_status scic_sds_port_link_down(struct isci_port *iport, +enum sci_status sci_port_link_down(struct isci_port *iport, struct isci_phy *iphy); struct isci_request; struct isci_remote_device; -enum sci_status scic_sds_port_start_io( +enum sci_status sci_port_start_io( struct isci_port *iport, struct isci_remote_device *idev, struct isci_request *ireq); -enum sci_status scic_sds_port_complete_io( +enum sci_status sci_port_complete_io( struct isci_port *iport, struct isci_remote_device *idev, struct isci_request *ireq); -enum sas_linkrate scic_sds_port_get_max_allowed_speed( +enum sas_linkrate sci_port_get_max_allowed_speed( struct isci_port *iport); -void scic_sds_port_broadcast_change_received( +void sci_port_broadcast_change_received( struct isci_port *iport, struct isci_phy *iphy); -bool scic_sds_port_is_valid_phy_assignment( +bool sci_port_is_valid_phy_assignment( struct isci_port *iport, u32 phy_index); -void scic_sds_port_get_sas_address( +void sci_port_get_sas_address( struct isci_port *iport, struct sci_sas_address *sas_address); -void scic_sds_port_get_attached_sas_address( +void sci_port_get_attached_sas_address( struct isci_port *iport, struct sci_sas_address *sas_address); diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index a0a135d54e95..c8b16db6bbde 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -112,7 +112,7 @@ static s32 sci_sas_address_compare( * port. port address if the port can be found to match the phy. * NULL if there is no matching port for the phy. */ -static struct isci_port *scic_sds_port_configuration_agent_find_port( +static struct isci_port *sci_port_configuration_agent_find_port( struct isci_host *ihost, struct isci_phy *iphy) { @@ -127,14 +127,14 @@ static struct isci_port *scic_sds_port_configuration_agent_find_port( * more phys match the sent and received SAS address as this phy in which * case it should participate in the same port. */ - scic_sds_phy_get_sas_address(iphy, &phy_sas_address); - scic_sds_phy_get_attached_sas_address(iphy, &phy_attached_device_address); + sci_phy_get_sas_address(iphy, &phy_sas_address); + sci_phy_get_attached_sas_address(iphy, &phy_attached_device_address); for (i = 0; i < ihost->logical_port_entries; i++) { struct isci_port *iport = &ihost->ports[i]; - scic_sds_port_get_sas_address(iport, &port_sas_address); - scic_sds_port_get_attached_sas_address(iport, &port_attached_device_address); + sci_port_get_sas_address(iport, &port_sas_address); + sci_port_get_attached_sas_address(iport, &port_attached_device_address); if (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0 && sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) @@ -156,9 +156,9 @@ static struct isci_port *scic_sds_port_configuration_agent_find_port( * this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION * the port configuration is not valid for this port configuration agent. */ -static enum sci_status scic_sds_port_configuration_agent_validate_ports( +static enum sci_status sci_port_configuration_agent_validate_ports( struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent) + struct sci_port_configuration_agent *port_agent) { struct sci_sas_address first_address; struct sci_sas_address second_address; @@ -194,8 +194,8 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * PE0 and PE3 can never have the same SAS Address unless they * are part of the same x4 wide port and we have already checked * for this condition. */ - scic_sds_phy_get_sas_address(&ihost->phys[0], &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[3], &second_address); + sci_phy_get_sas_address(&ihost->phys[0], &first_address); + sci_phy_get_sas_address(&ihost->phys[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -207,8 +207,8 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * part of the same port. */ if (port_agent->phy_valid_port_range[0].min_index == 0 && port_agent->phy_valid_port_range[1].min_index == 1) { - scic_sds_phy_get_sas_address(&ihost->phys[0], &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[2], &second_address); + sci_phy_get_sas_address(&ihost->phys[0], &first_address); + sci_phy_get_sas_address(&ihost->phys[2], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -221,8 +221,8 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( * part of the same port. */ if (port_agent->phy_valid_port_range[2].min_index == 2 && port_agent->phy_valid_port_range[3].min_index == 3) { - scic_sds_phy_get_sas_address(&ihost->phys[1], &first_address); - scic_sds_phy_get_sas_address(&ihost->phys[3], &second_address); + sci_phy_get_sas_address(&ihost->phys[1], &first_address); + sci_phy_get_sas_address(&ihost->phys[3], &second_address); if (sci_sas_address_compare(first_address, second_address) == 0) { return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; @@ -239,8 +239,8 @@ static enum sci_status scic_sds_port_configuration_agent_validate_ports( /* verify all of the phys in the same port are using the same SAS address */ static enum sci_status -scic_sds_mpc_agent_validate_phy_configuration(struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent) +sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost, + struct sci_port_configuration_agent *port_agent) { u32 phy_mask; u32 assigned_phy_mask; @@ -254,7 +254,7 @@ scic_sds_mpc_agent_validate_phy_configuration(struct isci_host *ihost, sas_address.low = 0; for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { - phy_mask = ihost->oem_parameters.sds1.ports[port_index].phy_mask; + phy_mask = ihost->oem_parameters.ports[port_index].phy_mask; if (!phy_mask) continue; @@ -269,7 +269,7 @@ scic_sds_mpc_agent_validate_phy_configuration(struct isci_host *ihost, for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { if ((phy_mask & (1 << phy_index)) == 0) continue; - scic_sds_phy_get_sas_address(&ihost->phys[phy_index], + sci_phy_get_sas_address(&ihost->phys[phy_index], &sas_address); /* @@ -294,7 +294,7 @@ scic_sds_mpc_agent_validate_phy_configuration(struct isci_host *ihost, while (phy_index < SCI_MAX_PHYS) { if ((phy_mask & (1 << phy_index)) == 0) continue; - scic_sds_phy_get_sas_address(&ihost->phys[phy_index], + sci_phy_get_sas_address(&ihost->phys[phy_index], &phy_assigned_address); if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { @@ -307,7 +307,7 @@ scic_sds_mpc_agent_validate_phy_configuration(struct isci_host *ihost, port_agent->phy_valid_port_range[phy_index].min_index = port_index; port_agent->phy_valid_port_range[phy_index].max_index = phy_index; - scic_sds_port_add_phy(&ihost->ports[port_index], + sci_port_add_phy(&ihost->ports[port_index], &ihost->phys[phy_index]); assigned_phy_mask |= (1 << phy_index); @@ -316,14 +316,14 @@ scic_sds_mpc_agent_validate_phy_configuration(struct isci_host *ihost, phy_index++; } - return scic_sds_port_configuration_agent_validate_ports(ihost, port_agent); + return sci_port_configuration_agent_validate_ports(ihost, port_agent); } static void mpc_agent_timeout(unsigned long data) { u8 index; struct sci_timer *tmr = (struct sci_timer *)data; - struct scic_sds_port_configuration_agent *port_agent; + struct sci_port_configuration_agent *port_agent; struct isci_host *ihost; unsigned long flags; u16 configure_phy_mask; @@ -355,8 +355,8 @@ done: spin_unlock_irqrestore(&ihost->scic_lock, flags); } -static void scic_sds_mpc_agent_link_up(struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent, +static void sci_mpc_agent_link_up(struct isci_host *ihost, + struct sci_port_configuration_agent *port_agent, struct isci_port *iport, struct isci_phy *iphy) { @@ -367,10 +367,10 @@ static void scic_sds_mpc_agent_link_up(struct isci_host *ihost, if (!iport) return; - port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(iphy)); - scic_sds_port_link_up(iport, iphy); - if ((iport->active_phy_mask & (1 << scic_sds_phy_get_index(iphy)))) - port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(iphy)); + port_agent->phy_ready_mask |= (1 << sci_phy_get_index(iphy)); + sci_port_link_up(iport, iphy); + if ((iport->active_phy_mask & (1 << sci_phy_get_index(iphy)))) + port_agent->phy_configured_mask |= (1 << sci_phy_get_index(iphy)); } /** @@ -390,9 +390,9 @@ static void scic_sds_mpc_agent_link_up(struct isci_host *ihost, * not associated with a port there is no action taken. Is it possible to get a * link down notification from a phy that has no assocoated port? */ -static void scic_sds_mpc_agent_link_down( +static void sci_mpc_agent_link_down( struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent, + struct sci_port_configuration_agent *port_agent, struct isci_port *iport, struct isci_phy *iphy) { @@ -405,9 +405,9 @@ static void scic_sds_mpc_agent_link_down( * state. */ port_agent->phy_ready_mask &= - ~(1 << scic_sds_phy_get_index(iphy)); + ~(1 << sci_phy_get_index(iphy)); port_agent->phy_configured_mask &= - ~(1 << scic_sds_phy_get_index(iphy)); + ~(1 << sci_phy_get_index(iphy)); /* * Check to see if there are more phys waiting to be @@ -424,7 +424,7 @@ static void scic_sds_mpc_agent_link_down( SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT); } - scic_sds_port_link_down(iport, iphy); + sci_port_link_down(iport, iphy); } } @@ -432,8 +432,8 @@ static void scic_sds_mpc_agent_link_down( * configuration mode. */ static enum sci_status -scic_sds_apc_agent_validate_phy_configuration(struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent) +sci_apc_agent_validate_phy_configuration(struct isci_host *ihost, + struct sci_port_configuration_agent *port_agent) { u8 phy_index; u8 port_index; @@ -446,11 +446,11 @@ scic_sds_apc_agent_validate_phy_configuration(struct isci_host *ihost, port_index = phy_index; /* Get the assigned SAS Address for the first PHY on the controller. */ - scic_sds_phy_get_sas_address(&ihost->phys[phy_index], + sci_phy_get_sas_address(&ihost->phys[phy_index], &sas_address); while (++phy_index < SCI_MAX_PHYS) { - scic_sds_phy_get_sas_address(&ihost->phys[phy_index], + sci_phy_get_sas_address(&ihost->phys[phy_index], &phy_assigned_address); /* Verify each of the SAS address are all the same for every PHY */ @@ -465,11 +465,11 @@ scic_sds_apc_agent_validate_phy_configuration(struct isci_host *ihost, } } - return scic_sds_port_configuration_agent_validate_ports(ihost, port_agent); + return sci_port_configuration_agent_validate_ports(ihost, port_agent); } -static void scic_sds_apc_agent_configure_ports(struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent, +static void sci_apc_agent_configure_ports(struct isci_host *ihost, + struct sci_port_configuration_agent *port_agent, struct isci_phy *iphy, bool start_timer) { @@ -478,10 +478,10 @@ static void scic_sds_apc_agent_configure_ports(struct isci_host *ihost, struct isci_port *iport; enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; - iport = scic_sds_port_configuration_agent_find_port(ihost, iphy); + iport = sci_port_configuration_agent_find_port(ihost, iphy); if (iport) { - if (scic_sds_port_is_valid_phy_assignment(iport, iphy->phy_index)) + if (sci_port_is_valid_phy_assignment(iport, iphy->phy_index)) apc_activity = SCIC_SDS_APC_ADD_PHY; else apc_activity = SCIC_SDS_APC_SKIP_PHY; @@ -499,7 +499,7 @@ static void scic_sds_apc_agent_configure_ports(struct isci_host *ihost, iport = &ihost->ports[port_index]; /* First we must make sure that this PHY can be added to this Port. */ - if (scic_sds_port_is_valid_phy_assignment(iport, iphy->phy_index)) { + if (sci_port_is_valid_phy_assignment(iport, iphy->phy_index)) { /* * Port contains a PHY with a greater PHY ID than the current * PHY that has gone link up. This phy can not be part of any @@ -559,7 +559,7 @@ static void scic_sds_apc_agent_configure_ports(struct isci_host *ihost, switch (apc_activity) { case SCIC_SDS_APC_ADD_PHY: - status = scic_sds_port_add_phy(iport, iphy); + status = sci_port_add_phy(iport, iphy); if (status == SCI_SUCCESS) { port_agent->phy_configured_mask |= (1 << iphy->phy_index); @@ -588,7 +588,7 @@ static void scic_sds_apc_agent_configure_ports(struct isci_host *ihost, } /** - * scic_sds_apc_agent_link_up - handle apc link up events + * sci_apc_agent_link_up - handle apc link up events * @scic: This is the controller object that receives the link up * notification. * @sci_port: This is the port object associated with the phy. If the is no @@ -599,8 +599,8 @@ static void scic_sds_apc_agent_configure_ports(struct isci_host *ihost, * notifications. Is it possible to get a link down notification from a phy * that has no assocoated port? */ -static void scic_sds_apc_agent_link_up(struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent, +static void sci_apc_agent_link_up(struct isci_host *ihost, + struct sci_port_configuration_agent *port_agent, struct isci_port *iport, struct isci_phy *iphy) { @@ -609,7 +609,7 @@ static void scic_sds_apc_agent_link_up(struct isci_host *ihost, if (!iport) { /* the phy is not the part of this port */ port_agent->phy_ready_mask |= 1 << phy_index; - scic_sds_apc_agent_configure_ports(ihost, port_agent, iphy, true); + sci_apc_agent_configure_ports(ihost, port_agent, iphy, true); } else { /* the phy is already the part of the port */ u32 port_state = iport->sm.current_state_id; @@ -620,7 +620,7 @@ static void scic_sds_apc_agent_link_up(struct isci_host *ihost, */ BUG_ON(port_state != SCI_PORT_RESETTING); port_agent->phy_ready_mask |= 1 << phy_index; - scic_sds_port_link_up(iport, iphy); + sci_port_link_up(iport, iphy); } } @@ -637,20 +637,20 @@ static void scic_sds_apc_agent_link_up(struct isci_host *ihost, * possible to get a link down notification from a phy that has no assocoated * port? */ -static void scic_sds_apc_agent_link_down( +static void sci_apc_agent_link_down( struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent, + struct sci_port_configuration_agent *port_agent, struct isci_port *iport, struct isci_phy *iphy) { - port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(iphy)); + port_agent->phy_ready_mask &= ~(1 << sci_phy_get_index(iphy)); if (!iport) return; if (port_agent->phy_configured_mask & (1 << iphy->phy_index)) { enum sci_status status; - status = scic_sds_port_remove_phy(iport, iphy); + status = sci_port_remove_phy(iport, iphy); if (status == SCI_SUCCESS) port_agent->phy_configured_mask &= ~(1 << iphy->phy_index); @@ -662,7 +662,7 @@ static void apc_agent_timeout(unsigned long data) { u32 index; struct sci_timer *tmr = (struct sci_timer *)data; - struct scic_sds_port_configuration_agent *port_agent; + struct sci_port_configuration_agent *port_agent; struct isci_host *ihost; unsigned long flags; u16 configure_phy_mask; @@ -686,7 +686,7 @@ static void apc_agent_timeout(unsigned long data) if ((configure_phy_mask & (1 << index)) == 0) continue; - scic_sds_apc_agent_configure_ports(ihost, port_agent, + sci_apc_agent_configure_ports(ihost, port_agent, &ihost->phys[index], false); } @@ -706,8 +706,8 @@ done: * call is universal for both manual port configuration and automatic port * configuration modes. */ -void scic_sds_port_configuration_agent_construct( - struct scic_sds_port_configuration_agent *port_agent) +void sci_port_configuration_agent_construct( + struct sci_port_configuration_agent *port_agent) { u32 index; @@ -725,29 +725,29 @@ void scic_sds_port_configuration_agent_construct( } } -enum sci_status scic_sds_port_configuration_agent_initialize( +enum sci_status sci_port_configuration_agent_initialize( struct isci_host *ihost, - struct scic_sds_port_configuration_agent *port_agent) + struct sci_port_configuration_agent *port_agent) { enum sci_status status; - enum scic_port_configuration_mode mode; + enum sci_port_configuration_mode mode; - mode = ihost->oem_parameters.sds1.controller.mode_type; + mode = ihost->oem_parameters.controller.mode_type; if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { - status = scic_sds_mpc_agent_validate_phy_configuration( + status = sci_mpc_agent_validate_phy_configuration( ihost, port_agent); - port_agent->link_up_handler = scic_sds_mpc_agent_link_up; - port_agent->link_down_handler = scic_sds_mpc_agent_link_down; + port_agent->link_up_handler = sci_mpc_agent_link_up; + port_agent->link_down_handler = sci_mpc_agent_link_down; sci_init_timer(&port_agent->timer, mpc_agent_timeout); } else { - status = scic_sds_apc_agent_validate_phy_configuration( + status = sci_apc_agent_validate_phy_configuration( ihost, port_agent); - port_agent->link_up_handler = scic_sds_apc_agent_link_up; - port_agent->link_down_handler = scic_sds_apc_agent_link_down; + port_agent->link_up_handler = sci_apc_agent_link_up; + port_agent->link_down_handler = sci_apc_agent_link_down; sci_init_timer(&port_agent->timer, apc_agent_timeout); } diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 99b13c191877..c7732fb28889 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -111,25 +111,15 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) return rom; } -/** - * isci_parse_oem_parameters() - This method will take OEM parameters - * from the module init parameters and copy them to oem_params. This will - * only copy values that are not set to the module parameter default values - * @oem_parameters: This parameter specifies the controller default OEM - * parameters. It is expected that this has been initialized to the default - * parameters for the controller - * - * - */ -enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, +enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem, struct isci_orom *orom, int scu_index) { /* check for valid inputs */ if (scu_index < 0 || scu_index >= SCI_MAX_CONTROLLERS || - scu_index > orom->hdr.num_elements || !oem_params) + scu_index > orom->hdr.num_elements || !oem) return -EINVAL; - oem_params->sds1 = orom->ctrl[scu_index]; + *oem = orom->ctrl[scu_index]; return 0; } diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index e40cb5f6eba5..dc007e692f4e 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -74,7 +74,7 @@ #define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED /* parameters that can be set by module parameters */ -struct scic_sds_user_parameters { +struct sci_user_parameters { struct sci_phy_user_params { /** * This field specifies the NOTIFY (ENABLE SPIN UP) primitive @@ -147,30 +147,16 @@ struct scic_sds_user_parameters { }; -/* XXX kill this union */ -union scic_user_parameters { - /** - * This field specifies the user parameters specific to the - * Storage Controller Unit (SCU) Driver Standard (SDS) version - * 1. - */ - struct scic_sds_user_parameters sds1; -}; - #define SCIC_SDS_PARM_PHY_MASK_MIN 0x0 #define SCIC_SDS_PARM_PHY_MASK_MAX 0xF #define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4 -struct scic_sds_oem_params; -int scic_oem_parameters_validate(struct scic_sds_oem_params *oem); - -union scic_oem_parameters; -void scic_oem_parameters_get(struct isci_host *ihost, - union scic_oem_parameters *oem); +struct sci_oem_params; +int sci_oem_parameters_validate(struct sci_oem_params *oem); struct isci_orom; struct isci_orom *isci_request_oprom(struct pci_dev *pdev); -enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem, +enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem, struct isci_orom *orom, int scu_index); struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); @@ -214,7 +200,7 @@ struct isci_oem_hdr { * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs * being assigned is sufficient to declare manual PORT configuration. */ -enum scic_port_configuration_mode { +enum sci_port_configuration_mode { SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0, SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1 }; @@ -230,7 +216,7 @@ struct sci_bios_oem_param_block_hdr { uint8_t reserved[8]; } __attribute__ ((packed)); -struct scic_sds_oem_params { +struct sci_oem_params { struct { uint8_t mode_type; uint8_t max_concurrent_dev_spin_up; @@ -255,19 +241,9 @@ struct scic_sds_oem_params { } phys[SCI_MAX_PHYS]; } __attribute__ ((packed)); -/* XXX kill this union */ -union scic_oem_parameters { - /** - * This field specifies the OEM parameters specific to the - * Storage Controller Unit (SCU) Driver Standard (SDS) version - * 1. - */ - struct scic_sds_oem_params sds1; -}; - struct isci_orom { struct sci_bios_oem_param_block_hdr hdr; - struct scic_sds_oem_params ctrl[SCI_MAX_CONTROLLERS]; + struct sci_oem_params ctrl[SCI_MAX_CONTROLLERS]; } __attribute__ ((packed)); #endif diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 9043b458c999..8c752abb4331 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -68,7 +68,7 @@ * @isci_host: This parameter specifies the isci host object. * @isci_device: This parameter specifies the remote device * - * scic_lock is held on entrance to this function. + * sci_lock is held on entrance to this function. */ static void isci_remote_device_not_ready(struct isci_host *ihost, struct isci_remote_device *idev, u32 reason) @@ -92,7 +92,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, "%s: isci_device = %p request = %p\n", __func__, idev, ireq); - scic_controller_terminate_request(ihost, + sci_controller_terminate_request(ihost, idev, ireq); } @@ -133,7 +133,7 @@ static void rnc_destruct_done(void *_dev) sci_change_state(&idev->sm, SCI_DEV_STOPPED); } -static enum sci_status scic_sds_remote_device_terminate_requests(struct isci_remote_device *idev) +static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_device *idev) { struct isci_host *ihost = idev->owning_port->owning_controller; enum sci_status status = SCI_SUCCESS; @@ -147,7 +147,7 @@ static enum sci_status scic_sds_remote_device_terminate_requests(struct isci_rem ireq->target_device != idev) continue; - s = scic_controller_terminate_request(ihost, idev, ireq); + s = sci_controller_terminate_request(ihost, idev, ireq); if (s != SCI_SUCCESS) status = s; } @@ -155,11 +155,11 @@ static enum sci_status scic_sds_remote_device_terminate_requests(struct isci_rem return status; } -enum sci_status scic_remote_device_stop(struct isci_remote_device *idev, +enum sci_status sci_remote_device_stop(struct isci_remote_device *idev, u32 timeout) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; switch (state) { case SCI_DEV_INITIAL: @@ -174,7 +174,7 @@ enum sci_status scic_remote_device_stop(struct isci_remote_device *idev, case SCI_DEV_STARTING: /* device not started so there had better be no requests */ BUG_ON(idev->started_request_count != 0); - scic_sds_remote_node_context_destruct(&idev->rnc, + sci_remote_node_context_destruct(&idev->rnc, rnc_destruct_done, idev); /* Transition to the stopping state and wait for the * remote node to complete being posted and invalidated. @@ -191,28 +191,28 @@ enum sci_status scic_remote_device_stop(struct isci_remote_device *idev, case SCI_SMP_DEV_CMD: sci_change_state(sm, SCI_DEV_STOPPING); if (idev->started_request_count == 0) { - scic_sds_remote_node_context_destruct(&idev->rnc, + sci_remote_node_context_destruct(&idev->rnc, rnc_destruct_done, idev); return SCI_SUCCESS; } else - return scic_sds_remote_device_terminate_requests(idev); + return sci_remote_device_terminate_requests(idev); break; case SCI_DEV_STOPPING: /* All requests should have been terminated, but if there is an * attempt to stop a device already in the stopping state, then * try again to terminate. */ - return scic_sds_remote_device_terminate_requests(idev); + return sci_remote_device_terminate_requests(idev); case SCI_DEV_RESETTING: sci_change_state(sm, SCI_DEV_STOPPING); return SCI_SUCCESS; } } -enum sci_status scic_remote_device_reset(struct isci_remote_device *idev) +enum sci_status sci_remote_device_reset(struct isci_remote_device *idev) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; switch (state) { case SCI_DEV_INITIAL: @@ -239,10 +239,10 @@ enum sci_status scic_remote_device_reset(struct isci_remote_device *idev) } } -enum sci_status scic_remote_device_reset_complete(struct isci_remote_device *idev) +enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; if (state != SCI_DEV_RESETTING) { dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", @@ -254,11 +254,11 @@ enum sci_status scic_remote_device_reset_complete(struct isci_remote_device *ide return SCI_SUCCESS; } -enum sci_status scic_sds_remote_device_suspend(struct isci_remote_device *idev, +enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev, u32 suspend_type) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; if (state != SCI_STP_DEV_CMD) { dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", @@ -266,15 +266,15 @@ enum sci_status scic_sds_remote_device_suspend(struct isci_remote_device *idev, return SCI_FAILURE_INVALID_STATE; } - return scic_sds_remote_node_context_suspend(&idev->rnc, + return sci_remote_node_context_suspend(&idev->rnc, suspend_type, NULL, NULL); } -enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device *idev, +enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev, u32 frame_index) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; struct isci_host *ihost = idev->owning_port->owning_controller; enum sci_status status; @@ -289,7 +289,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %d\n", __func__, state); /* Return the frame back to the controller */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return SCI_FAILURE_INVALID_STATE; case SCI_DEV_READY: case SCI_STP_DEV_NCQ_ERROR: @@ -302,7 +302,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * void *frame_header; ssize_t word_cnt; - status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + status = sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, &frame_header); if (status != SCI_SUCCESS) @@ -311,22 +311,22 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * word_cnt = sizeof(hdr) / sizeof(u32); sci_swab32_cpy(&hdr, frame_header, word_cnt); - ireq = scic_request_by_tag(ihost, be16_to_cpu(hdr.tag)); + ireq = sci_request_by_tag(ihost, be16_to_cpu(hdr.tag)); if (ireq && ireq->target_device == idev) { /* The IO request is now in charge of releasing the frame */ - status = scic_sds_io_request_frame_handler(ireq, frame_index); + status = sci_io_request_frame_handler(ireq, frame_index); } else { /* We could not map this tag to a valid IO * request Just toss the frame and continue */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); } break; } case SCI_STP_DEV_NCQ: { struct dev_to_host_fis *hdr; - status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + status = sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&hdr); if (status != SCI_SUCCESS) @@ -349,7 +349,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * } else status = SCI_FAILURE; - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); break; } case SCI_STP_DEV_CMD: @@ -358,7 +358,7 @@ enum sci_status scic_sds_remote_device_frame_handler(struct isci_remote_device * * in this state. All unsolicited frames are forwarded to the io request * object. */ - status = scic_sds_io_request_frame_handler(idev->working_request, frame_index); + status = sci_io_request_frame_handler(idev->working_request, frame_index); break; } @@ -369,7 +369,7 @@ static bool is_remote_device_ready(struct isci_remote_device *idev) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; switch (state) { case SCI_DEV_READY: @@ -386,25 +386,25 @@ static bool is_remote_device_ready(struct isci_remote_device *idev) } } -enum sci_status scic_sds_remote_device_event_handler(struct isci_remote_device *idev, +enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev, u32 event_code) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; enum sci_status status; switch (scu_get_event_type(event_code)) { case SCU_EVENT_TYPE_RNC_OPS_MISC: case SCU_EVENT_TYPE_RNC_SUSPEND_TX: case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: - status = scic_sds_remote_node_context_event_handler(&idev->rnc, event_code); + status = sci_remote_node_context_event_handler(&idev->rnc, event_code); break; case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { status = SCI_SUCCESS; /* Suspend the associated RNC */ - scic_sds_remote_node_context_suspend(&idev->rnc, + sci_remote_node_context_suspend(&idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); @@ -439,13 +439,13 @@ enum sci_status scic_sds_remote_device_event_handler(struct isci_remote_device * */ if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) - status = scic_sds_remote_node_context_resume(&idev->rnc, NULL, NULL); + status = sci_remote_node_context_resume(&idev->rnc, NULL, NULL); } return status; } -static void scic_sds_remote_device_start_request(struct isci_remote_device *idev, +static void sci_remote_device_start_request(struct isci_remote_device *idev, struct isci_request *ireq, enum sci_status status) { @@ -453,19 +453,19 @@ static void scic_sds_remote_device_start_request(struct isci_remote_device *idev /* cleanup requests that failed after starting on the port */ if (status != SCI_SUCCESS) - scic_sds_port_complete_io(iport, idev, ireq); + sci_port_complete_io(iport, idev, ireq); else { kref_get(&idev->kref); - scic_sds_remote_device_increment_request_count(idev); + sci_remote_device_increment_request_count(idev); } } -enum sci_status scic_sds_remote_device_start_io(struct isci_host *ihost, +enum sci_status sci_remote_device_start_io(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; struct isci_port *iport = idev->owning_port; enum sci_status status; @@ -488,15 +488,15 @@ enum sci_status scic_sds_remote_device_start_io(struct isci_host *ihost, * successful it will start the request for the port object then * increment its own request count. */ - status = scic_sds_port_start_io(iport, idev, ireq); + status = sci_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&idev->rnc, ireq); + status = sci_remote_node_context_start_io(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(ireq); + status = sci_request_start(ireq); break; case SCI_STP_DEV_IDLE: { /* handle the start io operation for a sata device that is in @@ -507,18 +507,18 @@ enum sci_status scic_sds_remote_device_start_io(struct isci_host *ihost, * If this is a softreset we may want to have a different * substate. */ - enum scic_sds_remote_device_states new_state; + enum sci_remote_device_states new_state; struct sas_task *task = isci_request_access_task(ireq); - status = scic_sds_port_start_io(iport, idev, ireq); + status = sci_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&idev->rnc, ireq); + status = sci_remote_node_context_start_io(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(ireq); + status = sci_request_start(ireq); if (status != SCI_SUCCESS) break; @@ -535,15 +535,15 @@ enum sci_status scic_sds_remote_device_start_io(struct isci_host *ihost, struct sas_task *task = isci_request_access_task(ireq); if (task->ata_task.use_ncq) { - status = scic_sds_port_start_io(iport, idev, ireq); + status = sci_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&idev->rnc, ireq); + status = sci_remote_node_context_start_io(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(ireq); + status = sci_request_start(ireq); } else return SCI_FAILURE_INVALID_STATE; break; @@ -551,15 +551,15 @@ enum sci_status scic_sds_remote_device_start_io(struct isci_host *ihost, case SCI_STP_DEV_AWAIT_RESET: return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; case SCI_SMP_DEV_IDLE: - status = scic_sds_port_start_io(iport, idev, ireq); + status = sci_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_io(&idev->rnc, ireq); + status = sci_remote_node_context_start_io(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(ireq); + status = sci_request_start(ireq); if (status != SCI_SUCCESS) break; @@ -574,7 +574,7 @@ enum sci_status scic_sds_remote_device_start_io(struct isci_host *ihost, return SCI_FAILURE_INVALID_STATE; } - scic_sds_remote_device_start_request(idev, ireq, status); + sci_remote_device_start_request(idev, ireq, status); return status; } @@ -584,24 +584,24 @@ static enum sci_status common_complete_io(struct isci_port *iport, { enum sci_status status; - status = scic_sds_request_complete(ireq); + status = sci_request_complete(ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_port_complete_io(iport, idev, ireq); + status = sci_port_complete_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - scic_sds_remote_device_decrement_request_count(idev); + sci_remote_device_decrement_request_count(idev); return status; } -enum sci_status scic_sds_remote_device_complete_io(struct isci_host *ihost, +enum sci_status sci_remote_device_complete_io(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; struct isci_port *iport = idev->owning_port; enum sci_status status; @@ -636,7 +636,7 @@ enum sci_status scic_sds_remote_device_complete_io(struct isci_host *ihost, * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ sci_change_state(sm, SCI_STP_DEV_AWAIT_RESET); - } else if (scic_sds_remote_device_get_request_count(idev) == 0) + } else if (sci_remote_device_get_request_count(idev) == 0) sci_change_state(sm, SCI_STP_DEV_IDLE); break; case SCI_SMP_DEV_CMD: @@ -650,8 +650,8 @@ enum sci_status scic_sds_remote_device_complete_io(struct isci_host *ihost, if (status != SCI_SUCCESS) break; - if (scic_sds_remote_device_get_request_count(idev) == 0) - scic_sds_remote_node_context_destruct(&idev->rnc, + if (sci_remote_device_get_request_count(idev) == 0) + sci_remote_node_context_destruct(&idev->rnc, rnc_destruct_done, idev); break; @@ -668,21 +668,21 @@ enum sci_status scic_sds_remote_device_complete_io(struct isci_host *ihost, return status; } -static void scic_sds_remote_device_continue_request(void *dev) +static void sci_remote_device_continue_request(void *dev) { struct isci_remote_device *idev = dev; /* we need to check if this request is still valid to continue. */ if (idev->working_request) - scic_controller_continue_io(idev->working_request); + sci_controller_continue_io(idev->working_request); } -enum sci_status scic_sds_remote_device_start_task(struct isci_host *ihost, +enum sci_status sci_remote_device_start_task(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; struct isci_port *iport = idev->owning_port; enum sci_status status; @@ -705,15 +705,15 @@ enum sci_status scic_sds_remote_device_start_task(struct isci_host *ihost, case SCI_STP_DEV_NCQ: case SCI_STP_DEV_NCQ_ERROR: case SCI_STP_DEV_AWAIT_RESET: - status = scic_sds_port_start_io(iport, idev, ireq); + status = sci_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_task(&idev->rnc, ireq); + status = sci_remote_node_context_start_task(&idev->rnc, ireq); if (status != SCI_SUCCESS) goto out; - status = scic_sds_request_start(ireq); + status = sci_request_start(ireq); if (status != SCI_SUCCESS) goto out; @@ -731,32 +731,32 @@ enum sci_status scic_sds_remote_device_start_task(struct isci_host *ihost, * the correct action when the remote node context is suspended * and later resumed. */ - scic_sds_remote_node_context_suspend(&idev->rnc, + sci_remote_node_context_suspend(&idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); - scic_sds_remote_node_context_resume(&idev->rnc, - scic_sds_remote_device_continue_request, + sci_remote_node_context_resume(&idev->rnc, + sci_remote_device_continue_request, idev); out: - scic_sds_remote_device_start_request(idev, ireq, status); + sci_remote_device_start_request(idev, ireq, status); /* We need to let the controller start request handler know that * it can't post TC yet. We will provide a callback function to * post TC when RNC gets resumed. */ return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; case SCI_DEV_READY: - status = scic_sds_port_start_io(iport, idev, ireq); + status = sci_port_start_io(iport, idev, ireq); if (status != SCI_SUCCESS) return status; - status = scic_sds_remote_node_context_start_task(&idev->rnc, ireq); + status = sci_remote_node_context_start_task(&idev->rnc, ireq); if (status != SCI_SUCCESS) break; - status = scic_sds_request_start(ireq); + status = sci_request_start(ireq); break; } - scic_sds_remote_device_start_request(idev, ireq, status); + sci_remote_device_start_request(idev, ireq, status); return status; } @@ -769,16 +769,16 @@ enum sci_status scic_sds_remote_device_start_task(struct isci_host *ihost, * This method takes the request and bulids an appropriate SCU context for the * request and then requests the controller to post the request. none */ -void scic_sds_remote_device_post_request( +void sci_remote_device_post_request( struct isci_remote_device *idev, u32 request) { u32 context; - context = scic_sds_remote_device_build_command_context(idev, request); + context = sci_remote_device_build_command_context(idev, request); - scic_sds_controller_post_request( - scic_sds_remote_device_get_controller(idev), + sci_controller_post_request( + sci_remote_device_get_controller(idev), context ); } @@ -798,7 +798,7 @@ static void remote_device_resume_done(void *_dev) sci_change_state(&idev->sm, SCI_DEV_READY); } -static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) +static void sci_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) { struct isci_remote_device *idev = _dev; struct isci_host *ihost = idev->owning_port->owning_controller; @@ -810,7 +810,7 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl isci_remote_device_ready(ihost, idev); } -static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_device_initial_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); @@ -819,7 +819,7 @@ static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_mac } /** - * scic_remote_device_destruct() - free remote node context and destruct + * sci_remote_device_destruct() - free remote node context and destruct * @remote_device: This parameter specifies the remote device to be destructed. * * Remote device objects are a limited resource. As such, they must be @@ -831,10 +831,10 @@ static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_mac * device isn't valid (e.g. it's already been destoryed, the handle isn't * valid, etc.). */ -static enum sci_status scic_remote_device_destruct(struct isci_remote_device *idev) +static enum sci_status sci_remote_device_destruct(struct isci_remote_device *idev) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; struct isci_host *ihost; if (state != SCI_DEV_STOPPED) { @@ -844,7 +844,7 @@ static enum sci_status scic_remote_device_destruct(struct isci_remote_device *id } ihost = idev->owning_port->owning_controller; - scic_sds_controller_free_remote_node_context(ihost, idev, + sci_controller_free_remote_node_context(ihost, idev, idev->rnc.remote_node_index); idev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; sci_change_state(sm, SCI_DEV_FINAL); @@ -869,12 +869,12 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ * io requests in process */ BUG_ON(!list_empty(&idev->reqs_in_process)); - scic_remote_device_destruct(idev); + sci_remote_device_destruct(idev); list_del_init(&idev->node); isci_put_device(idev); } -static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); struct isci_host *ihost = idev->owning_port->owning_controller; @@ -887,19 +887,19 @@ static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_mac if (prev_state == SCI_DEV_STOPPING) isci_remote_device_deconstruct(ihost, idev); - scic_sds_controller_remote_device_stopped(ihost, idev); + sci_controller_remote_device_stopped(ihost, idev); } -static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_device_starting_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = sci_remote_device_get_controller(idev); isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); } -static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_device_ready_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); struct isci_host *ihost = idev->owning_port->owning_controller; @@ -913,7 +913,7 @@ static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machi isci_remote_device_ready(ihost, idev); } -static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machine *sm) +static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); struct domain_device *dev = idev->domain_dev; @@ -926,42 +926,42 @@ static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machin } } -static void scic_sds_remote_device_resetting_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_device_resetting_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - scic_sds_remote_node_context_suspend( + sci_remote_node_context_suspend( &idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); } -static void scic_sds_remote_device_resetting_state_exit(struct sci_base_state_machine *sm) +static void sci_remote_device_resetting_state_exit(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - scic_sds_remote_node_context_resume(&idev->rnc, NULL, NULL); + sci_remote_node_context_resume(&idev->rnc, NULL, NULL); } -static void scic_sds_stp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) +static void sci_stp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); idev->working_request = NULL; - if (scic_sds_remote_node_context_is_ready(&idev->rnc)) { + if (sci_remote_node_context_is_ready(&idev->rnc)) { /* * Since the RNC is ready, it's alright to finish completion * processing (e.g. signal the remote device is ready). */ - scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(idev); + sci_stp_remote_device_ready_idle_substate_resume_complete_handler(idev); } else { - scic_sds_remote_node_context_resume(&idev->rnc, - scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, + sci_remote_node_context_resume(&idev->rnc, + sci_stp_remote_device_ready_idle_substate_resume_complete_handler, idev); } } -static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) +static void sci_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = sci_remote_device_get_controller(idev); BUG_ON(idev->working_request == NULL); @@ -969,28 +969,28 @@ static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_ SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); } -static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm) +static void sci_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = sci_remote_device_get_controller(idev); if (idev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) isci_remote_device_not_ready(ihost, idev, idev->not_ready_reason); } -static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) +static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = sci_remote_device_get_controller(idev); isci_remote_device_ready(ihost, idev); } -static void scic_sds_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) +static void sci_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = scic_sds_remote_device_get_controller(idev); + struct isci_host *ihost = sci_remote_device_get_controller(idev); BUG_ON(idev->working_request == NULL); @@ -998,83 +998,83 @@ static void scic_sds_smp_remote_device_ready_cmd_substate_enter(struct sci_base_ SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED); } -static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_state_machine *sm) +static void sci_smp_remote_device_ready_cmd_substate_exit(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); idev->working_request = NULL; } -static const struct sci_base_state scic_sds_remote_device_state_table[] = { +static const struct sci_base_state sci_remote_device_state_table[] = { [SCI_DEV_INITIAL] = { - .enter_state = scic_sds_remote_device_initial_state_enter, + .enter_state = sci_remote_device_initial_state_enter, }, [SCI_DEV_STOPPED] = { - .enter_state = scic_sds_remote_device_stopped_state_enter, + .enter_state = sci_remote_device_stopped_state_enter, }, [SCI_DEV_STARTING] = { - .enter_state = scic_sds_remote_device_starting_state_enter, + .enter_state = sci_remote_device_starting_state_enter, }, [SCI_DEV_READY] = { - .enter_state = scic_sds_remote_device_ready_state_enter, - .exit_state = scic_sds_remote_device_ready_state_exit + .enter_state = sci_remote_device_ready_state_enter, + .exit_state = sci_remote_device_ready_state_exit }, [SCI_STP_DEV_IDLE] = { - .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, + .enter_state = sci_stp_remote_device_ready_idle_substate_enter, }, [SCI_STP_DEV_CMD] = { - .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, + .enter_state = sci_stp_remote_device_ready_cmd_substate_enter, }, [SCI_STP_DEV_NCQ] = { }, [SCI_STP_DEV_NCQ_ERROR] = { - .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, + .enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter, }, [SCI_STP_DEV_AWAIT_RESET] = { }, [SCI_SMP_DEV_IDLE] = { - .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, + .enter_state = sci_smp_remote_device_ready_idle_substate_enter, }, [SCI_SMP_DEV_CMD] = { - .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, - .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, + .enter_state = sci_smp_remote_device_ready_cmd_substate_enter, + .exit_state = sci_smp_remote_device_ready_cmd_substate_exit, }, [SCI_DEV_STOPPING] = { }, [SCI_DEV_FAILED] = { }, [SCI_DEV_RESETTING] = { - .enter_state = scic_sds_remote_device_resetting_state_enter, - .exit_state = scic_sds_remote_device_resetting_state_exit + .enter_state = sci_remote_device_resetting_state_enter, + .exit_state = sci_remote_device_resetting_state_exit }, [SCI_DEV_FINAL] = { }, }; /** - * scic_remote_device_construct() - common construction + * sci_remote_device_construct() - common construction * @sci_port: SAS/SATA port through which this device is accessed. * @sci_dev: remote device to construct * * This routine just performs benign initialization and does not * allocate the remote_node_context which is left to - * scic_remote_device_[de]a_construct(). scic_remote_device_destruct() + * sci_remote_device_[de]a_construct(). sci_remote_device_destruct() * frees the remote_node_context(s) for the device. */ -static void scic_remote_device_construct(struct isci_port *iport, +static void sci_remote_device_construct(struct isci_port *iport, struct isci_remote_device *idev) { idev->owning_port = iport; idev->started_request_count = 0; - sci_init_sm(&idev->sm, scic_sds_remote_device_state_table, SCI_DEV_INITIAL); + sci_init_sm(&idev->sm, sci_remote_device_state_table, SCI_DEV_INITIAL); - scic_sds_remote_node_context_construct(&idev->rnc, + sci_remote_node_context_construct(&idev->rnc, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX); } /** - * scic_remote_device_da_construct() - construct direct attached device. + * sci_remote_device_da_construct() - construct direct attached device. * * The information (e.g. IAF, Signature FIS, etc.) necessary to build * the device is known to the SCI Core since it is contained in the - * scic_phy object. Remote node context(s) is/are a global resource - * allocated by this routine, freed by scic_remote_device_destruct(). + * sci_phy object. Remote node context(s) is/are a global resource + * allocated by this routine, freed by sci_remote_device_destruct(). * * Returns: * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed. @@ -1082,20 +1082,20 @@ static void scic_remote_device_construct(struct isci_port *iport, * sata-only controller instance. * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ -static enum sci_status scic_remote_device_da_construct(struct isci_port *iport, +static enum sci_status sci_remote_device_da_construct(struct isci_port *iport, struct isci_remote_device *idev) { enum sci_status status; struct domain_device *dev = idev->domain_dev; - scic_remote_device_construct(iport, idev); + sci_remote_device_construct(iport, idev); /* * This information is request to determine how many remote node context * entries will be needed to store the remote node. */ idev->is_direct_attached = true; - status = scic_sds_controller_allocate_remote_node_context(iport->owning_controller, + status = sci_controller_allocate_remote_node_context(iport->owning_controller, idev, &idev->rnc.remote_node_index); @@ -1108,7 +1108,7 @@ static enum sci_status scic_remote_device_da_construct(struct isci_port *iport, else return SCI_FAILURE_UNSUPPORTED_PROTOCOL; - idev->connection_rate = scic_sds_port_get_max_allowed_speed(iport); + idev->connection_rate = sci_port_get_max_allowed_speed(iport); /* / @todo Should I assign the port width by reading all of the phys on the port? */ idev->device_port_width = 1; @@ -1117,10 +1117,10 @@ static enum sci_status scic_remote_device_da_construct(struct isci_port *iport, } /** - * scic_remote_device_ea_construct() - construct expander attached device + * sci_remote_device_ea_construct() - construct expander attached device * * Remote node context(s) is/are a global resource allocated by this - * routine, freed by scic_remote_device_destruct(). + * routine, freed by sci_remote_device_destruct(). * * Returns: * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed. @@ -1128,15 +1128,15 @@ static enum sci_status scic_remote_device_da_construct(struct isci_port *iport, * sata-only controller instance. * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ -static enum sci_status scic_remote_device_ea_construct(struct isci_port *iport, +static enum sci_status sci_remote_device_ea_construct(struct isci_port *iport, struct isci_remote_device *idev) { struct domain_device *dev = idev->domain_dev; enum sci_status status; - scic_remote_device_construct(iport, idev); + sci_remote_device_construct(iport, idev); - status = scic_sds_controller_allocate_remote_node_context(iport->owning_controller, + status = sci_controller_allocate_remote_node_context(iport->owning_controller, idev, &idev->rnc.remote_node_index); if (status != SCI_SUCCESS) @@ -1155,7 +1155,7 @@ static enum sci_status scic_remote_device_ea_construct(struct isci_port *iport, * connection the logical link rate is that same as the * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay * one another, so this code works for both situations. */ - idev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(iport), + idev->connection_rate = min_t(u16, sci_port_get_max_allowed_speed(iport), dev->linkrate); /* / @todo Should I assign the port width by reading all of the phys on the port? */ @@ -1165,7 +1165,7 @@ static enum sci_status scic_remote_device_ea_construct(struct isci_port *iport, } /** - * scic_remote_device_start() - This method will start the supplied remote + * sci_remote_device_start() - This method will start the supplied remote * device. This method enables normal IO requests to flow through to the * remote device. * @remote_device: This parameter specifies the device to be started. @@ -1177,11 +1177,11 @@ static enum sci_status scic_remote_device_ea_construct(struct isci_port *iport, * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start * the device when there have been no phys added to it. */ -static enum sci_status scic_remote_device_start(struct isci_remote_device *idev, +static enum sci_status sci_remote_device_start(struct isci_remote_device *idev, u32 timeout) { struct sci_base_state_machine *sm = &idev->sm; - enum scic_sds_remote_device_states state = sm->current_state_id; + enum sci_remote_device_states state = sm->current_state_id; enum sci_status status; if (state != SCI_DEV_STOPPED) { @@ -1190,7 +1190,7 @@ static enum sci_status scic_remote_device_start(struct isci_remote_device *idev, return SCI_FAILURE_INVALID_STATE; } - status = scic_sds_remote_node_context_resume(&idev->rnc, + status = sci_remote_node_context_resume(&idev->rnc, remote_device_resume_done, idev); if (status != SCI_SUCCESS) @@ -1209,9 +1209,9 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport, enum sci_status status; if (dev->parent && dev_is_expander(dev->parent)) - status = scic_remote_device_ea_construct(iport, idev); + status = sci_remote_device_ea_construct(iport, idev); else - status = scic_remote_device_da_construct(iport, idev); + status = sci_remote_device_da_construct(iport, idev); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: construct failed: %d\n", @@ -1221,7 +1221,7 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport, } /* start the device. */ - status = scic_remote_device_start(idev, ISCI_REMOTE_DEVICE_START_TIMEOUT); + status = sci_remote_device_start(idev, ISCI_REMOTE_DEVICE_START_TIMEOUT); if (status != SCI_SUCCESS) dev_warn(&ihost->pdev->dev, "remote device start failed: %d\n", @@ -1322,7 +1322,7 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem set_bit(IDEV_STOP_PENDING, &idev->flags); spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_stop(idev, 50); + status = sci_remote_device_stop(idev, 50); spin_unlock_irqrestore(&ihost->scic_lock, flags); /* Wait for the stop complete callback. */ diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index bc4da20a13fa..fa9a0e6cc309 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -61,7 +61,7 @@ #include "remote_node_context.h" #include "port.h" -enum scic_remote_device_not_ready_reason_code { +enum sci_remote_device_not_ready_reason_code { SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED, SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED, SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED, @@ -97,7 +97,7 @@ struct isci_remote_device { enum sas_linkrate connection_rate; bool is_direct_attached; struct isci_port *owning_port; - struct scic_sds_remote_node_context rnc; + struct sci_remote_node_context rnc; /* XXX unify with device reference counting and delete */ u32 started_request_count; struct isci_request *working_request; @@ -106,7 +106,7 @@ struct isci_remote_device { #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 -/* device reference routines must be called under scic_lock */ +/* device reference routines must be called under sci_lock */ static inline struct isci_remote_device *isci_lookup_device(struct domain_device *dev) { struct isci_remote_device *idev = dev->lldd_dev; @@ -137,7 +137,7 @@ bool isci_device_is_reset_pending(struct isci_host *ihost, void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev); /** - * scic_remote_device_stop() - This method will stop both transmission and + * sci_remote_device_stop() - This method will stop both transmission and * reception of link activity for the supplied remote device. This method * disables normal IO requests from flowing through to the remote device. * @remote_device: This parameter specifies the device to be stopped. @@ -148,12 +148,12 @@ void isci_device_clear_reset_pending(struct isci_host *ihost, * This value is returned if the transmission and reception for the device was * successfully stopped. */ -enum sci_status scic_remote_device_stop( +enum sci_status sci_remote_device_stop( struct isci_remote_device *idev, u32 timeout); /** - * scic_remote_device_reset() - This method will reset the device making it + * sci_remote_device_reset() - This method will reset the device making it * ready for operation. This method must be called anytime the device is * reset either through a SMP phy control or a port hard reset request. * @remote_device: This parameter specifies the device to be reset. @@ -164,11 +164,11 @@ enum sci_status scic_remote_device_stop( * was accepted. SCI_SUCCESS This value is returned if the device reset is * started. */ -enum sci_status scic_remote_device_reset( +enum sci_status sci_remote_device_reset( struct isci_remote_device *idev); /** - * scic_remote_device_reset_complete() - This method informs the device object + * sci_remote_device_reset_complete() - This method informs the device object * that the reset operation is complete and the device can resume operation * again. * @remote_device: This parameter specifies the device which is to be informed @@ -177,18 +177,16 @@ enum sci_status scic_remote_device_reset( * An indication that the device is resuming operation. SCI_SUCCESS the device * is resuming operation. */ -enum sci_status scic_remote_device_reset_complete( +enum sci_status sci_remote_device_reset_complete( struct isci_remote_device *idev); -#define scic_remote_device_is_atapi(device_handle) false - /** - * enum scic_sds_remote_device_states - This enumeration depicts all the states + * enum sci_remote_device_states - This enumeration depicts all the states * for the common remote device state machine. * * */ -enum scic_sds_remote_device_states { +enum sci_remote_device_states { /** * Simply the initial state for the base remote device state machine. */ @@ -293,7 +291,7 @@ enum scic_sds_remote_device_states { SCI_DEV_FINAL, }; -static inline struct isci_remote_device *rnc_to_dev(struct scic_sds_remote_node_context *rnc) +static inline struct isci_remote_device *rnc_to_dev(struct sci_remote_node_context *rnc) { struct isci_remote_device *idev; @@ -308,122 +306,120 @@ static inline bool dev_is_expander(struct domain_device *dev) } /** - * scic_sds_remote_device_increment_request_count() - + * sci_remote_device_increment_request_count() - * * This macro incrments the request count for this device */ -#define scic_sds_remote_device_increment_request_count(idev) \ +#define sci_remote_device_increment_request_count(idev) \ ((idev)->started_request_count++) /** - * scic_sds_remote_device_decrement_request_count() - + * sci_remote_device_decrement_request_count() - * * This macro decrements the request count for this device. This count will * never decrment past 0. */ -#define scic_sds_remote_device_decrement_request_count(idev) \ +#define sci_remote_device_decrement_request_count(idev) \ ((idev)->started_request_count > 0 ? \ (idev)->started_request_count-- : 0) /** - * scic_sds_remote_device_get_request_count() - + * sci_remote_device_get_request_count() - * * This is a helper macro to return the current device request count. */ -#define scic_sds_remote_device_get_request_count(idev) \ +#define sci_remote_device_get_request_count(idev) \ ((idev)->started_request_count) /** - * scic_sds_remote_device_get_controller() - + * sci_remote_device_get_controller() - * * This macro returns the controller object that contains this device object */ -#define scic_sds_remote_device_get_controller(idev) \ - scic_sds_port_get_controller(scic_sds_remote_device_get_port(idev)) +#define sci_remote_device_get_controller(idev) \ + sci_port_get_controller(sci_remote_device_get_port(idev)) /** - * scic_sds_remote_device_get_port() - + * sci_remote_device_get_port() - * * This macro returns the owning port of this device */ -#define scic_sds_remote_device_get_port(idev) \ +#define sci_remote_device_get_port(idev) \ ((idev)->owning_port) /** - * scic_sds_remote_device_get_controller_peg() - + * sci_remote_device_get_controller_peg() - * * This macro returns the controllers protocol engine group */ -#define scic_sds_remote_device_get_controller_peg(idev) \ +#define sci_remote_device_get_controller_peg(idev) \ (\ - scic_sds_controller_get_protocol_engine_group(\ - scic_sds_port_get_controller(\ - scic_sds_remote_device_get_port(idev) \ + sci_controller_get_protocol_engine_group(\ + sci_port_get_controller(\ + sci_remote_device_get_port(idev) \ ) \ ) \ ) /** - * scic_sds_remote_device_get_index() - + * sci_remote_device_get_index() - * * This macro returns the remote node index for this device object */ -#define scic_sds_remote_device_get_index(idev) \ +#define sci_remote_device_get_index(idev) \ ((idev)->rnc.remote_node_index) /** - * scic_sds_remote_device_build_command_context() - + * sci_remote_device_build_command_context() - * * This macro builds a remote device context for the SCU post request operation */ -#define scic_sds_remote_device_build_command_context(device, command) \ +#define sci_remote_device_build_command_context(device, command) \ ((command) \ - | (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \ + | (sci_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \ | ((device)->owning_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \ - | (scic_sds_remote_device_get_index((device))) \ + | (sci_remote_device_get_index((device))) \ ) /** - * scic_sds_remote_device_set_working_request() - + * sci_remote_device_set_working_request() - * * This macro makes the working request assingment for the remote device * object. To clear the working request use this macro with a NULL request * object. */ -#define scic_sds_remote_device_set_working_request(device, request) \ +#define sci_remote_device_set_working_request(device, request) \ ((device)->working_request = (request)) -enum sci_status scic_sds_remote_device_frame_handler( +enum sci_status sci_remote_device_frame_handler( struct isci_remote_device *idev, u32 frame_index); -enum sci_status scic_sds_remote_device_event_handler( +enum sci_status sci_remote_device_event_handler( struct isci_remote_device *idev, u32 event_code); -enum sci_status scic_sds_remote_device_start_io( +enum sci_status sci_remote_device_start_io( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); -enum sci_status scic_sds_remote_device_start_task( +enum sci_status sci_remote_device_start_task( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); -enum sci_status scic_sds_remote_device_complete_io( +enum sci_status sci_remote_device_complete_io( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq); -enum sci_status scic_sds_remote_device_suspend( +enum sci_status sci_remote_device_suspend( struct isci_remote_device *idev, u32 suspend_type); -void scic_sds_remote_device_post_request( +void sci_remote_device_post_request( struct isci_remote_device *idev, u32 request); -#define scic_sds_remote_device_is_atapi(idev) false - #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 8a5203b6eb09..c2dfd5a72181 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -81,8 +81,8 @@ * otherwise it will return false bool true if the remote node context is in * the ready state. false if the remote node context is not in the ready state. */ -bool scic_sds_remote_node_context_is_ready( - struct scic_sds_remote_node_context *sci_rnc) +bool sci_remote_node_context_is_ready( + struct sci_remote_node_context *sci_rnc) { u32 current_state = sci_rnc->sm.current_state_id; @@ -93,15 +93,16 @@ bool scic_sds_remote_node_context_is_ready( return false; } -/** - * - * @sci_dev: The remote device to use to construct the RNC buffer. - * @rnc: The buffer into which the remote device data will be copied. - * - * This method will construct the RNC buffer for this remote device object. none - */ -static void scic_sds_remote_node_context_construct_buffer( - struct scic_sds_remote_node_context *sci_rnc) +static union scu_remote_node_context *sci_rnc_by_id(struct isci_host *ihost, u16 id) +{ + if (id < ihost->remote_node_entries && + ihost->device_table[id]) + return &ihost->remote_node_context_table[id]; + + return NULL; +} + +static void sci_remote_node_context_construct_buffer(struct sci_remote_node_context *sci_rnc) { struct isci_remote_device *idev = rnc_to_dev(sci_rnc); struct domain_device *dev = idev->domain_dev; @@ -110,11 +111,11 @@ static void scic_sds_remote_node_context_construct_buffer( struct isci_host *ihost; __le64 sas_addr; - ihost = scic_sds_remote_device_get_controller(idev); - rnc = scic_sds_controller_get_remote_node_context_buffer(ihost, rni); + ihost = sci_remote_device_get_controller(idev); + rnc = sci_rnc_by_id(ihost, rni); memset(rnc, 0, sizeof(union scu_remote_node_context) - * scic_sds_remote_device_node_count(idev)); + * sci_remote_device_node_count(idev)); rnc->ssp.remote_node_index = rni; rnc->ssp.remote_node_port_width = idev->device_port_width; @@ -135,14 +136,14 @@ static void scic_sds_remote_node_context_construct_buffer( if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { rnc->ssp.connection_occupancy_timeout = - ihost->user_parameters.sds1.stp_max_occupancy_timeout; + ihost->user_parameters.stp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = - ihost->user_parameters.sds1.stp_inactivity_timeout; + ihost->user_parameters.stp_inactivity_timeout; } else { rnc->ssp.connection_occupancy_timeout = - ihost->user_parameters.sds1.ssp_max_occupancy_timeout; + ihost->user_parameters.ssp_max_occupancy_timeout; rnc->ssp.connection_inactivity_timeout = - ihost->user_parameters.sds1.ssp_inactivity_timeout; + ihost->user_parameters.ssp_inactivity_timeout; } rnc->ssp.initial_arbitration_wait_time = 0; @@ -164,8 +165,8 @@ static void scic_sds_remote_node_context_construct_buffer( * to its ready state. If the remote node context is already setup to * transition to its final state then this function does nothing. none */ -static void scic_sds_remote_node_context_setup_to_resume( - struct scic_sds_remote_node_context *sci_rnc, +static void sci_remote_node_context_setup_to_resume( + struct sci_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, void *callback_parameter) { @@ -176,8 +177,8 @@ static void scic_sds_remote_node_context_setup_to_resume( } } -static void scic_sds_remote_node_context_setup_to_destory( - struct scic_sds_remote_node_context *sci_rnc, +static void sci_remote_node_context_setup_to_destory( + struct sci_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, void *callback_parameter) { @@ -192,8 +193,8 @@ static void scic_sds_remote_node_context_setup_to_destory( * This method just calls the user callback function and then resets the * callback. */ -static void scic_sds_remote_node_context_notify_user( - struct scic_sds_remote_node_context *rnc) +static void sci_remote_node_context_notify_user( + struct sci_remote_node_context *rnc) { if (rnc->user_callback != NULL) { (*rnc->user_callback)(rnc->user_cookie); @@ -203,99 +204,80 @@ static void scic_sds_remote_node_context_notify_user( } } -static void scic_sds_remote_node_context_continue_state_transitions(struct scic_sds_remote_node_context *rnc) +static void sci_remote_node_context_continue_state_transitions(struct sci_remote_node_context *rnc) { if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) - scic_sds_remote_node_context_resume(rnc, rnc->user_callback, + sci_remote_node_context_resume(rnc, rnc->user_callback, rnc->user_cookie); } -/** - * - * @sci_rnc: The remote node context object that is to be validated. - * - * This method will mark the rnc buffer as being valid and post the request to - * the hardware. none - */ -static void scic_sds_remote_node_context_validate_context_buffer( - struct scic_sds_remote_node_context *sci_rnc) +static void sci_remote_node_context_validate_context_buffer(struct sci_remote_node_context *sci_rnc) { + union scu_remote_node_context *rnc_buffer; struct isci_remote_device *idev = rnc_to_dev(sci_rnc); struct domain_device *dev = idev->domain_dev; - union scu_remote_node_context *rnc_buffer; + struct isci_host *ihost = idev->owning_port->owning_controller; - rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(idev), - sci_rnc->remote_node_index - ); + rnc_buffer = sci_rnc_by_id(ihost, sci_rnc->remote_node_index); rnc_buffer->ssp.is_valid = true; if (!idev->is_direct_attached && (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))) { - scic_sds_remote_device_post_request(idev, - SCU_CONTEXT_COMMAND_POST_RNC_96); + sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_96); } else { - scic_sds_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_32); + sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_32); - if (idev->is_direct_attached) { - scic_sds_port_setup_transports(idev->owning_port, - sci_rnc->remote_node_index); - } + if (idev->is_direct_attached) + sci_port_setup_transports(idev->owning_port, + sci_rnc->remote_node_index); } } -/** - * - * @sci_rnc: The remote node context object that is to be invalidated. - * - * This method will update the RNC buffer and post the invalidate request. none - */ -static void scic_sds_remote_node_context_invalidate_context_buffer( - struct scic_sds_remote_node_context *sci_rnc) +static void sci_remote_node_context_invalidate_context_buffer(struct sci_remote_node_context *sci_rnc) { union scu_remote_node_context *rnc_buffer; + struct isci_remote_device *idev = rnc_to_dev(sci_rnc); + struct isci_host *ihost = idev->owning_port->owning_controller; - rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( - scic_sds_remote_device_get_controller(rnc_to_dev(sci_rnc)), - sci_rnc->remote_node_index); + rnc_buffer = sci_rnc_by_id(ihost, sci_rnc->remote_node_index); rnc_buffer->ssp.is_valid = false; - scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), - SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE); + sci_remote_device_post_request(rnc_to_dev(sci_rnc), + SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE); } -static void scic_sds_remote_node_context_initial_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_node_context_initial_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); + struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); /* Check to see if we have gotten back to the initial state because * someone requested to destroy the remote node context object. */ if (sm->previous_state_id == SCI_RNC_INVALIDATING) { rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - scic_sds_remote_node_context_notify_user(rnc); + sci_remote_node_context_notify_user(rnc); } } -static void scic_sds_remote_node_context_posting_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_node_context_posting_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *sci_rnc = container_of(sm, typeof(*sci_rnc), sm); + struct sci_remote_node_context *sci_rnc = container_of(sm, typeof(*sci_rnc), sm); - scic_sds_remote_node_context_validate_context_buffer(sci_rnc); + sci_remote_node_context_validate_context_buffer(sci_rnc); } -static void scic_sds_remote_node_context_invalidating_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_node_context_invalidating_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); + struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); - scic_sds_remote_node_context_invalidate_context_buffer(rnc); + sci_remote_node_context_invalidate_context_buffer(rnc); } -static void scic_sds_remote_node_context_resuming_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_node_context_resuming_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); + struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); struct isci_remote_device *idev; struct domain_device *dev; @@ -310,73 +292,73 @@ static void scic_sds_remote_node_context_resuming_state_enter(struct sci_base_st */ if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) && idev->is_direct_attached) - scic_sds_port_setup_transports(idev->owning_port, + sci_port_setup_transports(idev->owning_port, rnc->remote_node_index); - scic_sds_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); + sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); } -static void scic_sds_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); + struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; if (rnc->user_callback) - scic_sds_remote_node_context_notify_user(rnc); + sci_remote_node_context_notify_user(rnc); } -static void scic_sds_remote_node_context_tx_suspended_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); + struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); - scic_sds_remote_node_context_continue_state_transitions(rnc); + sci_remote_node_context_continue_state_transitions(rnc); } -static void scic_sds_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm) +static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm) { - struct scic_sds_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); + struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); - scic_sds_remote_node_context_continue_state_transitions(rnc); + sci_remote_node_context_continue_state_transitions(rnc); } -static const struct sci_base_state scic_sds_remote_node_context_state_table[] = { +static const struct sci_base_state sci_remote_node_context_state_table[] = { [SCI_RNC_INITIAL] = { - .enter_state = scic_sds_remote_node_context_initial_state_enter, + .enter_state = sci_remote_node_context_initial_state_enter, }, [SCI_RNC_POSTING] = { - .enter_state = scic_sds_remote_node_context_posting_state_enter, + .enter_state = sci_remote_node_context_posting_state_enter, }, [SCI_RNC_INVALIDATING] = { - .enter_state = scic_sds_remote_node_context_invalidating_state_enter, + .enter_state = sci_remote_node_context_invalidating_state_enter, }, [SCI_RNC_RESUMING] = { - .enter_state = scic_sds_remote_node_context_resuming_state_enter, + .enter_state = sci_remote_node_context_resuming_state_enter, }, [SCI_RNC_READY] = { - .enter_state = scic_sds_remote_node_context_ready_state_enter, + .enter_state = sci_remote_node_context_ready_state_enter, }, [SCI_RNC_TX_SUSPENDED] = { - .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter, + .enter_state = sci_remote_node_context_tx_suspended_state_enter, }, [SCI_RNC_TX_RX_SUSPENDED] = { - .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter, + .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter, }, [SCI_RNC_AWAIT_SUSPENSION] = { }, }; -void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, +void sci_remote_node_context_construct(struct sci_remote_node_context *rnc, u16 remote_node_index) { - memset(rnc, 0, sizeof(struct scic_sds_remote_node_context)); + memset(rnc, 0, sizeof(struct sci_remote_node_context)); rnc->remote_node_index = remote_node_index; rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; - sci_init_sm(&rnc->sm, scic_sds_remote_node_context_state_table, SCI_RNC_INITIAL); + sci_init_sm(&rnc->sm, sci_remote_node_context_state_table, SCI_RNC_INITIAL); } -enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_context *sci_rnc, u32 event_code) { enum scis_sds_remote_node_context_states state; @@ -476,7 +458,7 @@ enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remot } -enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback cb_fn, void *cb_p) { @@ -485,7 +467,7 @@ enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_nod state = sci_rnc->sm.current_state_id; switch (state) { case SCI_RNC_INVALIDATING: - scic_sds_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); + sci_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); return SCI_SUCCESS; case SCI_RNC_POSTING: case SCI_RNC_RESUMING: @@ -493,7 +475,7 @@ enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_nod case SCI_RNC_TX_SUSPENDED: case SCI_RNC_TX_RX_SUSPENDED: case SCI_RNC_AWAIT_SUSPENSION: - scic_sds_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); + sci_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING); return SCI_SUCCESS; case SCI_RNC_INITIAL: @@ -511,7 +493,7 @@ enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_nod } } -enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc, u32 suspend_type, scics_sds_remote_node_context_callback cb_fn, void *cb_p) @@ -530,7 +512,7 @@ enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node sci_rnc->suspension_code = suspend_type; if (suspend_type == SCI_SOFTWARE_SUSPENSION) { - scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc), + sci_remote_device_post_request(rnc_to_dev(sci_rnc), SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); } @@ -538,7 +520,7 @@ enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node return SCI_SUCCESS; } -enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback cb_fn, void *cb_p) { @@ -550,8 +532,8 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ if (sci_rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_STATE; - scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); - scic_sds_remote_node_context_construct_buffer(sci_rnc); + sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); + sci_remote_node_context_construct_buffer(sci_rnc); sci_change_state(&sci_rnc->sm, SCI_RNC_POSTING); return SCI_SUCCESS; case SCI_RNC_POSTING: @@ -567,7 +549,7 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ struct isci_remote_device *idev = rnc_to_dev(sci_rnc); struct domain_device *dev = idev->domain_dev; - scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); + sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev)) @@ -584,11 +566,11 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ return SCI_SUCCESS; } case SCI_RNC_TX_RX_SUSPENDED: - scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); + sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); return SCI_FAILURE_INVALID_STATE; case SCI_RNC_AWAIT_SUSPENSION: - scic_sds_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); + sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); return SCI_SUCCESS; default: dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), @@ -597,7 +579,7 @@ enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_ } } -enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc, struct isci_request *ireq) { enum scis_sds_remote_node_context_states state; @@ -622,7 +604,7 @@ enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_nod return SCI_FAILURE_INVALID_STATE; } -enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_context *sci_rnc, struct isci_request *ireq) { enum scis_sds_remote_node_context_states state; @@ -635,7 +617,7 @@ enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_n return SCI_SUCCESS; case SCI_RNC_TX_SUSPENDED: case SCI_RNC_TX_RX_SUSPENDED: - scic_sds_remote_node_context_resume(sci_rnc, NULL, NULL); + sci_remote_node_context_resume(sci_rnc, NULL, NULL); return SCI_SUCCESS; default: dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index 7a24c7a12de1..b475c5c26642 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -80,7 +80,7 @@ struct isci_request; struct isci_remote_device; -struct scic_sds_remote_node_context; +struct sci_remote_node_context; typedef void (*scics_sds_remote_node_context_callback)(void *); @@ -147,19 +147,19 @@ enum scis_sds_remote_node_context_states { * This enumeration is used to define the end destination state for the remote * node context. */ -enum scic_sds_remote_node_context_destination_state { +enum sci_remote_node_context_destination_state { SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED, SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY, SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL }; /** - * struct scic_sds_remote_node_context - This structure contains the data + * struct sci_remote_node_context - This structure contains the data * associated with the remote node context object. The remote node context * (RNC) object models the the remote device information necessary to manage * the silicon RNC. */ -struct scic_sds_remote_node_context { +struct sci_remote_node_context { /** * This field indicates the remote node index (RNI) associated with * this RNC. @@ -177,7 +177,7 @@ struct scic_sds_remote_node_context { * state. This can cause an automatic resume on receiving a suspension * notification. */ - enum scic_sds_remote_node_context_destination_state destination_state; + enum sci_remote_node_context_destination_state destination_state; /** * This field contains the callback function that the user requested to be @@ -197,31 +197,31 @@ struct scic_sds_remote_node_context { struct sci_base_state_machine sm; }; -void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc, +void sci_remote_node_context_construct(struct sci_remote_node_context *rnc, u16 remote_node_index); -bool scic_sds_remote_node_context_is_ready( - struct scic_sds_remote_node_context *sci_rnc); +bool sci_remote_node_context_is_ready( + struct sci_remote_node_context *sci_rnc); -#define scic_sds_remote_node_context_get_remote_node_index(rcn) \ +#define sci_remote_node_context_get_remote_node_index(rcn) \ ((rnc)->remote_node_index) -enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_context *sci_rnc, u32 event_code); -enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback callback, void *callback_parameter); -enum sci_status scic_sds_remote_node_context_suspend(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc, u32 suspend_type, scics_sds_remote_node_context_callback cb_fn, void *cb_p); -enum sci_status scic_sds_remote_node_context_resume(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc, scics_sds_remote_node_context_callback cb_fn, void *cb_p); -enum sci_status scic_sds_remote_node_context_start_task(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_context *sci_rnc, struct isci_request *ireq); -enum sci_status scic_sds_remote_node_context_start_io(struct scic_sds_remote_node_context *sci_rnc, +enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc, struct isci_request *ireq); #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ diff --git a/drivers/scsi/isci/remote_node_table.c b/drivers/scsi/isci/remote_node_table.c index 6b9465a5a217..301b3141945e 100644 --- a/drivers/scsi/isci/remote_node_table.c +++ b/drivers/scsi/isci/remote_node_table.c @@ -74,8 +74,8 @@ * just bit position. u32 This is the absolute bit position for an available * group. */ -static u32 scic_sds_remote_node_table_get_group_index( - struct scic_remote_node_table *remote_node_table, +static u32 sci_remote_node_table_get_group_index( + struct sci_remote_node_table *remote_node_table, u32 group_table_index) { u32 dword_index; @@ -108,8 +108,8 @@ static u32 scic_sds_remote_node_table_get_group_index( * This method will clear the group index entry in the specified group index * table. none */ -static void scic_sds_remote_node_table_clear_group_index( - struct scic_remote_node_table *remote_node_table, +static void sci_remote_node_table_clear_group_index( + struct sci_remote_node_table *remote_node_table, u32 group_table_index, u32 group_index) { @@ -138,8 +138,8 @@ static void scic_sds_remote_node_table_clear_group_index( * This method will set the group index bit entry in the specified gropu index * table. none */ -static void scic_sds_remote_node_table_set_group_index( - struct scic_remote_node_table *remote_node_table, +static void sci_remote_node_table_set_group_index( + struct sci_remote_node_table *remote_node_table, u32 group_table_index, u32 group_index) { @@ -167,8 +167,8 @@ static void scic_sds_remote_node_table_set_group_index( * This method will set the remote to available in the remote node allocation * table. none */ -static void scic_sds_remote_node_table_set_node_index( - struct scic_remote_node_table *remote_node_table, +static void sci_remote_node_table_set_node_index( + struct sci_remote_node_table *remote_node_table, u32 remote_node_index) { u32 dword_location; @@ -200,8 +200,8 @@ static void scic_sds_remote_node_table_set_node_index( * This method clears the remote node index from the table of available remote * nodes. none */ -static void scic_sds_remote_node_table_clear_node_index( - struct scic_remote_node_table *remote_node_table, +static void sci_remote_node_table_clear_node_index( + struct sci_remote_node_table *remote_node_table, u32 remote_node_index) { u32 dword_location; @@ -231,8 +231,8 @@ static void scic_sds_remote_node_table_clear_node_index( * * This method clears the entire table slot at the specified slot index. none */ -static void scic_sds_remote_node_table_clear_group( - struct scic_remote_node_table *remote_node_table, +static void sci_remote_node_table_clear_group( + struct sci_remote_node_table *remote_node_table, u32 group_index) { u32 dword_location; @@ -258,8 +258,8 @@ static void scic_sds_remote_node_table_clear_group( * * THis method sets an entire remote node group in the remote node table. */ -static void scic_sds_remote_node_table_set_group( - struct scic_remote_node_table *remote_node_table, +static void sci_remote_node_table_set_group( + struct sci_remote_node_table *remote_node_table, u32 group_index) { u32 dword_location; @@ -288,8 +288,8 @@ static void scic_sds_remote_node_table_set_group( * This method will return the group value for the specified group index. The * bit values at the specified remote node group index. */ -static u8 scic_sds_remote_node_table_get_group_value( - struct scic_remote_node_table *remote_node_table, +static u8 sci_remote_node_table_get_group_value( + struct sci_remote_node_table *remote_node_table, u32 group_index) { u32 dword_location; @@ -313,8 +313,8 @@ static u8 scic_sds_remote_node_table_get_group_value( * * This method will initialize the remote node table for use. none */ -void scic_sds_remote_node_table_initialize( - struct scic_remote_node_table *remote_node_table, +void sci_remote_node_table_initialize( + struct sci_remote_node_table *remote_node_table, u32 remote_node_entries) { u32 index; @@ -342,7 +342,7 @@ void scic_sds_remote_node_table_initialize( /* Initialize each full DWORD to a FULL SET of remote nodes */ for (index = 0; index < remote_node_entries; index++) { - scic_sds_remote_node_table_set_node_index(remote_node_table, index); + sci_remote_node_table_set_node_index(remote_node_table, index); } remote_node_table->group_array_size = (u16) @@ -353,14 +353,14 @@ void scic_sds_remote_node_table_initialize( /* * These are all guaranteed to be full slot values so fill them in the * available sets of 3 remote nodes */ - scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index); + sci_remote_node_table_set_group_index(remote_node_table, 2, index); } /* Now fill in any remainders that we may find */ if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) { - scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index); + sci_remote_node_table_set_group_index(remote_node_table, 1, index); } else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) { - scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index); + sci_remote_node_table_set_group_index(remote_node_table, 0, index); } } @@ -379,8 +379,8 @@ void scic_sds_remote_node_table_initialize( * updated. The RNi value or an invalid remote node context if an RNi can not * be found. */ -static u16 scic_sds_remote_node_table_allocate_single_remote_node( - struct scic_remote_node_table *remote_node_table, +static u16 sci_remote_node_table_allocate_single_remote_node( + struct sci_remote_node_table *remote_node_table, u32 group_table_index) { u8 index; @@ -388,12 +388,12 @@ static u16 scic_sds_remote_node_table_allocate_single_remote_node( u32 group_index; u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - group_index = scic_sds_remote_node_table_get_group_index( + group_index = sci_remote_node_table_get_group_index( remote_node_table, group_table_index); /* We could not find an available slot in the table selector 0 */ if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { - group_value = scic_sds_remote_node_table_get_group_value( + group_value = sci_remote_node_table_get_group_value( remote_node_table, group_index); for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) { @@ -402,16 +402,16 @@ static u16 scic_sds_remote_node_table_allocate_single_remote_node( remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT + index); - scic_sds_remote_node_table_clear_group_index( + sci_remote_node_table_clear_group_index( remote_node_table, group_table_index, group_index ); - scic_sds_remote_node_table_clear_node_index( + sci_remote_node_table_clear_node_index( remote_node_table, remote_node_index ); if (group_table_index > 0) { - scic_sds_remote_node_table_set_group_index( + sci_remote_node_table_set_group_index( remote_node_table, group_table_index - 1, group_index ); } @@ -436,24 +436,24 @@ static u16 scic_sds_remote_node_table_allocate_single_remote_node( * The remote node index that represents three consecutive remote node entries * or an invalid remote node context if none can be found. */ -static u16 scic_sds_remote_node_table_allocate_triple_remote_node( - struct scic_remote_node_table *remote_node_table, +static u16 sci_remote_node_table_allocate_triple_remote_node( + struct sci_remote_node_table *remote_node_table, u32 group_table_index) { u32 group_index; u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; - group_index = scic_sds_remote_node_table_get_group_index( + group_index = sci_remote_node_table_get_group_index( remote_node_table, group_table_index); if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT; - scic_sds_remote_node_table_clear_group_index( + sci_remote_node_table_clear_group_index( remote_node_table, group_table_index, group_index ); - scic_sds_remote_node_table_clear_group( + sci_remote_node_table_clear_group( remote_node_table, group_index ); } @@ -473,31 +473,31 @@ static u16 scic_sds_remote_node_table_allocate_triple_remote_node( * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). u16 This is * the remote node index that is returned or an invalid remote node context. */ -u16 scic_sds_remote_node_table_allocate_remote_node( - struct scic_remote_node_table *remote_node_table, +u16 sci_remote_node_table_allocate_remote_node( + struct sci_remote_node_table *remote_node_table, u32 remote_node_count) { u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { remote_node_index = - scic_sds_remote_node_table_allocate_single_remote_node( + sci_remote_node_table_allocate_single_remote_node( remote_node_table, 0); if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { remote_node_index = - scic_sds_remote_node_table_allocate_single_remote_node( + sci_remote_node_table_allocate_single_remote_node( remote_node_table, 1); } if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { remote_node_index = - scic_sds_remote_node_table_allocate_single_remote_node( + sci_remote_node_table_allocate_single_remote_node( remote_node_table, 2); } } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { remote_node_index = - scic_sds_remote_node_table_allocate_triple_remote_node( + sci_remote_node_table_allocate_triple_remote_node( remote_node_table, 2); } @@ -511,8 +511,8 @@ u16 scic_sds_remote_node_table_allocate_remote_node( * This method will free a single remote node index back to the remote node * table. This routine will update the remote node groups */ -static void scic_sds_remote_node_table_release_single_remote_node( - struct scic_remote_node_table *remote_node_table, +static void sci_remote_node_table_release_single_remote_node( + struct sci_remote_node_table *remote_node_table, u16 remote_node_index) { u32 group_index; @@ -520,7 +520,7 @@ static void scic_sds_remote_node_table_release_single_remote_node( group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; - group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index); + group_value = sci_remote_node_table_get_group_value(remote_node_table, group_index); /* * Assert that we are not trying to add an entry to a slot that is already @@ -531,22 +531,22 @@ static void scic_sds_remote_node_table_release_single_remote_node( /* * There are no entries in this slot so it must be added to the single * slot table. */ - scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index); + sci_remote_node_table_set_group_index(remote_node_table, 0, group_index); } else if ((group_value & (group_value - 1)) == 0) { /* * There is only one entry in this slot so it must be moved from the * single slot table to the dual slot table */ - scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index); - scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index); + sci_remote_node_table_clear_group_index(remote_node_table, 0, group_index); + sci_remote_node_table_set_group_index(remote_node_table, 1, group_index); } else { /* * There are two entries in the slot so it must be moved from the dual * slot table to the tripple slot table. */ - scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index); - scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index); + sci_remote_node_table_clear_group_index(remote_node_table, 1, group_index); + sci_remote_node_table_set_group_index(remote_node_table, 2, group_index); } - scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index); + sci_remote_node_table_set_node_index(remote_node_table, remote_node_index); } /** @@ -557,19 +557,19 @@ static void scic_sds_remote_node_table_release_single_remote_node( * This method will release a group of three consecutive remote nodes back to * the free remote nodes. */ -static void scic_sds_remote_node_table_release_triple_remote_node( - struct scic_remote_node_table *remote_node_table, +static void sci_remote_node_table_release_triple_remote_node( + struct sci_remote_node_table *remote_node_table, u16 remote_node_index) { u32 group_index; group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; - scic_sds_remote_node_table_set_group_index( + sci_remote_node_table_set_group_index( remote_node_table, 2, group_index ); - scic_sds_remote_node_table_set_group(remote_node_table, group_index); + sci_remote_node_table_set_group(remote_node_table, group_index); } /** @@ -582,16 +582,16 @@ static void scic_sds_remote_node_table_release_triple_remote_node( * This method will release the remote node index back into the remote node * table free pool. */ -void scic_sds_remote_node_table_release_remote_node_index( - struct scic_remote_node_table *remote_node_table, +void sci_remote_node_table_release_remote_node_index( + struct sci_remote_node_table *remote_node_table, u32 remote_node_count, u16 remote_node_index) { if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { - scic_sds_remote_node_table_release_single_remote_node( + sci_remote_node_table_release_single_remote_node( remote_node_table, remote_node_index); } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { - scic_sds_remote_node_table_release_triple_remote_node( + sci_remote_node_table_release_triple_remote_node( remote_node_table, remote_node_index); } } diff --git a/drivers/scsi/isci/remote_node_table.h b/drivers/scsi/isci/remote_node_table.h index 5737d9a30cca..721ab982d2ac 100644 --- a/drivers/scsi/isci/remote_node_table.h +++ b/drivers/scsi/isci/remote_node_table.h @@ -130,11 +130,11 @@ #define SCU_SATA_REMOTE_NODE_COUNT 1 /** - * struct scic_remote_node_table - + * struct sci_remote_node_table - * * */ -struct scic_remote_node_table { +struct sci_remote_node_table { /** * This field contains the array size in dwords */ @@ -172,16 +172,16 @@ struct scic_remote_node_table { /* --------------------------------------------------------------------------- */ -void scic_sds_remote_node_table_initialize( - struct scic_remote_node_table *remote_node_table, +void sci_remote_node_table_initialize( + struct sci_remote_node_table *remote_node_table, u32 remote_node_entries); -u16 scic_sds_remote_node_table_allocate_remote_node( - struct scic_remote_node_table *remote_node_table, +u16 sci_remote_node_table_allocate_remote_node( + struct sci_remote_node_table *remote_node_table, u32 remote_node_count); -void scic_sds_remote_node_table_release_remote_node_index( - struct scic_remote_node_table *remote_node_table, +void sci_remote_node_table_release_remote_node_index( + struct sci_remote_node_table *remote_node_table, u32 remote_node_count, u16 remote_node_index); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 36e674896bc5..bcb3c08c19a7 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -89,7 +89,7 @@ static dma_addr_t to_sgl_element_pair_dma(struct isci_host *ihost, return ihost->task_context_dma + offset; } - return scic_io_request_get_dma_addr(ireq, &ireq->sg_table[idx - 2]); + return sci_io_request_get_dma_addr(ireq, &ireq->sg_table[idx - 2]); } static void init_sgl_element(struct scu_sgl_element *e, struct scatterlist *sg) @@ -100,7 +100,7 @@ static void init_sgl_element(struct scu_sgl_element *e, struct scatterlist *sg) e->address_modifier = 0; } -static void scic_sds_request_build_sgl(struct isci_request *ireq) +static void sci_request_build_sgl(struct isci_request *ireq) { struct isci_host *ihost = ireq->isci_host; struct sas_task *task = isci_request_access_task(ireq); @@ -158,7 +158,7 @@ static void scic_sds_request_build_sgl(struct isci_request *ireq) } } -static void scic_sds_io_request_build_ssp_command_iu(struct isci_request *ireq) +static void sci_io_request_build_ssp_command_iu(struct isci_request *ireq) { struct ssp_cmd_iu *cmd_iu; struct sas_task *task = isci_request_access_task(ireq); @@ -178,7 +178,7 @@ static void scic_sds_io_request_build_ssp_command_iu(struct isci_request *ireq) sizeof(task->ssp_task.cdb) / sizeof(u32)); } -static void scic_sds_task_request_build_ssp_task_iu(struct isci_request *ireq) +static void sci_task_request_build_ssp_task_iu(struct isci_request *ireq) { struct ssp_task_iu *task_iu; struct sas_task *task = isci_request_access_task(ireq); @@ -211,8 +211,8 @@ static void scu_ssp_reqeust_construct_task_context( struct isci_remote_device *idev; struct isci_port *iport; - idev = scic_sds_request_get_device(ireq); - iport = scic_sds_request_get_port(ireq); + idev = sci_request_get_device(ireq); + iport = sci_request_get_port(ireq); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -220,13 +220,13 @@ static void scu_ssp_reqeust_construct_task_context( task_context->initiator_request = 1; task_context->connection_rate = idev->connection_rate; task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(controller); - task_context->logical_port_index = scic_sds_port_get_index(iport); + sci_controller_get_protocol_engine_group(controller); + task_context->logical_port_index = sci_port_get_index(iport); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; - task_context->remote_node_index = scic_sds_remote_device_get_index(idev); + task_context->remote_node_index = sci_remote_device_get_index(idev); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -242,9 +242,9 @@ static void scu_ssp_reqeust_construct_task_context( task_context->task_phase = 0x01; ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(controller) << + (sci_controller_get_protocol_engine_group(controller) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(iport) << + (sci_port_get_index(iport) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | ISCI_TAG_TCI(ireq->io_tag)); @@ -252,7 +252,7 @@ static void scu_ssp_reqeust_construct_task_context( * Copy the physical address for the command buffer to the * SCU Task Context */ - dma_addr = scic_io_request_get_dma_addr(ireq, &ireq->ssp.cmd); + dma_addr = sci_io_request_get_dma_addr(ireq, &ireq->ssp.cmd); task_context->command_iu_upper = upper_32_bits(dma_addr); task_context->command_iu_lower = lower_32_bits(dma_addr); @@ -261,7 +261,7 @@ static void scu_ssp_reqeust_construct_task_context( * Copy the physical address for the response buffer to the * SCU Task Context */ - dma_addr = scic_io_request_get_dma_addr(ireq, &ireq->ssp.rsp); + dma_addr = sci_io_request_get_dma_addr(ireq, &ireq->ssp.rsp); task_context->response_iu_upper = upper_32_bits(dma_addr); task_context->response_iu_lower = lower_32_bits(dma_addr); @@ -298,7 +298,7 @@ static void scu_ssp_io_request_construct_task_context(struct isci_request *ireq, task_context->transfer_length_bytes = len; if (task_context->transfer_length_bytes > 0) - scic_sds_request_build_sgl(ireq); + sci_request_build_sgl(ireq); } /** @@ -349,8 +349,8 @@ static void scu_sata_reqeust_construct_task_context( struct isci_remote_device *idev; struct isci_port *iport; - idev = scic_sds_request_get_device(ireq); - iport = scic_sds_request_get_port(ireq); + idev = sci_request_get_device(ireq); + iport = sci_request_get_port(ireq); /* Fill in the TC with the its required data */ task_context->abort = 0; @@ -358,14 +358,14 @@ static void scu_sata_reqeust_construct_task_context( task_context->initiator_request = 1; task_context->connection_rate = idev->connection_rate; task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(controller); + sci_controller_get_protocol_engine_group(controller); task_context->logical_port_index = - scic_sds_port_get_index(iport); + sci_port_get_index(iport); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; - task_context->remote_node_index = scic_sds_remote_device_get_index(idev); + task_context->remote_node_index = sci_remote_device_get_index(idev); task_context->command_code = 0; task_context->link_layer_control = 0; @@ -385,9 +385,9 @@ static void scu_sata_reqeust_construct_task_context( task_context->type.words[0] = *(u32 *)&ireq->stp.cmd; ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(controller) << + (sci_controller_get_protocol_engine_group(controller) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(iport) << + (sci_port_get_index(iport) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | ISCI_TAG_TCI(ireq->io_tag)); /* @@ -395,7 +395,7 @@ static void scu_sata_reqeust_construct_task_context( * Context. We must offset the command buffer by 4 bytes because the * first 4 bytes are transfered in the body of the TC. */ - dma_addr = scic_io_request_get_dma_addr(ireq, + dma_addr = sci_io_request_get_dma_addr(ireq, ((char *) &ireq->stp.cmd) + sizeof(u32)); @@ -420,7 +420,7 @@ static void scu_stp_raw_request_construct_task_context(struct isci_request *ireq task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32); } -static enum sci_status scic_sds_stp_pio_request_construct(struct isci_request *ireq, +static enum sci_status sci_stp_pio_request_construct(struct isci_request *ireq, bool copy_rx_frame) { struct isci_stp_request *stp_req = &ireq->stp.req; @@ -432,7 +432,7 @@ static enum sci_status scic_sds_stp_pio_request_construct(struct isci_request *i stp_req->sgl.set = SCU_SGL_ELEMENT_PAIR_A; if (copy_rx_frame) { - scic_sds_request_build_sgl(ireq); + sci_request_build_sgl(ireq); stp_req->sgl.index = 0; } else { /* The user does not want the data copied to the SGL buffer location */ @@ -454,7 +454,7 @@ static enum sci_status scic_sds_stp_pio_request_construct(struct isci_request *i * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method * returns an indication as to whether the construction was successful. */ -static void scic_sds_stp_optimized_request_construct(struct isci_request *ireq, +static void sci_stp_optimized_request_construct(struct isci_request *ireq, u8 optimized_task_type, u32 len, enum dma_data_direction dir) @@ -465,7 +465,7 @@ static void scic_sds_stp_optimized_request_construct(struct isci_request *ireq, scu_sata_reqeust_construct_task_context(ireq, task_context); /* Copy over the SGL elements */ - scic_sds_request_build_sgl(ireq); + sci_request_build_sgl(ireq); /* Copy over the number of bytes to be transfered */ task_context->transfer_length_bytes = len; @@ -490,7 +490,7 @@ static void scic_sds_stp_optimized_request_construct(struct isci_request *ireq, static enum sci_status -scic_io_request_construct_sata(struct isci_request *ireq, +sci_io_request_construct_sata(struct isci_request *ireq, u32 len, enum dma_data_direction dir, bool copy) @@ -533,7 +533,7 @@ scic_io_request_construct_sata(struct isci_request *ireq, /* NCQ */ if (task->ata_task.use_ncq) { - scic_sds_stp_optimized_request_construct(ireq, + sci_stp_optimized_request_construct(ireq, SCU_TASK_TYPE_FPDMAQ_READ, len, dir); return SCI_SUCCESS; @@ -541,17 +541,17 @@ scic_io_request_construct_sata(struct isci_request *ireq, /* DMA */ if (task->ata_task.dma_xfer) { - scic_sds_stp_optimized_request_construct(ireq, + sci_stp_optimized_request_construct(ireq, SCU_TASK_TYPE_DMA_IN, len, dir); return SCI_SUCCESS; } else /* PIO */ - return scic_sds_stp_pio_request_construct(ireq, copy); + return sci_stp_pio_request_construct(ireq, copy); return status; } -static enum sci_status scic_io_request_construct_basic_ssp(struct isci_request *ireq) +static enum sci_status sci_io_request_construct_basic_ssp(struct isci_request *ireq) { struct sas_task *task = isci_request_access_task(ireq); @@ -561,28 +561,28 @@ static enum sci_status scic_io_request_construct_basic_ssp(struct isci_request * task->data_dir, task->total_xfer_len); - scic_sds_io_request_build_ssp_command_iu(ireq); + sci_io_request_build_ssp_command_iu(ireq); sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED); return SCI_SUCCESS; } -enum sci_status scic_task_request_construct_ssp( +enum sci_status sci_task_request_construct_ssp( struct isci_request *ireq) { /* Construct the SSP Task SCU Task Context */ scu_ssp_task_request_construct_task_context(ireq); /* Fill in the SSP Task IU */ - scic_sds_task_request_build_ssp_task_iu(ireq); + sci_task_request_build_ssp_task_iu(ireq); sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED); return SCI_SUCCESS; } -static enum sci_status scic_io_request_construct_basic_sata(struct isci_request *ireq) +static enum sci_status sci_io_request_construct_basic_sata(struct isci_request *ireq) { enum sci_status status; bool copy = false; @@ -592,7 +592,7 @@ static enum sci_status scic_io_request_construct_basic_sata(struct isci_request copy = (task->data_dir == DMA_NONE) ? false : true; - status = scic_io_request_construct_sata(ireq, + status = sci_io_request_construct_sata(ireq, task->total_xfer_len, task->data_dir, copy); @@ -603,7 +603,7 @@ static enum sci_status scic_io_request_construct_basic_sata(struct isci_request return status; } -enum sci_status scic_task_request_construct_sata(struct isci_request *ireq) +enum sci_status sci_task_request_construct_sata(struct isci_request *ireq) { enum sci_status status = SCI_SUCCESS; @@ -648,7 +648,7 @@ static u32 sci_req_tx_bytes(struct isci_request *ireq) * BAR1 is the scu_registers * 0x20002C = 0x200000 + 0x2c * = start of task context SRAM + offset of (type.ssp.data_offset) - * TCi is the io_tag of struct scic_sds_request + * TCi is the io_tag of struct sci_request */ ret_val = readl(scu_reg_base + (SCU_TASK_CONTEXT_SRAM + offsetof(struct scu_task_context, type.ssp.data_offset)) + @@ -658,7 +658,7 @@ static u32 sci_req_tx_bytes(struct isci_request *ireq) return ret_val; } -enum sci_status scic_sds_request_start(struct isci_request *ireq) +enum sci_status sci_request_start(struct isci_request *ireq) { enum sci_base_request_states state; struct scu_task_context *tc = ireq->tc; @@ -708,7 +708,7 @@ enum sci_status scic_sds_request_start(struct isci_request *ireq) } enum sci_status -scic_sds_io_request_terminate(struct isci_request *ireq) +sci_io_request_terminate(struct isci_request *ireq) { enum sci_base_request_states state; @@ -716,7 +716,7 @@ scic_sds_io_request_terminate(struct isci_request *ireq) switch (state) { case SCI_REQ_CONSTRUCTED: - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED); @@ -759,7 +759,7 @@ scic_sds_io_request_terminate(struct isci_request *ireq) return SCI_FAILURE_INVALID_STATE; } -enum sci_status scic_sds_request_complete(struct isci_request *ireq) +enum sci_status sci_request_complete(struct isci_request *ireq) { enum sci_base_request_states state; struct isci_host *ihost = ireq->owning_controller; @@ -770,7 +770,7 @@ enum sci_status scic_sds_request_complete(struct isci_request *ireq) return SCI_FAILURE_INVALID_STATE; if (ireq->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) - scic_sds_controller_release_frame(ihost, + sci_controller_release_frame(ihost, ireq->saved_rx_frame_index); /* XXX can we just stop the machine and remove the 'final' state? */ @@ -778,7 +778,7 @@ enum sci_status scic_sds_request_complete(struct isci_request *ireq) return SCI_SUCCESS; } -enum sci_status scic_sds_io_request_event_handler(struct isci_request *ireq, +enum sci_status sci_io_request_event_handler(struct isci_request *ireq, u32 event_code) { enum sci_base_request_states state; @@ -818,7 +818,7 @@ enum sci_status scic_sds_io_request_event_handler(struct isci_request *ireq, * @sci_req: This parameter specifies the request object for which to copy * the response data. */ -static void scic_sds_io_request_copy_response(struct isci_request *ireq) +static void sci_io_request_copy_response(struct isci_request *ireq) { void *resp_buf; u32 len; @@ -848,7 +848,7 @@ request_started_state_tc_event(struct isci_request *ireq, */ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; @@ -868,11 +868,11 @@ request_started_state_tc_event(struct isci_request *ireq, word_cnt); if (resp->status == 0) { - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY); } else { - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); } @@ -885,7 +885,7 @@ request_started_state_tc_event(struct isci_request *ireq, &ireq->ssp.rsp, word_cnt); - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); break; @@ -900,11 +900,11 @@ request_started_state_tc_event(struct isci_request *ireq, datapres = resp_iu->datapres; if (datapres == 1 || datapres == 2) { - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); } else - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; @@ -921,12 +921,12 @@ request_started_state_tc_event(struct isci_request *ireq, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): if (ireq->protocol == SCIC_STP_PROTOCOL) { - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); } else { - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -944,7 +944,7 @@ request_started_state_tc_event(struct isci_request *ireq, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); @@ -967,7 +967,7 @@ request_started_state_tc_event(struct isci_request *ireq, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): default: - scic_sds_request_set_status( + sci_request_set_status( ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, @@ -991,7 +991,7 @@ request_aborting_state_tc_event(struct isci_request *ireq, switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): - scic_sds_request_set_status(ireq, SCU_TASK_DONE_TASK_ABORT, + sci_request_set_status(ireq, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); @@ -1012,7 +1012,7 @@ static enum sci_status ssp_task_request_await_tc_event(struct isci_request *ireq { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_change_state(&ireq->sm, SCI_REQ_TASK_WAIT_TC_RESP); @@ -1036,7 +1036,7 @@ static enum sci_status ssp_task_request_await_tc_event(struct isci_request *ireq * If a NAK was received, then it is up to the user to retry * the request. */ - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -1057,7 +1057,7 @@ smp_request_await_response_tc_event(struct isci_request *ireq, * unexpected. but if the TC has success status, we * complete the IO anyway. */ - scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); @@ -1074,7 +1074,7 @@ smp_request_await_response_tc_event(struct isci_request *ireq, * these SMP_XXX_XX_ERR status. For these type of error, * we ask ihost user to retry the request. */ - scic_sds_request_set_status(ireq, SCU_TASK_DONE_SMP_RESP_TO_ERR, + sci_request_set_status(ireq, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); @@ -1084,7 +1084,7 @@ smp_request_await_response_tc_event(struct isci_request *ireq, /* All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request */ - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -1101,7 +1101,7 @@ smp_request_await_tc_event(struct isci_request *ireq, { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); @@ -1111,7 +1111,7 @@ smp_request_await_tc_event(struct isci_request *ireq, * complete. If a NAK was received, then it is up to * the user to retry the request. */ - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -1122,7 +1122,7 @@ smp_request_await_tc_event(struct isci_request *ireq, return SCI_SUCCESS; } -void scic_stp_io_request_set_ncq_tag(struct isci_request *ireq, +void sci_stp_io_request_set_ncq_tag(struct isci_request *ireq, u16 ncq_tag) { /** @@ -1171,7 +1171,7 @@ stp_request_non_data_await_h2d_tc_event(struct isci_request *ireq, { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_change_state(&ireq->sm, SCI_REQ_STP_NON_DATA_WAIT_D2H); @@ -1182,7 +1182,7 @@ stp_request_non_data_await_h2d_tc_event(struct isci_request *ireq, * complete. If a NAK was received, then it is up to * the user to retry the request. */ - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -1198,7 +1198,7 @@ stp_request_non_data_await_h2d_tc_event(struct isci_request *ireq, /* transmit DATA_FIS from (current sgl + offset) for input * parameter length. current sgl and offset is alreay stored in the IO request */ -static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( +static enum sci_status sci_stp_request_pio_data_out_trasmit_data_frame( struct isci_request *ireq, u32 length) { @@ -1223,10 +1223,10 @@ static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( task_context->type.stp.fis_type = FIS_DATA; /* send the new TC out. */ - return scic_controller_continue_io(ireq); + return sci_controller_continue_io(ireq); } -static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct isci_request *ireq) +static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_request *ireq) { struct isci_stp_request *stp_req = &ireq->stp.req; struct scu_sgl_element_pair *sgl_pair; @@ -1252,7 +1252,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct is return SCI_SUCCESS; if (stp_req->pio_len >= len) { - status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(ireq, len); + status = sci_stp_request_pio_data_out_trasmit_data_frame(ireq, len); if (status != SCI_SUCCESS) return status; stp_req->pio_len -= len; @@ -1261,7 +1261,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct is sgl = pio_sgl_next(stp_req); offset = 0; } else if (stp_req->pio_len < len) { - scic_sds_stp_request_pio_data_out_trasmit_data_frame(ireq, stp_req->pio_len); + sci_stp_request_pio_data_out_trasmit_data_frame(ireq, stp_req->pio_len); /* Sgl offset will be adjusted and saved for future */ offset += stp_req->pio_len; @@ -1284,7 +1284,7 @@ static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct is * specified data region. enum sci_status */ static enum sci_status -scic_sds_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req, +sci_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req, u8 *data_buf, u32 len) { struct isci_request *ireq; @@ -1328,7 +1328,7 @@ scic_sds_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_r * * Copy the data buffer to the io request data region. enum sci_status */ -static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( +static enum sci_status sci_stp_request_pio_data_in_copy_data( struct isci_stp_request *stp_req, u8 *data_buffer) { @@ -1338,14 +1338,14 @@ static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( * If there is less than 1K remaining in the transfer request * copy just the data for the transfer */ if (stp_req->pio_len < SCU_MAX_FRAME_BUFFER_SIZE) { - status = scic_sds_stp_request_pio_data_in_copy_data_buffer( + status = sci_stp_request_pio_data_in_copy_data_buffer( stp_req, data_buffer, stp_req->pio_len); if (status == SCI_SUCCESS) stp_req->pio_len = 0; } else { /* We are transfering the whole frame so copy */ - status = scic_sds_stp_request_pio_data_in_copy_data_buffer( + status = sci_stp_request_pio_data_in_copy_data_buffer( stp_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); if (status == SCI_SUCCESS) @@ -1363,7 +1363,7 @@ stp_request_pio_await_h2d_completion_tc_event(struct isci_request *ireq, switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); @@ -1375,7 +1375,7 @@ stp_request_pio_await_h2d_completion_tc_event(struct isci_request *ireq, * complete. If a NAK was received, then it is up to * the user to retry the request. */ - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -1398,7 +1398,7 @@ pio_data_out_tx_done_tc_event(struct isci_request *ireq, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): /* Transmit data */ if (stp_req->pio_len != 0) { - status = scic_sds_stp_request_pio_data_out_transmit_data(ireq); + status = sci_stp_request_pio_data_out_transmit_data(ireq); if (status == SCI_SUCCESS) { if (stp_req->pio_len == 0) all_frames_transferred = true; @@ -1426,7 +1426,7 @@ pio_data_out_tx_done_tc_event(struct isci_request *ireq, * If a NAK was received, then it is up to the user to retry * the request. */ - scic_sds_request_set_status( + sci_request_set_status( ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -1438,16 +1438,16 @@ pio_data_out_tx_done_tc_event(struct isci_request *ireq, return status; } -static void scic_sds_stp_request_udma_complete_request( +static void sci_stp_request_udma_complete_request( struct isci_request *ireq, u32 scu_status, enum sci_status sci_status) { - scic_sds_request_set_status(ireq, scu_status, sci_status); + sci_request_set_status(ireq, scu_status, sci_status); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } -static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct isci_request *ireq, +static enum sci_status sci_stp_request_udma_general_frame_handler(struct isci_request *ireq, u32 frame_index) { struct isci_host *ihost = ireq->owning_controller; @@ -1455,28 +1455,28 @@ static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct is enum sci_status status; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + status = sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); if ((status == SCI_SUCCESS) && (frame_header->fis_type == FIS_REGD2H)) { - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&ireq->stp.rsp, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); } - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return status; } enum sci_status -scic_sds_io_request_frame_handler(struct isci_request *ireq, +sci_io_request_frame_handler(struct isci_request *ireq, u32 frame_index) { struct isci_host *ihost = ireq->owning_controller; @@ -1491,7 +1491,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct ssp_frame_hdr ssp_hdr; void *frame_header; - scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, &frame_header); @@ -1502,7 +1502,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct ssp_response_iu *resp_iu; ssize_t word_cnt = SSP_RESP_IU_MAX_SIZE / sizeof(u32); - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&resp_iu); @@ -1512,11 +1512,11 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, if (resp_iu->datapres == 0x01 || resp_iu->datapres == 0x02) { - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); } else - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); } else { @@ -1531,22 +1531,22 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, * In any case we are done with this frame buffer return it to * the controller */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return SCI_SUCCESS; } case SCI_REQ_TASK_WAIT_TC_RESP: - scic_sds_io_request_copy_response(ireq); + sci_io_request_copy_response(ireq); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); - scic_sds_controller_release_frame(ihost,frame_index); + sci_controller_release_frame(ihost, frame_index); return SCI_SUCCESS; case SCI_REQ_SMP_WAIT_RESP: { struct smp_resp *rsp_hdr = &ireq->smp.rsp; void *frame_header; - scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, &frame_header); @@ -1557,7 +1557,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, if (rsp_hdr->frame_type == SMP_RESPONSE) { void *smp_resp; - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, &smp_resp); @@ -1567,7 +1567,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, smp_resp, word_cnt); - scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_change_state(&ireq->sm, SCI_REQ_SMP_WAIT_TC_COMP); @@ -1584,31 +1584,31 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, frame_index, rsp_hdr->frame_type); - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_SMP_FRM_TYPE_ERR, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return SCI_SUCCESS; } case SCI_REQ_STP_UDMA_WAIT_TC_COMP: - return scic_sds_stp_request_udma_general_frame_handler(ireq, + return sci_stp_request_udma_general_frame_handler(ireq, frame_index); case SCI_REQ_STP_UDMA_WAIT_D2H: /* Use the general frame handler to copy the resposne data */ - status = scic_sds_stp_request_udma_general_frame_handler(ireq, + status = sci_stp_request_udma_general_frame_handler(ireq, frame_index); if (status != SCI_SUCCESS) return status; - scic_sds_stp_request_udma_complete_request(ireq, + sci_stp_request_udma_complete_request(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); @@ -1618,7 +1618,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct dev_to_host_fis *frame_header; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + status = sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); @@ -1636,16 +1636,16 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, switch (frame_header->fis_type) { case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&ireq->stp.rsp, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); /* The command has completed with error */ - scic_sds_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, + sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); break; @@ -1655,7 +1655,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, "violation occurred\n", __func__, stp_req, frame_index); - scic_sds_request_set_status(ireq, SCU_TASK_DONE_UNEXP_FIS, + sci_request_set_status(ireq, SCU_TASK_DONE_UNEXP_FIS, SCI_FAILURE_PROTOCOL_VIOLATION); break; } @@ -1663,7 +1663,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return status; } @@ -1673,7 +1673,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct dev_to_host_fis *frame_header; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + status = sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); @@ -1688,7 +1688,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, switch (frame_header->fis_type) { case FIS_PIO_SETUP: /* Get from the frame buffer the PIO Setup Data */ - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); @@ -1704,7 +1704,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, /* status: 4th byte in the 3rd dword */ stp_req->status = (frame_buffer[2] >> 24) & 0xff; - scic_sds_controller_copy_sata_response(&ireq->stp.rsp, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); @@ -1717,7 +1717,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_DATA_IN); } else if (task->data_dir == DMA_TO_DEVICE) { /* Transmit data */ - status = scic_sds_stp_request_pio_data_out_transmit_data(ireq); + status = sci_stp_request_pio_data_out_transmit_data(ireq); if (status != SCI_SUCCESS) break; sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_DATA_OUT); @@ -1745,15 +1745,15 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, break; } - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&ireq->stp.req, + sci_controller_copy_sata_response(&ireq->stp.req, frame_header, frame_buffer); - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); @@ -1766,7 +1766,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, } /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return status; } @@ -1775,7 +1775,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct dev_to_host_fis *frame_header; struct sata_fis_data *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + status = sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); @@ -1800,14 +1800,14 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, frame_index, frame_header->fis_type); - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return status; } @@ -1815,15 +1815,15 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, ireq->saved_rx_frame_index = frame_index; stp_req->pio_len = 0; } else { - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); - status = scic_sds_stp_request_pio_data_in_copy_data(stp_req, + status = sci_stp_request_pio_data_in_copy_data(stp_req, (u8 *)frame_buffer); /* Frame is decoded return it to the controller */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); } /* Check for the end of the transfer, are there more @@ -1833,7 +1833,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, return status; if ((stp_req->status & ATA_BUSY) == 0) { - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); @@ -1848,7 +1848,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, struct dev_to_host_fis *frame_header; u32 *frame_buffer; - status = scic_sds_unsolicited_frame_control_get_header(&ihost->uf_control, + status = sci_unsolicited_frame_control_get_header(&ihost->uf_control, frame_index, (void **)&frame_header); if (status != SCI_SUCCESS) { @@ -1864,16 +1864,16 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, switch (frame_header->fis_type) { case FIS_REGD2H: - scic_sds_unsolicited_frame_control_get_buffer(&ihost->uf_control, + sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, frame_index, (void **)&frame_buffer); - scic_sds_controller_copy_sata_response(&ireq->stp.rsp, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); /* The command has completed with error */ - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); break; @@ -1886,7 +1886,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, stp_req, frame_index); - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_TASK_DONE_UNEXP_FIS, SCI_FAILURE_PROTOCOL_VIOLATION); break; @@ -1895,7 +1895,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame has been decoded return it to the controller */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return status; } @@ -1904,7 +1904,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, * TODO: Is it even possible to get an unsolicited frame in the * aborting state? */ - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return SCI_SUCCESS; default: @@ -1915,7 +1915,7 @@ scic_sds_io_request_frame_handler(struct isci_request *ireq, frame_index, state); - scic_sds_controller_release_frame(ihost, frame_index); + sci_controller_release_frame(ihost, frame_index); return SCI_FAILURE_INVALID_STATE; } } @@ -1927,7 +1927,7 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_stp_request_udma_complete_request(ireq, + sci_stp_request_udma_complete_request(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); break; @@ -1938,10 +1938,10 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq * completion. */ if (ireq->stp.rsp.fis_type == FIS_REGD2H) { - scic_sds_remote_device_suspend(ireq->target_device, + sci_remote_device_suspend(ireq->target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); - scic_sds_stp_request_udma_complete_request(ireq, + sci_stp_request_udma_complete_request(ireq, SCU_TASK_DONE_CHECK_RESPONSE, SCI_FAILURE_IO_RESPONSE_VALID); } else { @@ -1965,12 +1965,12 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): - scic_sds_remote_device_suspend(ireq->target_device, + sci_remote_device_suspend(ireq->target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); /* Fall through to the default case */ default: /* All other completion status cause the IO to be complete. */ - scic_sds_stp_request_udma_complete_request(ireq, + sci_stp_request_udma_complete_request(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); break; @@ -1985,7 +1985,7 @@ stp_request_soft_reset_await_h2d_asserted_tc_event(struct isci_request *ireq, { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_change_state(&ireq->sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG); @@ -1997,7 +1997,7 @@ stp_request_soft_reset_await_h2d_asserted_tc_event(struct isci_request *ireq, * If a NAK was received, then it is up to the user to retry * the request. */ - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -2014,7 +2014,7 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq, { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - scic_sds_request_set_status(ireq, SCU_TASK_DONE_GOOD, + sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, SCI_SUCCESS); sci_change_state(&ireq->sm, SCI_REQ_STP_SOFT_RESET_WAIT_D2H); @@ -2025,7 +2025,7 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq, * a NAK was received, then it is up to the user to retry the * request. */ - scic_sds_request_set_status(ireq, + sci_request_set_status(ireq, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); @@ -2037,7 +2037,7 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq, } enum sci_status -scic_sds_io_request_tc_completion(struct isci_request *ireq, +sci_io_request_tc_completion(struct isci_request *ireq, u32 completion_code) { enum sci_base_request_states state; @@ -2832,7 +2832,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost, ); /* complete the io request to the core. */ - scic_controller_complete_io(ihost, request->target_device, request); + sci_controller_complete_io(ihost, request->target_device, request); isci_put_device(idev); /* set terminated handle so it cannot be completed or @@ -2842,7 +2842,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost, set_bit(IREQ_TERMINATED, &request->flags); } -static void scic_sds_request_started_state_enter(struct sci_base_state_machine *sm) +static void sci_request_started_state_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); struct domain_device *dev = ireq->target_device->domain_dev; @@ -2879,7 +2879,7 @@ static void scic_sds_request_started_state_enter(struct sci_base_state_machine * } } -static void scic_sds_request_completed_state_enter(struct sci_base_state_machine *sm) +static void sci_request_completed_state_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); struct isci_host *ihost = ireq->owning_controller; @@ -2892,7 +2892,7 @@ static void scic_sds_request_completed_state_enter(struct sci_base_state_machine isci_task_request_complete(ihost, ireq, ireq->sci_status); } -static void scic_sds_request_aborting_state_enter(struct sci_base_state_machine *sm) +static void sci_request_aborting_state_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); @@ -2900,31 +2900,31 @@ static void scic_sds_request_aborting_state_enter(struct sci_base_state_machine ireq->tc->abort = 1; } -static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(struct sci_base_state_machine *sm) +static void sci_stp_request_started_non_data_await_h2d_completion_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - scic_sds_remote_device_set_working_request(ireq->target_device, + sci_remote_device_set_working_request(ireq->target_device, ireq); } -static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(struct sci_base_state_machine *sm) +static void sci_stp_request_started_pio_await_h2d_completion_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - scic_sds_remote_device_set_working_request(ireq->target_device, + sci_remote_device_set_working_request(ireq->target_device, ireq); } -static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(struct sci_base_state_machine *sm) +static void sci_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - scic_sds_remote_device_set_working_request(ireq->target_device, + sci_remote_device_set_working_request(ireq->target_device, ireq); } -static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(struct sci_base_state_machine *sm) +static void sci_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); struct scu_task_context *tc = ireq->tc; @@ -2938,22 +2938,22 @@ static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_complet /* Clear the TC control bit */ tc->control_frame = 0; - status = scic_controller_continue_io(ireq); + status = sci_controller_continue_io(ireq); WARN_ONCE(status != SCI_SUCCESS, "isci: continue io failure\n"); } -static const struct sci_base_state scic_sds_request_state_table[] = { +static const struct sci_base_state sci_request_state_table[] = { [SCI_REQ_INIT] = { }, [SCI_REQ_CONSTRUCTED] = { }, [SCI_REQ_STARTED] = { - .enter_state = scic_sds_request_started_state_enter, + .enter_state = sci_request_started_state_enter, }, [SCI_REQ_STP_NON_DATA_WAIT_H2D] = { - .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, + .enter_state = sci_stp_request_started_non_data_await_h2d_completion_enter, }, [SCI_REQ_STP_NON_DATA_WAIT_D2H] = { }, [SCI_REQ_STP_PIO_WAIT_H2D] = { - .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, + .enter_state = sci_stp_request_started_pio_await_h2d_completion_enter, }, [SCI_REQ_STP_PIO_WAIT_FRAME] = { }, [SCI_REQ_STP_PIO_DATA_IN] = { }, @@ -2961,10 +2961,10 @@ static const struct sci_base_state scic_sds_request_state_table[] = { [SCI_REQ_STP_UDMA_WAIT_TC_COMP] = { }, [SCI_REQ_STP_UDMA_WAIT_D2H] = { }, [SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, + .enter_state = sci_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, }, [SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG] = { - .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, + .enter_state = sci_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, }, [SCI_REQ_STP_SOFT_RESET_WAIT_D2H] = { }, [SCI_REQ_TASK_WAIT_TC_COMP] = { }, @@ -2972,20 +2972,20 @@ static const struct sci_base_state scic_sds_request_state_table[] = { [SCI_REQ_SMP_WAIT_RESP] = { }, [SCI_REQ_SMP_WAIT_TC_COMP] = { }, [SCI_REQ_COMPLETED] = { - .enter_state = scic_sds_request_completed_state_enter, + .enter_state = sci_request_completed_state_enter, }, [SCI_REQ_ABORTING] = { - .enter_state = scic_sds_request_aborting_state_enter, + .enter_state = sci_request_aborting_state_enter, }, [SCI_REQ_FINAL] = { }, }; static void -scic_sds_general_request_construct(struct isci_host *ihost, +sci_general_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { - sci_init_sm(&ireq->sm, scic_sds_request_state_table, SCI_REQ_INIT); + sci_init_sm(&ireq->sm, sci_request_state_table, SCI_REQ_INIT); ireq->target_device = idev; ireq->protocol = SCIC_NO_PROTOCOL; @@ -2997,7 +2997,7 @@ scic_sds_general_request_construct(struct isci_host *ihost, } static enum sci_status -scic_io_request_construct(struct isci_host *ihost, +sci_io_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { @@ -3005,7 +3005,7 @@ scic_io_request_construct(struct isci_host *ihost, enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(ihost, idev, ireq); + sci_general_request_construct(ihost, idev, ireq); if (idev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) return SCI_FAILURE_INVALID_REMOTE_DEVICE; @@ -3024,7 +3024,7 @@ scic_io_request_construct(struct isci_host *ihost, return status; } -enum sci_status scic_task_request_construct(struct isci_host *ihost, +enum sci_status sci_task_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, u16 io_tag, struct isci_request *ireq) { @@ -3032,7 +3032,7 @@ enum sci_status scic_task_request_construct(struct isci_host *ihost, enum sci_status status = SCI_SUCCESS; /* Build the common part of the request */ - scic_sds_general_request_construct(ihost, idev, ireq); + sci_general_request_construct(ihost, idev, ireq); if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { @@ -3053,7 +3053,7 @@ static enum sci_status isci_request_ssp_request_construct( "%s: request = %p\n", __func__, request); - status = scic_io_request_construct_basic_ssp(request); + status = sci_io_request_construct_basic_ssp(request); return status; } @@ -3074,7 +3074,7 @@ static enum sci_status isci_request_stp_request_construct( */ register_fis = isci_sata_task_to_fis_copy(task); - status = scic_io_request_construct_basic_sata(request); + status = sci_io_request_construct_basic_sata(request); /* Set the ncq tag in the fis, from the queue * command in the task. @@ -3091,7 +3091,7 @@ static enum sci_status isci_request_stp_request_construct( } static enum sci_status -scic_io_request_construct_smp(struct device *dev, +sci_io_request_construct_smp(struct device *dev, struct isci_request *ireq, struct sas_task *task) { @@ -3141,8 +3141,8 @@ scic_io_request_construct_smp(struct device *dev, task_context = ireq->tc; - idev = scic_sds_request_get_device(ireq); - iport = scic_sds_request_get_port(ireq); + idev = sci_request_get_device(ireq); + iport = sci_request_get_port(ireq); /* * Fill in the TC with the its required data @@ -3152,8 +3152,8 @@ scic_io_request_construct_smp(struct device *dev, task_context->initiator_request = 1; task_context->connection_rate = idev->connection_rate; task_context->protocol_engine_index = - scic_sds_controller_get_protocol_engine_group(ihost); - task_context->logical_port_index = scic_sds_port_get_index(iport); + sci_controller_get_protocol_engine_group(ihost); + task_context->logical_port_index = sci_port_get_index(iport); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; task_context->abort = 0; task_context->valid = SCU_TASK_CONTEXT_VALID; @@ -3195,9 +3195,9 @@ scic_io_request_construct_smp(struct device *dev, task_context->task_phase = 0; ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (scic_sds_controller_get_protocol_engine_group(ihost) << + (sci_controller_get_protocol_engine_group(ihost) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (scic_sds_port_get_index(iport) << + (sci_port_get_index(iport) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | ISCI_TAG_TCI(ireq->io_tag)); /* @@ -3229,7 +3229,7 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) struct device *dev = &ireq->isci_host->pdev->dev; enum sci_status status = SCI_FAILURE; - status = scic_io_request_construct_smp(dev, ireq, task); + status = sci_io_request_construct_smp(dev, ireq, task); if (status != SCI_SUCCESS) dev_warn(&ireq->isci_host->pdev->dev, "%s: failed with status = %d\n", @@ -3283,7 +3283,7 @@ static enum sci_status isci_io_request_build(struct isci_host *ihost, return SCI_FAILURE_INSUFFICIENT_RESOURCES; } - status = scic_io_request_construct(ihost, idev, request); + status = sci_io_request_construct(ihost, idev, request); if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, @@ -3388,7 +3388,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide * request was built that way (ie. * ireq->is_task_management_request is false). */ - status = scic_controller_start_task(ihost, + status = sci_controller_start_task(ihost, idev, ireq); } else { @@ -3396,7 +3396,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide } } else { /* send the request, let the core assign the IO TAG. */ - status = scic_controller_start_io(ihost, idev, + status = sci_controller_start_io(ihost, idev, ireq); } diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 0cafcead7a01..08fcf98e70f4 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -301,75 +301,75 @@ enum sci_base_request_states { }; /** - * scic_sds_request_get_controller() - + * sci_request_get_controller() - * * This macro will return the controller for this io request object */ -#define scic_sds_request_get_controller(ireq) \ +#define sci_request_get_controller(ireq) \ ((ireq)->owning_controller) /** - * scic_sds_request_get_device() - + * sci_request_get_device() - * * This macro will return the device for this io request object */ -#define scic_sds_request_get_device(ireq) \ +#define sci_request_get_device(ireq) \ ((ireq)->target_device) /** - * scic_sds_request_get_port() - + * sci_request_get_port() - * * This macro will return the port for this io request object */ -#define scic_sds_request_get_port(ireq) \ - scic_sds_remote_device_get_port(scic_sds_request_get_device(ireq)) +#define sci_request_get_port(ireq) \ + sci_remote_device_get_port(sci_request_get_device(ireq)) /** - * scic_sds_request_get_post_context() - + * sci_request_get_post_context() - * * This macro returns the constructed post context result for the io request. */ -#define scic_sds_request_get_post_context(ireq) \ +#define sci_request_get_post_context(ireq) \ ((ireq)->post_context) /** - * scic_sds_request_get_task_context() - + * sci_request_get_task_context() - * * This is a helper macro to return the os handle for this request object. */ -#define scic_sds_request_get_task_context(request) \ +#define sci_request_get_task_context(request) \ ((request)->task_context_buffer) /** - * scic_sds_request_set_status() - + * sci_request_set_status() - * * This macro will set the scu hardware status and sci request completion * status for an io request. */ -#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \ +#define sci_request_set_status(request, scu_status_code, sci_status_code) \ { \ (request)->scu_status = (scu_status_code); \ (request)->sci_status = (sci_status_code); \ } -enum sci_status scic_sds_request_start(struct isci_request *ireq); -enum sci_status scic_sds_io_request_terminate(struct isci_request *ireq); +enum sci_status sci_request_start(struct isci_request *ireq); +enum sci_status sci_io_request_terminate(struct isci_request *ireq); enum sci_status -scic_sds_io_request_event_handler(struct isci_request *ireq, +sci_io_request_event_handler(struct isci_request *ireq, u32 event_code); enum sci_status -scic_sds_io_request_frame_handler(struct isci_request *ireq, +sci_io_request_frame_handler(struct isci_request *ireq, u32 frame_index); enum sci_status -scic_sds_task_request_terminate(struct isci_request *ireq); +sci_task_request_terminate(struct isci_request *ireq); extern enum sci_status -scic_sds_request_complete(struct isci_request *ireq); +sci_request_complete(struct isci_request *ireq); extern enum sci_status -scic_sds_io_request_tc_completion(struct isci_request *ireq, u32 code); +sci_io_request_tc_completion(struct isci_request *ireq, u32 code); /* XXX open code in caller */ static inline dma_addr_t -scic_io_request_get_dma_addr(struct isci_request *ireq, void *virt_addr) +sci_io_request_get_dma_addr(struct isci_request *ireq, void *virt_addr) { char *requested_addr = (char *)virt_addr; @@ -500,17 +500,17 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide void isci_terminate_pending_requests(struct isci_host *ihost, struct isci_remote_device *idev); enum sci_status -scic_task_request_construct(struct isci_host *ihost, +sci_task_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, u16 io_tag, struct isci_request *ireq); enum sci_status -scic_task_request_construct_ssp(struct isci_request *ireq); +sci_task_request_construct_ssp(struct isci_request *ireq); enum sci_status -scic_task_request_construct_sata(struct isci_request *ireq); +sci_task_request_construct_sata(struct isci_request *ireq); void -scic_stp_io_request_set_ncq_tag(struct isci_request *ireq, u16 ncq_tag); -void scic_sds_smp_request_copy_response(struct isci_request *ireq); +sci_stp_io_request_set_ncq_tag(struct isci_request *ireq, u16 ncq_tag); +void sci_smp_request_copy_response(struct isci_request *ireq); static inline int isci_task_is_ncq_recovery(struct sas_task *task) { diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c index 87d8cc1a6e39..47b96c21548f 100644 --- a/drivers/scsi/isci/sata.c +++ b/drivers/scsi/isci/sata.c @@ -116,7 +116,7 @@ void isci_sata_set_ncq_tag( struct isci_request *request = task->lldd_task; register_fis->sector_count = qc->tag << 3; - scic_stp_io_request_set_ncq_tag(request, qc->tag); + sci_stp_io_request_set_ncq_tag(request, qc->tag); } /** @@ -187,7 +187,7 @@ enum sci_status isci_sata_management_task_request_build(struct isci_request *ire /* core builds the protocol specific request * based on the h2d fis. */ - status = scic_task_request_construct_sata(ireq); + status = sci_task_request_construct_sata(ireq); return status; } diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 3a1fc55a7557..d040aa2f3722 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -257,12 +257,12 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, return NULL; /* let the core do it's construct. */ - status = scic_task_request_construct(ihost, idev, tag, + status = sci_task_request_construct(ihost, idev, tag, ireq); if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, - "%s: scic_task_request_construct failed - " + "%s: sci_task_request_construct failed - " "status = 0x%x\n", __func__, status); @@ -272,7 +272,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, /* XXX convert to get this from task->tproto like other drivers */ if (dev->dev_type == SAS_END_DEV) { isci_tmf->proto = SAS_PROTOCOL_SSP; - status = scic_task_request_construct_ssp(ireq); + status = sci_task_request_construct_ssp(ireq); if (status != SCI_SUCCESS) return NULL; } @@ -332,7 +332,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, spin_lock_irqsave(&ihost->scic_lock, flags); /* start the TMF io. */ - status = scic_controller_start_task(ihost, idev, ireq); + status = sci_controller_start_task(ihost, idev, ireq); if (status != SCI_TASK_SUCCESS) { dev_warn(&ihost->pdev->dev, @@ -364,7 +364,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, if (tmf->cb_state_func != NULL) tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); - scic_controller_terminate_request(ihost, + sci_controller_terminate_request(ihost, idev, ireq); @@ -556,7 +556,7 @@ static void isci_terminate_request_core(struct isci_host *ihost, if (!test_bit(IREQ_TERMINATED, &isci_request->flags)) { was_terminated = true; needs_cleanup_handling = true; - status = scic_controller_terminate_request(ihost, + status = sci_controller_terminate_request(ihost, idev, isci_request); } @@ -569,7 +569,7 @@ static void isci_terminate_request_core(struct isci_host *ihost, */ if (status != SCI_SUCCESS) { dev_err(&ihost->pdev->dev, - "%s: scic_controller_terminate_request" + "%s: sci_controller_terminate_request" " returned = 0x%x\n", __func__, status); @@ -1251,7 +1251,7 @@ isci_task_request_complete(struct isci_host *ihost, /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ tmf_complete = tmf->complete; - scic_controller_complete_io(ihost, ireq->target_device, ireq); + sci_controller_complete_io(ihost, ireq->target_device, ireq); /* set the 'terminated' flag handle to make sure it cannot be terminated * or completed again. */ @@ -1514,12 +1514,12 @@ static int isci_reset_device(struct isci_host *ihost, dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_reset(idev); + status = sci_remote_device_reset(idev); if (status != SCI_SUCCESS) { spin_unlock_irqrestore(&ihost->scic_lock, flags); dev_warn(&ihost->pdev->dev, - "%s: scic_remote_device_reset(%p) returned %d!\n", + "%s: sci_remote_device_reset(%p) returned %d!\n", __func__, idev, status); return TMF_RESP_FUNC_FAILED; @@ -1540,7 +1540,7 @@ static int isci_reset_device(struct isci_host *ihost, /* Since all pending TCs have been cleaned, resume the RNC. */ spin_lock_irqsave(&ihost->scic_lock, flags); - status = scic_remote_device_reset_complete(idev); + status = sci_remote_device_reset_complete(idev); spin_unlock_irqrestore(&ihost->scic_lock, flags); /* If this is a device on an expander, bring the phy back up. */ @@ -1560,7 +1560,7 @@ static int isci_reset_device(struct isci_host *ihost, if (status != SCI_SUCCESS) { dev_warn(&ihost->pdev->dev, - "%s: scic_remote_device_reset_complete(%p) " + "%s: sci_remote_device_reset_complete(%p) " "returned %d!\n", __func__, idev, status); } diff --git a/drivers/scsi/isci/unsolicited_frame_control.c b/drivers/scsi/isci/unsolicited_frame_control.c index a0e6f89fc6a1..e9e1e2abacb9 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.c +++ b/drivers/scsi/isci/unsolicited_frame_control.c @@ -57,10 +57,10 @@ #include "unsolicited_frame_control.h" #include "registers.h" -int scic_sds_unsolicited_frame_control_construct(struct isci_host *ihost) +int sci_unsolicited_frame_control_construct(struct isci_host *ihost) { - struct scic_sds_unsolicited_frame_control *uf_control = &ihost->uf_control; - struct scic_sds_unsolicited_frame *uf; + struct sci_unsolicited_frame_control *uf_control = &ihost->uf_control; + struct sci_unsolicited_frame *uf; u32 buf_len, header_len, i; dma_addr_t dma; size_t size; @@ -139,23 +139,14 @@ int scic_sds_unsolicited_frame_control_construct(struct isci_host *ihost) return 0; } -/** - * This method returns the frame header for the specified frame index. - * @uf_control: - * @frame_index: - * @frame_header: - * - * enum sci_status - */ -enum sci_status scic_sds_unsolicited_frame_control_get_header( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index, - void **frame_header) +enum sci_status sci_unsolicited_frame_control_get_header(struct sci_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_header) { if (frame_index < SCU_MAX_UNSOLICITED_FRAMES) { - /* - * Skip the first word in the frame since this is a controll word used - * by the hardware. */ + /* Skip the first word in the frame since this is a controll word used + * by the hardware. + */ *frame_header = &uf_control->buffers.array[frame_index].header->data; return SCI_SUCCESS; @@ -164,18 +155,9 @@ enum sci_status scic_sds_unsolicited_frame_control_get_header( return SCI_FAILURE_INVALID_PARAMETER_VALUE; } -/** - * This method returns the frame buffer for the specified frame index. - * @uf_control: - * @frame_index: - * @frame_buffer: - * - * enum sci_status - */ -enum sci_status scic_sds_unsolicited_frame_control_get_buffer( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index, - void **frame_buffer) +enum sci_status sci_unsolicited_frame_control_get_buffer(struct sci_unsolicited_frame_control *uf_control, + u32 frame_index, + void **frame_buffer) { if (frame_index < SCU_MAX_UNSOLICITED_FRAMES) { *frame_buffer = uf_control->buffers.array[frame_index].buffer; @@ -186,19 +168,8 @@ enum sci_status scic_sds_unsolicited_frame_control_get_buffer( return SCI_FAILURE_INVALID_PARAMETER_VALUE; } -/** - * This method releases the frame once this is done the frame is available for - * re-use by the hardware. The data contained in the frame header and frame - * buffer is no longer valid. - * @uf_control: This parameter specifies the UF control object - * @frame_index: This parameter specifies the frame index to attempt to release. - * - * This method returns an indication to the caller as to whether the - * unsolicited frame get pointer should be updated. - */ -bool scic_sds_unsolicited_frame_control_release_frame( - struct scic_sds_unsolicited_frame_control *uf_control, - u32 frame_index) +bool sci_unsolicited_frame_control_release_frame(struct sci_unsolicited_frame_control *uf_control, + u32 frame_index) { u32 frame_get; u32 frame_cycle; diff --git a/drivers/scsi/isci/unsolicited_frame_control.h b/drivers/scsi/isci/unsolicited_frame_control.h index c0285a3db562..b849a84af34f 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.h +++ b/drivers/scsi/isci/unsolicited_frame_control.h @@ -92,12 +92,12 @@ enum unsolicited_frame_state { }; /** - * struct scic_sds_unsolicited_frame - + * struct sci_unsolicited_frame - * * This is the unsolicited frame data structure it acts as the container for * the current frame state, frame header and frame buffer. */ -struct scic_sds_unsolicited_frame { +struct sci_unsolicited_frame { /** * This field contains the current frame state */ @@ -116,11 +116,11 @@ struct scic_sds_unsolicited_frame { }; /** - * struct scic_sds_uf_header_array - + * struct sci_uf_header_array - * * This structure contains all of the unsolicited frame header information. */ -struct scic_sds_uf_header_array { +struct sci_uf_header_array { /** * This field is represents a virtual pointer to the start * address of the UF address table. The table contains @@ -137,19 +137,19 @@ struct scic_sds_uf_header_array { }; /** - * struct scic_sds_uf_buffer_array - + * struct sci_uf_buffer_array - * * This structure contains all of the unsolicited frame buffer (actual payload) * information. */ -struct scic_sds_uf_buffer_array { +struct sci_uf_buffer_array { /** * This field is the unsolicited frame data its used to manage * the data for the unsolicited frame requests. It also represents * the virtual address location that corresponds to the * physical_address field. */ - struct scic_sds_unsolicited_frame array[SCU_MAX_UNSOLICITED_FRAMES]; + struct sci_unsolicited_frame array[SCU_MAX_UNSOLICITED_FRAMES]; /** * This field specifies the physical address location for the UF @@ -159,13 +159,13 @@ struct scic_sds_uf_buffer_array { }; /** - * struct scic_sds_uf_address_table_array - + * struct sci_uf_address_table_array - * * This object maintains all of the unsolicited frame address table specific * data. The address table is a collection of 64-bit pointers that point to * 1KB buffers into which the silicon will DMA unsolicited frames. */ -struct scic_sds_uf_address_table_array { +struct sci_uf_address_table_array { /** * This field represents a virtual pointer that refers to the * starting address of the UF address table. @@ -182,11 +182,11 @@ struct scic_sds_uf_address_table_array { }; /** - * struct scic_sds_unsolicited_frame_control - + * struct sci_unsolicited_frame_control - * * This object contains all of the data necessary to handle unsolicited frames. */ -struct scic_sds_unsolicited_frame_control { +struct sci_unsolicited_frame_control { /** * This field is the software copy of the unsolicited frame queue * get pointer. The controller object writes this value to the @@ -198,38 +198,38 @@ struct scic_sds_unsolicited_frame_control { * This field contains all of the unsolicited frame header * specific fields. */ - struct scic_sds_uf_header_array headers; + struct sci_uf_header_array headers; /** * This field contains all of the unsolicited frame buffer * specific fields. */ - struct scic_sds_uf_buffer_array buffers; + struct sci_uf_buffer_array buffers; /** * This field contains all of the unsolicited frame address table * specific fields. */ - struct scic_sds_uf_address_table_array address_table; + struct sci_uf_address_table_array address_table; }; struct isci_host; -int scic_sds_unsolicited_frame_control_construct(struct isci_host *ihost); +int sci_unsolicited_frame_control_construct(struct isci_host *ihost); -enum sci_status scic_sds_unsolicited_frame_control_get_header( - struct scic_sds_unsolicited_frame_control *uf_control, +enum sci_status sci_unsolicited_frame_control_get_header( + struct sci_unsolicited_frame_control *uf_control, u32 frame_index, void **frame_header); -enum sci_status scic_sds_unsolicited_frame_control_get_buffer( - struct scic_sds_unsolicited_frame_control *uf_control, +enum sci_status sci_unsolicited_frame_control_get_buffer( + struct sci_unsolicited_frame_control *uf_control, u32 frame_index, void **frame_buffer); -bool scic_sds_unsolicited_frame_control_release_frame( - struct scic_sds_unsolicited_frame_control *uf_control, +bool sci_unsolicited_frame_control_release_frame( + struct sci_unsolicited_frame_control *uf_control, u32 frame_index); #endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */ -- cgit v1.2.3 From 34a991587a5cc9f78960c2c9beea217866458c41 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 1 Jul 2011 02:25:15 -0700 Subject: isci: kill 'get/set' macros Most of these simple dereference macros are longer than their open coded equivalent. Deleting enum sci_controller_mode is thrown in for good measure. Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 8 +- drivers/scsi/isci/host.h | 20 +- drivers/scsi/isci/isci.h | 5 - drivers/scsi/isci/phy.c | 33 ++-- drivers/scsi/isci/phy.h | 17 -- drivers/scsi/isci/port.c | 4 +- drivers/scsi/isci/port.h | 17 -- drivers/scsi/isci/port_config.c | 14 +- drivers/scsi/isci/remote_device.c | 43 ++--- drivers/scsi/isci/remote_device.h | 97 ++-------- drivers/scsi/isci/remote_node_context.c | 2 +- drivers/scsi/isci/remote_node_context.h | 3 - drivers/scsi/isci/request.c | 328 +++++++++++++------------------- drivers/scsi/isci/request.h | 73 ------- drivers/scsi/isci/task.c | 2 +- 15 files changed, 188 insertions(+), 478 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index f31f64e4b713..88e731333532 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -2627,7 +2627,7 @@ enum sci_status sci_controller_start_io(struct isci_host *ihost, return status; set_bit(IREQ_ACTIVE, &ireq->flags); - sci_controller_post_request(ihost, sci_request_get_post_context(ireq)); + sci_controller_post_request(ihost, ireq->post_context); return SCI_SUCCESS; } @@ -2707,7 +2707,7 @@ enum sci_status sci_controller_continue_io(struct isci_request *ireq) } set_bit(IREQ_ACTIVE, &ireq->flags); - sci_controller_post_request(ihost, sci_request_get_post_context(ireq)); + sci_controller_post_request(ihost, ireq->post_context); return SCI_SUCCESS; } @@ -2747,9 +2747,7 @@ enum sci_task_status sci_controller_start_task(struct isci_host *ihost, return SCI_SUCCESS; case SCI_SUCCESS: set_bit(IREQ_ACTIVE, &ireq->flags); - - sci_controller_post_request(ihost, - sci_request_get_post_context(ireq)); + sci_controller_post_request(ihost, ireq->post_context); break; default: break; diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index d87f21de1807..a72d2be2445d 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -172,6 +172,7 @@ struct isci_host { /* XXX kill */ bool phy_startup_timer_pending; u32 next_phy_to_start; + /* XXX convert to unsigned long and use bitops */ u8 invalid_phy_mask; /* TODO attempt dynamic interrupt coalescing scheme */ @@ -359,13 +360,8 @@ static inline struct isci_host *dev_to_ihost(struct domain_device *dev) return dev->port->ha->lldd_ha; } -/** - * sci_controller_get_protocol_engine_group() - - * - * This macro returns the protocol engine group for this controller object. - * Presently we only support protocol engine group 0 so just return that - */ -#define sci_controller_get_protocol_engine_group(controller) 0 +/* we always use protocol engine group zero */ +#define ISCI_PEG 0 /* see sci_controller_io_tag_allocate|free for how seq and tci are built */ #define ISCI_TAG(seq, tci) (((u16) (seq)) << 12 | tci) @@ -385,16 +381,6 @@ static inline int sci_remote_device_node_count(struct isci_remote_device *idev) return SCU_SSP_REMOTE_NODE_COUNT; } -/** - * sci_controller_set_invalid_phy() - - * - * This macro will set the bit in the invalid phy mask for this controller - * object. This is used to control messages reported for invalid link up - * notifications. - */ -#define sci_controller_set_invalid_phy(controller, phy) \ - ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index)) - /** * sci_controller_clear_invalid_phy() - * diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 3afccfcb94e1..d1de63312e7f 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -73,11 +73,6 @@ #define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF -enum sci_controller_mode { - SCI_MODE_SPEED, - SCI_MODE_SIZE /* deprecated */ -}; - #define SCI_MAX_PHYS (4UL) #define SCI_MAX_PORTS SCI_MAX_PHYS #define SCI_MAX_SMP_PHYS (384) /* not silicon constrained */ diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 0df9f713f487..e56080af78f4 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -265,10 +265,11 @@ done: * port (i.e. it's contained in the dummy port). !NULL All other * values indicate a handle/pointer to the port containing the phy. */ -struct isci_port *phy_get_non_dummy_port( - struct isci_phy *iphy) +struct isci_port *phy_get_non_dummy_port(struct isci_phy *iphy) { - if (sci_port_get_index(iphy->owning_port) == SCIC_SDS_DUMMY_PORT) + struct isci_port *iport = iphy->owning_port; + + if (iport->physical_port_index == SCIC_SDS_DUMMY_PORT) return NULL; return iphy->owning_port; @@ -858,10 +859,9 @@ enum sci_status sci_phy_frame_handler(struct isci_phy *iphy, u32 frame_index) struct dev_to_host_fis *frame_header; u32 *fis_frame_data; - result = sci_unsolicited_frame_control_get_header( - &(sci_phy_get_controller(iphy)->uf_control), - frame_index, - (void **)&frame_header); + result = sci_unsolicited_frame_control_get_header(&ihost->uf_control, + frame_index, + (void **)&frame_header); if (result != SCI_SUCCESS) return result; @@ -1090,6 +1090,8 @@ static void scu_link_layer_tx_hard_reset( static void sci_phy_stopped_state_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); + struct isci_port *iport = iphy->owning_port; + struct isci_host *ihost = iport->owning_controller; /* * @todo We need to get to the controller to place this PE in a @@ -1100,14 +1102,14 @@ static void sci_phy_stopped_state_enter(struct sci_base_state_machine *sm) scu_link_layer_stop_protocol_engine(iphy); if (iphy->sm.previous_state_id != SCI_PHY_INITIAL) - sci_controller_link_down(sci_phy_get_controller(iphy), - phy_get_non_dummy_port(iphy), - iphy); + sci_controller_link_down(ihost, phy_get_non_dummy_port(iphy), iphy); } static void sci_phy_starting_state_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); + struct isci_port *iport = iphy->owning_port; + struct isci_host *ihost = iport->owning_controller; scu_link_layer_stop_protocol_engine(iphy); scu_link_layer_start_oob(iphy); @@ -1117,9 +1119,7 @@ static void sci_phy_starting_state_enter(struct sci_base_state_machine *sm) iphy->bcn_received_while_port_unassigned = false; if (iphy->sm.previous_state_id == SCI_PHY_READY) - sci_controller_link_down(sci_phy_get_controller(iphy), - phy_get_non_dummy_port(iphy), - iphy); + sci_controller_link_down(ihost, phy_get_non_dummy_port(iphy), iphy); sci_change_state(&iphy->sm, SCI_PHY_SUB_INITIAL); } @@ -1127,11 +1127,10 @@ static void sci_phy_starting_state_enter(struct sci_base_state_machine *sm) static void sci_phy_ready_state_enter(struct sci_base_state_machine *sm) { struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm); + struct isci_port *iport = iphy->owning_port; + struct isci_host *ihost = iport->owning_controller; - sci_controller_link_up(sci_phy_get_controller(iphy), - phy_get_non_dummy_port(iphy), - iphy); - + sci_controller_link_up(ihost, phy_get_non_dummy_port(iphy), iphy); } static void sci_phy_ready_state_exit(struct sci_base_state_machine *sm) diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h index 5d2c1b4906a3..67699c8e321c 100644 --- a/drivers/scsi/isci/phy.h +++ b/drivers/scsi/isci/phy.h @@ -440,23 +440,6 @@ enum sci_phy_states { SCI_PHY_FINAL, }; -/** - * sci_phy_get_index() - - * - * This macro returns the phy index for the specified phy - */ -#define sci_phy_get_index(phy) \ - ((phy)->phy_index) - -/** - * sci_phy_get_controller() - This macro returns the controller for this - * phy - * - * - */ -#define sci_phy_get_controller(phy) \ - (sci_port_get_controller((phy)->owning_port)) - void sci_phy_construct( struct isci_phy *iphy, struct isci_port *iport, diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 1822ed68409e..8f6f9b77e41a 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -654,7 +654,7 @@ static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy, bool do_notify_user) { - struct isci_host *ihost = sci_port_get_controller(iport); + struct isci_host *ihost = iport->owning_controller; iport->active_phy_mask &= ~(1 << iphy->phy_index); @@ -678,7 +678,7 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i * invalid link. */ if ((ihost->invalid_phy_mask & (1 << iphy->phy_index)) == 0) { - sci_controller_set_invalid_phy(ihost, iphy); + ihost->invalid_phy_mask |= 1 << iphy->phy_index; dev_warn(&ihost->pdev->dev, "Invalid link up!\n"); } } diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index 4c4ab8126d9f..b50ecd4e8f9c 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -210,23 +210,6 @@ enum sci_port_states { }; -/** - * sci_port_get_controller() - - * - * Helper macro to get the owning controller of this port - */ -#define sci_port_get_controller(this_port) \ - ((this_port)->owning_controller) - -/** - * sci_port_get_index() - - * - * This macro returns the physical port index for this port object - */ -#define sci_port_get_index(this_port) \ - ((this_port)->physical_port_index) - - static inline void sci_port_decrement_request_count(struct isci_port *iport) { if (WARN_ONCE(iport->started_request_count == 0, diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index c8b16db6bbde..486b113c634a 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -367,10 +367,10 @@ static void sci_mpc_agent_link_up(struct isci_host *ihost, if (!iport) return; - port_agent->phy_ready_mask |= (1 << sci_phy_get_index(iphy)); + port_agent->phy_ready_mask |= (1 << iphy->phy_index); sci_port_link_up(iport, iphy); - if ((iport->active_phy_mask & (1 << sci_phy_get_index(iphy)))) - port_agent->phy_configured_mask |= (1 << sci_phy_get_index(iphy)); + if ((iport->active_phy_mask & (1 << iphy->phy_index))) + port_agent->phy_configured_mask |= (1 << iphy->phy_index); } /** @@ -404,10 +404,8 @@ static void sci_mpc_agent_link_down( * rebuilding the port with the phys that remain in the ready * state. */ - port_agent->phy_ready_mask &= - ~(1 << sci_phy_get_index(iphy)); - port_agent->phy_configured_mask &= - ~(1 << sci_phy_get_index(iphy)); + port_agent->phy_ready_mask &= ~(1 << iphy->phy_index); + port_agent->phy_configured_mask &= ~(1 << iphy->phy_index); /* * Check to see if there are more phys waiting to be @@ -643,7 +641,7 @@ static void sci_apc_agent_link_down( struct isci_port *iport, struct isci_phy *iphy) { - port_agent->phy_ready_mask &= ~(1 << sci_phy_get_index(iphy)); + port_agent->phy_ready_mask &= ~(1 << iphy->phy_index); if (!iport) return; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 8c752abb4331..85e54f542075 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -456,7 +456,7 @@ static void sci_remote_device_start_request(struct isci_remote_device *idev, sci_port_complete_io(iport, idev, ireq); else { kref_get(&idev->kref); - sci_remote_device_increment_request_count(idev); + idev->started_request_count++; } } @@ -636,7 +636,7 @@ enum sci_status sci_remote_device_complete_io(struct isci_host *ihost, * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ sci_change_state(sm, SCI_STP_DEV_AWAIT_RESET); - } else if (sci_remote_device_get_request_count(idev) == 0) + } else if (idev->started_request_count == 0) sci_change_state(sm, SCI_STP_DEV_IDLE); break; case SCI_SMP_DEV_CMD: @@ -650,10 +650,10 @@ enum sci_status sci_remote_device_complete_io(struct isci_host *ihost, if (status != SCI_SUCCESS) break; - if (sci_remote_device_get_request_count(idev) == 0) + if (idev->started_request_count == 0) sci_remote_node_context_destruct(&idev->rnc, - rnc_destruct_done, - idev); + rnc_destruct_done, + idev); break; } @@ -761,26 +761,17 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost, return status; } -/** - * - * @sci_dev: - * @request: - * - * This method takes the request and bulids an appropriate SCU context for the - * request and then requests the controller to post the request. none - */ -void sci_remote_device_post_request( - struct isci_remote_device *idev, - u32 request) +void sci_remote_device_post_request(struct isci_remote_device *idev, u32 request) { + struct isci_port *iport = idev->owning_port; u32 context; - context = sci_remote_device_build_command_context(idev, request); + context = request | + (ISCI_PEG << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + idev->rnc.remote_node_index; - sci_controller_post_request( - sci_remote_device_get_controller(idev), - context - ); + sci_controller_post_request(iport->owning_controller, context); } /* called once the remote node context has transisitioned to a @@ -893,7 +884,7 @@ static void sci_remote_device_stopped_state_enter(struct sci_base_state_machine static void sci_remote_device_starting_state_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = sci_remote_device_get_controller(idev); + struct isci_host *ihost = idev->owning_port->owning_controller; isci_remote_device_not_ready(ihost, idev, SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); @@ -961,7 +952,7 @@ static void sci_stp_remote_device_ready_idle_substate_enter(struct sci_base_stat static void sci_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = sci_remote_device_get_controller(idev); + struct isci_host *ihost = idev->owning_port->owning_controller; BUG_ON(idev->working_request == NULL); @@ -972,7 +963,7 @@ static void sci_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state static void sci_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = sci_remote_device_get_controller(idev); + struct isci_host *ihost = idev->owning_port->owning_controller; if (idev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) isci_remote_device_not_ready(ihost, idev, @@ -982,7 +973,7 @@ static void sci_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = sci_remote_device_get_controller(idev); + struct isci_host *ihost = idev->owning_port->owning_controller; isci_remote_device_ready(ihost, idev); } @@ -990,7 +981,7 @@ static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_stat static void sci_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); - struct isci_host *ihost = sci_remote_device_get_controller(idev); + struct isci_host *ihost = idev->owning_port->owning_controller; BUG_ON(idev->working_request == NULL); diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index fa9a0e6cc309..57ccfc3d6ad3 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h @@ -305,91 +305,18 @@ static inline bool dev_is_expander(struct domain_device *dev) return dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV; } -/** - * sci_remote_device_increment_request_count() - - * - * This macro incrments the request count for this device - */ -#define sci_remote_device_increment_request_count(idev) \ - ((idev)->started_request_count++) - -/** - * sci_remote_device_decrement_request_count() - - * - * This macro decrements the request count for this device. This count will - * never decrment past 0. - */ -#define sci_remote_device_decrement_request_count(idev) \ - ((idev)->started_request_count > 0 ? \ - (idev)->started_request_count-- : 0) - -/** - * sci_remote_device_get_request_count() - - * - * This is a helper macro to return the current device request count. - */ -#define sci_remote_device_get_request_count(idev) \ - ((idev)->started_request_count) - -/** - * sci_remote_device_get_controller() - - * - * This macro returns the controller object that contains this device object - */ -#define sci_remote_device_get_controller(idev) \ - sci_port_get_controller(sci_remote_device_get_port(idev)) - -/** - * sci_remote_device_get_port() - - * - * This macro returns the owning port of this device - */ -#define sci_remote_device_get_port(idev) \ - ((idev)->owning_port) - -/** - * sci_remote_device_get_controller_peg() - - * - * This macro returns the controllers protocol engine group - */ -#define sci_remote_device_get_controller_peg(idev) \ - (\ - sci_controller_get_protocol_engine_group(\ - sci_port_get_controller(\ - sci_remote_device_get_port(idev) \ - ) \ - ) \ - ) - -/** - * sci_remote_device_get_index() - - * - * This macro returns the remote node index for this device object - */ -#define sci_remote_device_get_index(idev) \ - ((idev)->rnc.remote_node_index) - -/** - * sci_remote_device_build_command_context() - - * - * This macro builds a remote device context for the SCU post request operation - */ -#define sci_remote_device_build_command_context(device, command) \ - ((command) \ - | (sci_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \ - | ((device)->owning_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \ - | (sci_remote_device_get_index((device))) \ - ) - -/** - * sci_remote_device_set_working_request() - - * - * This macro makes the working request assingment for the remote device - * object. To clear the working request use this macro with a NULL request - * object. - */ -#define sci_remote_device_set_working_request(device, request) \ - ((device)->working_request = (request)) +static inline void sci_remote_device_decrement_request_count(struct isci_remote_device *idev) +{ + /* XXX delete this voodoo when converting to the top-level device + * reference count + */ + if (WARN_ONCE(idev->started_request_count == 0, + "%s: tried to decrement started_request_count past 0!?", + __func__)) + /* pass */; + else + idev->started_request_count--; +} enum sci_status sci_remote_device_frame_handler( struct isci_remote_device *idev, diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index c2dfd5a72181..748e8339d1ec 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -111,7 +111,7 @@ static void sci_remote_node_context_construct_buffer(struct sci_remote_node_cont struct isci_host *ihost; __le64 sas_addr; - ihost = sci_remote_device_get_controller(idev); + ihost = idev->owning_port->owning_controller; rnc = sci_rnc_by_id(ihost, rni); memset(rnc, 0, sizeof(union scu_remote_node_context) diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index b475c5c26642..41580ad12520 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h @@ -204,9 +204,6 @@ void sci_remote_node_context_construct(struct sci_remote_node_context *rnc, bool sci_remote_node_context_is_ready( struct sci_remote_node_context *sci_rnc); -#define sci_remote_node_context_get_remote_node_index(rcn) \ - ((rnc)->remote_node_index) - enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_context *sci_rnc, u32 event_code); enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context *sci_rnc, diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index bcb3c08c19a7..7c500bb6a8e0 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -211,22 +211,21 @@ static void scu_ssp_reqeust_construct_task_context( struct isci_remote_device *idev; struct isci_port *iport; - idev = sci_request_get_device(ireq); - iport = sci_request_get_port(ireq); + idev = ireq->target_device; + iport = idev->owning_port; /* Fill in the TC with the its required data */ task_context->abort = 0; task_context->priority = 0; task_context->initiator_request = 1; task_context->connection_rate = idev->connection_rate; - task_context->protocol_engine_index = - sci_controller_get_protocol_engine_group(controller); - task_context->logical_port_index = sci_port_get_index(iport); + task_context->protocol_engine_index = ISCI_PEG; + task_context->logical_port_index = iport->physical_port_index; task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; - task_context->remote_node_index = sci_remote_device_get_index(idev); + task_context->remote_node_index = idev->rnc.remote_node_index; task_context->command_code = 0; task_context->link_layer_control = 0; @@ -242,9 +241,8 @@ static void scu_ssp_reqeust_construct_task_context( task_context->task_phase = 0x01; ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (sci_controller_get_protocol_engine_group(controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (sci_port_get_index(iport) << + (ISCI_PEG << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | ISCI_TAG_TCI(ireq->io_tag)); @@ -349,23 +347,21 @@ static void scu_sata_reqeust_construct_task_context( struct isci_remote_device *idev; struct isci_port *iport; - idev = sci_request_get_device(ireq); - iport = sci_request_get_port(ireq); + idev = ireq->target_device; + iport = idev->owning_port; /* Fill in the TC with the its required data */ task_context->abort = 0; task_context->priority = SCU_TASK_PRIORITY_NORMAL; task_context->initiator_request = 1; task_context->connection_rate = idev->connection_rate; - task_context->protocol_engine_index = - sci_controller_get_protocol_engine_group(controller); - task_context->logical_port_index = - sci_port_get_index(iport); + task_context->protocol_engine_index = ISCI_PEG; + task_context->logical_port_index = iport->physical_port_index; task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; - task_context->remote_node_index = sci_remote_device_get_index(idev); + task_context->remote_node_index = idev->rnc.remote_node_index; task_context->command_code = 0; task_context->link_layer_control = 0; @@ -385,11 +381,10 @@ static void scu_sata_reqeust_construct_task_context( task_context->type.words[0] = *(u32 *)&ireq->stp.cmd; ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (sci_controller_get_protocol_engine_group(controller) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (sci_port_get_index(iport) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(ireq->io_tag)); + (ISCI_PEG << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (iport->physical_port_index << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + ISCI_TAG_TCI(ireq->io_tag)); /* * Copy the physical address for the command buffer to the SCU Task * Context. We must offset the command buffer by 4 bytes because the @@ -716,10 +711,8 @@ sci_io_request_terminate(struct isci_request *ireq) switch (state) { case SCI_REQ_CONSTRUCTED: - sci_request_set_status(ireq, - SCU_TASK_DONE_TASK_ABORT, - SCI_FAILURE_IO_TERMINATED); - + ireq->scu_status = SCU_TASK_DONE_TASK_ABORT; + ireq->sci_status = SCI_FAILURE_IO_TERMINATED; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; case SCI_REQ_STARTED: @@ -848,9 +841,8 @@ request_started_state_tc_event(struct isci_request *ireq, */ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - sci_request_set_status(ireq, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS); + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): { /* There are times when the SCU hardware will return an early @@ -868,13 +860,11 @@ request_started_state_tc_event(struct isci_request *ireq, word_cnt); if (resp->status == 0) { - sci_request_set_status(ireq, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS_IO_DONE_EARLY); + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS_IO_DONE_EARLY; } else { - sci_request_set_status(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; } break; } @@ -885,9 +875,8 @@ request_started_state_tc_event(struct isci_request *ireq, &ireq->ssp.rsp, word_cnt); - sci_request_set_status(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; break; } @@ -900,13 +889,12 @@ request_started_state_tc_event(struct isci_request *ireq, datapres = resp_iu->datapres; if (datapres == 1 || datapres == 2) { - sci_request_set_status(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - } else - sci_request_set_status(ireq, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS); + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; + } else { + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; + } break; /* only stp device gets suspended. */ case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): @@ -921,15 +909,13 @@ request_started_state_tc_event(struct isci_request *ireq, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): if (ireq->protocol == SCIC_STP_PROTOCOL) { - sci_request_set_status(ireq, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); + ireq->scu_status = SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT; + ireq->sci_status = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; } else { - sci_request_set_status(ireq, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + ireq->scu_status = SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT; + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; } break; @@ -944,10 +930,9 @@ request_started_state_tc_event(struct isci_request *ireq, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): - sci_request_set_status(ireq, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED); + ireq->scu_status = SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT; + ireq->sci_status = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; break; /* neither ssp nor stp gets suspended. */ @@ -967,11 +952,9 @@ request_started_state_tc_event(struct isci_request *ireq, case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): default: - sci_request_set_status( - ireq, - SCU_GET_COMPLETION_TL_STATUS(completion_code) >> - SCU_COMPLETION_TL_STATUS_SHIFT, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + ireq->scu_status = SCU_GET_COMPLETION_TL_STATUS(completion_code) >> + SCU_COMPLETION_TL_STATUS_SHIFT; + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; break; } @@ -991,9 +974,8 @@ request_aborting_state_tc_event(struct isci_request *ireq, switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): - sci_request_set_status(ireq, SCU_TASK_DONE_TASK_ABORT, - SCI_FAILURE_IO_TERMINATED); - + ireq->scu_status = SCU_TASK_DONE_TASK_ABORT; + ireq->sci_status = SCI_FAILURE_IO_TERMINATED; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; @@ -1012,9 +994,8 @@ static enum sci_status ssp_task_request_await_tc_event(struct isci_request *ireq { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; sci_change_state(&ireq->sm, SCI_REQ_TASK_WAIT_TC_RESP); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): @@ -1036,10 +1017,8 @@ static enum sci_status ssp_task_request_await_tc_event(struct isci_request *ireq * If a NAK was received, then it is up to the user to retry * the request. */ - sci_request_set_status(ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1057,12 +1036,10 @@ smp_request_await_response_tc_event(struct isci_request *ireq, * unexpected. but if the TC has success status, we * complete the IO anyway. */ - sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; - case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): @@ -1074,20 +1051,16 @@ smp_request_await_response_tc_event(struct isci_request *ireq, * these SMP_XXX_XX_ERR status. For these type of error, * we ask ihost user to retry the request. */ - sci_request_set_status(ireq, SCU_TASK_DONE_SMP_RESP_TO_ERR, - SCI_FAILURE_RETRY_REQUIRED); - + ireq->scu_status = SCU_TASK_DONE_SMP_RESP_TO_ERR; + ireq->sci_status = SCI_FAILURE_RETRY_REQUIRED; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; - default: /* All other completion status cause the IO to be complete. If a NAK * was received, then it is up to the user to retry the request */ - sci_request_set_status(ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1101,9 +1074,8 @@ smp_request_await_tc_event(struct isci_request *ireq, { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; default: @@ -1111,10 +1083,8 @@ smp_request_await_tc_event(struct isci_request *ireq, * complete. If a NAK was received, then it is up to * the user to retry the request. */ - sci_request_set_status(ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1171,9 +1141,8 @@ stp_request_non_data_await_h2d_tc_event(struct isci_request *ireq, { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; sci_change_state(&ireq->sm, SCI_REQ_STP_NON_DATA_WAIT_D2H); break; @@ -1182,10 +1151,8 @@ stp_request_non_data_await_h2d_tc_event(struct isci_request *ireq, * complete. If a NAK was received, then it is up to * the user to retry the request. */ - sci_request_set_status(ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1363,10 +1330,8 @@ stp_request_pio_await_h2d_completion_tc_event(struct isci_request *ireq, switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - sci_request_set_status(ireq, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_WAIT_FRAME); break; @@ -1375,10 +1340,8 @@ stp_request_pio_await_h2d_completion_tc_event(struct isci_request *ireq, * complete. If a NAK was received, then it is up to * the user to retry the request. */ - sci_request_set_status(ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1426,11 +1389,8 @@ pio_data_out_tx_done_tc_event(struct isci_request *ireq, * If a NAK was received, then it is up to the user to retry * the request. */ - sci_request_set_status( - ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1438,15 +1398,6 @@ pio_data_out_tx_done_tc_event(struct isci_request *ireq, return status; } -static void sci_stp_request_udma_complete_request( - struct isci_request *ireq, - u32 scu_status, - enum sci_status sci_status) -{ - sci_request_set_status(ireq, scu_status, sci_status); - sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); -} - static enum sci_status sci_stp_request_udma_general_frame_handler(struct isci_request *ireq, u32 frame_index) { @@ -1512,13 +1463,12 @@ sci_io_request_frame_handler(struct isci_request *ireq, if (resp_iu->datapres == 0x01 || resp_iu->datapres == 0x02) { - sci_request_set_status(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - } else - sci_request_set_status(ireq, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS); + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; + } else { + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; + } } else { /* not a response frame, why did it get forwarded? */ dev_err(&ihost->pdev->dev, @@ -1567,9 +1517,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, smp_resp, word_cnt); - sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; sci_change_state(&ireq->sm, SCI_REQ_SMP_WAIT_TC_COMP); } else { /* @@ -1584,10 +1533,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_index, rsp_hdr->frame_type); - sci_request_set_status(ireq, - SCU_TASK_DONE_SMP_FRM_TYPE_ERR, - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR; + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } @@ -1602,16 +1549,14 @@ sci_io_request_frame_handler(struct isci_request *ireq, case SCI_REQ_STP_UDMA_WAIT_D2H: /* Use the general frame handler to copy the resposne data */ - status = sci_stp_request_udma_general_frame_handler(ireq, - frame_index); + status = sci_stp_request_udma_general_frame_handler(ireq, frame_index); if (status != SCI_SUCCESS) return status; - sci_stp_request_udma_complete_request(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); return SCI_SUCCESS; case SCI_REQ_STP_NON_DATA_WAIT_D2H: { @@ -1645,8 +1590,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_buffer); /* The command has completed with error */ - sci_request_set_status(ireq, SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; break; default: @@ -1655,8 +1600,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, "violation occurred\n", __func__, stp_req, frame_index); - sci_request_set_status(ireq, SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); + ireq->scu_status = SCU_TASK_DONE_UNEXP_FIS; + ireq->sci_status = SCI_FAILURE_PROTOCOL_VIOLATION; break; } @@ -1753,10 +1698,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_header, frame_buffer); - sci_request_set_status(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; @@ -1800,10 +1743,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_index, frame_header->fis_type); - sci_request_set_status(ireq, - SCU_TASK_DONE_GOOD, - SCI_FAILURE_IO_REQUIRES_SCSI_ABORT); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); /* Frame is decoded return it to the controller */ @@ -1833,10 +1774,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, return status; if ((stp_req->status & ATA_BUSY) == 0) { - sci_request_set_status(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); - + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } else { sci_change_state(&ireq->sm, SCI_REQ_STP_PIO_WAIT_FRAME); @@ -1873,9 +1812,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_buffer); /* The command has completed with error */ - sci_request_set_status(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; break; default: @@ -1886,9 +1824,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, stp_req, frame_index); - sci_request_set_status(ireq, - SCU_TASK_DONE_UNEXP_FIS, - SCI_FAILURE_PROTOCOL_VIOLATION); + ireq->scu_status = SCU_TASK_DONE_UNEXP_FIS; + ireq->sci_status = SCI_FAILURE_PROTOCOL_VIOLATION; break; } @@ -1927,9 +1864,9 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - sci_stp_request_udma_complete_request(ireq, - SCU_TASK_DONE_GOOD, - SCI_SUCCESS); + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): @@ -1941,9 +1878,9 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq sci_remote_device_suspend(ireq->target_device, SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code))); - sci_stp_request_udma_complete_request(ireq, - SCU_TASK_DONE_CHECK_RESPONSE, - SCI_FAILURE_IO_RESPONSE_VALID); + ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; + ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } else { /* If we have an error completion status for the * TC then we can expect a D2H register FIS from @@ -1970,9 +1907,9 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq /* Fall through to the default case */ default: /* All other completion status cause the IO to be complete. */ - sci_stp_request_udma_complete_request(ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; + sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -1985,9 +1922,8 @@ stp_request_soft_reset_await_h2d_asserted_tc_event(struct isci_request *ireq, { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; sci_change_state(&ireq->sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG); break; @@ -1997,10 +1933,8 @@ stp_request_soft_reset_await_h2d_asserted_tc_event(struct isci_request *ireq, * If a NAK was received, then it is up to the user to retry * the request. */ - sci_request_set_status(ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -2014,9 +1948,8 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq, { switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): - sci_request_set_status(ireq, SCU_TASK_DONE_GOOD, - SCI_SUCCESS); - + ireq->scu_status = SCU_TASK_DONE_GOOD; + ireq->sci_status = SCI_SUCCESS; sci_change_state(&ireq->sm, SCI_REQ_STP_SOFT_RESET_WAIT_D2H); break; @@ -2025,10 +1958,8 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq, * a NAK was received, then it is up to the user to retry the * request. */ - sci_request_set_status(ireq, - SCU_NORMALIZE_COMPLETION_STATUS(completion_code), - SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR); - + ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); + ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); break; } @@ -2504,7 +2435,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost, completion_status); spin_lock(&request->state_lock); - request_status = isci_request_get_state(request); + request_status = request->status; /* Decode the request status. Note that if the request has been * aborted by a task management function, we don't care @@ -2904,24 +2835,21 @@ static void sci_stp_request_started_non_data_await_h2d_completion_enter(struct s { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - sci_remote_device_set_working_request(ireq->target_device, - ireq); + ireq->target_device->working_request = ireq; } static void sci_stp_request_started_pio_await_h2d_completion_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - sci_remote_device_set_working_request(ireq->target_device, - ireq); + ireq->target_device->working_request = ireq; } static void sci_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(struct sci_base_state_machine *sm) { struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - sci_remote_device_set_working_request(ireq->target_device, - ireq); + ireq->target_device->working_request = ireq; } static void sci_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(struct sci_base_state_machine *sm) @@ -3141,8 +3069,8 @@ sci_io_request_construct_smp(struct device *dev, task_context = ireq->tc; - idev = sci_request_get_device(ireq); - iport = sci_request_get_port(ireq); + idev = ireq->target_device; + iport = idev->owning_port; /* * Fill in the TC with the its required data @@ -3151,9 +3079,8 @@ sci_io_request_construct_smp(struct device *dev, task_context->priority = 0; task_context->initiator_request = 1; task_context->connection_rate = idev->connection_rate; - task_context->protocol_engine_index = - sci_controller_get_protocol_engine_group(ihost); - task_context->logical_port_index = sci_port_get_index(iport); + task_context->protocol_engine_index = ISCI_PEG; + task_context->logical_port_index = iport->physical_port_index; task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; task_context->abort = 0; task_context->valid = SCU_TASK_CONTEXT_VALID; @@ -3195,11 +3122,10 @@ sci_io_request_construct_smp(struct device *dev, task_context->task_phase = 0; ireq->post_context = (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | - (sci_controller_get_protocol_engine_group(ihost) << - SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | - (sci_port_get_index(iport) << - SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | - ISCI_TAG_TCI(ireq->io_tag)); + (ISCI_PEG << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) | + (iport->physical_port_index << + SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) | + ISCI_TAG_TCI(ireq->io_tag)); /* * Copy the physical address for the command buffer to the SCU Task * Context command buffer should not contain command header. diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 08fcf98e70f4..597084027819 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -300,58 +300,6 @@ enum sci_base_request_states { SCI_REQ_FINAL, }; -/** - * sci_request_get_controller() - - * - * This macro will return the controller for this io request object - */ -#define sci_request_get_controller(ireq) \ - ((ireq)->owning_controller) - -/** - * sci_request_get_device() - - * - * This macro will return the device for this io request object - */ -#define sci_request_get_device(ireq) \ - ((ireq)->target_device) - -/** - * sci_request_get_port() - - * - * This macro will return the port for this io request object - */ -#define sci_request_get_port(ireq) \ - sci_remote_device_get_port(sci_request_get_device(ireq)) - -/** - * sci_request_get_post_context() - - * - * This macro returns the constructed post context result for the io request. - */ -#define sci_request_get_post_context(ireq) \ - ((ireq)->post_context) - -/** - * sci_request_get_task_context() - - * - * This is a helper macro to return the os handle for this request object. - */ -#define sci_request_get_task_context(request) \ - ((request)->task_context_buffer) - -/** - * sci_request_set_status() - - * - * This macro will set the scu hardware status and sci request completion - * status for an io request. - */ -#define sci_request_set_status(request, scu_status_code, sci_status_code) \ - { \ - (request)->scu_status = (scu_status_code); \ - (request)->sci_status = (sci_status_code); \ - } - enum sci_status sci_request_start(struct isci_request *ireq); enum sci_status sci_io_request_terminate(struct isci_request *ireq); enum sci_status @@ -381,27 +329,6 @@ sci_io_request_get_dma_addr(struct isci_request *ireq, void *virt_addr) return ireq->request_daddr + (requested_addr - base_addr); } -/** - * This function gets the status of the request object. - * @request: This parameter points to the isci_request object - * - * status of the object as a isci_request_status enum. - */ -static inline enum isci_request_status -isci_request_get_state(struct isci_request *isci_request) -{ - BUG_ON(isci_request == NULL); - - /*probably a bad sign... */ - if (isci_request->status == unallocated) - dev_warn(&isci_request->isci_host->pdev->dev, - "%s: isci_request->status == unallocated\n", - __func__); - - return isci_request->status; -} - - /** * isci_request_change_state() - This function sets the status of the request * object. diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index d040aa2f3722..20112cd5b646 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -654,7 +654,7 @@ static void isci_terminate_request_core(struct isci_host *ihost, * needs to be detached and freed here. */ spin_lock_irqsave(&isci_request->state_lock, flags); - request_status = isci_request_get_state(isci_request); + request_status = isci_request->status; if ((isci_request->ttype == io_task) /* TMFs are in their own thread */ && ((request_status == aborted) -- cgit v1.2.3 From 16ba77091b44af28b3ff3318b4a2aa4fbf7d4c24 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 1 Jul 2011 10:52:55 -0700 Subject: isci: merge sata.[ch] into request.c Undo some needless separation. Signed-off-by: Dan Williams --- drivers/scsi/isci/Makefile | 2 +- drivers/scsi/isci/request.c | 71 ++++++++------ drivers/scsi/isci/request.h | 2 - drivers/scsi/isci/sata.c | 232 -------------------------------------------- drivers/scsi/isci/sata.h | 79 --------------- drivers/scsi/isci/task.c | 100 +++++++++++++++---- drivers/scsi/isci/task.h | 12 --- 7 files changed, 120 insertions(+), 378 deletions(-) delete mode 100644 drivers/scsi/isci/sata.c delete mode 100644 drivers/scsi/isci/sata.h diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 42449701ad9e..3359e10e0d8f 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_SCSI_ISCI) += isci.o -isci-objs := init.o phy.o request.o sata.o \ +isci-objs := init.o phy.o request.o \ remote_device.o port.o \ host.o task.o probe_roms.o \ remote_node_context.o \ diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 7c500bb6a8e0..33c8ed1741e6 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -56,7 +56,6 @@ #include "isci.h" #include "task.h" #include "request.h" -#include "sata.h" #include "scu_completion_codes.h" #include "scu_event_codes.h" #include "sas.h" @@ -1092,16 +1091,6 @@ smp_request_await_tc_event(struct isci_request *ireq, return SCI_SUCCESS; } -void sci_stp_io_request_set_ncq_tag(struct isci_request *ireq, - u16 ncq_tag) -{ - /** - * @note This could be made to return an error to the user if the user - * attempts to set the NCQ tag in the wrong state. - */ - ireq->tc->type.stp.ncq_tag = ncq_tag; -} - static struct scu_sgl_element *pio_sgl_next(struct isci_stp_request *stp_req) { struct scu_sgl_element *sgl; @@ -2410,6 +2399,29 @@ static void isci_task_save_for_upper_layer_completion( } } +static void isci_request_process_stp_response(struct sas_task *task, + void *response_buffer) +{ + struct dev_to_host_fis *d2h_reg_fis = response_buffer; + struct task_status_struct *ts = &task->task_status; + struct ata_task_resp *resp = (void *)&ts->buf[0]; + + resp->frame_len = le16_to_cpu(*(__le16 *)(response_buffer + 6)); + memcpy(&resp->ending_fis[0], response_buffer + 16, 24); + ts->buf_valid_size = sizeof(*resp); + + /** + * If the device fault bit is set in the status register, then + * set the sense data and return. + */ + if (d2h_reg_fis->status & ATA_DF) + ts->stat = SAS_PROTO_RESPONSE; + else + ts->stat = SAM_STAT_GOOD; + + ts->resp = SAS_TASK_COMPLETE; +} + static void isci_request_io_request_complete(struct isci_host *ihost, struct isci_request *request, enum sci_io_status completion_status) @@ -2985,34 +2997,29 @@ static enum sci_status isci_request_ssp_request_construct( return status; } -static enum sci_status isci_request_stp_request_construct( - struct isci_request *request) +static enum sci_status isci_request_stp_request_construct(struct isci_request *ireq) { - struct sas_task *task = isci_request_access_task(request); + struct sas_task *task = isci_request_access_task(ireq); + struct host_to_dev_fis *fis = &ireq->stp.cmd; + struct ata_queued_cmd *qc = task->uldd_task; enum sci_status status; - struct host_to_dev_fis *register_fis; - dev_dbg(&request->isci_host->pdev->dev, - "%s: request = %p\n", + dev_dbg(&ireq->isci_host->pdev->dev, + "%s: ireq = %p\n", __func__, - request); - - /* Get the host_to_dev_fis from the core and copy - * the fis from the task into it. - */ - register_fis = isci_sata_task_to_fis_copy(task); + ireq); - status = sci_io_request_construct_basic_sata(request); + memcpy(fis, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); + if (!task->ata_task.device_control_reg_update) + fis->flags |= 0x80; + fis->flags &= 0xF0; - /* Set the ncq tag in the fis, from the queue - * command in the task. - */ - if (isci_sata_is_task_ncq(task)) { + status = sci_io_request_construct_basic_sata(ireq); - isci_sata_set_ncq_tag( - register_fis, - task - ); + if (qc && (qc->tf.command == ATA_CMD_FPDMA_WRITE || + qc->tf.command == ATA_CMD_FPDMA_READ)) { + fis->sector_count = qc->tag << 3; + ireq->tc->type.stp.ncq_tag = qc->tag; } return status; diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 597084027819..11bc279457aa 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -435,8 +435,6 @@ enum sci_status sci_task_request_construct_ssp(struct isci_request *ireq); enum sci_status sci_task_request_construct_sata(struct isci_request *ireq); -void -sci_stp_io_request_set_ncq_tag(struct isci_request *ireq, u16 ncq_tag); void sci_smp_request_copy_response(struct isci_request *ireq); static inline int isci_task_is_ncq_recovery(struct sas_task *task) diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c deleted file mode 100644 index 47b96c21548f..000000000000 --- a/drivers/scsi/isci/sata.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "isci.h" -#include "remote_device.h" -#include "task.h" -#include "request.h" -#include "sata.h" - -/** - * isci_sata_task_to_fis_copy() - This function gets the host_to_dev_fis from - * the core and copies the fis from the task into it. - * @task: This parameter is a pointer to the task struct from libsas. - * - * pointer to the host_to_dev_fis from the core request object. - */ -struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task) -{ - struct isci_request *ireq = task->lldd_task; - struct host_to_dev_fis *fis = &ireq->stp.cmd; - - memcpy(fis, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); - - if (!task->ata_task.device_control_reg_update) - fis->flags |= 0x80; - - fis->flags &= 0xF0; - - return fis; -} - -/** - * isci_sata_is_task_ncq() - This function determines if the given stp task is - * a ncq request. - * @task: This parameter is a pointer to the task struct from libsas. - * - * true if the task is ncq - */ -bool isci_sata_is_task_ncq(struct sas_task *task) -{ - struct ata_queued_cmd *qc = task->uldd_task; - - bool ret = (qc && - (qc->tf.command == ATA_CMD_FPDMA_WRITE || - qc->tf.command == ATA_CMD_FPDMA_READ)); - - return ret; -} - -/** - * isci_sata_set_ncq_tag() - This function sets the ncq tag field in the - * host_to_dev_fis equal to the tag in the queue command in the task. - * @task: This parameter is a pointer to the task struct from libsas. - * @register_fis: This parameter is a pointer to the host_to_dev_fis from the - * core request object. - * - */ -void isci_sata_set_ncq_tag( - struct host_to_dev_fis *register_fis, - struct sas_task *task) -{ - struct ata_queued_cmd *qc = task->uldd_task; - struct isci_request *request = task->lldd_task; - - register_fis->sector_count = qc->tag << 3; - sci_stp_io_request_set_ncq_tag(request, qc->tag); -} - -/** - * isci_request_process_stp_response() - This function sets the status and - * response, in the task struct, from the request object for the upper layer - * driver. - * @sas_task: This parameter is the task struct from the upper layer driver. - * @response_buffer: This parameter points to the response of the completed - * request. - * - * none. - */ -void isci_request_process_stp_response(struct sas_task *task, - void *response_buffer) -{ - struct dev_to_host_fis *d2h_reg_fis = response_buffer; - struct task_status_struct *ts = &task->task_status; - struct ata_task_resp *resp = (void *)&ts->buf[0]; - - resp->frame_len = le16_to_cpu(*(__le16 *)(response_buffer + 6)); - memcpy(&resp->ending_fis[0], response_buffer + 16, 24); - ts->buf_valid_size = sizeof(*resp); - - /** - * If the device fault bit is set in the status register, then - * set the sense data and return. - */ - if (d2h_reg_fis->status & ATA_DF) - ts->stat = SAS_PROTO_RESPONSE; - else - ts->stat = SAM_STAT_GOOD; - - ts->resp = SAS_TASK_COMPLETE; -} - -enum sci_status isci_sata_management_task_request_build(struct isci_request *ireq) -{ - struct isci_tmf *isci_tmf; - enum sci_status status; - - if (tmf_task != ireq->ttype) - return SCI_FAILURE; - - isci_tmf = isci_request_access_tmf(ireq); - - switch (isci_tmf->tmf_code) { - - case isci_tmf_sata_srst_high: - case isci_tmf_sata_srst_low: { - struct host_to_dev_fis *fis = &ireq->stp.cmd; - - memset(fis, 0, sizeof(*fis)); - - fis->fis_type = 0x27; - fis->flags &= ~0x80; - fis->flags &= 0xF0; - if (isci_tmf->tmf_code == isci_tmf_sata_srst_high) - fis->control |= ATA_SRST; - else - fis->control &= ~ATA_SRST; - break; - } - /* other management commnd go here... */ - default: - return SCI_FAILURE; - } - - /* core builds the protocol specific request - * based on the h2d fis. - */ - status = sci_task_request_construct_sata(ireq); - - return status; -} - -/** - * isci_task_send_lu_reset_sata() - This function is called by of the SAS - * Domain Template functions. This is one of the Task Management functoins - * called by libsas, to reset the given SAS lun. Note the assumption that - * while this call is executing, no I/O will be sent by the host to the - * device. - * @lun: This parameter specifies the lun to be reset. - * - * status, zero indicates success. - */ -int isci_task_send_lu_reset_sata( - struct isci_host *isci_host, - struct isci_remote_device *isci_device, - u8 *lun) -{ - struct isci_tmf tmf; - int ret = TMF_RESP_FUNC_FAILED; - - /* Send the soft reset to the target */ - #define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */ - isci_task_build_tmf(&tmf, isci_tmf_sata_srst_high, NULL, NULL); - - ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, - ISCI_SRST_TIMEOUT_MS); - - if (ret != TMF_RESP_FUNC_COMPLETE) { - dev_warn(&isci_host->pdev->dev, - "%s: Assert SRST failed (%p) = %x", - __func__, - isci_device, - ret); - - /* Return the failure so that the LUN reset is escalated - * to a target reset. - */ - } - return ret; -} diff --git a/drivers/scsi/isci/sata.h b/drivers/scsi/isci/sata.h deleted file mode 100644 index 1b89f1f75770..000000000000 --- a/drivers/scsi/isci/sata.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -struct host_to_dev_fis *isci_sata_task_to_fis_copy( - struct sas_task *task); - -bool isci_sata_is_task_ncq( - struct sas_task *task); - -void isci_sata_set_ncq_tag( - struct host_to_dev_fis *register_fis, - struct sas_task *task); - -void isci_request_process_stp_response( - struct sas_task *task, - void *response_buffer); - -u8 isci_sata_get_sat_protocol( - struct isci_request *isci_request); - -enum sci_status isci_sata_management_task_request_build( - struct isci_request *isci_request); - -int isci_task_send_lu_reset_sata( - struct isci_host *isci_host, - struct isci_remote_device *isci_device, - u8 *lun); diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 20112cd5b646..5d962b6b03eb 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -61,7 +61,6 @@ #include "remote_node_context.h" #include "isci.h" #include "request.h" -#include "sata.h" #include "task.h" #include "host.h" @@ -238,6 +237,46 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) return 0; } +static enum sci_status isci_sata_management_task_request_build(struct isci_request *ireq) +{ + struct isci_tmf *isci_tmf; + enum sci_status status; + + if (tmf_task != ireq->ttype) + return SCI_FAILURE; + + isci_tmf = isci_request_access_tmf(ireq); + + switch (isci_tmf->tmf_code) { + + case isci_tmf_sata_srst_high: + case isci_tmf_sata_srst_low: { + struct host_to_dev_fis *fis = &ireq->stp.cmd; + + memset(fis, 0, sizeof(*fis)); + + fis->fis_type = 0x27; + fis->flags &= ~0x80; + fis->flags &= 0xF0; + if (isci_tmf->tmf_code == isci_tmf_sata_srst_high) + fis->control |= ATA_SRST; + else + fis->control &= ~ATA_SRST; + break; + } + /* other management commnd go here... */ + default: + return SCI_FAILURE; + } + + /* core builds the protocol specific request + * based on the h2d fis. + */ + status = sci_task_request_construct_sata(ireq); + + return status; +} + static struct isci_request *isci_task_request_build(struct isci_host *ihost, struct isci_remote_device *idev, u16 tag, struct isci_tmf *isci_tmf) @@ -287,9 +326,9 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, return ireq; } -int isci_task_execute_tmf(struct isci_host *ihost, - struct isci_remote_device *idev, - struct isci_tmf *tmf, unsigned long timeout_ms) +static int isci_task_execute_tmf(struct isci_host *ihost, + struct isci_remote_device *idev, + struct isci_tmf *tmf, unsigned long timeout_ms) { DECLARE_COMPLETION_ONSTACK(completion); enum sci_task_status status = SCI_TASK_FAILURE; @@ -401,13 +440,12 @@ int isci_task_execute_tmf(struct isci_host *ihost, return ret; } -void isci_task_build_tmf( - struct isci_tmf *tmf, - enum isci_tmf_function_codes code, - void (*tmf_sent_cb)(enum isci_tmf_cb_state, - struct isci_tmf *, - void *), - void *cb_data) +static void isci_task_build_tmf(struct isci_tmf *tmf, + enum isci_tmf_function_codes code, + void (*tmf_sent_cb)(enum isci_tmf_cb_state, + struct isci_tmf *, + void *), + void *cb_data) { memset(tmf, 0, sizeof(*tmf)); @@ -416,16 +454,14 @@ void isci_task_build_tmf( tmf->cb_data = cb_data; } -static void isci_task_build_abort_task_tmf( - struct isci_tmf *tmf, - enum isci_tmf_function_codes code, - void (*tmf_sent_cb)(enum isci_tmf_cb_state, - struct isci_tmf *, - void *), - struct isci_request *old_request) +static void isci_task_build_abort_task_tmf(struct isci_tmf *tmf, + enum isci_tmf_function_codes code, + void (*tmf_sent_cb)(enum isci_tmf_cb_state, + struct isci_tmf *, + void *), + struct isci_request *old_request) { - isci_task_build_tmf(tmf, code, tmf_sent_cb, - (void *)old_request); + isci_task_build_tmf(tmf, code, tmf_sent_cb, old_request); tmf->io_tag = old_request->io_tag; } @@ -804,6 +840,30 @@ static int isci_task_send_lu_reset_sas( return ret; } +static int isci_task_send_lu_reset_sata(struct isci_host *ihost, + struct isci_remote_device *idev, u8 *lun) +{ + int ret = TMF_RESP_FUNC_FAILED; + struct isci_tmf tmf; + + /* Send the soft reset to the target */ + #define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */ + isci_task_build_tmf(&tmf, isci_tmf_sata_srst_high, NULL, NULL); + + ret = isci_task_execute_tmf(ihost, idev, &tmf, ISCI_SRST_TIMEOUT_MS); + + if (ret != TMF_RESP_FUNC_COMPLETE) { + dev_warn(&ihost->pdev->dev, + "%s: Assert SRST failed (%p) = %x", + __func__, idev, ret); + + /* Return the failure so that the LUN reset is escalated + * to a target reset. + */ + } + return ret; +} + /** * isci_task_lu_reset() - This function is one of the SAS Domain Template * functions. This is one of the Task Management functoins called by libsas, diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index 42019de23805..4a7fa90287ef 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -211,18 +211,6 @@ int isci_queuecommand( int isci_bus_reset_handler(struct scsi_cmnd *cmd); -void isci_task_build_tmf( - struct isci_tmf *tmf, - enum isci_tmf_function_codes code, - void (*tmf_sent_cb)(enum isci_tmf_cb_state, - struct isci_tmf *, - void *), - void *cb_data); - -int isci_task_execute_tmf(struct isci_host *isci_host, - struct isci_remote_device *idev, - struct isci_tmf *tmf, unsigned long timeout_ms); - /** * enum isci_completion_selection - This enum defines the possible actions to * take with respect to a given request's notification back to libsas. -- cgit v1.2.3 From 4e4dca3de9658f364d34924e072f2b64e5c3d267 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 1 Jul 2011 11:15:12 -0700 Subject: isci: merge scu_unsolicited_frame.h into unsolicited_frame_control.h Does not need its own file. Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 1 - drivers/scsi/isci/host.h | 1 - drivers/scsi/isci/scu_unsolicited_frame.h | 117 -------------------------- drivers/scsi/isci/unsolicited_frame_control.h | 45 +++++++++- 4 files changed, 44 insertions(+), 120 deletions(-) delete mode 100644 drivers/scsi/isci/scu_unsolicited_frame.h diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 88e731333532..b554ea271ba6 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -67,7 +67,6 @@ #include "registers.h" #include "scu_remote_node_context.h" #include "scu_task_context.h" -#include "scu_unsolicited_frame.h" #define SCU_CONTEXT_RAM_INIT_STALL_TIME 200 diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index a72d2be2445d..ec0bba5367ba 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -60,7 +60,6 @@ #include "isci.h" #include "remote_node_table.h" #include "registers.h" -#include "scu_unsolicited_frame.h" #include "unsolicited_frame_control.h" #include "probe_roms.h" diff --git a/drivers/scsi/isci/scu_unsolicited_frame.h b/drivers/scsi/isci/scu_unsolicited_frame.h deleted file mode 100644 index 187c4f03f596..000000000000 --- a/drivers/scsi/isci/scu_unsolicited_frame.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * BSD LICENSE - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This field defines the SCU format of an unsolicited frame (UF). A UF is a - * frame received by the SCU for which there is no known corresponding task - * context (TC). - * - * - */ - -#ifndef _SCU_UNSOLICITED_FRAME_H_ -#define _SCU_UNSOLICITED_FRAME_H_ - -#include - -/** - * - * - * This constant defines the number of DWORDS found the unsolicited frame - * header data member. - */ -#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15 - -/** - * struct scu_unsolicited_frame_header - - * - * This structure delineates the format of an unsolicited frame header. The - * first DWORD are UF attributes defined by the silicon architecture. The data - * depicts actual header information received on the link. - */ -struct scu_unsolicited_frame_header { - /** - * This field indicates if there is an Initiator Index Table entry with - * which this header is associated. - */ - u32 iit_exists:1; - - /** - * This field simply indicates the protocol type (i.e. SSP, STP, SMP). - */ - u32 protocol_type:3; - - /** - * This field indicates if the frame is an address frame (IAF or OAF) - * or if it is a information unit frame. - */ - u32 is_address_frame:1; - - /** - * This field simply indicates the connection rate at which the frame - * was received. - */ - u32 connection_rate:4; - - u32 reserved:23; - - /** - * This field represents the actual header data received on the link. - */ - u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS]; - -}; - -#endif /* _SCU_UNSOLICITED_FRAME_H_ */ diff --git a/drivers/scsi/isci/unsolicited_frame_control.h b/drivers/scsi/isci/unsolicited_frame_control.h index b849a84af34f..31cb9506f52d 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.h +++ b/drivers/scsi/isci/unsolicited_frame_control.h @@ -57,7 +57,50 @@ #define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ #include "isci.h" -#include "scu_unsolicited_frame.h" + +#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15 + +/** + * struct scu_unsolicited_frame_header - + * + * This structure delineates the format of an unsolicited frame header. The + * first DWORD are UF attributes defined by the silicon architecture. The data + * depicts actual header information received on the link. + */ +struct scu_unsolicited_frame_header { + /** + * This field indicates if there is an Initiator Index Table entry with + * which this header is associated. + */ + u32 iit_exists:1; + + /** + * This field simply indicates the protocol type (i.e. SSP, STP, SMP). + */ + u32 protocol_type:3; + + /** + * This field indicates if the frame is an address frame (IAF or OAF) + * or if it is a information unit frame. + */ + u32 is_address_frame:1; + + /** + * This field simply indicates the connection rate at which the frame + * was received. + */ + u32 connection_rate:4; + + u32 reserved:23; + + /** + * This field represents the actual header data received on the link. + */ + u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS]; + +}; + + /** * enum unsolicited_frame_state - -- cgit v1.2.3 From dc00c8b6940aa10ab1ce6a4d10b1bfe7b848781b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 1 Jul 2011 11:41:21 -0700 Subject: isci: cleanup silicon revision detection Perform checking per-pci device (even though all systems will only have 1 pci device in this generation), and delete support for silicon that does not report a proper revision (i.e. A0). Reported-by: Christoph Hellwig Signed-off-by: Dan Williams --- drivers/scsi/isci/host.c | 31 +++++++++++++------------------ drivers/scsi/isci/host.h | 32 ++++++++++++-------------------- drivers/scsi/isci/init.c | 33 ++------------------------------- drivers/scsi/isci/phy.c | 2 +- drivers/scsi/isci/probe_roms.c | 6 +++--- 5 files changed, 31 insertions(+), 73 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index b554ea271ba6..26072f1e9852 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1886,6 +1886,7 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost, static void sci_controller_afe_initialization(struct isci_host *ihost) { const struct sci_oem_params *oem = &ihost->oem_parameters; + struct pci_dev *pdev = ihost->pdev; u32 afe_status; u32 phy_id; @@ -1893,7 +1894,7 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); - if (is_b0()) { + if (is_b0(pdev)) { /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement * Timer, PM Stagger Timer */ writel(0x0007BFFF, &ihost->scu_registers->afe.afe_pmsn_master_control2); @@ -1901,17 +1902,15 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) } /* Configure bias currents to normal */ - if (is_a0()) - writel(0x00005500, &ihost->scu_registers->afe.afe_bias_control); - else if (is_a2()) + if (is_a2(pdev)) writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control); - else if (is_b0() || is_c0()) + else if (is_b0(pdev) || is_c0(pdev)) writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable PLL */ - if (is_b0() || is_c0()) + if (is_b0(pdev) || is_c0(pdev)) writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0); else writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0); @@ -1924,7 +1923,7 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) udelay(AFE_REGISTER_WRITE_DELAY); } while ((afe_status & 0x00001000) == 0); - if (is_a0() || is_a2()) { + if (is_a2(pdev)) { /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); @@ -1933,11 +1932,11 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id]; - if (is_b0()) { + if (is_b0(pdev)) { /* Configure transmitter SSC parameters */ writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); - } else if (is_c0()) { + } else if (is_c0(pdev)) { /* Configure transmitter SSC parameters */ writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); @@ -1961,11 +1960,9 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) /* * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) * & increase TX int & ext bias 20%....(0xe85c) */ - if (is_a0()) - writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); - else if (is_a2()) + if (is_a2(pdev)) writel(0x000003F0, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); - else if (is_b0()) { + else if (is_b0(pdev)) { /* Power down TX and RX (PWRDNTX and PWRDNRX) */ writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); @@ -1985,7 +1982,7 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) } udelay(AFE_REGISTER_WRITE_DELAY); - if (is_a0() || is_a2()) { + if (is_a2(pdev)) { /* Enable TX equalization (0xe824) */ writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); udelay(AFE_REGISTER_WRITE_DELAY); @@ -1998,11 +1995,9 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) udelay(AFE_REGISTER_WRITE_DELAY); /* Leave DFE/FFE on */ - if (is_a0()) - writel(0x3F09983F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); - else if (is_a2()) + if (is_a2(pdev)) writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); - else if (is_b0()) { + else if (is_b0(pdev)) { writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable TX equalization (0xe824) */ diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index ec0bba5367ba..062101a39f79 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -416,33 +416,25 @@ static inline struct device *scirdev_to_dev(struct isci_remote_device *idev) return &idev->isci_port->isci_host->pdev->dev; } -enum { - ISCI_SI_REVA0, - ISCI_SI_REVA2, - ISCI_SI_REVB0, - ISCI_SI_REVC0 -}; - -extern int isci_si_rev; - -static inline bool is_a0(void) -{ - return isci_si_rev == ISCI_SI_REVA0; -} - -static inline bool is_a2(void) +static inline bool is_a2(struct pci_dev *pdev) { - return isci_si_rev == ISCI_SI_REVA2; + if (pdev->revision < 4) + return true; + return false; } -static inline bool is_b0(void) +static inline bool is_b0(struct pci_dev *pdev) { - return isci_si_rev == ISCI_SI_REVB0; + if (pdev->revision == 4) + return true; + return false; } -static inline bool is_c0(void) +static inline bool is_c0(struct pci_dev *pdev) { - return isci_si_rev > ISCI_SI_REVB0; + if (pdev->revision >= 5) + return true; + return false; } void sci_controller_post_request(struct isci_host *ihost, diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 8d9a8bfff4d5..61e0d09e2b57 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -85,10 +85,6 @@ MODULE_DEVICE_TABLE(pci, isci_id_table); /* linux isci specific settings */ -int isci_si_rev = ISCI_SI_REVA2; -module_param(isci_si_rev, int, 0); -MODULE_PARM_DESC(isci_si_rev, "(deprecated) override default si rev (0: A0 1: A2 2: B0)"); - unsigned char no_outbound_task_to = 20; module_param(no_outbound_task_to, byte, 0); MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)"); @@ -435,32 +431,6 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) return NULL; } -static void check_si_rev(struct pci_dev *pdev) -{ - switch (pdev->revision) { - case 0: - case 1: - /* if the id is ambiguous don't update isci_si_rev */ - break; - case 3: - isci_si_rev = ISCI_SI_REVA2; - break; - case 4: - isci_si_rev = ISCI_SI_REVB0; - break; - default: - case 5: - isci_si_rev = ISCI_SI_REVC0; - break; - } - - dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n", - isci_si_rev == ISCI_SI_REVA0 ? "A0" : - isci_si_rev == ISCI_SI_REVA2 ? "A2" : - isci_si_rev == ISCI_SI_REVB0 ? "B0" : "C0", pdev->revision); - -} - static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct isci_pci_info *pci_info; @@ -470,7 +440,8 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic struct isci_orom *orom = NULL; char *source = "(platform)"; - check_si_rev(pdev); + dev_info(&pdev->dev, "driver configured for rev: %d silicon\n", + pdev->revision); pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL); if (!pci_info) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index e56080af78f4..d8f893ee7d03 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -211,7 +211,7 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate); writel(llctl, &iphy->link_layer_registers->link_layer_control); - if (is_a0() || is_a2()) { + if (is_a2(ihost->pdev)) { /* Program the max ARB time for the PHY to 700us so we inter-operate with * the PMC expander which shuts down PHYs if the expander PHY generates too * many breaks. This time value will guarantee that the initiator PHY will diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index c7732fb28889..4b9d813c63b1 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -146,13 +146,13 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw memcpy(orom, fw->data, fw->size); + if (is_c0(pdev)) + goto out; + /* * deprecated: override default amp_control for pre-preproduction * silicon revisions */ - if (isci_si_rev <= ISCI_SI_REVB0) - goto out; - for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++) for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) { orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03; -- cgit v1.2.3 From a8a0a133b03c6863d0f77229d19befca4de905fa Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 1 Jul 2011 12:07:25 -0700 Subject: isci: pare back error messsages The messages emitted from task.c and some from request.c likely duplicate (in a less undertandable way) what is reported by the midlayer. Signed-off-by: Dan Williams --- drivers/scsi/isci/request.c | 18 +++++++++--------- drivers/scsi/isci/task.c | 38 +++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 33c8ed1741e6..a46e07ac789f 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2350,7 +2350,7 @@ static void isci_task_save_for_upper_layer_completion( /* No notification to libsas because this request is * already in the abort path. */ - dev_warn(&host->pdev->dev, + dev_dbg(&host->pdev->dev, "%s: Aborted - task = %p, response=%d (%d), status=%d (%d)\n", __func__, task, @@ -2373,7 +2373,7 @@ static void isci_task_save_for_upper_layer_completion( case isci_perform_error_io_completion: /* Use sas_task_abort */ - dev_warn(&host->pdev->dev, + dev_dbg(&host->pdev->dev, "%s: Error - task = %p, response=%d (%d), status=%d (%d)\n", __func__, task, @@ -2385,7 +2385,7 @@ static void isci_task_save_for_upper_layer_completion( break; default: - dev_warn(&host->pdev->dev, + dev_dbg(&host->pdev->dev, "%s: Unknown - task = %p, response=%d (%d), status=%d (%d)\n", __func__, task, @@ -2710,7 +2710,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost, default: /* Catch any otherwise unhandled error codes here. */ - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: invalid completion code: 0x%x - " "isci_request = %p\n", __func__, completion_status, request); @@ -3164,7 +3164,7 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) status = sci_io_request_construct_smp(dev, ireq, task); if (status != SCI_SUCCESS) - dev_warn(&ireq->isci_host->pdev->dev, + dev_dbg(&ireq->isci_host->pdev->dev, "%s: failed with status = %d\n", __func__, status); @@ -3219,7 +3219,7 @@ static enum sci_status isci_io_request_build(struct isci_host *ihost, status = sci_io_request_construct(ihost, idev, request); if (status != SCI_SUCCESS) { - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: failed request construct\n", __func__); return SCI_FAILURE; @@ -3238,7 +3238,7 @@ static enum sci_status isci_io_request_build(struct isci_host *ihost, status = isci_request_stp_request_construct(request); break; default: - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: unknown protocol\n", __func__); return SCI_FAILURE; } @@ -3302,7 +3302,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide status = isci_io_request_build(ihost, ireq, idev); if (status != SCI_SUCCESS) { - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: request_construct failed - status = 0x%x\n", __func__, status); @@ -3335,7 +3335,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide if (status != SCI_SUCCESS && status != SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: failed request start (0x%x)\n", __func__, status); spin_unlock_irqrestore(&ihost->scic_lock, flags); diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 5d962b6b03eb..22504c7ef2dc 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -104,7 +104,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, /* No notification because this request is already in the * abort path. */ - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: Aborted - task = %p, response=%d, " "status=%d\n", __func__, task, response, status); @@ -112,7 +112,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, case isci_perform_error_io_completion: /* Use sas_task_abort */ - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: Error - task = %p, response=%d, " "status=%d\n", __func__, task, response, status); @@ -121,7 +121,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, break; default: - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: isci task notification default case!", __func__); sas_task_abort(task); @@ -374,7 +374,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost, status = sci_controller_start_task(ihost, idev, ireq); if (status != SCI_TASK_SUCCESS) { - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: start_io failed - status = 0x%x, request = %p\n", __func__, status, @@ -604,7 +604,7 @@ static void isci_terminate_request_core(struct isci_host *ihost, * being aborted. */ if (status != SCI_SUCCESS) { - dev_err(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: sci_controller_terminate_request" " returned = 0x%x\n", __func__, status); @@ -662,7 +662,7 @@ static void isci_terminate_request_core(struct isci_host *ihost, if (!termination_completed) { - dev_err(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: *** Timeout waiting for " "termination(%p/%p)\n", __func__, io_request_completion, @@ -853,7 +853,7 @@ static int isci_task_send_lu_reset_sata(struct isci_host *ihost, ret = isci_task_execute_tmf(ihost, idev, &tmf, ISCI_SRST_TIMEOUT_MS); if (ret != TMF_RESP_FUNC_COMPLETE) { - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: Assert SRST failed (%p) = %x", __func__, idev, ret); @@ -897,7 +897,7 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) */ if (!isci_device || isci_device_is_reset_pending(isci_host, isci_device)) { - dev_warn(&isci_host->pdev->dev, + dev_dbg(&isci_host->pdev->dev, "%s: No dev (%p), or " "RESET PENDING: domain_device=%p\n", __func__, isci_device, domain_device); @@ -970,7 +970,7 @@ static void isci_abort_task_process_cb( */ if ((old_request->status != aborted) && (old_request->status != completed)) - dev_err(&old_request->isci_host->pdev->dev, + dev_dbg(&old_request->isci_host->pdev->dev, "%s: Bad request status (%d): tmf=%p, old_request=%p\n", __func__, old_request->status, tmf, old_request); break; @@ -988,7 +988,7 @@ static void isci_abort_task_process_cb( break; default: - dev_err(&old_request->isci_host->pdev->dev, + dev_dbg(&old_request->isci_host->pdev->dev, "%s: Bad cb_state (%d): tmf=%p, old_request=%p\n", __func__, cb_state, tmf, old_request); break; @@ -1046,7 +1046,7 @@ int isci_task_abort_task(struct sas_task *task) * SCSI error handler thread to escalate to LUN reset */ if (sas_protocol_ata(task->task_proto)) { - dev_warn(&isci_host->pdev->dev, + dev_dbg(&isci_host->pdev->dev, " task %p is for a STP/SATA device;" " returning TMF_RESP_FUNC_FAILED\n" " to cause a LUN reset...\n", task); @@ -1176,7 +1176,7 @@ int isci_task_abort_task(struct sas_task *task) ISCI_ABORT_TASK_TIMEOUT_MS); if (ret != TMF_RESP_FUNC_COMPLETE) - dev_err(&isci_host->pdev->dev, + dev_dbg(&isci_host->pdev->dev, "%s: isci_task_send_tmf failed\n", __func__); } @@ -1395,7 +1395,7 @@ static int isci_smp_execute_task(struct isci_host *ihost, if (res) { del_timer(&task->timer); - dev_err(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: executing SMP task failed:%d\n", __func__, res); goto ex_err; @@ -1404,12 +1404,12 @@ static int isci_smp_execute_task(struct isci_host *ihost, wait_for_completion(&task->completion); res = -ECOMM; if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { - dev_err(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: smp task timed out or aborted\n", __func__); isci_task_abort_task(task); if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - dev_err(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: SMP task aborted and not done\n", __func__); goto ex_err; @@ -1432,7 +1432,7 @@ static int isci_smp_execute_task(struct isci_host *ihost, res = -EMSGSIZE; break; } else { - dev_err(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: task to dev %016llx response: 0x%x " "status 0x%x\n", __func__, SAS_ADDR(dev->sas_addr), @@ -1526,7 +1526,7 @@ static void isci_wait_for_smp_phy_reset(struct isci_remote_device *idev, int phy tmo = deadline - jiffies; if (res) { - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: iteration %d, phase %d:" " SMP error=%d, time_remaining=%lu\n", __func__, iteration, phy_state, res, tmo); @@ -1578,7 +1578,7 @@ static int isci_reset_device(struct isci_host *ihost, if (status != SCI_SUCCESS) { spin_unlock_irqrestore(&ihost->scic_lock, flags); - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: sci_remote_device_reset(%p) returned %d!\n", __func__, idev, status); @@ -1619,7 +1619,7 @@ static int isci_reset_device(struct isci_host *ihost, } if (status != SCI_SUCCESS) { - dev_warn(&ihost->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: sci_remote_device_reset_complete(%p) " "returned %d!\n", __func__, idev, status); } -- cgit v1.2.3 From bc6f387d3156702a0430585b93c04934254c0de1 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Fri, 1 Jul 2011 13:03:44 -0700 Subject: isci: Device reset should request sas_phy_reset(phy, true) The hard_reset parameter passed to the LLDD in the direct-attached phy control case allows the LLDD to filter link failure events while the direct-attached device reset is executing. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/task.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 22504c7ef2dc..2df45c57fc60 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -1563,7 +1563,7 @@ static void isci_wait_for_smp_phy_reset(struct isci_remote_device *idev, int phy } static int isci_reset_device(struct isci_host *ihost, - struct isci_remote_device *idev, int hard_reset) + struct isci_remote_device *idev) { struct sas_phy *phy = sas_find_local_phy(idev->domain_dev); struct isci_port *iport = idev->isci_port; @@ -1593,7 +1593,7 @@ static int isci_reset_device(struct isci_host *ihost, if (!scsi_is_sas_phy_local(phy)) set_bit(IPORT_BCN_BLOCKED, &iport->flags); - rc = sas_phy_reset(phy, hard_reset); + rc = sas_phy_reset(phy, true); /* Terminate in-progress I/O now. */ isci_remote_device_nuke_requests(ihost, idev); @@ -1633,8 +1633,8 @@ int isci_task_I_T_nexus_reset(struct domain_device *dev) { struct isci_host *ihost = dev_to_ihost(dev); struct isci_remote_device *idev; - int ret, hard_reset = 1; unsigned long flags; + int ret; spin_lock_irqsave(&ihost->scic_lock, flags); idev = isci_lookup_device(dev); @@ -1645,10 +1645,7 @@ int isci_task_I_T_nexus_reset(struct domain_device *dev) goto out; } - if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) - hard_reset = 0; - - ret = isci_reset_device(ihost, idev, hard_reset); + ret = isci_reset_device(ihost, idev); out: isci_put_device(idev); return ret; @@ -1659,11 +1656,8 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) struct domain_device *dev = sdev_to_domain_dev(cmd->device); struct isci_host *ihost = dev_to_ihost(dev); struct isci_remote_device *idev; - int ret, hard_reset = 1; unsigned long flags; - - if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) - hard_reset = 0; + int ret; spin_lock_irqsave(&ihost->scic_lock, flags); idev = isci_lookup_device(dev); @@ -1674,7 +1668,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd) goto out; } - ret = isci_reset_device(ihost, idev, hard_reset); + ret = isci_reset_device(ihost, idev); out: isci_put_device(idev); return ret; -- cgit v1.2.3 From b6b2a1e8068684baf67307a994180976b7c443ed Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 3 Jul 2011 13:32:53 +0200 Subject: hwmon: (emc6w201) Properly handle all errors Handle errors on 8-bit register reads and writes too. Also use likely and unlikely to make the functions faster on success. Signed-off-by: Jean Delvare Acked-by: Guenter Roeck --- drivers/hwmon/emc6w201.c | 58 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c index e0ef32378ac6..0064432f361f 100644 --- a/drivers/hwmon/emc6w201.c +++ b/drivers/hwmon/emc6w201.c @@ -78,8 +78,9 @@ static u16 emc6w201_read16(struct i2c_client *client, u8 reg) lsb = i2c_smbus_read_byte_data(client, reg); msb = i2c_smbus_read_byte_data(client, reg + 1); - if (lsb < 0 || msb < 0) { - dev_err(&client->dev, "16-bit read failed at 0x%02x\n", reg); + if (unlikely(lsb < 0 || msb < 0)) { + dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n", + 16, "read", reg); return 0xFFFF; /* Arbitrary value */ } @@ -95,10 +96,39 @@ static int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val) int err; err = i2c_smbus_write_byte_data(client, reg, val & 0xff); - if (!err) + if (likely(!err)) err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8); - if (err < 0) - dev_err(&client->dev, "16-bit write failed at 0x%02x\n", reg); + if (unlikely(err < 0)) + dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n", + 16, "write", reg); + + return err; +} + +/* Read 8-bit value from register */ +static u8 emc6w201_read8(struct i2c_client *client, u8 reg) +{ + int val; + + val = i2c_smbus_read_byte_data(client, reg); + if (unlikely(val < 0)) { + dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n", + 8, "read", reg); + return 0x00; /* Arbitrary value */ + } + + return val; +} + +/* Write 8-bit value to register */ +static int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val) +{ + int err; + + err = i2c_smbus_write_byte_data(client, reg, val); + if (unlikely(err < 0)) + dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n", + 8, "write", reg); return err; } @@ -114,25 +144,25 @@ static struct emc6w201_data *emc6w201_update_device(struct device *dev) if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { for (nr = 0; nr < 6; nr++) { data->in[input][nr] = - i2c_smbus_read_byte_data(client, + emc6w201_read8(client, EMC6W201_REG_IN(nr)); data->in[min][nr] = - i2c_smbus_read_byte_data(client, + emc6w201_read8(client, EMC6W201_REG_IN_LOW(nr)); data->in[max][nr] = - i2c_smbus_read_byte_data(client, + emc6w201_read8(client, EMC6W201_REG_IN_HIGH(nr)); } for (nr = 0; nr < 6; nr++) { data->temp[input][nr] = - i2c_smbus_read_byte_data(client, + emc6w201_read8(client, EMC6W201_REG_TEMP(nr)); data->temp[min][nr] = - i2c_smbus_read_byte_data(client, + emc6w201_read8(client, EMC6W201_REG_TEMP_LOW(nr)); data->temp[max][nr] = - i2c_smbus_read_byte_data(client, + emc6w201_read8(client, EMC6W201_REG_TEMP_HIGH(nr)); } @@ -192,7 +222,7 @@ static ssize_t set_in(struct device *dev, struct device_attribute *devattr, mutex_lock(&data->update_lock); data->in[sf][nr] = SENSORS_LIMIT(val, 0, 255); - err = i2c_smbus_write_byte_data(client, reg, data->in[sf][nr]); + err = emc6w201_write8(client, reg, data->in[sf][nr]); mutex_unlock(&data->update_lock); return err < 0 ? err : count; @@ -229,7 +259,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, mutex_lock(&data->update_lock); data->temp[sf][nr] = SENSORS_LIMIT(val, -127, 128); - err = i2c_smbus_write_byte_data(client, reg, data->temp[sf][nr]); + err = emc6w201_write8(client, reg, data->temp[sf][nr]); mutex_unlock(&data->update_lock); return err < 0 ? err : count; @@ -444,7 +474,7 @@ static int emc6w201_detect(struct i2c_client *client, /* Check configuration */ config = i2c_smbus_read_byte_data(client, EMC6W201_REG_CONFIG); - if ((config & 0xF4) != 0x04) + if (config < 0 || (config & 0xF4) != 0x04) return -ENODEV; if (!(config & 0x01)) { dev_err(&client->dev, "Monitoring not enabled\n"); -- cgit v1.2.3 From 7958e3b45dd03bf4bc35b3ec97b8a9a4d6c616a5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 3 Jul 2011 13:32:53 +0200 Subject: hwmon: Use <> rather than () around my e-mail address Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare --- drivers/hwmon/f71882fg.c | 2 +- drivers/hwmon/sch5627.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index a4a94a096c90..f8ef19673391 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2662,7 +2662,7 @@ static void __exit f71882fg_exit(void) } MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); -MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)"); +MODULE_AUTHOR("Hans Edgington, Hans de Goede "); MODULE_LICENSE("GPL"); module_init(f71882fg_init); diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c index 020c87273ea1..3494a4cce414 100644 --- a/drivers/hwmon/sch5627.c +++ b/drivers/hwmon/sch5627.c @@ -887,7 +887,7 @@ static void __exit sch5627_exit(void) } MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver"); -MODULE_AUTHOR("Hans de Goede (hdegoede@redhat.com)"); +MODULE_AUTHOR("Hans de Goede "); MODULE_LICENSE("GPL"); module_init(sch5627_init); -- cgit v1.2.3 From 5da556e33fc53179a5bec10b5698e262cf68e26d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 3 Jul 2011 13:32:53 +0200 Subject: hwmon: (f71882fg) Add support for the F71869A The F71869A is almost the same as the F71869F/E, except that it has the normal number of temp and pwm zones for a F71882FG derived chip, rather then the limited number of the F71869F/E. Signed-off-by: Hans de Goede Tested-by: Max Baldwin Acked-by: Guenter Roeck Signed-off-by: Jean Delvare --- Documentation/hwmon/f71882fg | 4 ++++ drivers/hwmon/Kconfig | 2 +- drivers/hwmon/f71882fg.c | 17 +++++++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg index 84d2623810f3..de91c0db5846 100644 --- a/Documentation/hwmon/f71882fg +++ b/Documentation/hwmon/f71882fg @@ -22,6 +22,10 @@ Supported chips: Prefix: 'f71869' Addresses scanned: none, address read from Super I/O config space Datasheet: Available from the Fintek website + * Fintek F71869A + Prefix: 'f71869a' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Not public * Fintek F71882FG and F71883FG Prefix: 'f71882fg' Addresses scanned: none, address read from Super I/O config space diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 16db83c83c8b..5f888f7e7dcb 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -333,7 +333,7 @@ config SENSORS_F71882FG F71858FG F71862FG F71863FG - F71869F/E + F71869F/E/A F71882FG F71883FG F71889FG/ED/A diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index f8ef19673391..2d96ed2bf8ed 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -52,6 +52,7 @@ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71869_ID 0x0814 /* Chipset ID */ +#define SIO_F71869A_ID 0x1007 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ #define SIO_F71889_ID 0x0723 /* Chipset ID */ #define SIO_F71889E_ID 0x0909 /* Chipset ID */ @@ -108,8 +109,8 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71882fg, f71889fg, - f71889ed, f71889a, f8000, f81865f }; +enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg, + f71889fg, f71889ed, f71889a, f8000, f81865f }; static const char *f71882fg_names[] = { "f71808e", @@ -117,6 +118,7 @@ static const char *f71882fg_names[] = { "f71858fg", "f71862fg", "f71869", /* Both f71869f and f71869e, reg. compatible and same id */ + "f71869a", "f71882fg", "f71889fg", /* f81801u too, same id */ "f71889ed", @@ -131,6 +133,7 @@ static const char f71882fg_has_in[][F71882FG_MAX_INS] = { [f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, [f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + [f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, @@ -145,6 +148,7 @@ static const char f71882fg_has_in1_alarm[] = { [f71858fg] = 0, [f71862fg] = 0, [f71869] = 0, + [f71869a] = 0, [f71882fg] = 1, [f71889fg] = 1, [f71889ed] = 1, @@ -159,6 +163,7 @@ static const char f71882fg_fan_has_beep[] = { [f71858fg] = 0, [f71862fg] = 1, [f71869] = 1, + [f71869a] = 1, [f71882fg] = 1, [f71889fg] = 1, [f71889ed] = 1, @@ -173,6 +178,7 @@ static const char f71882fg_nr_fans[] = { [f71858fg] = 3, [f71862fg] = 3, [f71869] = 3, + [f71869a] = 3, [f71882fg] = 4, [f71889fg] = 3, [f71889ed] = 3, @@ -187,6 +193,7 @@ static const char f71882fg_temp_has_beep[] = { [f71858fg] = 0, [f71862fg] = 1, [f71869] = 1, + [f71869a] = 1, [f71882fg] = 1, [f71889fg] = 1, [f71889ed] = 1, @@ -201,6 +208,7 @@ static const char f71882fg_nr_temps[] = { [f71858fg] = 3, [f71862fg] = 3, [f71869] = 3, + [f71869a] = 3, [f71882fg] = 3, [f71889fg] = 3, [f71889ed] = 3, @@ -2243,6 +2251,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) case f71808e: case f71808a: case f71869: + case f71869a: /* These always have signed auto point temps */ data->auto_point_temp_signed = 1; /* Fall through to select correct fan/pwm reg bank! */ @@ -2305,6 +2314,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) case f71808e: case f71808a: case f71869: + case f71869a: case f71889fg: case f71889ed: case f71889a: @@ -2528,6 +2538,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, case SIO_F71869_ID: sio_data->type = f71869; break; + case SIO_F71869A_ID: + sio_data->type = f71869a; + break; case SIO_F71882_ID: sio_data->type = f71882fg; break; -- cgit v1.2.3 From 014ab488e2ebdc65d2088a3ab6d4b8c4472c57fe Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 3 Jul 2011 13:32:54 +0200 Subject: hwmon-vid: Fix typo in VIA CPU name It's Nehemiah, not Nemiah. Signed-off-by: Jean Delvare Acked-by: Guenter Roeck --- drivers/hwmon/hwmon-vid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index 2582bfef6ccb..c8195a077da3 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -202,7 +202,7 @@ static struct vrm_model vrm_models[] = { {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */ {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */ - {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */ + {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nehemiah */ {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M, Eden-N */ {X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0}, /* No information */ {X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13}, /* C7, Esther */ -- cgit v1.2.3 From af75d5b771269f764999a67511e7d0c995d1a185 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 3 Jul 2011 13:32:54 +0200 Subject: hwmon: (k10temp) Update documentation for Fam12h Add some CPU series IDs and links to the Fam12h datasheets. Signed-off-by: Clemens Ladisch Signed-off-by: Jean Delvare --- Documentation/hwmon/k10temp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp index 0393c89277c0..a10f73624ad3 100644 --- a/Documentation/hwmon/k10temp +++ b/Documentation/hwmon/k10temp @@ -9,8 +9,8 @@ Supported chips: Socket S1G3: Athlon II, Sempron, Turion II * AMD Family 11h processors: Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra) -* AMD Family 12h processors: "Llano" -* AMD Family 14h processors: "Brazos" (C/E/G-Series) +* AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series) +* AMD Family 14h processors: "Brazos" (C/E/G/Z-Series) * AMD Family 15h processors: "Bulldozer" Prefix: 'k10temp' @@ -20,12 +20,16 @@ Supported chips: http://support.amd.com/us/Processor_TechDocs/31116.pdf BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors: http://support.amd.com/us/Processor_TechDocs/41256.pdf + BIOS and Kernel Developer's Guide (BKDG) for AMD Family 12h Processors: + http://support.amd.com/us/Processor_TechDocs/41131.pdf BIOS and Kernel Developer's Guide (BKDG) for AMD Family 14h Models 00h-0Fh Processors: http://support.amd.com/us/Processor_TechDocs/43170.pdf Revision Guide for AMD Family 10h Processors: http://support.amd.com/us/Processor_TechDocs/41322.pdf Revision Guide for AMD Family 11h Processors: http://support.amd.com/us/Processor_TechDocs/41788.pdf + Revision Guide for AMD Family 12h Processors: + http://support.amd.com/us/Processor_TechDocs/44739.pdf Revision Guide for AMD Family 14h Models 00h-0Fh Processors: http://support.amd.com/us/Processor_TechDocs/47534.pdf AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks: -- cgit v1.2.3 From a5ec7f86dc5432c44d8407a144e7617ec65da770 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 3 Jul 2011 14:14:45 -0500 Subject: [SCSI] isci: fix checkpatch errors Signed-off-by: James Bottomley --- drivers/scsi/isci/phy.c | 2 +- drivers/scsi/isci/probe_roms.c | 7 ++-- drivers/scsi/isci/remote_device.c | 2 +- drivers/scsi/isci/request.h | 4 +-- drivers/scsi/isci/task.c | 71 ++++++++++++++++++++------------------- 5 files changed, 44 insertions(+), 42 deletions(-) diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index d8f893ee7d03..79313a7a2356 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -197,7 +197,7 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, (u8)ihost->user_parameters.no_outbound_task_timeout); - switch(phy_user->max_speed_generation) { + switch (phy_user->max_speed_generation) { case SCIC_SDS_PARM_GEN3_SPEED: link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3; break; diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 4b9d813c63b1..b5f4341de243 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -34,8 +34,9 @@ #include "task.h" #include "probe_roms.h" -static efi_char16_t isci_efivar_name[] = - {'R', 's', 't', 'S', 'c', 'u', 'O'}; +static efi_char16_t isci_efivar_name[] = { + 'R', 's', 't', 'S', 'c', 'u', 'O' +}; struct isci_orom *isci_request_oprom(struct pci_dev *pdev) { @@ -182,7 +183,7 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) struct isci_oem_hdr *oem_hdr; u8 *tmp, sum; int j; - ssize_t data_len; + unsigned long data_len; u8 *efi_data; u32 efi_attrib = 0; diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 85e54f542075..b6e6368c2665 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -73,7 +73,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, struct isci_remote_device *idev, u32 reason) { - struct isci_request * ireq; + struct isci_request *ireq; dev_dbg(&ihost->pdev->dev, "%s: isci_device = %p\n", __func__, idev); diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 11bc279457aa..7a1d5a9778eb 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -440,8 +440,8 @@ void sci_smp_request_copy_response(struct isci_request *ireq); static inline int isci_task_is_ncq_recovery(struct sas_task *task) { return (sas_protocol_ata(task->task_proto) && - task->ata_task.fis.command == ATA_CMD_READ_LOG_EXT && - task->ata_task.fis.lbal == ATA_LOG_SATA_NCQ); + task->ata_task.fis.command == ATA_CMD_READ_LOG_EXT && + task->ata_task.fis.lbal == ATA_LOG_SATA_NCQ); } diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 2df45c57fc60..d6bcdd013dc9 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -88,44 +88,45 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, * function should not be completed to the host in the regular path. */ switch (disposition) { - case isci_perform_normal_io_completion: - /* Normal notification (task_done) */ - dev_dbg(&ihost->pdev->dev, - "%s: Normal - task = %p, response=%d, " - "status=%d\n", - __func__, task, response, status); + case isci_perform_normal_io_completion: + /* Normal notification (task_done) */ + dev_dbg(&ihost->pdev->dev, + "%s: Normal - task = %p, response=%d, " + "status=%d\n", + __func__, task, response, status); - task->lldd_task = NULL; + task->lldd_task = NULL; - isci_execpath_callback(ihost, task, task->task_done); - break; + isci_execpath_callback(ihost, task, task->task_done); + break; - case isci_perform_aborted_io_completion: - /* No notification because this request is already in the - * abort path. - */ - dev_dbg(&ihost->pdev->dev, - "%s: Aborted - task = %p, response=%d, " - "status=%d\n", - __func__, task, response, status); - break; + case isci_perform_aborted_io_completion: + /* + * No notification because this request is already in the + * abort path. + */ + dev_dbg(&ihost->pdev->dev, + "%s: Aborted - task = %p, response=%d, " + "status=%d\n", + __func__, task, response, status); + break; - case isci_perform_error_io_completion: - /* Use sas_task_abort */ - dev_dbg(&ihost->pdev->dev, - "%s: Error - task = %p, response=%d, " - "status=%d\n", - __func__, task, response, status); + case isci_perform_error_io_completion: + /* Use sas_task_abort */ + dev_dbg(&ihost->pdev->dev, + "%s: Error - task = %p, response=%d, " + "status=%d\n", + __func__, task, response, status); - isci_execpath_callback(ihost, task, sas_task_abort); - break; + isci_execpath_callback(ihost, task, sas_task_abort); + break; - default: - dev_dbg(&ihost->pdev->dev, - "%s: isci task notification default case!", - __func__); - sas_task_abort(task); - break; + default: + dev_dbg(&ihost->pdev->dev, + "%s: isci task notification default case!", + __func__); + sas_task_abort(task); + break; } } @@ -1056,7 +1057,7 @@ int isci_task_abort_task(struct sas_task *task) dev_dbg(&isci_host->pdev->dev, "%s: old_request == %p\n", __func__, old_request); - any_dev_reset = isci_device_is_reset_pending(isci_host,isci_device); + any_dev_reset = isci_device_is_reset_pending(isci_host, isci_device); spin_lock_irqsave(&task->task_state_lock, flags); @@ -1115,9 +1116,9 @@ int isci_task_abort_task(struct sas_task *task) __func__, task); } goto out; - } - else + } else { spin_unlock_irqrestore(&task->task_state_lock, flags); + } spin_lock_irqsave(&isci_host->scic_lock, flags); -- cgit v1.2.3 From 178783622ce0fd629fad21b33b8f8f56b64c5e45 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 3 Jul 2011 23:24:21 +0100 Subject: ARM: dmabounce: fix map_single() error return value When map_single() is unable to obtain a safe buffer, we must return the dma_addr_t error value, which is ~0 rather than 0. Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index e5681636626f..841df7d21c2f 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -255,7 +255,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size, if (buf == 0) { dev_err(dev, "%s: unable to map unsafe buffer %p!\n", __func__, ptr); - return 0; + return ~0; } dev_dbg(dev, -- cgit v1.2.3 From 60b677034fcb3e48ffa30d638b09ac925afb4b36 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Fri, 1 Jul 2011 22:06:44 +0000 Subject: net: 8139too: Initial necessary vlan_features to support vlan Offload setting of vlan device requires vlan_features to be initialized. Signed-off-by: Shan Wei Acked-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/8139too.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 98517a373473..e3bad8247fd1 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -992,6 +992,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, * features */ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; + dev->vlan_features = dev->features; dev->irq = pdev->irq; -- cgit v1.2.3 From 2fb83cd618be34546fb526a9051eceaa95517026 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 3 Jul 2011 22:34:29 -0700 Subject: natsemi: silence dma-debug warnings This silences dma-debug warnings: https://lkml.org/lkml/2011/6/30/341 ------------[ cut here ]------------ WARNING: at /home/jimc/projects/lx/linux-2.6/lib/dma-debug.c:820 check_unmap+0x1fe/0x56a() natsemi 0000:00:06.0: DMA-API: device driver frees DMA memory with different size [device address=0x0000000006ef0040] [map size=1538 bytes] [unmap size=1522 bytes] Modules linked in: pc8736x_gpio pc87360 hwmon_vid scx200_gpio nsc_gpio scx200_hrt scx200_acb i2c_core arc4 rtl8180 mac80211 eeprom_93cx6 cfg80211 pcspkr rfkill scx200 ide_gd_mod ide_pci_generic ohci_hcd usbcore sc1200 ide_core Pid: 870, comm: collector Not tainted 3.0.0-rc5-sk-00080-gca56a95 #1 Call Trace: [] warn_slowpath_common+0x4a/0x5f [] ? check_unmap+0x1fe/0x56a [] warn_slowpath_fmt+0x26/0x2a [] check_unmap+0x1fe/0x56a [] debug_dma_unmap_page+0x53/0x5b [] pci_unmap_single+0x4d/0x57 [] natsemi_poll+0x343/0x5ca [] ? try_to_wake_up+0xea/0xfc [] ? spin_unlock_irq.clone.28+0x18/0x23 [] net_rx_action+0x3f/0xe5 [] __do_softirq+0x5b/0xd1 [] ? local_bh_enable+0xa/0xa [] ? irq_exit+0x34/0x75 [] ? do_IRQ+0x66/0x79 [] ? common_interrupt+0x29/0x30 [] ? finish_task_switch.clone.118+0x31/0x72 [] ? schedule+0x3b2/0x3f1 [] ? hrtimer_start_range_ns+0x10/0x12 [] ? hrtimer_start_expires+0x1c/0x24 [] ? schedule_hrtimeout_range_clock+0x8e/0xb4 [] ? update_rmtp+0x68/0x68 [] ? schedule_hrtimeout_range+0xa/0xc [] ? poll_schedule_timeout+0x27/0x3e [] ? do_select+0x488/0x4cd [] ? finish_task_switch.clone.118+0x43/0x72 [] ? need_resched+0x14/0x1e [] ? poll_freewait+0x74/0x74 [] ? need_resched+0x14/0x1e [] ? schedule+0x3e1/0x3f1 [] ? irq_exit+0x47/0x75 [] ? need_resched+0x14/0x1e [] ? preempt_schedule_irq+0x44/0x4a [] ? need_resched+0x17/0x19 [] ? put_dec_full+0x7b/0xaa [] ? blkdev_ioctl+0x434/0x618 [] ? put_dec+0x2f/0x6d [] ? number.clone.1+0x10b/0x1d0 [] ? preempt_schedule_irq+0x44/0x4a [] ? need_resched+0x17/0x19 [] ? vsnprintf+0x225/0x264 [] ? vsnprintf+0x7f/0x264 [] ? seq_printf+0x22/0x40 [] ? do_task_stat+0x582/0x5a3 [] ? poll_schedule_timeout+0x27/0x3e [] ? core_sys_select+0x11f/0x1a3 [] ? poll_schedule_timeout+0x27/0x3e [] ? proc_tgid_stat+0xd/0xf [] ? recalc_sigpending+0x32/0x35 [] ? __set_task_blocked+0x64/0x6a [] ? timespec_add_safe+0x24/0x48 [] ? spin_unlock_irq.clone.16+0x18/0x23 [] ? sys_pselect6+0xe5/0x13e [] ? syscall_call+0x7/0xb [] ? rpc_clntdir_depopulate+0x26/0x30 ---[ end trace 180dcac41a50938b ]--- Reported-by: Jim Cromie Signed-off-by: FUJITA Tomonori Tested-by: Jim Cromie Signed-off-by: David S. Miller --- drivers/net/natsemi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index b78be088c4ad..8f8b65af9ed5 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2360,7 +2360,8 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do) PCI_DMA_FROMDEVICE); } else { pci_unmap_single(np->pci_dev, np->rx_dma[entry], - buflen, PCI_DMA_FROMDEVICE); + buflen + NATSEMI_PADDING, + PCI_DMA_FROMDEVICE); skb_put(skb = np->rx_skbuff[entry], pkt_len); np->rx_skbuff[entry] = NULL; } -- cgit v1.2.3 From 3e86f1d8e397b1ef59a97910089e16a99e8f31f7 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Mon, 27 Jun 2011 23:08:53 +0000 Subject: vesafb: fix memory leak When releasing framebuffer, free colourmap allocations. Signed-off-by: Daniel J Blueman Signed-off-by: Paul Mundt --- drivers/video/vesafb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index a99bbe86db13..501b3406c6d5 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -175,6 +175,7 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, static void vesafb_destroy(struct fb_info *info) { + fb_dealloc_cmap(&info->cmap); if (info->screen_base) iounmap(info->screen_base); release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); -- cgit v1.2.3 From 07ad6ab3d79ede41cd8a69499e81df7b405635d2 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Mon, 4 Jul 2011 03:56:15 -0700 Subject: omap: drop __initdata tags from static struct platform_device declarations Pointers to statically declared platform device structures which are registered with platform_device_register() are then used during run time to access these structure members, for example from platform_uevent() and much more. Therefore, these structures should never be placed inside sections which are dropped after boot. Fix platform devices incorrectly tagged with __initdata which happen to exist inside OMAP sub-trees. This bug has exhibited itself on my ARM/OMAP1 based Amstrad Delta videophone after commit 6d3163ce86dd386b4f7bda80241d7fea2bc0bb1d, "mm: check if any page in a pageblock is reserved before marking it MIGRATE_RESERVE", resulting in reading from several /sys/device/platform/*/uevent files always ending up with segmentation faults. Signed-off-by: Janusz Krzysztofik Acked-by: Felipe Balbi Cc: Varadarajan, Charulatha Cc: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-ams-delta.c | 8 ++++---- arch/arm/mach-omap1/gpio15xx.c | 4 ++-- arch/arm/mach-omap1/gpio16xx.c | 10 +++++----- arch/arm/mach-omap1/gpio7xx.c | 14 +++++++------- arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index de88c9297b68..f49ce85d2448 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -215,7 +215,7 @@ static struct omap_kp_platform_data ams_delta_kp_data __initdata = { .delay = 9, }; -static struct platform_device ams_delta_kp_device __initdata = { +static struct platform_device ams_delta_kp_device = { .name = "omap-keypad", .id = -1, .dev = { @@ -225,12 +225,12 @@ static struct platform_device ams_delta_kp_device __initdata = { .resource = ams_delta_kp_resources, }; -static struct platform_device ams_delta_lcd_device __initdata = { +static struct platform_device ams_delta_lcd_device = { .name = "lcd_ams_delta", .id = -1, }; -static struct platform_device ams_delta_led_device __initdata = { +static struct platform_device ams_delta_led_device = { .name = "ams-delta-led", .id = -1 }; @@ -267,7 +267,7 @@ static struct soc_camera_link ams_delta_iclink = { .power = ams_delta_camera_power, }; -static struct platform_device ams_delta_camera_device __initdata = { +static struct platform_device ams_delta_camera_device = { .name = "soc-camera-pdrv", .id = 0, .dev = { diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index 04c4b04cf54e..364137c2042c 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -41,7 +41,7 @@ static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = { .bank_stride = 1, }; -static struct __initdata platform_device omap15xx_mpu_gpio = { +static struct platform_device omap15xx_mpu_gpio = { .name = "omap_gpio", .id = 0, .dev = { @@ -70,7 +70,7 @@ static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = { .bank_width = 16, }; -static struct __initdata platform_device omap15xx_gpio = { +static struct platform_device omap15xx_gpio = { .name = "omap_gpio", .id = 1, .dev = { diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 5dd0d4c82b24..293a246e2824 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -44,7 +44,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = { .bank_stride = 1, }; -static struct __initdata platform_device omap16xx_mpu_gpio = { +static struct platform_device omap16xx_mpu_gpio = { .name = "omap_gpio", .id = 0, .dev = { @@ -73,7 +73,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { .bank_width = 16, }; -static struct __initdata platform_device omap16xx_gpio1 = { +static struct platform_device omap16xx_gpio1 = { .name = "omap_gpio", .id = 1, .dev = { @@ -102,7 +102,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = { .bank_width = 16, }; -static struct __initdata platform_device omap16xx_gpio2 = { +static struct platform_device omap16xx_gpio2 = { .name = "omap_gpio", .id = 2, .dev = { @@ -131,7 +131,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = { .bank_width = 16, }; -static struct __initdata platform_device omap16xx_gpio3 = { +static struct platform_device omap16xx_gpio3 = { .name = "omap_gpio", .id = 3, .dev = { @@ -160,7 +160,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = { .bank_width = 16, }; -static struct __initdata platform_device omap16xx_gpio4 = { +static struct platform_device omap16xx_gpio4 = { .name = "omap_gpio", .id = 4, .dev = { diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c index 1204c8b871af..c6ad248d63a6 100644 --- a/arch/arm/mach-omap1/gpio7xx.c +++ b/arch/arm/mach-omap1/gpio7xx.c @@ -46,7 +46,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = { .bank_stride = 2, }; -static struct __initdata platform_device omap7xx_mpu_gpio = { +static struct platform_device omap7xx_mpu_gpio = { .name = "omap_gpio", .id = 0, .dev = { @@ -75,7 +75,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = { .bank_width = 32, }; -static struct __initdata platform_device omap7xx_gpio1 = { +static struct platform_device omap7xx_gpio1 = { .name = "omap_gpio", .id = 1, .dev = { @@ -104,7 +104,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = { .bank_width = 32, }; -static struct __initdata platform_device omap7xx_gpio2 = { +static struct platform_device omap7xx_gpio2 = { .name = "omap_gpio", .id = 2, .dev = { @@ -133,7 +133,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = { .bank_width = 32, }; -static struct __initdata platform_device omap7xx_gpio3 = { +static struct platform_device omap7xx_gpio3 = { .name = "omap_gpio", .id = 3, .dev = { @@ -162,7 +162,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = { .bank_width = 32, }; -static struct __initdata platform_device omap7xx_gpio4 = { +static struct platform_device omap7xx_gpio4 = { .name = "omap_gpio", .id = 4, .dev = { @@ -191,7 +191,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = { .bank_width = 32, }; -static struct __initdata platform_device omap7xx_gpio5 = { +static struct platform_device omap7xx_gpio5 = { .name = "omap_gpio", .id = 5, .dev = { @@ -220,7 +220,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = { .bank_width = 32, }; -static struct __initdata platform_device omap7xx_gpio6 = { +static struct platform_device omap7xx_gpio6 = { .name = "omap_gpio", .id = 6, .dev = { diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 990366726c58..88bd6f7705f0 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -558,7 +558,7 @@ static struct radio_si4713_platform_data rx51_si4713_data __initdata_or_module = .subdev_board_info = &rx51_si4713_board_info, }; -static struct platform_device rx51_si4713_dev __initdata_or_module = { +static struct platform_device rx51_si4713_dev = { .name = "radio-si4713", .id = -1, .dev = { -- cgit v1.2.3 From 713d1369789f2a2336c3431b15276c968862bdb7 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 1 Jul 2011 13:56:13 -0600 Subject: ASoC: Tegra: I2S: Ensure clock is enabled when writing regs The I2S controller needs a clock to respond to register writes. Without this, register writes will at worst hang the CPU. In practice, I've only observed writes being dropped. Luckily, the dropped register writes historically had no effect: TEGRA_I2S_TIMING: The value we wrote was the reset default. TEGRA_I2S_FIFO_SCR: The default was for the FIFOs to request more data when one slot was empty. The requested value was for the FIFOs to request when four slots were empty. The DMA controller in the mainline kernel is configured to burst a single entry at a time into the FIFO, hence there was no issue. The only negative effect was on bus efficiency losses due to an increased number of arbitration attempts. However, in various non-upstream changes, the DMA controller now bursts four entries at a time into the FIFO. If there is only space for one entry, the data is simply dropped. In practice, this resulted in 3/4 of samples being dropped, and playback at 4x the expected rate and pitch. By fixing the clocking issue, this is solved. Signed-off-by: Stephen Warren Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_i2s.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c index 6b817e20548c..95f03c10b4f7 100644 --- a/sound/soc/tegra/tegra_i2s.c +++ b/sound/soc/tegra/tegra_i2s.c @@ -222,12 +222,18 @@ static int tegra_i2s_hw_params(struct snd_pcm_substream *substream, if (i2sclock % (2 * srate)) reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE; + if (!i2s->clk_refs) + clk_enable(i2s->clk_i2s); + tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg); tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR, TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); + if (!i2s->clk_refs) + clk_disable(i2s->clk_i2s); + return 0; } -- cgit v1.2.3 From 8e9ddf811ba021506d2316fcfe619faa0ab3f567 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 1 Jul 2011 17:24:46 -0700 Subject: ASoC: Ensure we delay long enough for WM8994 FLL to lock when starting This delay is very conservative. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Cc: stable@kernel.org --- sound/soc/codecs/wm8994.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 970a95c5360b..c2fc0356c2a4 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1713,6 +1713,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, WM8994_FLL1_ENA | WM8994_FLL1_FRAC, reg); + + msleep(5); } wm8994->fll[id].in = freq_in; -- cgit v1.2.3 From 64393b3ae4e3cc86e2d622f682d736ec973364b6 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Fri, 1 Jul 2011 12:25:24 +0200 Subject: AT91: Change nand buswidth logic to match hardware default configuration The recently modified nand buswitth configuration is not aligned with board reality: the double footprint on boards is always populated with 8bits buswidth nand flashes. So we have to consider that without particular configuration the 8bits buswidth is selected by default. Moreover, the previous logic was always using !board_have_nand_8bit(), we change it to a simpler: board_have_nand_16bit(). Signed-off-by: Nicolas Ferre Tested-by: Ludovic Desroches Signed-off-by: Arnd Bergmann --- arch/arm/mach-at91/board-cap9adk.c | 2 +- arch/arm/mach-at91/board-sam9260ek.c | 2 +- arch/arm/mach-at91/board-sam9261ek.c | 2 +- arch/arm/mach-at91/board-sam9263ek.c | 2 +- arch/arm/mach-at91/board-sam9g20ek.c | 2 +- arch/arm/mach-at91/board-sam9m10g45ek.c | 2 +- arch/arm/mach-at91/include/mach/system_rev.h | 10 +++++----- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c index 1904fdf87613..cdb65d483250 100644 --- a/arch/arm/mach-at91/board-cap9adk.c +++ b/arch/arm/mach-at91/board-cap9adk.c @@ -215,7 +215,7 @@ static void __init cap9adk_add_device_nand(void) csa = at91_sys_read(AT91_MATRIX_EBICSA); at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_VDDIOMSEL_3_3V); - cap9adk_nand_data.bus_width_16 = !board_have_nand_8bit(); + cap9adk_nand_data.bus_width_16 = board_have_nand_16bit(); /* setup bus-width (8 or 16) */ if (cap9adk_nand_data.bus_width_16) cap9adk_nand_smc_config.mode |= AT91_SMC_DBW_16; diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index d600dc123227..5c240743c5b7 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -214,7 +214,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = { static void __init ek_add_device_nand(void) { - ek_nand_data.bus_width_16 = !board_have_nand_8bit(); + ek_nand_data.bus_width_16 = board_have_nand_16bit(); /* setup bus-width (8 or 16) */ if (ek_nand_data.bus_width_16) ek_nand_smc_config.mode |= AT91_SMC_DBW_16; diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index f897f84d43dc..b60c22b6e241 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -220,7 +220,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = { static void __init ek_add_device_nand(void) { - ek_nand_data.bus_width_16 = !board_have_nand_8bit(); + ek_nand_data.bus_width_16 = board_have_nand_16bit(); /* setup bus-width (8 or 16) */ if (ek_nand_data.bus_width_16) ek_nand_smc_config.mode |= AT91_SMC_DBW_16; diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 605b26f40a4c..9bbdc92ea194 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -221,7 +221,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = { static void __init ek_add_device_nand(void) { - ek_nand_data.bus_width_16 = !board_have_nand_8bit(); + ek_nand_data.bus_width_16 = board_have_nand_16bit(); /* setup bus-width (8 or 16) */ if (ek_nand_data.bus_width_16) ek_nand_smc_config.mode |= AT91_SMC_DBW_16; diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index 7624cf0d006b..1325a50101a8 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -198,7 +198,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = { static void __init ek_add_device_nand(void) { - ek_nand_data.bus_width_16 = !board_have_nand_8bit(); + ek_nand_data.bus_width_16 = board_have_nand_16bit(); /* setup bus-width (8 or 16) */ if (ek_nand_data.bus_width_16) ek_nand_smc_config.mode |= AT91_SMC_DBW_16; diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index 063c95d0e8f0..33eaa135f248 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -178,7 +178,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = { static void __init ek_add_device_nand(void) { - ek_nand_data.bus_width_16 = !board_have_nand_8bit(); + ek_nand_data.bus_width_16 = board_have_nand_16bit(); /* setup bus-width (8 or 16) */ if (ek_nand_data.bus_width_16) ek_nand_smc_config.mode |= AT91_SMC_DBW_16; diff --git a/arch/arm/mach-at91/include/mach/system_rev.h b/arch/arm/mach-at91/include/mach/system_rev.h index b855ee75f72c..8f4866045b41 100644 --- a/arch/arm/mach-at91/include/mach/system_rev.h +++ b/arch/arm/mach-at91/include/mach/system_rev.h @@ -13,13 +13,13 @@ * the 16-31 bit are reserved for at91 generic information * * bit 31: - * 0 => nand 16 bit - * 1 => nand 8 bit + * 0 => nand 8 bit + * 1 => nand 16 bit */ -#define BOARD_HAVE_NAND_8BIT (1 << 31) -static int inline board_have_nand_8bit(void) +#define BOARD_HAVE_NAND_16BIT (1 << 31) +static inline int board_have_nand_16bit(void) { - return system_rev & BOARD_HAVE_NAND_8BIT; + return system_rev & BOARD_HAVE_NAND_16BIT; } #endif /* __ARCH_SYSTEM_REV_H__ */ -- cgit v1.2.3 From b2bc4782191cb574924a1d09f48083ea8b33a93b Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues Date: Mon, 4 Jul 2011 09:26:57 -0700 Subject: RDMA: Check for NULL mode in .devnode methods Commits 71c29bd5c235 ("IB/uverbs: Add devnode method to set path/mode") and c3af0980ce01 ("IB: Add devnode methods to cm_class and umad_class") added devnode methods that set the mode. However, these methods don't check for a NULL mode, and so we get a crash when unloading modules because devtmpfs_delete_node() calls device_get_devnode() with mode == NULL. Add the missing checks. Signed-off-by: Goldwyn Rodrigues [ Also fix cm.c. - Roland ] Signed-off-by: Roland Dreier Signed-off-by: Linus Torvalds --- drivers/infiniband/core/cm.c | 3 ++- drivers/infiniband/core/uverbs_main.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index f62f52fb9ece..fc0f2bd9ca82 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3641,7 +3641,8 @@ static struct kobj_type cm_port_obj_type = { static char *cm_devnode(struct device *dev, mode_t *mode) { - *mode = 0666; + if (mode) + *mode = 0666; return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev)); } diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index e49a85f8a44d..56898b6578a4 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -826,7 +826,8 @@ static void ib_uverbs_remove_one(struct ib_device *device) static char *uverbs_devnode(struct device *dev, mode_t *mode) { - *mode = 0666; + if (mode) + *mode = 0666; return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev)); } -- cgit v1.2.3 From fe0d42203cb5616eeff68b14576a0f7e2dd56625 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 4 Jul 2011 15:56:24 -0700 Subject: Linux 3.0-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dc670467fb8c..86f47a0ddc79 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Sneaky Weasel # *DOCUMENTATION* -- cgit v1.2.3 From c349a528cd47e2272ded0ea358363855e86180da Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Mon, 4 Jul 2011 01:30:29 +0000 Subject: net: bind() fix error return on wrong address family Hi, Reinhard Max also pointed out that the error should EAFNOSUPPORT according to POSIX. The Linux manpages have it as EINVAL, some other OSes (Minix, HPUX, perhaps BSD) use EAFNOSUPPORT. Windows uses WSAEFAULT according to MSDN. Other protocols error values in their af bind() methods in current mainline git as far as a brief look shows: EAFNOSUPPORT: atm, appletalk, l2tp, llc, phonet, rxrpc EINVAL: ax25, bluetooth, decnet, econet, ieee802154, iucv, netlink, netrom, packet, rds, rose, unix, x25, No check?: can/raw, ipv6/raw, irda, l2tp/l2tp_ip Ciao, Marcus Signed-off-by: Marcus Meissner Cc: Reinhard Max Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 4 +++- net/ipv6/af_inet6.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index eae1f676f870..ef1528af7abf 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -465,8 +465,10 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len < sizeof(struct sockaddr_in)) goto out; - if (addr->sin_family != AF_INET) + if (addr->sin_family != AF_INET) { + err = -EAFNOSUPPORT; goto out; + } chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index d450a2f9fc06..3b5669a2582d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -274,7 +274,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL; if (addr->sin6_family != AF_INET6) - return -EINVAL; + return -EAFNOSUPPORT; addr_type = ipv6_addr_type(&addr->sin6_addr); if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM) -- cgit v1.2.3 From 9b9cfe7cf663c16c0d93349cc0094bb28ae7135a Mon Sep 17 00:00:00 2001 From: Kristoffer Glembo Date: Mon, 4 Jul 2011 21:39:10 -0700 Subject: greth: greth_set_mac_add would corrupt the MAC address. The MAC address was set using the signed char sockaddr->sa_addr field and thus the address could be corrupted through sign extension. Signed-off-by: Kristoffer Glembo Signed-off-by: David S. Miller --- drivers/net/greth.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index f181304a7ab6..672f096fe090 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -1015,11 +1015,10 @@ static int greth_set_mac_add(struct net_device *dev, void *p) return -EINVAL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]); + GRETH_REGSAVE(regs->esa_lsb, dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 | + dev->dev_addr[4] << 8 | dev->dev_addr[5]); - GRETH_REGSAVE(regs->esa_msb, addr->sa_data[0] << 8 | addr->sa_data[1]); - GRETH_REGSAVE(regs->esa_lsb, - addr->sa_data[2] << 24 | addr-> - sa_data[3] << 16 | addr->sa_data[4] << 8 | addr->sa_data[5]); return 0; } -- cgit v1.2.3 From 1d08382a0e8a272fed9517a1b39ae6be634a77d5 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 8 Jun 2011 11:03:23 +0200 Subject: input: pmic8xxx-keypad: Do not use mfd_get_data() mfd_get_data() has been removed from the MFD API. Cc: Anirudh Ghayal Signed-off-by: Samuel Ortiz --- drivers/input/keyboard/pmic8xxx-keypad.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 40b02ae96f86..6229c3e8e78b 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -520,7 +520,8 @@ static void pmic8xxx_kp_close(struct input_dev *dev) */ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) { - const struct pm8xxx_keypad_platform_data *pdata = mfd_get_data(pdev); + const struct pm8xxx_keypad_platform_data *pdata = + dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap_data; struct pmic8xxx_kp *kp; int rc; -- cgit v1.2.3 From 63ef1124f1cb07836f232b8eaed1ae4c73899643 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 8 Jun 2011 11:06:30 +0200 Subject: input: pmic8xxx-pwrkey: Do not use mfd_get_data() mfd_get_data() has been removed from the MFD API. Cc: Anirudh Ghayal Signed-off-by: Samuel Ortiz --- drivers/input/misc/pmic8xxx-pwrkey.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index 97e07e786e41..b3cfb9c71e66 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c @@ -90,7 +90,8 @@ static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) unsigned int delay; u8 pon_cntl; struct pmic8xxx_pwrkey *pwrkey; - const struct pm8xxx_pwrkey_platform_data *pdata = mfd_get_data(pdev); + const struct pm8xxx_pwrkey_platform_data *pdata = + dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "power key platform data not supplied\n"); -- cgit v1.2.3 From 8f2df0147fc78804a869150e6439be2605b5dc2d Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Mon, 20 Jun 2011 15:22:56 +0200 Subject: Revert "mfd: Add omap-usbhs runtime PM support" This reverts commit 7e6502d577106fb5b202bbaac64c5f1b065e6daa. Oops are produced during initialization of ehci and ohci drivers. This is because the run time pm apis are used by the driver but the corresponding hwmod structures and initialization is not merged. hence revering back the commit id 7e6502d577106fb5b202bbaac64c5f1b065e6daa Signed-off-by: Keshava Munegowda Reported-by: Luciano Coelho Acked-by: Felipe Balbi Signed-off-by: Samuel Ortiz --- drivers/mfd/omap-usb-host.c | 131 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 855219526ccb..1717144fe7f4 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -26,7 +26,6 @@ #include #include #include -#include #define USBHS_DRIVER_NAME "usbhs-omap" #define OMAP_EHCI_DEVICE "ehci-omap" @@ -147,6 +146,9 @@ struct usbhs_hcd_omap { + struct clk *usbhost_ick; + struct clk *usbhost_hs_fck; + struct clk *usbhost_fs_fck; struct clk *xclk60mhsp1_ck; struct clk *xclk60mhsp2_ck; struct clk *utmi_p1_fck; @@ -156,6 +158,8 @@ struct usbhs_hcd_omap { struct clk *usbhost_p2_fck; struct clk *usbtll_p2_fck; struct clk *init_60m_fclk; + struct clk *usbtll_fck; + struct clk *usbtll_ick; void __iomem *uhh_base; void __iomem *tll_base; @@ -349,13 +353,46 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) omap->platdata.ehci_data = pdata->ehci_data; omap->platdata.ohci_data = pdata->ohci_data; - pm_runtime_enable(&pdev->dev); + omap->usbhost_ick = clk_get(dev, "usbhost_ick"); + if (IS_ERR(omap->usbhost_ick)) { + ret = PTR_ERR(omap->usbhost_ick); + dev_err(dev, "usbhost_ick failed error:%d\n", ret); + goto err_end; + } + + omap->usbhost_hs_fck = clk_get(dev, "hs_fck"); + if (IS_ERR(omap->usbhost_hs_fck)) { + ret = PTR_ERR(omap->usbhost_hs_fck); + dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret); + goto err_usbhost_ick; + } + + omap->usbhost_fs_fck = clk_get(dev, "fs_fck"); + if (IS_ERR(omap->usbhost_fs_fck)) { + ret = PTR_ERR(omap->usbhost_fs_fck); + dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret); + goto err_usbhost_hs_fck; + } + + omap->usbtll_fck = clk_get(dev, "usbtll_fck"); + if (IS_ERR(omap->usbtll_fck)) { + ret = PTR_ERR(omap->usbtll_fck); + dev_err(dev, "usbtll_fck failed error:%d\n", ret); + goto err_usbhost_fs_fck; + } + + omap->usbtll_ick = clk_get(dev, "usbtll_ick"); + if (IS_ERR(omap->usbtll_ick)) { + ret = PTR_ERR(omap->usbtll_ick); + dev_err(dev, "usbtll_ick failed error:%d\n", ret); + goto err_usbtll_fck; + } omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); if (IS_ERR(omap->utmi_p1_fck)) { ret = PTR_ERR(omap->utmi_p1_fck); dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); - goto err_end; + goto err_usbtll_ick; } omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); @@ -485,8 +522,22 @@ err_xclk60mhsp1_ck: err_utmi_p1_fck: clk_put(omap->utmi_p1_fck); +err_usbtll_ick: + clk_put(omap->usbtll_ick); + +err_usbtll_fck: + clk_put(omap->usbtll_fck); + +err_usbhost_fs_fck: + clk_put(omap->usbhost_fs_fck); + +err_usbhost_hs_fck: + clk_put(omap->usbhost_hs_fck); + +err_usbhost_ick: + clk_put(omap->usbhost_ick); + err_end: - pm_runtime_disable(&pdev->dev); kfree(omap); end_probe: @@ -520,7 +571,11 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev) clk_put(omap->utmi_p2_fck); clk_put(omap->xclk60mhsp1_ck); clk_put(omap->utmi_p1_fck); - pm_runtime_disable(&pdev->dev); + clk_put(omap->usbtll_ick); + clk_put(omap->usbtll_fck); + clk_put(omap->usbhost_fs_fck); + clk_put(omap->usbhost_hs_fck); + clk_put(omap->usbhost_ick); kfree(omap); return 0; @@ -640,6 +695,7 @@ static int usbhs_enable(struct device *dev) struct usbhs_omap_platform_data *pdata = &omap->platdata; unsigned long flags = 0; int ret = 0; + unsigned long timeout; unsigned reg; dev_dbg(dev, "starting TI HSUSB Controller\n"); @@ -652,7 +708,11 @@ static int usbhs_enable(struct device *dev) if (omap->count > 0) goto end_count; - pm_runtime_get_sync(dev); + clk_enable(omap->usbhost_ick); + clk_enable(omap->usbhost_hs_fck); + clk_enable(omap->usbhost_fs_fck); + clk_enable(omap->usbtll_fck); + clk_enable(omap->usbtll_ick); if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { @@ -676,6 +736,50 @@ static int usbhs_enable(struct device *dev) omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); + /* perform TLL soft reset, and wait until reset is complete */ + usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, + OMAP_USBTLL_SYSCONFIG_SOFTRESET); + + /* Wait for TLL reset to complete */ + timeout = jiffies + msecs_to_jiffies(1000); + while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) + & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { + cpu_relax(); + + if (time_after(jiffies, timeout)) { + dev_dbg(dev, "operation timed out\n"); + ret = -EINVAL; + goto err_tll; + } + } + + dev_dbg(dev, "TLL RESET DONE\n"); + + /* (1<<3) = no idle mode only for initial debugging */ + usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, + OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | + OMAP_USBTLL_SYSCONFIG_SIDLEMODE | + OMAP_USBTLL_SYSCONFIG_AUTOIDLE); + + /* Put UHH in NoIdle/NoStandby mode */ + reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG); + if (is_omap_usbhs_rev1(omap)) { + reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP + | OMAP_UHH_SYSCONFIG_SIDLEMODE + | OMAP_UHH_SYSCONFIG_CACTIVITY + | OMAP_UHH_SYSCONFIG_MIDLEMODE); + reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; + + + } else if (is_omap_usbhs_rev2(omap)) { + reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; + reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; + reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; + reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; + } + + usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); + reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN @@ -815,8 +919,6 @@ end_count: return 0; err_tll: - pm_runtime_put_sync(dev); - spin_unlock_irqrestore(&omap->lock, flags); if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) gpio_free(pdata->ehci_data->reset_gpio_port[0]); @@ -824,6 +926,13 @@ err_tll: if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) gpio_free(pdata->ehci_data->reset_gpio_port[1]); } + + clk_disable(omap->usbtll_ick); + clk_disable(omap->usbtll_fck); + clk_disable(omap->usbhost_fs_fck); + clk_disable(omap->usbhost_hs_fck); + clk_disable(omap->usbhost_ick); + spin_unlock_irqrestore(&omap->lock, flags); return ret; } @@ -896,7 +1005,11 @@ static void usbhs_disable(struct device *dev) clk_disable(omap->utmi_p1_fck); } - pm_runtime_put_sync(dev); + clk_disable(omap->usbtll_ick); + clk_disable(omap->usbtll_fck); + clk_disable(omap->usbhost_fs_fck); + clk_disable(omap->usbhost_hs_fck); + clk_disable(omap->usbhost_ick); /* The gpio_free migh sleep; so unlock the spinlock */ spin_unlock_irqrestore(&omap->lock, flags); -- cgit v1.2.3 From 1e8ece5cb85361ac01c95aecdfdbfa5f8b7242af Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 23 Jun 2011 10:17:43 +0800 Subject: mfd: Fix build error for tps65911-comparator.c Fix below build error: CC drivers/mfd/tps65911-comparator.o drivers/mfd/tps65911-comparator.c: In function 'tps65911_comparator_probe': drivers/mfd/tps65911-comparator.c:131: error: 'struct tps65910_platform_data' has no member named 'vmbch_threshold' drivers/mfd/tps65911-comparator.c:137: error: 'struct tps65910_platform_data' has no member named 'vmbch2_threshold' make[2]: *** [drivers/mfd/tps65911-comparator.o] Error 1 make[1]: *** [drivers/mfd] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/tps65911-comparator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c index 3d2dc56a3d40..283ac6759757 100644 --- a/drivers/mfd/tps65911-comparator.c +++ b/drivers/mfd/tps65911-comparator.c @@ -125,7 +125,7 @@ static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL); static __devinit int tps65911_comparator_probe(struct platform_device *pdev) { struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); - struct tps65910_platform_data *pdata = dev_get_platdata(tps65910->dev); + struct tps65910_board *pdata = dev_get_platdata(tps65910->dev); int ret; ret = comp_threshold_set(tps65910, COMP1, pdata->vmbch_threshold); -- cgit v1.2.3 From 8509e142567d69e170a184ecf27d7a6a3239fd72 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 23 Jun 2011 10:15:51 +0800 Subject: mfd: Add Makefile and Kconfig Entries for tps65911 comparator Base on Mark's comment [1], I make the Kconfig entry invisible to users. [1] https://lkml.org/lkml/2011/5/14/136 Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 3 +++ drivers/mfd/Makefile | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 0f09c057e796..6ca938a6bf94 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -728,6 +728,9 @@ config MFD_TPS65910 if you say yes here you get support for the TPS65910 series of Power Management chips. +config TPS65911_COMPARATOR + tristate + endif # MFD_SUPPORT menu "Multimedia Capabilities Port drivers" diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index efe3cc33ed92..d7d47d2a4c76 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -94,3 +94,4 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o +obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o -- cgit v1.2.3 From e4c2fb0d5776b58049d2556b456144a4db3fe5a9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 5 Jul 2011 10:56:32 +0200 Subject: sched: Disable (revert) SCHED_LOAD_SCALE increase Alex reported that commit c8b281161df ("sched: Increase SCHED_LOAD_SCALE resolution") caused a power usage regression under light load as it increases the number of load-balance operations and keeps idle cpus from staying idle. Time has run out to find the root cause for this release so disable the feature for v3.0 until we can figure out what causes the problem. Reported-by: "Alex, Shi" Signed-off-by: Peter Zijlstra Cc: Nikhil Rao Cc: Ming Lei Cc: Mike Galbraith Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/n/tip-m4onxn0sxnyn5iz9o88eskc3@git.kernel.org Signed-off-by: Ingo Molnar --- include/linux/sched.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index a837b20ba190..496770a96487 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -808,7 +808,7 @@ enum cpu_idle_type { * when BITS_PER_LONG <= 32 are pretty high and the returns do not justify the * increased costs. */ -#if BITS_PER_LONG > 32 +#if 0 /* BITS_PER_LONG > 32 -- currently broken: it increases power usage under light load */ # define SCHED_LOAD_RESOLUTION 10 # define scale_load(w) ((w) << SCHED_LOAD_RESOLUTION) # define scale_load_down(w) ((w) >> SCHED_LOAD_RESOLUTION) -- cgit v1.2.3 From f4f38430c94c38187db73a2cf3892cc8b12a2713 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 1 Jul 2011 14:38:12 +0100 Subject: ARM: 6989/1: perf: do not start the PMU when no events are present armpmu_enable can be called in situations where no events are present (for example, from the event rotation tick after a profiled task has exited). In this case, we currently start the PMU anyway which may leave it active inevitably without any events being monitored. This patch adds a simple check to the enabling code so that we avoid starting the PMU when no events are present. Cc: Reported-by: Ashwin Chaugle Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/perf_event.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index d53c0abc4dd3..2b5b1421596c 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -583,7 +583,7 @@ static int armpmu_event_init(struct perf_event *event) static void armpmu_enable(struct pmu *pmu) { /* Enable all of the perf events on hardware. */ - int idx; + int idx, enabled = 0; struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); if (!armpmu) @@ -596,9 +596,11 @@ static void armpmu_enable(struct pmu *pmu) continue; armpmu->enable(&event->hw, idx); + enabled = 1; } - armpmu->start(); + if (enabled) + armpmu->start(); } static void armpmu_disable(struct pmu *pmu) -- cgit v1.2.3 From 6f96521fab978046070a697926cf351c2c37af29 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 1 Jul 2011 14:38:53 +0100 Subject: ARM: 6990/1: MAINTAINERS: add entry for ARM PMU profiling and debugging Following a request from Russell King: http://lists.infradead.org/pipermail/linux-arm-kernel/2011-June/055031.html Add myself as the ARM PMU profiling and debugging maintainer. This covers the ARM implementations of perf, oprofile and hw_breakpoint along with the glue for this to work on different platforms. Cc: Jean Pihet Acked-by: Jamie Iles Acked-by: Linus Walleij Signed-off-by: Will Deacon Signed-off-by: Russell King --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d2dcef7cd9b2..ec32825ca319 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -594,6 +594,16 @@ S: Maintained F: arch/arm/lib/floppydma.S F: arch/arm/include/asm/floppy.h +ARM PMU PROFILING AND DEBUGGING +M: Will Deacon +S: Maintained +F: arch/arm/kernel/perf_event* +F: arch/arm/oprofile/common.c +F: arch/arm/kernel/pmu.c +F: arch/arm/include/asm/pmu.h +F: arch/arm/kernel/hw_breakpoint.c +F: arch/arm/include/asm/hw_breakpoint.h + ARM PORT M: Russell King L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -- cgit v1.2.3 From 873bd4cb4fbba6a3e99f750e17ef2ba6ef96e9d3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 5 Jul 2011 09:25:59 +0200 Subject: ASoC: Don't set invalid name string to snd_card->driver field The snd_card->driver field contains a driver name string, and in general it shouldn't contain space or special letters. The commit 2b39535b9e54888649923beaab443af212b6c0fd changed the string copy from card->name, but the long name string may contain such letters, thus it may still lead to a segfault. A temporary fix is not to copy the long name string but just keep it empty as the earlier version did. Reported-by: Kuninori Morimoto Acked-by: Liam Girdwood Signed-off-by: Takashi Iwai --- sound/soc/soc-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d75043ed7fc0..b194be09e74d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1929,8 +1929,9 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) "%s", card->name); snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), "%s", card->long_name ? card->long_name : card->name); - snprintf(card->snd_card->driver, sizeof(card->snd_card->driver), - "%s", card->driver_name ? card->driver_name : card->name); + if (card->driver_name) + strlcpy(card->snd_card->driver, card->driver_name, + sizeof(card->snd_card->driver)); if (card->late_probe) { ret = card->late_probe(card); -- cgit v1.2.3 From 4c7c5374ce6876d3d2c7013ef815051df4258952 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 4 Jul 2011 10:27:51 -0700 Subject: ASoC: Manage WM8731 ACTIVE bit as a supply widget Now we have supply widgets there's no need to open code the handling of the ACTIVE bit. Signed-off-by: Mark Brown Tested-by: Nicolas Ferre Acked-by: Liam Girdwood --- sound/soc/codecs/wm8731.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 2dc964b55e4f..76b4361e9b80 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -175,6 +175,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls = SOC_DAPM_ENUM("Input Select", wm8731_insel_enum); static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { +SND_SOC_DAPM_SUPPLY("ACTIVE",WM8731_ACTIVE, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0), SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, &wm8731_output_mixer_controls[0], @@ -204,6 +205,8 @@ static int wm8731_check_osc(struct snd_soc_dapm_widget *source, static const struct snd_soc_dapm_route wm8731_intercon[] = { {"DAC", NULL, "OSC", wm8731_check_osc}, {"ADC", NULL, "OSC", wm8731_check_osc}, + {"DAC", NULL, "ACTIVE"}, + {"ADC", NULL, "ACTIVE"}, /* output mixer */ {"Output Mixer", "Line Bypass Switch", "Line Input"}, @@ -315,29 +318,6 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, return 0; } -static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - - /* set active */ - snd_soc_write(codec, WM8731_ACTIVE, 0x0001); - - return 0; -} - -static void wm8731_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - - /* deactivate */ - if (!codec->active) { - udelay(50); - snd_soc_write(codec, WM8731_ACTIVE, 0x0); - } -} - static int wm8731_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; @@ -480,7 +460,6 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, snd_soc_write(codec, WM8731_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8731_ACTIVE, 0x0); snd_soc_write(codec, WM8731_PWR, 0xffff); regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); @@ -496,9 +475,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, SNDRV_PCM_FMTBIT_S24_LE) static struct snd_soc_dai_ops wm8731_dai_ops = { - .prepare = wm8731_pcm_prepare, .hw_params = wm8731_hw_params, - .shutdown = wm8731_shutdown, .digital_mute = wm8731_mute, .set_sysclk = wm8731_set_dai_sysclk, .set_fmt = wm8731_set_dai_fmt, -- cgit v1.2.3 From 0371d3f7e8f1cddaee1f215e42c09a40e235d810 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 5 Jul 2011 19:58:29 +0100 Subject: ARM: move memory layout sanity checking before meminfo initialization Ensure that the meminfo array is sanity checked before we pass the memory to memblock. This helps to ensure that memblock and meminfo agree on the dimensions of memory, especially when more memory is passed than the kernel can deal with. Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 2 ++ arch/arm/mm/mmu.c | 5 +++-- arch/arm/mm/nommu.c | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index ed11fb08b05a..acbb447ac6b5 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -73,6 +73,7 @@ __setup("fpe=", fpe_setup); #endif extern void paging_init(struct machine_desc *desc); +extern void sanity_check_meminfo(void); extern void reboot_setup(char *str); unsigned int processor_id; @@ -900,6 +901,7 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); + sanity_check_meminfo(); arm_memblock_init(&meminfo, mdesc); paging_init(mdesc); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9d9e736c2b4f..594d677b92c8 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -759,7 +759,7 @@ early_param("vmalloc", early_vmalloc); static phys_addr_t lowmem_limit __initdata = 0; -static void __init sanity_check_meminfo(void) +void __init sanity_check_meminfo(void) { int i, j, highmem = 0; @@ -1032,8 +1032,9 @@ void __init paging_init(struct machine_desc *mdesc) { void *zero_page; + memblock_set_current_limit(lowmem_limit); + build_mem_type_table(); - sanity_check_meminfo(); prepare_page_table(); map_lowmem(); devicemaps_init(mdesc); diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 687d02319a41..941a98c9e8aa 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -27,6 +27,10 @@ void __init arm_mm_memblock_reserve(void) memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE); } +void __init sanity_check_meminfo(void) +{ +} + /* * paging_init() sets up the page tables, initialises the zone memory * maps, and sets up the zero page, bad page and bad page tables. -- cgit v1.2.3 From a0d8efedb203b5b908dd46cea38201761e2380f9 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 16 Jun 2011 16:12:35 +0900 Subject: ARM: EXYNOS4: Fix card detection for sdhci 0 and 2 On SMDKV310 board, a card detect gpio pin is available that is directly connected to the io pad of the sdhci controller. Fix incorrect value of cd_type field in platform data for sdhci instance 0 and 2. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/mach-smdkv310.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c index 152676471b67..edd814110da8 100644 --- a/arch/arm/mach-exynos4/mach-smdkv310.c +++ b/arch/arm/mach-exynos4/mach-smdkv310.c @@ -78,9 +78,7 @@ static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = { }; static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = { - .cd_type = S3C_SDHCI_CD_GPIO, - .ext_cd_gpio = EXYNOS4_GPK0(2), - .ext_cd_gpio_invert = 1, + .cd_type = S3C_SDHCI_CD_INTERNAL, .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, #ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT .max_width = 8, @@ -96,9 +94,7 @@ static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = { }; static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = { - .cd_type = S3C_SDHCI_CD_GPIO, - .ext_cd_gpio = EXYNOS4_GPK2(2), - .ext_cd_gpio_invert = 1, + .cd_type = S3C_SDHCI_CD_INTERNAL, .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, #ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT .max_width = 8, -- cgit v1.2.3 From a3df1d4811bb7710d6497334e3b6a37064527684 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Chatradhi Date: Thu, 16 Jun 2011 19:33:29 +0900 Subject: ARM: EXYNOS4: fix improper gpio configuration These pins are incorrectly configured for PCM2 configure them to SPDIF(_OUT & _EXT_CLK) Signed-off-by: Naveen Krishna Chatradhi Acked-by: Jassi Brar Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/dev-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos4/dev-audio.c b/arch/arm/mach-exynos4/dev-audio.c index 1eed5f9f7bd3..983069a53239 100644 --- a/arch/arm/mach-exynos4/dev-audio.c +++ b/arch/arm/mach-exynos4/dev-audio.c @@ -330,7 +330,7 @@ struct platform_device exynos4_device_ac97 = { static int exynos4_spdif_cfg_gpio(struct platform_device *pdev) { - s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 2, S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 2, S3C_GPIO_SFN(4)); return 0; } -- cgit v1.2.3 From bb8bb57b213f63ffba29b3a7f1c7974782b8127d Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Wed, 22 Jun 2011 18:03:21 +0900 Subject: ARM: SAMSUNG: header file revised to prevent declaring duplicated There has been no #ifndef - #define - #endif protection for this header file. Signed-off-by: MyungJoo Ham Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/devs.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 4af108ff4112..e3b31c26ac3e 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -12,6 +12,10 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + +#ifndef __PLAT_DEVS_H +#define __PLAT_DEVS_H __FILE__ + #include struct s3c24xx_uart_resources { @@ -159,3 +163,5 @@ extern struct platform_device s3c_device_ac97; */ extern void *s3c_set_platdata(void *pd, size_t pdsize, struct platform_device *pdev); + +#endif /* __PLAT_DEVS_H */ -- cgit v1.2.3 From 27ea7fd2889eb93041480b18de655b1ff003e05d Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Thu, 23 Jun 2011 21:43:58 +0900 Subject: ARM: S5P: Fix bug on init of PWMTimers for HRTimer This patch fixes following. <6>[ 0.000000] sched_clock: 32 bits at 33MHz, ... <6>[ 128.651309] Calibrating delay loop... There is a big jump. The reason is that PWM Timer which is for HRTimer was used before its initialization. So this patch changes its order and following is kernel boot log message after this. <6>[ 0.000000] sched_clock: 32 bits at 33MHz, ... <6>[ 0.000088] Calibrating delay loop... Signed-off-by: Sangbeom Kim Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/s5p-time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c index 899a8cc011ff..612934c48b0d 100644 --- a/arch/arm/plat-s5p/s5p-time.c +++ b/arch/arm/plat-s5p/s5p-time.c @@ -370,11 +370,11 @@ static void __init s5p_clocksource_init(void) clock_rate = clk_get_rate(tin_source); - init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate); - s5p_time_setup(timer_source.source_id, TCNT_MAX); s5p_time_start(timer_source.source_id, PERIODIC); + init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate); + if (clocksource_register_hz(&time_clocksource, clock_rate)) panic("%s: can't register clocksource\n", time_clocksource.name); } -- cgit v1.2.3 From 152c036a8096ed219c965957acb63490a2c0c963 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Mon, 4 Jul 2011 19:03:54 +0900 Subject: ARM: EXYNOS4: Address a section mismatch w/ suspend issue. The section mismatch in headsmp.S made hotplug stop working after the first instance of suspend-to-RAM and its wakeup. Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/headsmp.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos4/headsmp.S b/arch/arm/mach-exynos4/headsmp.S index 6c6cfc50c46b..3cdeb3647542 100644 --- a/arch/arm/mach-exynos4/headsmp.S +++ b/arch/arm/mach-exynos4/headsmp.S @@ -13,7 +13,7 @@ #include #include - __INIT + __CPUINIT /* * exynos4 specific entry point for secondary CPUs. This provides -- cgit v1.2.3 From 44661462ee1ee3c922754fc1f246867f0d01e7ea Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 5 Jul 2011 13:58:33 +0000 Subject: bridge: Always flood broadcast packets As is_multicast_ether_addr returns true on broadcast packets as well, we need to explicitly exclude broadcast packets so that they're always flooded. This wasn't an issue before as broadcast packets were considered to be an unregistered multicast group, which were always flooded. However, as we now only flood such packets to router ports, this is no longer acceptable. Reported-by: Michael Guntsche Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_device.c | 4 +++- net/bridge/br_input.c | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index c188c803c09c..32b8f9f7f79e 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -49,7 +49,9 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) skb_pull(skb, ETH_HLEN); rcu_read_lock(); - if (is_multicast_ether_addr(dest)) { + if (is_broadcast_ether_addr(dest)) + br_flood_deliver(br, skb); + else if (is_multicast_ether_addr(dest)) { if (unlikely(netpoll_tx_running(dev))) { br_flood_deliver(br, skb); goto out; diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index f3ac1e858ee1..f06ee39c73fd 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -60,7 +60,7 @@ int br_handle_frame_finish(struct sk_buff *skb) br = p->br; br_fdb_update(br, p, eth_hdr(skb)->h_source); - if (is_multicast_ether_addr(dest) && + if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && br_multicast_rcv(br, p, skb)) goto drop; @@ -77,7 +77,9 @@ int br_handle_frame_finish(struct sk_buff *skb) dst = NULL; - if (is_multicast_ether_addr(dest)) { + if (is_broadcast_ether_addr(dest)) + skb2 = skb; + else if (is_multicast_ether_addr(dest)) { mdst = br_mdb_get(br, skb); if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) { if ((mdst && mdst->mglist) || -- cgit v1.2.3 From 5318d809d7b4975ce5e5303e8508f89a5458c2b6 Mon Sep 17 00:00:00 2001 From: Shreyas Bhatewara Date: Tue, 5 Jul 2011 14:34:05 +0000 Subject: vmxnet3: fix starving rx ring whenoc_skb kb fails If the rx ring is completely empty, then the device may never fire an rx interrupt. Unfortunately, the rx interrupt is what triggers populating the rx ring with fresh buffers, so this will cause networking to lock up. This patch replenishes the skb in recv descriptor as soon as it is peeled off while processing rx completions. If the skb/buffer allocation fails, existing one is recycled and the packet in hand is dropped. This way none of the RX desc is ever left empty, thus avoiding starvation Signed-off-by: Scott J. Goldman Signed-off-by: Shreyas N Bhatewara Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 135 ++++++++++++++++++++++++++------------ drivers/net/vmxnet3/vmxnet3_int.h | 4 +- 2 files changed, 96 insertions(+), 43 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index fa6e2ac7475a..45a23b2599f3 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -575,7 +575,7 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx, struct vmxnet3_cmd_ring *ring = &rq->rx_ring[ring_idx]; u32 val; - while (num_allocated < num_to_alloc) { + while (num_allocated <= num_to_alloc) { struct vmxnet3_rx_buf_info *rbi; union Vmxnet3_GenericDesc *gd; @@ -621,9 +621,15 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx, BUG_ON(rbi->dma_addr == 0); gd->rxd.addr = cpu_to_le64(rbi->dma_addr); - gd->dword[2] = cpu_to_le32((ring->gen << VMXNET3_RXD_GEN_SHIFT) + gd->dword[2] = cpu_to_le32((!ring->gen << VMXNET3_RXD_GEN_SHIFT) | val | rbi->len); + /* Fill the last buffer but dont mark it ready, or else the + * device will think that the queue is full */ + if (num_allocated == num_to_alloc) + break; + + gd->dword[2] |= cpu_to_le32(ring->gen << VMXNET3_RXD_GEN_SHIFT); num_allocated++; vmxnet3_cmd_ring_adv_next2fill(ring); } @@ -1140,6 +1146,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2 }; u32 num_rxd = 0; + bool skip_page_frags = false; struct Vmxnet3_RxCompDesc *rcd; struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx; #ifdef __BIG_ENDIAN_BITFIELD @@ -1150,11 +1157,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, &rxComp); while (rcd->gen == rq->comp_ring.gen) { struct vmxnet3_rx_buf_info *rbi; - struct sk_buff *skb; + struct sk_buff *skb, *new_skb = NULL; + struct page *new_page = NULL; int num_to_alloc; struct Vmxnet3_RxDesc *rxd; u32 idx, ring_idx; - + struct vmxnet3_cmd_ring *ring = NULL; if (num_rxd >= quota) { /* we may stop even before we see the EOP desc of * the current pkt @@ -1165,6 +1173,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2); idx = rcd->rxdIdx; ring_idx = rcd->rqID < adapter->num_rx_queues ? 0 : 1; + ring = rq->rx_ring + ring_idx; vmxnet3_getRxDesc(rxd, &rq->rx_ring[ring_idx].base[idx].rxd, &rxCmdDesc); rbi = rq->buf_info[ring_idx] + idx; @@ -1193,37 +1202,80 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, goto rcd_done; } + skip_page_frags = false; ctx->skb = rbi->skb; - rbi->skb = NULL; + new_skb = dev_alloc_skb(rbi->len + NET_IP_ALIGN); + if (new_skb == NULL) { + /* Skb allocation failed, do not handover this + * skb to stack. Reuse it. Drop the existing pkt + */ + rq->stats.rx_buf_alloc_failure++; + ctx->skb = NULL; + rq->stats.drop_total++; + skip_page_frags = true; + goto rcd_done; + } pci_unmap_single(adapter->pdev, rbi->dma_addr, rbi->len, PCI_DMA_FROMDEVICE); skb_put(ctx->skb, rcd->len); + + /* Immediate refill */ + new_skb->dev = adapter->netdev; + skb_reserve(new_skb, NET_IP_ALIGN); + rbi->skb = new_skb; + rbi->dma_addr = pci_map_single(adapter->pdev, + rbi->skb->data, rbi->len, + PCI_DMA_FROMDEVICE); + rxd->addr = cpu_to_le64(rbi->dma_addr); + rxd->len = rbi->len; + } else { - BUG_ON(ctx->skb == NULL); + BUG_ON(ctx->skb == NULL && !skip_page_frags); + /* non SOP buffer must be type 1 in most cases */ - if (rbi->buf_type == VMXNET3_RX_BUF_PAGE) { - BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_BODY); + BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_PAGE); + BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_BODY); - if (rcd->len) { - pci_unmap_page(adapter->pdev, - rbi->dma_addr, rbi->len, - PCI_DMA_FROMDEVICE); + /* If an sop buffer was dropped, skip all + * following non-sop fragments. They will be reused. + */ + if (skip_page_frags) + goto rcd_done; - vmxnet3_append_frag(ctx->skb, rcd, rbi); - rbi->page = NULL; - } - } else { - /* - * The only time a non-SOP buffer is type 0 is - * when it's EOP and error flag is raised, which - * has already been handled. + new_page = alloc_page(GFP_ATOMIC); + if (unlikely(new_page == NULL)) { + /* Replacement page frag could not be allocated. + * Reuse this page. Drop the pkt and free the + * skb which contained this page as a frag. Skip + * processing all the following non-sop frags. */ - BUG_ON(true); + rq->stats.rx_buf_alloc_failure++; + dev_kfree_skb(ctx->skb); + ctx->skb = NULL; + skip_page_frags = true; + goto rcd_done; + } + + if (rcd->len) { + pci_unmap_page(adapter->pdev, + rbi->dma_addr, rbi->len, + PCI_DMA_FROMDEVICE); + + vmxnet3_append_frag(ctx->skb, rcd, rbi); } + + /* Immediate refill */ + rbi->page = new_page; + rbi->dma_addr = pci_map_page(adapter->pdev, rbi->page, + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + rxd->addr = cpu_to_le64(rbi->dma_addr); + rxd->len = rbi->len; } + skb = ctx->skb; if (rcd->eop) { skb->len += skb->data_len; @@ -1244,26 +1296,27 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, } rcd_done: - /* device may skip some rx descs */ - rq->rx_ring[ring_idx].next2comp = idx; - VMXNET3_INC_RING_IDX_ONLY(rq->rx_ring[ring_idx].next2comp, - rq->rx_ring[ring_idx].size); - - /* refill rx buffers frequently to avoid starving the h/w */ - num_to_alloc = vmxnet3_cmd_ring_desc_avail(rq->rx_ring + - ring_idx); - if (unlikely(num_to_alloc > VMXNET3_RX_ALLOC_THRESHOLD(rq, - ring_idx, adapter))) { - vmxnet3_rq_alloc_rx_buf(rq, ring_idx, num_to_alloc, - adapter); - - /* if needed, update the register */ - if (unlikely(rq->shared->updateRxProd)) { - VMXNET3_WRITE_BAR0_REG(adapter, - rxprod_reg[ring_idx] + rq->qid * 8, - rq->rx_ring[ring_idx].next2fill); - rq->uncommitted[ring_idx] = 0; - } + /* device may have skipped some rx descs */ + ring->next2comp = idx; + num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring); + ring = rq->rx_ring + ring_idx; + while (num_to_alloc) { + vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd, + &rxCmdDesc); + BUG_ON(!rxd->addr); + + /* Recv desc is ready to be used by the device */ + rxd->gen = ring->gen; + vmxnet3_cmd_ring_adv_next2fill(ring); + num_to_alloc--; + } + + /* if needed, update the register */ + if (unlikely(rq->shared->updateRxProd)) { + VMXNET3_WRITE_BAR0_REG(adapter, + rxprod_reg[ring_idx] + rq->qid * 8, + ring->next2fill); + rq->uncommitted[ring_idx] = 0; } vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring); diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index f50d36fdf405..8db7ecf5bcab 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -68,10 +68,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.1.9.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.1.14.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01010900 +#define VMXNET3_DRIVER_VERSION_NUM 0x01010E00 #if defined(CONFIG_PCI_MSI) /* RSS only makes sense if MSI-X is supported. */ -- cgit v1.2.3 From b49c78d4827be8d7e67e5b94adac6b30a4a9ad14 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Wed, 6 Jul 2011 10:56:30 +1000 Subject: x86, reboot: Acer Aspire One A110 reboot quirk Since git commit 660e34cebf0a11d54f2d5dd8838607452355f321 x86: reorder reboot method preferences, my Acer Aspire One hangs on reboot. It appears that its ACPI method for rebooting is broken. The attached patch adds a quirk so that the machine will reboot via the BIOS. [ hpa: verified that the ACPI control on this machine is just plain broken. ] Signed-off-by: Peter Chubb Link: http://lkml.kernel.org/r/w439iki5vl.wl%25peter@chubb.wattle.id.au Signed-off-by: H. Peter Anvin --- arch/x86/kernel/reboot.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 0c016f727695..4f0d46fefa7f 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -294,6 +294,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"), }, }, + { /* Handle reboot issue on Acer Aspire one */ + .callback = set_bios_reboot, + .ident = "Acer Aspire One A110", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"), + }, + }, { } }; -- cgit v1.2.3 From 712ae51afd55b20c04c5383d02ba5d10233313b1 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 5 Jul 2011 20:43:12 -0700 Subject: net: vlan: enable soft features regardless of underlying device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If gso/gro feature of underlying device is turned off, then new created vlan device never can turn gso/gro on. Although underlying device don't support TSO, we still should use software segments for vlan device. Signed-off-by: Shan Wei Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 7ea5cf9ea08a..86bff9b1ac47 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -586,9 +586,14 @@ static void vlan_dev_uninit(struct net_device *dev) static u32 vlan_dev_fix_features(struct net_device *dev, u32 features) { struct net_device *real_dev = vlan_dev_info(dev)->real_dev; + u32 old_features = features; features &= real_dev->features; features &= real_dev->vlan_features; + + if (old_features & NETIF_F_SOFT_FEATURES) + features |= old_features & NETIF_F_SOFT_FEATURES; + if (dev_ethtool_get_rx_csum(real_dev)) features |= NETIF_F_RXCSUM; features |= NETIF_F_LLTX; -- cgit v1.2.3 From 58956ba23e2dce83e78cd212cc8305261647684f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Jul 2011 10:08:27 +0800 Subject: gpio: tps65910: add missing breaks in tps65910_gpio_init Signed-off-by: Axel Lin Signed-off-by: Grant Likely --- drivers/gpio/tps65910-gpio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/tps65910-gpio.c b/drivers/gpio/tps65910-gpio.c index 8d1ddfdd63eb..15097ca616d6 100644 --- a/drivers/gpio/tps65910-gpio.c +++ b/drivers/gpio/tps65910-gpio.c @@ -81,8 +81,10 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) switch(tps65910_chip_id(tps65910)) { case TPS65910: tps65910->gpio.ngpio = 6; + break; case TPS65911: tps65910->gpio.ngpio = 9; + break; default: return; } -- cgit v1.2.3 From 8918034dfb7b0f625ba9eb0329d5750a9573f62e Mon Sep 17 00:00:00 2001 From: Padmavathi Venna Date: Tue, 5 Jul 2011 17:13:56 +0900 Subject: ARM: SAMSUNG: Add tx_st_done variable tx_st_done is required for checking the transmission status of SPI channels with different fifo levels Signed-off-by: Padmavathi Venna Acked-by: Jassi Brar Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/dev-spi.c | 2 ++ arch/arm/mach-s5p64x0/dev-spi.c | 4 ++++ arch/arm/mach-s5pc100/dev-spi.c | 3 +++ arch/arm/mach-s5pv210/dev-spi.c | 2 ++ arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 2 ++ 5 files changed, 13 insertions(+) diff --git a/arch/arm/mach-s3c64xx/dev-spi.c b/arch/arm/mach-s3c64xx/dev-spi.c index 82db072cb836..5e6b42089eb4 100644 --- a/arch/arm/mach-s3c64xx/dev-spi.c +++ b/arch/arm/mach-s3c64xx/dev-spi.c @@ -88,6 +88,7 @@ static struct s3c64xx_spi_info s3c64xx_spi0_pdata = { .cfg_gpio = s3c64xx_spi_cfg_gpio, .fifo_lvl_mask = 0x7f, .rx_lvl_offset = 13, + .tx_st_done = 21, }; static u64 spi_dmamask = DMA_BIT_MASK(32); @@ -132,6 +133,7 @@ static struct s3c64xx_spi_info s3c64xx_spi1_pdata = { .cfg_gpio = s3c64xx_spi_cfg_gpio, .fifo_lvl_mask = 0x7f, .rx_lvl_offset = 13, + .tx_st_done = 21, }; struct platform_device s3c64xx_device_spi1 = { diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c index e78ee18c76e3..ac825e826326 100644 --- a/arch/arm/mach-s5p64x0/dev-spi.c +++ b/arch/arm/mach-s5p64x0/dev-spi.c @@ -112,12 +112,14 @@ static struct s3c64xx_spi_info s5p6440_spi0_pdata = { .cfg_gpio = s5p6440_spi_cfg_gpio, .fifo_lvl_mask = 0x1ff, .rx_lvl_offset = 15, + .tx_st_done = 25, }; static struct s3c64xx_spi_info s5p6450_spi0_pdata = { .cfg_gpio = s5p6450_spi_cfg_gpio, .fifo_lvl_mask = 0x1ff, .rx_lvl_offset = 15, + .tx_st_done = 25, }; static u64 spi_dmamask = DMA_BIT_MASK(32); @@ -160,12 +162,14 @@ static struct s3c64xx_spi_info s5p6440_spi1_pdata = { .cfg_gpio = s5p6440_spi_cfg_gpio, .fifo_lvl_mask = 0x7f, .rx_lvl_offset = 15, + .tx_st_done = 25, }; static struct s3c64xx_spi_info s5p6450_spi1_pdata = { .cfg_gpio = s5p6450_spi_cfg_gpio, .fifo_lvl_mask = 0x7f, .rx_lvl_offset = 15, + .tx_st_done = 25, }; struct platform_device s5p64x0_device_spi1 = { diff --git a/arch/arm/mach-s5pc100/dev-spi.c b/arch/arm/mach-s5pc100/dev-spi.c index 57b19794d9bb..2b58c9a2cf70 100644 --- a/arch/arm/mach-s5pc100/dev-spi.c +++ b/arch/arm/mach-s5pc100/dev-spi.c @@ -90,6 +90,7 @@ static struct s3c64xx_spi_info s5pc100_spi0_pdata = { .fifo_lvl_mask = 0x7f, .rx_lvl_offset = 13, .high_speed = 1, + .tx_st_done = 21, }; static u64 spi_dmamask = DMA_BIT_MASK(32); @@ -134,6 +135,7 @@ static struct s3c64xx_spi_info s5pc100_spi1_pdata = { .fifo_lvl_mask = 0x7f, .rx_lvl_offset = 13, .high_speed = 1, + .tx_st_done = 21, }; struct platform_device s5pc100_device_spi1 = { @@ -176,6 +178,7 @@ static struct s3c64xx_spi_info s5pc100_spi2_pdata = { .fifo_lvl_mask = 0x7f, .rx_lvl_offset = 13, .high_speed = 1, + .tx_st_done = 21, }; struct platform_device s5pc100_device_spi2 = { diff --git a/arch/arm/mach-s5pv210/dev-spi.c b/arch/arm/mach-s5pv210/dev-spi.c index e3249a47e3b1..eaf9a7bff7a0 100644 --- a/arch/arm/mach-s5pv210/dev-spi.c +++ b/arch/arm/mach-s5pv210/dev-spi.c @@ -85,6 +85,7 @@ static struct s3c64xx_spi_info s5pv210_spi0_pdata = { .fifo_lvl_mask = 0x1ff, .rx_lvl_offset = 15, .high_speed = 1, + .tx_st_done = 25, }; static u64 spi_dmamask = DMA_BIT_MASK(32); @@ -129,6 +130,7 @@ static struct s3c64xx_spi_info s5pv210_spi1_pdata = { .fifo_lvl_mask = 0x7f, .rx_lvl_offset = 15, .high_speed = 1, + .tx_st_done = 25, }; struct platform_device s5pv210_device_spi1 = { diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index 0ffe34a21554..4c16fa3621bb 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -39,6 +39,7 @@ struct s3c64xx_spi_csinfo { * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6 * @rx_lvl_offset: Depends on tx fifo_lvl field and bus number * @high_speed: If the controller supports HIGH_SPEED_EN bit + * @tx_st_done: Depends on tx fifo_lvl field */ struct s3c64xx_spi_info { int src_clk_nr; @@ -53,6 +54,7 @@ struct s3c64xx_spi_info { int fifo_lvl_mask; int rx_lvl_offset; int high_speed; + int tx_st_done; }; /** -- cgit v1.2.3 From 3075741417d47cccc890ed30da9ece666006553a Mon Sep 17 00:00:00 2001 From: Padmavathi Venna Date: Tue, 5 Jul 2011 17:14:02 +0900 Subject: spi/s3c64xx: Bug fix for SPI with different FIFO level The existing macro fails for following scenarios. 1) S5P64X0 channel 1 2) S5PV210 channel 1 The FIFO data level supported in the above SoCs either 64 or 256 bytes depending on the channel. Because of this the TX_DONE is the 25 bit in the status register. The existing macro works for the following scenarios 1) S3C6410 all channels 2) S5PC100 all channels The FIFO data level supported in the above SoCs 64 bytes on all the channels. Because of this the TX_DONE is the 21 bit in the status register. So when we use the existing macro for the non-working SoCs it is not anding with the TX_DONE bit for transmission status check. Signed-off-by: Padmavathi Venna Acked-by: Jassi Brar Acked-by: Grant Likely Signed-off-by: Kukjin Kim --- drivers/spi/spi_s3c64xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c index 795828b90f45..8945e201e42e 100644 --- a/drivers/spi/spi_s3c64xx.c +++ b/drivers/spi/spi_s3c64xx.c @@ -116,9 +116,7 @@ (((i)->fifo_lvl_mask + 1))) \ ? 1 : 0) -#define S3C64XX_SPI_ST_TX_DONE(v, i) ((((v) >> (i)->rx_lvl_offset) & \ - (((i)->fifo_lvl_mask + 1) << 1)) \ - ? 1 : 0) +#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0) #define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask) #define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask) -- cgit v1.2.3 From 8fa9dd04b7f7ab1807ebcc274601dd8e2d215569 Mon Sep 17 00:00:00 2001 From: Padmavathi Venna Date: Wed, 6 Jul 2011 15:37:08 +0900 Subject: ARM: S5PC100: Fix for compilation error S5PC100 Compilation fails without this patch Signed-off-by: Padmavathi Venna Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pc100/dev-spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-s5pc100/dev-spi.c b/arch/arm/mach-s5pc100/dev-spi.c index 57b19794d9bb..cd7ca47d8746 100644 --- a/arch/arm/mach-s5pc100/dev-spi.c +++ b/arch/arm/mach-s5pc100/dev-spi.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 91a5615203355bb34e0b9e68e94f27f24719a74c Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 5 Jul 2011 20:33:51 +0000 Subject: net: sh_eth: fix cannot work half-duplex mode When link was down, the bit of DM in ECMR was always set. So, we could not use half-duplex mode on the controller. Signed-off-by: Yoshihiro Shimoda Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 8a72a979ee71..35bbc2718c13 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -1184,8 +1184,8 @@ static void sh_eth_adjust_link(struct net_device *ndev) mdp->cd->set_rate(ndev); } if (mdp->link == PHY_DOWN) { - sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_TXF) - | ECMR_DM, ECMR); + sh_eth_write(ndev, + (sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR); new_state = 1; mdp->link = phydev->link; } -- cgit v1.2.3 From 2e98e7974de208de0dab9e9969bd47576d07ff10 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 5 Jul 2011 20:33:57 +0000 Subject: net: sh_eth: fix the parameter for the ETHER of SH7757 If the driver didn't set this parameter on the ETHER, the CPU will encounter the "data address error" exception. Signed-off-by: Yoshihiro Shimoda Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 35bbc2718c13..1f3f7b4dd638 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -140,6 +140,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .tpauser = 1, .hw_swap = 1, .no_ade = 1, + .rpadir = 1, + .rpadir_value = 2 << 16, }; #define SH_GIGA_ETH_BASE 0xfee00000 -- cgit v1.2.3 From 5f27275edb7082505eaac1c85a15620207351b63 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 6 Jul 2011 16:04:09 +0900 Subject: ARM: EXYNOS4: Set appropriate I2C device variant Set up a correct I2C bus controller variant name for Exynos4. Without this change the I2C bus driver fails to acquire its clocks. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 9babe4473e88..bfd621460abf 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -132,6 +133,11 @@ void __init exynos4_map_io(void) s3c_fimc_setname(1, "exynos4-fimc"); s3c_fimc_setname(2, "exynos4-fimc"); s3c_fimc_setname(3, "exynos4-fimc"); + + /* The I2C bus controllers are directly compatible with s3c2440 */ + s3c_i2c0_setname("s3c2440-i2c"); + s3c_i2c1_setname("s3c2440-i2c"); + s3c_i2c2_setname("s3c2440-i2c"); } void __init exynos4_init_clocks(int xtal) -- cgit v1.2.3 From a51cb91d81f8e6fc4e5e08b772cc3ceb13ac9d37 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 6 Jul 2011 12:33:55 +0200 Subject: fs: fix lock initialization locks_alloc_lock() assumed that the allocated struct file_lock is already initialized to zero members. This is only true for the first allocation of the structure, after reuse some of the members will have random values. This will for example result in passing random fl_start values to userspace in fuse for FL_FLOCK locks, which is an information leak at best. Fix by reinitializing those members which may be non-zero after freeing. Signed-off-by: Miklos Szeredi CC: stable@kernel.org Signed-off-by: Linus Torvalds --- fs/locks.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index 0a4f50dfadfb..b286539d547a 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -160,10 +160,28 @@ EXPORT_SYMBOL_GPL(unlock_flocks); static struct kmem_cache *filelock_cache __read_mostly; +static void locks_init_lock_always(struct file_lock *fl) +{ + fl->fl_next = NULL; + fl->fl_fasync = NULL; + fl->fl_owner = NULL; + fl->fl_pid = 0; + fl->fl_nspid = NULL; + fl->fl_file = NULL; + fl->fl_flags = 0; + fl->fl_type = 0; + fl->fl_start = fl->fl_end = 0; +} + /* Allocate an empty lock structure. */ struct file_lock *locks_alloc_lock(void) { - return kmem_cache_alloc(filelock_cache, GFP_KERNEL); + struct file_lock *fl = kmem_cache_alloc(filelock_cache, GFP_KERNEL); + + if (fl) + locks_init_lock_always(fl); + + return fl; } EXPORT_SYMBOL_GPL(locks_alloc_lock); @@ -200,17 +218,9 @@ void locks_init_lock(struct file_lock *fl) INIT_LIST_HEAD(&fl->fl_link); INIT_LIST_HEAD(&fl->fl_block); init_waitqueue_head(&fl->fl_wait); - fl->fl_next = NULL; - fl->fl_fasync = NULL; - fl->fl_owner = NULL; - fl->fl_pid = 0; - fl->fl_nspid = NULL; - fl->fl_file = NULL; - fl->fl_flags = 0; - fl->fl_type = 0; - fl->fl_start = fl->fl_end = 0; fl->fl_ops = NULL; fl->fl_lmops = NULL; + locks_init_lock_always(fl); } EXPORT_SYMBOL(locks_init_lock); -- cgit v1.2.3 From 23c570a67448e803408191f529ed9a83fd34a25a Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Tue, 5 Jul 2011 23:44:30 -0700 Subject: resource: ability to resize an allocated resource Provides the ability to resize a resource that is already allocated. This functionality is put in place to support reallocation needs of pci resources. Signed-off-by: Ram Pai Acked-by: Jesse Barnes Signed-off-by: Linus Torvalds --- kernel/resource.c | 116 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 98 insertions(+), 18 deletions(-) diff --git a/kernel/resource.c b/kernel/resource.c index 798e2fae2a06..3ff40178dce7 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -38,6 +38,14 @@ struct resource iomem_resource = { }; EXPORT_SYMBOL(iomem_resource); +/* constraints to be met while allocating resources */ +struct resource_constraint { + resource_size_t min, max, align; + resource_size_t (*alignf)(void *, const struct resource *, + resource_size_t, resource_size_t); + void *alignf_data; +}; + static DEFINE_RWLOCK(resource_lock); static void *r_next(struct seq_file *m, void *v, loff_t *pos) @@ -384,16 +392,13 @@ static bool resource_contains(struct resource *res1, struct resource *res2) } /* - * Find empty slot in the resource tree given range and alignment. + * Find empty slot in the resource tree with the given range and + * alignment constraints */ -static int find_resource(struct resource *root, struct resource *new, - resource_size_t size, resource_size_t min, - resource_size_t max, resource_size_t align, - resource_size_t (*alignf)(void *, - const struct resource *, - resource_size_t, - resource_size_t), - void *alignf_data) +static int __find_resource(struct resource *root, struct resource *old, + struct resource *new, + resource_size_t size, + struct resource_constraint *constraint) { struct resource *this = root->child; struct resource tmp = *new, avail, alloc; @@ -404,25 +409,26 @@ static int find_resource(struct resource *root, struct resource *new, * Skip past an allocated resource that starts at 0, since the assignment * of this->start - 1 to tmp->end below would cause an underflow. */ - if (this && this->start == 0) { - tmp.start = this->end + 1; + if (this && this->start == root->start) { + tmp.start = (this == old) ? old->start : this->end + 1; this = this->sibling; } for(;;) { if (this) - tmp.end = this->start - 1; + tmp.end = (this == old) ? this->end : this->start - 1; else tmp.end = root->end; - resource_clip(&tmp, min, max); + resource_clip(&tmp, constraint->min, constraint->max); arch_remove_reservations(&tmp); /* Check for overflow after ALIGN() */ avail = *new; - avail.start = ALIGN(tmp.start, align); + avail.start = ALIGN(tmp.start, constraint->align); avail.end = tmp.end; if (avail.start >= tmp.start) { - alloc.start = alignf(alignf_data, &avail, size, align); + alloc.start = constraint->alignf(constraint->alignf_data, &avail, + size, constraint->align); alloc.end = alloc.start + size - 1; if (resource_contains(&avail, &alloc)) { new->start = alloc.start; @@ -432,14 +438,75 @@ static int find_resource(struct resource *root, struct resource *new, } if (!this) break; - tmp.start = this->end + 1; + if (this != old) + tmp.start = this->end + 1; this = this->sibling; } return -EBUSY; } +/* + * Find empty slot in the resource tree given range and alignment. + */ +static int find_resource(struct resource *root, struct resource *new, + resource_size_t size, + struct resource_constraint *constraint) +{ + return __find_resource(root, NULL, new, size, constraint); +} + /** - * allocate_resource - allocate empty slot in the resource tree given range & alignment + * reallocate_resource - allocate a slot in the resource tree given range & alignment. + * The resource will be relocated if the new size cannot be reallocated in the + * current location. + * + * @root: root resource descriptor + * @old: resource descriptor desired by caller + * @newsize: new size of the resource descriptor + * @constraint: the size and alignment constraints to be met. + */ +int reallocate_resource(struct resource *root, struct resource *old, + resource_size_t newsize, + struct resource_constraint *constraint) +{ + int err=0; + struct resource new = *old; + struct resource *conflict; + + write_lock(&resource_lock); + + if ((err = __find_resource(root, old, &new, newsize, constraint))) + goto out; + + if (resource_contains(&new, old)) { + old->start = new.start; + old->end = new.end; + goto out; + } + + if (old->child) { + err = -EBUSY; + goto out; + } + + if (resource_contains(old, &new)) { + old->start = new.start; + old->end = new.end; + } else { + __release_resource(old); + *old = new; + conflict = __request_resource(root, old); + BUG_ON(conflict); + } +out: + write_unlock(&resource_lock); + return err; +} + + +/** + * allocate_resource - allocate empty slot in the resource tree given range & alignment. + * The resource will be reallocated with a new size if it was already allocated * @root: root resource descriptor * @new: resource descriptor desired by caller * @size: requested resource region size @@ -459,12 +526,25 @@ int allocate_resource(struct resource *root, struct resource *new, void *alignf_data) { int err; + struct resource_constraint constraint; if (!alignf) alignf = simple_align_resource; + constraint.min = min; + constraint.max = max; + constraint.align = align; + constraint.alignf = alignf; + constraint.alignf_data = alignf_data; + + if ( new->parent ) { + /* resource is already allocated, try reallocating with + the new constraints */ + return reallocate_resource(root, new, size, &constraint); + } + write_lock(&resource_lock); - err = find_resource(root, new, size, min, max, align, alignf, alignf_data); + err = find_resource(root, new, size, &constraint); if (err >= 0 && __request_resource(root, new)) err = -EBUSY; write_unlock(&resource_lock); -- cgit v1.2.3 From 4d4cf23cdde2f8f9324f5684a7f349e182039529 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 6 Jul 2011 20:15:23 +0200 Subject: PM / Hibernate: Fix free_unnecessary_pages() There is a bug in free_unnecessary_pages() that causes it to attempt to free too many pages in some cases, which triggers the BUG_ON() in memory_bm_clear_bit() for copy_bm. Namely, if count_data_pages() is initially greater than alloc_normal, we get to_free_normal equal to 0 and "save" greater from 0. In that case, if the sum of "save" and count_highmem_pages() is greater than alloc_highmem, we subtract a positive number from to_free_normal. Hence, since to_free_normal was 0 before the subtraction and is an unsigned int, the result is converted to a huge positive number that is used as the number of pages to free. Fix this bug by checking if to_free_normal is actually greater than or equal to the number we're going to subtract from it. Signed-off-by: Rafael J. Wysocki Reported-and-tested-by: Matthew Garrett Cc: stable@kernel.org --- kernel/power/snapshot.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index ace55889f702..06efa54f93d6 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1211,7 +1211,11 @@ static void free_unnecessary_pages(void) to_free_highmem = alloc_highmem - save; } else { to_free_highmem = 0; - to_free_normal -= save - alloc_highmem; + save -= alloc_highmem; + if (to_free_normal > save) + to_free_normal -= save; + else + to_free_normal = 0; } memory_bm_position_reset(©_bm); -- cgit v1.2.3 From bcb65a797eb7c51e4f227dd19295f14d38738fee Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Wed, 6 Jul 2011 12:26:05 +0100 Subject: FDPIC: Fix memory leak The shdr4extnum variable isn't being freed in the cleanup process of elf_fdpic_core_dump(). Signed-off-by: Davidlohr Bueso Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- fs/binfmt_elf_fdpic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 63039ed9576f..2bc5dc644b4c 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1864,6 +1864,7 @@ cleanup: kfree(psinfo); kfree(notes); kfree(fpu); + kfree(shdr4extnum); #ifdef ELF_CORE_COPY_XFPREGS kfree(xfpu); #endif -- cgit v1.2.3 From 2eb5af44b1d22d7f7b715e0b9a4e516eb4451bf9 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 28 Jun 2011 09:53:20 +0100 Subject: ARM: 6979/1: mach-vt8500: add forgotten irq_data conversion This platform has not been converted to 'struct irq_data' when the big pile was done and fails to compile nowadays. Tested on a JayPC-Tablet. Signed-off-by: Wolfram Sang Acked-by: Alexey Charkov Signed-off-by: Russell King --- arch/arm/mach-vt8500/irq.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c index 245140c0df10..642de0408f25 100644 --- a/arch/arm/mach-vt8500/irq.c +++ b/arch/arm/mach-vt8500/irq.c @@ -39,9 +39,10 @@ static void __iomem *ic_regbase; static void __iomem *sic_regbase; -static void vt8500_irq_mask(unsigned int irq) +static void vt8500_irq_mask(struct irq_data *d) { void __iomem *base = ic_regbase; + unsigned irq = d->irq; u8 edge; if (irq >= 64) { @@ -64,9 +65,10 @@ static void vt8500_irq_mask(unsigned int irq) } } -static void vt8500_irq_unmask(unsigned int irq) +static void vt8500_irq_unmask(struct irq_data *d) { void __iomem *base = ic_regbase; + unsigned irq = d->irq; u8 dctr; if (irq >= 64) { @@ -78,10 +80,11 @@ static void vt8500_irq_unmask(unsigned int irq) writeb(dctr, base + VT8500_IC_DCTR + irq); } -static int vt8500_irq_set_type(unsigned int irq, unsigned int flow_type) +static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type) { void __iomem *base = ic_regbase; - unsigned int orig_irq = irq; + unsigned irq = d->irq; + unsigned orig_irq = irq; u8 dctr; if (irq >= 64) { @@ -114,11 +117,11 @@ static int vt8500_irq_set_type(unsigned int irq, unsigned int flow_type) } static struct irq_chip vt8500_irq_chip = { - .name = "vt8500", - .ack = vt8500_irq_mask, - .mask = vt8500_irq_mask, - .unmask = vt8500_irq_unmask, - .set_type = vt8500_irq_set_type, + .name = "vt8500", + .irq_ack = vt8500_irq_mask, + .irq_mask = vt8500_irq_mask, + .irq_unmask = vt8500_irq_unmask, + .irq_set_type = vt8500_irq_set_type, }; void __init vt8500_init_irq(void) -- cgit v1.2.3 From 757df746fc5db0020ddab45914617a19d149c252 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 30 Jun 2011 15:10:21 +0100 Subject: ARM: 6980/1: mmci: use StartBitErr to detect bad connections Stresstesting insert/remove of SD-cards can trigger a StartBitErr. This made the driver to hang in forever waiting for a non ocurring data timeout. This bit and interrupt is documented in the original PL180 TRM, just never implemented until now. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Jonas Aberg Signed-off-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 2 ++ drivers/mmc/host/mmci.h | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 7721de942c69..fe140724a02e 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -582,6 +582,8 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, data->error = -EILSEQ; } else if (status & MCI_DATATIMEOUT) { data->error = -ETIMEDOUT; + } else if (status & MCI_STARTBITERR) { + data->error = -ECOMM; } else if (status & MCI_TXUNDERRUN) { data->error = -EIO; } else if (status & MCI_RXOVERRUN) { diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index bb32e21c09db..2164e8c6476c 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -86,6 +86,7 @@ #define MCI_CMDRESPEND (1 << 6) #define MCI_CMDSENT (1 << 7) #define MCI_DATAEND (1 << 8) +#define MCI_STARTBITERR (1 << 9) #define MCI_DATABLOCKEND (1 << 10) #define MCI_CMDACTIVE (1 << 11) #define MCI_TXACTIVE (1 << 12) @@ -112,6 +113,7 @@ #define MCI_CMDRESPENDCLR (1 << 6) #define MCI_CMDSENTCLR (1 << 7) #define MCI_DATAENDCLR (1 << 8) +#define MCI_STARTBITERRCLR (1 << 9) #define MCI_DATABLOCKENDCLR (1 << 10) /* Extended status bits for the ST Micro variants */ #define MCI_ST_SDIOITC (1 << 22) @@ -127,6 +129,7 @@ #define MCI_CMDRESPENDMASK (1 << 6) #define MCI_CMDSENTMASK (1 << 7) #define MCI_DATAENDMASK (1 << 8) +#define MCI_STARTBITERRMASK (1 << 9) #define MCI_DATABLOCKENDMASK (1 << 10) #define MCI_CMDACTIVEMASK (1 << 11) #define MCI_TXACTIVEMASK (1 << 12) @@ -150,7 +153,7 @@ #define MCI_IRQENABLE \ (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ - MCI_CMDRESPENDMASK|MCI_CMDSENTMASK) + MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_STARTBITERRMASK) /* These interrupts are directed to IRQ1 when two IRQ lines are available */ #define MCI_IRQ1MASK \ -- cgit v1.2.3 From 186dcaa448c0a7a99933efac2af225fc4fe82c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Fri, 17 Jun 2011 11:10:04 +0100 Subject: ARM: 6966/1: ep93xx: fix inverted RTS/DTR signals on uart1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was discovered by Roberto Bergo, that RTS/DTR signals are inverted after the boot, because it was causing him problems with hardware controlled modem connected on ttyAM0. Todd Valentic came with this patch for the issue. Discussion: http://tech.groups.yahoo.com/group/ts-7000/message/20259 Comments from Petr Štetiar: Sorry, but forget to add Acked-by[1]: 1. https://patchwork.kernel.org/patch/873052/ Cc: Ryan Mallon Cc: Hartley Sweeten Signed-off-by: Todd Valentic Tested-by: Roberto Bergo Signed-off-by: Petr Štetiar Acked-by: H Hartley Sweeten Signed-off-by: Russell King --- arch/arm/mach-ep93xx/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 1d4b65fd673e..6659a0d137a3 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -251,9 +251,9 @@ static void ep93xx_uart_set_mctrl(struct amba_device *dev, unsigned int mcr; mcr = 0; - if (!(mctrl & TIOCM_RTS)) + if (mctrl & TIOCM_RTS) mcr |= 2; - if (!(mctrl & TIOCM_DTR)) + if (mctrl & TIOCM_DTR) mcr |= 1; __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET); -- cgit v1.2.3 From 38a8914f9ac2379293944f613e6ca24b61373de8 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 1 Jul 2011 14:36:19 +0100 Subject: ARM: 6987/1: l2x0: fix disabling function to avoid deadlock The l2x0_disable function attempts to writel with the l2x0_lock held. This results in deadlock when the writel contains an outer_sync call for the platform since the l2x0_lock is already held by the disable function. A further problem is that disabling the L2 without flushing it first can lead to the spin_lock operation becoming visible after the spin_unlock, causing any subsequent L2 maintenance to deadlock. This patch replaces the writel with a call to writel_relaxed in the disabling code and adds a flush before disabling in the control register, preventing livelock from occurring. Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index ef59099a5463..44c086710d2b 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -120,17 +120,22 @@ static void l2x0_cache_sync(void) spin_unlock_irqrestore(&l2x0_lock, flags); } -static void l2x0_flush_all(void) +static void __l2x0_flush_all(void) { - unsigned long flags; - - /* clean all ways */ - spin_lock_irqsave(&l2x0_lock, flags); debug_writel(0x03); writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); cache_sync(); debug_writel(0x00); +} + +static void l2x0_flush_all(void) +{ + unsigned long flags; + + /* clean all ways */ + spin_lock_irqsave(&l2x0_lock, flags); + __l2x0_flush_all(); spin_unlock_irqrestore(&l2x0_lock, flags); } @@ -266,7 +271,9 @@ static void l2x0_disable(void) unsigned long flags; spin_lock_irqsave(&l2x0_lock, flags); - writel(0, l2x0_base + L2X0_CTRL); + __l2x0_flush_all(); + writel_relaxed(0, l2x0_base + L2X0_CTRL); + dsb(); spin_unlock_irqrestore(&l2x0_lock, flags); } -- cgit v1.2.3 From 0dcb6d737c8d1a31476cbab4d640022b53070ffa Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 6 Jul 2011 11:19:56 -0700 Subject: MAINTAINERS: move kernel-doc patches location Move location of quilt series for kernel-doc patches. Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 584bdb2fe544..9820e89c827c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2197,7 +2197,7 @@ F: drivers/acpi/dock.c DOCUMENTATION M: Randy Dunlap L: linux-doc@vger.kernel.org -T: quilt oss.oracle.com/~rdunlap/kernel-doc-patches/current/ +T: quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/ S: Maintained F: Documentation/ -- cgit v1.2.3 From 316b3799880c55bb20f6d2db904245eccc30e25f Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 6 Jul 2011 11:27:17 -0700 Subject: Documentation: update CodingStyle memory allocators The list of available general purpose memory allocators in Documentation/CodingStyle chapter 14 is incomplete. This patch adds the missing vzalloc() to the list. Signed-off-by: Jesper Juhl Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/CodingStyle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index 58b0bf917834..fa6e25b94a54 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -680,8 +680,8 @@ ones already enabled by DEBUG. Chapter 14: Allocating memory The kernel provides the following general purpose memory allocators: -kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API -documentation for further information about them. +kmalloc(), kzalloc(), kcalloc(), vmalloc(), and vzalloc(). Please refer to +the API documentation for further information about them. The preferred form for passing a size of a struct is the following: -- cgit v1.2.3 From 9b61fc4cf3a7232ecc39f573a1e68148ef40ea49 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Wed, 6 Jul 2011 11:26:26 -0700 Subject: Documentation: fix cgroup blkio throttle filenames All the blkio.throttle.* file names are incorrectly reported without ".throttle" in the documentation. Fix it. Signed-off-by: Andrea Righi Signed-off-by: Randy Dunlap Acked-by: Vivek Goyal Signed-off-by: Linus Torvalds --- Documentation/cgroups/blkio-controller.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index cd45c8ea7463..84f0a15fc210 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt @@ -77,7 +77,7 @@ Throttling/Upper Limit policy - Specify a bandwidth rate on particular device for root group. The format for policy is ": ". - echo "8:16 1048576" > /sys/fs/cgroup/blkio/blkio.read_bps_device + echo "8:16 1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device Above will put a limit of 1MB/second on reads happening for root group on device having major/minor number 8:16. @@ -90,7 +90,7 @@ Throttling/Upper Limit policy 1024+0 records out 4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s - Limits for writes can be put using blkio.write_bps_device file. + Limits for writes can be put using blkio.throttle.write_bps_device file. Hierarchical Cgroups ==================== @@ -286,28 +286,28 @@ Throttling/Upper limit policy files specified in bytes per second. Rules are per deivce. Following is the format. - echo ": " > /cgrp/blkio.read_bps_device + echo ": " > /cgrp/blkio.throttle.read_bps_device - blkio.throttle.write_bps_device - Specifies upper limit on WRITE rate to the device. IO rate is specified in bytes per second. Rules are per deivce. Following is the format. - echo ": " > /cgrp/blkio.write_bps_device + echo ": " > /cgrp/blkio.throttle.write_bps_device - blkio.throttle.read_iops_device - Specifies upper limit on READ rate from the device. IO rate is specified in IO per second. Rules are per deivce. Following is the format. - echo ": " > /cgrp/blkio.read_iops_device + echo ": " > /cgrp/blkio.throttle.read_iops_device - blkio.throttle.write_iops_device - Specifies upper limit on WRITE rate to the device. IO rate is specified in io per second. Rules are per deivce. Following is the format. - echo ": " > /cgrp/blkio.write_iops_device + echo ": " > /cgrp/blkio.throttle.write_iops_device Note: If both BW and IOPS rules are specified for a device, then IO is subjectd to both the constraints. -- cgit v1.2.3 From 1316d4da3f632d5843d5a446203e73067dc40f09 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 4 Jul 2011 05:27:36 +0000 Subject: xfs: unpin stale inodes directly in IOP_COMMITTED When inodes are marked stale in a transaction, they are treated specially when the inode log item is being inserted into the AIL. It tries to avoid moving the log item forward in the AIL due to a race condition with the writing the underlying buffer back to disk. The was "fixed" in commit de25c18 ("xfs: avoid moving stale inodes in the AIL"). To avoid moving the item forward, we return a LSN smaller than the commit_lsn of the completing transaction, thereby trying to trick the commit code into not moving the inode forward at all. I'm not sure this ever worked as intended - it assumes the inode is already in the AIL, but I don't think the returned LSN would have been small enough to prevent moving the inode. It appears that the reason it worked is that the lower LSN of the inodes meant they were inserted into the AIL and flushed before the inode buffer (which was moved to the commit_lsn of the transaction). The big problem is that with delayed logging, the returning of the different LSN means insertion takes the slow, non-bulk path. Worse yet is that insertion is to a position -before- the commit_lsn so it is doing a AIL traversal on every insertion, and has to walk over all the items that have already been inserted into the AIL. It's expensive. To compound the matter further, with delayed logging inodes are likely to go from clean to stale in a single checkpoint, which means they aren't even in the AIL at all when we come across them at AIL insertion time. Hence these were all getting inserted into the AIL when they simply do not need to be as inodes marked XFS_ISTALE are never written back. Transactional/recovery integrity is maintained in this case by the other items in the unlink transaction that were modified (e.g. the AGI btree blocks) and committed in the same checkpoint. So to fix this, simply unpin the stale inodes directly in xfs_inode_item_committed() and return -1 to indicate that the AIL insertion code does not need to do any further processing of these inodes. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_inode_item.c | 14 ++++++++------ fs/xfs/xfs_trans.c | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 09983a3344a5..b1e88d56069c 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -681,15 +681,15 @@ xfs_inode_item_unlock( * where the cluster buffer may be unpinned before the inode is inserted into * the AIL during transaction committed processing. If the buffer is unpinned * before the inode item has been committed and inserted, then it is possible - * for the buffer to be written and IO completions before the inode is inserted + * for the buffer to be written and IO completes before the inode is inserted * into the AIL. In that case, we'd be inserting a clean, stale inode into the * AIL which will never get removed. It will, however, get reclaimed which * triggers an assert in xfs_inode_free() complaining about freein an inode * still in the AIL. * - * To avoid this, return a lower LSN than the one passed in so that the - * transaction committed code will not move the inode forward in the AIL but - * will still unpin it properly. + * To avoid this, just unpin the inode directly and return a LSN of -1 so the + * transaction committed code knows that it does not need to do any further + * processing on the item. */ STATIC xfs_lsn_t xfs_inode_item_committed( @@ -699,8 +699,10 @@ xfs_inode_item_committed( struct xfs_inode_log_item *iip = INODE_ITEM(lip); struct xfs_inode *ip = iip->ili_inode; - if (xfs_iflags_test(ip, XFS_ISTALE)) - return lsn - 1; + if (xfs_iflags_test(ip, XFS_ISTALE)) { + xfs_inode_item_unpin(lip, 0); + return -1; + } return lsn; } diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 7c7bc2b786bd..c83f63b33aae 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -1361,7 +1361,7 @@ xfs_trans_item_committed( lip->li_flags |= XFS_LI_ABORTED; item_lsn = IOP_COMMITTED(lip, commit_lsn); - /* If the committed routine returns -1, item has been freed. */ + /* item_lsn of -1 means the item needs no further processing */ if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) return; @@ -1474,7 +1474,7 @@ xfs_trans_committed_bulk( lip->li_flags |= XFS_LI_ABORTED; item_lsn = IOP_COMMITTED(lip, commit_lsn); - /* item_lsn of -1 means the item was freed */ + /* item_lsn of -1 means the item needs no further processing */ if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) continue; -- cgit v1.2.3 From 0942caa373c676dca614ea8352ac77e0270aba73 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 28 Jun 2011 15:10:37 +0000 Subject: btrfs: add missing options displayed in mount output There are three missed mount options settable by user which are not currently displayed in mount output. Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 5 +++++ fs/btrfs/super.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8e948ec1ee6b..60e13ef23a5e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1336,6 +1336,11 @@ struct btrfs_ioctl_defrag_range_args { */ #define BTRFS_STRING_ITEM_KEY 253 +/* + * Flags for mount options. + * + * Note: don't forget to add new options to btrfs_show_options() + */ #define BTRFS_MOUNT_NODATASUM (1 << 0) #define BTRFS_MOUNT_NODATACOW (1 << 1) #define BTRFS_MOUNT_NOBARRIER (1 << 2) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3559d0b3518a..5746081199ee 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -721,6 +721,12 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_puts(seq, ",clear_cache"); if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) seq_puts(seq, ",user_subvol_rm_allowed"); + if (btrfs_test_opt(root, ENOSPC_DEBUG)) + seq_puts(seq, ",enospc_debug"); + if (btrfs_test_opt(root, AUTO_DEFRAG)) + seq_puts(seq, ",autodefrag"); + if (btrfs_test_opt(root, INODE_MAP_CACHE)) + seq_puts(seq, ",inode_cache"); return 0; } -- cgit v1.2.3 From 508794eb5ec2a2b832742e78c6766844b10c0c94 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Sat, 2 Jul 2011 21:24:41 +0000 Subject: Btrfs: don't panic if we get an error while balancing V2 A user reported an error where if we try to balance an fs after a device has been removed it will blow up. This is because we get an EIO back and this is where BUG_ON(ret) bites us in the ass. To fix we just exit. Thanks, Reported-by: Anand Jain Signed-off-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 1efa56e18f9b..19450bc53632 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2098,7 +2098,8 @@ int btrfs_balance(struct btrfs_root *dev_root) chunk_root->root_key.objectid, found_key.objectid, found_key.offset); - BUG_ON(ret && ret != -ENOSPC); + if (ret && ret != -ENOSPC) + goto error; key.offset = found_key.offset - 1; } ret = 0; -- cgit v1.2.3 From 149e2d76b4886c4c7ff5e077646a8ba3563c8026 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Wed, 6 Jul 2011 18:51:53 -0400 Subject: btrfs: fix oops when doing space balance We need to make sure the data relocation inode doesn't go through the delayed metadata updates, otherwise we get an oops during balance: kernel BUG at fs/btrfs/relocation.c:4303! [SNIP] Call Trace: [] ? update_ref_for_cow+0x22d/0x330 [btrfs] [] __btrfs_cow_block+0x451/0x5e0 [btrfs] [] ? read_block_for_search+0x14d/0x4d0 [btrfs] [] btrfs_cow_block+0x10b/0x240 [btrfs] [] btrfs_search_slot+0x49e/0x7a0 [btrfs] [] btrfs_lookup_inode+0x2f/0xa0 [btrfs] [] ? mutex_lock+0x1e/0x50 [] btrfs_update_delayed_inode+0x71/0x160 [btrfs] [] ? __btrfs_release_delayed_node+0x67/0x190 [btrfs] [] btrfs_run_delayed_items+0xe8/0x120 [btrfs] [] btrfs_commit_transaction+0x250/0x850 [btrfs] [] ? find_get_pages+0x39/0x130 [] ? join_transaction+0x25/0x250 [btrfs] [] ? wake_up_bit+0x40/0x40 [] prepare_to_relocate+0xda/0xf0 [btrfs] [] relocate_block_group+0x4b/0x620 [btrfs] [] ? btrfs_clean_old_snapshots+0x35/0x150 [btrfs] [] btrfs_relocate_block_group+0x1b3/0x2e0 [btrfs] [] ? btrfs_tree_unlock+0x50/0x50 [btrfs] [] btrfs_relocate_chunk+0x8b/0x670 [btrfs] [] ? btrfs_set_path_blocking+0x3d/0x50 [btrfs] [] ? read_extent_buffer+0xd8/0x1d0 [btrfs] [] ? btrfs_previous_item+0xb1/0x150 [btrfs] [] ? read_extent_buffer+0xd8/0x1d0 [btrfs] [] btrfs_balance+0x21a/0x2b0 [btrfs] [] btrfs_ioctl+0x798/0xd20 [btrfs] [] ? handle_mm_fault+0x148/0x270 [] ? do_page_fault+0x1d8/0x4b0 [] do_vfs_ioctl+0x9a/0x540 [] sys_ioctl+0xa1/0xb0 [] system_call_fastpath+0x16/0x1b [SNIP] RIP [] btrfs_reloc_cow_block+0x22c/0x270 [btrfs] Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 447612d3a16a..4a1373083747 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2678,12 +2678,14 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, int ret; /* - * If root is tree root, it means this inode is used to - * store free space information. And these inodes are updated - * when committing the transaction, so they needn't delaye to - * be updated, or deadlock will occured. + * If the inode is a free space inode, we can deadlock during commit + * if we put it into the delayed code. + * + * The data relocation inode should also be directly updated + * without delay */ - if (!is_free_space_inode(root, inode)) { + if (!is_free_space_inode(root, inode) + && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { ret = btrfs_delayed_update_inode(trans, root, inode); if (!ret) btrfs_set_inode_last_trans(trans, inode); -- cgit v1.2.3 From 7a3136666bc0f0419f7aaa7b1fabb4b0e0a7fb76 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 6 Jul 2011 18:10:34 -0700 Subject: x86, suspend: Restore MISC_ENABLE MSR in realmode wakeup Some BIOSes will reset the Intel MISC_ENABLE MSR (specifically the XD_DISABLE bit) when resuming from S3, which can interact poorly with ebba638ae723d8a8fc2f7abce5ec18b688b791d7. In 32bit PAE mode, this can lead to a fault when EFER is restored by the kernel wakeup routines, due to it setting the NX bit for a CPU that (thanks to the BIOS reset) now incorrectly thinks it lacks the NX feature. (64bit is not affected because it uses a common CPU bring-up that specifically handles the XD_DISABLE bit.) The need for MISC_ENABLE being restored so early is specific to the S3 resume path. Normally, MISC_ENABLE is saved in save_processor_state(), but this happens after the resume header is created, so just reproduce the logic here. (acpi_suspend_lowlevel() creates the header, calls do_suspend_lowlevel, which calls save_processor_state(), so the saved processor context isn't available during resume header creation.) [ hpa: Consider for stable if OK in mainline ] Signed-off-by: Kees Cook Link: http://lkml.kernel.org/r/20110707011034.GA8523@outflux.net Signed-off-by: H. Peter Anvin Cc: Rafael J. Wysocki Cc: 2.6.38+ --- arch/x86/kernel/acpi/realmode/wakeup.S | 14 ++++++++++++++ arch/x86/kernel/acpi/realmode/wakeup.h | 6 ++++++ arch/x86/kernel/acpi/sleep.c | 6 ++++++ 3 files changed, 26 insertions(+) diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S index ead21b663117..b4fd836e4053 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.S +++ b/arch/x86/kernel/acpi/realmode/wakeup.S @@ -28,6 +28,8 @@ pmode_cr3: .long 0 /* Saved %cr3 */ pmode_cr4: .long 0 /* Saved %cr4 */ pmode_efer: .quad 0 /* Saved EFER */ pmode_gdt: .quad 0 +pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */ +pmode_behavior: .long 0 /* Wakeup behavior flags */ realmode_flags: .long 0 real_magic: .long 0 trampoline_segment: .word 0 @@ -91,6 +93,18 @@ wakeup_code: /* Call the C code */ calll main + /* Restore MISC_ENABLE before entering protected mode, in case + BIOS decided to clear XD_DISABLE during S3. */ + movl pmode_behavior, %eax + btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax + jnc 1f + + movl pmode_misc_en, %eax + movl pmode_misc_en + 4, %edx + movl $MSR_IA32_MISC_ENABLE, %ecx + wrmsr +1: + /* Do any other stuff... */ #ifndef CONFIG_64BIT diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h index e1828c07e79c..97a29e1430e3 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.h +++ b/arch/x86/kernel/acpi/realmode/wakeup.h @@ -21,6 +21,9 @@ struct wakeup_header { u32 pmode_efer_low; /* Protected mode EFER */ u32 pmode_efer_high; u64 pmode_gdt; + u32 pmode_misc_en_low; /* Protected mode MISC_ENABLE */ + u32 pmode_misc_en_high; + u32 pmode_behavior; /* Wakeup routine behavior flags */ u32 realmode_flags; u32 real_magic; u16 trampoline_segment; /* segment with trampoline code, 64-bit only */ @@ -39,4 +42,7 @@ extern struct wakeup_header wakeup_header; #define WAKEUP_HEADER_SIGNATURE 0x51ee1111 #define WAKEUP_END_SIGNATURE 0x65a22c82 +/* Wakeup behavior bits */ +#define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0 + #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */ diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 18a857ba7a25..103b6ab368d3 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -77,6 +77,12 @@ int acpi_suspend_lowlevel(void) header->pmode_cr0 = read_cr0(); header->pmode_cr4 = read_cr4_safe(); + header->pmode_behavior = 0; + if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, + &header->pmode_misc_en_low, + &header->pmode_misc_en_high)) + header->pmode_behavior |= + (1 << WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE); header->realmode_flags = acpi_realmode_flags; header->real_magic = 0x12345678; -- cgit v1.2.3 From eebb02b1f03b3722d678bfcb560f3b26661ab0d2 Mon Sep 17 00:00:00 2001 From: Shreyas Bhatewara Date: Thu, 7 Jul 2011 00:25:52 -0700 Subject: vmxnet3: round down # of queues to power of two vmxnet3 device supports only power-of-two number of queues. The driver therefore needs to check this and rounds down the number of queues to the nearest power of two. Signed-off-by: Yong Wang Signed-off-by: Shreyas N Bhatewara Reviewed-by: Dmitry Torokhov --- drivers/net/vmxnet3/vmxnet3_drv.c | 3 +++ drivers/net/vmxnet3/vmxnet3_int.h | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 45a23b2599f3..67402350d0df 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2947,6 +2947,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, else #endif num_rx_queues = 1; + num_rx_queues = rounddown_pow_of_two(num_rx_queues); if (enable_mq) num_tx_queues = min(VMXNET3_DEVICE_MAX_TX_QUEUES, @@ -2954,6 +2955,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, else num_tx_queues = 1; + num_tx_queues = rounddown_pow_of_two(num_tx_queues); netdev = alloc_etherdev_mq(sizeof(struct vmxnet3_adapter), max(num_tx_queues, num_rx_queues)); printk(KERN_INFO "# of Tx queues : %d, # of Rx queues : %d\n", @@ -3138,6 +3140,7 @@ vmxnet3_remove_device(struct pci_dev *pdev) else #endif num_rx_queues = 1; + num_rx_queues = rounddown_pow_of_two(num_rx_queues); cancel_work_sync(&adapter->work); diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 8db7ecf5bcab..e08d75e3f170 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -55,6 +55,7 @@ #include #include #include +#include #include "vmxnet3_defs.h" @@ -68,10 +69,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.1.14.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.1.18.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01010E00 +#define VMXNET3_DRIVER_VERSION_NUM 0x01011200 #if defined(CONFIG_PCI_MSI) /* RSS only makes sense if MSI-X is supported. */ -- cgit v1.2.3 From 9c7a083d94656ad6d6f2e03ba90194f2cc5bced5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 7 Jul 2011 09:25:54 +0200 Subject: ALSA: hda - Change all ADCs for dual-adc switching mode for Realtek When the dual-adc switching mode is active in Realtek auto-parser, we need to couple all ADCs as a single capture-volume. Currently, the volume control changes only the first ADC, thus others may remain silent. This patch fixes the problem. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d21191dcfe88..7d492713c1c1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2715,17 +2715,30 @@ typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol, static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol, - getput_call_t func) + getput_call_t func, bool check_adc_switch) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - int err; + int i, err; mutex_lock(&codec->control_mutex); - kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx], - 3, 0, HDA_INPUT); - err = func(kcontrol, ucontrol); + if (check_adc_switch && spec->dual_adc_switch) { + for (i = 0; i < spec->num_adc_nids; i++) { + kcontrol->private_value = + HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], + 3, 0, HDA_INPUT); + err = func(kcontrol, ucontrol); + if (err < 0) + goto error; + } + } else { + i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + kcontrol->private_value = + HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], + 3, 0, HDA_INPUT); + err = func(kcontrol, ucontrol); + } + error: mutex_unlock(&codec->control_mutex); return err; } @@ -2734,14 +2747,14 @@ static int alc_cap_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { return alc_cap_getput_caller(kcontrol, ucontrol, - snd_hda_mixer_amp_volume_get); + snd_hda_mixer_amp_volume_get, false); } static int alc_cap_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { return alc_cap_getput_caller(kcontrol, ucontrol, - snd_hda_mixer_amp_volume_put); + snd_hda_mixer_amp_volume_put, true); } /* capture mixer elements */ @@ -2751,14 +2764,14 @@ static int alc_cap_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { return alc_cap_getput_caller(kcontrol, ucontrol, - snd_hda_mixer_amp_switch_get); + snd_hda_mixer_amp_switch_get, false); } static int alc_cap_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { return alc_cap_getput_caller(kcontrol, ucontrol, - snd_hda_mixer_amp_switch_put); + snd_hda_mixer_amp_switch_put, true); } #define _DEFINE_CAPMIX(num) \ -- cgit v1.2.3 From f03d78db65085609938fdb686238867e65003181 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 7 Jul 2011 00:27:05 -0700 Subject: net: refine {udp|tcp|sctp}_mem limits Current tcp/udp/sctp global memory limits are not taking into account hugepages allocations, and allow 50% of ram to be used by buffers of a single protocol [ not counting space used by sockets / inodes ...] Lets use nr_free_buffer_pages() and allow a default of 1/8 of kernel ram per protocol, and a minimum of 128 pages. Heavy duty machines sysadmins probably need to tweak limits anyway. References: https://bugzilla.stlinux.com/show_bug.cgi?id=38032 Reported-by: starlight Suggested-by: Andrew Morton Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 10 ++-------- net/ipv4/udp.c | 10 ++-------- net/sctp/protocol.c | 11 +---------- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 054a59d21eb0..46febcacb729 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3220,7 +3220,7 @@ __setup("thash_entries=", set_thash_entries); void __init tcp_init(void) { struct sk_buff *skb = NULL; - unsigned long nr_pages, limit; + unsigned long limit; int i, max_share, cnt; unsigned long jiffy = jiffies; @@ -3277,13 +3277,7 @@ void __init tcp_init(void) sysctl_tcp_max_orphans = cnt / 2; sysctl_max_syn_backlog = max(128, cnt / 256); - /* Set the pressure threshold to be a fraction of global memory that - * is up to 1/2 at 256 MB, decreasing toward zero with the amount of - * memory, with a floor of 128 pages. - */ - nr_pages = totalram_pages - totalhigh_pages; - limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); - limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); + limit = nr_free_buffer_pages() / 8; limit = max(limit, 128UL); sysctl_tcp_mem[0] = limit / 4 * 3; sysctl_tcp_mem[1] = limit; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 48cd88e62553..198f75b7bdd3 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2209,16 +2209,10 @@ void __init udp_table_init(struct udp_table *table, const char *name) void __init udp_init(void) { - unsigned long nr_pages, limit; + unsigned long limit; udp_table_init(&udp_table, "UDP"); - /* Set the pressure threshold up by the same strategy of TCP. It is a - * fraction of global memory that is up to 1/2 at 256 MB, decreasing - * toward zero with the amount of memory, with a floor of 128 pages. - */ - nr_pages = totalram_pages - totalhigh_pages; - limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); - limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); + limit = nr_free_buffer_pages() / 8; limit = max(limit, 128UL); sysctl_udp_mem[0] = limit / 4 * 3; sysctl_udp_mem[1] = limit; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 67380a29e2e9..207175b2f40a 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1058,7 +1058,6 @@ SCTP_STATIC __init int sctp_init(void) int status = -EINVAL; unsigned long goal; unsigned long limit; - unsigned long nr_pages; int max_share; int order; @@ -1148,15 +1147,7 @@ SCTP_STATIC __init int sctp_init(void) /* Initialize handle used for association ids. */ idr_init(&sctp_assocs_id); - /* Set the pressure threshold to be a fraction of global memory that - * is up to 1/2 at 256 MB, decreasing toward zero with the amount of - * memory, with a floor of 128 pages. - * Note this initializes the data in sctpv6_prot too - * Unabashedly stolen from tcp_init - */ - nr_pages = totalram_pages - totalhigh_pages; - limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); - limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); + limit = nr_free_buffer_pages() / 8; limit = max(limit, 128UL); sysctl_sctp_mem[0] = limit / 4 * 3; sysctl_sctp_mem[1] = limit; -- cgit v1.2.3 From fcb857abc4c0d512e99a08ba0415be9a6d65b4c0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 6 Jul 2011 19:52:27 +0000 Subject: drm/radeon/kms: fix typo in IH_CNTL swap bitfield Only affects BE systems. Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreend.h | 2 +- drivers/gpu/drm/radeon/r600d.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 1636e3449825..5fd287ad9d97 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -466,7 +466,7 @@ #define IH_RB_WPTR_ADDR_LO 0x3e14 #define IH_CNTL 0x3e18 # define ENABLE_INTR (1 << 0) -# define IH_MC_SWAP(x) ((x) << 2) +# define IH_MC_SWAP(x) ((x) << 1) # define IH_MC_SWAP_NONE 0 # define IH_MC_SWAP_16BIT 1 # define IH_MC_SWAP_32BIT 2 diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index f140a0d5cb54..0245ae6c204e 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -536,7 +536,7 @@ #define IH_RB_WPTR_ADDR_LO 0x3e14 #define IH_CNTL 0x3e18 # define ENABLE_INTR (1 << 0) -# define IH_MC_SWAP(x) ((x) << 2) +# define IH_MC_SWAP(x) ((x) << 1) # define IH_MC_SWAP_NONE 0 # define IH_MC_SWAP_16BIT 1 # define IH_MC_SWAP_32BIT 2 -- cgit v1.2.3 From 37cba6c6f4687e694ac6e3adcf2c2b2974aa3aae Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 6 Jul 2011 19:37:47 +0000 Subject: drm/radeon/kms: fix typo in evergreen disp int status register Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 5fd287ad9d97..b7b2714f0b32 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -547,7 +547,7 @@ # define LB_D5_VBLANK_INTERRUPT (1 << 3) # define DC_HPD5_INTERRUPT (1 << 17) # define DC_HPD5_RX_INTERRUPT (1 << 18) -#define DISP_INTERRUPT_STATUS_CONTINUE5 0x6050 +#define DISP_INTERRUPT_STATUS_CONTINUE5 0x6150 # define LB_D6_VLINE_INTERRUPT (1 << 2) # define LB_D6_VBLANK_INTERRUPT (1 << 3) # define DC_HPD6_INTERRUPT (1 << 17) -- cgit v1.2.3 From ccd6895d401efad0c0e41d0e93fba4ef3085e268 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 6 Jul 2011 18:30:09 +0000 Subject: drm/radeon/kms: free ib pool on module unloading ib pool weren't free for various newer asic on module unload. This doesn't cause much arm but still could be candidate for stable. Signed-off-by: Jerome Glisse cc: stable@kernel.org Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 1 + drivers/gpu/drm/radeon/ni.c | 1 + drivers/gpu/drm/radeon/r600.c | 1 + drivers/gpu/drm/radeon/rv770.c | 1 + 4 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e8a5ffb0124d..a2d900809900 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -3237,6 +3237,7 @@ void evergreen_fini(struct radeon_device *rdev) r700_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); evergreen_pcie_gart_fini(rdev); radeon_gem_fini(rdev); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 16caafeadf5e..559dbd412906 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1581,6 +1581,7 @@ void cayman_fini(struct radeon_device *rdev) cayman_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); cayman_pcie_gart_fini(rdev); radeon_gem_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index f79d2ccb6755..bc54b26cb32f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2628,6 +2628,7 @@ void r600_fini(struct radeon_device *rdev) r600_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); r600_pcie_gart_fini(rdev); radeon_agp_fini(rdev); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 8bb347d23ca6..4de51891aa6d 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1368,6 +1368,7 @@ void rv770_fini(struct radeon_device *rdev) r700_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); + radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); rv770_pcie_gart_fini(rdev); rv770_vram_scratch_fini(rdev); -- cgit v1.2.3 From d61a06862ba8c14466e1dd718cac460da0465ddd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Jul 2011 03:16:17 +0000 Subject: drm/kms: allow drm_mode_group with no objects Sometimes we could be controlling a device (such as an NVIDIA Tesla) that has no crtcs/encoders/connectors. One could argue that the driver should unset DRIVER_MODESET in this case, but that changes a whole heap of the DRM's other behaviours, and it's much easier to just be a modesetting driver without any outputs. Signed-off-by: Ben Skeggs Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 21058e6ad2b8..82db18506662 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -886,9 +886,6 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) total_objects += dev->mode_config.num_connector; total_objects += dev->mode_config.num_encoder; - if (total_objects == 0) - return -EINVAL; - group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); if (!group->id_list) return -ENOMEM; -- cgit v1.2.3 From f70e957cda22d309c769805cbb932407a5232219 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 6 Jul 2011 16:52:37 -0400 Subject: x86: Don't use the EFI reboot method by default Testing suggests that at least some Lenovos and some Intels will fail to reboot via EFI, attempting to jump to an unmapped physical address. In the long run we could handle this by providing a page table with a 1:1 mapping of physical addresses, but for now it's probably just easier to assume that ACPI or legacy methods will be present and reboot via those. Signed-off-by: Matthew Garrett Cc: Linus Torvalds Cc: Andrew Morton Cc: Alan Cox Link: http://lkml.kernel.org/r/1309985557-15350-1-git-send-email-mjg@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/efi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 474356b98ede..899e393d8e73 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -504,9 +504,6 @@ void __init efi_init(void) x86_platform.set_wallclock = efi_set_rtc_mmss; #endif - /* Setup for EFI runtime service */ - reboot_type = BOOT_EFI; - #if EFI_DEBUG print_efi_memmap(); #endif -- cgit v1.2.3 From 949123016a2ef578009b6aa3e98d45d1a154ebfb Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 2 Jul 2011 09:28:04 +0000 Subject: sctp: fix missing send up SCTP_SENDER_DRY_EVENT when subscribe it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We forgot to send up SCTP_SENDER_DRY_EVENT notification when user app subscribes to this event, and there is no data to be sent or retransmit. This is required by the Socket API and used by the DTLS/SCTP implementation. Reported-by: Michael Tüxen Signed-off-by: Wei Yongjun Tested-by: Robin Seggelmann Signed-off-by: David S. Miller --- net/sctp/socket.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6766913a53e6..08c6238802de 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2073,10 +2073,33 @@ static int sctp_setsockopt_disable_fragments(struct sock *sk, static int sctp_setsockopt_events(struct sock *sk, char __user *optval, unsigned int optlen) { + struct sctp_association *asoc; + struct sctp_ulpevent *event; + if (optlen > sizeof(struct sctp_event_subscribe)) return -EINVAL; if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) return -EFAULT; + + /* + * At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, + * if there is no data to be sent or retransmit, the stack will + * immediately send up this notification. + */ + if (sctp_ulpevent_type_enabled(SCTP_SENDER_DRY_EVENT, + &sctp_sk(sk)->subscribe)) { + asoc = sctp_id2assoc(sk, 0); + + if (asoc && sctp_outq_is_empty(&asoc->outqueue)) { + event = sctp_ulpevent_make_sender_dry_event(asoc, + GFP_ATOMIC); + if (!event) + return -ENOMEM; + + sctp_ulpq_tail_event(&asoc->ulpq, event); + } + } + return 0; } -- cgit v1.2.3 From 90c5ffe592ff3b33afe2bdfe5e9ec630fc599e32 Mon Sep 17 00:00:00 2001 From: Vitaly Kuzmichev Date: Thu, 7 Jul 2011 14:56:05 +0100 Subject: ARM: 6994/1: smp_twd: Fix typo in 'twd_timer_rate' printing To get hundredths of MHz the rate needs to be divided by 10'000. Here is an example: twd_timer_rate = 123456789 Before the patch: twd_timer_rate / 1000000 = 123 (twd_timer_rate / 1000000) % 100 = 23 Result: 123.23MHz. After being fixed: twd_timer_rate / 1000000 = 123 (twd_timer_rate / 10000) % 100 = 45 Result: 123.45MHz. Signed-off-by: Vitaly Kuzmichev Signed-off-by: Russell King --- arch/arm/kernel/smp_twd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 60636f499cb3..2c277d40cee6 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -115,7 +115,7 @@ static void __cpuinit twd_calibrate_rate(void) twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000, - (twd_timer_rate / 1000000) % 100); + (twd_timer_rate / 10000) % 100); } } -- cgit v1.2.3 From ee339fe63ac408e4604c1c88b1f9a428f2511b70 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 6 Jul 2011 09:43:16 -0400 Subject: xen/pci: Move check for acpi_sci_override_gsi to xen_setup_acpi_sci. Previously we would check for acpi_sci_override_gsi == gsi every time a PCI device was enabled. That works during early bootup, but later on it could lead to triggering unnecessarily the acpi_gsi_to_irq(..) lookup. The reason is that acpi_sci_override_gsi was declared in __initdata and after early bootup could contain bogus values. This patch moves the check for acpi_sci_override_gsi to the site where the ACPI SCI is preset. CC: stable@kernel.org Reported-by: Raghavendra D Prabhu Tested-by: Raghavendra D Prabhu [http://lists.xensource.com/archives/html/xen-devel/2011-07/msg00154.html] Suggested-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/pci/xen.c | 56 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index fe008309ffec..f567965c0620 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -327,13 +327,12 @@ int __init pci_xen_hvm_init(void) } #ifdef CONFIG_XEN_DOM0 -static int xen_register_pirq(u32 gsi, int triggering) +static int xen_register_pirq(u32 gsi, int gsi_override, int triggering) { int rc, pirq, irq = -1; struct physdev_map_pirq map_irq; int shareable = 0; char *name; - bool gsi_override = false; if (!xen_pv_domain()) return -1; @@ -345,31 +344,12 @@ static int xen_register_pirq(u32 gsi, int triggering) shareable = 1; name = "ioapic-level"; } - pirq = xen_allocate_pirq_gsi(gsi); if (pirq < 0) goto out; - /* Before we bind the GSI to a Linux IRQ, check whether - * we need to override it with bus_irq (IRQ) value. Usually for - * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so: - * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level) - * but there are oddballs where the IRQ != GSI: - * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level) - * which ends up being: gsi_to_irq[9] == 20 - * (which is what acpi_gsi_to_irq ends up calling when starting the - * the ACPI interpreter and keels over since IRQ 9 has not been - * setup as we had setup IRQ 20 for it). - */ - if (gsi == acpi_sci_override_gsi) { - /* Check whether the GSI != IRQ */ - acpi_gsi_to_irq(gsi, &irq); - if (irq != gsi) - /* Bugger, we MUST have that IRQ. */ - gsi_override = true; - } - if (gsi_override) - irq = xen_bind_pirq_gsi_to_irq(irq, pirq, shareable, name); + if (gsi_override >= 0) + irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name); else irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name); if (irq < 0) @@ -392,7 +372,7 @@ out: return irq; } -static int xen_register_gsi(u32 gsi, int triggering, int polarity) +static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity) { int rc, irq; struct physdev_setup_gsi setup_gsi; @@ -403,7 +383,7 @@ static int xen_register_gsi(u32 gsi, int triggering, int polarity) printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", gsi, triggering, polarity); - irq = xen_register_pirq(gsi, triggering); + irq = xen_register_pirq(gsi, gsi_override, triggering); setup_gsi.gsi = gsi; setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); @@ -425,6 +405,8 @@ static __init void xen_setup_acpi_sci(void) int rc; int trigger, polarity; int gsi = acpi_sci_override_gsi; + int irq = -1; + int gsi_override = -1; if (!gsi) return; @@ -441,7 +423,25 @@ static __init void xen_setup_acpi_sci(void) printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " "polarity=%d\n", gsi, trigger, polarity); - gsi = xen_register_gsi(gsi, trigger, polarity); + /* Before we bind the GSI to a Linux IRQ, check whether + * we need to override it with bus_irq (IRQ) value. Usually for + * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so: + * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level) + * but there are oddballs where the IRQ != GSI: + * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level) + * which ends up being: gsi_to_irq[9] == 20 + * (which is what acpi_gsi_to_irq ends up calling when starting the + * the ACPI interpreter and keels over since IRQ 9 has not been + * setup as we had setup IRQ 20 for it). + */ + /* Check whether the GSI != IRQ */ + if (acpi_gsi_to_irq(gsi, &irq) == 0) { + if (irq >= 0 && irq != gsi) + /* Bugger, we MUST have that IRQ. */ + gsi_override = irq; + } + + gsi = xen_register_gsi(gsi, gsi_override, trigger, polarity); printk(KERN_INFO "xen: acpi sci %d\n", gsi); return; @@ -450,7 +450,7 @@ static __init void xen_setup_acpi_sci(void) static int acpi_register_gsi_xen(struct device *dev, u32 gsi, int trigger, int polarity) { - return xen_register_gsi(gsi, trigger, polarity); + return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity); } static int __init pci_xen_initial_domain(void) @@ -489,7 +489,7 @@ void __init xen_setup_pirqs(void) if (acpi_get_override_irq(irq, &trigger, &polarity) == -1) continue; - xen_register_pirq(irq, + xen_register_pirq(irq, -1 /* no GSI override */, trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); } } -- cgit v1.2.3 From bd7fdbcaa2d06d446577fd3c9b81847b04469e01 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 6 Jul 2011 17:58:56 -0700 Subject: ASoC: ak4642: fixup snd_soc_update_bits mask for PW_MGMT2 mask didn't cover update-data Signed-off-by: Kuninori Morimoto Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/ak4642.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 4be0570e3f1f..65f46047b1cb 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -357,7 +357,7 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) default: return -EINVAL; } - snd_soc_update_bits(codec, PW_MGMT2, MS, data); + snd_soc_update_bits(codec, PW_MGMT2, MS | MCKO | PMPLL, data); snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko); /* format type */ -- cgit v1.2.3 From c902ce1bfb40d8b049bd2319b388b4b68b04bc27 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Jul 2011 12:19:48 +0100 Subject: FS-Cache: Add a helper to bulk uncache pages on an inode Add an FS-Cache helper to bulk uncache pages on an inode. This will only work for the circumstance where the pages in the cache correspond 1:1 with the pages attached to an inode's page cache. This is required for CIFS and NFS: When disabling inode cookie, we were returning the cookie and setting cifsi->fscache to NULL but failed to invalidate any previously mapped pages. This resulted in "Bad page state" errors and manifested in other kind of errors when running fsstress. Fix it by uncaching mapped pages when we disable the inode cookie. This patch should fix the following oops and "Bad page state" errors seen during fsstress testing. ------------[ cut here ]------------ kernel BUG at fs/cachefiles/namei.c:201! invalid opcode: 0000 [#1] SMP Pid: 5, comm: kworker/u:0 Not tainted 2.6.38.7-30.fc15.x86_64 #1 Bochs Bochs RIP: 0010: cachefiles_walk_to_object+0x436/0x745 [cachefiles] RSP: 0018:ffff88002ce6dd00 EFLAGS: 00010282 RAX: ffff88002ef165f0 RBX: ffff88001811f500 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000100 RDI: 0000000000000282 RBP: ffff88002ce6dda0 R08: 0000000000000100 R09: ffffffff81b3a300 R10: 0000ffff00066c0a R11: 0000000000000003 R12: ffff88002ae54840 R13: ffff88002ae54840 R14: ffff880029c29c00 R15: ffff88001811f4b0 FS: 00007f394dd32720(0000) GS:ffff88002ef00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00007fffcb62ddf8 CR3: 000000001825f000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process kworker/u:0 (pid: 5, threadinfo ffff88002ce6c000, task ffff88002ce55cc0) Stack: 0000000000000246 ffff88002ce55cc0 ffff88002ce6dd58 ffff88001815dc00 ffff8800185246c0 ffff88001811f618 ffff880029c29d18 ffff88001811f380 ffff88002ce6dd50 ffffffff814757e4 ffff88002ce6dda0 ffffffff8106ac56 Call Trace: cachefiles_lookup_object+0x78/0xd4 [cachefiles] fscache_lookup_object+0x131/0x16d [fscache] fscache_object_work_func+0x1bc/0x669 [fscache] process_one_work+0x186/0x298 worker_thread+0xda/0x15d kthread+0x84/0x8c kernel_thread_helper+0x4/0x10 RIP cachefiles_walk_to_object+0x436/0x745 [cachefiles] ---[ end trace 1d481c9af1804caa ]--- I tested the uncaching by the following means: (1) Create a big file on my NFS server (104857600 bytes). (2) Read the file into the cache with md5sum on the NFS client. Look in /proc/fs/fscache/stats: Pages : mrk=25601 unc=0 (3) Open the file for read/write ("bash 5<>/warthog/bigfile"). Look in proc again: Pages : mrk=25601 unc=25601 Reported-by: Jeff Layton Signed-off-by: David Howells Reviewed-and-Tested-by: Suresh Jayaraman cc: stable@kernel.org Signed-off-by: Linus Torvalds --- Documentation/filesystems/caching/netfs-api.txt | 16 +++++++++ fs/cifs/fscache.c | 1 + fs/fscache/page.c | 44 +++++++++++++++++++++++++ fs/nfs/fscache.c | 8 ++--- include/linux/fscache.h | 21 ++++++++++++ 5 files changed, 85 insertions(+), 5 deletions(-) diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt index a167ab876c35..7cc6bf2871eb 100644 --- a/Documentation/filesystems/caching/netfs-api.txt +++ b/Documentation/filesystems/caching/netfs-api.txt @@ -673,6 +673,22 @@ storage request to complete, or it may attempt to cancel the storage request - in which case the page will not be stored in the cache this time. +BULK INODE PAGE UNCACHE +----------------------- + +A convenience routine is provided to perform an uncache on all the pages +attached to an inode. This assumes that the pages on the inode correspond on a +1:1 basis with the pages in the cache. + + void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie, + struct inode *inode); + +This takes the netfs cookie that the pages were cached with and the inode that +the pages are attached to. This function will wait for pages to finish being +written to the cache and for the cache to finish with the page generally. No +error is returned. + + ========================== INDEX AND DATA FILE UPDATE ========================== diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index 816696621ec9..42e5363b4102 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -92,6 +92,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode) if (cifsi->fscache) { cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); + fscache_uncache_all_inode_pages(cifsi->fscache, inode); fscache_relinquish_cookie(cifsi->fscache, 1); cifsi->fscache = NULL; } diff --git a/fs/fscache/page.c b/fs/fscache/page.c index a2a5d19ece6a..2f343b4d7a7d 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c @@ -954,3 +954,47 @@ void fscache_mark_pages_cached(struct fscache_retrieval *op, pagevec_reinit(pagevec); } EXPORT_SYMBOL(fscache_mark_pages_cached); + +/* + * Uncache all the pages in an inode that are marked PG_fscache, assuming them + * to be associated with the given cookie. + */ +void __fscache_uncache_all_inode_pages(struct fscache_cookie *cookie, + struct inode *inode) +{ + struct address_space *mapping = inode->i_mapping; + struct pagevec pvec; + pgoff_t next; + int i; + + _enter("%p,%p", cookie, inode); + + if (!mapping || mapping->nrpages == 0) { + _leave(" [no pages]"); + return; + } + + pagevec_init(&pvec, 0); + next = 0; + while (next <= (loff_t)-1 && + pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE) + ) { + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + pgoff_t page_index = page->index; + + ASSERTCMP(page_index, >=, next); + next = page_index + 1; + + if (PageFsCache(page)) { + __fscache_wait_on_page_write(cookie, page); + __fscache_uncache_page(cookie, page); + } + } + pagevec_release(&pvec); + cond_resched(); + } + + _leave(""); +} +EXPORT_SYMBOL(__fscache_uncache_all_inode_pages); diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index ce153a6b3aec..419119c371bf 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -259,12 +259,10 @@ static void nfs_fscache_disable_inode_cookie(struct inode *inode) dfprintk(FSCACHE, "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode)); - /* Need to invalidate any mapped pages that were read in before - * turning off the cache. + /* Need to uncache any pages attached to this inode that + * fscache knows about before turning off the cache. */ - if (inode->i_mapping && inode->i_mapping->nrpages) - invalidate_inode_pages2(inode->i_mapping); - + fscache_uncache_all_inode_pages(NFS_I(inode)->fscache, inode); nfs_fscache_zap_inode_cookie(inode); } } diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 7c4d72f5581f..9ec20dec3353 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -204,6 +204,8 @@ extern bool __fscache_check_page_write(struct fscache_cookie *, struct page *); extern void __fscache_wait_on_page_write(struct fscache_cookie *, struct page *); extern bool __fscache_maybe_release_page(struct fscache_cookie *, struct page *, gfp_t); +extern void __fscache_uncache_all_inode_pages(struct fscache_cookie *, + struct inode *); /** * fscache_register_netfs - Register a filesystem as desiring caching services @@ -643,4 +645,23 @@ bool fscache_maybe_release_page(struct fscache_cookie *cookie, return false; } +/** + * fscache_uncache_all_inode_pages - Uncache all an inode's pages + * @cookie: The cookie representing the inode's cache object. + * @inode: The inode to uncache pages from. + * + * Uncache all the pages in an inode that are marked PG_fscache, assuming them + * to be associated with the given cookie. + * + * This function may sleep. It will wait for pages that are being written out + * and will wait whilst the PG_fscache mark is removed by the cache. + */ +static inline +void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie, + struct inode *inode) +{ + if (fscache_cookie_valid(cookie)) + __fscache_uncache_all_inode_pages(cookie, inode); +} + #endif /* _LINUX_FSCACHE_H */ -- cgit v1.2.3 From ca5c485f55d326d9a23e4badd05890148aa53f74 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 6 Jul 2011 17:03:45 -0400 Subject: USB: additional regression fix for device removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit e534c5b831c8b8e9f5edee5c8a37753c808b80dc (USB: fix regression occurring during device removal) didn't go far enough. It failed to take into account that when a driver claims multiple interfaces, it may release them all at the same time. As a result, some interfaces can get released before they are unregistered, and we deadlock trying to acquire the bandwidth_mutex that we already own. This patch (asl478) handles this case by setting the "unregistering" flag on all the interfaces before removing any of them. Signed-off-by: Alan Stern Cc: stable Tested-by: Éric Piel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index e0719b4ee189..0b5ec234c787 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1147,6 +1147,14 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) * any drivers bound to them (a key side effect) */ if (dev->actconfig) { + /* + * FIXME: In order to avoid self-deadlock involving the + * bandwidth_mutex, we have to mark all the interfaces + * before unregistering any of them. + */ + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) + dev->actconfig->interface[i]->unregistering = 1; + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *interface; @@ -1156,7 +1164,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) continue; dev_dbg(&dev->dev, "unregistering interface %s\n", dev_name(&interface->dev)); - interface->unregistering = 1; remove_intf_ep_devs(interface); device_del(&interface->dev); } -- cgit v1.2.3 From 5838e9b8dada491278db48ff9162e25125fa89d6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 8 Jul 2011 14:33:02 +0900 Subject: ARM: S3C24XX: don't use uninitialized variable in dma.c Commit 8970ef47 (S3C24XX: Remove hardware specific registers from DMA calls) removed the parameter dcon in s3c2410_dma_config() and calculates it on its own. So the debug-output for the old parameter can go, too. Fixes: arch/arm/plat-s3c24xx/dma.c: In function 's3c2410_dma_config': arch/arm/plat-s3c24xx/dma.c:1030:2: warning: 'dcon' is used uninitialized in this function Signed-off-by: Wolfram Sang Cc: Ben Dooks Signed-off-by: Kukjin Kim --- arch/arm/plat-s3c24xx/dma.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 2abf9660bc6c..a5b3684e1154 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1027,17 +1027,13 @@ int s3c2410_dma_config(unsigned int channel, struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); unsigned int dcon; - pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n", - __func__, channel, xferunit, dcon); + pr_debug("%s: chan=%d, xfer_unit=%d\n", __func__, channel, xferunit); if (chan == NULL) return -EINVAL; - pr_debug("%s: Initial dcon is %08x\n", __func__, dcon); - dcon = chan->dcon & dma_sel.dcon_mask; - - pr_debug("%s: New dcon is %08x\n", __func__, dcon); + pr_debug("%s: dcon is %08x\n", __func__, dcon); switch (chan->req_ch) { case DMACH_I2S_IN: -- cgit v1.2.3 From cb26a7b1c18857d14913040b45f3fe51b513f936 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 8 Jul 2011 14:33:02 +0900 Subject: ARM: S3C24XX: drop return codes in void function of dma.c Commit bb072c3c (ARM / Samsung: Use struct syscore_ops for "core" power management) turned s3c2410_dma_resume_chan() from int to void. So, drop the actual return values, too. Fixes: arch/arm/plat-s3c24xx/dma.c: In function 's3c2410_dma_resume_chan': arch/arm/plat-s3c24xx/dma.c:1238:3: warning: 'return' with a value, in function returning void arch/arm/plat-s3c24xx/dma.c:1250:2: warning: 'return' with a value, in function returning void Signed-off-by: Wolfram Sang Acked-by: Rafael J. Wysocki Signed-off-by: Kukjin Kim --- arch/arm/plat-s3c24xx/dma.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index a5b3684e1154..a79a8ccd25f6 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1231,7 +1231,7 @@ static void s3c2410_dma_resume_chan(struct s3c2410_dma_chan *cp) /* restore channel's hardware configuration */ if (!cp->in_use) - return 0; + return; printk(KERN_INFO "dma%d: restoring configuration\n", cp->number); @@ -1242,8 +1242,6 @@ static void s3c2410_dma_resume_chan(struct s3c2410_dma_chan *cp) if (cp->map != NULL) dma_sel.select(cp, cp->map); - - return 0; } static void s3c2410_dma_resume(void) -- cgit v1.2.3 From d34c1fcddc3a159d52576c656f8caabc0cf4894b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 8 Jul 2011 18:16:56 +0900 Subject: ARM: S3C2440: fix section mismatch on mini2440 If mini2440_init() is in __init, mini2440_parse_features() should also be in __init. Fixes: (.text+0x9adc): Section mismatch in reference from the function mini2440_parse_features.clone.0() to the (unknown reference) .init.data:(unknown) The function mini2440_parse_features.clone.0() references the (unknown reference) __initdata (unknown). Signed-off-by: Wolfram Sang Cc: Michel Pollet Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c2440/mach-mini2440.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c index dd3120df09fe..fc2dc0b3d4fe 100644 --- a/arch/arm/mach-s3c2440/mach-mini2440.c +++ b/arch/arm/mach-s3c2440/mach-mini2440.c @@ -552,7 +552,7 @@ struct mini2440_features_t { struct platform_device *optional[8]; }; -static void mini2440_parse_features( +static void __init mini2440_parse_features( struct mini2440_features_t * features, const char * features_str ) { -- cgit v1.2.3 From 2345b20fd9160d99f7cdf34e7b028ea351bf9c25 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 8 Jul 2011 10:02:18 +0100 Subject: gpio/langwell_gpio: ack the correct bit for langwell gpio interrupts The wrong bit was masked when acking langwell gpio interrupts. Reason for maskig the wrong bit was probably because__ffs() and ffs() functions return bit indexes differently (0..31 vs 1..32) This fixes langwell based devices from hanging when a gpio interrupt is triggered and undoes the breakage which occurred in change set 732063b92bb727b27e61580ce278dddefe31c6ad Signed-off-by: Mathias Nyman Signed-off-by: Alan Cox Signed-off-by: Grant Likely --- drivers/gpio/langwell_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index bd6571e0097a..644ba1255d3c 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c @@ -223,7 +223,7 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) gedr = gpio_reg(&lnw->chip, base, GEDR); pending = readl(gedr); while (pending) { - gpio = __ffs(pending) - 1; + gpio = __ffs(pending); mask = BIT(gpio); pending &= ~mask; /* Clear before handling so we can't lose an edge */ -- cgit v1.2.3 From b7eff394670366a42935bfbaef67a6f7185627d7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 8 Jul 2011 11:44:56 -0400 Subject: drm/radeon/kms: clean up multiple crtc handling for evergreen+ (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit evergreen+ asics have 2-6 crtcs. Don't access crtc registers for crtc regs that don't exist as they have very high latency and may cause problems on some asics. The previous code missed a few cases and was not fine grained enough (missed the 4 crtc case for example). Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=38800 v2: fix typo noticed by Chris Bandy Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Tested-by: Simon Farnsworth Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 159 +++++++++++++++++++++++-------------- 1 file changed, 98 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index a2d900809900..660f96401a05 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -985,17 +985,19 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav { save->vga_control[0] = RREG32(D1VGA_CONTROL); save->vga_control[1] = RREG32(D2VGA_CONTROL); - save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); - save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); - save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); - save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); save->vga_render_control = RREG32(VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { + save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); + save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); + save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); } @@ -1004,35 +1006,45 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav WREG32(VGA_RENDER_CONTROL, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); + } + if (rdev->num_crtc >= 6) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); } WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } WREG32(D1VGA_CONTROL, 0); WREG32(D2VGA_CONTROL, 0); - WREG32(EVERGREEN_D3VGA_CONTROL, 0); - WREG32(EVERGREEN_D4VGA_CONTROL, 0); - WREG32(EVERGREEN_D5VGA_CONTROL, 0); - WREG32(EVERGREEN_D6VGA_CONTROL, 0); + if (rdev->num_crtc >= 4) { + WREG32(EVERGREEN_D3VGA_CONTROL, 0); + WREG32(EVERGREEN_D4VGA_CONTROL, 0); + } + if (rdev->num_crtc >= 6) { + WREG32(EVERGREEN_D5VGA_CONTROL, 0); + WREG32(EVERGREEN_D6VGA_CONTROL, 0); + } } void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) @@ -1055,7 +1067,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, (u32)rdev->mc.vram_start); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, upper_32_bits(rdev->mc.vram_start)); WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, @@ -1073,7 +1085,8 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s (u32)rdev->mc.vram_start); WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, (u32)rdev->mc.vram_start); - + } + if (rdev->num_crtc >= 6) { WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, upper_32_bits(rdev->mc.vram_start)); WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, @@ -1101,31 +1114,41 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s /* Restore video state */ WREG32(D1VGA_CONTROL, save->vga_control[0]); WREG32(D2VGA_CONTROL, save->vga_control[1]); - WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); - WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); - WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); - WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); + if (rdev->num_crtc >= 4) { + WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); + WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); + } + if (rdev->num_crtc >= 6) { + WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); + WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); + } WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); + } + if (rdev->num_crtc >= 6) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); } WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); + } + if (rdev->num_crtc >= 6) { WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); } WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } @@ -2417,18 +2440,22 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) WREG32(GRBM_INT_CNTL, 0); WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } @@ -2547,19 +2574,25 @@ int evergreen_irq_set(struct radeon_device *rdev) WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1); WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2); - if (!(rdev->flags & RADEON_IS_IGP)) { + if (rdev->num_crtc >= 4) { WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3); WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); + } + if (rdev->num_crtc >= 6) { WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5); WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); } WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); + } WREG32(DC_HPD1_INT_CONTROL, hpd1); WREG32(DC_HPD2_INT_CONTROL, hpd2); @@ -2583,53 +2616,57 @@ static inline void evergreen_irq_ack(struct radeon_device *rdev) rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); - rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); - rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); - rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); - rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); + if (rdev->num_crtc >= 4) { + rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); + } if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); - if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) - WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); - if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) - WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); - if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) - WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); - if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) - WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK); - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK); if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); - - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); - - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); - - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); + if (rdev->num_crtc >= 4) { + if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); + } + + if (rdev->num_crtc >= 6) { + if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) + WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) + WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); + } if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { tmp = RREG32(DC_HPD1_INT_CONTROL); -- cgit v1.2.3 From e2cf3137aaa23faf2b8c1335671f1a0a0d90aab5 Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Wed, 15 Jun 2011 17:54:12 +0900 Subject: regulator: max8952 - fix wrong gpio valid check Signed-off-by: Jonghwan Choi Acked-by: MyungJoo Ham Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/max8952.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index daff7fd0e95c..486ed8141fcd 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -139,7 +139,7 @@ static int max8952_set_voltage(struct regulator_dev *rdev, s8 vid = -1, i; if (!gpio_is_valid(max8952->pdata->gpio_vid0) || - !gpio_is_valid(max8952->pdata->gpio_vid0)) { + !gpio_is_valid(max8952->pdata->gpio_vid1)) { /* DVS not supported */ return -EPERM; } -- cgit v1.2.3 From dbb48e7c3db4871803fc990864e37917e413ccb2 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Tue, 21 Jun 2011 09:08:59 +0530 Subject: regulator: MAX8997: Fix for divide by zero error Currently, ramp_delay variable is used uninitialzed in max8997_set_voltage_ldobuck which gets called through regulator_register calls. To fix the problem, in max8997_pmic_probe, ramp_delay initialization code is moved before calls to regulator_register. Cc: Liam Girdwood Cc: Mark Brown Cc: MyungJoo Ham Cc: Kyungmin Park Cc: Samuel Ortiz Signed-off-by: Tushar Behera Acked-by: MyungJoo Ham Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/max8997.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 10d5a1d9768e..0fc7b8c720d2 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -1124,6 +1124,10 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) 0x3f); } + /* Misc Settings */ + max8997->ramp_delay = 10; /* set 10mV/us, which is the default */ + max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9); + for (i = 0; i < pdata->num_regulators; i++) { const struct voltage_map_desc *desc; int id = pdata->regulators[i].id; @@ -1148,10 +1152,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) } } - /* Misc Settings */ - max8997->ramp_delay = 10; /* set 10mV/us, which is the default */ - max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9); - return 0; err: for (i = 0; i < max8997->num_regulators; i++) -- cgit v1.2.3 From 6e0414a5c89c708efe67f828f3a9c12293ce326e Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Mon, 20 Jun 2011 17:30:17 +0900 Subject: regulator: max8997: remove dependency on platform_data pointer The platform_data (pdata) may be pointing to __initdata section, which may be free'd from the memory. The dependency on pdata in non-init functions is removed in this patch to allow platform to declare __initdata for platform data. Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/max8997.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 0fc7b8c720d2..f8940c603cf0 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -39,25 +39,28 @@ struct max8997_data { struct regulator_dev **rdev; int ramp_delay; /* in mV/us */ + bool buck1_gpiodvs; + bool buck2_gpiodvs; + bool buck5_gpiodvs; u8 buck1_vol[8]; u8 buck2_vol[8]; u8 buck5_vol[8]; + int buck125_gpios[3]; int buck125_gpioindex; + bool ignore_gpiodvs_side_effect; u8 saved_states[MAX8997_REG_MAX]; }; static inline void max8997_set_gpio(struct max8997_data *max8997) { - struct max8997_platform_data *pdata = - dev_get_platdata(max8997->iodev->dev); int set3 = (max8997->buck125_gpioindex) & 0x1; int set2 = ((max8997->buck125_gpioindex) >> 1) & 0x1; int set1 = ((max8997->buck125_gpioindex) >> 2) & 0x1; - gpio_set_value(pdata->buck125_gpios[0], set1); - gpio_set_value(pdata->buck125_gpios[1], set2); - gpio_set_value(pdata->buck125_gpios[2], set3); + gpio_set_value(max8997->buck125_gpios[0], set1); + gpio_set_value(max8997->buck125_gpios[1], set2); + gpio_set_value(max8997->buck125_gpios[2], set3); } struct voltage_map_desc { @@ -380,8 +383,6 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev, static int max8997_get_voltage(struct regulator_dev *rdev) { struct max8997_data *max8997 = rdev_get_drvdata(rdev); - struct max8997_platform_data *pdata = - dev_get_platdata(max8997->iodev->dev); struct i2c_client *i2c = max8997->iodev->i2c; int reg, shift, mask, ret; int rid = max8997_get_rid(rdev); @@ -391,9 +392,9 @@ static int max8997_get_voltage(struct regulator_dev *rdev) if (ret) return ret; - if ((rid == MAX8997_BUCK1 && pdata->buck1_gpiodvs) || - (rid == MAX8997_BUCK2 && pdata->buck2_gpiodvs) || - (rid == MAX8997_BUCK5 && pdata->buck5_gpiodvs)) + if ((rid == MAX8997_BUCK1 && max8997->buck1_gpiodvs) || + (rid == MAX8997_BUCK2 && max8997->buck2_gpiodvs) || + (rid == MAX8997_BUCK5 && max8997->buck5_gpiodvs)) reg += max8997->buck125_gpioindex; ret = max8997_read_reg(i2c, reg, &val); @@ -561,8 +562,6 @@ static int max8997_assess_side_effect(struct regulator_dev *rdev, u8 new_val, int *best) { struct max8997_data *max8997 = rdev_get_drvdata(rdev); - struct max8997_platform_data *pdata = - dev_get_platdata(max8997->iodev->dev); int rid = max8997_get_rid(rdev); u8 *buckx_val[3]; bool buckx_gpiodvs[3]; @@ -589,9 +588,9 @@ static int max8997_assess_side_effect(struct regulator_dev *rdev, buckx_val[0] = max8997->buck1_vol; buckx_val[1] = max8997->buck2_vol; buckx_val[2] = max8997->buck5_vol; - buckx_gpiodvs[0] = pdata->buck1_gpiodvs; - buckx_gpiodvs[1] = pdata->buck2_gpiodvs; - buckx_gpiodvs[2] = pdata->buck5_gpiodvs; + buckx_gpiodvs[0] = max8997->buck1_gpiodvs; + buckx_gpiodvs[1] = max8997->buck2_gpiodvs; + buckx_gpiodvs[2] = max8997->buck5_gpiodvs; for (i = 0; i < 8; i++) { int others; @@ -640,8 +639,6 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct max8997_data *max8997 = rdev_get_drvdata(rdev); - struct max8997_platform_data *pdata = - dev_get_platdata(max8997->iodev->dev); int rid = max8997_get_rid(rdev); const struct voltage_map_desc *desc; int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; @@ -653,15 +650,15 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, switch (rid) { case MAX8997_BUCK1: - if (pdata->buck1_gpiodvs) + if (max8997->buck1_gpiodvs) gpio_dvs_mode = true; break; case MAX8997_BUCK2: - if (pdata->buck2_gpiodvs) + if (max8997->buck2_gpiodvs) gpio_dvs_mode = true; break; case MAX8997_BUCK5: - if (pdata->buck5_gpiodvs) + if (max8997->buck5_gpiodvs) gpio_dvs_mode = true; break; } @@ -695,7 +692,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, new_idx = tmp_idx; new_val = tmp_val; - if (pdata->ignore_gpiodvs_side_effect == false) + if (max8997->ignore_gpiodvs_side_effect == false) return -EINVAL; dev_warn(&rdev->dev, "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:" @@ -993,6 +990,11 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) i2c = max8997->iodev->i2c; max8997->buck125_gpioindex = pdata->buck125_default_idx; + max8997->buck1_gpiodvs = pdata->buck1_gpiodvs; + max8997->buck2_gpiodvs = pdata->buck2_gpiodvs; + max8997->buck5_gpiodvs = pdata->buck5_gpiodvs; + memcpy(max8997->buck125_gpios, pdata->buck125_gpios, sizeof(int) * 3); + max8997->ignore_gpiodvs_side_effect = pdata->ignore_gpiodvs_side_effect; for (i = 0; i < 8; i++) { max8997->buck1_vol[i] = ret = -- cgit v1.2.3 From 90609503b71b6ec4aaf325c88de98da28740bc1d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Jul 2011 11:41:12 +0800 Subject: regulator: db8500-prcmu: small fixes Small cleanups for better readability. Signed-off-by: Axel Lin Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/db8500-prcmu.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index e5f7b8fe51f4..2bb8f451cc06 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -266,7 +266,7 @@ static struct regulator_ops db8500_regulator_switch_ops = { * Regulator information */ static struct db8500_regulator_info - db8500_regulator_info[DB8500_NUM_REGULATORS] = { +db8500_regulator_info[DB8500_NUM_REGULATORS] = { [DB8500_REGULATOR_VAPE] = { .desc = { .name = "db8500-vape", @@ -492,11 +492,9 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) info->desc.name, err); /* if failing, unregister all earlier regulators */ - i--; - while (i >= 0) { + while (--i >= 0) { info = &db8500_regulator_info[i]; regulator_unregister(info->rdev); - i--; } return err; } @@ -536,13 +534,7 @@ static struct platform_driver db8500_regulator_driver = { static int __init db8500_regulator_init(void) { - int ret; - - ret = platform_driver_register(&db8500_regulator_driver); - if (ret < 0) - return -ENODEV; - - return 0; + return platform_driver_register(&db8500_regulator_driver); } static void __exit db8500_regulator_exit(void) -- cgit v1.2.3 From 6ff325a2d85481cbe31dfbb74b4fd2d94c115300 Mon Sep 17 00:00:00 2001 From: Donggeun Kim Date: Thu, 7 Jul 2011 16:51:56 +0900 Subject: regulator: max8997: Fix setting inappropriate value for ramp_delay variable The ramp_delay variable can be set lower than the desired value. This patch fixes it. Signed-off-by: Donggeun Kim Signed-off-by: MyungJoo Ham Signed-off-by: KyungMin Park Acked-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/regulator/max8997.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index f8940c603cf0..ad6628ca94f4 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -544,7 +544,8 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, rid == MAX8997_BUCK4 || rid == MAX8997_BUCK5) { /* If the voltage is increasing */ if (org < i) - udelay(desc->step * (i - org) / max8997->ramp_delay); + udelay(DIV_ROUND_UP(desc->step * (i - org), + max8997->ramp_delay)); } return ret; -- cgit v1.2.3 From f483d3923dc3a6394c483e28ccb3fe700bdf399e Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Thu, 7 Jul 2011 11:19:10 -0700 Subject: PCI: conditional resource-reallocation through kernel parameter pci=realloc Multiple attempts to dynamically reallocate pci resources have unfortunately lead to regressions. Though we continue to fix the regressions and fine tune the dynamic-reallocation behavior, we have not reached a acceptable state yet. This patch provides a interim solution. It disables dynamic reallocation by default, but adds the ability to enable it through pci=realloc kernel command line parameter. Tested-by: Oliver Hartkopp Signed-off-by: Ram Pai Signed-off-by: Jesse Barnes --- Documentation/kernel-parameters.txt | 2 ++ drivers/pci/pci.c | 2 ++ drivers/pci/pci.h | 2 ++ drivers/pci/setup-bus.c | 15 +++++++++++++++ 4 files changed, 21 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index fd248a318211..aa47be71df4c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2015,6 +2015,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. the default. off: Turn ECRC off on: Turn ECRC on. + realloc reallocate PCI resources if allocations done by BIOS + are erroneous. pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power Management. diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 2c5b9b991279..692671b11667 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3483,6 +3483,8 @@ static int __init pci_setup(char *str) pci_no_msi(); } else if (!strcmp(str, "noaer")) { pci_no_aer(); + } else if (!strncmp(str, "realloc", 7)) { + pci_realloc(); } else if (!strcmp(str, "nodomains")) { pci_no_domains(); } else if (!strncmp(str, "cbiosize=", 9)) { diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 731e20265ace..3a39bf1f1e2c 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -146,6 +146,8 @@ static inline void pci_no_msi(void) { } static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } #endif +extern void pci_realloc(void); + static inline int pci_no_d1d2(struct pci_dev *dev) { unsigned int parent_dstates = 0; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 1e9e5a5b8c81..9995842e45b5 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -47,6 +47,13 @@ struct resource_list_x { (head)->next = NULL; \ } while (0) +int pci_realloc_enable = 0; +#define pci_realloc_enabled() pci_realloc_enable +void pci_realloc(void) +{ + pci_realloc_enable = 1; +} + /** * add_to_list() - add a new resource tracker to the list * @head: Head of the list @@ -1025,6 +1032,7 @@ static int __init pci_get_max_depth(void) return depth; } + /* * first try will not touch pci bridge res * second and later try will clear small leaf bridge res @@ -1068,6 +1076,13 @@ again: /* any device complain? */ if (!head.next) goto enable_and_dump; + + /* don't realloc if asked to do so */ + if (!pci_realloc_enabled()) { + free_list(resource_list_x, &head); + goto enable_and_dump; + } + failed_type = 0; for (list = head.next; list;) { failed_type |= list->flags; -- cgit v1.2.3 From 27739e694a3c34b5e371575d74e500d60111c689 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 27 Jun 2011 11:22:46 -0700 Subject: hwmon: (lm95241) Fix chip detection code The LM95241 driver accepts every chip ID equal to or larger than 0xA4 as its own, and other chips such as LM95245 use chip IDs in the accepted ID range. This results in false chip detection. Fix problem by accepting only the known LM95241 chip ID. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.30+ --- drivers/hwmon/lm95241.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 1a6dfb6df1e7..01c638e31e07 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -339,7 +339,7 @@ static int lm95241_detect(struct i2c_client *new_client, if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) == MANUFACTURER_ID) && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) - >= DEFAULT_REVISION)) { + == DEFAULT_REVISION)) { name = DEVNAME; } else { dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n", -- cgit v1.2.3 From 08951e545918c1594434d000d88a7793e2452a9b Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 8 Jul 2011 15:39:36 -0700 Subject: mm: vmscan: correct check for kswapd sleeping in sleeping_prematurely MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During allocator-intensive workloads, kswapd will be woken frequently causing free memory to oscillate between the high and min watermark. This is expected behaviour. Unfortunately, if the highest zone is small, a problem occurs. This seems to happen most with recent sandybridge laptops but it's probably a co-incidence as some of these laptops just happen to have a small Normal zone. The reproduction case is almost always during copying large files that kswapd pegs at 100% CPU until the file is deleted or cache is dropped. The problem is mostly down to sleeping_prematurely() keeping kswapd awake when the highest zone is small and unreclaimable and compounded by the fact we shrink slabs even when not shrinking zones causing a lot of time to be spent in shrinkers and a lot of memory to be reclaimed. Patch 1 corrects sleeping_prematurely to check the zones matching the classzone_idx instead of all zones. Patch 2 avoids shrinking slab when we are not shrinking a zone. Patch 3 notes that sleeping_prematurely is checking lower zones against a high classzone which is not what allocators or balance_pgdat() is doing leading to an artifical belief that kswapd should be still awake. Patch 4 notes that when balance_pgdat() gives up on a high zone that the decision is not communicated to sleeping_prematurely() This problem affects 2.6.38.8 for certain and is expected to affect 2.6.39 and 3.0-rc4 as well. If accepted, they need to go to -stable to be picked up by distros and this series is against 3.0-rc4. I've cc'd people that reported similar problems recently to see if they still suffer from the problem and if this fixes it. This patch: correct the check for kswapd sleeping in sleeping_prematurely() During allocator-intensive workloads, kswapd will be woken frequently causing free memory to oscillate between the high and min watermark. This is expected behaviour. A problem occurs if the highest zone is small. balance_pgdat() only considers unreclaimable zones when priority is DEF_PRIORITY but sleeping_prematurely considers all zones. It's possible for this sequence to occur 1. kswapd wakes up and enters balance_pgdat() 2. At DEF_PRIORITY, marks highest zone unreclaimable 3. At DEF_PRIORITY-1, ignores highest zone setting end_zone 4. At DEF_PRIORITY-1, calls shrink_slab freeing memory from highest zone, clearing all_unreclaimable. Highest zone is still unbalanced 5. kswapd returns and calls sleeping_prematurely 6. sleeping_prematurely looks at *all* zones, not just the ones being considered by balance_pgdat. The highest small zone has all_unreclaimable cleared but the zone is not balanced. all_zones_ok is false so kswapd stays awake This patch corrects the behaviour of sleeping_prematurely to check the zones balance_pgdat() checked. Signed-off-by: Mel Gorman Reported-by: Pádraig Brady Tested-by: Pádraig Brady Tested-by: Andrew Lutomirski Acked-by: Rik van Riel Reviewed-by: Minchan Kim Reviewed-by: KOSAKI Motohiro Cc: Johannes Weiner Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 4f49535d4cd3..04c49fe781fe 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2326,7 +2326,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining, return true; /* Check the watermark levels */ - for (i = 0; i < pgdat->nr_zones; i++) { + for (i = 0; i <= classzone_idx; i++) { struct zone *zone = pgdat->node_zones + i; if (!populated_zone(zone)) -- cgit v1.2.3 From d7868dae893c83c50c7824bc2bc75f93d114669f Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 8 Jul 2011 15:39:38 -0700 Subject: mm: vmscan: do not apply pressure to slab if we are not applying pressure to zone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During allocator-intensive workloads, kswapd will be woken frequently causing free memory to oscillate between the high and min watermark. This is expected behaviour. When kswapd applies pressure to zones during node balancing, it checks if the zone is above a high+balance_gap threshold. If it is, it does not apply pressure but it unconditionally shrinks slab on a global basis which is excessive. In the event kswapd is being kept awake due to a high small unreclaimable zone, it skips zone shrinking but still calls shrink_slab(). Once pressure has been applied, the check for zone being unreclaimable is being made before the check is made if all_unreclaimable should be set. This miss of unreclaimable can cause has_under_min_watermark_zone to be set due to an unreclaimable zone preventing kswapd backing off on congestion_wait(). Signed-off-by: Mel Gorman Reported-by: Pádraig Brady Tested-by: Pádraig Brady Tested-by: Andrew Lutomirski Acked-by: Rik van Riel Reviewed-by: Minchan Kim Reviewed-by: KOSAKI Motohiro Cc: Johannes Weiner Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 04c49fe781fe..a0245861934a 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2510,18 +2510,18 @@ loop_again: KSWAPD_ZONE_BALANCE_GAP_RATIO); if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone) + balance_gap, - end_zone, 0)) + end_zone, 0)) { shrink_zone(priority, zone, &sc); - reclaim_state->reclaimed_slab = 0; - nr_slab = shrink_slab(&shrink, sc.nr_scanned, lru_pages); - sc.nr_reclaimed += reclaim_state->reclaimed_slab; - total_scanned += sc.nr_scanned; - if (zone->all_unreclaimable) - continue; - if (nr_slab == 0 && - !zone_reclaimable(zone)) - zone->all_unreclaimable = 1; + reclaim_state->reclaimed_slab = 0; + nr_slab = shrink_slab(&shrink, sc.nr_scanned, lru_pages); + sc.nr_reclaimed += reclaim_state->reclaimed_slab; + total_scanned += sc.nr_scanned; + + if (nr_slab == 0 && !zone_reclaimable(zone)) + zone->all_unreclaimable = 1; + } + /* * If we've done a decent amount of scanning and * the reclaim ratio is low, start doing writepage @@ -2531,6 +2531,9 @@ loop_again: total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2) sc.may_writepage = 1; + if (zone->all_unreclaimable) + continue; + if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), end_zone, 0)) { all_zones_ok = 0; -- cgit v1.2.3 From da175d06b437093f93109ba9e5efbe44dfdf9409 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 8 Jul 2011 15:39:39 -0700 Subject: mm: vmscan: evaluate the watermarks against the correct classzone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When deciding if kswapd is sleeping prematurely, the classzone is taken into account but this is different to what balance_pgdat() and the allocator are doing. Specifically, the DMA zone will be checked based on the classzone used when waking kswapd which could be for a GFP_KERNEL or GFP_HIGHMEM request. The lowmem reserve limit kicks in, the watermark is not met and kswapd thinks it's sleeping prematurely keeping kswapd awake in error. Signed-off-by: Mel Gorman Reported-by: Pádraig Brady Tested-by: Pádraig Brady Tested-by: Andrew Lutomirski Acked-by: Rik van Riel Reviewed-by: Minchan Kim Cc: KOSAKI Motohiro Cc: Johannes Weiner Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index a0245861934a..a51b3c9f05ba 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2344,7 +2344,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining, } if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), - classzone_idx, 0)) + i, 0)) all_zones_ok = false; else balanced += zone->present_pages; -- cgit v1.2.3 From 215ddd6664ced067afca7eebd2d1eb83f064ff5a Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 8 Jul 2011 15:39:40 -0700 Subject: mm: vmscan: only read new_classzone_idx from pgdat when reclaiming successfully MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During allocator-intensive workloads, kswapd will be woken frequently causing free memory to oscillate between the high and min watermark. This is expected behaviour. Unfortunately, if the highest zone is small, a problem occurs. When balance_pgdat() returns, it may be at a lower classzone_idx than it started because the highest zone was unreclaimable. Before checking if it should go to sleep though, it checks pgdat->classzone_idx which when there is no other activity will be MAX_NR_ZONES-1. It interprets this as it has been woken up while reclaiming, skips scheduling and reclaims again. As there is no useful reclaim work to do, it enters into a loop of shrinking slab consuming loads of CPU until the highest zone becomes reclaimable for a long period of time. There are two problems here. 1) If the returned classzone or order is lower, it'll continue reclaiming without scheduling. 2) if the highest zone was marked unreclaimable but balance_pgdat() returns immediately at DEF_PRIORITY, the new lower classzone is not communicated back to kswapd() for sleeping. This patch does two things that are related. If the end_zone is unreclaimable, this information is communicated back. Second, if the classzone or order was reduced due to failing to reclaim, new information is not read from pgdat and instead an attempt is made to go to sleep. Due to this, it is also necessary that pgdat->classzone_idx be initialised each time to pgdat->nr_zones - 1 to avoid re-reads being interpreted as wakeups. Signed-off-by: Mel Gorman Reported-by: Pádraig Brady Tested-by: Pádraig Brady Tested-by: Andrew Lutomirski Acked-by: Rik van Riel Cc: Minchan Kim Cc: KOSAKI Motohiro Cc: Johannes Weiner Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index a51b3c9f05ba..5ed24b94c5e6 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2451,7 +2451,6 @@ loop_again: if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), 0, 0)) { end_zone = i; - *classzone_idx = i; break; } } @@ -2531,8 +2530,11 @@ loop_again: total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2) sc.may_writepage = 1; - if (zone->all_unreclaimable) + if (zone->all_unreclaimable) { + if (end_zone && end_zone == i) + end_zone--; continue; + } if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), end_zone, 0)) { @@ -2712,8 +2714,8 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx) */ static int kswapd(void *p) { - unsigned long order; - int classzone_idx; + unsigned long order, new_order; + int classzone_idx, new_classzone_idx; pg_data_t *pgdat = (pg_data_t*)p; struct task_struct *tsk = current; @@ -2743,17 +2745,23 @@ static int kswapd(void *p) tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD; set_freezable(); - order = 0; - classzone_idx = MAX_NR_ZONES - 1; + order = new_order = 0; + classzone_idx = new_classzone_idx = pgdat->nr_zones - 1; for ( ; ; ) { - unsigned long new_order; - int new_classzone_idx; int ret; - new_order = pgdat->kswapd_max_order; - new_classzone_idx = pgdat->classzone_idx; - pgdat->kswapd_max_order = 0; - pgdat->classzone_idx = MAX_NR_ZONES - 1; + /* + * If the last balance_pgdat was unsuccessful it's unlikely a + * new request of a similar or harder type will succeed soon + * so consider going to sleep on the basis we reclaimed at + */ + if (classzone_idx >= new_classzone_idx && order == new_order) { + new_order = pgdat->kswapd_max_order; + new_classzone_idx = pgdat->classzone_idx; + pgdat->kswapd_max_order = 0; + pgdat->classzone_idx = pgdat->nr_zones - 1; + } + if (order < new_order || classzone_idx > new_classzone_idx) { /* * Don't sleep if someone wants a larger 'order' @@ -2766,7 +2774,7 @@ static int kswapd(void *p) order = pgdat->kswapd_max_order; classzone_idx = pgdat->classzone_idx; pgdat->kswapd_max_order = 0; - pgdat->classzone_idx = MAX_NR_ZONES - 1; + pgdat->classzone_idx = pgdat->nr_zones - 1; } ret = try_to_freeze(); -- cgit v1.2.3 From 0b43c3aab0137595335b08b340a3f3e5af9818a6 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 8 Jul 2011 15:39:41 -0700 Subject: mm: __tlb_remove_page() check the correct batch __tlb_remove_page() switches to a new batch page, but still checks space in the old batch. This check always fails, and causes a forced tlb flush. Signed-off-by: Shaohua Li Acked-by: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/memory.c b/mm/memory.c index 40b7531ee8ba..9b8a01d941cb 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -305,6 +305,7 @@ int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) if (batch->nr == batch->max) { if (!tlb_next_batch(tlb)) return 0; + batch = tlb->active; } VM_BUG_ON(batch->nr > batch->max); -- cgit v1.2.3 From 4d0c066d29f030d47d19678f8008933e67dd3b72 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Fri, 8 Jul 2011 15:39:42 -0700 Subject: memcg: fix reclaimable lru check in memcg Now, in mem_cgroup_hierarchical_reclaim(), mem_cgroup_local_usage() is used for checking whether the memcg contains reclaimable pages or not. If no pages in it, the routine skips it. But, mem_cgroup_local_usage() contains Unevictable pages and cannot handle "noswap" condition correctly. This doesn't work on a swapless system. This patch adds test_mem_cgroup_reclaimable() and replaces mem_cgroup_local_usage(). test_mem_cgroup_reclaimable() see LRU counter and returns correct answer to the caller. And this new function has "noswap" argument and can see only FILE LRU if necessary. [akpm@linux-foundation.org: coding-style fixes] [akpm@linux-foundation.org: fix kerneldoc layout] Signed-off-by: KAMEZAWA Hiroyuki Cc: Michal Hocko Cc: Ying Han Cc: Johannes Weiner Cc: Daisuke Nishimura Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 107 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 31 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index ddffc74cdebe..a7a5cb1bf2c7 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -577,15 +577,6 @@ static long mem_cgroup_read_stat(struct mem_cgroup *mem, return val; } -static long mem_cgroup_local_usage(struct mem_cgroup *mem) -{ - long ret; - - ret = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_RSS); - ret += mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_CACHE); - return ret; -} - static void mem_cgroup_swap_statistics(struct mem_cgroup *mem, bool charge) { @@ -1129,7 +1120,6 @@ unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, return MEM_CGROUP_ZSTAT(mz, lru); } -#ifdef CONFIG_NUMA static unsigned long mem_cgroup_node_nr_file_lru_pages(struct mem_cgroup *memcg, int nid) { @@ -1141,6 +1131,17 @@ static unsigned long mem_cgroup_node_nr_file_lru_pages(struct mem_cgroup *memcg, return ret; } +static unsigned long mem_cgroup_node_nr_anon_lru_pages(struct mem_cgroup *memcg, + int nid) +{ + unsigned long ret; + + ret = mem_cgroup_get_zonestat_node(memcg, nid, LRU_INACTIVE_ANON) + + mem_cgroup_get_zonestat_node(memcg, nid, LRU_ACTIVE_ANON); + return ret; +} + +#if MAX_NUMNODES > 1 static unsigned long mem_cgroup_nr_file_lru_pages(struct mem_cgroup *memcg) { u64 total = 0; @@ -1152,17 +1153,6 @@ static unsigned long mem_cgroup_nr_file_lru_pages(struct mem_cgroup *memcg) return total; } -static unsigned long mem_cgroup_node_nr_anon_lru_pages(struct mem_cgroup *memcg, - int nid) -{ - unsigned long ret; - - ret = mem_cgroup_get_zonestat_node(memcg, nid, LRU_INACTIVE_ANON) + - mem_cgroup_get_zonestat_node(memcg, nid, LRU_ACTIVE_ANON); - - return ret; -} - static unsigned long mem_cgroup_nr_anon_lru_pages(struct mem_cgroup *memcg) { u64 total = 0; @@ -1559,6 +1549,28 @@ mem_cgroup_select_victim(struct mem_cgroup *root_mem) return ret; } +/** + * test_mem_cgroup_node_reclaimable + * @mem: the target memcg + * @nid: the node ID to be checked. + * @noswap : specify true here if the user wants flle only information. + * + * This function returns whether the specified memcg contains any + * reclaimable pages on a node. Returns true if there are any reclaimable + * pages in the node. + */ +static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *mem, + int nid, bool noswap) +{ + if (mem_cgroup_node_nr_file_lru_pages(mem, nid)) + return true; + if (noswap || !total_swap_pages) + return false; + if (mem_cgroup_node_nr_anon_lru_pages(mem, nid)) + return true; + return false; + +} #if MAX_NUMNODES > 1 /* @@ -1580,15 +1592,8 @@ static void mem_cgroup_may_update_nodemask(struct mem_cgroup *mem) for_each_node_mask(nid, node_states[N_HIGH_MEMORY]) { - if (mem_cgroup_get_zonestat_node(mem, nid, LRU_INACTIVE_FILE) || - mem_cgroup_get_zonestat_node(mem, nid, LRU_ACTIVE_FILE)) - continue; - - if (total_swap_pages && - (mem_cgroup_get_zonestat_node(mem, nid, LRU_INACTIVE_ANON) || - mem_cgroup_get_zonestat_node(mem, nid, LRU_ACTIVE_ANON))) - continue; - node_clear(nid, mem->scan_nodes); + if (!test_mem_cgroup_node_reclaimable(mem, nid, false)) + node_clear(nid, mem->scan_nodes); } } @@ -1627,11 +1632,51 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *mem) return node; } +/* + * Check all nodes whether it contains reclaimable pages or not. + * For quick scan, we make use of scan_nodes. This will allow us to skip + * unused nodes. But scan_nodes is lazily updated and may not cotain + * enough new information. We need to do double check. + */ +bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap) +{ + int nid; + + /* + * quick check...making use of scan_node. + * We can skip unused nodes. + */ + if (!nodes_empty(mem->scan_nodes)) { + for (nid = first_node(mem->scan_nodes); + nid < MAX_NUMNODES; + nid = next_node(nid, mem->scan_nodes)) { + + if (test_mem_cgroup_node_reclaimable(mem, nid, noswap)) + return true; + } + } + /* + * Check rest of nodes. + */ + for_each_node_state(nid, N_HIGH_MEMORY) { + if (node_isset(nid, mem->scan_nodes)) + continue; + if (test_mem_cgroup_node_reclaimable(mem, nid, noswap)) + return true; + } + return false; +} + #else int mem_cgroup_select_victim_node(struct mem_cgroup *mem) { return 0; } + +bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap) +{ + return test_mem_cgroup_node_reclaimable(mem, 0, noswap); +} #endif /* @@ -1702,7 +1747,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, } } } - if (!mem_cgroup_local_usage(victim)) { + if (!mem_cgroup_reclaimable(victim, noswap)) { /* this cgroup's local usage == 0 */ css_put(&victim->css); continue; -- cgit v1.2.3 From 453a9bf347f1e22a5bb3605ced43b2366921221d Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Fri, 8 Jul 2011 15:39:43 -0700 Subject: memcg: fix numa scan information update to be triggered by memory event commit 889976dbcb12 ("memcg: reclaim memory from nodes in round-robin order") adds an numa node round-robin for memcg. But the information is updated once per 10sec. This patch changes the update trigger from jiffies to memcg's event count. After this patch, numa scan information will be updated when we see 1024 events of pagein/pageout under a memcg. [akpm@linux-foundation.org: attempt to repair code layout] Signed-off-by: KAMEZAWA Hiroyuki Cc: Michal Hocko Cc: Ying Han Cc: Johannes Weiner Cc: Daisuke Nishimura Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a7a5cb1bf2c7..e013b8e57d25 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -108,10 +108,12 @@ enum mem_cgroup_events_index { enum mem_cgroup_events_target { MEM_CGROUP_TARGET_THRESH, MEM_CGROUP_TARGET_SOFTLIMIT, + MEM_CGROUP_TARGET_NUMAINFO, MEM_CGROUP_NTARGETS, }; #define THRESHOLDS_EVENTS_TARGET (128) #define SOFTLIMIT_EVENTS_TARGET (1024) +#define NUMAINFO_EVENTS_TARGET (1024) struct mem_cgroup_stat_cpu { long count[MEM_CGROUP_STAT_NSTATS]; @@ -237,7 +239,8 @@ struct mem_cgroup { int last_scanned_node; #if MAX_NUMNODES > 1 nodemask_t scan_nodes; - unsigned long next_scan_node_update; + atomic_t numainfo_events; + atomic_t numainfo_updating; #endif /* * Should the accounting and control be hierarchical, per subtree? @@ -680,6 +683,9 @@ static void __mem_cgroup_target_update(struct mem_cgroup *mem, int target) case MEM_CGROUP_TARGET_SOFTLIMIT: next = val + SOFTLIMIT_EVENTS_TARGET; break; + case MEM_CGROUP_TARGET_NUMAINFO: + next = val + NUMAINFO_EVENTS_TARGET; + break; default: return; } @@ -698,11 +704,19 @@ static void memcg_check_events(struct mem_cgroup *mem, struct page *page) mem_cgroup_threshold(mem); __mem_cgroup_target_update(mem, MEM_CGROUP_TARGET_THRESH); if (unlikely(__memcg_event_check(mem, - MEM_CGROUP_TARGET_SOFTLIMIT))){ + MEM_CGROUP_TARGET_SOFTLIMIT))) { mem_cgroup_update_tree(mem, page); __mem_cgroup_target_update(mem, - MEM_CGROUP_TARGET_SOFTLIMIT); + MEM_CGROUP_TARGET_SOFTLIMIT); + } +#if MAX_NUMNODES > 1 + if (unlikely(__memcg_event_check(mem, + MEM_CGROUP_TARGET_NUMAINFO))) { + atomic_inc(&mem->numainfo_events); + __mem_cgroup_target_update(mem, + MEM_CGROUP_TARGET_NUMAINFO); } +#endif } } @@ -1582,11 +1596,15 @@ static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *mem, static void mem_cgroup_may_update_nodemask(struct mem_cgroup *mem) { int nid; - - if (time_after(mem->next_scan_node_update, jiffies)) + /* + * numainfo_events > 0 means there was at least NUMAINFO_EVENTS_TARGET + * pagein/pageout changes since the last update. + */ + if (!atomic_read(&mem->numainfo_events)) + return; + if (atomic_inc_return(&mem->numainfo_updating) > 1) return; - mem->next_scan_node_update = jiffies + 10*HZ; /* make a nodemask where this memcg uses memory from */ mem->scan_nodes = node_states[N_HIGH_MEMORY]; @@ -1595,6 +1613,9 @@ static void mem_cgroup_may_update_nodemask(struct mem_cgroup *mem) if (!test_mem_cgroup_node_reclaimable(mem, nid, false)) node_clear(nid, mem->scan_nodes); } + + atomic_set(&mem->numainfo_events, 0); + atomic_set(&mem->numainfo_updating, 0); } /* -- cgit v1.2.3 From f607e7fc5fb94d92030c4527287e9c149ddf9e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Dagenais?= Date: Fri, 8 Jul 2011 15:39:44 -0700 Subject: w1: ds1wm: add a reset recovery parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a regression in 3.0 reported by Paul Parsons regarding the removal of the msleep(1) in the ds1wm_reset() function: : The linux-3.0-rc4 DS1WM 1-wire driver is logging "bus error, retrying" : error messages on an HP iPAQ hx4700 PDA (XScale-PXA270): : : : Driver for 1-wire Dallas network protocol. : DS1WM w1 busmaster driver - (c) 2004 Szabolcs Gyurko : 1-Wire driver for the DS2760 battery monitor chip - (c) 2004-2005, Szabolcs Gyurko : ds1wm ds1wm: pass: 1 bus error, retrying : ds1wm ds1wm: pass: 2 bus error, retrying : ds1wm ds1wm: pass: 3 bus error, retrying : ds1wm ds1wm: pass: 4 bus error, retrying : ds1wm ds1wm: pass: 5 bus error, retrying : ... : : The visible result is that the battery charging LED is erratic; sometimes : it works, mostly it doesn't. : : The linux-2.6.39 DS1WM 1-wire driver worked OK. I haven't tried 3.0-rc1, : 3.0-rc2, or 3.0-rc3. This sleep should not be required on normal circuitry provided the pull-ups on the bus are correctly adapted to the slaves. Unfortunately, this is not always the case. The sleep is restored but as a parameter to the probe function in the pdata. [akpm@linux-foundation.org: coding-style fixes] Reported-by: Paul Parsons Tested-by: Paul Parsons Signed-off-by: Jean-François Dagenais Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mfd/asic3.c | 1 + drivers/mfd/htc-pasic3.c | 1 + drivers/w1/masters/ds1wm.c | 5 +++++ include/linux/mfd/ds1wm.h | 7 +++++++ 4 files changed, 14 insertions(+) diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index c27fd1fc3b86..c71ae09430c5 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -619,6 +619,7 @@ static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk) /* MFD cells (SPI, PWM, LED, DS1WM, MMC) */ static struct ds1wm_driver_data ds1wm_pdata = { .active_high = 1, + .reset_recover_delay = 1, }; static struct resource ds1wm_resources[] = { diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 2808bd125d13..04c7093d6499 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -99,6 +99,7 @@ static int ds1wm_disable(struct platform_device *pdev) static struct ds1wm_driver_data ds1wm_pdata = { .active_high = 0, + .reset_recover_delay = 1, }; static struct resource ds1wm_resources[] __initdata = { diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index ad57593d224a..a0c8965c1a79 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c @@ -109,6 +109,7 @@ struct ds1wm_data { /* byte to write that makes all intr disabled, */ /* considering active_state (IAS) (optimization) */ u8 int_en_reg_none; + unsigned int reset_recover_delay; /* see ds1wm.h */ }; static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg, @@ -187,6 +188,9 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data) return 1; } + if (ds1wm_data->reset_recover_delay) + msleep(ds1wm_data->reset_recover_delay); + return 0; } @@ -490,6 +494,7 @@ static int ds1wm_probe(struct platform_device *pdev) } ds1wm_data->irq = res->start; ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0); + ds1wm_data->reset_recover_delay = plat->reset_recover_delay; if (res->flags & IORESOURCE_IRQ_HIGHEDGE) irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING); diff --git a/include/linux/mfd/ds1wm.h b/include/linux/mfd/ds1wm.h index be469a357cbb..38a372a0e285 100644 --- a/include/linux/mfd/ds1wm.h +++ b/include/linux/mfd/ds1wm.h @@ -3,4 +3,11 @@ struct ds1wm_driver_data { int active_high; int clock_rate; + /* in milliseconds, the amount of time to */ + /* sleep following a reset pulse. Zero */ + /* should work if your bus devices recover*/ + /* time respects the 1-wire spec since the*/ + /* ds1wm implements the precise timings of*/ + /* a reset pulse/presence detect sequence.*/ + unsigned int reset_recover_delay; }; -- cgit v1.2.3 From 8f3b1327aa454bc8283e96bca7669c3c88b83f79 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Fri, 8 Jul 2011 15:39:46 -0700 Subject: mm/nommu.c: fix remap_pfn_range() remap_pfn_range() means map physical address pfn<vm_start = pfn << PAGE_SHIFT which is wrong acroding the original meaning of this function. And some driver developer using remap_pfn_range() with correct parameter will get unexpected result because vm_start is changed. It should be implementd like addr = pfn << PAGE_SHIFT but which is meanless on nommu arch, this patch just make it simply return. Parameter name and setting of vma->vm_flags also be fixed. Signed-off-by: Bob Liu Cc: Geert Uytterhoeven Cc: David Howells Acked-by: Greg Ungerer Cc: Mike Frysinger Cc: Bob Liu Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/nommu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mm/nommu.c b/mm/nommu.c index 1fd0c51b10a6..9edc897a3970 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1813,10 +1813,13 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, return NULL; } -int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, - unsigned long to, unsigned long size, pgprot_t prot) +int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, unsigned long size, pgprot_t prot) { - vma->vm_start = vma->vm_pgoff << PAGE_SHIFT; + if (addr != (pfn << PAGE_SHIFT)) + return -EINVAL; + + vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; return 0; } EXPORT_SYMBOL(remap_pfn_range); -- cgit v1.2.3 From 30cb35be6daff48ad6c049466ac92a22c200d1b2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 8 Jul 2011 15:39:46 -0700 Subject: drivers/leds/leds-pca9532.c: change driver name to be unique This driver handles the variants pca9530-pca9533, so it chose the name "pca953x". However, there is a gpio driver which decided on the same name. As a result, those two can't be loaded at the same time. Add a subsystem prefix to make the driver name unique. Device matching will not suffer, because both are I2C drivers which match using a i2c_device_id-table which is not altered. Signed-off-by: Wolfram Sang Acked-by: Jean Delvare Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-pca9532.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index d8d3a1e910a1..a2c874623e35 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -88,7 +88,7 @@ static const struct pca9532_chip_info pca9532_chip_info_tbl[] = { static struct i2c_driver pca9532_driver = { .driver = { - .name = "pca953x", + .name = "leds-pca953x", }, .probe = pca9532_probe, .remove = pca9532_remove, -- cgit v1.2.3 From c2d197e82b6267fd3338f3fbcb12750ca9f5abda Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 8 Jul 2011 15:39:48 -0700 Subject: MAINTAINERS: update Bjorn Helgaas's email address Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9820e89c827c..4af7ab032660 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4982,7 +4982,7 @@ F: drivers/power/power_supply* PNP SUPPORT M: Adam Belay -M: Bjorn Helgaas +M: Bjorn Helgaas S: Maintained F: drivers/pnp/ -- cgit v1.2.3 From abaead6ac55dbda8b4bae40251d69dc3f0c49b1c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 9 Jul 2011 11:55:28 +0200 Subject: ALSA: hda - Fix a copmile warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's harmless but annyoing. sound/pci/hda/patch_realtek.c: In function ‘alc_cap_getput_caller’: sound/pci/hda/patch_realtek.c:2722:9: warning: ‘err’ may be used uninitialized in this function Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7d492713c1c1..b48fb43b5448 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2719,7 +2719,7 @@ static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; - int i, err; + int i, err = 0; mutex_lock(&codec->control_mutex); if (check_adc_switch && spec->dual_adc_switch) { -- cgit v1.2.3 From 0c2a40e2fe4f4af0410f57e84b95b817ec15aa70 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 30 Jun 2011 02:09:37 -0700 Subject: hwmon: (lm95241) Fix negative temperature results Negative temperatures were returned in degrees C instead of milli-Degrees C. Also, negative temperatures were reported for remote temperature sensors even if the chip was configured for positive-only results. Fix by detecting temperature modes, and by treating negative temperatures similar to positive temperatures, with appropriate sign extension. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.30+ --- drivers/hwmon/lm95241.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 01c638e31e07..d3b464b74ced 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -98,11 +98,16 @@ struct lm95241_data { }; /* Conversions */ -static int TempFromReg(u8 val_h, u8 val_l) +static int temp_from_reg_signed(u8 val_h, u8 val_l) { - if (val_h & 0x80) - return val_h - 0x100; - return val_h * 1000 + val_l * 1000 / 256; + s16 val_hl = (val_h << 8) | val_l; + return val_hl * 1000 / 256; +} + +static int temp_from_reg_unsigned(u8 val_h, u8 val_l) +{ + u16 val_hl = (val_h << 8) | val_l; + return val_hl * 1000 / 256; } static struct lm95241_data *lm95241_update_device(struct device *dev) @@ -135,10 +140,13 @@ static ssize_t show_input(struct device *dev, struct device_attribute *attr, char *buf) { struct lm95241_data *data = lm95241_update_device(dev); + int index = to_sensor_dev_attr(attr)->index; return snprintf(buf, PAGE_SIZE - 1, "%d\n", - TempFromReg(data->temp[to_sensor_dev_attr(attr)->index], - data->temp[to_sensor_dev_attr(attr)->index + 1])); + index == 0 || (data->config & (1 << (index / 2))) ? + temp_from_reg_signed(data->temp[index], data->temp[index + 1]) : + temp_from_reg_unsigned(data->temp[index], + data->temp[index + 1])); } static ssize_t show_type(struct device *dev, struct device_attribute *attr, -- cgit v1.2.3 From 22e6b2312d221376dcd98a8afb0f314b62d33a91 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 3 Jul 2011 13:08:03 -0700 Subject: hwmon: (pmbus) Improve auto-detection of temperature status register It is possible that a PMBus device supports the READ_TEMPERATURE2 and/or READ_TEMPERATURE3 registers but does not support READ_TEMPERATURE1. Improve temperature status register detection to address this condition. Reported-by: Jean Delvare Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.39+ --- drivers/hwmon/pmbus.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/pmbus.c b/drivers/hwmon/pmbus.c index 931d940923ae..9b1f0c37ef77 100644 --- a/drivers/hwmon/pmbus.c +++ b/drivers/hwmon/pmbus.c @@ -59,16 +59,17 @@ static void pmbus_find_sensor_groups(struct i2c_client *client, if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) info->func[0] |= PMBUS_HAVE_STATUS_FAN34; } - if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) { + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) info->func[0] |= PMBUS_HAVE_TEMP; - if (pmbus_check_byte_register(client, 0, - PMBUS_STATUS_TEMPERATURE)) - info->func[0] |= PMBUS_HAVE_STATUS_TEMP; - } if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) info->func[0] |= PMBUS_HAVE_TEMP2; if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) info->func[0] |= PMBUS_HAVE_TEMP3; + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3) + && pmbus_check_byte_register(client, 0, + PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; /* Sensors detected on all pages */ for (page = 0; page < info->pages; page++) { -- cgit v1.2.3